天天看点

spring boot 自定义注解第一类 @Loguser第二类 验证

java 自定义注解

在项目开发的过程中我们能遇到的自定义注解一般分为两类:

  1. 通过自定义注解自动获取参数值。比如:@LoginUser
  2. 通过自定义注解做验证。比如 验签,token验证

    上面两类最大的区别就是一个需要返回值一个不需要返回值。

    接下来我将对如上两类自定义的处理方法进行实际的实现,自定义的基础理论可以在网上查找一下,我这里就不做详细的介绍。

第一类 @Loguser

实现分为三步:

  1. 定义一个注解@LoginUser
  2. 创建一个LoginUser注解的解析器
  3. 创建一个配置类(在WebMvcConfigurer )

定义一个注解

注意: Target

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {
}
           

创建一个LoginUser注解的解析器

@Component
public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Autowired
	private LoginService loginService;
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().isAssignableFrom(User.class) && parameter.hasParameterAnnotation(LoginUser.class);
    }
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,NativeWebRequest request, WebDataBinderFactory factory) throws Exception {
        	Long cUserId=(Long) request.getAttribute(Constants.CURRENT_USER_ID,RequestAttributes.SCOPE_REQUEST);
        	 if (cUserId>0) {
        	    
                  User user = loginService.getUserById(cUserId);
                  if(user == null) {
        	          throw new RuntimeException(i18nService.getMessage("user.not.exist"));
                  }
                  //重点是这里返回对象
                  return user;
        	 }
     }
}

           

创建一个配置类

@Configuration
public class LoginUserConfigurer implements WebMvcConfigurer {
    //必须用注入方式,不能用new,否则此对象内部属性无法被注入
    @Autowired
    private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver;
 
    /**
     * 配置自定义参数解析器
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
    }

}
           

直接可以在代码里面使用

public ResponseResult saveServiceInfo(@LoginUser User loginUser) {
    // 下面直接获取数据
    loginUser.getUsername();
}
           

第二类 验证

  1. 先定义注解
  2. 定义一个切面
  3. 直接使用

定义注解

注意: Target

import java.lang.annotation.*;
@Target({ElementType.METHOD,ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValidatedSignature {
    String value() default "";
}
           

定义切面

Aspect
@Component
@SuppressWarnings({"unused"})
public class ValidatedSignatureAspect {

    public static final Logger logger = LoggerFactory.getLogger(ValidatedSignature.class);

    public static final String TOKEN_KEY = "token";

    /**
     * checkUrl,keyUrl,tokenScope是通过Spring的@Value注解来获取配置文件中的配置项
     *
     * @Value等同于Spring原先的配置模式中的value <bean id="" class="">
     * <property name="" value="">
     * </bean>
     */


    @Pointcut("@annotation(com.louis.kitty.admin.annotation.ValidatedSignature)")
    public void annotationPointcut() {
        logger.info("annotationPointcut()");

    }


    @Before("annotationPointcut()")
    public void beforePointcut(JoinPoint joinPoint) {
        // 此处进入到方法前  可以实现一些业务逻辑
        logger.info("beforePointcutJoinPoint joinPoint)");
    }

    @Around("annotationPointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info("doAround(ProceedingJoinPoint joinPoint)");

        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String[] params = methodSignature.getParameterNames();// 获取参数名称
        Class[] paramsType = methodSignature.getParameterTypes();
        Object[] args = joinPoint.getArgs();// 获取参数值
        JSONObject jsonObj=new JSONObject();
        for (int index=0;index<params.length;index++) {
            jsonObj.put(params[index],args[index]);
        }
        logger.info(jsonObj.toJSONString());
        int size1=params.length;
        int size2=paramsType.length;
        int size3=args.length;


        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String token = request.getHeader("token");


//        if (null == params || params.length == 0) {
//            String mes = "Using Token annotation, the token parameter is not passed, and the parameter is not valid.";
//            logger.info(mes);
//            throw new Exception(mes);
//        }
//        boolean hasToken = false;
//        int index = 0;
//        for (int i = 0; i < params.length; i++) {
//            if (TOKEN_KEY.equals(params[i])) {
//                hasToken = true;
//                index = i;
//                break;
//            }
//        }
//        if (!hasToken) {
//            String mes = "The token parameter is not included in the requested parameter, the parameter is not valid.";
//            logger.info(mes);
//            throw new Exception(mes);
//        }
        return jsonObj;
//        return joinPoint.proceed();
    }

    /**
     * 在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
     *
     * @param joinPoint
     */
    @AfterReturning("annotationPointcut()")
    public void doAfterReturning(JoinPoint joinPoint) {
        logger.info("doAfterReturning(JoinPoint joinPoint)");
    }
}
           

代码直接使用

@ValidatedSignature
public ResponseResult saveServiceInfo() {
 
}
           

继续阅读