java编写自定义注解还是不难的,一般多用于鉴权之类的。
1.首先新建一个Annotation如图所示,我用的开发工具是idea。
2.建好之后需要在类上面加上
@Target
@Retention
@Documented
三个注解。
其中
@Target :注解作用的目标
我们看一下Target中的源码
我们点开ElementType,如图。表示目标可以是这些,大家见名知意。
ElementType.TYPE:接口、类、枚举、注解
ElementType.FIELD:字段、枚举的常量
ElementType.METHOD:方法
ElementType.PARAMETER:方法参数
ElementType.CONSTRUCTOR:构造函数
ElementType.LOCAL_VARIABLE:局部变量
ElementType.ANNOTATION_TYPE:注解
ElementType.PACKAGE:包
我们点开@Retention
我们继续点开RetentionPolicy,图片是部分
RetentionPolicy.SOURCE:注解仅存在于源码中,在class字节码文件中不包含
RetentionPolicy.CLASS:默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
RetentionPolicy.RUNTIME:注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Document:说明该注解将被包含在javadoc中。
解释完之后上干货,操作一下子。我这里写的是登录权限验证token,即验证接口是否需要登录:
我们先创建一个Annotation的java文件
然后加上@Target @Retention @Document这三个注解
括号里面的你们可以自行选择。
注解有了,我们需要写怎么实现使用这个注解后去验证。
在这里我们讲一下这个接口:HandlerInterceptor
这个接口定义了三个方法,分别是:
1. default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
2. default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView)throws Exception {
}
3. default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex)throws Exception {
}
preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView (这个博主就基本不怎么用了);
afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);
我们新建一个UserInterceptor类去实现这个HandlerInterceptor接口,因为是要鉴定接口中的方法是否需要登录权限,所以我们需要重写preHandle方法:
然后我们需要在preHandle方法里去写我们实现登录权限验证token判断用户是否登录:
还记得Retention里面的RUNTIME吗,这次要用到了,我们需要用到反射。
我们在preHandle方法里先写一个if判断
解释一下isAssignableFrom()方法和instanceof的区别:
isAssignableFrom()方法是从类继承的角度去判断,instanceof关键字是从实例继承的角度去判断。
isAssignableFrom()方法是判断是否为某个类的父类,instanceof关键字是判断是否某个类的子类。
HandlerMethod类详解:我们看一下源码(图中为部分源码)
HandleMethod是SpringMVC中处理请求的方法。
然后我们在preHandle方法中通过获得请求头的方法获得用户token:
String token = request.getHeader("token");
if (Strings.isNullOrEmpty(token)) {
token = request.getParameter("token");
}
获得请求方法类和所属类:
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
Class clazz = method.getDeclaringClass();
// 需要登录
if (clazz.isAnnotationPresent(LoginRequired.class)
|| method.isAnnotationPresent(LoginRequired.class)) {
// 没有传Token
if (Strings.isNullOrEmpty(token)) {
throw new RuntimeException("请求异常");
}
isAnnotationPresent()方法详解:
例:F.isAnnotationPresent(G.class);
G类型的注解是否在F类上
最后查询此token是否存在。
如果存在的话,我们可以把信息传给我们
一个自定义注解验证接口是否需要登录就完成啦。
注意:UserInterceptor类上需要加上@Component注解,因为需要被扫描到。