一、Java元注解
java中元注解:@Retention、@Inherited、@Documented、@Target
ps :
retention [rɪˈtenʃn] 保留
Inherited [ɪn’herɪtɪd] 继承
@Retention
注解的保留位置(枚举RetentionPolicy),RetentionPolicy可选值:
RetentionPolicy.SOURCE:注解仅存在于源码中,在class字节码文件中不包含
RetentionPolicy.CLASS:默认的保留策略,注解在class字节码文件中存在,但运行时无法获得
RetentionPolicy.RUNTIME:注解在class字节码文件中存在,在运行时可以通过反射获取到
首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解。
@Inherited
声明子类可以继承此注解,如果一个类A使用此注解,则类A的子类也继承此注解
@Documented
声明注解能够被javadoc等识别
@Target
用来声明注解范围(枚举ElementType),ElementType可选值:
TYPE----------------接口、类、枚举、注解
FIELD---------------字段、枚举的常量
METHOD--------------方法method
PARAMETER-----------方法参数parameter
CONSTRUCTOR---------构造函数constructor [kən'strʌktə]
LOCAL_VARIABLE------局部变量local_variable
ANNOTATION_TYPE-----注解annotation_type
PACKAGE-------------包package
注解的获取可以通过Class对象的一些方法:
isAnnotationPresent 判断是否应用了某个注解
getAnnotation 获取元素上指定的某个注解
getAnnotations 获取元素上的所有注解
二、自定义登录注解LoginRequired
登录判断:以登录标签+拦截器形式实现
1、自定义注解LoginRequired
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface LoginRequired {
boolean required() default false;
}
2、按SpringBoot方式创建Login拦截器
LoginInterceptor:handler需先转为HandlerMethod
public class LoginInterceptor implements HandlerInterceptor{
private static final Logger LOGGER= LoggerFactory.getLogger(LoginInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.判断是否存在注解
if(!(handler instanceof HandlerMethod)){
LOGGER.info("不是HandlerMethod类型,则无需检查");
return true;
}
HandlerMethod method = (HandlerMethod)handler;
boolean hasLoginAnnotation=method.getMethod().isAnnotationPresent(LoginRequired.class);
if(!hasLoginAnnotation){
//不存在LoginRequired注解,则直接通过
LOGGER.info("不存在LoginRequired注解,则直接通过");
return true;
}
LoginRequired loginRequired=method.getMethod().getAnnotation(LoginRequired.class);
//2.required=false,则无需检查是否登录
if(!loginRequired.required()){
LOGGER.info("required=false,则无需检查是否登录");
return true;
}
//3.登录状态检查,使用response返回指定信息
LOGGER.info("required=true,需检查是否登录");
response.getWriter().append("you need login!");
return false;
}
}
LoginConfiguration
@Configuration
public class LoginConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor());
}
}
3、编写测试类
LoginAction
@RestController
public class LoginAction {
private static final Logger LOGGER= LoggerFactory.getLogger(LoginAction.class);
/**
* 首页数据接口,无需登录
* @return
*/
@RequestMapping("index")
public String index(){
return "index";
}
/**
* 签到接口(需要在登录状态下)
* @param request
* @return
*/
@LoginRequired(required = true)
@RequestMapping("signIn")
public String signIn(HttpServletRequest request){
//进行签到逻辑
return "success";
}
}
4、验证注解功能:登录检查
访问 http://localhost:8080/index 返回 index
访问 http://localhost:8080/signIn 返回 you need login!
验证@LoginRequired功能成功,通过required=true 或者false来控制是否进行登录状态检查。