spring mvc 拦截器

Scroll Down

spring mvc 拦截器

过滤器和拦截器的区别

拦截器是基于AOP思想的

拦截器只会拦截访问的控制器方法,是方法级别的拦截

Spring MVC Architecture

  • When DispatcherServlet receives the request, it dispatches the task of selecting an appropriate controller to HandlerMapping. Then, HandlerMapping selects the controller which is mapped to the incoming request URL and returns the (selected Handler) and Controller to DispatcherServlet.

  • DispatcherServlet dispatches the task of executing the business logic by Controller to HandlerAdapter. HandlerAdapter calls the business logic process of Controller. When the HandlerAdapter calls the controller, Interceptor is invoked to intercept the request.

  • Then, Controller executes the business logic and sets the processing result in Model. Then, if there is any Interceptor to intercept the response, is invoked as a post process. Then Controller returns the logical name of view to HandlerAdapter.

  • DispatcherServlet dispatches the task of resolving the View corresponding to the View name to ViewResolver. ViewResolver returns the View mapped to View name.

  • DispatcherServlet dispatches the rendering process to returned View.

  • View renders Model data and returns the response.

工作流如下

  1. DispatcherServlet收到请求,分发给负责HandlerMapping的控制器
  2. DispatcherServlet分发任务处理业务逻辑给HandlerAdapter适配器,适配器调用Controller的方法,当适配器调用方法前,拦截器介入,拦截
  3. 如果拦截器不放行,处理器不执行请求,如果拦截器方向,后面的过程和正常的一样

自定义拦截器

All HandlerMapping implementations support handler interceptors that are useful when you want to apply specific functionality to certain requests

所有的处理器映射的实现类支持处理器拦截器,并在你想在特定的请求上完成一些特点的功能会很有用

Interceptors must implement HandlerInterceptor from the org.springframework.web.servlet package

所有的拦截器都必须继承,HandlerInterceptor 接口,且有三个方法可以继承

  1. preHandle(..):在之际的处理器执行之前做
  2. postHandle(..):在处理器执行之后做
  3. afterCompletion(..):在请求执行完成之后做

The preHandle(..) method returns a boolean value. You can use this method to break or continue the processing of the execution chain. When this method returns true, the handler execution chain continues. When it returns false, the DispatcherServlet assumes the interceptor itself has taken care of requests (and, for example, rendered an appropriate view) and does not continue executing the other interceptors and the actual handler in the execution chain.

preHandle(..)方法返回一个布尔值,我们可以用这个方法去拦截或者放行执行链。当这个方法返回值为true ,拦截器放行,当返回值为falseDispatcherServlet认为这个拦截器本身就已经做了处理,比

如说跳到了某个特定的视图,然后就不去执行其他拦截器或者执行真正的处理器了

实现接口

拦截器最常用的业务场景就是判断用户有没有登录和有没有权限访问

public class LoginInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获得请求路径的uri
        String uri = request.getRequestURI();

        // 进入登录页面,判断session中是否有key,有的话重定向到首页,否则进入登录界面
        if(uri.endsWith("/login")||uri.contains("Login")||uri.contains("login")) {
            return true;
        }

        // 如果没有session就代表没有登录
        if(request.getSession() == null)
        {
            response.sendRedirect(request.getContextPath());
        }
        
        // 其他情况判断session中是否有key,有的话继续用户的操作
        if(request.getSession().getAttribute("user") != null) {
            return true;
        }

        // 最后的情况就是进入登录页面
        response.sendRedirect(request.getContextPath());

        return false;
    }
}

配置拦截器

通过mvc:interceptors

<mvc:interceptors>
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <mvc:exclude-mapping path="/admin/**"/>
        <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/secure/*"/>
        <bean class="org.example.SecurityInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

通过RequestMappingHandlerMapping

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
    <property name="interceptors">
        <bean class="com.lucas.interceptor.LoginInterceptor"/>
    </property>
    <property name="order" value="-1"/>
</bean>

多个拦截器配置

参考博客: https://blog.csdn.net/itcats_cn/article/details/80371639

  • preHandle按拦截器定义顺序调用
  • postHandler按拦截器定义逆序调用
  • afterCompletion按拦截器定义逆序调用
  • postHandler在拦截器链内所有拦截器返成功调用
  • afterCompletion只有preHandle返回true才调用