后台中的Convert转换

分类

后台中的Convert,我总结了如下分类:

  1. springmvc自定义属性编辑器PropertyEditor

    我们在使用SpringMVC时,常常需要把表单中的参数映射到我们对象的属性中,我们只要使用默认的配置即可做到普通数据类型的转换,如将String转换成Integer和Double等。但如果我要把String映射到对象上,如“rick-18”映射到Student对象,就必须自定义converter。值得注意的是,这里的提交方式不能是raw(application/json)的 。只能是x-www-form-urlencoded/form-data类型

  2. springmvc自定义Converter

    Converter能完成属性编辑器的功能,而且更加通用,不仅仅可以接收UI参数。是Spring推荐的实现方式。关于两者的比较,可以查看https://stackoverflow.com/questions/12544479/spring-mvc-type-conversion-propertyeditor-or-converter

  3. stringmvc自定义HttpMessageConverter

    HTTP消息转换,比如可以让spring接收Content-Type:xx/yy类型,body是字符串“rick-18”,后台用对象Student接收。自定义raw。spring提供了很多默认的转换,如FormHttpMessageConverter,MappingJackson2HttpMessageConverter

  4. hibernate自定义属性

    hibernate在持久化,如果是自定义属性,该如何处理映射呢?如,有个属性是Student对象,希望能够将Student的json对象存储varchar到列stu上

  5. hibernate validation自定义验证方法

    如何自定义validation,验证逻辑错误。

实现

所有实现都是基于Springboot2.0,VEHICLE_BRAND#NS 映射到 Word

  • ## PropertyEditor
  1. 定义属性编辑器
    WordEditor.java
  1. public class WordEditor extends PropertyEditorSupport {
  2. private static final String PARAM_SEPARATOR = "#";
  3. @Override
  4. public void setAsText(String text) throws IllegalArgumentException {
  5. if (StringUtils.hasText(text)) {
  6. String[] values = text.split(PARAM_SEPARATOR);
  7. Word word = new Word();
  8. word.setCategory(values[0]);
  9. word.setName(values[1]);
  10. setValue(word);
  11. } else {
  12. setValue(null);
  13. }
  14. }
  15. @Override
  16. public String getAsText() {
  17. Word word = (Word) getValue();
  18. if (word != null) {
  19. return word.getCategory() + "#" + word.getName();
  20. } else {
  21. return "";
  22. }
  23. }
  24. }
  1. 全局绑定属性编辑器

PropertyConfiguration.java

  1. @RestControllerAdvice
  2. public class PropertyConfiguration {
  3. @InitBinder
  4. public void registerCustomEditors(WebDataBinder binder) {
  5. binder.registerCustomEditor(Word.class, new WordEditor());
  6. }
  7. }

当然,可用在单独的Controller中绑定

  • ## Converter
  1. 定义Converter

StringToWordConverter.java

  1. @Component
  2. public class StringToWordConverter implements Converter<String, Word> {
  3. private static final String PARAM_SEPARATOR = "#";
  4. @Override
  5. public Word convert(String s) {
  6. String[] values = s.split(PARAM_SEPARATOR);
  7. Word word = new Word();
  8. word.setCategory(values[0]);
  9. word.setName(values[1]);
  10. return word;
  11. }
  12. }

注意:Converter是来自接口org.springframework.core.convert.converter.Converter

  1. 添加Converter
  1. @Configuration
  2. public class MyWebMvcConfigurer implements WebMvcConfigurer {
  3. @Override
  4. public void addFormatters(FormatterRegistry registry) {
  5. registry.addConverter(new StringToWordConverter());
  6. }
  7. }
  • ## HttpMessageConverter
  1. 定义 HttpMessageConverter

WordHttpMessageConverter.java

  1. @Component
  2. public class WordHttpMessageConverter extends AbstractHttpMessageConverter<Word> {
  3. private static final String PARAM_SEPARATOR = "#";
  4. public WordConverter() {
  5. super(new MediaType("text", "word"));
  6. }
  7. @Override
  8. protected boolean supports(Class<?> aClass) {
  9. return Word.class.isAssignableFrom(aClass);
  10. }
  11. @Override
  12. protected Word readInternal(Class<? extends Word> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
  13. String s = toString(httpInputMessage.getBody());
  14. String[] values = s.split(PARAM_SEPARATOR);
  15. Word word = new Word();
  16. word.setCategory(values[0]);
  17. word.setName(values[1]);
  18. return word;
  19. }
  20. @Override
  21. protected void writeInternal(Word word, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
  22. OutputStream outputStream = httpOutputMessage.getBody();
  23. String body = word.getCategory() + "#" + word.getName();
  24. outputStream.write(body.getBytes());
  25. outputStream.close();
  26. }
  27. private static String toString(InputStream inputStream) {
  28. Scanner scanner = new Scanner(inputStream, "UTF-8");
  29. return scanner.useDelimiter("\\A").next();
  30. }
  31. }

前端可用通过Content-Type: text/word,进行消息转换

  1. 添加MessageConverter
  1. @Configuration
  2. public class OAWebMvcConfigurer implements WebMvcConfigurer {
  3. @Override
  4. public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
  5. converters.add(new WordConverter());
  6. }
  7. }
  • ## hibernate Converter
  1. 新建Converter

WordJpaConverter.java

  1. @Convert
  2. public class WordJpaConverter implements AttributeConverter<Word, String> {
  3. private static final String PARAM_SEPARATOR = "#";
  4. @Override
  5. public String convertToDatabaseColumn(Word word) {
  6. if (Objects.isNull(word)) return "";
  7. StringBuilder sb = new StringBuilder();
  8. return sb.append(word.getCategory()).append(PARAM_SEPARATOR).append(word.getName()).toString();
  9. }
  10. @Override
  11. public Word convertToEntityAttribute(String s) {
  12. if (StringUtils.hasText(s)) {
  13. String[] values = s.split(PARAM_SEPARATOR);
  14. Word word = new Word();
  15. word.setCategory(values[0]);
  16. word.setName(values[1]);
  17. return word;
  18. }
  19. return null;
  20. }
  21. }
  1. 使用Converter

Vehicle.java

  1. @Entity
  2. public class Vehicle {
  3. @Id
  4. private Long id;
  5. @Convert(converter = WordJpaConverter.class)
  6. private Word vehicleBrand;
  7. }
  • ## hibernate validation
  1. 添加注解DictionaryConstraint.java
  1. @Documented
  2. @Constraint(validatedBy = DictionaryValidator.class)
  3. @Target( { ElementType.METHOD, ElementType.FIELD })
  4. @Retention(RetentionPolicy.RUNTIME)
  5. public @interface DictionaryConstraint {
  6. String message() default "Invalid dictionary data";
  7. String name();
  8. Class<?>[] groups() default {};
  9. Class<? extends Payload>[] payload() default {};
  10. }
  1. 设置验证逻辑DictionaryValidator.java
  1. public class DictionaryValidator implements ConstraintValidator<DictionaryConstraint, Word> {
  2. private DictionaryConstraint constraintAnnotation;
  3. @Override
  4. public void initialize(DictionaryConstraint constraintAnnotation) {
  5. this.constraintAnnotation = constraintAnnotation;
  6. }
  7. @Override
  8. public boolean isValid(Word word, ConstraintValidatorContext constraintValidatorContext) {
  9. String category = constraintAnnotation.name();
  10. if (Objects.nonNull(category) && !Objects.equals(category, word.getCategory())) return false;
  11. DictionaryService dictionaryService = Global.applicationContext.getBean(DictionaryService.class);
  12. Word _word = dictionaryService.findByCategoryAndName(category, word.getName());
  13. return Objects.nonNull(_word);
  14. }
  15. }
  1. 使用验证
    Vehicle.java
  1. @Entity
  2. public class Vehicle {
  3. @Id
  4. private Long id;
  5. @DictionaryConstraint(name = "VEHICLE_BRAND")
  6. @Convert(converter = WordJpaConverter.class)
  7. private Word vehicleBrand;
  8. }