스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 대시보드 - 인프런 | 강의 (inflearn.com)
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의
웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., -
www.inflearn.com
HTTP 요청 메시지 - JSON
json 형식을 HelloData 객체로 바로 받을 수 있음
객체를 return하면 json 형식으로 출력
1
2
3
4
5
6
|
@ResponseBody
@PostMapping("/request-body-json-v5")
public HelloData requestBodyJsonV5(@RequestBody HelloData helloData throws IOException {
log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());
return helloData;
}
|
cs |
응답 - 정적 리소스, 뷰 템플릿
@ResponseBody 붙이면 화면에 "response/hello" 출력됨
1
2
3
4
5
|
@RequestMapping("/response-view-v2")
public String responseViewV2(Model model) {
model.addAttribute("data", "hello");
return "response/hello";
}
|
cs |
view 이름과 url 같으면 return 생략 가능
하지만, 명시성이 떨어지고 일치하는 경우가 별로 없음
1
2
3
4
|
@RequestMapping("/response/hello")
public void responseViewV3(Model model) {
model.addAttribute("data", "hello");
}
|
cs |
HTTP 응답 - HTTP API, 메시지 바디에 직접 입력
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@GetMapping("/response-body-json-v1")
public ResponseEntity<HelloData> responseBodyJsonV1() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(11);
return new ResponseEntity<>(helloData, HttpStatus.OK);
}
@ResponseStatus(HttpStatus.OK)
@ResponseBody
@GetMapping("/response-body-json-v2")
public HelloData responseBodyJsonV2() {
HelloData helloData = new HelloData();
helloData.setUsername("userA");
helloData.setAge(11);
return helloData;
}
|
cs |
@ResponseBody를 사용하면 HelloData를 바로 return 할 수 있음.
하지만, @ResponseStatus()를 어노테이션으로 지정해야하므로, HttpStatus 동적으로 변경 불가.
응답 코드를 동적으로 변경해야 한다면, V1처럼 ResponseEntity<>()를 return함
HTTP 메시지 컨버터
스프링 MVC는 다음의 경우에 HTTP 메시지 컨버터를 적용한다.
HTTP 요청: @RequestBody , HttpEntity(RequestEntity) ,
HTTP 응답: @ResponseBody , HttpEntity(ResponseEntity) ,
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 대시보드 - 인프런 | 강의 (inflearn.com)
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의
웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있
www.inflearn.com
타임리프 (Thymeleaf)
속성 변경 - th:href
th:href="@{/css/bootstrap.min.css}"
href="value1" 을 th:href="value2" 의 값으로 변경한다.
URL 링크 표현식 - @{...},
th:href="@{/css/bootstrap.min.css}"
속성 변경 - th:onclick
onclick="location.href='addForm.html'"
th:onclick="|location.href='@{/basic/items/add}'|"
리터럴 대체 - |...|
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
-> <span th:text="|Welcome to our application, ${user.name}!|">
location.href='/basic/items/add'
-> th:onclick="'location.href=' + '\'' + @{/basic/items/add} + '\''"
-> th:onclick="|location.href='@{/basic/items/add}'|"
반복 출력 - th:each
<tr th:each="item : ${items}">
변수 표현식 - ${...}
<td th:text="${item.price}">10000</td>
내용 변경 - th:text
<td th:text="${item.price}">10000</td>
URL 링크 표현식2 - @{...},
th:href="@{/basic/items/{itemId}(itemId=${item.id})}"
쿼리 파라미터 생성 가능
예) th:href="@{/basic/items/{itemId}(itemId=${item.id}, query='test')}"
생성 링크: http://localhost:8080/basic/items/1?query=test
URL 링크 간단히
th:href="@{|/basic/items/${item.id}|}"
1
2
3
4
5
6
|
<tr th:each="item : ${items}">
<td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.id}">회원id</a></td>
<td><a href="item.html" th:href="@{|/basic/items/${item.id}|}" th:text="${item.itemName}">상품명</a></td>
<td th:text="${item.price}">가격</td>
<td th:text="${item.quantity}">수량</td>
</tr>
|
cs |
상품 등록 폼
th:action에 값이 없으면 현재 url 전송
1
2
|
<form action="item.html" th:action="/basic/items/add" method="post">
<form action="item.html" th:action method="post">
|
cs |
상품 등록 처리 - @ModelAttribute
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@PostMapping("/add")
public String addItemV1(@RequestParam String itemName,
@RequestParam int price,
@RequestParam Integer quantity,
Model model) {
Item item = new Item();
item.setItemName(itemName);
item.setPrice(price);
item.setQuantity(quantity);
itemRepository.save(item);
model.addAttribute("item", item);
return "basic/item";
}
|
cs |
@ModelAttribute() 사용하면 model.addAttribute()까지 같이 해줌
1
2
3
4
5
|
@PostMapping("/add")
public String addItemV2(@ModelAttribute("item") Item item) {
itemRepository.save(item);
return "basic/item";
}
|
cs |
괄호를 지우면 클래스명 첫 글자를 소문자로 바꿔서 model.addAttribute()
1
2
3
4
5
|
@PostMapping("/add")
public String addItemV3(@ModelAttribute Item item) {
itemRepository.save(item);
return "basic/item";
}
|
cs |
@ModelAttribute 생략 가능
1
2
3
4
5
|
@PostMapping("/add")
public String addItemV4(Item item) {
itemRepository.save(item);
return "basic/item";
}
|
cs |
PRG Post/Redirect/Get
상품 등록을 완료하고 웹 브라우저의 새로고침 버튼을 클릭해보자.
상품이 계속해서 중복 등록되는 것을 확인할 수 있다.
새로고침 시 마지막에 서버에 전송한 데이터를 다시 전송
마지막 행위: POST /add
POST 처리 후 Redirect하면 마지막 요청이 GET으로 변경됨
새로고침하면 GET 호출됨
※ 주의
"redirect:/basic/items/" + item.getId() redirect에서 +item.getId() 처럼 URL에 변수를
더해서 사용하는 것은 URL 인코딩이 안되기 때문에 위험하다.
RedirectAttributes
상품 등록 후에 "저장되었습니다" 띄우기
-> Redirect 한 곳에서 처리
redirectAttributes.addAttribute()에 넣은 값으로 치환 가능
URL 인코딩 문제 해결 가능
치환 안하면 쿼리 파라미터로 넘어감
1
2
3
4
5
6
7
|
@PostMapping("/add")
public String addItemV6(Item item, RedirectAttributes redirectAttributes) {
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/basic/items/{itemId}";
}
|
cs |
'오늘 배운 것' 카테고리의 다른 글
[알고리즘] 다익스트라, 세그먼트 트리 (0) | 2021.07.13 |
---|---|
[알고리즘] 위상정렬, 프림, 크루스칼 (0) | 2021.07.12 |
[스프링 MVC 2] 타임리프 - 스프링 통합과 폼, 메시지, 국제화 (0) | 2021.07.02 |
[스프링 MVC 2] 타임리프 - 기본 기능(2) (0) | 2021.07.01 |
[스프링 MVC 1] 스프링 MVC - 기본 기능 (1) (0) | 2021.06.28 |