亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring Validator接口校驗與全局異常處理器

 更新時間:2019年11月12日 10:33:04   作者:zzzjustin_z  
這篇文章主要介紹了Spring Validator接口校驗與全局異常處理器,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

Spring Validator接口校驗

上一篇日志使用Bean Validation校驗機制,對基本數(shù)據(jù)類型進行校驗,方法是在實體類屬性上使用注解標(biāo)識校驗方式,最后在Controller類中具體方法的形參里添加@Vlidated注解。Bean Validation校驗有一個缺點是,我們的數(shù)據(jù)校驗是在Java實體類里進行約束的,如果我們有多個處理器方法需要用到同一個實體類,那么定義在實體類屬性上的校驗規(guī)則就不好劃分了,有的處理器只需要校驗一個屬性,而有的處理器需要校驗多個屬性,我們不可能為每一個處理器都創(chuàng)建一個實體類。解決的方法在上一篇日志里也說到,使用分組校驗方式,除此之外,還可以使用Spring的Validator接口校驗,它允許我們在外部指定某一對象的校驗規(guī)則。

校驗器實現(xiàn)類

Spring的Validator是一個接口,我們自己的校驗實現(xiàn)類必須實現(xiàn)這個接口,才可以通過重寫方法完成自定義的校驗規(guī)則,需要我們實現(xiàn)的方法有兩個:supports()和validate()

public class UserValidator implements Validator {
	@Override
	public boolean supports(Class<?> clazz) {
		// 反射機制通過類的class靜態(tài)變量獲得該類的實例
		return User.class.equals(clazz);
	}
 
	@Override
	public void validate(Object obj, Errors errors) {
		// 錯誤信息放入errors對象
		ValidationUtils.rejectIfEmpty(errors, "username", "Username.is.empty", 
				"用戶名不允許為空。");
		User user = (User) obj;
		if (user.getPassword() == null || user.getPassword().equals("")) {
			// rejectValue()參數(shù):錯誤字段名,全局錯誤碼,默認錯誤提示信息
			errors.rejectValue("password", "Password.is.empty", "密碼不允許為空。");
		} else if (user.getPassword().length() < 8) {
			errors.rejectValue("password", "Length.too.short", "密碼長度不能小于八位。");
		}
	}
}

Support()方法的功能是判斷該校驗類,是否支持被校驗的實體類。例如我們這個校驗類負責(zé)對User類進行校驗,supports()方法傳入被校驗的實體類,通過反射機制獲得User類實例,然后判斷是否與傳入的被校驗實體類匹配。Validate()方法則是進行校驗的具體實現(xiàn)方法,方法參數(shù)列表中有一個Errors對象,負責(zé)往里面存放校驗的錯誤信息。下面就是具體的校驗規(guī)則了,我們可以使用ValidationUtils校驗工具類的方法進行校驗,提供的參數(shù)依次為存放錯誤信息對象error,校驗的字段名(對于校驗實體類中的屬性),全局錯誤碼(類似于Bean Validation校驗中根據(jù)錯誤碼,使用外部properties的錯誤提示信息),最后一個參數(shù)是默認錯誤提示信息,當(dāng)全局錯誤碼沒有找到對應(yīng)的提示信息時,使用默認的錯誤提示信息。

除了使用ValidationUtils校驗工具類外,第23行還也可以使用erroe對象的方法,設(shè)置獲取校驗錯誤信息,參數(shù)和ValidationUtils類的方法幾乎一致。

Controller實現(xiàn)類

校驗器類配置完后,在具體的業(yè)務(wù)邏輯處理部分,Controller類中使用。

@Controller
@RequestMapping("user")
public class InterfaceValidationController {
	@InitBinder
	public void initBinder(DataBinder binder) {
		// 為DataBinder對象設(shè)置Validator校驗接口
		binder.setValidator(new UserValidator());
	}
	
	@RequestMapping("login")
	public String login(Model model, @Valid User user, BindingResult result) {
		List<ObjectError> allErrors = null;
		if (result.hasErrors()) {
			allErrors = result.getAllErrors();
			// 輸出所有錯誤信息
			for(ObjectError objectError : allErrors) {
				System.out.println("code = " + objectError.getCode() + 
						"DefaultMessage = " + objectError.getDefaultMessage());
				// 將錯誤信息發(fā)送到前端頁面
				model.addAttribute("allErrors", allErrors);
			}
			
			// 最后返回視圖
			return "users/login";
		} else {
			// 如果校驗沒有錯誤,跳轉(zhuǎn)到成功登陸的頁面
			return "users/successLogin";
		}
	}

首先需要通過initBinder()方法,在Controller類方法中進行校驗器的綁定,方法需要DataBinder對象參數(shù),DataBinder對象的功能是進行數(shù)據(jù)綁定,可以將數(shù)據(jù)進行類型轉(zhuǎn)換,設(shè)置校驗器等。DataBinder有一個成員變量BindingResult,進行了數(shù)據(jù)綁定了校驗器綁定,當(dāng)校驗數(shù)據(jù)有錯誤信息時,就會將其放入到BindingResult對象中的Errors屬性中,Errors對象集合前面說到,就是用來存放錯誤信息的。在Controller具體方法的參數(shù)列表中對要校驗的數(shù)據(jù)對象User類添加@Valid注解,標(biāo)識對該對象進行數(shù)據(jù)校驗,接著添加BindingResult對象(這里有一點要注意,BindingResult參數(shù)位置必須緊跟在被校驗的數(shù)據(jù)對象后面),當(dāng)校驗出現(xiàn)錯誤信息時,第15行我們就可以通過該對象的hasErrors()方法判斷校驗是否出錯,然后使用getAllErrors()方法獲取錯誤信息進行輸出。最后第22行我們將錯誤信息傳到前端頁面上顯示,給用戶提示。

前端頁面測試

最后,在前端頁面進行簡單的登陸測試:

<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登錄界面</title>
</head>
<body>
	<from action="login.action" method="post">
		用戶名:<input type="text" name="username" /></br>
		密碼:  &nbsp;&nbsp;&nbsp;<input type="password" name="password" /></br>
		<input type="submit" value="登錄"/>
		<!-- 顯示校驗錯誤信息 -->
		<c:if test="${allErrors != null }">
			<c:forEach items="${allErrors}" var="error">
				</br><font color="red">${error.defaultMessage}</font>
			</c:forEach>
		</c:if>
	</from>
</body>
</html>

第15行遍歷后臺發(fā)來的allErrors錯誤信息集合,如果出現(xiàn)校驗出錯,則顯示錯誤信息。根據(jù)我們前面校驗器的配置,對于User類對象的數(shù)據(jù)校驗,用戶名和密碼都不允許為空:

當(dāng)輸入信息正確,用戶名和密碼都不為空,且密碼長度不低于8位,便可成功跳轉(zhuǎn):

全局異常處理器Exception Resolver

對于程序運行時的錯誤信息,我們可以通過查看日志來排查錯誤,當(dāng)我們把錯誤信息傳到前端頁面時,為了讓用戶能看懂錯誤原因,就需要對錯誤信息進行處理,在信息傳送到前端頁面前,將其捕獲。完成錯誤信息捕獲和加工處理,就需要配置我們的異常處理器。異常處理器用來自定義程序運行時如何解析異常,它需要自定義異常類,里面存儲了對應(yīng)異常的異常信息。還需要配置異常處理器,對于捕捉到的異常,如果是在自定義異常類中配置好的預(yù)期異常,則拋出相應(yīng)的錯誤信息,否則,就進行其他顯示。

自定義異常類

首先是自定義異常類,示例我們定義一個處理User類的異常類和異常處理器,在異常類中,設(shè)置對于User類出現(xiàn)異常時的錯誤信息存儲。

package com.mvc.exception;
 
public class UserException extends Exception {
	private static final long serialVersionUID = 1L;
	private String exceptionMessage;
	
	public UserException(String exceptionMessage) {
		super(exceptionMessage);
		this.exceptionMessage = exceptionMessage;
	}
	
	public String getExceptionMessage() {
		return exceptionMessage;
	}
	public void setExceptionMessage(String exceptionMessage) {
		this.exceptionMessage = exceptionMessage;
	}
}

自定義異常類UserException專門負責(zé)處理User類異常,它怎么指定處理User類呢?這個是在異常處理器中完成,UserException繼承了Exception類,這樣我們就可以在具體Controller方法中將其throws拋出該異常。該類中定義了一個異常信息變量,用來存放異常信息,當(dāng)異常處理器捕獲到User類的異常時,通過UserException的構(gòu)造方法設(shè)置異常信息,最后拋出UserException。

異常處理器

來到異常處理器的配置,異常處理器是捕獲和處理異常的核心,在Spring MVC中,底層異常會一級一級往上拋,最后到達全局異常處理器,全局異常處理器的工作主要有四步:

  1. 捕獲異常,解析出異常類型。
  2. 如果異常是預(yù)期異常(有定義好的異常類),則拋出相應(yīng)的異常信息。
  3. 如果異常不是預(yù)期異常,則創(chuàng)建一個自定義異常類,拋出相應(yīng)的異常信息(如:“未知異常信息”)。
  4. 將異常信息綁定到前端頁面,跳轉(zhuǎn)到相應(yīng)的異常信息頁面中去。

結(jié)合上面的自定義異常類,來看看針對User類的異常處理器的配置:

package com.mvc.exception;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
 
public class UserExceptionResolver implements HandlerExceptionResolver {
	@Override
	public ModelAndView resolveException(HttpServletRequest request, 
			HttpServletResponse response, Object handler, Exception ex) {
		// 首先解析出異常的類型
		UserException userException = null;
		if (ex instanceof UserException) {
			// 如果異常類型是UserException,則直接創(chuàng)建該類型的異常信息
			userException = (UserException) ex;
		} else {
			// 否則創(chuàng)建一個自定義的異常類型
			userException = new UserException("發(fā)生未知錯誤。");
		}
		
		// 取出錯誤信息
		String errorMessage = userException.getExceptionMessage();
		ModelAndView modelAndView = new ModelAndView();
		// 錯誤信息傳送到前端頁面
		modelAndView.addObject("errorMessage", errorMessage);
		// 定向到錯誤提示頁面
		modelAndView.setViewName("errorPage/userError");
		
		return modelAndView;
	}
	
}

Spring MVC中,異常信息最終通過DispatcherServlet交由全局異常處理器處理,需要全局異常處理器實現(xiàn)HandlerExceptionResolver接口接,重寫里面的resolverException()方法完成異常處理。該方法中有兩個參數(shù)要注意,object handler指定異常處理器要處理的對象,Exception ex顯然就是接收底層拋出的異常。

在我們的異常處理器UserExceptionResolver中,第14行首先判斷異常類型是否我們的定義的預(yù)期異常UserException,如果是,則拋出,否則,創(chuàng)建一個自定義異常類型,并給出錯誤提示“發(fā)生未知錯誤”。最后第26行,對異常信息處理完后,發(fā)送到前端頁面進行展示,并跳轉(zhuǎn)到錯誤提示界面。

測試用例

最后要使用我們的異常處理器,先要在Spring配置文件中添加這個異常處理器:

<!-- 配置全局異常處理器 -->
<bean class="com.mvc.exception.UserExceptionResolver"></bean>

然后在Controller類方法中做相應(yīng)的判斷,如果出現(xiàn)預(yù)期異常,則拋出:

@Controller
@RequestMapping("user")
public class InterfaceValidationController {
	@InitBinder
	public void initBinder(DataBinder binder) {
		// 為DataBinder對象設(shè)置Validator校驗接口
		binder.setValidator(new UserValidator());
	}
 
	@RequestMapping("login")
	public String login(Model model, @Valid User user, BindingResult result) 
			throws UserException {
		boolean allowVisit = checkUser(user);
		if (!allowVisit) {
			// 該用戶沒有訪問權(quán)限,拋出異常
			throw new UserException("您沒有權(quán)限訪問!");
		}
		
		List<ObjectError> allErrors = null;
		if (result.hasErrors()) {
			allErrors = result.getAllErrors();
			// 輸出所有錯誤信息
			for(ObjectError objectError : allErrors) {
				System.out.println("code = " + objectError.getCode() + 
						"DefaultMessage = " + objectError.getDefaultMessage());
				// 將錯誤信息發(fā)送到前端頁面
				model.addAttribute("allErrors", allErrors);
			}
			
			// 最后返回視圖
			return "users/login";
		} else {
			// 如果校驗沒有錯誤,跳轉(zhuǎn)到成功登陸的頁面
			return "users/successLogin";
		}
	}

可以看到第57行最后我們還要跳轉(zhuǎn)到錯誤頁面,將錯誤信息顯示出來:

<%@ page language="java" import="java.util.*" 
	contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta charset="utf-8">
<title>錯誤提示</title>
</head>
<body>
	發(fā)生異常,錯誤信息如下:</br>
	<h3>
		<font color="red">${errorMessage}</font>
	</h3></br>
</body>
</html>

完整代碼已上傳GitHub:

https://github.com/justinzengtm/SSM-Framework/tree/master/SpringMVC_Project

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring Mybatis 分頁插件使用教程

    Spring Mybatis 分頁插件使用教程

    這篇文章主要介紹了Spring Mybatis分頁插件使用教程,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2018-02-02
  • JAVA代碼塊你了解嗎

    JAVA代碼塊你了解嗎

    這篇文章主要介紹了舉例說明Java中的代碼塊,包括靜態(tài)屬性和非靜態(tài)屬性以及構(gòu)造函數(shù)等相關(guān)的執(zhí)行先后,需要的朋友可以參考下
    2021-09-09
  • SpringBoot整合Dubbo+Zookeeper實現(xiàn)RPC調(diào)用

    SpringBoot整合Dubbo+Zookeeper實現(xiàn)RPC調(diào)用

    這篇文章主要給大家介紹了Spring Boot整合Dubbo+Zookeeper實現(xiàn)RPC調(diào)用的步驟詳解,文中有詳細的代碼示例,對我們的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-07-07
  • SpringMVC整合SSM實現(xiàn)表現(xiàn)層數(shù)據(jù)封裝詳解

    SpringMVC整合SSM實現(xiàn)表現(xiàn)層數(shù)據(jù)封裝詳解

    這篇文章主要介紹了SpringMVC整合SSM實現(xiàn)表現(xiàn)層數(shù)據(jù)封裝,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-10-10
  • eclipse+jdk安裝以及會遇到的問題及解決方法

    eclipse+jdk安裝以及會遇到的問題及解決方法

    這篇文章主要介紹了eclipse+jdk安裝以及會遇到的問題+解決方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • Java詳解表格的創(chuàng)建與使用流程

    Java詳解表格的創(chuàng)建與使用流程

    這篇文章主要介紹了怎么用Java來創(chuàng)建和使用表格,表格是我們經(jīng)常要用的工具,但是你有想過自己怎么去實現(xiàn)它嗎,感興趣的朋友跟隨文章往下看看吧
    2022-04-04
  • java啟動如何設(shè)置JAR包內(nèi)存大小

    java啟動如何設(shè)置JAR包內(nèi)存大小

    這篇文章主要介紹了java啟動如何設(shè)置JAR包內(nèi)存大小問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • java利用SMB讀取遠程文件的方法

    java利用SMB讀取遠程文件的方法

    這篇文章主要為大家詳細介紹了java利用SMB讀取遠程文件的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • 一種類似JAVA線程池的C++線程池實現(xiàn)方法

    一種類似JAVA線程池的C++線程池實現(xiàn)方法

    線程池(thread pool)是一種線程使用模式。線程過多或者頻繁創(chuàng)建和銷毀線程會帶來調(diào)度開銷,進而影響緩存局部性和整體性能。這篇文章主要介紹了一種類似JAVA線程池的C++線程池實現(xiàn)方法,需要的朋友可以參考下
    2019-07-07
  • 淺析Mybatis 在CS程序中的應(yīng)用

    淺析Mybatis 在CS程序中的應(yīng)用

    如果是自己用的Mybatis,不需要考慮對配置文件加密,如果不是,那就需要考慮加密,這篇文章主要講如何配置CS的Mybatis
    2013-07-07

最新評論