[스프링 MVC 1편] 7 - (3) 상품 목록 - 타임리프
* 스프링 입문 = window, 스프링 MVC 1편 = Mac 으로 진행합니다
* 섹션7 부터는 자바 17 버전으로 진행합니다
* 진도 : 섹션7 - (4) ~ (6)
* : 자바 클래스명, : 코드, : 단축키
1. 상품서비스 HTML
해당 부분은 강의를 참고해주세요 간단해서 넘어갑니다 ~
<참고>
이렇게 정적 리소스가 공개되는 /resources/static 폴더에 HTML을 넣어두면 실제 서비스에서도 공개된다
(지금처럼 공개할 필요없는 HTML을 두는 것은 주의)
2. 상품목록 - 타임리프
1) 컨트롤러 만들기
[ java/hello/itemservice/web/basic/BasicItemController ]
@Controller
@RequestMapping("/basic/items")
@RequiredArgsConstructor
public class BasicItemController {
private final ItemRepository itemRepository;
@GetMapping
public String items(Model model){
List<Item> items = itemRepository.findAll();
model.addAttribute("items", items);
return "basic/items";
}
@PostConstruct
public void init(){
itemRepository.save(new Item("itemA", 10000,10));
itemRepository.save(new Item("itemB", 20000,20));
}
}
- @Controller
- 요청 정보 매핑 @RequestMapping
- 요청 정보를 매핑 (해당 URL이 호출되면 이 메서드가 호출 )
- @RequiredArgsConstructor
- (command+N)_Constuctor 클릭 - @Autowired(= 생성자 하나면 생략가능) 넣은 코드의 줄임버전
- 컨트롤러가 스프링빈에 등록되면서 스프링빈에 리포지토리 주입된다
- 리포지토리 생성 private final ~
- 모델 객체 생성 public String ~ (Model model)
- 목록 전체 조회 List<Item> ~ findAll (option + command +v)
- Model에 데이터 추가 .addAttribute()
- 뷰 반환
- @Controller를 사용하면서 String으로 반환하면 [반환값 = 뷰의 논리적이름]
- 테스트 데이터 임의로 넣어보기 @PostContructor ~
2) 뷰 화면 타임리프로 만들기
위 컨트롤러에서 임의로 정한 테스트 데이터가 출력될 수 있도록 타임리프 만들어보자!
- resources/static/css에 bootstrap 파일넣기 (강의 참고)
- resources/static/html에 add, edit, item, items 파일넣기 (강의 참고)
- [resources/templates/basic/items]에서 타임리프 영역 수정하기 (강의 참고)
타임리프 사용 선언
- <html xmlns:th="http://www.thymeleaf.org">
속성 변경 - 절대 경로 추가
- th:href="@{/css/bootstrap.min.css}"
타임리프 뷰 템플릿을 거치게 되면 기존의 href를 날리고 설정한 th:xxx 값으로 동적 변경해 실행
URL 링크 표현식
- @{...} : URL 링크
속성 변경 - 상품 등록 폼으로 이동
- th:onclick="|location.href='@{/basic/items/add}'|"
리터럴 대체
- |...|: + 없이 문자와 표현식 이어주기 가능
반복 출력
- th:each
- <tr th:each="item : ${items}">
모델에 있는 items 데이터 item 변수에 넣기
변수 표현식
- ${...}
내용 변경
- th:text
- <td th:text="${item.price}">10000</td>
10000을 ${item.price} 의 값으로 변경
URL 링크 표현식2
- th:href="@{/basic/items/{itemId}(itemId=${item.id})}"
< 예시 >
<td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}" th:text="${item.id}">회원id</a></td>
- : 기존 경로
- : 렌더링 되면 열리는 치환 링크 경로
- : 데이터 들어가는 부분 (변수)
★ 순수 HTML을 그대로 유지하면서 뷰 템플릿도 사용할 수 있는 타임리프를 네츄럴 템플릿 (natural templates)라 한다
3. 상품 상세
1) 컨트롤러에 추가
[ java/hello/itemservice/web/basic/BasicItemController ]
@GetMapping("/{itemId}")
public String item(@PathVariable("itemId") long itemId, Model model){
Item item = itemRepository.findById(itemId);
model.addAttribute("item",item);
return "basic/item";
}
- @PathVariable ()
- 넘어온 상품ID로 상품을 조회하고, 모델에 담아두고 뷰 템플릿 호출
- itemId, 모델 객체 생성 public String ~ (Model model)
- id로 찾아서 상품 꺼내기 itemRepository.findById ~ (option + command +v)
- Model에 데이터 추가 .addAttribute()
- 뷰 반환
- @Controller를 사용하면서 String으로 반환하면 [반환값 = 뷰의 논리적이름]
2) 뷰 화면 타임리프로 만들기
- [resources/templates/basic/item]에서 타임리프 영역 수정하기 (강의 참고)
타임리프 사용 선언
<html xmlns:th="http://www.thymeleaf.org">
속성 변경 - 절대 경로 추가 / URL 링크 표현식
th:href="@{/css/bootstrap.min.css}"
- 타임리프 뷰 템플릿을 거치게 되면 기존의 href를 날리고 설정한 th:xxx 값으로 동적 변경해 실행
- @{...} : URL 링크
속성 변경 - th:value
th:value="${item.id}"
th:value="${item.itemName}"
th:value="${item.price}"
th:value="${item.quantity}"
-
모델에 있는 item 정보를 획득하고 프로퍼티 접근법으로 출력
속성 변경 - 상품 수정 폼으로 이동 / 상품 목록 폼으로 이동
th:onclick="|location.href='@{/basic/items/{itemId}/edit(itemId=${item.id})}'|"
th:onclick="|location.href='@{/basic/items}'|"
< 여기서 문제!! >
코드를 올바르게 넣었는데도 아래와 같이 에러가 뜬다면?!!
- 에러이유 -
스프링 부트 3.2.0부터 @PathValuable 사용할 때 -parameters 라는 자바 컴파일 옵션을 설정해야 파라미터 이름을 생략할 수 있다
intellij idea로 build 시 -parameters 옵션이 설정되어 있지 않기 때문에 안되고 gradle로 build 시에는 -parameters 옵션이 자동 설정되어서 실행은 가능하나 속도가 너무 느리다
- 해결책 -
해결 방안1(권장)
애노테이션에 이름을 생략하지 않고 다음과 같이 이름을 항상 적어준다. 이 방법을 권장한다.
@RequestParam("username") String username
@PathVariable("itemId") long itemId