JPA @Past日期/日历验证

时间:2017-01-27 21:46:26

标签: java hibernate date jpa jackson

在基于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,一切正常,但我必须禁用将来的日期。

那么如何在没有时区的情况下验证日期,我的意思是我需要在后端完全相同的日期,因为它是从客户端发送的?!

1 个答案:

答案 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)字段。