SpringMVC拦截器及异常处理

SpringMVC拦截器

简介

拦截器和过滤器不一样,拦截器是作用于控制器方法前后的

拦截器的配置

SpringMVC中的拦截器需要创建一个类实现HandlerInterceptor接口,并重写他的三个抽象方法

  • preHandle:作用于控制器方法之前
  • postHandle:作用于控制器方法执行完毕后
  • afterCompletion:作用于视图渲染等一系列操作之后(可以理解为即将要返回给客户端时)
@Component
public class FirstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("FirstInterceptor---->preHandle");
        return true;
    }

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

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

SpringMVC配置器必须在spring MVC.xml文件中进行拦截器的配置

    <!--配置拦截器-->
    <mvc:interceptors>
    <!--<bean class="com.yellowstar.mvc.interceptors.FirstInterceptor"></bean>-->
    <!--<ref bean="firstInterceptor"></ref>-->
        以上通过bean或者ref进行对拦截器的配置,将作用于工程中的所有控制器前后
        以下通过mvc:interceptor进行配置
        	可以通过mvc:mapping设置起作用的请求路径,所有请求用“/**”表示
        	通过mvc:exclude-mapping设置不起作用的路径
<!--        <mvc:interceptor>-->
<!--            <mvc:mapping path="/**"/>-->
<!--            <mvc:exclude-mapping path="/"/>-->
<!--            <bean class="com.yellowstar.mvc.interceptors.FirstInterceptor"></bean>-->
<!--        </mvc:interceptor>-->
    </mvc:interceptors>

多个拦截器的执行顺序

拦截器的执行顺序取决于在xml文件中配置的先后顺序,进行如下配置,来看一下结果

    <mvc:interceptors>
        <ref bean="firstInterceptor"></ref>
        <ref bean="secondInterceptor"></ref>
    </mvc:interceptors>
以下是多个拦截器全部放行的例子
通过观察可以发现,在执行preHandle时,写在前面的拦截器会先执行
FirstInterceptor---->preHandle
SecondInterceptor---->preHandle
在执行postHandle、afterCompletion时,写在后面的拦截器会先执行
SecondInterceptor---->postHandle
FirstInterceptor---->postHandle
SecondInterceptor---->afterCompletion
FirstInterceptor---->afterCompletion

看一下源码

在这里插入图片描述

通过观察dispatchServlet的doDispatch可以发现,preHandle是在控制器方法执行之前执行的,而mappedHandler是一个集合,集合中包含控制器对象,一个拦截器的集合,而SpringMVC其实是自带一个拦截器,都是放在集合的末尾,最后还有一个下标

在这里插入图片描述

看一下applyPreHandle方法,他是一个正序的循环方式,所以最先执行的应该是First过滤器,并且这里要注意的是interceptorIndex,他会在方法的最后执行interceptorIndex=i的操作

在这里插入图片描述

如果所有拦截器都放行,程序才会开始执行controller方法,执行完毕后执行applyPostHandle,不难看出applyPostHandle执行的先后顺序是倒序,所以second拦截器会最先执行

在这里插入图片描述

最后才会执行triggerAfterCompletion拦截器,这里与前两个不一样的是,for循环的起点是interceptorIndex的值,也是倒叙的形式

在这里插入图片描述

在这里插入图片描述

第二种情况:多个拦截器中有一个返回值为false,执行结果如下
FirstInterceptor---->preHandle
SecondInterceptor---->preHandle
FirstInterceptor---->afterCompletion

总结

当有多个拦截器且多个拦截器都放行时,在执行preHandle时,写在前面的拦截器会先执行,在执行postHandle、afterCompletion时,写在后面的拦截器会先执行

当有多个拦截器但某个拦截器被拦截时,在执行preHandle时,会执行到被拦截的拦截器,但并不会执行postHandle,在执行afterCompletion时,会从被拦截的拦截器前一个拦截器开始,倒序执行


SpringMVC异常处理

controller控制器中出现异常时,SpringMVC会对其进行异常处理,用来返回一个比较友好的页面

SpringMVC有提供默认的异常处理器,如果我们需要返回一个较为友好的页面,需要配置异常处理器

在这里插入图片描述

基于配置文件进行异常处理

在SpringMVC.xml配置文件中配置异常处理

    <!--配置异常处理器-->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!--配置异常信息-->
        <property name="exceptionMappings">
            <props>
                <!--
                    key:可能出现异常的全类名
                    值:出现异常返回的视图名称
                -->
                <prop key="java.lang.ArithmeticException">error</prop>
            </props>
        </property>
        <!--出现异常,将异常值放入请求域中,给值配健-->
        <property name="exceptionAttribute" value="ex"></property>
    </bean>

基于注解方式进行异常处理

@ControllerAdvice
public class ReplaceExceptionController {
    //此注解的值为异常类的数组,可以添加多个可能出现的异常
    @ExceptionHandler({ArithmeticException.class,NullPointerException.class})
    //其中形参的Exception的值为抛出的异常,相当于上述的<prop key="java.lang.ArithmeticException">error</prop>
    public String toErrorPage(Exception ex, Model model){
        model.addAttribute("ex",ex);
        return "error";
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值