zoukankan      html  css  js  c++  java
  • springAOP与注解

    https://412887952-qq-com.iteye.com/blog/2299732
    SpringMVC自带@Valid和@Validated两个注解可用来检查参数,但只能检查参数是bean的情况,对于参数是String或者Long类型的就不适用了,而且有时候这两个注解又突然失效了(没有仔细去调查过原因),对此,可以利用Spring的AOP和自定义注解,自己写一个参数校验的功能。
    注解是一个特殊的类,它可以给对象、参数、方法添加额外的这个类信息。说白了就是添加了更多的信息,我们可以称注解信息为元信息。我们通过java的运行时公共方法可以获取这些信息。所以,注解只有当你定义了专门的注解处理程序的时候才有用,否则一无是处!
    注解就是springAOP最好的使用例子。
    当请求过来的时候,spring框架的拦截器会检查被请求的controller方法接口中的注解,根据注解类型,调用不同的AOP处理程序进行处理。

    先定义一个注解:

    /**
     * 对 String 参数类型起非空校验作用
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.PARAMETER, ElementType.METHOD})
    @Inherited
    public @interface NotNull {
    
        String msg() default " 字段不能为null";
        String msg1() default " 字段不能为blank";
    }
    

    再写一个切面,处理被注解的参数:

    @Slf4j
    @Aspect
    @Component
    public class NotNullValidAspect {
    
         @Pointcut("execution(public * com.infoholdcity.parking.*.web..*(..)) && @annotation(com.infoholdcity.parking.common.annotation.NotNull)")
        public void checkParam(){}
    
        @Before("checkParam()")
        public void beforePointcut(JoinPoint joinPoint) {
            log.debug("参数验证中……");
            //获取参数对象
            Object[] args = joinPoint.getArgs();
            //获取方法参数
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Parameter[] parameters = signature.getMethod().getParameters();
            for (int i = 0; i < parameters.length; i++) {
                Parameter parameter = parameters[i];
    
                //HttpServletRequest、HttpServletResponse、HttpSession时,都不做处理
                if (parameter.getType().isAssignableFrom(HttpServletRequest.class) || parameter.getType().isAssignableFrom(HttpSession.class) ||
                        parameter.getType().isAssignableFrom(HttpServletResponse.class)) {
                    continue;
                }
    
                log.debug("参数类型:"+ parameter.getType().getName());
                log.debug("参数名:"+ parameter.getName());
    
                //该参数有该注解,且是String类型
                    NotNull notNull = parameter.getAnnotation(NotNull.class);
                if (notNull != null && String.class.isAssignableFrom(parameter.getType())) {
                    if (args[i] == null) {
                        throw new ParamBlankException(parameter.getName() + notNull.msg());
                    }else if(StringUtils.isBlank(args[i].toString())){
                        throw new ParamBlankException(parameter.getName() + notNull.msg1());
                    }
                    //TODO
                    continue;
                }
    
            }
        }
    
    }
    
    

    定义一个异常,用于捕获:

    /**
     * String参数为null或blank异常
     */
    public class ParamBlankException extends RuntimeException{
        public ParamBlankException() {
        }
    
        public ParamBlankException(String message) {
            super(message);
        }
    }
    

    全局异常处理器:

    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        /**
         * 手机号,车牌号格式校验, 在自定义类参数前加 @Validated 即可生效
         * @param e
         * @return
         */
        @ExceptionHandler(MethodArgumentNotValidException.class)
        @ResponseBody
        public RestResponse<Object> exceptionMethod1(MethodArgumentNotValidException e) {
            RestResponse<Object> rr = new RestResponse<Object>();
            BindingResult bindingResult = e.getBindingResult();
            FieldError fieldError = bindingResult.getFieldError();
            rr.setStatus("500");
            rr.setMessage(fieldError.getField() + " " + fieldError.getDefaultMessage());
            return rr;
        }
    
    
    
        /**
         * 手机号,车牌号格式校验
         * @param e
         * @return
         */
        @ExceptionHandler(ParamBlankException.class)
        @ResponseBody
        public RestResponse<Object> exceptionMethod2(ParamBlankException e) {
            RestResponse<Object> rr = new RestResponse<Object>();
            rr.setStatus("500");
            rr.setMessage(e.getMessage());
            return rr;
        }
    
        @ExceptionHandler(Exception.class)
        @ResponseBody
        public RestResponse<Object> exceptionMethod(Exception ex) {
            RestResponse<Object> rr = new RestResponse<Object>();
            rr.setStatus("500");
            rr.setMessage("inner error of server." + ex.getMessage());
            return rr;
        }
    }
    

    接口里的注解使用:

    	@PostMapping("/login")
    	@ApiOperation(value = "用户登录/注册接口")
    	@ApiImplicitParams({
    			@ApiImplicitParam(name = "identifyCode", value = "用户输入的验证码", required = true),
    			@ApiImplicitParam(name = "telNumber", value = "用户手机号", required = true),
    	})
    	public RestResponse login(BaseMsg baseMsg, @NotNull String identifyCode)  {
    		return this.wrap(baseMsgService.login(baseMsg, identifyCode));
    	}
    

    https://blog.csdn.net/oKuZuoZhou/article/details/81024795
    切入点的定义

    http://www.jfinal.com/share/1306
    注解传入数组

    https://blog.csdn.net/piaoranyuji/article/details/89448632
    request

    https://www.iteye.com/blog/elim-1812584
    不适用aop

    https://blog.csdn.net/qq_15071263/article/details/83825132
    参考

  • 相关阅读:
    记一道乘法&加法线段树(模版题)
    2021CCPC网络赛(重赛)题解
    Codeforces Round #747 (Div. 2)题解
    F. Mattress Run 题解
    Codeforces Round #744 (Div. 3) G题题解
    AtCoder Beginner Contest 220部分题(G,H)题解
    Educational Codeforces Round 114 (Rated for Div. 2)题解
    Codeforces Global Round 16题解
    Educational Codeforces Round 113 (Rated for Div. 2)题解
    AtCoder Beginner Contest 182 F
  • 原文地址:https://www.cnblogs.com/cashew/p/11357975.html
Copyright © 2011-2022 走看看