在後臺對前端提交的參數驗證是必須的。Spring Boot 內置了相關參數校驗。
1、添加依賴
使用的是Spring Boot 2.7版本,經過測試需要安裝 spring-boot-starter-validation 依賴。如果 pom 沒有從 parent 繼承,需要添加版本號。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
2、 @RequestParam註解參數校驗
前後端參數提交的方式很多,一般使用 @RequestParam ,@RequestBody註解自動獲取參數,有關這兩者的區別參考:SpringBoot中使用註解@RequestParam與 @RequestBody區別
對@RequestParam的參數校驗如下:
controller上添加 @Validated 註解,參數前添加對應註解。
@Validated @RestController @RequestMapping("/load") public class PayloadController { @PostMapping("manage") public ResponseWrapper postEarthStation( @RequestParam("id") @Min(0) @Max(127) int id, ...... ) { ......return reply.equals("success") ? ResponseWrapper.success : ResponseWrapper.fail; } }
3、@RequestBody註解參數校驗
@RequestBody 一般對 content-type: application/json 類型的參數進行校驗,需要定義一個實體類,字段和前端參數需要一一對應。
定義實體類,並對實體類字段進行校驗。
public class TmParamEntity { @NotNull(message = "satId字段不能爲空") private int satId; ...... }
需要添加兩個註解: controller加上@Validated註解,參數前添加@Valid註解。
@Validated @RestController @RequestMapping("tele") public class TelemetryController { @PostMapping("postData") public ResponseWrapper postTmData(@RequestBody @Valid List<TmParamEntity> tmParamEntity, HttpServletRequest httpServletRequest) { ...... return ResponseWrapper.success; } }
需要注意的是,如果前端傳遞參數是一個對象,那麼參數類型就是實體類型,如果前端傳遞的是一個數組Array,這裏需要使用 List<TmParamEntity> 類型。添加 @Valid註解,即可使參數校驗生效。參數的反序列化工作,Spring 內置了Jackson 自動處理。如果字段沒對上,會報錯。
4、直接讀取InputStream
有時我們需要無需藉助 Jackson反序列化,直接從 httpServletRequest 拿到參數,有兩種方法:
InputStreamReader inputStreamReader = new InputStreamReader(httpServletRequest.getInputStream()); char[] chars = new char[1024]; StringBuilder stringBuilder = new StringBuilder(); while ((inputStreamReader.read(chars)) != -1) { stringBuilder.append(new String(chars).trim()); }
StringBuilder stringBuilder = new StringBuilder(); try (BufferedReader bufferedReader = httpServletRequest.getReader()) { String lineString = bufferedReader.readLine(); while (lineString != null) { stringBuilder.append(lineString); lineString = bufferedReader.readLine(); } }
前者從 InputStreamReader 中讀,後者直接從 BufferedReader 中讀數據。需要注意的是,無論是哪種讀取方式,stream數據只能讀一次。例如使用了Jackson,再用 bufferedReader 去讀,返回的是個null。注意到使用了try(resource) 對網絡資源進行釋放。