HandlerInterceptor(处理器拦截器)
常见使用场景
日志记录: 记录请求信息的日志, 以便进行信息监控, 信息统计, 计算PV(page View)等
性能监控:
权限检查:
通用行为:
使用自定义注解实现权限拦截
首先HandlerInterceptor了解
在HandlerInterceptor中有三个方法:
public interface HandlerInterceptor {

// 在执行目标方法之前执行
    boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler)throws Exception;

// 执行目标方法之后执行
    void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;

// 在请求已经返回之后执行
    void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;

}
在以上注释中已经写明执行顺序, 测试及测试结果如下:
public class TestInterceptor implements HandlerInterceptor {

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandler");
        return true;
    }

@Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandler");
    }

@Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
    }
}
结果:
preHandler
postHandler
afterCompletion
如何配置拦截器后面讲:
下面来讲讲这个拦截器是拦截的什么?
方法拦截器HandlerInterceptor
我们使用SpringMVC都知道SpringMVC是基于方法的请求处理, 和Struts2有明显区别(我是这么理解的), 并且Controller是单例模式, 所有请求都是从DispatcherServlet来调用请求url对应的方法的(处理器映射器的功能), 那么它是一个方法拦截器, 如何知道呢?
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println(handler.getClass());
    return true;
}
执行结果:
class org.springframework.web.method.HandlerMethod
已经看到拦截器如何工作, 并且知道它是方法级别的拦截器, 那么接下来看看如何配置拦截器, 让它在服务器运行期间起作用
实现HandlerInterceptor
实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter类
HandlerInterceptorAdapter适配器是对HandlerInterceptor接口做了默认实现, 这种适配器模式, 是为了方便开发者只去想要复写方法, 其他方法采取默认措施.
上面的TestInterceptor就是一个Demo, 具体可以按需求在我们想要拦截的位置进行相应的逻辑处理
配置拦截器
从Spring4.x开始, 就支持注解配置具体是使用@Configuration注解标注一个普通类, 使该类成为配置类, 可以在该类中定义Bean, 以及注入一些配置参数等.
首先, 我们要配置拦截器,就需要想SpringMvc的拦截链中取注入我们的拦截器, 这样才能请求进来时去拦截我们想要拦截的请求, 所以, 需要我们新建一个普通类, 使用@Configuration注解标注在类名上, 并且让该类继承WebMvcConfigurerAdapter,为什么不实现WebMvcConfigurer接口呢? 因为方法太多,我们不需要复写其中所有方法...
下面让我们新建一个配置类, 来配置我们的拦截器
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {

public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TestInterceptor()).addPathPatterns("/**");
    }
}
复写addInterceptors之后, 当我们的服务器启动时, 会自动调用这个方法, 参数怎么传我们都不用管(目前是java初级阶段, 没空研究Spring深层原理), 我们只要知道这个方法一定会被调用就行了.
我们直接new一个自定义拦截器, 注册到整个拦截链中, 并且制定拦截路径, 这样当满足请求url拦截配置时, 我们的自定义拦截器就会执行相应的方法了.
拦截方法是非常灵的, 除了拦截配置的, 也可以拦截非匹配的, 也可以根据正则表达式拦截请求
至此, 我们的拦截器就完成了, 接下来自定义权限相关注解
自定义权限注解
定义一个@interface类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Access {

String[] value() default {};

String[] authorities() default {};

String[] roles() default {};

}
@Target注解是标注这个类它可以标注的位置:
常用的元素类型(ElementType):
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    // TYPE类型可以声明在类上或枚举上或者是注解上
    TYPE,
    /** Field declaration (includes enum constants) */
    // FIELD声明在字段上
    FIELD,
    /** Method declaration */
    // 声明在方法上
    METHOD,
    /** Formal parameter declaration */
    // 声明在形参列表中
    PARAMETER,
    /** Constructor declaration */
    // 声明在构造方法上
    CONSTRUCTOR,
    /** Local variable declaration */
    // 声明在局部变量上
    LOCAL_VARIABLE,
    /** Annotation type declaration */
    ANNOTATION_TYPE,
    /** Package declaration */
    PACKAGE,
    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,
    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}
@Retention注解表示的是本注解(标注这个注解的注解保留时期)
public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    // 源代码时期
    SOURCE,
    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    // 字节码时期, 编译之后
    CLASS,
    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
     // 运行时期, 也就是一直保留, 通常也都用这个
    RUNTIME
}
@Documented是否生成文档的标注, 也就是生成接口文档是, 是否生成注解文档
注解说完了, 下面需要到对应的controller的方法中取添加注解, 配置该方法允许的权限
在方法上配置权限
@RestController
public class HelloController {

@RequestMapping(value = "/admin", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.GET)
    // 配置注解权限, 允许身份为admin, 或者说允许权限为admin的人访问
    @Access(authorities = {"admin"})
    public String hello() {
        return "Hello, admin";
    }
}
编写权限逻辑
// 自定义一个权限拦截器, 继承HandlerInterceptorAdapter类
public class AuthenticationInterceptor extends HandlerInterceptorAdapter {

// 在调用方法之前执行拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 将handler强转为HandlerMethod, 前面已经证实这个handler就是HandlerMethod
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        // 从方法处理器中获取出要调用的方法
        Method method = handlerMethod.getMethod();
        // 获取出方法上的Access注解
        Access access = method.getAnnotation(Access.class);
        if (access == null) {
        // 如果注解为null, 说明不需要拦截, 直接放过
            return true;
        }
        if (access.authorities().length > 0) {
            // 如果权限配置不为空, 则取出配置值
            String[] authorities = access.authorities();
            Set<String> authSet = new HashSet<>();
            for (String authority : authorities) {
            // 将权限加入一个set集合中
                authSet.add(authority);
            }
            // 这里我为了方便是直接参数传入权限, 在实际操作中应该是从参数中获取用户Id
            // 到数据库权限表中查询用户拥有的权限集合, 与set集合中的权限进行对比完成权限校验
            String role = request.getParameter("role");
            if (StringUtils.isNotBlank(role)) {
                if (authSet.contains(role)) {
                // 校验通过返回true, 否则拦截请求
                    return true;
                }
            }
        }
        // 拦截之后应该返回公共结果, 这里没做处理
        return false;
    }

}

Spring MVC学习总结(19)——SpringMVC权限注解拦截相关推荐

  1. spring mvc学习(19):cookievalue注解(显示cookie的值,默认必须有值)

    目录结构 web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi= ...

  2. Spring MVC 学习总结(一)——MVC概要与环境配置 转载自【张果】博客

    Spring MVC 学习总结(一)--MVC概要与环境配置 目录 一.MVC概要 二.Spring MVC介绍 三.第一个Spring MVC 项目:Hello World 3.1.通过Maven新 ...

  3. Spring MVC 学习总结(五)——校验与文件上传 转自 张果 博客;已经编程校验;正确无误;...

    Spring MVC 学习总结(五)--校验与文件上传 目录 一.Spring MVC验证器Validator 1.1.定义验证器 1.2.执行校验 1.3.在UI中添加错误标签 1.4.测试运行 二 ...

  4. Spring MVC 学习笔记 对locale和theme的支持

    Spring MVC 学习笔记 对locale和theme的支持 Locale Spring MVC缺省使用AcceptHeaderLocaleResolver来根据request header中的 ...

  5. Spring MVC 学习总结(二)——控制器定义与@RequestMapping详解

    Spring MVC 学习总结(二)--控制器定义与@RequestMapping详解 目录 一.控制器定义 1.1.实现接口Controller定义控制器 1.2.使用注解@Controller定义 ...

  6. Spring MVC 学习总结(九)——Spring MVC实现RESTful与JSON(Spring MVC为前端提供服务)...

    Spring MVC 学习总结(九)--Spring MVC实现RESTful与JSON(Spring MVC为前端提供服务) 目录 一.JSON 1.1.概要 1.2.使用ModelAndView ...

  7. Spring MVC 学习笔记一 HelloWorld

    Spring MVC 学习笔记一 HelloWorld Spring MVC 的使用可以按照以下步骤进行(使用Eclipse): 加入JAR包 在web.xml中配置DispatcherServlet ...

  8. Spring MVC学习(8)—HandlerInterceptor处理器拦截器机制全解

    基于最新Spring 5.x,详细介绍了Spring MVC的HandlerInterceptor处理器拦截器机制,以及它的一系列拦截方法. 本次我们来学习Sring MVC的HandlerInter ...

  9. Spring MVC学习指南(11-12章总结)

    11:上传文件 将介绍如何在SpringMVC中使用Commons FileUpload和Servlet 3上传文件. 在填写表单的html中,必须将html的enctype属性值设置为multipa ...

最新文章

  1. 如何衡量一个项目的交付质量???
  2. 面试程序员总结的通病!
  3. Kali Linux软件更新日报20190622
  4. python面向对象代码示例
  5. 1352. 虫洞【难度: 中 / 枚举 判环】
  6. webflux系列--源码解析二
  7. 如何创建最简单的 ABAP 数据库表,以及编码从数据库表中读取数据 (上) 试读版
  8. DotFuscator 小记
  9. 拿到参考资料的预训练模型,太可怕了!
  10. php获取客户端的真实IP的方法
  11. 基于Spring+SpringMVC+Mybatis分布式敏捷开发系统架构
  12. H3C防火墙透明模式部署trunk
  13. Web程序设计-客户端表单验证
  14. Python爬虫笔记【一】模拟用户访问之验证码清理(4)
  15. 深度学习(十三) Adversarial Attack 理论部分
  16. c语言课程设计作业五子棋,c语言课程设计案例-五子棋.ppt
  17. idea,maven飘红及无法打包问题
  18. 时间序列平稳性分析和白噪声检验
  19. 视频教程-Oracle12数据库管理/DBA/数据库工程师培训-Oracle
  20. android 设置背景ah,Ahjesus,

热门文章

  1. python selenium po_python+selenium基于po模式的web自动化测试框架
  2. yii mysql 查询 类型转换_Yii2.0 API改造(返回数据库对应字段数据类型)
  3. C++新特性探究(五):for循环、范围for语句
  4. 计算机的智能化研究领域的是,科学网—第五代计算机为何在“智能化”阶段的发展像蜗牛般的徘徊前行? - 邹晓辉的博文...
  5. java future用法_你必须掌握的 21 个 Java 核心技术
  6. linux 内存泄露 工具,Linux Kernel模块内存泄露分析
  7. c语言用指针删除链表free,leetcode剑指 Offer 18(删除链表的节点)--C语言实现
  8. slurm安装配置_安装Slurm_鲲鹏高性能计算解决方案_安装指南_Slurm 18.08.7 安装指南_Slurm的安装配置_华为云...
  9. ffmpeg添加到环境变量_如何在Windows 10上下载和安装FFmpeg
  10. java word转图片tiff_Word 2010中将文档保存为TIFF图片的方法