背景:
其实就是想用一个注解,来统一处理获取userid的解析过程。 嗯,但是我觉得自己对注解也没有那么了解,所以再记录下。
spring boot 中自定义注解的方案:
STEP1. 定义注解
STEP2. 注解解析
1. 定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface InternalSubject {
}
看起来很简单哈哈
简单说明下
@Target说明了Annotation所修饰的对象范围。 就是这个注解可以用在什么地方。ElementType)有:
- CONSTRUCTOR:用于描述构造器
- FIELD:用于描述域
- LOCAL_VARIABLE:用于描述局部变量
- METHOD:用于描述方法
- PACKAGE:用于描述包
- PARAMETER:用于描述参数
- TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention定义了该Annotation被保留的时间长短。用于描述注解的生命周期(即:被描述的注解在什么范围内有效)取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留
@Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API
@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的
2. 注解解析
这里主要是要解析userid,一个参数。所以其实是通过
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor // 这个如果需要初始化的参数可以不用
public class InternalSubjectResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.hasParameterAnnotation(InternalSubject.class); // 检查需要解析的参数条件,这里是被使用了该注解的参数
}
@Override
public Object resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest,
WebDataBinderFactory webDataBinderFactory) throws Exception {
return UserIdHolder.getUserId(); // 核心在这里 返回要解析的参数的的返回值
}
}
对于参数的解析,其实是在一个地方赋值过了。
所以其实
public class UserIdHolder {
private static ThreadLocal<String> tokenThreadLocal = new ThreadLocal<>(); // 通过这个记录
public static String getAuthorizedUserId() {
return tokenThreadLocal.get();
}
public static void setAuthorizedUserIdn(String userId) {
tokenThreadLocal.set(userId); // 可以在filter 或则interceptor中进行set !! 这是关联性
}
public static void removeAuthorizedUserId() {
tokenThreadLocal.remove();
}
}
备注下 maven
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <optional>true</optional> </dependency>