时常可能有这样的需求:在请求之前对于请求参数做校验,这样做一方面可以过滤掉一部分无效的请求(请求参数错误),另一方面也可以有效的限制错误请求占用请求时间,减少并发。而且在请求之前做参数校验是很好的,在数据的源头遏制脏数据,会比在代码中,甚至数据库中处理数据要方便和省力很多。
最近在做一个项目需要自定义一个时间校验器做接口参数的时间校验
- 需要校验传入的时间
- 不能使用自定义的响应来判断程序是否能调通,而要使用http的状态码来判断
- 注意时间格式需要从客户的订单数据中捞一下(避免直接使用文档中可能和客户的时间格式不同,前提是我们已经完成了联调和测试)
先看看最终的实现效果
想法1:
校验时间的工具方法即可
想在方法里面拿到请求的参数然后写一个校验的方法做时间参数的校验,这种方法是可以实现对于请求参数做参数校验的,最终根据校验方法的结果自定义响应结果。
但是我们接口已经大致开发好,而且接口文档提供的是使用http的状态码来作为最终的响应,而不是使用自定义的响应。
想法2
使用常见的时间校验器
比如@DatetimeFormat注解来做校验
报错
日期转换异常 JSON parse error: Cannot deserialize value of type java.util.Date
from String
在网上搜索很很多处理方式:比如说使用JsonFormat等或者加时区等等的处理方式,发版测试之后还是不生效(这里的不生效指的没有解决异常,仍然报错日期转换异常)
想法3(最终实现)
自定义一个时间校验器的注解来实现自定义的时间校验
自定义注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author: leiyu
* @Date: 2021/11/3
* @Description:
*/
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = DateTimeValidator.class)
public @interface DateTime {
String message() default "格式错误";
String[] format() default "yyyy-MM-dd";;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
时间校验器
package com.shuyun.omni.rest;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.text.SimpleDateFormat;
/**
* @Author: leiyu
* @Date: 2021/11/3
* @Description:
*/
public class DateTimeValidator implements ConstraintValidator<DateTime, String> {
private DateTime dateTime;
public void initialize(DateTime dateTime) {
this.dateTime = dateTime;
}
public boolean isValid(String value, ConstraintValidatorContext context) {
// 如果 value 为空则不进行格式验证,为空验证可以使用 @NotBlank @NotNull @NotEmpty 等注解来进行控制,职责分离
if (value == null) {
return true;
}
String[] format = dateTime.format();
for (int i = 0; i < format.length; i++) {
if (value.length() == format[i].length()) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format[i]);
try {
simpleDateFormat.parse(value);
return true;
} catch (Exception e) {
return false;
}
}
}
return false;
}
}
最终实现
- 可以实现对于时间的格式校验
- 可以配合@NotBlank等注解配合使用,比较灵活