Spring MVC 数据格式化
Spring MVC提供了数据格式化机制,自动完成字符串与日期、数字等类型的转换。
日期格式化
@DateTimeFormat注解
Java
@Data
public class UserDTO {
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@DateTimeFormat(iso = ISO.DATE) // yyyy-MM-dd
private LocalDate birthDate;
@DateTimeFormat(iso = ISO.DATE_TIME) // yyyy-MM-dd'T'HH:mm:ss
private LocalDateTime registerTime;
}
ISO格式枚举
| ISO值 | 格式 | 示例 |
|---|---|---|
| ISO.DATE | yyyy-MM-dd | 2026-05-18 |
| ISO.TIME | HH:mm:ss | 10:30:00 |
| ISO.DATE_TIME | yyyy-MM-dd'T'HH:mm:ss | 2026-05-18T10:30:00 |
| ISO.NONE | 自定义pattern | 用户指定 |
数字格式化
@NumberFormat注解
Java
@Data
public class ProductDTO {
@NumberFormat(style = Style.NUMBER)
private Integer quantity;
@NumberFormat(style = Style.CURRENCY, pattern = "#,##0.00")
private BigDecimal price;
@NumberFormat(style = Style.PERCENT)
private Double discount;
@NumberFormat(pattern = "#,###")
private Long sales;
}
Style枚举
| Style值 | 说明 | 示例 |
|---|---|---|
| Style.NUMBER | 普通数字 | 1234 |
| Style.CURRENCY | 货币格式 | ¥1,234.00 |
| Style.PERCENT | 百分比格式 | 12% |
Controller接收格式化数据
Java
@RestController
@RequestMapping("/api/user")
public class UserController {
@PostMapping
public User create(@RequestBody UserDTO dto) {
// 日期字符串自动转换为Date类型
return userService.create(dto);
}
@GetMapping("/search")
public List<User> search(
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate) {
return userService.search(startDate, endDate);
}
}
配置全局格式化
Java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
// 添加日期格式化器
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
registrar.setTimeFormatter(DateTimeFormatter.ofPattern("HH:mm:ss"));
registrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
registrar.registerFormatters(registry);
// 添加数字格式化器
NumberFormatterRegistrar numberRegistrar = new NumberFormatterRegistrar();
numberRegistrar.registerFormatters(registry);
}
}
自定义格式化器
Formatter接口
Java
public interface Formatter<T> extends Printer<T>, Parser<T> {
String print(T object, Locale locale); // 对象转字符串
T parse(String text, Locale locale) throws ParseException; // 字符串转对象
}
自定义日期格式化器
Java
@Component
public class CustomDateFormatter implements Formatter<Date> {
private static final String PATTERN = "yyyy年MM月dd日";
@Override
public String print(Date date, Locale locale) {
return new SimpleDateFormat(PATTERN).format(date);
}
@Override
public Date parse(String text, Locale locale) throws ParseException {
return new SimpleDateFormat(PATTERN).parse(text);
}
}
注册自定义格式化器
Java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private CustomDateFormatter customDateFormatter;
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(customDateFormatter);
}
}
自定义枚举格式化器
Java
@Component
public class StatusFormatter implements Formatter<Status> {
@Override
public String print(Status status, Locale locale) {
return status.getCode();
}
@Override
public Status parse(String text, Locale locale) {
return Status.fromCode(text);
}
}
public enum Status {
ACTIVE("active"),
INACTIVE("inactive");
private final String code;
Status(String code) { this.code = code; }
public String getCode() { return code; }
public static Status fromCode(String code) {
for (Status status : values()) {
if (status.code.equals(code)) {
return status;
}
}
throw new IllegalArgumentException("Unknown status: " + code);
}
}
AnnotationFormatterFactory
根据注解创建格式化器:
Java
@Component
public class DateFormatAnnotationFormatterFactory
implements AnnotationFormatterFactory<DateFormat> {
@Override
public Set<Class<?>> getFieldTypes() {
return Set.of(Date.class, LocalDate.class, LocalDateTime.class);
}
@Override
public Printer<?> getPrinter(DateFormat annotation, Class<?> fieldType) {
return new DateFormatter(annotation.pattern());
}
@Override
public Parser<?> getParser(DateFormat annotation, Class<?> fieldType) {
return new DateFormatter(annotation.pattern());
}
}
// 自定义注解
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface DateFormat {
String pattern() default "yyyy-MM-dd";
}
响应数据格式化
使用@ResponseBody返回格式化数据
Java
@RestController
public class UserController {
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
User user = userService.findById(id);
// 日期字段使用@JsonFormat格式化输出
return user;
}
}
@JsonFormat注解
Java
@Data
public class User {
private Long id;
private String name;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private LocalDate birthday;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "#,##0.00")
private BigDecimal balance;
}
ConversionService与Formatter
Java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Bean
public ConversionService conversionService() {
DefaultFormattingConversionService service = new DefaultFormattingConversionService();
// 添加默认格式化器
service.addFormatterForFieldType(Date.class, new DateFormatter("yyyy-MM-dd"));
service.addFormatterForFieldType(LocalDate.class, new TemporalFormatter());
return service;
}
}
前端到后端格式化流程
text
前端字符串 → FormatterRegistry → Formatter.parse() → Java对象 → Controller
后端到前端格式化流程
text
Controller返回对象 → @JsonFormat/Formatter.print() → JSON字符串 → 前端
日期格式化配置对比
| 方式 | 用途 | 示例 |
|---|---|---|
| @DateTimeFormat | 请求参数转换 | @DateTimeFormat(pattern="yyyy-MM-dd") |
| @JsonFormat | 响应JSON格式化 | @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") |
| 全局配置 | 统一格式 | DateTimeFormatterRegistrar |
| 自定义Formatter | 特殊格式 | implements Formatter<Date> |
要点总结
- @DateTimeFormat用于请求参数日期格式化
- @JsonFormat用于响应JSON日期格式化
- @NumberFormat用于数字格式化
- 通过WebMvcConfigurer.addFormatters注册自定义格式化器
- Formatter接口实现print和parse方法
- ISO枚举提供标准日期格式
📝 发现内容有误?点击此处直接编辑