跳转至

一般方式

@RestController
public class StudentController {
    @PostMapping("/students")
    public String create(@RequestBody Student student) {
        if(student.getId() == null) {
            throw new RuntimeException("id 不可為 null");
        }
        return "執行資料庫的 Create 操作";
    }
}
Talend API Tester

當我們request body 只傳了name 沒有 id時

{
    "name": "ts"
}

驗證請求參數 pom.xml 設定

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
提醒: Spring Boot 2.3 之後的才需要額外去加上這個validation

@Valid

對要驗證的參數 加上 @NotNull

代表說這個id的值不可以為null

這樣就可以去檢查id 這個請求參數的值了

import javax.validation.constraints.NotNull;
public class Student {
    @NotNull  // 要選 javax.validation.constraints 這個package
    Integer id;
}

在這邊要加上 @Valid 這樣 vo 的 @NotNull 才會生效

@RestController
public class StudentController {
    @PostMapping("/students")
    public String create(@RequestBody @Valid Student student) {
        return "執行資料庫的 Create 操作";
    }
}

Talend API Tester 少了一個id 結果會怎麼樣?

request body

{
    "name": "ts"
}

console: [Field error in object 'student' on field 'id': rejected value [null];

2023-02-05 14:38:17.616 WARN 5272 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : 
Resolved [org.springframework.web.bind.MethodArgumentNotValidException: 
Validation failed for argument [0] in public java.lang.String com.example.demo.StudentController.create(com.example.demo.Student): 
[Field error in object 'student' on field 'id': rejected value [null]; 
codes [NotNull.student.id,NotNull.id,NotNull.java.lang.Integer,NotNull]; 
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [student.id,id]; 
arguments []; default message [id]]; default message [不得是空值]] ]

content-type 錯誤

Talend API Tester

如果沒有加上Content-Type:application/json

Spring Boot 無法判斷是request body 是json格式 會跳415

在header 加上 Content-Type:application/json

console:

2023-02-05 14:09:29.639  WARN 9992 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : 
Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: 
Content type 'text/plain;charset=UTF-8' not supported]

json 格式錯誤

Talend API Tester

request body

{
    "id": 36  // 這裡少了一個逗號
    "name": "ts"
}

console:

2023-02-05 14:36:10.232  WARN 5272 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : 
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: 
JSON parse error: Unexpected character ('"' (code 34)): was expecting comma to separate Object entries; 
nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('"' (code 34)): 
was expecting comma to separate Object entries<EOL> at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); 
line: 3, column: 4]]

常用的 驗證請求參數的註解

@NotNull 不能為null
@NotBlank 不能為null ,且不能空白的字串 , 用在驗證String 類型的參數上
@NotEmpty 不能為null ,且size必須>0 , 用在驗證集合類型 (List ,Set ,Map) 的參數上
@Min 值必須 >= value , 用在驗證數字類型的參數上
@Max 值必須 <= value , 用在驗證數字類型的參數上

@NotBlank 測試

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
public class Student {
    @NotNull
    Integer id;
    @NotBlank
    String name;
}

Talend API Tester

request body

{
    "id": 36
}
{
    "id": 36,
    "name": ""
}
{
    "id": 36,
    "name": "    "
}

console:

2023-02-05 14:47:17.182 WARN 11184 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : 
Resolved [org.springframework.web.bind.MethodArgumentNotValidException: 
Validation failed for argument [0] in public java.lang.String com.example.demo.StudentController.create(com.example.demo.Student): 
[Field error in object 'student' on field 'name': 
rejected value [null]; codes [NotBlank.student.name,NotBlank.name,NotBlank.java.lang.String,NotBlank]; 
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [student.name,name]; 
arguments []; default message [name]]; default message [不得空白]] ]

@NotEmpty 測試

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
public class Student {
    @NotNull
    Integer id;
    @NotBlank
    String name;

    @NotEmpty 
    List<String> courseList;
}

Talend API Tester

request body

{
    "id": 36,
    "name": "ts"
}
console: courseList is null

{
    "id": 36,
    "name": "ts"
    "courseList":[]
}

console: courseList 是空集合

{
    "id": 36,
    "name": "ts"
    "courseList":["math"]
}

因為size>0 ,所以通過了檢查

可以同時加上多個驗證請求參數的註解

import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
public class Student {
    @NotNull
    @Min(1000)
    Integer id;
}

其他 驗證請求參數的註解

@Size(min ,max) min <= 字串長度 or 集合的size <= max ,可以只設定 max 或 min
@Email 必須符合電子郵件的格式
@Pattern(regexp) 必須符合正規表達式的regexp
@Past 必須比當前時間早 ,也就是被註解的參數必須是以前的時間
@Future 必須比當前時間晚 ,也就是被註解的參數必須是未來的時間
@AssertTrue 必須為 true ,用在驗證boolean 類型的參數上
@AssertFalse 必須為 false ,用在驗證boolean 類型的參數上
@Null 必須為null

總結

驗證請求參數的註解 分成兩種

@Valid + @驗證請求參數

public class Student {
    @NotNull
    @Min(1000)
    Integer id;
}
@RestController
public class StudentController {
    @PostMapping("/students")
    public String create(@RequestBody @Valid Student student) { // 驗證請求參數的註解 @Valid
        return "執行資料庫的 Create 操作";
    }
}

@Validated + @驗證請求參數

直接把驗證請求參數寫在裡面 要讓裡面註解的 @Min(100) 生效 需要在最上面加上 @Validated

@RestController
@Validated
public class StudentController {
    @GetMapping("/students/{studentId}")
    public String read(@PathVariable @Min(100) Integer studentId) { // 可以直接使用 @Min(100)
        return "執行資料庫的 Read 操作";
    }
}

http status code

用來表示這次http 請求的結果為何

可以根據首位數字分成五大類

1xx: 資訊

2xx: 成功

200 OK 請求成功
201 Created 請求成功且新的資源成功被創建 ,通常用在POST 的response
202 Accepted 請求已經接受 , 但尚未處理完成

3xx: 重新導向

301 Moved Permanently 永久性重新導向 , 新的 url 應放在 response header 的 “Location” 中返回 , 通常會用在網頁班加上
302 Found 臨時重新導向 , 新的臨時性的 url 應放在 response header 的 “Location” 中返回

4xx: 前端請求錯誤

400 Bad Request 前端的請求參數有錯誤 (ex: 前端傳給後端的參數名稱不同 、請求格式有問題)
401 Unauthorized 沒有通過身份驗證
403 Forbidden 請求背後端拒絕 , 通常是權限不足導致的
404 Not Found 網頁不存在 , 可能是資源被移走或是 url 輸入錯誤

5xx: 後端處理有問題

500 Internal Server Error 後端在執行程式時發生錯誤 , 可能是程式內有bug 導致的
503 Service Unavailable 由於臨時維護或是流量太大 , 後端目前沒有辦法處理請求
504 Gateway Timeout 請求超時

Spring Boot 預設返回的 http 狀態碼

正常執行 test 方法 ,返回200

@RestController
public class MyController5 {
    @RequestMapping("/test")
    public String test() {
        return "Hello World";
    }
}

噴出 exception 返回 500

@RestController
public class MyController5 {
    @RequestMapping("/test")
    public String test() {
        throw new RuntimeException();
    }
}