# [Spring Boot] 請求與回應 [TOC] |註釋|用途|使用| |-|-|-| |@Controller|將 Class 變成由 Spring 容器所管理的 Bean (Object),並且可以在內部使用 @RequestMapping。需搭配@ResponseBody,才能返回 Json 格式|class| |@RestController|將 Class 變成由 Spring 容器所管理的 Bean (Object),並且可以在內部使用 @RequestMapping。可以直接返回 Json 格式|class| |@RequestMapping|需搭配 @Controller 或 @RestController,將 url 路徑對應到方法上|class、方法| |@ResponseBody|需搭配@Controller,才能返回 Json 格式|方法| |@RequestParam|取得 url 裡面的參數|方法上的參數| |@PathVariable|取得 url 路徑的值|方法上的參數| |@RequestBody|取得 request body 的參數|方法上的參數| |@RequestHeader|取得 request header 的 header|方法上的參數| |@GetMapping|將 url 路徑對應到方法上,並限制前端只能夠使用 GET,來請求這個 url 路徑|方法| |@PostMapping|將 url 路徑對應到方法上,並限制前端只能夠使用 POST,來請求這個 url 路徑|方法| |@PutMapping|將 url 路徑對應到方法上,並限制前端只能夠使用 PUT,來請求這個 url 路徑|方法| |@Validated|若@PathVariable、@RequestParam、@RequestHeader的參數上想要使用驗證,須加上此註解|class| |@Valid|若@RequestBody的參數想要使用驗證,須加上此註解|方法上的參數| |@NotNull|表示該參數不能為 null|方法上的參數、參數| |@NotBlank|表示該參數不能為 null、且不能為空白的字串|方法上的參數、參數| |@NotEmpty|表示該參數不能為 null、且 size 必須 > 0 (使用於List、Set、Map)|方法上的參數、參數| ## @Controller 與 @RestController 差異 @Controller 需要搭配 @ResponseBody,該方法才會傳送JSON格式的資料給Client ```=Java @Controller public class myController(){ @ResponseBody @RequestMapping("/index") public String hello(){ return "hello world!"; } //不會使用JSON格式傳送資料給Client @RequestMapping("/index") public String hello(){ return "hello world!"; } } ``` @RestController 不須在方法上加@ResponseBody,即可傳送JSON格式的資料給Client ```=Java @RestController public class myController(){ @RequestMapping("/index") public String hello(){ return "hello world!"; } } ``` ## 取得請求參數 ### @RequestParam * name 指定 url 參數的名字 * required 表示此參數是否是必須的參數 * defaultValue 提前設定好參數的預設值,如果 url 裡面沒有該參數的話,就使用這個預設值 ### @PathVariable 若要取得路徑為 http://localhost:8080/test/123 內的123 ```Java @RestController public class myController(){ @RequestMapping("/test/{user}") public String test(@PathVariable String user){ // } } ``` :::warning **@RequestParam 與 @PathVariable 的差異** @RequestParam 將參數置於路徑後: http://localhost:8080/test?id=123 @PathVariable 將參數置於路徑之中: http://localhost:8080/test/123 ::: ### @RequestBody 可以將 request body 裡面的 Json 格式的參數 ,轉為 Spring Boot 中 自定義的 Java class ```Java @RestController public class myController(){ @RequestMapping("/test") public String test(@RequestBody List userlist){ //userlist是取得的Json資料 // } } ``` 註: 直接通過瀏覽器輸入url獲取不到Json物件,需要用後端或者ajax的方法請求,將Content-Type設定為application/json ### @RequestHeader * name 指定 header 內參數的名字 若 request header 內有 Content-Type: application/json (Content-Type 是用來表示 request body 的格式) ```Java @RestController public class myController(){ @RequestMapping("/test") public String test(@RequestHeader(name="Content-Type") String contentType){ // } } ``` * required 表示此 header 是否是必須的 header * defaultValue 提前設定好 header 的預設值,如果 request header 裡面沒有該 header 的話,就使用這個預設值 ## RESTful API 當你所設計的 API 符合 REST 風格時,你所設計的 API 就可以稱為是 RESTful API RESTful API 主要包含三大條件 1. **使用 http method 表示動作** http method 會對應到資料庫的 CRUD 操作 * GET-->Read * POST-->Create * PUT-->Update * DELETE-->Delete 2. **使用 url 路徑描述資源之間的階層關係**,比如 * GET /users--> 取得所有 user * GET /users/123--> 取得 user id 為 123 的 user 3. **response body 返回 json 或是 xml 格式** 註: GET 會將參數放在 url 的最後面來傳遞,POST 會將參數放在 request body 裡面來傳遞 ## 驗證請求參數 ### @Validated 若想要在加上「@PathVariable、@RequestParam、@RequestHeader」的參數上,使用 @NotNull... 這類的驗證請求參數的註解的話,則需要在這個 Class 上加上 @Validated ```Java @RestController @Validated public class UserController { @GetMapping("/users/{userId}") public String read(@PathVariable @Min(100) Integer userId){ return "檢視使用者"; } } ``` ### @Valid 若想要在加上「@RequestBody」的 student 參數裡面,使用 @NotNull... 這類的驗證請求參數的註解的話,則需要在 User 參數前面加上 @Valid ```Java @PostMapping("/users") public String cearte(@RequestBody @Valid User user){ return "新增使用者"; } ``` 以下是有使用驗證的Bean ```Java public class User{ @NotNull Integer id; @NotBlank String name; //getter、setter } ``` ### 自定義回傳的 Http Response 狀態碼 可使用 `ResponseEntity<?>` 此方法返回 Http status 類型 ```=Java! @RequestMapping("/test") public ResponseEntity<String> test(){ return ResponseEntity.status(HttpStatus.ACCEPTED); } ``` ## [補充] @Validated 無效 > 環境: > spring boot 2.7.6 + apache maven 在Controller內的參數使用 @Min 及 @Max 沒有效果 ```=java! import javax.validation.constraints.Max; import javax.validation.constraints.Min; @GetMapping(value = "/{type}/products") public ResponseEntity<ApiResponse<List<product>>> types( @PathVariable @Min(1) @Max(10) int type ) { List<product> result = productService.getAllByType(type); var response = new ApiResponse<>(SUCCESS, message, result); return ResponseEntity.ok().body(response); } ``` 原以為 validated 會包在 spring-boot-web 內,查詢後發現要另外引入 spring-boot-validated > maven central repository > https://central.sonatype.com/artifact/org.springframework.boot/spring-boot-starter-validation/2.7.6/overview 最後依專案選用 apache maven 2.7.6 的版本,在 pom.xml 加入下列程式碼即可使用 spring validated ```=xml! <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <version>2.7.6</version> </dependency> ``` ## [補充] Json 全稱為 JavaScript Object Notation,是一種檔案格式,可將資料結構化,用於網頁呈現或傳輸數據。格式包含一個 key + 一個 value,key必須使用雙引號 `""` 包覆,value的值則有以下資料類型 * 整數 * 浮點數 * 字串 * Boolean * 其他物件(如陣列) --- 參考資料 * [使用 JSON 資料](https://developer.mozilla.org/zh-TW/docs/Learn/JavaScript/Objects/JSON) * [Day 6 Spring Boot -Controller(上)](https://ithelp.ithome.com.tw/articles/10193631) * [17. Web MVC framework](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html)