zoukankan      html  css  js  c++  java
  • springmvc-拦截器

    1.

    Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
    用户可以自己定义一些拦截器来实现特定的功能。
    谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺
    序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
    说到这里,可能大家脑海中有了一个疑问,这不是我们之前学的过滤器吗?是的它和过滤器是有几分相似,但
    是也有区别,接下来我们就来说说他们的区别:
    过滤器是 servlet 规范中的一部分, 任何 java web 工程都可以使用。
    拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
    过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
    拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp, html,css,image 或者 js 是不会进行拦
    截的。
    它也是 AOP 思想的具体应用。
    我们要想自定义拦截器, 要求必须实现: HandlerInterceptor 接口。

    2.作用过程

    拦截器的作用对象的controller,拦截器有个放行的功能,可以在放行之前和之后编写一些代码

    预处理,在请求controller之前,会先经过拦截器

    后处理,在请求controller之后,跳转某个页面之前,会经过拦截器

    拦截器链,也就是会有多个拦截器,比如第一个拦截器放行了,会再经过第二个拦截器...一直到没有了,才会执行controller,返回依然。

     演示

    一、jsp页面

    1.index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>拦截器</title>
    </head>
    <body>
        <h3>拦截器</h3>
        <a href="user/testInterceptor">测试拦截器</a>
    </body>
    </html>

    2.跳转成功页面success.jsp,会有一个在控制台输出的代码,方便演示

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h3>跳转成功</h3>
        <%System.out.println("run success.jsp...");%>
    </body>
    </html>

    3.跳转失败的页面error.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h3>跳转失败页面</h3>
    </body>
    </html>

    二、控制器

    @Controller
    @RequestMapping("/user")
    public class UserController {
        @RequestMapping("/testInterceptor")
        public String testInterceptor(){
            System.out.println("run testInterceptor()...");
            return "success";
        }
    }

    三、拦截器

    拦截器需要实现HandlerInterceptor类,这个类有三个方法

    1.preHandle()方法

    这里先演示第一个方法,也就是在controller执行之前的方法

    public class MyInterceptor implements HandlerInterceptor {
        /**
         * 预处理,controller执行之前执行这个方法
         * @param request
         * @param response
         * @param handler
         * @return true,表示放行,会执行这个方法的代码,然后再执行下一个拦截器,如果没有,则执行controller中的方法;
         *         false则表示不放行,也就是只执行这个方法的代码,不会执行controller中的方法,可以通过request和response直接跳转到某个页面
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("run MyInterceptor1.preHandle()...");
    //        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
            return true;
        }
    }

    拦截器需要在springmvc.xml配置文件中配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
        <context:component-scan base-package="com.cong.controller"></context:component-scan>
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/pages/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
        <!--配置拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
                <!--要拦截的具体的方法-->
                <mvc:mapping path="/user/*"/>
                <!--不要拦截的具体的方法-->
                <!--<mvc:exclude-mapping path=""/>-->
                <!--配置拦截器对象-->
                <bean class="com.cong.interceptor.MyInterceptor"/>
            </mvc:interceptor>
            <!--配置第二个拦截器要另外写一个mvc:interceptor-->
            <!--<mvc:interceptor></mvc:interceptor>-->
        </mvc:interceptors>
        <mvc:annotation-driven></mvc:annotation-driven>
    </beans>

    结果,根据打印的内容,可以看出,

    先是执行了拦截器的preHandle()方法,然后放行,执行controller中的方法,最后跳转到success.jsp页面

    如果, 将preHandle()方法的返回值设置为false,那么就是拦截器不允许通过,

    也就是不会执行controller中的方法,再取消注释,手动跳转到error.jsp页面

    结果如下,根据控制台的打印内容,

    先是执行了拦截器的preHandle()方法,然后不放行,不再执行controller中的方法,直接跳转到error.jsp页面

     2.postHandle()方法

    在preHandle()的基础上添加一个postHandle()方法

    public class MyInterceptor implements HandlerInterceptor {
        /**
         * 预处理,controller执行之前执行这个方法
         * @param request
         * @param response
         * @param handler
         * @return true,表示放行,执行下一个拦截器,如果没有,则执行controller中的方法;
         *          false则表示不放行,可以通过request和response直接跳转到某个页面
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("run MyInterceptor1.preHandle()...");
    //        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
            return true;
        }
    
        /**
         * 后处理的方法,当controller的方法执行完,要进行页面跳转了(也就是执行success.jsp),就会先这个方法
         * 也可以直接进行页面跳转
         * @param request
         * @param response
         * @param handler
         * @param modelAndView
         * @throws Exception
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("run MyInterceptor1.postHandle()...");
    //        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
        }
    }

    结果如下,也就是先执行了preHandle()方法,然后执行controller中的方法,再执行postHandle()方法,最后跳转到success.jsp页面

    postHandle()没有返回值,但是一样可以直接进行页面跳转,如果直接进行页面跳转,结果如下

    也就是先执行了preHandle()方法,然后执行controller中的方法,再执行postHandle()方法,最后跳转到error.jsp页面

    (虽然打印了run success.jsp...   但实际上并没有跳转到success。jsp)

     3.afterCompletion()方法

    public class MyInterceptor implements HandlerInterceptor {
        /**
         * 预处理,controller执行之前执行这个方法
         * @param request
         * @param response
         * @param handler
         * @return true,表示放行,执行下一个拦截器,如果没有,则执行controller中的方法;
         *          false则表示不放行,可以通过request和response直接跳转到某个页面
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("run MyInterceptor1.preHandle()...");
    //        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
            return true;
        }
    
        /**
         * 后处理的方法,当controller的方法执行完,要进行页面跳转了(也就是执行success.jsp),就会先这个方法
         * 也可以直接进行页面跳转
         * @param request
         * @param response
         * @param handler
         * @param modelAndView
         * @throws Exception
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("run MyInterceptor1.postHandle()...");
            //request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
        }
    
        /**
         * success.jsp执行之后再执行的方法,一般用作释放资源
         * @param request
         * @param response
         * @param handler
         * @param ex
         * @throws Exception
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("run MyInterceptor1.afterCompletion()...");
        }
    }

    结果如下,也就是afterComplition()方法是在页面跳转之后再进行执行的

     在这里,再写一个拦截器

    public class MyInterceptor2 implements HandlerInterceptor {
        /**
         * 预处理,controller执行之前执行这个方法
         * @param request
         * @param response
         * @param handler
         * @return true,表示放行,执行下一个拦截器,如果没有,则执行controller中的方法;
         *          false则表示不放行,可以通过request和response直接跳转到某个页面
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("run MyInterceptor2.preHandle()...");
    //        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
            return true;
        }
    
        /**
         * 后处理的方法,当controller的方法执行完,要进行页面跳转了(也就是执行success.jsp),就会经过这个方法
         * @param request
         * @param response
         * @param handler
         * @param modelAndView
         * @throws Exception
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("run MyInterceptor2.postHandle()...");
    //        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
        }
    
        /**
         * success.jsp执行之后再执行的方法,一般用作释放资源
         * @param request
         * @param response
         * @param handler
         * @param ex
         * @throws Exception
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("run MyInterceptor2.afterCompletion()...");
        }
    }

    注入到容器中

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

    执行的过程如下

    爱生活,爱码字

    我是匆匆、我曾喂自己半年酒。

    好好生活吧,有缘或许相见。

  • 相关阅读:
    基于发布/订阅模型的应用程序的主循环设计
    C++使用继承时子对象的内存布局
    安装 CentOS 后的系统配置及软件安装备忘
    环形无锁队列
    并发编程基础
    线程池实现
    Git远程操作
    Unix权限管理
    jquery中,某些写法后来更新导致版本不支持的替代方法
    js相关
  • 原文地址:https://www.cnblogs.com/ccoonngg/p/11854487.html
Copyright © 2011-2022 走看看