zoukankan      html  css  js  c++  java
  • Springboot 自定义注解+AOP实现参数不能为空

    一:自定义注解类

     1 package com.wing.my.cloud.system.modular.system.util.annotation;
     2 
     3 import java.lang.annotation.*;
     4 
     5 @Target({ElementType.PARAMETER, ElementType.METHOD})
     6 @Retention(RetentionPolicy.RUNTIME)
     7 @Documented
     8 public @interface CheckNullParams {
     9     String[] params();
    10 }
    View Code

    二:AOP

      1 package com.wing.my.cloud.system.modular.system.util.aspect;
      2 
      3 import com.alibaba.fastjson.JSON;
      4 import com.alibaba.fastjson.JSONObject;
      5 import com.alibaba.fastjson.serializer.SerializerFeature;
      6 import com.wing.my.cloud.kernel.model.exception.ServiceException;
      7 import com.wing.my.cloud.system.modular.system.util.annotation.CheckNullParams;
      8 import lombok.extern.slf4j.Slf4j;
      9 import org.aspectj.lang.ProceedingJoinPoint;
     10 import org.aspectj.lang.annotation.Around;
     11 import org.aspectj.lang.annotation.Aspect;
     12 import org.aspectj.lang.annotation.Pointcut;
     13 import org.aspectj.lang.reflect.MethodSignature;
     14 import org.springframework.stereotype.Component;
     15 import org.springframework.util.StringUtils;
     16 import org.springframework.web.context.request.RequestContextHolder;
     17 import org.springframework.web.context.request.ServletRequestAttributes;
     18 
     19 import javax.servlet.http.HttpServletRequest;
     20 import java.util.*;
     21 
     22 /**
     23  * 校验参数不能为空
     24  * ProceedingJoinPoint只能用在环绕通知上。
     25  */
     26 @Slf4j
     27 @Aspect
     28 @Component
     29 public class CheckNullParamsAspect {
     30 
     31     private static String dateFormat = "yyyy-MM-dd HH:mm:ss";
     32 
     33     @Pointcut("@annotation(com.wing.my.cloud.system.modular.system.util.annotation.CheckNullParams)")
     34     public void paramNotNull(){}
     35 
     36     @Around("paramNotNull()")
     37     public Object  doAround(ProceedingJoinPoint joinPoint) throws Throwable{
     38         log.info("进入到环绕通知中");
     39         // 1、记录方法开始执行的时间
     40         long start = System.currentTimeMillis();
     41 
     42         // 2、打印请求参数
     43         ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
     44         HttpServletRequest request = attributes.getRequest();
     45         String target = joinPoint.getSignature().getDeclaringTypeName();              // 全路径类名
     46         String classNm = target.substring(target.lastIndexOf(".") + 1, target.length()); // 类名截取
     47         String method = joinPoint.getSignature().getName();                          // 获取方法名
     48         Map<String, String> params = getAllRequestParam(request);                    // 获取请求参数
     49         log.info("{}.{} 接收参数: {}", classNm, method, JSON.toJSONString(params));
     50 
     51         CheckNullParams check = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(CheckNullParams.class); // 获取注解
     52         String[] requiredFields = check.params();                                   // 获取注解参数
     53         // 3、必填参数非空校验
     54         Map<String,Object> result = validParams(params, requiredFields);
     55         if ((Boolean) result.get("boolean")) {
     56 
     57             Object object = joinPoint.proceed();        // 必填参数非空校验通过,执行方法,获取执行结果
     58             // 4、打印应答数据和方法耗时
     59             long time = System.currentTimeMillis() - start;
     60             log.info("{}.{} 应答数据: {}; 耗时 {} ms", classNm, method, JSONObject.toJSONStringWithDateFormat(object,
     61                     dateFormat, SerializerFeature.WriteMapNullValue), time);
     62             return object;
     63         } else {
     64             // 必填参数非空校验未通过,抛出异常,由GlobalExceptionHandler捕获全局异常,返回调用方“参数缺失”
     65             throw new ServiceException(500, "参数【" + result.get("param") + "】缺失或格式错误");
     66 
     67         }
     68 
     69     }
     70 
     71     /**
     72      * 校验传入参数params(非null)中是否必含requiredFields(非null)中的各个属性,且属性值非空
     73      *
     74      * @param params         传入参数
     75      * @param requiredFields 设置的非空属性数组
     76      * @return 校验通过返回true,否则返回false
     77      */
     78     private Map<String,Object> validParams(Map<String, String> params, String[] requiredFields) {
     79         Map<String, Object> map = new HashMap<>(2);
     80         if (requiredFields.length == 0) {
     81             // 无必送参数,直接返回true
     82             map.put("boolean", true);
     83             return map;
     84         } else {
     85             for (String field : requiredFields) {
     86                 if (StringUtils.isEmpty(params.get(field))) {
     87                     map.put("boolean", false);
     88                     map.put("param", field);
     89                     return map;
     90                 }
     91             }
     92             map.put("boolean", true);
     93             return map;
     94         }
     95     }
     96 
     97     /**
     98      * 获取请求参数
     99      */
    100     public static Map<String, String> getAllRequestParam(HttpServletRequest request) {
    101         Map<String, String> res = new HashMap<>();
    102         Enumeration<?> temp = request.getParameterNames();
    103         if (null != temp) {
    104             while (temp.hasMoreElements()) {
    105                 String en = (String) temp.nextElement();
    106                 String value = request.getParameter(en);
    107                 res.put(en, value);
    108                 // 在报文上送时,如果字段的值为空,则不上送<下面的处理为在获取所有参数数据时,判断若值为空,则删除这个字段>
    109                 if (StringUtils.isEmpty(res.get(en))) {
    110                     res.remove(en);
    111                 }
    112             }
    113         }
    114         return res;
    115     }
    116 
    117 }
    View Code

    三:实现

     1 @ApiImplicitParams({
     2             @ApiImplicitParam(name = "channelParam", value = "闲钱保渠道维护表实体类", dataType = "ChannelParam", paramType = "query", example = "xxx"),
     3     })
     4     @ResponseBody
     5     @ApiResource(name = "测试接口", path = "/test1")
     6     @CheckNullParams(params = {"custId","inpName"})  //参数不能为空
     7     public ResponseData test1( InsurancePolicyParam insurancePolicyParam) {
     8         testUserService.testExceptionAop(insurancePolicyParam);
     9         return ResponseData.success();
    10     }
    View Code

    参数 custId,inpName为InsurancePolicyParam实体类的属性。

    AOP各种通知

    前置通知

    方法执行前开始执行

    1 @Before("declareJointPointExpression()")
    2     public void beforeMethod(JoinPoint joinPoint) {
    3         String methodName = joinPoint.getSignature().getName();
    4         Object[] args = joinPoint.getArgs();
    5 
    6         System.out.println("这是切面开始打印出来的--->The method " + methodName + " begins with " + Arrays.asList(args));
    7     }
    View Code
    1 //后置通知
    2 //方法执行后开始执行
    3 @After("declareJointPointExpression()")
    4 public void afterMethod(JoinPoint joinPoint) {
    5 String methodName = joinPoint.getSignature().getName();
    6 System.out.println("这是切面结束打印出来的--->The method " + methodName + " ends");
    7 }
    View Code

    带返回值的后置通知

    方法正常执行后执行

    1 @AfterReturning(value = "declareJointPointExpression()",
    2             returning = "result")
    3     public void afterReturningMethod(JoinPoint joinPoint,Object result) {
    4         String methodName = joinPoint.getSignature().getName();
    5         System.out.println("The method " + methodName + " ends with " + result);
    6     }
    View Code

    异常通知

    代码执行中出现异常后执行

    1  @AfterThrowing(value = "exceptionLog()",throwing = "e")
    2     public void afterThrowing(JoinPoint point, Exception e) throws Throwable {
    3         String target = point.getSignature().getDeclaringTypeName();              // 全路径类名
    4         String classNm = target.substring(target.lastIndexOf(".") + 1, target.length()); // 类名截取
    5         String method = point.getSignature().getName();                          // 获取方法名
    6         log.error("{}.{} 【异常信息】: {}", classNm, method, e.getMessage());
    7     }
    View Code

    先执行前置通知,然后代码,然后异常通知,然后后置通知。

  • 相关阅读:
    MySQL视图——学习笔记及实验
    小学生四则运算自动刷题库优化升级
    软件工程小项目——小学生四则运算自动刷题库
    笔记--运算符、表达式和语句
    笔记--基本数据类型与数组
    笔记--java入门
    原因: java.lang.ClassNotFoundException: Hello
    使用gopm代替go get 解决go包卡慢的问题
    调用微信截图功能c# 截图带扩展名
    如何用golang搜索抓取淘宝商品
  • 原文地址:https://www.cnblogs.com/bulrush/p/14004412.html
Copyright © 2011-2022 走看看