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
参考

原文地址:https://www.cnblogs.com/cashew/p/11357975.html