分类
后台中的Convert,我总结了如下分类:
-
springmvc自定义属性编辑器PropertyEditor
我们在使用SpringMVC时,常常需要把表单中的参数映射到我们对象的属性中,我们只要使用默认的配置即可做到普通数据类型的转换,如将String转换成Integer和Double等。但如果我要把String映射到对象上,如“rick-18”映射到Student对象,就必须自定义converter。值得注意的是,这里的提交方式不能是raw(application/json)的 。只能是
x-www-form-urlencoded/form-data
类型 -
springmvc自定义Converter
Converter能完成属性编辑器的功能,而且更加通用,不仅仅可以接收UI参数。是Spring推荐的实现方式。关于两者的比较,可以查看https://stackoverflow.com/questions/12544479/spring-mvc-type-conversion-propertyeditor-or-converter
-
stringmvc自定义HttpMessageConverter
HTTP消息转换,比如可以让spring接收Content-Type:xx/yy类型,body是字符串“rick-18”,后台用对象Student接收。自定义raw。spring提供了很多默认的转换,如
FormHttpMessageConverter
,MappingJackson2HttpMessageConverter
-
hibernate自定义属性
hibernate在持久化,如果是自定义属性,该如何处理映射呢?如,有个属性是Student对象,希望能够将Student的json对象存储varchar到列stu上
-
hibernate validation自定义验证方法
如何自定义validation,验证逻辑错误。
实现
所有实现都是基于Springboot2.0,VEHICLE_BRAND#NS
映射到 Word
- ## PropertyEditor
- 定义属性编辑器
WordEditor.java
public class WordEditor extends PropertyEditorSupport {
private static final String PARAM_SEPARATOR = "#";
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.hasText(text)) {
String[] values = text.split(PARAM_SEPARATOR);
Word word = new Word();
word.setCategory(values[0]);
word.setName(values[1]);
setValue(word);
} else {
setValue(null);
}
}
@Override
public String getAsText() {
Word word = (Word) getValue();
if (word != null) {
return word.getCategory() + "#" + word.getName();
} else {
return "";
}
}
}
- 全局绑定属性编辑器
PropertyConfiguration.java
@RestControllerAdvice
public class PropertyConfiguration {
@InitBinder
public void registerCustomEditors(WebDataBinder binder) {
binder.registerCustomEditor(Word.class, new WordEditor());
}
}
当然,可用在单独的Controller中绑定
- ## Converter
- 定义Converter
StringToWordConverter.java
@Component
public class StringToWordConverter implements Converter<String, Word> {
private static final String PARAM_SEPARATOR = "#";
@Override
public Word convert(String s) {
String[] values = s.split(PARAM_SEPARATOR);
Word word = new Word();
word.setCategory(values[0]);
word.setName(values[1]);
return word;
}
}
注意:Converter
是来自接口org.springframework.core.convert.converter.Converter
- 添加
Converter
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToWordConverter());
}
}
- ## HttpMessageConverter
- 定义
HttpMessageConverter
WordHttpMessageConverter.java
@Component
public class WordHttpMessageConverter extends AbstractHttpMessageConverter<Word> {
private static final String PARAM_SEPARATOR = "#";
public WordConverter() {
super(new MediaType("text", "word"));
}
@Override
protected boolean supports(Class<?> aClass) {
return Word.class.isAssignableFrom(aClass);
}
@Override
protected Word readInternal(Class<? extends Word> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
String s = toString(httpInputMessage.getBody());
String[] values = s.split(PARAM_SEPARATOR);
Word word = new Word();
word.setCategory(values[0]);
word.setName(values[1]);
return word;
}
@Override
protected void writeInternal(Word word, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {
OutputStream outputStream = httpOutputMessage.getBody();
String body = word.getCategory() + "#" + word.getName();
outputStream.write(body.getBytes());
outputStream.close();
}
private static String toString(InputStream inputStream) {
Scanner scanner = new Scanner(inputStream, "UTF-8");
return scanner.useDelimiter("\\A").next();
}
}
前端可用通过Content-Type: text/word
,进行消息转换
- 添加MessageConverter
@Configuration
public class OAWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new WordConverter());
}
}
- ## hibernate Converter
- 新建Converter
WordJpaConverter.java
@Convert
public class WordJpaConverter implements AttributeConverter<Word, String> {
private static final String PARAM_SEPARATOR = "#";
@Override
public String convertToDatabaseColumn(Word word) {
if (Objects.isNull(word)) return "";
StringBuilder sb = new StringBuilder();
return sb.append(word.getCategory()).append(PARAM_SEPARATOR).append(word.getName()).toString();
}
@Override
public Word convertToEntityAttribute(String s) {
if (StringUtils.hasText(s)) {
String[] values = s.split(PARAM_SEPARATOR);
Word word = new Word();
word.setCategory(values[0]);
word.setName(values[1]);
return word;
}
return null;
}
}
- 使用Converter
Vehicle.java
@Entity
public class Vehicle {
@Id
private Long id;
@Convert(converter = WordJpaConverter.class)
private Word vehicleBrand;
}
- ## hibernate validation
- 添加注解
DictionaryConstraint.java
@Documented
@Constraint(validatedBy = DictionaryValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DictionaryConstraint {
String message() default "Invalid dictionary data";
String name();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
- 设置验证逻辑
DictionaryValidator.java
public class DictionaryValidator implements ConstraintValidator<DictionaryConstraint, Word> {
private DictionaryConstraint constraintAnnotation;
@Override
public void initialize(DictionaryConstraint constraintAnnotation) {
this.constraintAnnotation = constraintAnnotation;
}
@Override
public boolean isValid(Word word, ConstraintValidatorContext constraintValidatorContext) {
String category = constraintAnnotation.name();
if (Objects.nonNull(category) && !Objects.equals(category, word.getCategory())) return false;
DictionaryService dictionaryService = Global.applicationContext.getBean(DictionaryService.class);
Word _word = dictionaryService.findByCategoryAndName(category, word.getName());
return Objects.nonNull(_word);
}
}
- 使用验证
Vehicle.java
@Entity
public class Vehicle {
@Id
private Long id;
@DictionaryConstraint(name = "VEHICLE_BRAND")
@Convert(converter = WordJpaConverter.class)
private Word vehicleBrand;
}