Spring MVC 对象转换器:初级开发者入门指南
为什么需要对象转换器?
在 Web 应用中,我们经常需要处理不同类型的对象。例如:前端数据到后端对象 :用户通过表单提交的数据通常是HttpServletRequest 对象,我们需要将其转换为 Java 对象(如 POJO)以便进行业务处理。后端对象到前端展示 :在将数据返回给前端时,可能需要将 Java 对象转换为适合前端展示的格式(如 JSON 或 XML)。对象转换是一个常见且重要的任务。它允许我们将一种类型的对象转换为另一种类型,以便在不同的层(如控制器、服务和视图)之间进行数据传递和处理。本文将详细介绍 Spring MVC 中的对象转换器,帮助初级开发者理解和掌握这一关键概念。
一、使用 Converter
接口
Converter<S, T>
接口用于将类型 S
转换为类型 T
,适用于简单类型或自定义对象转换。
1. 实现自定义 Converter
java">import org.springframework.core.convert.converter.Converter;
// 示例:将字符串 "yyyy-MM-dd" 转换为 Date 对象
public class StringToDateConverter implements Converter<String, Date> {
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date convert(String source) {
try {
return dateFormat.parse(source);
} catch (ParseException e) {
throw new IllegalArgumentException("无效的日期格式,请使用 yyyy-MM-dd");
}
}
}
2. 注册 Converter
通过 WebMvcConfigurer
配置类注册自定义转换器:
java">@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToDateConverter());
}
}
二、使用 Formatter
接口
Formatter<T>
专门用于处理字符串与对象的转换(如 HTTP 请求参数的转换)。
1. 实现自定义 Formatter
java">import org.springframework.format.Formatter;
import java.text.ParseException;
import java.util.Locale;
public class DateFormatter implements Formatter<Date> {
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date parse(String text, Locale locale) throws ParseException {
return dateFormat.parse(text);
}
@Override
public String print(Date date, Locale locale) {
return dateFormat.format(date);
}
}
2. 注册 Formatter
同样通过 WebMvcConfigurer
注册:
java">@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new DateFormatter());
}
}
三、使用 HttpMessageConverter
(处理 JSON/XML)
当使用 @RequestBody
或 @ResponseBody
时,Spring 使用 HttpMessageConverter
进行对象与 JSON/XML 的转换。常用的是 Jackson 的 MappingJackson2HttpMessageConverter
。
1. 自定义 Jackson 的 ObjectMapper
java">@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper;
}
@Bean
public MappingJackson2HttpMessageConverter jacksonConverter(ObjectMapper objectMapper) {
return new MappingJackson2HttpMessageConverter(objectMapper);
}
}
2. 注册自定义 HttpMessageConverter
java">@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter(objectMapper()));
}
@Bean
public ObjectMapper objectMapper() {
// 同上
}
}
四、使用 @InitBinder
(局部绑定)
在控制器中为特定字段注册自定义编辑器。
示例:绑定日期格式
java">@Controller
public class MyController {
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
}
五、常见场景示例
1. 枚举类型转换
将请求参数转换为枚举:
java">public enum Status {
ACTIVE, INACTIVE;
}
// 自定义 Converter
public class StringToStatusConverter implements Converter<String, Status> {
@Override
public Status convert(String source) {
return Status.valueOf(source.toUpperCase());
}
}
2. 自定义对象转换
将 String
转换为 User
对象:
java">public class StringToUserConverter implements Converter<String, User> {
@Override
public User convert(String source) {
String[] parts = source.split(",");
User user = new User();
user.setName(parts[0]);
user.setAge(Integer.parseInt(parts[1]));
return user;
}
}
六、注意事项
- 优先级:
Converter
和Formatter
的注册顺序可能影响结果。 - 全局 vs 局部:
@InitBinder
仅作用于当前控制器,而Converter/Formatter
是全局的。 - JSON 配置:在 Spring Boot 中,可以通过
application.properties
配置 Jackson:spring.jackson.date-format=yyyy-MM-dd HH:mm:ss spring.jackson.time-zone=GMT+8
通过合理使用这些转换器,可以灵活处理 Spring MVC 中的数据类型转换需求。