SpringMVC拦截器与异常处理

在咱们SpringMVC中也可使用拦截器对用户的请求进行拦截,用户能够自定义拦截器来实现特定的功能。自定义拦截器必需要实现HandlerInterceptor接口java

复制代码
package com.spring.mvc.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author:SimpleWu
 * @to:拦截器执行流程:preHandle - 目标方法 - postHandle -渲染视图 - afterCompletion
 */
public class MyInterceptor implements HandlerInterceptor{
    
    /**
     * 渲染视图以后被调用
     * 释放资源
     */
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        System.out.println("[MyInterceptor] afterCompletion");
    }
    /**
     * 该方法是在目标方法以后,渲染视图以前被调用
     * 能够对请求域中的参数或视图作出修改
     */
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {
        System.out.println("[MyInterceptor] postHandle");
    }
    /**
     * 该方法在目标方法前调用
     * 1)若是返回值为true则继续调用后续的拦截器和目标方法
     * 2)若是返回值为false则不会调用后续的拦截器和目标方法
     * 能够考虑作权限,日志。
     */
    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
        System.out.println("[MyInterceptor] preHandle : 目标方法以前被调用。");
        return true;
    }

}
复制代码

而后咱们须要在SpringMVC中配置拦截器。web

复制代码
<mvc:interceptors>
        <!-- 配置自定义拦截器 -->
        <bean id="myInterceptor" class="com.spring.mvc.interceptor.MyInterceptor"/>
        <mvc:interceptor>
            <!-- 配置拦截器的做用路径 -->
            <mvc:mapping path="/user/*"/>
            <!-- 
                配置拦截器不做用的路径
                <mvc:exclude-mapping path=""/>
             -->
            <bean class="com.spring.mvc.interceptor.UserInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
复制代码

若是咱们配置了做用的路径那么咱们如今只有user/*后面的请求它才会被咱们的拦截器给拦截。spring

在咱们拦截器中执行顺序:首先调用preHandler方法而后进入请求的业务方法以后出来的时候会先调用postHandler这个方法(业务方法前,视图渲染后),最后视图渲染以后调用拦截器的afterCompletion方法。mvc

若是咱们有多个拦截器那么他会按照配置顺序执行preHandler,按逆方向执行postHandler与agterCompletion方法。app

假如咱们有两个拦截器,在第一个拦截器的preHandler中返回false那么全部的方法都不会执行,若是咱们在第二个拦截器返回false第一个拦截器还会多执行一个afterCompletion方法。jsp

SpringMVC异常处理ide

在SpringMVC中异常的处理与Struts2有点相似。post

SpringMVC经过HandlerExceptionResolver处理程序异常,包括Handler映射,数据绑定以及目标方法执行时所发生的异常。网站

SpringMVC中默认是没有加装载HandlerExceptionResolver,咱们须要在SpringMVC.xml中配置spa

<mvc:annotation-driven />

咱们能够在Controller类中定义一个局部(方法所在类)的异常处理的方法

复制代码
/**
     *    在这个方法中能够加入Exception类型的参数,该参数即对于发生的异常对象
     *    入参中不能传入map,若但愿吧异常信息传到页面上须要使用ModelAndView做为返回值 
     */
    @ExceptionHandler({NullPointerException.class})
    public String handlerNullPointerException(Exception ex){
        System.out.println("异常 : " + ex);
        return "error";
    }
复制代码

这个方法他会针对这个类中的NullPointerException异常将他捕获,而后执行这个方法。若是咱们但愿在页面上显示异常信息的话咱们只须要返回ModelAndView便可。

除了这种局部异常咱们还能够配置全局异常处理类,这个类须要使用注解@ControllerAdvice修饰。

复制代码
package com.spring.mvc.exceptionprocess;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author SimpleWu
 * @ControllerAdvice:若是在当前Handler找不到当前方法出现的异常则未来这个注解标记的类中查找处理异常。
 * 意为定义一个全局异常
 */
@ControllerAdvice
public class UserException {
    
    @ExceptionHandler({NullPointerException.class})
    public ModelAndView handlerNullPointerException(Exception ex){
        System.out.println("[异常] : " + ex);
        ModelAndView mav = new ModelAndView("error");
        mav.addObject("exception",ex);
        return mav;
    }
}
复制代码

固然在开发咱们可能在上面的类中有两个方法例如一个是RuntimeException和NullPointerException那么他会调用那个捕获方法呢?

它不会应为RuntimeException能够匹配就匹配这个他会根据最靠近这个异常的类型去匹配。

定制异常页面

在网站中若是咱们发生页面不存在咱们可以看到页面显示:

在这里咱们能够自定义异常显示。咱们能够定义一个异常类使用@ResponseStatus注解修饰

复制代码
package com.spring.mvc.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

/**
 * @author SimpleWu
 * 当捕获当这个异常后更改错误提示
 */
@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="用户密码为空")
public class UserPassIsNullException extends RuntimeException{
    private static final long serialVersionUID = 1L;
}
复制代码

在这里咱们定义了一个异常,若是在请求的方法中抛出咱们的异常,页面就会显示咱们定制的状态码与提示信息。

SimpleMappingExceptionResolver:

若是但愿对异常进行统一处理咱们能够装配这个bean,将它的异常类名映射为视图名,发生异常时使用对应视图报告异常

复制代码
<!-- 
        配置SimpleMappingExceptionResolverl来映射异常
        至关于捕获一个全局异常
     -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        
        <!-- 自定义异常属性名字 -->
        <property name="exceptionAttribute" value="ex"/>
        <property name="exceptionMappings">
            <props>
                <!-- 捕获到java.lang.ArithmeticException异常跳转error.jsp页面 -->
                <prop key="java.lang.ArithmeticException">error</prop>
            </props>
        </property>
    </bean>
复制代码

若是咱们捕获到这个算数异常那么咱们就会返回error视图。本该在jsp中咱们的页面上显示异常默认使用exception如今名字换成了ex

相关文章
相关标签/搜索