前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >自定义注解(拦截器实现)

自定义注解(拦截器实现)

原创
作者头像
Java king
发布2023-02-21 15:18:42
5160
发布2023-02-21 15:18:42
举报
文章被收录于专栏:后端Java后端Java

你因成功而内心充满喜悦的时候,就没有时间颓废——弗兰克·迈耶

通过注解的形式,实现一个简单的接口权限限制,这里通过拦截器实现。

拦截器咱们使用HandlerInterceptorAdapter

首先介绍一下拦截器

拦截器是在面向切面编程中应用的,就是在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法。是基于JAVA的反射机制

1.拦截器(Interceptor)执行顺序:
  1. 请求到达 DispatcherServlet
    1. DispatcherServlet 发送至 Interceptor ,执行 preHandle
      1. 请求达到 Controller
        1. 请求结束后,postHandle 执行
2.拦截器(Interceptor)和过滤器(Filter)的执行顺序

过滤前->拦截前->Action处理->拦截后->过滤后

3.使用方法
1:预处理preHandle()方法

用户发送请求时,先执行preHandle()方法。会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则执行用户请求的url方法。

2:后处理postHandle()方法

调用了Service并返回ModelAndView,但未进行页面渲染,可以在这里继续修改ModelAndView

3:返回处理afterCompletion()方法

已经渲染了页面,在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。

注:一般使用preHandle这个拦截器进行预处理,对url进行请求拦截

介绍完拦截器相信已经对拦截器已经有了大概的认知。

咱们现在开始自定义注解

代码语言:java
复制
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface RoleAuth {

    /**
     * 功能类型
     */
    String type();
}

我这里是一个很简单的注解,里面只有一个type类型。

首先咱们先介绍@Retention注解是什么:

@Retention的作用是定义被它所注解的注解保留多久。

咱们通过注解的源码可以清楚的看到他所需要的是一个RetentionPolicy枚举类型值。

打开RetentionPolicy这个枚举类之后,从注释上看:

source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略

class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期

runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在

这3个生命周期分别对应于:Java源文件(.java文件) ---> .class文件 ---> 内存中的字节码。

那怎么来选择合适的注解生命周期呢?

首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife,就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override@SuppressWarnings,则可选用 SOURCE 注解

介绍完@Retention之后咱们在看@Target是什么东西:

@Target用来表示注解作用范围,超过这个作用范围,编译的时候就会报错。

@Target(ElementType.TYPE)——接口、类、枚举、注解

@Target(ElementType.FIELD)——字段、枚举的常量

@Target(ElementType.METHOD)——方法

@Target(ElementType.PARAMETER)——方法参数

@Target(ElementType.CONSTRUCTOR) ——构造函数

@Target(ElementType.LOCAL_VARIABLE)——局部变量

@Target(ElementType.ANNOTATION_TYPE)——注解

@Target(ElementType.PACKAGE)——包

@Target里面是可以允许传入多个值,例如:@Target({ElementType.METHOD, ElementType.TYPE})

我这里选择的范围是:接口、类、枚举、注解、方法上。

介绍完注解之后,咱们就可以通过拦截器和注解(反射机制)实现通过注解拦截到用户请求。

代码语言:java
复制
@Component
public class RoleAuthInterceptor extends HandlerInterceptorAdapter {
  
}

首先新建一个类去继承HandlerInterceptorAdapter类,并实现HandlerInterceptorAdapterpreHandle的方法。

代码语言:java
复制
//这里的意思是:如果不是映射到方法上直接通过
if (!(handler instanceof HandlerMethod)) {
  return super.preHandle(request, response, handler);
}

然后通过反射的方式拿到注解里面的内容,进行业务代码实现,如果不符合要求直接抛出异常,反之return true

注册拦截器之后需要继承WebMvcConfigurerAdapter,不然是不会进行拦截的。

需要重写addInterceptors方法,这里是对根目录"/"进行拦截,可以指定拦截url请求目录。

写到这里,咱们就可以通过注解的方式进行拦截了。

代码语言:java
复制
//放到接口上,就会被拦截该接口,进行业务判断。
@RoleAuth(type = FunctionConstant.COURSE)

这样简单自定义注解+拦截器就完事了。

最后把我最喜欢的一句话贴到这里:"人生最好的贵人,就是努力向上的自己。”生活不会辜负一个一直在努力的人。愿我们都能在各自坚持的道路上,遇见更好的自己

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.拦截器(Interceptor)执行顺序:
  • 2.拦截器(Interceptor)和过滤器(Filter)的执行顺序
  • 3.使用方法
    • 1:预处理preHandle()方法
      • 2:后处理postHandle()方法
        • 3:返回处理afterCompletion()方法
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档