springMVC拦截器执行过程和使用

本文详细介绍了SpringMVC中的拦截器,包括其执行流程、各个方法的功能,如preHandle用于认证和授权,postHandle处理公共模型数据,afterCompletion负责异常处理和资源清理。同时,讲解了如何配置和使用拦截器,强调了配置顺序与执行顺序的关系,并给出了运行示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.拦截器: 用于对handle进行预处理和后处理
2.执行过程
在org.springframework.web.servlet.DispatcherServlet#doDispatch中:

HandlerExecutionChain mappedHandler = null;
//首先获取HandlerExecutionChain(handle和拦截器)
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest, false);

...
//1.拦截器开始作用(PreHandle方法:说明切点是在执行handle之前)
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
//只要有拦截器返回false就退出,同时在catch语句块中触发AfterCompletion
                    return;
                }

//通过applyPreHandle的for循环可以看出PreHandle的执行顺序为顺序执行
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (getInterceptors() != null) {
            for (int i = 0; i < getInterceptors().length; i++) {
                HandlerInterceptor interceptor = getInterceptors()[i];
                //只要一个preHandle返回false,就返回false
                if (!interceptor.preHandle(request, response, this.handler)) {
                    triggerAfterCompletion(request, response, null);
                    return false;
                }
                this.interceptorIndex = i;
            }
        }
        return true;
    }

//执行handle
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());


//2.执行PostHandle(切点在handle执行后,视图返回之前)
mappedHandler.applyPostHandle(processedRequest, response, mv);

//通过applyPostHandle的for循环可以知道PostHandle执行顺序为逆序
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
        if (getInterceptors() == null) {
            return;
        }
        for (int i = getInterceptors().length - 1; i >= 0; i--) {
            HandlerInterceptor interceptor = getInterceptors()[i];
            interceptor.postHandle(request, response, this.handler, mv);
        }
    }


//3.AfterCompletion在下面的方法中被调用(AfterCompletion切入点是在视图渲染后(执行异常后也会被调用),也就是视图返回前执行)
//视图渲染,处理异常(视图渲染之后会执行triggerAfterCompletion)
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
//出现异常错误后执行
catch (Exception ex) {
    triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
    triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}

//afterCompletion被使用的方法:(从for循环可以看出是逆序执行)
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
            throws Exception {

        if (getInterceptors() == null) {
            return;
        }
        for (int i = this.interceptorIndex; i >= 0; i--) {
            HandlerInterceptor interceptor = getInterceptors()[i];
            try {
                interceptor.afterCompletion(request, response, this.handler, ex);
            }
            catch (Throwable ex2) {
                logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
            }
        }
    }

3.拦截器各个方法的作用
a)preHandle

//Called after HandlerMapping determined an appropriate handler object, but before HandlerAdapter invokes the handler.(在handle被调用之前执行)
//return false表示拦截,不向下执行
//return true表示放行
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception;

作用:用于身份认证、身份授权

b)postHandle

//Called after HandlerAdapter actually invoked the handler, but before the DispatcherServlet renders the view.(handlle执行之后,视图返回之前)
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;

作用:将公用的模型数据在这里传到视图,也可以在这里统一指定视图(比如:菜单导航)

c)afterCompletion

//Callback after completion of request processing, that is, after rendering the view.(视图渲染后执行)
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;

作用:统一异常处理,统一日志处理,资源清理

4.拦截器的配置和使用

配置:
主要使用springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中。
在springMVC的配置文件中配置

<mvc:interceptors>
        <!--多个拦截器,顺序执行 -->
        <mvc:interceptor>
            <!-- /**表示所有url包括子url路径 -->
            <mvc:mapping path="/**"/>
            <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2"></bean>
        </mvc:interceptor>
</mvc:interceptors>

当需要配置公开地址时,在<mvc:interceptor> 中添加:

<!--将公开地址配置在path中-->
<mvc:exclude-mapping path="/"/>

使用:
实现org.springframework.web.servlet.HandlerInterceptor这个接口

public class HandlerInterceptor1 implements HandlerInterceptor{...}

5.注意点
1)对于统一日志处理之类的全局设置:需要将对应的拦截器放在拦截器链的第一个
2)preHandle方法按拦截器配置的顺序执行,postHandle和afterCompletion按拦截器配置的逆向顺序执行。
3)只要有一个拦截器不放行,postHandle不会执行,只有在拦截器链内所有拦截器放行(即返回true)才会执行
4)只有preHandle返回true,afterCompletion才会执行

运行示例
比如两个拦截器:
1)第一个拦截器放行,第二个放行:

HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle

HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle

HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion

2)第一个拦截器放行,第二个拦截:

HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle

HandlerInterceptor1...afterCompletion

3)第一个拦截器拦截,第二个放行(或者不放行):
HandlerInterceptor1…preHandle

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值