在使用Spring MVC進行開發時,老是要對系統異常和用戶的異常行爲進行處理,以提供給用戶友好的提示,也能夠提升系統的安全性。css
攔截系統響應錯誤html
首先是攔截系統響應錯誤,這個能夠在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>
使用攔截器進行權限校檢java
在配置web.xml時,能夠配置DispatcherServlet的處理解析路徑。web
<!-- 配置前端控制器 --> <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> <!-- 一、.action訪問以.action結尾的 由DispatcherServlet進行解析 二、/,全部訪問都由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就找不到,形成全部的靜態資源都訪問不了。這個問題有兩種解決辦法:spring
1.在web.xml中配置servlet來映射靜態資源。apache
<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中配置靜態資源文件映射session
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權限管理和異常處理的簡單示例,若是要深刻使用或者要理解其原理仍是參考官方文檔以及源碼。
轉載請指明來源。
若有錯誤,敬請指正。