自定义注解很简单,无非就是了解几个元注解,元注解都在java.lang.annotation包:
- @Target
- @Retention
- @Documented
- @Inherited
常用的就以上四个,下面写的详细点:
- @Target
- 描述注解的使用范围(可以修饰什么地方)
可传入类型:
public enum ElementType {
TYPE, // 类、接口、枚举类
FIELD, // 成员变量(包括:枚举常量)
METHOD, // 成员方法
PARAMETER, // 方法参数
CONSTRUCTOR, // 构造方法
LOCAL_VARIABLE, // 局部变量
ANNOTATION_TYPE, // 注解类
PACKAGE, // 可用于修饰:包
TYPE_PARAMETER, // 类型参数,JDK 1.8 新增
TYPE_USE // 使用类型的任何地方,JDK 1.8 新增
}
- @Retention
- 描述注解保留的时间范围(被描述的注解在它所修饰的类中可以被保留到何时),共有三种策略。
可传入类型:
public enum RetentionPolicy {
SOURCE, // 源文件保留
CLASS, // 编译期保留,默认值
RUNTIME // 运行期保留,可通过反射去获取注解信息
}
- @Documented
- 描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息。
- @Inherited
- 使被它修饰的注解具有继承性(如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解)。
使用注解拦截用户信息Demo代码:
LoginRequired注解:
import java.lang.annotation.*;
@Inherited
@Documented
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {
boolean required() default false;
}
LoginInterceptor拦截器:
public class LoginInterceptor implements HandlerInterceptor {
private static final Logger log = LoggerFactory.getLogger(LoginInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.判断是否存在注解
if (!(handler instanceof HandlerMethod)) {
log.info("不是HandlerMethod类型,则无需检查");
return true;
}
HandlerMethod method = (HandlerMethod) handler;
boolean hasLoginAnnotation = method.getMethod().isAnnotationPresent(LoginRequired.class);
if (!hasLoginAnnotation) {
//不存在LoginRequired注解,则直接通过
log.info("不存在LoginRequired注解,则直接通过");
return true;
}
LoginRequired loginRequired = method.getMethod().getAnnotation(LoginRequired.class);
//2.required=false,则无需检查是否登录
if (!loginRequired.required()) {
log.info("required=false,则无需检查是否登录");
return true;
}
//3.登录状态检查,使用response返回指定信息
log.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());
}
}
测试Controller:
@Controller("/")
@ResponseBody
public class IndexController {
@LoginRequired()
@GetMapping("/ok")
public String index(){
return "ok";
}
@LoginRequired(required = true)
@GetMapping("/fail")
public String fail(){
return "fail";
}
}