1 简介
自定义注解是Java中一种用于定义和创建自己的注解类型的机制。注解是元数据的一种形式,用于在代码中添加额外的信息。自定义注解可以帮助开发者减少重复代码、增强代码的可读性,并且可以用于各种场景,如验证、日志记录、事务管理等。
1.1 定义自定义注解
使用@interface
关键字来定义的。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedLogin {
}
1.2 使用在自定义注解上的注解
@Target
:用于定义注解的使用位置。
选项:
ElementType.ANNOTATION_TYPE
: 应用于自定义注解上。ElementType.CONSTRUCTOR
: 应用于构造方法上。ElementType.FIELD
:用于字段或属性。ElementType.LOCAL_VARIABLE
: 用于局部变量。ElementType.METHOD
:用于方法。ElementType.PACKAGE
:用于包。ElementType.PARAMETER
:用于参数。ElementType.TYPE
:用于类、接口(包括注解类型)或枚举
@Retention
:用于指定自定义注解的保留策略,即注解的生存周期,注解在何时生效。
选项:
RetentionPolicy.SOURCE
:注解仅在源码中保留,编译时会被丢弃。RetentionPolicy.CLASS
:注解在编译时保留在类文件中,但运行时不保留(默认)。RetentionPolicy.RUNTIME
:注解在运行时保留,可以通过反射机制读取。
@Documented
: 用于指定自定义注解是否包含在Javadoc中。默认情况下,自定义注解不会出现在Javadoc中。@Inherited
:用于指定自定义注解是否可以被子类继承。注意,@Inherited
只能应用于类级别的注解(@Target(ElementType.TYPE)
)
2 代码实现
2.1 定义@NeedLogin 自定义注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedLogin {
}
2.2 定义拦截器拦截请求
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
/**
* 在请求处理之前被调用。
* @param request
* @param response
* @param handler
* @return 返回 true 表示继续处理请求,返回 false 表示请求被拦截。
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("*************进入拦截器*****************");
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
NeedLogin methodAnnotation = handlerMethod.getMethodAnnotation(NeedLogin.class);
if (methodAnnotation == null) {
return true;
}
String token = request.getHeader("token");
if (StrUtil.isBlank(token)) {
setResponseData(response, "token不存在");
return false;
}
try {
// 校验token信息是否合法
} catch (Exception e) {
setResponseData(response, "非法token");
return false;
}
return true;
}
return true;
}
/**
* 在整个请求完成之后被调用,即视图渲染之后。
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
private void setResponseData(HttpServletResponse response, String message) throws IOException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"status\":401,\"message\":\"" + message + "\"}");
}
}
2.3 注册拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器,定义需要拦截和放行的路径
registry.addInterceptor(loginInterceptor).addPathPatterns("/**")
.excludePathPatterns("/doc.html", "/v3/api-docs/**");
}
}
2.4 使用注解
@GetMapping("/list")
@NeedLogin
public List<User> selectUserList() {
return userService.selectUserList();
}
2.5 验证注解
登录之后下发合法token,携带token请求/list
,该请求会被拦截,如果token合法会放行,反之,会直接返回401状态码。