thymeleaf
유틸리티 오브젝트
👉🏻자주 사용하는 java.util을 타임리프에서도 활용할 수 있게 제공한다.- #을 사용한다.
- 참고 사이트 : https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#standard-expression-syntax
👉🏻날짜➡️ ${now}
- new Date() : 현재 날짜
➡️ ${#dates.format(new, ‘yyyy-MM-dd HH:mm:ss’)}
➡️ ${’₩’ + #numbers.formatInteger(price, 3, ‘COMMA’)}
리스트
➡️ ${#lists.isEmpty(memberList)}
- 리스트 객체 존재여부
➡️ ${#lists.size(memberList)}
- 리스트 객체의 크기
링크표현
👉🏻th:src, th:action, th:href, ….➡️ ex) th:href=”@{https://www.naver.com}”
쿼리스트링(쿼리파라미터) 표현
➡️ localhost/member/detail?memberId=id001&memberPw=pw001
➡️ ex) th:href=”@{localhost/member/detail(memberId=${키}, memberPw=${’값’})}”
rest API 주소체계
➡️ 자원(RESOURCE) - URI
➡️ 행위(Verb) - HTTP METHOD (GET, POST, PUT, DELETE)
➡️ 표현(Representations)
➡️ ex) localhost/member/id001 → localhost/member/${변수명}
@PathVariable(name=”변수명”) String pathValue
GET → id001의 정보요구
POST → id001의 정보생성
PUT → id001의 정보수정
DELETE → id001의 정보삭제
👉🏻쿼리 파라미터 받는 방법- @RequestParam
- 타입 자동 형변환, 쿼리파라미터를 받아 올지 말지 강제로 선택 가능
- 커맨드 객체 (dto)
- 사용자가 요청하는 쿼리파라미터 키와 일치되는 멤버변수를 가지고 있다면 set메소드를 이용하여 값을 할당.
- controller에서만 존재
- 다음 인수에 값을 가져올 객체를 작성해줘야 한번에 받아올 수 있다.
@RequestParam(name=” “, value = “ “, defaultValue=“ “, required=true/false)
➡️ name : 쿼리파라미터 키
➡️ value : name의 별칭
➡️ defaultValue : 초깃값
➡️ required : 쿼리파라미터 필수 여부
== request.getParameter(”키”);
➡️ String memerId = request.getParameter(”키”);
== @RequestParam(name=”memberId”) String memberId
- 맨 뒤에는 받아주는 변수를 꼭 적어줘야 한다.
- @RequestParam
thymeleaf 코드 예제
ExamController.java
package com.thymeleaf.controller; import com.thymeleaf.dto.Member; import com.thymeleaf.service.MemberService; import jakarta.annotation.PostConstruct; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import java.util.Date; import java.util.List; @Controller public class ExamController { // 생성자 메소드 주입방식(@Autowired 명시하지 않아도 의존성 주입) private final MemberService memberService; public ExamController(MemberService memberService){ this.memberService = memberService; } // @PostConstruct : 해당 클래스를 스프링이 관리하는 객체로 생성 후 이벤트 실행 @PostConstruct public void examControllerInit() { System.out.println("ExamController 객체 생성"); } @GetMapping("/exam5") public String exam5(Model model) { model.addAttribute("title", "exam5"); model.addAttribute("now", new Date()); model.addAttribute("price", 5000000); List<Member> memberList = memberService.getMemberList(); model.addAttribute("memberList", memberList); return "exam/exam5"; } @GetMapping("/exam6") public String exam6(Model model) { model.addAttribute("title", "exam6"); Member memberInfo = memberService.getMemberInfo(); model.addAttribute("memberInfo", memberInfo); return "exam/exam6"; } @GetMapping("/member/detail") public String getMemberInfo(Model model, @RequestParam(name = "memberId", required = false) String memberId, Member member) { System.out.println("사용자가 요청한 쿼리파라미터" + memberId); System.out.println("사용자가 요청한 쿼리파라미터(커맨드객체)" + member); model.addAttribute("title", "exam7"); Member memberInfo = memberService.getMemberInfoById(memberId); model.addAttribute("memberInfo", memberInfo); return "exam/exam7"; } @GetMapping("/member/{memberId}") public String getMemberById(Model model, @PathVariable(name = "memberId") String memberId) { System.out.println("/member/id001 주소요청 시 memberId의 값 : " + memberId); model.addAttribute("title", "exam8"); Member memberInfo = memberService.getMemberInfoById(memberId); model.addAttribute("memberInfo", memberInfo); return "exam/exam7"; } }
MemberService.java
package com.thymeleaf.service; import com.thymeleaf.dto.Member; import jakarta.annotation.PostConstruct; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; @Service public class MemberService { // @PostConstruct : 해당 클래스를 스프링이 관리하는 객체로 생성 후 이벤트 실행 @PostConstruct public void memberServiceInit() { System.out.println("MemberService 객체 생성"); } public Member getMemberInfo() { Member memberInfo = new Member("id001", "pw001", "관리자", "홍01", "홍01@email.com"); return memberInfo; } public List<Member> getMemberList() { List<Member> lm = new ArrayList<Member>(); String[] memberLevelArr = {"구매자", "관리자", "판매자"}; Member memberInfo = null; for(int i=1; i<10; i+=1){ memberInfo = new Member("id00"+i, "pw00"+i, memberLevelArr[i%3], "홍0"+i, "홍0"+i+"@email.com"); lm.add(memberInfo); } return lm; } public Member getMemberInfoById(String memberId) { int digit = Integer.parseInt(memberId.substring(2)); String memberPw = "pw" + String.format("%03d", digit); String[] memberLevelArr = {"구매자", "관리자", "판매자"}; String memberLevel = memberLevelArr[digit%3]; String memberName = "홍" + String.format("%02d", digit); String memberEmail = memberName + "@email.com"; return new Member(memberId, memberPw, memberLevel, memberName, memberEmail); } }
Member.java
package com.thymeleaf.dto; public class Member { private String memberId; private String memberPw; private String memberLevel; private String memberName; private String memberEmail; // 1 생성자, 매개변수 있는 생성자 public Member() {} public Member(String memberId, String memberPw, String memberLevel, String memberName, String memberEmail){ this.memberId = memberId; this.memberPw = memberPw; this.memberLevel = memberLevel; this.memberName = memberName; this.memberEmail = memberEmail; } // 2 set, get public void setMemberId(String memberId) { this.memberId = memberId; } public String getMemberId() { return memberId; } public String getMemberPw() { return memberPw; } public void setMemberPw(String memberPw) { this.memberPw = memberPw; } public String getMemberLevel() { return memberLevel; } public void setMemberLevel(String memberLevel) { this.memberLevel = memberLevel; } public String getMemberName() { return memberName; } public void setMemberName(String memberName) { this.memberName = memberName; } public String getMemberEmail() { return memberEmail; } public void setMemberEmail(String memberEmail) { this.memberEmail = memberEmail; } @Override public String toString() { final StringBuilder sb = new StringBuilder("Member{"); sb.append("memberId='").append(memberId).append('\''); sb.append(", memberPw='").append(memberPw).append('\''); sb.append(", memberLevel='").append(memberLevel).append('\''); sb.append(", memberName='").append(memberName).append('\''); sb.append(", memberEmail='").append(memberEmail).append('\''); sb.append('}'); return sb.toString(); } }
exam5.html (주소 : localhost/exam5, 폴더경로 : templates/exam/exam5.html)
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title th:text="${title}">유틸리티 오브젝트</title> </head> <body> <h1>유틸리티 오브젝트</h1> - 자주 사용하는 java.util 을 타임리프에서도 활용할 수 있게 제공 (#을 사용) <br> - 참고 사이트: https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#standard-expression-syntax <h2 th:text="${now}">new Date(): 현재 날짜</h2> <h2 th:text="${#dates.format(now, 'yyyy-MM-dd HH:mm:ss')}"></h2> <h2 th:text="${'₩' + #numbers.formatInteger(price, 3, 'COMMA')}"></h2> <h2 th:text="${#lists.isEmpty(memberList)}">리스트 객체 존재여부</h2> <h2 th:text="${#lists.size(memberList)}">리스트 객체의 크기</h2> </body> </html>
exam6.html (주소 : localhost/exam6, 폴더경로 : templates/exam/exam6.html)
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title th:text="${title}">thymeleaf 링크표현</title> </head> <body> <h1>thymeleaf 링크표현</h1> - th:src, th:action, th:href, ... ex) th:href="@{https://www.naver.com}" <br> - 쿼리스트링(쿼리파라미터표현)? localhost/member/detail?memberId=id001&memberPw=pw001 <br> - ex) th:href="@{localhost/member/detail(memberId=${키}, memberPw=${'pw001'})}" <br> <th:block th:object="${memberInfo}"> <a th:href="@{https://www.thymeleaf.org}">타임리프 공식 사이트</a> <br> <!-- 쿼리파라미터 적용 --> <!-- 애스터리크 : 오브젝트의 필드를 바로 접근할 때 사용 *{memberId} => (=${memberInfo.memberId}) --> <a th:href="@{/member/detail(memberId=*{memberId}, memberPw=*{memberPw})}">하이퍼링크1</a> <br> <a href="@{/member/detail(memberId=*{memberId}, memberPw=*{memberPw})}">잘못된 링크표현(가장 많이 실수하는 부분)</a> <br> <!-- rest API 주소체계 --> <!-- - 자원(RESOURCE) - URI - 행위(Verb) - HTTP METHOD (GET(R) POST(C) PUT(U) DELETE(D)) - 표현(Representations)--> 예시) localhost/member/detail?memberId=id001 (X) <br> 예시) localhost/member/id001 GET : id001의 정보요구, POST : id001의 정보생성, DELETE : id001의 정보삭제 <br> <a th:href="@{|/member/*{memberId}|}">회원상세보기1</a> <br> <a th:href="@{/member/{memberId}(memberId=*{memberId})}">회원상세보기2</a> <br> </th:block> </body> </html>
exam7.html (주소1 : localhost/member/detail, 주소2 : localhost/member/id001, 폴더경로 : templates/exam/exam7.html)
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title th:text="${title}">상세정보</title> <style> table{ border : 1px solid black; width : 700px; table-layout : auto; text-align : center; } th{ border : 1px solid black; background-color: cornflowerblue; color: azure; height: 30px; } td{ border : 1px solid black; height: 30px; } </style> </head> <body> <form th:action="@{#}" method="post"> <table th:object="${memberInfo}" border="1"> <thead> <tr> <th colspan="2">상세정보</th> </tr> </thead> <tbody> <tr> <td> <label for="memberId">회원아이디</label> </td> <td> <input th:value="*{memberId}" type="text" id="memberId" readonly="readonly"> </td> </tr> <tr> <td> <label for="memberPw">회원비밀번호</label> </td> <td> <input th:value="*{memberPw}" type="text" id="memberPw"> </td> </tr> <tr> <td> <label for="memberLevel">회원권한</label> </td> <td> <input th:value="*{memberLevel}" type="text" id="memberLevel"> </td> </tr> <tr> <td> <label for="memberName">회원이름</label> </td> <td> <input th:value="*{memberName}" type="text" id="memberName"> </td> </tr> <tr> <td> <label for="memberEmail">회원이메일</label> </td> <td> <input th:value="*{memberEmail}" type="text" id="memberEmail"> </td> </tr> </tbody> <tfoot> <tr> <td> <button type="button" id="modifyBtn">수정</button> </td> <td> <button type="reset" id="resetBtn">취소</button> </td> </tr> </tfoot> </table> </form> </body> </html>
ajax 통신
➡️ @Controller + @ResponseBody (spring boot 자바객체를 JSON 객체로 변환)
@ResponseBody
➡️ 메소드 타입 앞에 위치 or GetMapping 아래에 위치
@RequestBody
➡️ 인수에 위치 (JSON 객체 → 자바 객체)
MemberController.java
package com.thymeleaf.controller; import com.thymeleaf.dto.Member; import com.thymeleaf.service.MemberService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import java.util.List; //@Controller @RestController public class MemberController { private final MemberService memberService; // 생성자 메소드 의존성 주입 방식 public MemberController(MemberService memberService) { this.memberService = memberService; } @GetMapping("/memberInfo/{memberId}") //@ResponseBody public Member getMemberInfoById(@PathVariable(name = "memberId") String memberId) { Member memberInfo = memberService.getMemberInfoById(memberId); // JSON 형태로 반환 return memberInfo; } @GetMapping("/member/list") //@ResponseBody public List<Member> getmemberList() { List<Member> memberList = memberService.getMemberList(); return memberList; } }
exam8.html (주소 : localhost/exam8, 폴더경로 : templates/exam/exam8.html)
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> <style> table{ border : 1px solid black; width : 700px; table-layout : auto; text-align : center; } th{ border : 1px solid black; background-color: cornflowerblue; color: azure; height: 30px; } td{ border : 1px solid black; height: 30px; } </style> </head> <body> <input type="text" id="memberId" placeholder="회원아이디를 입력해주세요."> <button type="button" id="ajaxBtn">ajax 통신</button> <button type="button" id="ajaxBtn2">ajax 통신(회원전체목록)</button> <br><br><br> <table> <thead> <tr> <th>회원아이디</th> <th>회원비밀번호</th> <th>회원등급</th> <th>회원이름</th> <th>회원이메일</th> </tr> </thead> <tbody id="tbody"> </tbody> </table> <script> const $ajaxBtn = document.querySelector('#ajaxBtn'); $ajaxBtn.addEventListener('click', function () { const $inputMemberId = document.querySelector('#memberId'); let memberId = $inputMemberId.value; console.log(memberId); if(typeof memberId == 'undefined' || memberId == null || memberId == ''){ alert('회원의 아이디를 입력해주세요.'); $inputMemberId.focus(); return ; } // 비동기 통신 ajax fetch('/memberInfo/' + memberId) .then(response => response.json()) .then(memberInfo =>{ console.log(memberInfo); const $tbody = document.querySelector('#tbody'); $tbody.innerHTML = ''; const $tr = document.createElement('tr'); for(let key in memberInfo) { const $td = document.createElement('td'); $td.textContent = memberInfo[key]; $tr.append($td); } $tbody.append($tr); }); }); const $ajaxBtn2 = document.querySelector('#ajaxBtn2'); $ajaxBtn2.addEventListener('click', function () { fetch('/member/list') .then(response => response.json()) .then(memberList =>{ console.log(Array.isArray(memberList)); const $tbody = document.querySelector('#tbody'); $tbody.innerHTML = ''; memberList.forEach(function (item, idx) { const $tr = document.createElement('tr'); console.log(`${idx}번째 요소 : ${item}`); for(let key in item) { const $td = document.createElement('td'); $td.textContent = item[key]; $tr.append($td); } $tbody.append($tr); }); }); }); </script> </body> </html>
- 아이디 1개 조회
- 회원전체목록
- JSON 변환
tag : #spring #thymeleaf #유틸리티 #링크 #쿼리파라미터 #ajax통신
Uploaded by N2T