以下:内容主要参考https://blog.csdn.net/piaoranyuji/article/details/89448632。部分内容有参考已标注,如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正。
整体是: 在ParamsCheckASpect中对整个controller目录下的所有controller类的所有方法进行监听,如果方法中的参数有ParamCheck注解,且其notNull为true时会进行非空校验,如果是空则抛出异常,由全局异常类捕获。
不过思想有点跑偏了,这个写法感觉已经偏离了Aop的思想了。如果我要过滤全部的Controller的全部方法,用拦截器会更合适吧。不过也是算熟悉一下AOP方面
1. pom.xml中引入ASpectJ 依赖
<!--引入AOP相应的注解-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.2</version>
</dependency>
2. 自定义参数验证注解
@Retention(RetentionPolicy.RUNTIME) //生命周期在运行期
@Target({ElementType.METHODPARAMETER) // 在参数上使用
@Documented // 保存在JavaDoc中
public @interface ParamCheck {
boolean notNull() default true;
}
3. 开启AspectJ 自动代理(在启动类上加)
@SpringBootApplication
@EnableTransactionManagement
@EnableAspectJAutoProxy (proxyTargetClass = true) // 启用AspectJ 自动代理
public class UtilplatformApplication {
public static void main(String[] args) {
SpringApplication.run(UtilplatformApplication.class, args);
}
}
4. 自定义异常类
public class ParamsException extends Exception {
private String paramName;
private String paramType;
public ParamsException() {
super("必填参数为空");
}
public ParamsException(String paramName, String paramType) {
this.paramName = paramName;
this.paramType = paramType;
}
public ParamsException(String message) {
super(message);
}
public ParamsException(String message, Throwable cause) {
super(message, cause);
}
public ParamsException(Throwable cause) {
super(cause);
}
public ParamsException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
@Override
public String getMessage() {
return paramName + " " + paramType + " 参数不能为null";
}
}
5. 定义全局异常捕获类
@ControllerAdvice // controller 的通知
// 可以写多个ExceptionHandler注解的不同异常的类
public class GlobalExceptionHandler {
/**
* 参数异常
* @param e
* @return
*/
@ExceptionHandler(ParamsException.class)
@ResponseBody
public JsonResult<Object> paramsExcetion(ParamsException e) {
JsonResult<Object> objectJsonResult = new JsonResult<>();
objectJsonResult.setFailSystemError(e.getMessage());
return objectJsonResult;
}
//
// /**
// * 总异常
// * @param e
// * @return
// */
// @ExceptionHandler(Exception.class)
// @ResponseBody
// public JsonResult<Object> excetion(Exception e) {
// JsonResult<Object> objectJsonResult = new JsonResult<>();
// objectJsonResult.setFailSystemError(e.getMessage());
// return objectJsonResult;
// }
}
6. 定义拦截器
@Component
@Aspect
public class ParamsCheckASpect {
@Pointcut("execution(public * com.kingfish.controller.*.*(..))")
// @Pointcut("@annotation(com.kingfish.commons.aspect.ParamCheck)") // 切点为注解,只能切方法上的注解
public void checkParams() {
}
// 执行过程是 around - before - 逻辑代码 - after - afterReturning - (如果出现异常)afterThrowing
@Around("checkParams()")
// @Around("execution(public * com.kingfish.controller.*.*(..))") // 也可以通过这种方式执行情况
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // 获取切点的署名
Method method = signature.getMethod(); // 得到拦截的方法
//获取方法参数注解,返回二维数组是因为某些参数可能存在多个注解 --- 如果该方法参数都没有注解则直接跳过
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations == null || parameterAnnotations.length == 0) {
return joinPoint.proceed();
}
// 获取参数名
String[] parameterNames = signature.getParameterNames();
Object[] args = joinPoint.getArgs(); // 获取参数值
//获取方法参数类型
Class<?>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterAnnotations.length; i++) {
for (int j = 0; i < parameterAnnotations[0].length; j++) {
// 如果参数注解不为空,且参数注解是ParamCheck的派生类,且notNull是true,且 参数值为null 抛出空异常
if (parameterAnnotations[i][j] != null && parameterAnnotations[i][j] instanceof ParamCheck
&& ((ParamCheck) parameterAnnotations[i][j]).notNull() && args[i] == null) {
throw new ParamsException(parameterNames[i], parameterTypes[i].getTypeName());
}
}
}
return joinPoint.proceed();
}
@Before("checkParams()")
public void before(){
System.out.println("执行了before");
}
}
7. Controller 调用
@RequestMapping("/getToolsList")
// 这里notNull设置成false,即不会查空
public JsonResult<List<PlatTools>> getToolsList( @ParamCheck(notNull = false) String category, @ParamCheck String account, String keyword) {
JsonResult<List<PlatTools>> jsonResult = new JsonResult<>();
try {
List<PlatTools> toolsList = platToolsService.getToolsList(category, account, keyword);
jsonResult.setSuccess(toolsList);
} catch (Exception e) {
e.printStackTrace();
jsonResult.setFailSystemError(e.getMessage());
}
return jsonResult;
}