springMVC-14 自定义拦截器

发布于:2025-06-21 ⋅ 阅读:(16) ⋅ 点赞:(0)

什么是拦截器

  • 说明

1.Spring MVC也可以使用拦截器对请求进任拦截处理,用户可以自定义拦截器来实现特定的功能。
2.自定义的拦截器必须实现HandlerInterceptor:接口

  • 自定义拦截器的三个方法

1.preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求request进行处理。
2.postHandle():这个方法在目标方法处理完请求后执行
3.afterCompletion():这个方法在完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。

  • 自定义拦截器执行流程分析图

  • 自定义拦截器执行流程说明

1.如果preHanle方法返回false,则不再执行目标方法,可以在此指定返回页面
2.postHandle在目标方法被执行后执行。可以在方法中访问到目标方法返回的ModelAndView对象
3.若preHandle返回true,则afterCompletion方法在渲染视图之后被执行。
4.若preHandle返回false,则afterCompletion方法不会被调用
5.在配置拦截器时,可以指定该拦截器对哪些请求生效,哪些请求不生效

应用实例

1.创建自定义的拦截器,com/stein/springMVC/interceptor/MyInterceptor.java

@Component //需要注入到容器
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("---MyInterceptor-preHandle()被调用--");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("---MyInterceptor-postHandle()被调用--");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("---MyInterceptor-afterCompletion()被调用--");

    }
}

2.在springMVC中进行配置,web/WEB-INF/springMVC-servlet.xml

说明:        
        拦截器Interceptor是由springMVC来配置
        过滤器Filter是由web.xml来配置

1)配置方法一,只配置一个拦截器

        可以直接放在<interceptors>里面,注意有s

        然后可以不配置<mvc:mapping>,默认拦截所有

    <mvc:interceptors>
         <ref bean="myInterceptor"/>
    </mvc:interceptors>

2)配置方法二,放在子<mvc:interceptor>里面,注意没有s

        可以配置多个<mvc:interceptor>
        但必须配置<mvc:mapping> ,否则使用时报错
        path的值,是对应的requestMapping,支持通配符操作
        交换mapping和ref标签的位置,软件会报错

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/h*" />
            <ref bean="myInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

3.创建访问页面,web/interceptor.jsp

    <h1>拦截器</h1>
    <a href="<%=request.getContextPath()%>/hello">--目标方法hello</a><br><br>
    <a href="<%=request.getContextPath()%>/hi">--目标方法hi</a><br><br>
    <a href="<%=request.getContextPath()%>/ok">--目标方法ok</a><br><br>

4.测试

        hi方法被拦截
        ok方法没有拦截

---MyInterceptor-preHandle()被调用--
hi
---MyInterceptor-postHandle()被调用--
---MyInterceptor-afterCompletion()被调用--


ok

注意事项和细节

1、默认配置是都所有的目标方法都进行拦截,也可以指定拦截目标方法,比如只是拦截hi

<mvc:interceptor>
    <mvc:mapping path="/hi"/>
    <ref bean="myInterceptor01"/>
</mvc:interceptor>

2、mvc:mapping支持通配符,同时指定不对哪些目标方法进行拦截

<mvc:interceptor>
    <mvc:mapping path="/h*"/>
    <mvc:exclude-mapping path="/hello"/>
    <ref bean="myInterceptor01"/>
</mvc:interceptor>

3、拦截器需要配置才生效,不配置是不生效的。

        @component + springMVC配置

4、如果preHandler()方法返回了false,就不会执行目标方法(前提是目标方法被拦截),程序员可以在这里根据业务需要指定跳转页面。

Debug代码

1.修改com/stein/springMVC/interceptor/InterceptorHandler.java的hi方法

        添加参数user,便于查看ModelAndView传递的数据

    @RequestMapping("/hi")
    public String hi(User user){
        System.out.println("hi~"+user);
        return "success";
    }

2.Debug模式启动,点击页面hi方法

3.后端可以看到,handler就是目标方法,同时拦截器的preHandle方法被调用

4.然后可以走到目标方法hi

5.继续运行到postHandle,可以看到modelAndView附带了参数,以及视图

6.通过Ctrl+N查找DispatcherServlet的render方法,可以看到mv依然为空

7.通过返回view视图,通过render渲染数据

8.最后返回afterCompletion,看到目标方法,以及有异常初选的话,会封装到Exception中去

9.也可以使用postman对user进行赋值,这样走debug的时候,有具体的数据

多个拦截器

多个拦截器执行流程示意图

应用实例1

代码实现

1.创建第二个拦截器,com/stein/springMVC/interceptor/MyInterceptor02.java

        注意使用注解@Component将其注入,否则后面配置不会生效

@Component
public class MyInterceptor02 implements HandlerInterceptor {

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

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

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("---MyInterceptor02.afterCompletion()---");
    }

2.配置web/WEB-INF/springMVC-servlet.xml

        第一个拦截器,排除/hi路径

        配置第二个拦截器,再次强调,对应的拦截器要注入

        可以看出,是按照配置的顺序,设定拦截器的生效顺序的

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/h*" />
            <mvc:exclude-mapping path="/hi"/>
            <ref bean="myInterceptor"/>
        </mvc:interceptor>

        <mvc:interceptor>
            <mvc:mapping path="/h*"/>
            <ref bean="myInterceptor02"/>
        </mvc:interceptor>
    </mvc:interceptors>

3.测试

测试1:点击hello方法

可以看到执行的流程

---MyInterceptor-preHandle()被调用--
---MyInterceptor02.preHandle()被调用---
hello
---MyInterceptor02.postHandle()---
---MyInterceptor.postHandle()被调用--
---MyInterceptor02.afterCompletion()---
---MyInterceptor.afterCompletion()被调用--

测试2:点击hi方法

因为拦截器1排除了目标方法hi,所以只有一个拦截

---MyInterceptor02.preHandle()被调用---
hi
---MyInterceptor02.postHandle()---
---MyInterceptor02.afterCompletion()---

测试3:点击ok方法

因为没有拦截器对其生效,所以没有拦截

ok

注意事项和细节

1.如果A拦截器的preHandle()返回false,则直接返回browser,后面都不在执行
2.如果B拦截器的preHandle()返回false,就直接执行第1个拦截器的afterCompletion()方法,如果拦截器更多,规则类似
3.上述两种情况,都不会执行目标方法hi();
4.说明:前面说的规则,都是目标方法被拦截的前提

应用实例2

1.需求:如果用户提交的数据有禁用词(比如病毒),则在第1个拦截器就返回,不再执行目标方法,功能效果示意图

2.创建跳转的页面,web/WEB-INF/page/warning.jsp

<h1>不要乱说讲话</h1>

3.修改拦截器的preHandler方法,com/stein/springMVC/interceptor/MyInterceptor02.java

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("---MyInterceptor02.preHandle()被调用---");

        String keyword = request.getParameter("keyword");
        if("病毒".equals(keyword)){
            System.out.println("true已经执行");
            //绝对路径(推荐):以 / 开头,表示从当前 Web 应用的根目录(Context Root)开始
            //request.getRequestDispatcher("web/WEB-INF/page/warning.jsp").forward(request, response);会找不到
            request.getRequestDispatcher("/WEB-INF/page/warning.jsp").forward(request, response);
            return false;
        }
        System.out.println("keyword="+keyword);
        return true;
    }

4.使用postman测试。post方法测试结果如需求1示例图,下面是get方法测试

        结果一致

---MyInterceptor02.preHandle()被调用---
true已经执行


网站公告

今日签到

点亮在社区的每一天
去签到