如何優雅的處理SpringBoot接口中參數校驗


相信我們在處理接口參數校驗時,都不會使用大量的if,else 進行來處理,這樣顯得太繁瑣,下面就來介紹一下如何能夠簡單而有效的處理方式:

一、使用注解來處理參數校驗

1、實體類

package com.dongl.bean.mybean;


import com.dongl.utils.annotation.CheckField;
import lombok.Data;
import org.hibernate.validator.constraints.Range;

import javax.validation.constraints.NotNull;
import java.util.Date;
@Data
public class User { /**主鍵*/ private Long id; /**姓名*/ @NotNull private String name; /**性別*/ @CheckField(fieldValues = {"男", "女"}) private String sex; /**出生日期*/ private Date birthDay; /**年齡*/ @Range(min = 20 , max = 99) private Short age; /**詳細地址*/ private String address; }

 

2、Controller層

package com.dongl.controller;

import com.dongl.bean.mybean.User;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * @author D-L
 * @Classname AnnotationController
 * @Version 1.0
 * @Description   接口參數校驗異常處理
 * @Date 2020/8/26
 */

@RestController
@RequestMapping("Annotation")
public class AnnotationController {

    @PostMapping(value = "user")
    public String test(@Validated @RequestBody User user  /*, BindingResult bindingResult*/) {
        System.out.println(user);
        return "do something you like ------";
    }
}

 

3、響應結果

測試參數:

{
    "name":"admin",
    "sex":"男",
    "age":120,
    "address":"杭州市西湖區"
}

response:

{
    "timestamp": "2020-08-26T07:25:45.547+0000",
    "status": 400,
    "error": "Bad Request",
    "errors": [
        {
            "codes": [
                "Range.user.age",
                "Range.age",
                "Range.java.lang.Short",
                "Range"
            ],
            "arguments": [
                {
                    "codes": [
                        "user.age",
                        "age"
                    ],
                    "arguments": null,
                    "defaultMessage": "age",
                    "code": "age"
                },
                99,
                20
            ],
            "defaultMessage": "需要在20和99之間", "objectName": "user",
            "field": "age",
            "rejectedValue": 120,
            "bindingFailure": false,
            "code": "Range"
        }
    ],
    "message": "Validation failed for object='user'. Error count: 1",
    "trace": "org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public java.lang.String com.dongl.controller.AnnotationController.test(com.dongl.bean.mybean.User): [Field error in object 'user' on field 'age': rejected value [120]; codes [Range.user.age,Range.age,Range.java.lang.Short,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.age,age]; arguments []; default message [age],99,20]; default message [需要在20和99之間]] \r\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat java.lang.Thread.run(Thread.java:748)\r\n",
    "path": "/Annotation/user"
}

結論】:這樣的響應結果顯然有點不夠優雅,太繁瑣,有沒有更好的處理方式,當然有,下面使用 BindResult 處理。

 

二、針對接口處理  Validator + BindResult進行校驗

1、處理響應結果

package com.dongl.controller;

import com.dongl.bean.mybean.User;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author D-L
 * @Classname AnnotationController
 * @Version 1.0
 * @Description   處理參數校驗異常 
 * @Date 2020/8/24
 */

@RestController
@RequestMapping("Annotation")
public class AnnotationController {

    @PostMapping(value = "user")
    public String test(@Validated @RequestBody User user  , BindingResult bindingResult) {
        List<ObjectError> allErrors = bindingResult.getAllErrors(); // 如果有參數校驗失敗,會將錯誤信息封裝成對象組裝在BindingResult里
        for(ObjectError error : allErrors){ return error.getDefaultMessage(); }
        System.out.println(user);
        return "do something you like ------";
    }
}

 

2、響應結果

需要在20和99之間

結論】當然這種方式已經解決了返回體繁瑣的問題,但是每一處理接口參數都需要添加,還是有點不盡人意,有沒有更好的解決方法,當然有,下面通過全局的方式處理。

 

三、全局異常處理  Validator + 自動拋出異常

1、全局處理響應結果

首先,我們需要新建一個類,在這個類上加上@ControllerAdvice或@RestControllerAdvice注解,這個類就配置成全局處理類了。(這個根據你的Controller層用的是@Controller還是@RestController來決定)

這里就以@RestController為例:

package com.dongl.utils.error;

import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * @author D-L
 * @Classname ExceptionControllerAdvice
 * @Version 1.0
 * @Description   全局處理參數校驗異常返回提示
 * @Date 2020/8/26
 */
@RestControllerAdvice
public class ExceptionControllerAdvice {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        // 從異常對象中拿到ObjectError對象
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        // 然后提取錯誤提示信息進行返回
        return objectError.getDefaultMessage();
    }
}

 

2、測試結果:

需要在20和99之間

注釋】:這里說明一下如果你進行了全局的處理,但在接口上又進行了手動處理,這時命中的是接口上的,也就是全局配置不生效了。


免責聲明!

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



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