zoukankan      html  css  js  c++  java
  • 过滤器/拦截器/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实现》杨开振

  • 相关阅读:
    奇数阶魔方问题
    《DSP using MATLAB》示例9.3
    《DSP using MATLAB》示例9.2
    《DSP using MATLAB》示例9.1
    找个目标很重要
    《DSP using MATLAB》示例Example 8.30
    《DSP using MATLAB》示例Example 8.29
    《DSP using MATLAB》示例Example 8.28
    《DSP using MATLAB》示例Example 8.27
    《DSP using MATLAB》示例Example 8.26
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/12690512.html
Copyright © 2011-2022 走看看