Spring MVC全局異常處理與攔截器校檢


在使用Spring MVC進行開發時,總是要對系統異常和用戶的異常行為進行處理,以提供給用戶友好的提示,也可以提高系統的安全性。

攔截系統響應錯誤

首先是攔截系統響應錯誤,這個可以在web.xml中配置,根據錯誤代碼跳轉到相應的提示頁面。這里要注意一個問題,錯誤處理頁面所用到的靜態資源最好是直接寫在頁面中,或者同一個文件夾下,因為如果用戶訪問了一個系統不存在的路徑,例如:**/ss/kk/ll/tt.jsp這樣就會有404錯誤就會跳轉到相應的處理頁面,但是這個處理頁面中的靜態資源的路徑就會變成**/ss/kk/ll/*.js這種,就會造成靜態資源不可以使用。

<!-- 404錯誤攔截 -->
  <error-page>
    <error-code>404</error-code>
    <location>/error404.jsp</location>
  </error-page>
  <!-- 500錯誤攔截 -->
  <error-page>
    <error-code>500</error-code>
    <location>/error500.jsp</location>
  </error-page>

 

使用攔截器進行權限校檢

在配置web.xml時,可以配置DispatcherServlet的處理解析路徑。

<!-- 配置前端控制器 -->
  <servlet>
      <servlet-name>spring</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
          <!-- ContextconfigLocation配置springmvc加載的配置文件
          適配器、處理映射器等
           -->
          <param-name>contextConfigLocation</param-name>
          <param-value>WEB-INF/classes/spring/springmvc.xml</param-value>
  </init-param>
  </servlet>
  <servlet-mapping>
      <servlet-name>spring</servlet-name>
      <!-- 1、.action訪問以.action結尾的  由DispatcherServlet進行解析
           2、/,所有訪問都由DispatcherServlet進行解析
       -->
      <url-pattern>/</url-pattern>
  </servlet-mapping>

 

這里需要特別注意的是如果只攔截像以.action結尾URL,可以通過Spring MVC的攔截器來攔截並對不同權限的用戶做出不同的響應,但是對靜態頁面.html,.jsp這種權限的校檢就沒有太好的辦法了。可以在每個JSP頁面中都檢測一次session,這樣一來在寫JSP頁面的時候就會很麻煩,還有可能用戶的權限不夠某些值為null,JSP的編譯都要報錯。但這種做法有一個優點就是不用操心靜態資源的訪問。還有一種就是想上面的配置一樣攔截所有的URL,這樣的話所有的RUL都會交給DispatcherServlet來分發,上面提到的JSP、html頁面的權限校檢的問題就可以解決了,完全可以通過攔截器來處理,但是也帶來了新的問題。如果不對js,css和圖片這種靜態資源進行映射的話,DispatcherServlet就找不到,造成所有的靜態資源都訪問不了。這個問題有兩種解決辦法:

1.在web.xml中配置servlet來映射靜態資源。

<servlet-mapping>  
    <servlet-name>default</servlet-name>  
    <url-pattern>/js/*</url-pattern>  
    <url-pattern>/css/*</url-pattern>  
    <url-pattern>/images/*</url-pattern>  
</servlet-mapping>

這個配置最好放在DispatcherServlet之前,在DispatcherServlet處理之前映射。這里使用的是Tomcat提供的default Servlet,其他應用服務器可能有所不同。

還需要在springmvc.xml配置文件中配置默認的靜態資源文件處理器

<mvc:default-servlet-handler />

2.在springmvc.xml中配置靜態資源文件映射

springmvc.xml是在配置DispatcherServlet時配置的映射文件。也就是默認的[name]-servlet.xml文件。

<mvc:resources mapping="/images/**" location="/images/" />
<mvc:resources mapping="/css/**" location="/css/" />  
<mvc:resources mapping="/js/**" location="/js/" />
<mvc:resources mapping="/imgdata/**" location="/imgdata/" />

這樣一來DispatcherServlet在分發請求時就可以找到對應的靜態資源文件了。這里還需要注意一個問題,在配置攔截器的時候務必要把這些文件過濾掉,不然還是無法使用。

通過以上的配置,靜態資源的訪問、系統異常的響應都沒有問題了。可以使用攔截器進行權限的校檢與管理了。

在springmvc.xml文件中配置攔截器:

攔截器直接定義就可以攔截所有的請求,但是這樣還會造成靜態資源被攔截。除非在實現攔截器的時候手動排除。

<!-- 定義攔截器 -->
    <mvc:interceptors>
    <!-- 直接定義攔截所有請求 -->
    <bean class="com.wxisme.ssm.interceptor.IdentityInterceptor"></bean>
    </mvc:interceptors>

也可以自定義攔截路徑

<!-- 定義攔截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
        <mvc:mapping path="/*.action" />
        <mvc:mapping path="/*.jsp" />
        <mvc:mapping path="/*.html" />
        <mvc:mapping path="/*.htm" />
        <mvc:exclude-mapping path="/login.jsp"/>
        <mvc:exclude-mapping path="/register.jsp"/>
        <mvc:exclude-mapping path="/about.jsp"/>
        <bean class="com.course.interceptor.IdentityInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

 

這樣就可以過濾掉靜態資源。

攔截器的編寫:

自定義攔截器要實現HandlerInterceptor接口。HandlerInterceptor接口定義了三個方法:preHandle、postHandle、afterCompletion。

preHandle在請求被處理器處理之前調用,postHandle在請求被處理之后,視圖生成之間調用,afterCompletion在請求完全處理后調用。如果有多個攔截器,先按順序調用preHandle方法,然后逆序調用每個攔截器的postHandle和afterCompletion方法。

看一個簡單的用戶校檢的例子:

package com.course.interceptor;

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

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

/**
 *身份認證攔截器
 *@author 王旭
 *@time 2015-9-6 上午9:51:27
 */
public class IdentityInterceptor implements HandlerInterceptor {


    /**
     * 進行身份認證,在handler執行之前執行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
            Object obj) throws Exception {
        
        
        HttpSession session = request.getSession();
        String username = (String) session.getAttribute("username");
        
        //判斷是否為公開地址
        String url = request.getRequestURL().toString();
        if(url.contains("login.")) {
            return true;//是公開地址則放行
        }
        //判斷用戶是否登錄
        else if(username != null) {
            return true;
        }
        else {
            //不是公開地址則重定向到登錄頁面
            request.getRequestDispatcher("/login.jsp").forward(request, response);
            return false;
        }
        
        
        
    }
    
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2, ModelAndView arg3) throws Exception {
        
    }
    
    @Override
    public void afterCompletion(HttpServletRequest arg0,
            HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        
    }
    
}

注意如果前面配置的時候沒有過濾掉靜態資源可以在代碼里手動過濾。

定義全局異常處理器

在srpingmvc.xml中配置全局異常處理器

 

<!-- 只有一個全局異常處理器起作用 -->
    <bean id="exceptionResolver" class="com.wxisme.ssm.exception.OverallExceptionResolver"></bean>

 

 

 

編寫全局異常處理器:

先編寫一個自定義異常CustomException

package com.course.exception;

/**
 *自定義異常類型
 *@author 王旭
 *@time 2015-10-4 下午3:51:10
 */
public class CustomException extends Exception {
    
    private String message;
    
    public CustomException(){}
    
    public CustomException(String message) {
        super(message);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
    

}

 

編寫全局異常處理器,要實現HandlerExceptionResolver接口,並重寫resolveException方法。

package com.course.exception;

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

import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

/**
 *系統全局異常處理器
 *@author 王旭
 *@time 2015-10-4 下午3:38:41
 */
@Controller
public class OverallExceptionResolver implements HandlerExceptionResolver {
    
    
    /**
     * 進行全局異常的過濾和處理
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {
        //handler為當前處理器適配器執行的對象
        String message = null;
        //判斷是否為系統自定義異常。
        if(ex instanceof CustomException) {
            message = ((CustomException) ex).getMessage();
        }
        
        else {
            message = "系統出錯啦,稍后再試試!";
        }
        
        
        ModelAndView modelAndView = new ModelAndView();
        //跳轉到相應的處理頁面
        modelAndView.addObject("errorMsg", message);
        modelAndView.setViewName("error");
        
        return modelAndView;
    }
    

}

 

這樣在系統拋異常的時候就會自動過濾並給用戶進行相關友好的提示。

用到了log4j一塊說了吧,添加jar包,再加一個配置文件log4j.properties就OK了。

                                                     

配置文件如下:

# Global logging configuration
#在開發環境中設置成DEBUG,在生產環境中設置成info或者error
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

 

這樣就可以在控制台查看日志信息了。

 

以上只是關於Spring MVC權限管理和異常處理的簡單示例,如果要深入使用或者要理解其原理還是參考官方文檔以及源碼。

 

轉載請指明來源。

如有錯誤,敬請指正。

 


免責聲明!

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



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