SpringMVC实现拦截器的两种方式(详细)

1、概念

Spring MVC 的拦截器(Interceptor)与 Java Servlet 的过滤器(Filter)类似,它主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。

在 Spring MVC 框架中定义一个拦截器需要对拦截器进行定义和配置,定义一个拦截器可以通过两种方式:一种是通过实现 HandlerInterceptor 接口或继承 HandlerInterceptor 接口的实现类来定义;另一种是通过实现 WebRequestInterceptor 接口或继承 WebRequestInterceptor 接口的实现类来定义。

2、区别

两个拦截器都是Spring提供的,但是WebRequestInterceptor只会起到一个请求验证的目的,表示请求会被WebRequestInterceptor实现类接收。并不会像HandlerInterceptor拦截器一样将不合法的请求死死拦截。

3、两个接口的方法

3.1、HandlerInterceptor接口的方法

public interface HandlerInterceptor {

	// 在Controller得到请求的时候进行拦截,如果不放行请求则Controller得不到请求
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
    
	//在Controller处理完请求要进行视图的跳转的时候进行调用此方法
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

	// 在视图跳转完成后调用此方法
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

HandlerInterceptor接口中的方法都是default的,表示不强制重写方法。但是我们一般都会重写这三个方法。

3.2、WebRequestInterceptor接口的方法

public interface WebRequestInterceptor {

	/** Controller得到请求之前调用此方法拦截请求,
		但是不会像HandlerInterceptor一样会拦截请求而不释放。
	**/
    void preHandle(WebRequest request) throws Exception;

	// Controller处理完请求后调用此方法
    void postHandle(WebRequest request, @Nullable ModelMap model) throws Exception;

	// 视图跳转后调用此方法。
    void afterCompletion(WebRequest request, @Nullable Exception ex) throws Exception;
}

WebRequestInterceptor只有preHandle方法与HandlerInterceptor接口中的preHandle方法不同外,其他都是一样的。
另外,WebRequestInterceptor中的方法都是Void类型,所有在实现此接口时必须重写接口内部的所有方法。(基础中的基础,不能忘记)
但是,WebRequestInterceptor是spring对HttpServletRequest的封装,所以,使用WebReqeustInterceptor处理的内容,会记录在HttpServletRequest中。

4、springMVC.xml的配置

   <!--配置拦截器-->
    <mvc:interceptors>
        <bean class="utils.Interceptor"/> <!--配置一个全局的拦截器,拦截所有请求-->
        <mvc:interceptor> <!--配置特定请求的拦截器,拦截指定的请求-->
            <mvc:mapping path="/**"/> <!--配置当前特定拦截器拦截的路径-->
            <mvc:exclude-mapping path="/login"/> <!--指定的请求不需要拦截-->
            <bean class="utils.Interceptor"/> <!--配置路径由那个拦截器进行拦截-->
        </mvc:interceptor>

        <mvc:interceptor>
            <mvc:mapping path="/loginOut"/>
            <mvc:exclude-mapping path="/login"/>
            <bean class="utils.WebInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

上述内容必须配置,否则拦截器无效,可以根据需要自行配置,但是拦截器的配置顺序有严格的要求:

<mvc:interceptor>
   <mvc:mapping path="拦截的请求"/>
   <mvc:exclude-mapping path="不拦截的请求"/>
   <bean class="拦截器对象的路径"/>
</mvc:interceptor>

5、话不多说,上代码

注意力集中,不然就是我在地球,你在外太空。

5.1、WebInterceptor实现类

public class Interceptor implements HandlerInterceptor {

    private static int preFlag = 0, postFlag = 0, afterFlag = 0;

    // 在Controller得到请求的时候进行拦截,如果不放行请求则Controller得不到请求
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器拦截到了请求,请求的URI为:" + request.getRequestURI());
        System.out.println("拦截次数=" + (++preFlag));
        return true; // 释放请求
        // 如果拦截器不释放请求,则请求会一直处于被拦截状态
    }

    // 在Controller处理完请求后,视图渲染之前,拦截器进行验证
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("拦截器开始解析请求" + modelAndView.getViewName());
        System.out.println("解析请求次数=" + (++postFlag));
    }

    // 视图渲染完成之后调用
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("请求完成");
        System.out.println("渲染次数=" + (++afterFlag));
    }
}

springMVC.xml的配置

    <mvc:interceptors>
        <bean class="utils.Interceptor"/> <!--配置一个全局的拦截器,拦截所有请求-->
        <mvc:interceptor> <!--配置特定请求的拦截器,拦截指定的请求-->
            <mvc:mapping path="/**"/> <!--配置当前特定拦截器拦截的路径-->
            <mvc:exclude-mapping path="/login"/> <!--指定的请求不需要拦截-->
            <bean class="utils.Interceptor"/> <!--配置路径由那个拦截器进行拦截-->
        </mvc:interceptor>
    </mvc:interceptors>

HandleInterceptor拦截器会对请求进行两次拦截,哈!为啥要进行两次拦截咧?

springMVC会认为你的请求URI是一个视图名称,然后在渲染视图之前会检查你的视图名称,如果是视图就抛出SerlvetException,这个错误会导致DispatcherServlet的整个流程重新开始。

这是我知道的答案。

看不懂,就看图,看效果
我配置的HandleInterceptor会拦截所有请求
在这里插入图片描述
搜索结果
在这里插入图片描述
后台拦截的结果
在这里插入图片描述

5.2、WebRequestInterceptor实现类

public class WebInterceptor implements WebRequestInterceptor {

    @Override
    public void preHandle(WebRequest request) throws Exception {
        System.out.println("开始拦截");
    }

    @Override
    public void postHandle(WebRequest request, ModelMap model) throws Exception {
        System.out.println("处理完成后查看请求");
    }

    @Override
    public void afterCompletion(WebRequest request, Exception ex) throws Exception {
        System.out.println("渲染完成");
    }
}

springMVC.xml的配置

<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/search"/> <!--只对搜索请求进行拦截-->
            <mvc:exclude-mapping path="/login"/> <!--不拦截登录请求-->
            <bean class="utils.WebInterceptor"/> <!--拦截器的实现类-->
        </mvc:interceptor>
   </mvc:interceptors>

WebRequestInterceptor始终都会对请求进行放行。
同样是拿搜索举例
在这里插入图片描述
按照我们的使用HandleInterceptor而言,是无法进行搜索的,因为在按钮被按下的时候,请求会被拦截器拦截,然后看prehandle返回值是false还是true,false则不放行请求,
而WebRequestInterceptor中的preHandle方法没有返回值,所以就会对所有请求都会放行。
结果也的确是这样:
在这里插入图片描述
后台拦截器的拦截效果
在这里插入图片描述
WebRequestInterceptor拦截器只会拦截一次,但是在效果上与handleInterceptor却有很大区别。

我想,对于用心学习的猿友,不可能不知道能拦截请求和不能拦截请求的重要性吧,不会吧,不会吧,应该不至于不知道吧。😥

6、OK,开始总结

过滤器是SpringMVC中的一个重要组件,良好的使用能起到事半功倍的效果,如果使用不良,嘿嘿,你们懂的(几个小时很快就过去了)。
当然除了使用SpringMVC中的这两个过滤器之外,还可以使用Servlet中的Filter接口自定义过滤器,使用哪种方式,还是看个人啦。

在这里插入图片描述

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值