REST
- HTTP URI로 해당 자원을 식별하고 HTTP method로 해당 자원에 대한 CRUD를 구분하여 자원만 리턴하는 방식
- HTML 뷰 페이지가 아닌 자원만 응답하기 때문에 웹 브라우저가 아닌 프로그램에서도 서버를 활용할 수 있다는 장점이 있다.
- Create, Insert (POST method) POST:/employee - 새 사원을 추가한다.
- Read, Select (GET method) GET:/employee/105 - 105번 사원을 조회한다.
- Update (PUT method) PUT:/employee/183 - 183번 사원을 수정한다.
- Delete (DELETE method) DELETE:/employee/170 - 170번 사원을 삭제한다.
Spring REST
- @RestController : 해당 클래스가 RestController임을 표시
- @ResponseBody : 해당 메서드가 뷰 페이지 대신 데이터를 응답한다는 것을 표시
- @RequestBody : 요청에 실려온 데이터를 바인딩해주는 어노테이션
- @PathVariable : 요청 URI의 일부분을 변수의 값으로 활용할 수 있다. (일반 컨트롤러에서도 사용 가능)
@RestController
- 일반 컨트롤러와 다르게 다음 뷰를 가리키는 대신 데이터를 응답한다.
- 컨트롤러의 내부 메서드의 리턴 타입은 뷰를 찾아가는 방식이 아니라 사용자에게 응답할 데이터의 타입을 의미한다.
- 주로 JSON 또는 XML 형식으로 응답하게 된다.
jackson-databind + jackson-dataformat-xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.15.2</version>
</dependency>
- @RestController에서 자바빈 객체(dto)를 리턴하면 알아서 JSON(또는 XML) 형식으로 변환해 응답해주는 라이브러리
예시)
package com.ezen.springrest.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import lombok.extern.log4j.Log4j;
@RequestMapping("/restful") // 공통되는 주소는 class 쪽으로 뺄 수 있다.
@Log4j
@RestController
public class RestSampleController {
// @RestController를 추가한 컨트롤러는
// 내부 메서드의 리턴 타입의 의미가 @Controller와 달라진다.
@GetMapping(value = "/value1", produces = "text/plain; charset=UTF-8")
public String value1() {
log.info("hello!");
return "<h1>Hello, world! 한글도 잘 갑니다</h1>";
}
@GetMapping(value = "/value2", produces = "text/html; charset=UTF-8")
public String value2() {
log.info("hello!");
return "<h1>Hello, world! 한글도 잘 갑니다</h1>";
}
}
JSON으로 데이터 응답하기(상세 [Spring] JSON 참고)
package com.ezen.springrest.controller;
import org.json.simple.JSONObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import dto.Employee;
import lombok.extern.log4j.Log4j;
@RequestMapping("/restful") // 공통되는 주소는 class 쪽으로 뺄 수 있다.
@Log4j
@RestController
public class RestSampleController {
@GetMapping(value = "/value3", produces = "application/json; charset=UTF-8")
public String value3() {
// DB에서 꺼낸 데이터라고 가정
Employee emp = new Employee();
emp.setFirst_name("steven");
emp.setLast_name("king");
emp.setSalary(24000);
JSONObject obj = new JSONObject();
obj.put("first_name", emp.getFirst_name());
obj.put("last_name", emp.getLast_name());
obj.put("salary", emp.getSalary());
return obj.toJSONString();
}
}
Jackson 이용해서 JSON / XML 응답하기
package com.ezen.springrest.controller;
import org.json.simple.JSONObject;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import dto.Employee;
import lombok.extern.log4j.Log4j;
@RequestMapping("/restful") // 공통되는 주소는 class 쪽으로 뺄 수 있다.
@Log4j
@RestController
public class RestSampleController {
@GetMapping(value = "/employee/json", produces = MediaType.APPLICATION_JSON_VALUE)
public Employee emp1() {
Employee e = new Employee();
e.setFirst_name("철수");
e.setLast_name("김");
e.setSalary(5000);
return e;
}
@GetMapping(value = "/employee/xml", produces = MediaType.APPLICATION_XML_VALUE)
public Employee emp2() {
Employee e = new Employee();
e.setFirst_name("철수");
e.setLast_name("김");
e.setSalary(5000);
return e;
}
}
ResponseEntity 사용법
package com.ezen.springrest.controller;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import dto.Employee;
import lombok.extern.log4j.Log4j;
@RequestMapping("/restful") // 공통되는 주소는 class 쪽으로 뺄 수 있다.
@Log4j
@RestController
public class RestSampleController {
@GetMapping("/resp1")
public ResponseEntity<String> resp1() {
// ResponseEntity.ok() : 상태 코드 200인 응답 인스턴스를 생성한다. (마저 만들어야 함)
ResponseEntity<String> myResponse = ResponseEntity.ok().contentType(MediaType.TEXT_HTML).body("<h1>My Response</h1>");
// ResponseEntity.ok(T body) : 상태 코드 200의 응답 인스턴스를 반환한다.
// ResponseEntity<String> myResponse = ResponseEntity.ok("<h1>data~</h1>");
return myResponse;
}
@GetMapping("/resp2")
public ResponseEntity<String> resp2() {
ResponseEntity<String> myResponse = ResponseEntity.status(HttpStatus.NOT_FOUND)
.contentType(MediaType.parseMediaType("text/plain; charset=UTF-8"))
.body("<h3>한글 잘 갈듯</h3>");
return myResponse;
}
@GetMapping("/resp3")
public ResponseEntity<String> resp3() throws ParseException {
ResponseEntity<String> myResponse = ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(new JSONParser().parse("{\"name\":\"박민수\", \"age\":22}").toString());
return myResponse;
}
}
'Spring' 카테고리의 다른 글
[Spring] 에러 처리 컨트롤러 (0) | 2023.07.13 |
---|---|
[Spring] JSON (0) | 2023.07.11 |
[Spring] Log4jdbc (0) | 2023.07.11 |
[Spring] 프로젝트 계층 분리 (0) | 2023.07.11 |
[Spring] Mybatis (0) | 2023.07.06 |