Spring中@DateTimeFormat(style="M-")的日期格式自定义方案咨询
解决方案:Spring Web多语言日期格式自定义
针对你的需求——在de_DE locale下显示13.01.2000,en_GB locale下显示13/01/2000,同时避免@DateTimeFormat style参数导致的年份位数问题,以下分当前版本(Spring Boot 2.7.x)和升级后版本(Spring Boot 3.x)给出实现方案:
一、Spring Boot 2.7.x(基于java.util.Date)
1. 全局自定义日期格式化器(推荐)
创建一个适配多locale的Formatter,根据当前请求的locale返回对应格式:
import org.springframework.format.Formatter; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; public class CustomDateFormatter implements Formatter<Date> { private final MessageSource messageSource; public CustomDateFormatter(MessageSource messageSource) { this.messageSource = messageSource; } @Override public Date parse(String text, Locale locale) throws ParseException { SimpleDateFormat sdf = getDateFormat(locale); return sdf.parse(text); } @Override public String print(Date object, Locale locale) { SimpleDateFormat sdf = getDateFormat(locale); return sdf.format(object); } private SimpleDateFormat getDateFormat(Locale locale) { // 从多语言配置文件中读取格式模板 String pattern = messageSource.getMessage("date.format", null, locale); SimpleDateFormat sdf = new SimpleDateFormat(pattern); sdf.setLenient(false); // 严格校验日期格式 return sdf; } }
注册该格式化器到Spring容器:
import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { private final MessageSource messageSource; public WebConfig(MessageSource messageSource) { this.messageSource = messageSource; } @Override public void addFormatters(FormatterRegistry registry) { registry.addFormatter(new CustomDateFormatter(messageSource)); } }
最后在多语言配置文件中定义格式:
messages_de.properties:date.format=dd.MM.yyyymessages_en_GB.properties:date.format=dd/MM/yyyy
2. Controller层局部绑定(按需使用)
如果只需针对特定Controller生效,可使用@InitBinder:
import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.beans.propertyeditors.CustomDateEditor; import java.text.SimpleDateFormat; import java.util.Locale; @ControllerAdvice // 全局生效,去掉则仅当前Controller生效 public class DateBindingAdvice { @InitBinder public void initBinder(WebDataBinder binder, Locale locale) { SimpleDateFormat sdf; if (Locale.GERMANY.equals(locale)) { sdf = new SimpleDateFormat("dd.MM.yyyy"); } else if (Locale.UK.equals(locale)) { sdf = new SimpleDateFormat("dd/MM/yyyy"); } else { sdf = (SimpleDateFormat) SimpleDateFormat.getDateInstance(SimpleDateFormat.MEDIUM, locale); } sdf.setLenient(false); binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true)); } }
二、Spring Boot 3.x(推荐使用Java 8+日期API)
Spring Boot 3.x建议迁移到LocalDate等Java 8+日期类,以下是适配方案:
1. 全局自定义LocalDate格式化器
首先修改模型类:
class PersonModel { private LocalDate birthdate; }
创建locale感知的格式化器:
import org.springframework.format.Formatter; import org.springframework.context.MessageSource; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Locale; public class LocaleAwareLocalDateFormatter implements Formatter<LocalDate> { private final MessageSource messageSource; public LocaleAwareLocalDateFormatter(MessageSource messageSource) { this.messageSource = messageSource; } @Override public LocalDate parse(String text, Locale locale) { DateTimeFormatter formatter = getFormatter(locale); return LocalDate.parse(text, formatter); } @Override public String print(LocalDate object, Locale locale) { DateTimeFormatter formatter = getFormatter(locale); return formatter.format(object); } private DateTimeFormatter getFormatter(Locale locale) { String pattern = messageSource.getMessage("date.format", null, locale); return DateTimeFormatter.ofPattern(pattern).withLocale(locale); } }
注册格式化器:
import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { private final MessageSource messageSource; public WebConfig(MessageSource messageSource) { this.messageSource = messageSource; } @Override public void addFormatters(FormatterRegistry registry) { registry.addFormatter(new LocaleAwareLocalDateFormatter(messageSource)); } }
同样在多语言配置文件中定义格式模板即可。
关键注意事项
- 确保Spring正确识别请求locale:默认通过
Accept-Language头解析,可自定义LocaleResolver调整逻辑。 - 解析日期时设置
lenient=false,避免接受无效日期格式。 - 升级到Spring Boot 3.x时,建议彻底迁移Java 8+日期API,替代老旧的
java.util.Date。
内容的提问来源于stack exchange,提问作者Jan Kuenstler
相关产品推荐
相关产品推荐

