Spring MVC使用篇(十二)—— 異常處理
1、綜述
在Web專案正式上線或者執行時,往往會出現一些不可預料的異常資訊。對於邏輯性或設計性問題,開發人員或者維護人員需要通過日誌,檢視異常資訊並排除異常;而對於使用者,則需要為其呈現出其可以理解的異常提示頁面,讓使用者有一個良好的使用體驗。所以異常的處理對於一個Web專案來說是非常重要的。Spring MVC提供了強大的異常處理機制。
2、全域性異常處理器
系統中的異常一般分為兩大類:預期異常和執行時異常。對於前者一般通過捕獲異常來獲取異常資訊,而後者主要通過規範程式碼的開發、測試,通過一些技術手段來減少執行時異常的發生。
在Spring MVC中,提供了一個全域性異常處理器,用於對系統中出現的異常進行統一處理。在一般的系統中,DAO、Service及Controller層出現的異常都以“throws Exception”的形式向上層丟擲,最後都會由Spring MVC的前端控制器(DispatcherServlet)統一交由全域性異常處理器進行異常處理。
當系統遇到異常時,不同層的異常會拋向上一級,並最終拋向Spring MVC的全域性異常處理器。該全域性處理器要實現的主要功能是:第一,解析出異常資訊,判斷異常屬於哪種異常類;第二,如果該異常型別是系統自定義的異常,直接取出異常資訊,並在錯誤頁面展示。如果該異常型別不是系統自定義的異常,構造一個自定義的異常型別,資訊為“未知錯誤”;第三,構建異常資訊展示檢視資訊,將異常資訊繫結到異常介面的Model域中,然後跳轉到相關的異常資訊顯示頁面。
2.1 SimpleMappingExceptionResolver異常處理器
SimpleMappingExceptionResolver異常處理器是系統定義好的異常處理器。該方式只需要在Spring MVC的核心配置檔案springmvc.xml中註冊該異常處理器Bean即可。該Bean比較特殊,沒有id屬性,無需顯示呼叫或被注入給其它Bean,當異常發生時會自動執行該類。
現在利用SimpleMappingExceptionResolver異常處理器處理系統預設異常的情況。
首先,在“com.ccff.controller”下建立名為“ExceptionController”的控制器,具體程式碼如下:
package com.ccff.controller;
import com.ccff.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/ExceptionTest")
public class ExceptionController {
@RequestMapping("/login")
public String login(){
return "exception/login";
}
@RequestMapping("/doLogin")
public String doLogin(User user){
if ("".equals(user.getUsername()) || "".equals(user.getPassword())){
throw new NullPointerException("空指標異常");
}
return "exception/success";
}
}
由上面的程式碼可以看出,login方法用於顯示登入頁面,而使用者輸入資訊後將表單提交到doLogin方法處理。而在doLogin方法中,如果使用者輸入的使用者名稱或者密碼為空時,將會直接丟擲NullPointerException(空指標異常)。注意:這裡僅僅是 為了演示對於系統自帶的異常的處理,並不完全符合業務邏輯。
接著,在springmvc.xml配置檔案中配置異常處理器,將如下程式碼加入到配置檔案中即可:
<!--配置異常處理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.NullPointerException">exception/nullError</prop>
</props>
</property>
<property name="defaultErrorView" value="exception/error" />
<property name="exceptionAttribute" value="ex" />
</bean>
由上面的程式碼可以看出,在springmvc.xml配置檔案中配置了SimpleMappingExceptionResolver異常處理器Bean,同時為其配置了以下三個屬性:
exceptionMappings:properties型別屬性,用於指定具體的不同型別的異常所對應的異常響應頁面。key為異常類的全限定性類名,value則為響應頁面路徑。(注意:由於之前配置過了InternalResourceViewResolver檢視解析器,同時配置了字首和字尾,這裡仍然是直接使用拼接形成最後路徑的方式)
defaultErrorView:指定預設的異常響應頁面。若發生的異常不是exceptionMappings中指定的異常,則使用預設異常響應頁面。
exceptionAttribute:捕獲到的異常物件。一般異常響應頁面中使用。
然後,在WEB-INF/jsp路徑下建立名為“exception”的資料夾用來存放和異常處理相關的JSP檔案。
登入頁面login.jsp程式碼如下所示:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>使用者登入</title>
</head>
<body>
<h3>使用者登入</h3>
<form action="doLogin.action" method="post">
<table width="300px;" border=1>
<tr>
<td>使用者編號:</td>
<td><input type="text" name="userId" id="userId" /></td>
</tr>
<tr>
<td>使用者名稱:</td>
<td><input type="text" name="username" id="username" /></td>
</tr>
<tr>
<td>密 碼:</td>
<td><input type="password" name="password" id="password" /></td>
</tr>
</table>
<br/>
<input type="submit" id="login_button" value="使用者登入" />
</form>
</body>
</html>
空資訊異常頁面nullError.jsp程式碼如下所示:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>NULL ERROR</title>
</head>
<body>
Null Error page<br>
<hr>
${ex.message }<br>
</body>
</html>
預設異常資訊頁面error.jsp程式碼如下所示:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>ERROR</title>
</head>
<body>
Error page<br>
<hr>
${ex.message }<br>
</body>
</html>
登入成功頁面success.jsp程式碼如下所示:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登入成功</title>
</head>
<body>
<h2>登入成功!</br></br>歡迎您${user.username}!</h2>
<hr/>
<h3>使用user引數顯示使用者註冊資訊</h3>
<table width="300px;" border=1>
<tr>
<td>使用者編號:</td>
<td>${user.userId}</td>
</tr>
<tr>
<td>使用者名稱:</td>
<td>${user.username}</td>
</tr>
<tr>
<td>密 碼:</td>
<td>${user.password}</td>
</tr>
</table>
</body>
</html>
最後,將專案部署到Tomcat上後,在瀏覽器內輸入請求URL:http://localhost:8080/demo/ExceptionTest/login.action 後向使用者顯示登入頁面,如下所示:
根據前面在Controller中的doLogin方法的登入處理邏輯,當用戶名或者密碼為空時,將會出現空指標異常,並根據在配置檔案中配置的異常頁面,將顯示nullError.jsp頁面的內容。
因此在登入頁面中僅輸入使用者編號後提交表單,則向用戶顯示結果如下:
2.2 自定義異常處理器
使用Spring MVC定義好的SimpleMappingExceptionResolver異常處理器,可以實現發生指定異常後的跳轉。但若要實現在捕獲到指定異常時,執行一些操作的目的,它是完成不了的。此時,就需要自定義異常處理器。
第一,在“com.ccff.exception”下建立名為“PasswordLengthException”的自定義異常,具體程式碼如下:
package com.ccff.exception;
public class PasswordLengthException extends Exception {
//異常資訊
private String message;
public PasswordLengthException(String message) {
super(message);
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
自定義異常類繼承了Exception父類。Exception類為java.lang.Throwable的子類,用於描述程式能夠捕獲的異常。在PasswordLengthException中設定了一個成員變數message,專門用來存放異常資訊。當需要丟擲PasswordLengthException型別的異常時,通過其構造方法就可以設定其異常資訊,後期在全域性異常處理器中,可以通過PasswordLengthException類的getMessage方法來獲取相關的異常資訊。
第二,自定義全域性異常處理器,即該核心異常處理器專門用於處理系統中所有關於PasswordLengthException的異常。在“com.ccff.exception”下建立名為“PasswordLengthExceptionResolver”的異常處理器。具體程式碼如下:
package com.ccff.exception;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class PasswordLengthExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
//1、解析出異常型別
PasswordLengthException passwordLengthException = null;
if (e instanceof PasswordLengthException){
//2、如果該異常型別是自定義的PasswordLengthException異常,直接取出異常資訊,在錯誤頁面顯示
passwordLengthException = (PasswordLengthException) e;
}else {
//3、如果該異常型別不是自定義的PasswordLengthException異常,構造一個自定義的異常型別(資訊為“未知錯誤”)
passwordLengthException = new PasswordLengthException("未知錯誤");
}
//錯誤資訊
String message = passwordLengthException.getMessage();
ModelAndView modelAndView = new ModelAndView();
//將錯誤資訊傳到頁面
modelAndView.addObject("message",message);
//指向到錯誤頁面
modelAndView.setViewName("/exception/passwordLengthError");
return modelAndView;
}
}
這裡需要注意的是:全域性異常處理器要實現Spring MVC提供的HandlerExceptionResolver介面。 從上面的程式碼中可以看到,HandlerExceptionResolver介面中定義了一個名為resolveException的方法,該方法主要用於處理Controller中的異常。引數“Exception e”即為Controller或其下層丟擲的異常。引數“Object o”就是處理器介面卡要執行的Handler物件。resolveException方法的返回值型別是ModelAndView,也就是說,可以通過這個返回值類設定發出異常時顯示的頁面。
第三,需要在WEB-INF/jsp/exception下建立一個名為“passwordLengthError.jsp”的頁面來顯示當密碼長度不符合要求時的需要顯示異常的頁面,具體程式碼如下:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>PASSWORD LENGTH ERROR</title>
</head>
<body>
Password Length Error page<br>
<hr>
${message }<br>
</body>
</html>
第四,修改控制器中的doLogin方法,具體程式碼如下:
package com.ccff.controller;
import com.ccff.exception.PasswordLengthException;
import com.ccff.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/ExceptionTest")
public class ExceptionController {
@RequestMapping("/login")
public String login(){
return "exception/login";
}
@RequestMapping("/doLogin")
public String doLogin(User user) throws PasswordLengthException {
if ("".equals(user.getUsername()) || "".equals(user.getPassword())){
throw new NullPointerException("空指標異常");
}else if (user.getPassword().length()<6 || user.getPassword().length()>12){
throw new PasswordLengthException("密碼長度異常");
}
return "exception/success";
}
}
第五,在Spring MVC的核心配置檔案springmvc.xml中將自定義的全域性異常處理器配置進去,具體配置如下:
<!--配置自定義異常處理器-->
<bean class="com.ccff.exception.PasswordLengthExceptionResolver" />
這裡雖然只添加了一個bean的載入配置,但是隻要該Bean對應的類實現了HandlerExceptionResolver介面,這個類就會被Spring MVC作為一個全域性異常處理器。
最後將專案部署到Tomcat上後,在瀏覽器內輸入請求URL:http://localhost:8080/demo/ExceptionTest/login.action 後,為了測試自定義的密碼長度異常,在登入表單中輸入3位的密碼,如下所示:
當表單提交後,在控制器的doLogin方法中會捕獲到密碼長度異常,並最終交由全域性異常處理器處理該異常,顯示結果如下:
2.3 異常處理註解
使用註解@ExceptionHandler可以將一個方法指定為異常處理方法。該註解只有一個可選屬性value,為一個class<?>陣列,用於指定該註解的方法所要處理的異常類,即所要匹配的異常。
&emsp 而被註解的方法,其返回值可以是ModelAndView、String或void,方法名隨意,方法引數可以是Exception及其子類物件、HttpServletRequest、HttpServletResponse等。系統會自動為這些方法引數賦值。
對於異常處理註解的用法,也可以直接將異常處理方法註解於Controller之中。不過一般不這樣使用,而是將異常處理方法專門定義在一個Controller中,讓其他Controller繼承該Controller即可。但是,這種用法的弊端也很明顯:Java是“單繼承多實現”的,這個Controller的繼承將這唯一的一個繼承機會使用了,使得若再有其他類需要繼承,將無法直接實現。
在這一節的演示專案中,我們使用異常處理註解的方法對使用者編號的驗證進行異常處理。驗證使用者登入時輸入的使用者編號是否大於0。
第一步,在“com.ccff.exception”下建立名為“UserIdBigZeroException”的自定義異常,具體程式碼如下:
package com.ccff.exception;
public class UserIdBigZeroException extends Exception {
//異常資訊
private String message;
public UserIdBigZeroException(String message) {
super(message);
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
第二步,在“com.ccff.exception”下建立名為“MyExceptionResolverController”的控制器,即定義異常處理的的Controller,具體程式碼如下:
package com.ccff.controller;
import com.ccff.exception.UserIdBigZeroException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class MyExceptionResolverController {
//用於處理使用者編號異常的方法
@ExceptionHandler(UserIdBigZeroException.class)
public ModelAndView handleUserIdBigZeroException(Exception ex){
ModelAndView modelAndView = new ModelAndView();
String message = ((UserIdBigZeroException)ex).getMessage();
modelAndView.addObject("message",message);
modelAndView.setViewName("/exception/userIdBigZeroError");
return modelAndView;
}
}
第三步,修改ExceptionController,讓其繼承自異常處理Controller,同時在ExceptionController中的doLogin方法中捕獲使用者編號大於0異常資訊,具體程式碼如下:
package com.ccff.controller;
import com.ccff.exception.PasswordLengthException;
import com.ccff.exception.UserIdBigZeroException;
import com.ccff.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/ExceptionTest")
public class ExceptionController extends MyExceptionResolverController {
@RequestMapping("/login")
public String login(){
return "exception/login";
}
@RequestMapping("/doLogin")
public String doLogin(User user) throws PasswordLengthException, UserIdBigZeroException {
if ((Integer)user.getUserId() instanceof Integer && user.getUserId()<=0){
throw new UserIdBigZeroException("使用者編號必須大於0");
}
if ("".equals(user.getUsername()) || "".equals(user.getPassword())){
相關推薦
Spring MVC使用篇(十二)—— 異常處理
1、綜述
在Web專案正式上線或者執行時,往往會出現一些不可預料的異常資訊。對於邏輯性或設計性問題,開發人員或者維護人員需要通過日誌,檢視異常資訊並排除異常;而對於使用者,則需要為其呈現出其可以理解的異常提示頁面,讓使用者有一個良好的使用體驗。所以異常的處
Python入門(十二)異常處理
Python 異常處理
python提供了兩個非常重要的功能來處理python程式在執行中出現的異常和錯誤。你可以使用該功能來除錯python程式。
異常處理: 本站Python教程會具體介紹。
斷言(Assertions):本站Python教程會具體介紹。
python的學習(十二)----異常處理(3)
異常處理(3)
一、異常基礎
try/except:捕捉由程式碼中的異常並恢復,匹配except裡面的錯誤,並自行except中定義的程式碼,後繼續執行程式(發生異常後,由except捕捉到異常後,不會中斷程式,繼續執行try語句後面的程式)
try/finally: 無論異常是否發生,都執行清理行為 (發
Spring Boot教程(十二)整合elk(1)
分享圖片 operation you 運行 hot href iba for 分享 elk 簡介
Elasticsearch是個開源分布式搜索引擎,它的特點有:分布式,零配置,自動發現,索引自動分片,索引副本機制,restful風格接口,多數據源,自動搜索負載等。
Spring原始碼解析(十二)——AOP原理——@EnableAspectJAutoProxy
一、@EnableAspectJAutoProxy
第一步:註冊AnnotationAwareAspectJAutoProxyCreator
把AnnotationAwareAspectJAutoProxyCreator建立為RootBeanDefinition,加入
linux基礎篇(十二):Redhat7系統中rpm的相關操作與第三方軟體庫的搭建與共享
RPM
RPM是Red-Hat Package Manager(RPM軟體包管理器)的縮寫,這一檔案格式名稱雖然打上了RedHat的標誌,但是其原始設計理念是開放式的,現在包括OpenLinux、S.u.S.E.以及Turbo Linux等Linux的分發版本都
Linux 網路協議棧開發基礎篇(十二)—— 使用wireshark分析TCP/IP協議中TCP包頭的格式
摘要:
本文簡單介紹了TCP面向連線理論知識,詳細講述了TCP報文各個欄位含義,並從Wireshark俘獲分組中選取TCP連線建立相關報文段進行分析。
一、概述
TCP是面向連線的可靠傳輸協議,兩個程序互發資料之前需要建立連線,這裡的連線只不過是端系統中分配的一些快
Spring Boot:(十二)Spring Boot使用單元測試
前言這次來介紹下Spring Boot中對單元測試的整合使用,本篇會通過以下4點來介紹,基本滿足日常需求Service層單元測試Controller層單元測試新斷言assertThat使用單元測試的回滾正文Spring Boot中引入單元測試很簡單,依賴如下:1
2
3
4
Spring Boot 入門(十二):報表匯出,對比poi、jxl和esayExcel的效率
本片部落格是緊接著Spring Boot 入門(十一):整合 WebSocket, 實時顯示系統日誌寫的
關於poi、jxl和esayExcel的介紹自行百度。
jxl最多支援03版excel,所以單個sheet頁面最多隻能匯出65536條資料。
我直接將excel匯入到瀏覽器並開啟,以下統計匯出時長指將資
spring-boot-route(十二)整合redis做為快取
## redis簡介
redis作為一種非關係型資料庫,讀寫非常快,應用十分廣泛,它採用key-value的形式儲存資料,value常用的五大資料型別有string(字串),list(連結串列),set(集合),zset(有序集合)和hash(雜湊表)。
redis的特性決定了它的功能,它可以用來做以下這
python學習筆記(十五)異常處理
關鍵字 .exe strip support 異常 解析器 輸入 rod () python解析器去執行程序,檢測到了一個錯誤時,觸發異常,異常觸發後且沒被處理的情況下,程序就在當前異常處終止,後面的代碼不會運行,所以你必須提供一種異常處理機制來增強你程序的健壯性與容錯性
C++語言學習(十八)——異常處理
right data ges cal 修飾符 當前 ins 最終 cati C++語言學習(十八)——異常處理
一、C語言異常處理
異常是指程序在運行過程中產生可預料的執行分支。如除0操作,數組訪問越界、要打開的文件不存在。Bug是指程序中的錯誤,是不被預期的運行方式。如野
分享知識-快樂自己:Spring中的(三種)異常處理機制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSch
(十二)springMvc 處理圖片,視訊等檔案的上傳
導包
需要匯入如下的包
commons-fileupload-1.3.3.jar
commons-io-2.6.jar
修改表單型別
想要上傳圖片、文字、電影、音樂等資源的時候,需要將 form 的
EMV規範學習與研究(十二)——指令碼處理
指令碼處理目的是髮卡行可以提供命令指令碼讓終端傳送給IC卡,這些命令執行的功能對當前交易沒有影響,但是對確保IC卡中後續的正常執行非常重要。在一個授權應答中又可能包括多個指令碼,每個指令碼包括多個髮卡行指令碼命令。
終端可能不能理解某個髮卡行指令碼命令,但是終端需要把每個指
Spring.NET教程(十九)整合NHibernate和ASP.NET MVC(基礎篇)
contains sar occurs false port company param soft stat 今天帶給大家的就是期待以久的ASP.net MVC與Spring.NET和NHibernate的組合,視圖打造.NET版的SSH(Spring-Struts-Hib
spring cloud微服務快速教程之(十二) 分散式ID解決方案(mybatis-plus篇)
0-前言
分散式系統中,分散式ID是個必須解決的問題點;
雪花演算法是個好方式,不過不能直接使用,因為如果直接使用的話,需要配置每個例項workerId和datacenterId,在微服務中,例項一般動態配置,直接指定具體例項的這兩個引數是不現實的;
所以,一般採用雪花演算法的變種,主要是將這兩個
學習MVC之租房網站(十二)-緩存和靜態頁面
.html 控制臺 ron 在線教育 適合 取代 system caching 租房網站 在上一篇<學習MVC之租房網站(十一)-定時任務和雲存儲>學習了Quartz的使用、發郵件,並將通過UEditor上傳的圖片保存到雲存儲。在項目的最後,再學習優化網站性能的
CoreThink開發(十二)更改默認出錯異常頁防止暴露敏感數據
highlight true pos pub light brush 關閉 sql exception 默認的異常頁會打印文件位置,而且是絕對路徑,會打印SQL語句,真實上線一定不要用這個默認的,而且關閉trace關閉調試模式也不行。
針對CoreThink1.2 Th
SpringMVC(十二)自定義異常處理器 HandlerExceptionResolver(接口)
pin org ota admin pack property framework ase exception 自定義異常處理器和系統異常處理器的提升版可以實現相同的功能,但是使用的方法不同,自定義異常處理器可以不用在配置文件中配置name多東西,只需要一個異常處理器就可以