在基于spring-boot的项目中,我有一个简单的DTO对象:
public class ExpenseDTO {
@Min(value = 1, message = "expense.amount.negative")
private int amount;
@Past
private Calendar createdAt;
// setters/getters/constructor are omitted
}
和这样的休息控制器:
public class ExpenseController {
private final ExpenseService expenseService;
@Autowired
public ExpenseController(ExpenseService expenseService) {
this.expenseService = expenseService;
}
@RequestMapping(value = ADD_EXPENSE, method = POST)
public ResponseEntity addExpense(@Valid @RequestBody ExpenseDTO expenseDTO, Principal principal) {
expenseService.addExpense(expenseDTO, principal.getName());
return ResponseEntity.ok().build();
}
}
从客户端我将发送当前日期:{“createdAt”:“2017-01-27T21:32:19.183Z”}但在后端验证期间,日期将被解析为“2017-01 -28T01:30:00.000 + 0200“因此结果错误且验证失败。我试图玩@JsonFormat但没有结果。
注意:我正在使用H2 db,如果从DTO对象中删除@Past,一切正常,但我必须禁用将来的日期。
那么如何在没有时区的情况下验证日期,我的意思是我需要在后端完全相同的日期,因为它是从客户端发送的?!
答案 0 :(得分:1)
可能是因为本地计算机中设置了TimeZone
。您可以在应用程序启动时将其设置为UTC
,例如:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
此外,您需要在TimeZone
内配置SimpleDateFormat
实例中的ObjectMapper
(如果您将ObjectMapper
配置为bean),例如:
@Bean
public ObjectMapper objectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.setSerializationInclusion(Include.NON_NULL);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
objectMapper.setDateFormat(simpleDateFormat);
return objectMapper;
}
如果它仍然不起作用,我建议为日历创建自定义反序列化器并在新实例中手动设置TimeZone
,例如:
@Component
public class CalendarDeserialiser extends JsonDeserializer<Calendar>{
TimeZone UTC = TimeZone.getTimeZone("UTC");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'");
@Override
public Calendar deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
Calendar calendar;
try{
calendar = Calendar.getInstance(UTC);
calendar.setTime(dateFormat.parse(p.getText()));
}catch(Exception e){
throw new IOException(e);
}
calendar.setTimeInMillis(p.getLongValue());
return calendar;
}
}
使用Calendar
注释您的@JsonDeserialize(using = CalendarDeserialiser.class)
字段。