关于“详解Spring AOP 实现‘切面式’valid校验”的完整攻略,这是一个相对比较复杂的话题,需要我们详细来讲解一下。下面是我的分享:
什么是AOP
AOP,Aspect Oriented Programming,面向切面编程,是OOP(Object Oriented Programming,面向对象编程)的一种补充。其实现是基于代理模式的基础之上的,目的是解决在面向对象编程中切面问题的技术。
Spring AOP
Spring AOP是Spring框架中对AOP实现的扩展,并且是基于代理的方式实现切面(也支持AspectJ编译时的AOP实现方式)。这样我们就可以通过Spring框架对AOP进行解决,消除Weave的依赖。
实现“切面式”valid校验
下面是实现“切面式”valid校验的完整攻略:
- 1.在maven依赖中添加spring-boot-starter-aop和spring-boot-starter-validation两个包。
- 2.自定义校验注解,可以通过@Target和@Retention来指定校验注解具体的作用场景和生命周期,可以有多条配置项,例如:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {IsMobileValidator.class })
public @interface IsMobile {
String message() default "手机号码格式错误";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
boolean required() default true;
}
其中,@Constraint是JSR303标准的注解,表示该注解是一个校验注解。@validatedBy是配合该注解的校验类。
- 3.编写校验类,继承ConstrainValidator和初始化方法,例如:
public class IsMobileValidator implements ConstraintValidator<IsMobile, String> {
private boolean required = false;
@Override
public void initialize(IsMobile constraintAnnotation) {
required = constraintAnnotation.required();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
... // 校验逻辑
return false;
}
}
其中,initialize方法的作用是将校验注解上的配置项读取到当前的校验类的成员变量中,isValid方法是校验逻辑的具体实现。这里涉及到的是JSR303标准的校验实现方式,需要了解。
- 4.编写AOP切面校验处理类。这里采用@Aspect和@Pointcut两个注解来指定切面的实现方式。@Before注解指定切面调用前的操作,例如:
@Aspect
@Component
public class ValidatorAspect {
@Pointcut("execution(* com.example.demo.service..*.*(..))")
public void pointcut() {
}
@Before("pointcut()")
public void before(JoinPoint joinPoint) throws Throwable {
// 取得传参
Object[] args = joinPoint.getArgs();
if (args == null || args.length == 0) {
return;
}
// 根据入参做字段校验
for (Object arg : args) {
// 校验逻辑
}
}
}
好了,至此,我们关于“切面式”valid校验的完整攻略就讲完了,其中包含了自定义注解、校验类、AOP处理类等多个环节的实现,需要认真理解和消化。下面给出两条示例:
示例一:
Account.java
public class Account {
@NotBlank(message = "姓名不能为空")
private String name;
@Min(value = 0, message = "年龄必须大于0")
@Max(value = 150, message = "年龄不能大于150")
private Integer age;
... // 其他字段
AccountService.java
@Service
public class AccountService {
public boolean add(Account account) {
boolean flag = ... // 具体的添加逻辑
return flag;
}
}
ValidatorAspect.java
@Aspect
@Component
public class ValidatorAspect {
@Pointcut("execution(* com.example.demo.service..*.*(..))")
public void pointcut() {
}
@Before("pointcut()")
public void before(JoinPoint joinPoint) throws Throwable {
// 取得传参
Object[] args = joinPoint.getArgs();
if (args == null || args.length == 0) {
return;
}
// 根据入参做字段校验
for (Object arg : args) {
ValidatorUtil.validate(arg);
}
}
}
示例二:
LoginRequest.java
public class LoginRequest {
@NotBlank(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
private String password;
... // 其他未含密码的字段
}
LoginController.java
@RestController
@RequestMapping("/login")
public class LoginController {
@PostMapping("/auth")
public Result<String> login(HttpServletRequest request, HttpServletResponse response, @Validated LoginRequest loginRequest) {
... // 具体的登录逻辑
}
}
ValidatorAspect.java
@Aspect
@Component
public class ValidatorAspect {
@Pointcut("execution(* com.example.demo.controller..*.*(..)) && args(.., @Validated *)")
public void pointcut() {
}
@Before("pointcut()")
public void before(JoinPoint joinPoint) throws Throwable {
// 取得传参
Object[] args = joinPoint.getArgs();
if (args == null || args.length == 0) {
return;
}
// 根据入参做字段校验
for (Object arg : args) {
ValidatorUtil.validate(arg);
}
}
}
在这两个示例中,我们均通过自定义注解、校验类以及AOP处理类等多个环节的实现,完成了对于“切面式”valid校验的支持。需要注意的是,具体实现方式可能因为版本差异、框架变化等原因存在差异,需要根据具体情况进行调整。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Spring AOP 实现“切面式”valid校验 - Python技术站