国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - SpringBoot validator參數驗證restful自定義錯誤碼響應方式

SpringBoot validator參數驗證restful自定義錯誤碼響應方式

2022-02-23 00:38shalousun Java教程

這篇文章主要介紹了SpringBoot validator參數驗證restful自定義錯誤碼響應方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

validator參數驗證restful自定義錯誤碼響應

關于spring web應用中關于如何使用 Bean Validation API和hibernate-validator的文章已經很多,本文就不再重復敘述,今天要介紹的重點是在SpringBoot restful服務中如何根據不同驗證錯誤響應不同的自定義錯誤碼。下面直接上代碼。

一、定義restful統一結果返回

阿里java開發手冊中定義的一段參考【“對于公司外的 http/api 開放接口必須使用“錯誤碼”; 而應用內部推薦異常拋出;跨應用間 RPC 調用優先考慮使用 Result 方式,封裝 isSuccess()方法、 “錯誤碼”、“錯誤簡短信息”。】。因此這里也定義個返回結構。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class CommonResult<T> implements Serializable {
    
    /**
     * serialVersionUID:.
     */
    private static final long serialVersionUID = -7268040542410707954L;
 
    /**
     * 是否成功
     */
    private boolean success = false;
 
    /**
     * 返回信息
     */
    private String message;
 
    /**
     * 裝在數據
     */
    private T data;
 
    /**
     * 錯誤代碼
     */
    private String code;
 
    /**
     * 默認構造器
     */
    public CommonResult(){
        
    }
    /**
     *
     * @param success
     *          是否成功
     * @param message
     *          返回的消息
     */
    public CommonResult(boolean success, String message){
        this.success = success;
        this.message = message;
    }
    /**
     *
     * @param success
     *          是否成功
     */
    public CommonResult(boolean success){
        this.success = success;
    }
 
    /**
     *
     * @param code error code
     * @param message success or error messages
     */
    public CommonResult(String code,String message){
        this.code = code;
        this.message = message;
    }
    /**
     *
     * @param success
     *          是否成功
     * @param message
     *          消息
     * @param data
     *          數據
     */
    public CommonResult(boolean success, String message, T data){
        this.success = success;
        this.message = message;
        this.data = data;
    }
    //省略get set
}

二、定義一個錯誤碼枚舉

在有需要國際化的項目,當然選擇通過i18n來配置更好,此處為了簡單直接采用枚舉定義。這里定義的錯誤僅供參考,不同公司每個應用在實際情況下可能都不大一樣。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
 * 錯誤代碼枚舉類
 *
 */
public enum ErrorCodeEnum {
    SUCCESS("0000", "success"),
    PARAM_EMPTY("1001", "必選參數為空"),
    PARAM_ERROR("1002", "參數格式錯誤"),
    UNKNOWN_ERROR("9999", "系統繁忙,請稍后再試....");
    private String code;
    private String desc;
    ErrorCodeEnum(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }
 
    public String getCode() {
        return this.code;
    }
 
    public String getDesc() {
        return desc;
    }
 
    @Override
    public String toString() {
        return "[" + this.code + "]" + this.desc;
    }
}

三、靜態封裝CommonResult

靜態封裝CommonResult主要是方便在項目中快速根據邏輯寫返回結果代碼。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
 * 公共響應結果成功失敗的靜態方法調用
 *
 */
public class ResultUtil {
 
 
    /**
     * return success
     *
     * @param data
     * @return
     */
    public static <T> CommonResult<T> returnSuccess(T data) {
        CommonResult<T> result = new CommonResult();
        result.setCode(ErrorCodeEnum.SUCCESS.getCode());
        result.setSuccess(true);
        result.setData(data);
        result.setMessage(ErrorCodeEnum.SUCCESS.getDesc());
        return result;
    }
 
    /**
     * return error
     *
     * @param code error code
     * @param msg  error message
     * @return
     */
    public static CommonResult returnError(String code, String msg) {
        CommonResult result = new CommonResult();
        result.setCode(code);
        result.setData("");
        result.setMessage(msg);
        return result;
    }
 
    /**
     * use enum
     *
     * @param status
     * @return
     */
    public static CommonResult returnError(ErrorCodeEnum status) {
        return returnError(status.getCode(), status.getDesc());
    }
}

四、定義BaseController來處理驗證錯誤自定義錯誤碼返回

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
 * BaseController
 *
 */
public abstract class BaseController {
    private static final Logger LOGGER = LoggerFactory.getLogger(BaseController.class);
    /**
     * validate params
     *
     * @param bindingResult
     * @return
     */
    protected CommonResult validParams(BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            return processBindingError(fieldError);
        }
        return ResultUtil.returnSuccess("");
    }
 
    /**
     * 根據spring binding 錯誤信息自定義返回錯誤碼和錯誤信息
     *
     * @param fieldError
     * @return
     */
    private CommonResult processBindingError(FieldError fieldError) {
        String code = fieldError.getCode();
        LOGGER.debug("validator error code: {}", code);
        switch (code) {
            case "NotEmpty":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_EMPTY.getCode(), fieldError.getDefaultMessage());
            case "NotBlank":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_EMPTY.getCode(), fieldError.getDefaultMessage());
            case "NotNull":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_EMPTY.getCode(), fieldError.getDefaultMessage());
            case "Pattern":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            case "Min":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            case "Max":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            case "Length":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            case "Range":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            case "Email":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            case "DecimalMin":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            case "DecimalMax":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            case "Size":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            case "Digits":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            case "Past":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            case "Future":
                return ResultUtil.returnError(ErrorCodeEnum.PARAM_ERROR.getCode(), fieldError.getDefaultMessage());
            default:
                return ResultUtil.returnError(ErrorCodeEnum.UNKNOWN_ERROR);
        }
    }
}

五、驗證實例

這里直接給出一個簡單的參數驗證例子。

Controller繼承上面寫的BaseController

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
 * 關于Validator使用測試
 *
 */
@RestController
@RequestMapping("validator")
public class ValidatorTestController extends BaseController {
    private static final Logger LOGGER = LoggerFactory.getLogger(ValidatorTestController.class);
    /**
     * validate驗證測試
     *
     * @param leader
     * @param bindingResult
     * @return
     */
    @PostMapping("/test")
    public CommonResult testSimpleValidate(@Valid @RequestBody Leader leader, BindingResult bindingResult) {
        LOGGER.debug("ReqParams:{}", JSON.toJSONString(leader));
        CommonResult result = validParams(bindingResult);
        if (!result.isSuccess()) {
            return result;
        }
        return ResultUtil.returnSuccess("");
    }
}

入參對象Leader代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Leader {
    /**
     * 姓名
     */
    @NotEmpty
    private String name;
 
    /**
     * 生日
     */
    @Pattern(regexp = "^[0-9]{4}-[0-9]{2}-[0-9]{2}$", message = "出生日期格式不正確")
    private String birthday;
 
    /**
     * 年齡
     */
    @Min(value = 0)
    private Integer age;
    //省略gettes and  setters
}

這時項目已經已經完全可以根據驗證錯誤來返回自定義的錯誤碼和提示了。

本例所涉及源代碼:https://github.com/shalousun/api-doc-test

小結一下

在一些對外服務提供restful的應用中,根據不同的驗證錯誤返回其實是避免不了。當然實現的方式可以有種,而本文所采用的方式相對來說簡單易懂。

使用validator-api驗證springboot的參數

作為服務端開發,驗證前端傳入的參數的合法性是一個必不可少的步驟,但是驗證參數是一個基本上是一個體力活,而且冗余代碼繁多,也影響代碼的可閱讀性,所以有沒有一個比較優雅的方式來解決這個問題?

這么簡單的問題當然早就有大神遇到并且解決了,這一篇文章主要講一下解決基于spring-boot的驗證參數的比較好的方法:利用validator-api來進行驗證參數。

在spring-boot-starter-web包里面有hibernate-validator包,它提供了一系列驗證各種參數的方法,所以說spring-boot已經幫我們想好要怎么解決這個問題了。

這篇文章針對spring-boot里面的spring-mvc介紹三種方式來驗證參數。

一、這個方法在網上大部分都可以查到

先假設我們的restful的接口接受一個GradeAndClassroomModel類型的對象,并且這個類被定義成

?
1
2
3
4
5
6
7
@Data
public class GradeAndClassroomModel { 
@Range(min = 1, max = 9, message = "年級只能從1-9"
private int grade; 
@Range(min = 1, max = 99, message = "班級只能從1-99"
private int classroomNumber;
}

利用validator提供的一系列注解,比如本例中的@Range,就可以表示參數的范圍和出錯時候的提示信息。還有很多其他注解,這里就不一一列出

然后我們的Controller層的代碼為

?
1
2
3
4
5
6
7
8
@RequestMapping(value = "/paramErrorTest", method = RequestMethod.GET)
public String paramErrorTest(   
  @Valid   
  @ModelAttribute   
  GradeAndClassroomModel gradeAndClassroomModel,
  BindingResult result) { 
  return classroomService.getTeacherName(gradeAndClassroomModel.getGrade(), gradeAndClassroomModel.getClassroomNumber());
}

其中如果驗證出錯,result對象里面就會有錯誤信息,然后可以自己進行處理。

二、針對上面的例子

會有人說,就兩個參數,為什么要作為對象呢?會不會太麻煩?確實,如果只有少數對象,直接把參數寫到Controller層,然后在Controller層進行驗證就可以了。

?
1
2
3
4
5
6
7
8
9
10
11
@RequestMapping(value = "/teacherName", method = RequestMethod.GET)
public String teacherName(
  @Range(min = 1, max = 9, message = "年級只能從1-9")       
  @RequestParam(name = "grade", required = true)
  int grade, 
  @Min(value = 1, message = "班級最小只能1")   
  @Max(value = 99, message = "班級最大只能99")     
  @RequestParam(name = "classroom", required = true)   
  int classroom) { 
return classroomService.getTeacherName(grade, classroom);
}

如果直接把validator提供的注解移除來寫到請求參數上面的話是不是就可以了呢?答案是錯,為什么這樣不能成功的驗證參數呢?具體原因大家可以參考官方文檔:

上面的文檔已經說的很清楚了,所以我們需要創建一個Bean

?
1
2
3
4
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() { 
  return new MethodValidationPostProcessor();
}

然后在類方法上面加上注解@Validated

?
1
2
3
4
5
6
@RestController
@RequestMapping("/spring-boot/classroom")
@Validated
public class ClassroomController {
 ...
}

然后之前沒有生效的注解@Range、@Min、@Max等validator包里面提供的注解就可以生效了。

三、估計到了這里又會有人問

如果validator包里面注解不能滿足我們的需求,我們是否可以自己定義參數驗證的邏輯。答案是肯定的,我們可以利用

?
1
2
3
4
5
6
7
8
9
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Constraint(validatedBy = {Validator.class})
public @interface ParamValidator {
  String message() default "Parameter error!";
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() default {};
}

?
1
2
3
public class Validator implements ConstraintValidator<ParamValidator, Object> {
  ...
}

組合進行自定義,具體的例子網上其他文章就很多了,這里就不進行詳細的例子了,但是最終使用的時候就是

?
1
2
3
4
5
6
7
8
9
10
@RequestMapping(value = "/paramValidator", method = RequestMethod.GET)
public String paramValidator(
    @ParamValidator(isRequired = true, desc = "年級", range = "int:1~9", message = "年級只能從1-9")
    @RequestParam(name = "grade", required = true)
    int grade,
    @ParamValidator(isRequired = true, desc = "班級", range = "int:1~99", message = "班級只能從1-99")
    @RequestParam(name = "classroom", required = true)
    int classroom) {
  return classroomService.getTeacherName(grade, classroom);
}

另外不要忘記方法二里面里面提到的MethodValidationPostProcessor這個bean,如果沒有初始化這個bean,自定義的驗證方法也不會執行。驗證邏輯會失效。

是不是通過這樣寫注解的方式來驗證進行請求的參數,代碼邏輯更佳清晰和優雅?表達的含義也會更佳清楚?并且沒有了大量重復的類似的驗證代碼。

Ps:這里的代碼都是基于spring-mvc框架來試驗的,如果有人并沒有使用spring-mvc作為rest框架,而是使用jersey來作為rest框架的話,可能一些細節方面需要調整, 但是這三種方案應該都是可以兼容的。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/shalousun/article/details/80960835

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 亚洲日本在线观看视频 | 国产综合精品一区二区三区 | 亚洲欧美v国产一区二区 | 亚洲依依 | 欧美日韩在线视频免费 | av网站在线免费观看 | 91午夜在线| 日韩色综合| 精品美女久久久 | 精精国产xxxx视频在线播放 | 自拍偷拍小视频 | 亚洲精品视 | 亚洲精品一区二三区不卡 | 免费一区二区 | 国产色婷婷 | 精品国产乱码久久久久久久 | 精品视频在线播放 | 一级二级在线观看 | 欧美1区2区3区 | a视频在线观看 | 国产一区在线不卡 | 久久久亚洲精品中文字幕 | 欧美日韩一区在线 | 黄色免费网 | 在线观看日韩av | 免费日韩一级片 | 欧美人成在线 | 午夜爱爱毛片xxxx视频免费看 | 国产一区二区精品在线观看 | 在线观看中文字幕 | 少妇看av一二三区 | 成人免费网站 | 国产一区二区精品 | 亚洲精品电影网在线观看 | 性吧在线| 黄视频在线播放 | 久久精品国产99国产 | 亚洲国内精品 | 中文字幕一区二区三区在线视频 | 亚洲电影在线 | av不卡电影在线观看 |