废话:一个同事写的,感觉很实用,然后我从中整理出来的一个小demo。
#问题引入
在日常开发中免不了对传入的参数进行校验,例如更新数据的时候id不能为空,新增数据的时候某个元素不能为空等。我们不得不写类似于下面的代码:
@RequestMapping("/createStudent")
public Object createStudent( Student student) {
String name = student.getName();
if ( StringUtils.isEmpty( name ) ){
return "姓名不能为空";
}
return student;
}
@RequestMapping("/updateStudent")
public Object updateStudent( Student student) {
String id = student.getId();
if ( StringUtils.isEmpty( id ) ){
return "id不能为空";
}
return student;
}
这样确实有很多重复的代码,于是就想着去解决,我把问题简化为下面的小demo,以供参考。
#项目结构
#定义注解用于分组
@Target({ElementType.PARAMETER,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validate
{
Class<?>[] groups() default { };
}
#定义两个组
public interface Create { }
public interface Update { }
#具体逻辑实现(重点)
@Component // 加入到IoC容器
@Aspect // 指定当前类为切面类
public class Aop {
@Autowired
protected Validator validator;
//@Pointcut("@annotation(springboot.Validate)")
@Pointcut("execution(* springboot.*.*(..))")
public void pointCut() {
}
@Around("pointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 获取当前方法
Parameter[] parameters = method.getParameters();
if (parameters != null && parameters.length > 0) {
for (int j = 0; j < parameters.length; j++) {
Parameter parameter = parameters[j];
Validate validate = parameter.getAnnotation(Validate.class);// 获取参数的注解
if (validate != null) {
Object arg = joinPoint.getArgs()[j];// 获取到参数
Class<?>[] groups = validate.groups();// 获取注解参数,验证组
List<ViolationMessage> violationErrors =groups.length!=0?beanValidator(arg, groups):beanValidator(arg);// 参数有效性验证
if (violationErrors != null) {
return violationErrors;// 验证不通过,返回结果
}
}
}
}
return joinPoint.proceed();
}
public List<ViolationMessage> beanValidator(Object object, Class<?>... groups) {
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
List<ViolationMessage> list = new ArrayList<>();
ViolationMessage vm = new ViolationMessage();
for (ConstraintViolation<Object> cv : constraintViolations) {
vm = new ViolationMessage();
vm.setProperty(cv.getPropertyPath().toString());
vm.setMessage(cv.getMessageTemplate());
list.add(vm);
}
return list;
}
return null;
}
}
原理,利用aop获取获取注解上的分组信息与当前参数,然后用validator进行校验。
#实体类
public class Student {
@NotNull(message="id:不能为空",groups={Update.class})
@Size(min = 3, max = 20, message = "id长度只能在3-20之间", groups = { Update.class})
private String id;
@NotNull(message = "姓名不能为空", groups = {Create.class})
private String name;
private String age;
/**get set省略**/
}
#错误信息封装
public class ViolationMessage implements Serializable{
private static final long serialVersionUID = 1L;
private String property;
private String message;
/**get set省略**/
}
#controller类
@RestController
public class TestController {
@RequestMapping("/createChack")
public Object createChack(@Validate(groups={Create.class}) Student student) {
return student;
}
@RequestMapping("/updateChack")
public Object updateChack(@Validate(groups={Update.class}) Student student) {
return student;
}
}
#运行SpringbootFirstApplication启动项目进行测试
请求1:http://127.0.0.1:8080/createChack
请求2:http://127.0.0.1:8080/updateChack?id=1
项目下载地址:
参考博客:
http://www.cnblogs.com/liangweiping/p/3837332.html
https://blog.csdn.net/wangjianwen8016/article/details/50461893
http://www.jb51.net/article/138424.htm
https://blog.csdn.net/littleskey/article/details/52224352
https://blog.csdn.net/weixin_42160445/article/details/82348500