• 过滤器/拦截器/AOP----springmvc之拦截器


    录:

    1、springmvc 执行流程 和 HandlerExecutionChain(handler 执行链,包含 handler 方法和拦截器
    2、开发拦截器
    3、多个拦截器的执行顺序
    4、拦截器的例子
    5、spring mvc的 HandlerMethod 和 ResourceHttpRequestHandler

    6、springboot 注册拦截器

    1、springmvc 执行流程 和 HandlerExecutionChain(handler 执行链,包含 handler 方法和拦截器)  <--返回目录

      springmvc 执行流程:

      拦截器是 springmvc 中强大的控件,可以在进入处理器之前做一些操作,或者在处理器完成后进行操作,甚至是在渲染视图后进行操作。springmvc 会在启动期间就通过 @RequestMapping 的注解解析URI 和处理器的对应关系,在运行的时候通过请求找到对应的 HandlerMapping,然后构建 HandlerExecutionChain 对象,它是一个执行的责任链对象,这个对象指向了控制器所对应的方法和拦截器。

    2、开发拦截器  <--返回目录

      使用拦截器需要实现接口 org.springframework.web.servlet.HandlerInterceptor,这个接口定义了三个方法,源码:

    package org.springframework.web.servlet;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.web.method.HandlerMethod;
    
    public interface HandlerInterceptor {
    
        /**
         * Intercept the execution of a handler. Called after HandlerMapping determined
         * an appropriate handler object, but before HandlerAdapter invokes the handler.*/
        boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;
    
        /**
         * Intercept the execution of a handler. Called after HandlerAdapter actually
         * invoked the handler, but before the DispatcherServlet renders the view.
         * Can expose additional model objects to the view via the given ModelAndView.*/
        void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
                throws Exception;
    
        /**
         * Callback after completion of request processing, that is, after rendering
         * the view. Will be called on any outcome of handler execution, thus allows
         * for proper resource cleanup.
         * <p>Note: Will only be called if this interceptor's {@code preHandle}
         * method has successfully completed and returned {@code true}!*/
        void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception;
    
    }

      1) PreHandle(request, response, handler):在处理器之前执行的前置方法,这样 springmvc 可以在进入 handler 方法前处理一些逻辑。注意,此方法返回一个 boolean 值,会影响后面 springmvc 的流程。返回 true,拦截。

      2) PostHandle(request, response, handler, modelAndView): 在处理器之后执行的后置方法,此时 DispatcherServlet 还没开始渲染视图,可以在这个方法里面 通过 ModelAndView 添加一些数据得等等。

      3) afterCompletion(request, response, handler, exception): 无论是否产生异常都会在渲染视图后执行的方法。

      开发拦截器

      1)可以通过实现 HandlerInterceptor 接口,但是这样要同时实现 HandlerInterceptor  接口的三个方法,通常开发中可以继承 HandlerInterceptorAdapter 类,然后重写相应的方法即可。

      2)注册拦截器。

      SSM项目里面,在springmvc配置文件里面配置

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**">
            <bean class="com.oy.interceptor.MyInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

      使用 JavaConfig 配置:

    public class WebConfig extends WebMvcConfigurerAdapter {
    
        /**
         * 注册拦截器
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**");
        }
        
    }

      拦截器的执行流程:

    3、多个拦截器的执行顺序  <--返回目录

      首先拦截器执行顺序按照注册配置拦截器顺序前后执行。

    4、拦截器的例子  <--返回目录

      需求:实现功能:标注@IsLogin的方法,必须登录才能访问;没有登录重定向到login.jsp

      步骤:

     * spring自定义注解拦截器的配置
     *      1)自定义注解IsLogin;
     *      2)自定义拦截器LoginInterceptor,映射路径"/**",拦截所有请求;
     *      3)注册拦截器;
     *      4)在contrller中测试LoginInterceptor + 注解@IsLogin的使用

       自定义注解 IsLogin

    package com.oy.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface IsLogin {
    }
    View Code

      拦截器(注册拦截器代码省略)

    package com.oy.interceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
    
    import com.oy.Pojo.User;
    import com.oy.annotation.IsLogin;
    
    public class LoginInterceptor extends HandlerInterceptorAdapter {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
    
            // 请求的目标不是方法,放行
            if (!(handler instanceof HandlerMethod)) {
                return true;
            }
    
            // 请求的目标是方法
            HandlerMethod hm = (HandlerMethod) handler;
            Object o = hm.getMethodAnnotation(IsLogin.class);
            
            if (o == null) {// 没有这个注解
                return true; // 放行
            }
            // 有注解
            User currentUser = (User) request.getSession().getAttribute("currentUser");
    
            if (currentUser == null) {// 没有登录
                response.sendRedirect("/login.jsp");
                return false;
            } else { // 登录了
                return true; // 放行
            }
        }
    
    }
    View Code

      测试 controller

    package com.oy.controller;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.oy.Pojo.User;
    import com.oy.annotation.IsLogin;
    
    /**
     * spring自定义注解拦截器的配置
     *     1)自定义注解IsLogin;
     *  2)自定义拦截器LoginInterceptor,映射路径"/**",拦截所有请求;
     *  3)注册拦截器;
     *  4)在本方法中测试LoginInterceptor + 注解@IsLogin的使用
     *  
     *  实现功能:标注@IsLogin的方法,必须登录才能访问;没有登录重定向到login.jsp;
     */
    @Controller
    public class CustomerInterceptorController {
        
        /**
         * 登录
         * @return
         */
        @RequestMapping("/test/login")
        @ResponseBody
        public String login(HttpServletRequest request) {
            
            User user = new User();
            user.setId(1);
            user.setUsername("xxx");
            user.setPassword("123");
            request.getSession().setAttribute("currentUser", user);
            return "<a href='/test/isLogin'>click,test is logged in or not</a>";
        }
        
        /**
         * 此方法被@IsLogin标注,只有登录才能调用此方法
         * @return
         */
        @IsLogin
        @RequestMapping("/test/isLogin")
        @ResponseBody
        public String add() {
            return "hello, xxx, you are welcome!";
        }
    }
    View Code

    5、spring mvc的 HandlerMethod 和 ResourceHttpRequestHandler  <--返回目录

      HandlerInterceptor 接口三个方法都有一个参数 handler, 如果请求目标是 controller 的方法,则 handler 类型是 org.springframework.web.method.HandlerMethod。HandlerMethod封装了很多属性,在访问请求方法的时候可以方便的访问到方法、方法参数、方法上的注解、所属类等并且对方法参数封装处理,也可以方便的访问到方法参数的注解等信息。如果请求目标是静态资,handler 类型是org.springframework.web.servlet.resource.ResourceHttpRequestHandler。

    6、springboot 注册拦截器  <--返回目录

      https://www.cnblogs.com/tiancai/p/11196667.html

    参考:

      1)《JavaEE互联网轻量级框架整合开发SSM框架(SpringMVC+Spring+MyBatis)和Redis实现》杨开振

  • 相关阅读:
    Java之字符串String,StringBuffer,StringBuilder
    去除前后空格,Oracle和SQLSERVER都适用。ltrim(rtrim(’ ‘))
    java IO,bufferedReader类
    Python与操作系统有关的模块
    u盘引导制作工具
    Shell中判断语句if中-z至-d的意思
    shell脚本输出带颜色字体
    MySQL数据库权限管理
    vi/vim使用进阶: 文件浏览和缓冲区浏览
    (转载)跟我一起学习VIM
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/12690512.html
Copyright © 2020-2023  润新知