JAVA開發中,API接口如何優雅的進行參數校驗?

我們在做與前端交互的後臺應用接口的過程中,會定義很多對應的接口及參數,而有些接口參數有一定的要求,比如最大值、最小值約束,涉及到手機號、身份證等規則校驗,參數是否為空等等,剛進入java領域的小夥伴們大部分第一時間都是針對每個參數進行一一判別校驗、當接口參數校驗,判斷邏輯代碼就顯得極其冗雜,不美觀也不便於閱讀。其實我們可以使用validation結合spring進行參數的校驗,並且通過Controller增強器@ControllerAdvice來定義全局異常處理類,配合@ExceptionHandler可以更加優雅的處理參數的校驗問題。

話不多述,看代碼:

1.新增全局異常處理

<code>@ControllerAdvice
@ResponseBody
public class CommonExceptionAdvice {
    private static Logger logger = LoggerFactory.getLogger(CommonExceptionAdvice.class);
    @Autowired
    private MessageSource messageSource;
    
   @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public BaseResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        logger.error("參數驗證失敗:{}", e.getMessage());
        BindingResult result = e.getBindingResult();
        List errorList = e.getBindingResult().getFieldErrors();
        List errorMessages = errorList.stream().map(x->{
            String itemMessage= messageSource.getMessage(x.getDefaultMessage(), null, x.getDefaultMessage(), LocaleContextHolder.getLocale());
            return String.format("%s", itemMessage);
        }).collect(Collectors.toList());
        return BaseResponse.errorResponse(errorMessages.toString());
    }
 }
/<code>

2.定義參數

基礎請求參數:

<code>/*
 * Copyright (C) 2020 Baidu, Inc. All Rights Reserved.
 */
package com.itstabber.blog.example.request;

import io.swagger.annotations.ApiModel;
import lombok.Data;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;

/**
 * TODO: 請添加描述
 *
 * @author Stabber
 * @date 2020/3/24 00:33
 * @since 1.0.0
 */
@Data
public class BaseRequest {
    @NotNull(message = "參數i不能為空")
    private Integer i;
    @NotBlank(message="參數s不能為空")
    private String s;

    @Min(value =0,message = "最小值不能小於0")
    private int min;

    @Max(value=100,message = "最大值不能大約100")
    private int max;


}

/<code>

@NotNull 用於約束請求參數不能為Null

@NotBlank針對於String類型,不能為空串或者全部空格的參數

@Min @Max 可以限制參數的最小、最大值

複雜請求參數

<code>@ApiModel("訂單申請信息")
public class OrderRequest extends BaseRequest{

    @ApiModelProperty(name="訂單編號")
    @Length( max= 10,message = "訂單編號最大10位")
    private String orderNo;

    @Valid
    @ApiModelProperty(name="商品列表信息")
    private List productRequestList;

}

@Data
@ApiModel("商品申請信息")
public class ProductRequest {

    @NotBlank
    @ApiModelProperty(name = "商品名稱")
    private String productName;
    @NotBlank
    @ApiModelProperty(name = "商品編碼")
    private String productCode;
}
/<code>

@Length 可以定義min,max屬性約束字段的最小、最大長度

@Valid 放在對象屬性上,可以是對象內的參數約束生效

3.定義controller

<code>@RequestMapping("/hello")
@RestController
@Api(tags = "HelloWorld 入口")
public class HelloWorld {

    @GetMapping("/world")
    @ApiOperation(value = "helloWorld")
    public String helloWorld() {
        return "hello world!";
    }


    @PostMapping("/test/param")
    @ApiOperation(value = "testParam")
    public BaseResponse testParam(
            @Valid @RequestBody BaseRequest baseRequest
    ) {
        return BaseResponse.successResponse("參數校驗成功");
    }

    @ApiOperation(value = "testOrderParam")
    @PostMapping("/test/order")
    public BaseResponse testOrderParam(
            @Validated @RequestBody OrderRequest baseRequest
    ) {
        return BaseResponse.successResponse("參數校驗成功");
    }
}
/<code> 

上面源碼可以看到,testParam接口和testOrderParam兩個接口使用的註解不一樣,一個是@Valid、另一個是@Validated,兩個稍有區別,前者使得當前對象內屬性校驗生效,如果包含對象屬性,則對象屬性自身的屬性校驗無法生效,而後者註釋的對象,對象內部配合@Valid可以使得對象內部的對象屬性的屬性校驗規則生效。

請求效果

項目引入swagger2,便於演示結果:

普通參數請求

請求參數

JAVA開發中,API接口如何優雅的進行參數校驗?

響應結果:

JAVA開發中,API接口如何優雅的進行參數校驗?

請求參數我全部設置的不滿足規則,響應結果輸出了所有的校驗不通過的信息。

複雜參數請求

請求參數

JAVA開發中,API接口如何優雅的進行參數校驗?

響應結果

JAVA開發中,API接口如何優雅的進行參數校驗?

如上可以看到,商品編號屬性是OrderRequest中的productRequestList的屬性,依然能夠成功校驗,另外,productCode和productName,傳遞參數的時候都是給到的空串,由於兩者的使用的註解不一樣,其中商品名稱被攔截,商品編碼規則通過,這也是針對String類型參數時,@NotBlank與@NotNull的不同之處。

本文就簡單的介紹在這裡,有興趣的小夥伴可以訪問我的github地址,本文的源碼請點擊:https://github.com/gdspw/blog-demo

源碼的全局異常處理類還有很多其他的異常攔截處理,可供參考。

有什麼問題需要問的或者可供討論的,歡迎在文章下方評論區留言!


分享到:


相關文章: