# RequestParameter

參考資料:(<https://www.baeldung.com/spring-request-param>) ModifyDate:2019/03/02

**@RequestParam 和 屬性，還有 @RequestParam & @PathVariable 的區別**

## RequestMapping

參考資料:(<https://www.baeldung.com/spring-requestmapping>)

```
@RequestMapping(value = "/ex/foos", method = RequestMethod.GET)
@ResponseBody
public String getFoosBySimplePath(){
    return "Get some Foos";
}
```

## 簡單映射 A Simple Mapping (如何接到 QueryString 的參數)

QueryString 的 **key** 和程式內的 **變數名稱** 相同，則可以直接Mapping

```
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam String id) {
    return "ID: " + id;
}
```

```
http://localhost:8080/api/foos?id=abc
----
ID: abc
```

## 指定請求參數 Specifying the Request Parameter Name

如果希望 QueryString 的 **key** 和程式內的 **變數名稱** 不同，則可以使用 **name** 這個屬性進行配置。

```
@PostMapping("/api/foos")
@ResponseBody
public String addFoo(@RequestParam(name = "id") String fooId, @RequestParam String name) { 
    return "ID: " + fooId + " Name: " + name;
}
```

這三個都可以達到同樣效果

```
@RequestParam(name = "id") String fooId
@RequestParam(value = "id") String fooId
@RequestParam("id") String fooId
```

## 製作可選的請求參數 Making an Optional Request Parameter

通常 @RequestParam 會默認為必填，這樣倘若沒有打參數，就會跳出錯誤

```
GET /api/foos HTTP/1.1
-----
400 Bad Request
Required String parameter 'id' is not present
```

所以我們可以將配置，改為可選

```
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false) String id) { 
    return "ID: " + id;
}
```

這樣，不論是

```
http://localhost:8080/api/foos?id=abc
----
ID: abc



http://localhost:8080/api/foos
----
ID: null
```

該呼叫都可以正常調用，但是沒有傳的參數會綁定為Null。

## 請求參數的默認值 A Default Value for the Request Parameter

利用屬性 **defaultValue** 設置 默認值

```
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(defaultValue = "test") String id) {
    return "ID: " + id;
}
```

```
http://localhost:8080/api/foos
----
ID: test


http://localhost:8080/api/foos?id=abc
----
ID: abc
```

當設置 defaultValue 這個屬性時，就像 required = false，而事實上 也的確被設置為 false。

## 映射所有參數 Mapping All Parameters

直接將 QueryString 的所有參數 key,value ，都放到一個 Map 裡

```
@PostMapping("/api/foos")
@ResponseBody
public String updateFoos(@RequestParam Map<String,String> allParams) {
    return "Parameters are " + allParams.entrySet();
}
```

```
curl -X POST -F 'name=abc' -F 'id=123' http://localhost:8080/api/foos
-----
Parameters are {[name=abc], [id=123]}
```

```
http://localhost:8080/api/foos?id=12&magic=Brian
-----
Parameters are [id=12, magic=Brian]
```

## 映射多值參數 Mapping a Multi-Value Parameter

QueryString 的 一個 key 可以有多個 value

```
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam List<String> id) {
    return "IDs are " + id + " size = " + id.size();
}
```

分別可以使用下列兩種

```
http://localhost:8080/api/foos?id=1,2,3
----
IDs are [1, 2, 3] size = 3

http://localhost:8080/api/foos?id=1&id=4
----
IDs are [1, 4] size = 2
```

但是不可以同時使用

```
http://localhost:8080/api/foos?id=1,2,3&id=4
-----
IDs are [1,2,3, 4] size = 2
```

## @RequestParam vs @PathVariable

@RequestParam 和 @PathVariable 都可以從URI提取值

### 查詢參數 & URI路徑

@RequestParam 是從查詢參數(QueryString) @PathVariable 是從URI路徑(ResourcePath)

@PathVariable

```
@GetMapping("/foos/{id}")
@ResponseBody
public String getFooById(@PathVariable String id) {
    return "ID: " + id;
}
```

```
http://localhost:8080/foos/abc
----
ID: abc
```

@RequestParam

```
@GetMapping("/foos")
@ResponseBody
public String getFooByIdUsingQueryParam(@RequestParam String id) {
    return "ID: " + id;
}
```

```
http://localhost:8080/foos?id=abc
----
ID: abc
```

### 編碼與精確值

@PathVariable 是從URI路徑 獲得參數，所以不會被編碼。 @RequestParam 則會被編碼。

@PathVariable

```
http://localhost:8080/foos/ab+c
----
ID: ab+c
```

@RequestParam

```
http://localhost:8080/foos?id=ab+c
----
ID: ab c
```

### 可選值

@PathVariable 從 Spring 4.3.3 開始，required 這個屬性讓其變得可選。

**用大括號去配置多個路徑**

```
@GetMapping({"/myfoos/optional", "/myfoos/optional/{id}"}) //注意大括號
@ResponseBody
public String getFooByOptionalId(@PathVariable(required = false) String id){
    return "ID: " + id;
}
```

```
http://localhost:8080/myfoos/optional/abc
----
ID: abc

http://localhost:8080/myfoos/optional
----
ID: null
```

**當使用 @PathVariable 的可選屬性時，要注意路徑衝突**
