SpringMVC拦截器

拦截器

过滤器过滤的是客户端对资源的访问

拦截器的配置

SpringMVC中的拦截器用于拦截控制器方法的执行

SpringMVC的拦截器需要实现HandlerInterceptor

SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置:

<mvc:interceptors>
        <bean id="firstInterceptor" class="com.my.interceptor.FirstInterceptor" />
        <ref bean="secondInterceptor" />
        <!-- bean标签和ref标签所配置的拦截器默认对DispatcherServlet处理的所有请求进行拦截 -->
        <!--<bean class="com.my.interceptor.FirstInterceptor"/>-->
        <!--<ref bean="firstInterceptor" />-->
        <!--<mvc:interceptor>
            <!-- 配置需要拦截的请求的请求路径,/**表示所有请求 -->
            <!-- <mvc:mapping path="/**"/>
            <!-- 配置需要排除拦截的请求的请求路径 -->
            <!-- <mvc:exclude-mapping path="/abc"/>
            <!-- 配置拦截器 -->
            <!-- <ref bean="firstInterceptor" />
        <!-- </mvc:interceptor> -->
    </mvc:interceptors>
/** 
 * 拦截器的三个方法:
 * preHandle():在控制器方法执行之前执行,其返回值表示对控制器方法的拦截(false) 或放行(true)
 * postHandle():在控制器方法执行之后执行
 * afterCompletion():在控制器方法执行之后,且渲染视图完毕之后执行 在render()之后执行,
 *
 * 多个拦截器执行顺序和在SpringMVC的配置文件中配置的顺序有关
 * preHandle()按照配置的顺序执行,而postHandle()和afterCompletion按照配置的反序执行
 */
@Component
public class FirstInterceptor implements HandlerInterceptor {
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 控制器方法执行之前执行 true 放行 false 拦截
        System.out.println("FirstInterceptor-->preHandle");
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
​
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("FirstInterceptor-->postHandle");
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }
​
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("FirstInterceptor-->afterCompletion");
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

异常处理器

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <!-- key设置要处理的异常,value设置出现该异常时要跳转的页面所对应的逻辑视图 -->
            <prop key="java.lang.ArithmeticException">error</prop>
        </props>
    </property>
    <!-- 设置共享在请求域中的异常信息的属性名 -->
    <property name="exceptionAttribute" value="ex"></property>
</bean>

处理器 == 控制器方法

applyPreHandle()源码

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
    for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex = i++) {
        HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
        if (!interceptor.preHandle(request, response, this.handler)) {
            this.triggerAfterCompletion(request, response, (Exception)null);
            return false;
        }
    }
​
    return true;
}

applyPostHandle()源码

void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
    for(int i = this.interceptorList.size() - 1; i >= 0; --i) {
        HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
        interceptor.postHandle(request, response, this.handler, mv);
    }
​
}

triggerAfterCompletion源码

void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
    for(int i = this.interceptorIndex; i >= 0; --i) {
        HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
​
        try {
            interceptor.afterCompletion(request, response, this.handler, ex);
        } catch (Throwable var7) {
            logger.error("HandlerInterceptor.afterCompletion threw exception", var7);
        }
    }
​
}

根据观察源码我们可以知道为什么preHandle()按照配置的顺序执行,而postHandle()和afterCompletion按照配置的反序执行。

因为在源码中applyPreHandle()遍历时用的是i++,而applyPostHandle()和triggerAfterCompletion()中用的是i--,

若拦截器中有某个拦截器的preHandle()返回了false

  • 拦截器的preHandle()返回了false和它之前的拦截器都会执行 之后的不会执行

  • 所有拦截器的postHandle()都不执行

  • 拦截器的preHandle()返回了false之前的拦截器的afterCompletion()会执行

异常处理器

SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口:Handler ExceptionResolver

Handler ExceptionResovler接口的实现类又:DefaultHandlerExceptionResolver 和 SimpleMappingExceptionResolver

SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResovler,使用方式:

XML

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <!-- key设置要处理的异常,value设置出现该异常时要跳转的页面所对应的逻辑视图 -->
            <prop key="java.lang.ArithmeticException">error</prop>
        </props>
    </property>
    <!-- 设置共享在请求域中的异常信息的属性名 -->
    <property name="exceptionAttribute" value="ex"></property>
</bean>

注解:

// 将当前类标识为异常处理的组件
@ControllerAdvice
public class ExceptionController {
​
    // 设置要处理的异常信息
    @ExceptionHandler(ArithmeticException.class)
    public String handleException(Throwable ex, Model model){
        // ex标识控制器方法所出现的异常
        model.addAttribute("ex", ex);
        return "error";
    }
​
}
  • 16
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值