Spring 숙련 강의
숙련 강의 1주차를 듣고 있지만 밀린 TIL을 쓰도록 하겠습니다..
http://localhost:8080/request-params?key1=value1&key2=value2
@Slf4j
@Controller
public class RequestParamController {
@GetMapping("/request-params")
public void params( HttpServletRequest request,
HttpServletResponse response ) throws IOException {
String key1Value = request.getParameter("key1");
String key2Value = request.getParameter("key2");
log.info("key1Value={}, key2Value={}", key1Value, key2Value);
response.getWriter().write("success");
}
}
response.getWriter().write()key1Value=value, key2Value=value2
HTTP Request Body에 쿼리 파라미터 형태로 전달하는 방법
HTTP Request
POST /form-data
content-type: application/x-www-form-urlencoded
key1=value1&key2=value2
@Slf4j
@Controller
public class RequestBodyController {
@PostMapping("/form-data")
public void requestBody( HttpServletRequest request,
HttpServletResponse response
) throws IOException {
String key1Value = request.getParameter("key1");
String key2Value = request.getParameter("key2");
log.info("key1Value={}, key2Value={}", key1Value, key2Value);
response.getWriter().write("success");
}
}
HttpServletRequest.getParameter(”key”);를 사용하면 Query Parameter, HTML Form Data 두가지 경우 모두 데이터 형식(key=value)이 같기 때문에 해당값에 접근할 수 있음
key1=value1&key2=value2
@Getter
@Setter
public class Board {
private String title;
private String content;
}
@Slf4j
@Controller
public class RequestBodyController {
// JSON을 객체로 변환해주는 Jackson 라이브러리
private ObjectMapper objectMapper = new ObjectMapper();
@PostMapping("/request-body")
public void requestBody(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
ServletInputStream inputStream = request.getInputStream();
String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("messageBody={}", messageBody);
Board board = objectMapper.readValue(messageBody, Board.clss);
log.info("board.getTitle()={}, board.getContent()={}", board.getTitle(), board.getContent());
response.getWriter().write("success");
}
}
{
"title": "value1",
"content": "value2"
}
messageBody={
"title": "value1",
"content": "value2"
}
board.getTitle()=value1, board.getContent()=value2
JSON을 Java 객체로 변환하려면 Jackson과 같은 라이브러리를 사용해야 하고 Spring Boot에포함되어 있음
startLine에서 ?뒤에 오는 URL을 Query String, Query Parameter, Request Param이라 함
@Slf4j
@Controller
public class RequestParamControllerV2 {
@ResponseBody
@GetMapping("/v1/request-param")
public String requestParamV1 (
@RequestParam("name") String userName,
@RequestParam("age") int userAge
) {
// logic
log.info("name={}", userName);
log.info("age={}", userAge);
return "success";
}
}
@Controller + @ResponseBody@RequestParam@RequestParam(”속성값”) localhost:8080/v2/request-param?name=sparta&age=100
name=sparta
age=100
ex) @RequestParam("name") String name
ex) String name
@RequestParam(required=false) 필수 여부 속성이 default로 설정위의 방식은 권장x
@ResponseBody
@GetMapping("/v4/request-param")
public String requestParam (
@RequestParam(required = true) String name, // 필수
@RequestParam(required = false) int age // 필수가 아님) {
// logic
log.info("name={}", name);
log.info("age={}", age);
return "success";
}
default 속성 적용
@ResponseBody
@GetMapping("/v5/request-param")
public String requestParam (
@RequestParam(required = true, defaultValue = "sparta") String name,
@RequestParam(required = false, defaultValue = "1") int age
) {
// logic
log.info("name={}", name);
log.info("age={}", age);
return "success"
}
Map 사용
@ResponseBody
@GetMapping("/v6/request-param")
public String requestParamV6(
@RequestParam Map<String, String> map
) {
// logic
log.info("name={}", map.get("name"));
log.info("age={}", map.get("age"));
return "success";
}
key=value)로 조회가 가능@RequestParam 의 Mapping을 사용하게 되면 객체를 생성하는 코드가 포함된다.
ex)
@Data
public class Tutor {
private String name;
private int age;
}
@Controller
public class ModelAttributeController {
@ResponseBody
@PostMapping("/v1/tutor")
public String requestParamV1(
@RequestParam String name,
@RequestParam int age
) {
Tutor tutor = new Tutor();
tutor.setName(name);
tutor.setAge(age);
return "tutor name = " + name + " age = " + age;
}
}
@ModelAttribute 는 해당 과정을 자동화
@ResponseBody
@PostMapping("/v2/tutor")
public String modelAttributeV2(
@ModelAttribute Tutor tutor
) {
String name = tutor.getName();
int age = tutor.getAge();
return "tutor name = " + name + " age = " + age;
}
name 이면 setName(value); 메서드를 호출생략 가능
Request Body의 Data를 바인딩하는 방법
HTTP Request Body에 Data가 전송되는 경우 HttpMessageConverter를 통해 바인딩
@Slf4j
@Controller
public class RequestBodyStringController {
@PostMapping("/v1/request-body-text")
public void requestBodyTextV1(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
ServletInputStream inputStream = request.getInputStream();
String bodyText = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
response.getWriter().write("response = " + bodyText);
}
}
@PostMapping("/v2/request-body-text")
public void requestBodyTextV2(
InputStream inputStream,
Writer responseWriter
) throws IOException {
String bodytext = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
responseWriter.write("response = " + bodyText);
}
@PostMapping("/v3/request-body-text")
public HttpEntity<String> requestBodyTextV3(HttpEntity<String> httpEntity) {
// HttpMessageConverter가 동작해서 아래 코드가 동작하게됨
String body = httpEntity.getBody();
return new HttpEntity<>("response = " + body); // 매개변수 = Body Message
}
HttpEntity는 HTTP Header, Body 정보를 편리하게 조회할 수 있도록 만들어줌
RequestEntity<>ResponseEntity<>ex)
@Controller
public class RequestBodyStringController {
@PostMapping("/v4/request-body-text")
public HttpEntity<String> requestBodyTextV4(RequestEntity<String> httpEntity) {
// HttpMessageConverter가 동작해서 아래 코드가 동작하게됨
String body = httpEntity.getBody();
// url, method 사용 가능
return new ResponseEntity<>("response = " + body, HttpStatus.CREATED); // Body Data,상태코드
}
}
Spring에서 @RequestBody, @ResponseBody 어노테이션을 사용하면 각각 Request, Response 객체의 Body에 편하게 접근 가능
ex)
@Controller // @RestController = @Controller + @ResponseBody
public class RequestBodyStringController {
@ResponseBody
@PostMapping("/v5/request-body-text")
public String requestBodyTextV5(
@RequestBody String body,
@RequestHeader HttpHeaders headers
) {
// HttpMessageConverter가 동작해서 아래 코드가 동작하게됨
String bodyMessage = body;
return "request header = " + headers + " response body = " + bodyMessage;
}
}
@Data
public class Tutor {
private String name;
private int age;
}
@RestController
public class JsonController {
private ObjectMapper objectMapper = new ObjectMapper();
@PostMapping("/v1/request-body-json")
public void requestBodyJsonV1(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
// request body message를 Read
ServletInputStream inputStream = request.getInputStream();
// UTF-8 형식의 String으로 변환한다.
String requestBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
// String requestBody를 ObjectMapper를 사용하여 변환 "{\"name\":\"wonuk\", \"age\":10}"
Tutor tutor = objectMapper.readValue(requestBody, Tutor.class);
// 응답
response.getWriter().write("tutor" + tutor);
}
}
@RestController
public class JsonController {
private ObjectMapper objectMapper = new ObjectMapper();
@PostMapping("/v2/request-body-json")
public String requesBodytJsonV2(@RequestBody String requestBody) throws IOException {
Tutor tutor = objectMapper.readValue(requestBody, Tutor.class);
return "tutor.getName() = " + tutor.getName() + "tutor.getAge() = " + tutor.getAge();
}
}
@RestController
public class JsonController {
@PostMapping("/v3/request-body-json")
public String requestBodyJsonV3(@RequestBody Tutor tutor) {
Tutor requestBodyTutor = tutor;
return "tutor = " + requestBodyTutor;
}
}
@RequestBody 어노테이션을 사용하면 Object를 Mapping할 수 있음HttpEntity<>, @RequestBody를 사용하면 HTTPMessageConverter가 Request Body의 Data를 개발자가 원하는 String이나 Object로 변환@RestController
public class JsonController {
@PostMapping("/v5/request-body-json")
public String requestBodyJsonV5(
HttpEntity<Tutor> httpEntity
) {
// 값을 꺼내서 사용해야한다!
Tutor tutor = httpEntity.getBody();
return "tutor.getName() = " + tutor.getName() + " tutor.getAge() = " + tutor.getAge();
}
}
@Controller
public class JsonController {
@ResponseBody
@PostMapping("/v6/request-body-json")
public Tutor requestJson(@RequestBody Tutor tutor) {
return tutor;
}
}
HttpMessageConverter가 동작MappingJackson2HttpMessageConverter 적용/static/public/META-INF/resourcessrc/main/resources/static src/main/resources/static/hello/world.html 디렉토리 구조라면http://localhost:8080/hello/world.html URL로 리소스에 접근이 가능 src/main/resources/templates)를 설정ThymeleafViewResolver와 필요한 Spring Bean들이 자동으로 등록@ResponseBody 가 없으면 View Resolver가 실행되며 View를 찾고 Renderingjava
@Controller
public class ViewTemplateController {
@RequestMapping("/response-view")
public String responseView(Model model) {
// key, value
model.addAttribute("data", "sparta");
return "thymeleaf-view";
}
}
html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
<h1>Thymeleaf</h1>
<h2 th:text="${data}"></h2>
</body>
</html>
@Controller
public class ViewTemplateController {
// thymeleaf-view.html 과 Mapping된다.
@RequestMapping("/thymeleaf-view")
public void responseViewV2(Model model) {
model.addAttribute("data", "sparta");
}
}
REST API를 만드는 경우 Server에서 Client로 HTML을 전달하는 방식이 아닌 HTTP Message Body에 직접 Data를 JSON 형식으로 담아 전달
@Controller
public class ResponseBodyController {
@GetMapping("/v1/response-body")
public void responseBodyV1( HttpServletResponse response) throws IOException {
response.getWriter().write("data");
}
}
@GetMapping("/v2/response-body")
public ResponseEntity<String> responseBodyV2() {
return new ResponseEntity<>("data", HttpStatus.OK);
}
@Data
@NoArgsConstructor // 기본 생성자
@AllArgsConstructor // 전체 필드를 인자로 가진 생성자
public class Tutor {
private String name;
private int age;
}
// TEXT 데이터 통신
@ResponseBody
@GetMapping("/v3/response-body-text")
public String responseBodyText() {
return "data"; // HTTP Message Body에 "data"
}
// JSON 데이터 통신
@ResponseBody
@GetMapping("/v3/response-body-json")
public Tutor responseBodyJson() {
Tutor tutor = new Tutor("wonuk", 100);
return tutor; // HTTP Message Body에 Tutor Object -> JSON
}
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/v4/response-body")
public Tutor responseBodyV4() {
Tutor tutor = new Tutor("wonuk", 100);
return tutor;
}
@ResponseBody
@GetMapping("/v5/response-body")
public ResponseEntity<Tutor> responseBody() {
Tutor tutor = new Tutor("wonuk", 100);
return new ResponseEntity<>(tutor, HttpStatus.OK);
}
ResponseEntity<>두 번째 파라미터에 Enum을 사용하여 상태 코드를 바꿀 수 있음뭔가 너무 집중하고 생각해서 그런가 에너지 소모가 많이 되는 것 같다. 아무래도 처음 배우는 부분이라 더 놓치지 않고 하려다 보니 그런 것 같기도 하고 아니면 너무 많은 지식이 들어와서 그런 것 같기도 하고 잘 모르겠다. 주말에 복습을 제대로 한번 해야 할 것 같다. 🥕🥕