天天看點

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() {
 
}
           

繼續閱讀