SpringMVC攔截器與異常處理


 

點擊查看上一章

在我們SpringMVC中也可以使用攔截器對用戶的請求進行攔截,用戶可以自定義攔截器來實現特定的功能。自定義攔截器必須要實現HandlerInterceptor接口

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中配置攔截器。

<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/*后面的請求它才會被我們的攔截器給攔截。

在我們攔截器中執行順序:首先調用preHandler方法然后進入請求的業務方法之后出來的時候會先調用postHandler這個方法(業務方法前,視圖渲染后),最后視圖渲染之后調用攔截器的afterCompletion方法。

如果我們有多個攔截器那么他會按照配置順序執行preHandler,按逆方向執行postHandler與afterCompletion方法。

假如我們有兩個攔截器,在第一個攔截器的preHandler中返回false那么所有的方法都不會執行,如果我們在第二個攔截器返回false第一個攔截器還會多執行一個afterCompletion方法。

SpringMVC異常處理

在SpringMVC中異常的處理與Struts2有點類似。

SpringMVC通過HandlerExceptionResolver處理程序異常,包括Handler映射,數據綁定以及目標方法執行時所發生的異常。

SpringMVC中默認是沒有加裝載HandlerExceptionResolver,我們需要在SpringMVC.xml中配置

<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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM