스프링 부트를 통해서 Controller를 통해서 원하는 내용을 내려줄 수 있다.
@RequestController 는 해당 클래스는 RESTAPI를 처리하는 컨트롤러라는 것을 알려주는 Annotation이고
@RequestMapping을 통해 URI를 지정하는 Annotation이다
@GetMapping
@GetMapping(path="")를 통해서 주소를 명시적으로 알려주는 방법이 있다.
과거에는 @RequestMapping("")이런 방식으로 사용을 했었는데 이방식은 GET/POST/PUT/DELTE 를 모두 사용할 수 있어서 속성으로 지정을 해줘야한다
ex)
@RequestMapping(path="/hi",method = RequestMethod.GET)
이런식으로 하면 주소는 http://localhost:8080/hi 라는 주소를 GET method를 사용하겠다 라는 의미이다.Path Variable를 사용하기
예를 들어 변화하는 값들을 주소에 받을 예정이다
http://localhost:8080/api/get/path-variable/{name}
어떤 사용자의 이름이 변화할 수 있기 때문에 Path Variable로 받을 수 있다.
// http://localhost:8080/api/get/path-variable/{name}
@GetMapping("/path-variable/{name}")
public String pathVariable(@PathVariable String name){
System.out.println("PathVariable : "+name);
return name;
}
Method의 파라미터에 받으려는 변화하는 값을 @PathVariable로 선언을 해주면된다.
주의할 점은 @GetMapping안에 중괄호({})안의 변수명과 @PathVariable로 선언한 변수명이 동일해야한다.
개발을 하면서 변수명이 달라질 수 있고 변수명을 같게 하지 않을 수도 있다.
그런경우 @PathVariable(name="")을 통해서 동일하게 세팅을 할 수 있다
@GetMapping("/path-variable/{name}")
public String pathVariable(@PathVariable(name="name") String pathName){
System.out.println("PathVariable : "+pathName);
return pathName;
}
QueryParameter는 검색을 할 때 여러가지 매개변수인자를 이야기하는것이다.
주로 검색할 때 사용하는 것이다
형식
?key=value&key2=value2
@GetMapping(path = "query-param") public String queryParam(@RequestParam Map<String, String> queryParam) { StringBuilder sb=new StringBuilder(); queryParam.entrySet().forEach(entry -> { System.out.println(entry.getKey()); System.out.println(entry.getValue()); System.out.println();
sb.append(entry.getKey()+"="+entry.getValue()+"\n");
}
);
return sb.toString();
}
이렇게 매개변수에 queryParameter를 사용할 경우 @RequestParam이라는 애노테이션을 추가를 해야 제대로 들어감을 알 수 있다.
Map으로 매개변수를 queryParameter를 받을때는 어떤값이 들어올지몰라 하나하나 지정을 해야한다.
### QueryParameter를 이용해 명확히 값을 명시적으로 지정해서 GET하는 방법
@GetMapping("query-param2")
public String queryParam2(
@RequestParam String name,
@RequestParam String email,
@RequestParam int age
) {
System.out.println(name);
System.out.println(email);
System.out.println(age);
return name +" "+ email +" "+ age;
}
여기서도 문제가 생긴다. 변수가 지정이 되어 있을경우는 상관이없다
하지만 변수가 계속 추가가 된다면?이라는 문제점이 발생한다
Spring에서는 DTO형태로 매핑할 수 있도록 해준다
### QueryParameter를 DTO형태로 매핑하는 방법(현업에서도 자주 사용)
dto 패키지에 UserRequest라는 객체를 생성한다
public class UserRequest {
private String name;
private String email;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "UserRequest{" +
"name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
@GetMapping("query-param3")
public String queryParam(UserRequest userRequest) {
System.out.println(userRequest.getName());
System.out.println(userRequest.getEmail());
System.out.println(userRequest.getAge());
return userRequest.toString();
}
여기서는 @RequestParam이라는 애노테이션을 사용하지 않는다.
Spring에서 주소에 나오는 ?key=value&key2=value2에서 key와 value를 해당 객체에서 변수와 이름매칭을 해주게 된다.
이렇게 사용하면 변수가 추가된다거나 그럴때 객체에 들어가는 변수들을 추가하면 된다는 점에서 편리하게 수정이 가능하다.
JSON에서는 string,number,boolean,object,array형태가 올 수 있다.
JSON에서는 Snake case 단어의 구분마다 언더바(_) 를 사용하는 방법과 CamelCase를 사용하는방법을 사용한다
{
"key": "value"
}
{
"phone_number" :"010-1111-2222" //String
"age" : 10, //number
"isAgree" : false, //boolean
"user" : {
"email" : "steve@gmail.com"
"password" : "1234"
}, //object
"user_list" : [{},{},{},{}] //array
}
@RestController
@RequestMapping("/api/post")
public class PostApiController {
@PostMapping()
public void post(@RequestBody Map<String, Object> requestData) {
requestData.forEach((key, value) -> {
System.out.println("key : " + key);
System.out.println("value : " + value);
});
}
}
POST의 경우에는 매개변수에 GET과 다르게 @RequestBody를 선언해 줘야 값들을 받을 수 있다.
값은 잘 들어옴을 알 수 있지만 어떤 값을 보낼지 다 알아야하므로 Map으로 받기는 애매한 상황이다.
값을 받을 수 있도록 DTO를 작성을 한다.
public class PostRequestDto {
private String account;
private String email;
private String address;
private String password;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "PostRequestDto{" +
"account='" + account + '\'' +
", email='" + email + '\'' +
", address='" + address + '\'' +
", password='" + password + '\'' +
'}';
}
}
@RestController
@RequestMapping("/api/post")
public class PostApiController {
@PostMapping()
public void post(@RequestBody PostRequestDto postRequestDto) {
System.out.println(postRequestDto);
}
}
제대로 값이 객체를 통해서 들어온것을 확인할 수 있다.
name,age(String)으로 받을예정이고 Car(array)로 받을예정이다.
{
"name" : "steve" ,
"age" : "20" ,
"car_list" : [
{
"name" : "BMW",
"car_number" : "11가 1234"
},
{
"name" : "A4",
"car_number" : "22가 1234"
}
]
}
}
public class CarDto {
private String name;
@JsonProperty("car_number")
private String carNumber;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCarNumber() {
return carNumber;
}
public void setCarNumber(String carNumber) {
this.carNumber = carNumber;
}
@Override
public String toString() {
return "CarDto{" +
"name='" + name + '\'' +
", carNumber='" + carNumber + '\'' +
'}';
}
}
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
public class PutRequestDto {
private String name;
private int age;
private List<CarDto> carList;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<CarDto> getCarList() {
return carList;
}
public void setCarList(List<CarDto> carList) {
this.carList = carList;
}
@Override
public String toString() {
return "PutRequestDto{" +
"name='" + name + '\'' +
", age=" + age +
", carList=" + carList +
'}';
}
}
@RestController
@RequestMapping("/api/put")
public class PutApiController {
@PutMapping()
public void put(@RequestBody PutRequestDto putRequestDto){
System.out.println(putRequestDto);
}
}
@RestController
@RequestMapping("/api/delete")
public class DeleteApiController {
@DeleteMapping("/{userId}")
public void delete(
@PathVariable String userId,
@RequestParam String account) {
System.out.println(userId);
System.out.println(account);
}
}
실행결과
100
user100
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/text")
public String text(@RequestParam String account) {
return account;
}
}
을 실행시켜서 Query Parameter에 account(key), user100(value)를 추가하여 GET을 구동시키면 body에 Text형태의 user100이 response로 받아오게 되어있다
이렇게 사용하는 경우는 실무에서 거의 없을 것이다
제일 많이 사용하는 방법은 JSON이다
//JSON
@PostMapping("/json")
public User json(@RequestBody User user) {
return user;
}
이렇게 해서
이렇게 실행을 시켜봤다 이결과 request body에 있는 값들을 obejct mapper가 object로 변형시켜 method 를 실행시키고 object가 리턴되어 object mapper를 통해
결과는 JSON 형태의 Response를 받을 수 있었다.
@RestController와 다르게 @Controller 애노테이션은 HTML 리소스를 찾아 return 해주는 Controller이다.
여기서 반환값의 자료형을 String으로 한다면 자동으로 resource에 있는 html을 찾아가게되는데 이때 JSON을 어떻게 내려줄것인가? -> 해답은 ResponseEntity를 쓰는 방법과 @ResponseBody애노테이션을 이용한 방법이 있다.
@ResponseBody 애노테이션은 객체 자체를 리턴했을 때 리소스를 찾지않고 ResponseBody를 만들어서 내리겠다는 애노테이션이다.
@ResponseBody
@GetMapping("/user")
public User user() {
var user = new User();
user.setName("steve");
user.setAddress("패스트캠퍼스");
return user;
}