日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
SpringBoot中處理校驗(yàn)邏輯的兩種方式,真的很機(jī)智!
  • 一種是用 Hibernate Validator 來處理
  • 一種是用全局異常來處理

兩種方式,我們一一來實(shí)踐體驗(yàn)一下。

我們提供的服務(wù)有:成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、東莞ssl等。為上千多家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的東莞網(wǎng)站制作公司

一、Hibernate Validator

Spring Boot 已經(jīng)內(nèi)置了 Hibernate Validator 校驗(yàn)框架,這個(gè)可以通過 Spring Boot 官網(wǎng)查看和確認(rèn)。

第一步,進(jìn)入 Spring Boot 官網(wǎng),點(diǎn)擊 learn 這個(gè)面板,點(diǎn)擊參考文檔。

第二步,在參考文檔頁點(diǎn)擊「依賴的版本」。

第三步,在依賴版本頁就可以查看到所有的依賴了,包括版本號(hào)。

PS:如果發(fā)現(xiàn)沒有起效,可能是依賴版本沖突了,手動(dòng)把 Hibernate Validator 依賴添加到 pom.xml 文件就可以了。


org.hibernate.validator
hibernate-validator
6.0.17.Final


javax.validation
validation-api
2.0.1.Final

通過 Hibernate Validator 校驗(yàn)框架,我們可以直接在請(qǐng)求參數(shù)的字段上加入注解來完成校驗(yàn)。

具體該怎么做呢?

第一步,在需要驗(yàn)證的字段上加上 Hibernate Validator 提供的校驗(yàn)注解。

比如說我現(xiàn)在有一個(gè)用戶名和密碼登錄的請(qǐng)求參數(shù) UsersLoginParam 類:

@Data
@ApiModel(value="用戶登錄", description="用戶表")
public class UsersLoginParam implements Serializable {
private static final long serialVersionUID = 1L;

@ApiModelProperty(value = "登錄名")
@NotBlank(message="登錄名不能為空")
private String userLogin;

@ApiModelProperty(value = "密碼")
@NotBlank(message="密碼不能為空")
private String userPass;
}

就可以通過 @NotBlank 注解來對(duì)用戶名和密碼進(jìn)行判空校驗(yàn)。除了 @NotBlank 注解,Hibernate Validator 還提供了以下常用注解:

  • @NotNull:被注解的字段不能為 null;
  • @NotEmpty:被注解的字段不能為空;
  • @Min:被注解的字段必須大于等于其value值;
  • @Max:被注解的字段必須小于等于其value值;
  • @Size:被注解的字段必須在其min和max值之間;
  • @Pattern:被注解的字段必須符合所定義的正則表達(dá)式;
  • @Email:被注解的字段必須符合郵箱格式。

第二步,在對(duì)應(yīng)的請(qǐng)求接口(UsersController.login())中添加 @Validated 注解,并注入一個(gè) BindingResult 參數(shù)。

@Controller
@Api(tags="用戶")
@RequestMapping("/users")
public class UsersController {
@Autowired
private IUsersService usersService;

@ApiOperation(value = "登錄以后返回token")
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public ResultObject login(@Validated UsersLoginParam users, BindingResult result) {
String token = usersService.login(users.getUserLogin(), users.getUserPass());
if (token == null) {
return ResultObject.validateFailed("用戶名或密碼錯(cuò)誤");
}
Map tokenMap = new HashMap<>();
tokenMap.put("token", token);
tokenMap.put("tokenHead", tokenHead);
return ResultObject.success(tokenMap);
}
}

第三步,為控制層(UsersController)創(chuàng)建一個(gè)切面,將通知注入到 BindingResult 對(duì)象中,然后再判斷是否有校驗(yàn)錯(cuò)誤,有錯(cuò)誤的話返回校驗(yàn)提示信息,否則放行。

@Aspect
@Component
@Order(2)
public class BindingResultAspect {
@Pointcut("execution(public * com.codingmore.controller.*.*(..))")
public void BindingResult() {
}

@Around("BindingResult()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
if (arg instanceof BindingResult) {
BindingResult result = (BindingResult) arg;
if (result.hasErrors()) {
FieldError fieldError = result.getFieldError();
if(fieldError!=null){
return ResultObject.validateFailed(fieldError.getDefaultMessage());
}else{
return ResultObject.validateFailed();
}
}
}
}
return joinPoint.proceed();
}
}

這里涉及到了 SpringBoot AOP 的知識(shí),我在前面的文章里講解過了,戳這個(gè)鏈接可以直達(dá):SpringBoot AOP 掃盲

第四步,訪問登錄接口,用戶名和密碼都不傳入的情況下,就會(huì)返回“用戶名不能為空”的提示信息。

通過 debug 的形式,體驗(yàn)一下整個(gè)工作流程。

可以看得出,Hibernate Validator 帶來的優(yōu)勢(shì)有這些:

  • 驗(yàn)證邏輯與業(yè)務(wù)邏輯進(jìn)行了分離,降低了程序耦合度;
  • 統(tǒng)一且規(guī)范的驗(yàn)證方式,無需再次編寫重復(fù)的驗(yàn)證代碼。

不過,也帶來一些弊端,比如說:

  • 需要在請(qǐng)求接口的方法中注入 BindingResult 對(duì)象
  • 只能校驗(yàn)一些非常簡(jiǎn)單的邏輯,涉及到數(shù)據(jù)查詢就無能為力了。

二、全局異常處理

使用全局異常處理的優(yōu)點(diǎn)就是比較靈活,可以處理比較復(fù)雜的邏輯校驗(yàn),在校驗(yàn)失敗的時(shí)候直接拋出異常,然后進(jìn)行捕獲處理就可以了。

第一步,新建一個(gè)自定義異常類 ApiException。

public class ApiException extends RuntimeException {
private IErrorCode errorCode;

public ApiException(IErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}

public ApiException(String message) {
super(message);
}

public ApiException(Throwable cause) {
super(cause);
}

public ApiException(String message, Throwable cause) {
super(message, cause);
}

public IErrorCode getErrorCode() {
return errorCode;
}
}

第二步,新建一個(gè)斷言處理類 Asserts,簡(jiǎn)化拋出 ApiException 的步驟。

public class Asserts {
public static void fail(String message) {
throw new ApiException(message);
}

public static void fail(IErrorCode errorCode) {
throw new ApiException(errorCode);
}
}

第三步,新建一全局異常處理類 GlobalExceptionHandler,對(duì)異常信息進(jìn)行解析,并封裝到統(tǒng)一的返回對(duì)象 ResultObject 中。

@ControllerAdvice
public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler(value = ApiException.class)
public ResultObject handle(ApiException e) {
if (e.getErrorCode() != null) {
return ResultObject.failed(e.getErrorCode());
}
return ResultObject.failed(e.getMessage());
}
}

全局異常處理類用到了兩個(gè)注解,@ControllerAdvice 和 @ExceptionHandler。

@ControllerAdvice 是一個(gè)特殊的@Component(可以通過源碼看得到),用于標(biāo)識(shí)一個(gè)類,這個(gè)類中被以下三種注解標(biāo)識(shí)的方法:@ExceptionHandler,@InitBinder,@ModelAttribute,將作用于所有@Controller 類的接口上。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
}

@ExceptionHandler 注解的作用就是標(biāo)識(shí)統(tǒng)一異常處理,它可以指定要統(tǒng)一處理的異常類型,比如說我們自定義的 ApiException。

第四步,在需要校驗(yàn)的地方通過 Asserts 類拋出異常 ApiException。還拿用戶登錄這個(gè)接口來說明吧。

@Controller
@Api(tags="用戶")
@RequestMapping("/users")
public class UsersController {
@ApiOperation(value = "登錄以后返回token")
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public ResultObject login(@Validated UsersLoginParam users, BindingResult result) {
String token = usersService.login(users.getUserLogin(), users.getUserPass());

Map tokenMap = new HashMap<>();
tokenMap.put("token", token);
tokenMap.put("tokenHead", tokenHead);
return ResultObject.success(tokenMap);
}
}

該接口需要查詢數(shù)據(jù)庫驗(yàn)證密碼是否正確,如果密碼不正確就拋出校驗(yàn)信息“密碼不正確”。

@Service
public class UsersServiceImpl extends ServiceImpl implements IUsersService {
public String login(String username, String password) {
String token = null;
//密碼需要客戶端加密后傳遞
UserDetails userDetails = loadUserByUsername(username);
if (!passwordEncoder.matches(password, userDetails.getPassword())) {
Asserts.fail("密碼不正確");
}
// 其他代碼省略
return token;
}
}

第五步,通過 ApiPost 來測(cè)試一下接口,故意把密碼輸錯(cuò)。

也可以通過 debug 的形式,體驗(yàn)一下整個(gè)工作流程。

三、總結(jié)

實(shí)際開發(fā)中把兩者結(jié)合在一起用,就可以彌補(bǔ)彼此的短板了,簡(jiǎn)單校驗(yàn)用 Hibernate Validator,復(fù)雜一點(diǎn)的邏輯校驗(yàn),比如說需要數(shù)據(jù)庫查詢用全局異常處理來實(shí)現(xiàn)。

源碼地址:https://github.com/itwanger/coding-more


網(wǎng)頁名稱:SpringBoot中處理校驗(yàn)邏輯的兩種方式,真的很機(jī)智!
網(wǎng)站路徑:http://www.dlmjj.cn/article/coehoje.html