@Controller
@Slf4j
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
/**
* 회원가입
*/
@GetMapping("/members/new")
public String createMemberForm(@ModelAttribute("memberForm") MemberForm memberForm, Model model) {
List<RoleCode> roleCodes = new ArrayList<>();
roleCodes.add(new RoleCode("admin", "판매자"));
roleCodes.add(new RoleCode("user", "구매자"));
model.addAttribute("roleCodes", roleCodes);
return "members/createMemberForm";
}
@Data
@AllArgsConstructor
static class RoleCode {
private String code;
private String displayName;
}
}
@Getter
@Setter
public class MemberForm {
@NotEmpty(message = "이름은 필수입니다.")
private String name;
@NotEmpty(message = "이메일은 필수입니다.")
@Email //이메일 형식 validation
private String email;
@NotEmpty(message = "비밀번호는 필수입니다.")
private String password;
private String city;
private String street;
private String zipcode;
private String role;
}
@PostMapping("/members/new")
public String createMember(@Valid @ModelAttribute MemberForm memberForm, BindingResult bindingResult, Model model,
@RequestParam("role") String role) {
//이름, 이메일, 패스워드 중 하나라도 입력을 안했을 시
if (bindingResult.hasErrors()) {
List<RoleCode> roleCodes = new ArrayList<>();
roleCodes.add(new RoleCode("admin", "판매자"));
roleCodes.add(new RoleCode("user", "구매자"));
model.addAttribute("roleCodes", roleCodes);
return "/members/createMemberForm";
}
Address address = new Address(memberForm.getCity(), memberForm.getStreet(), memberForm.getZipcode());
try {
Member member = Member.builder()
.name(memberForm.getName())
.email(memberForm.getEmail())
.password(memberForm.getPassword())
.address(address)
.build();
member.changeRole(role); //사용자에게 권한 설정(판매자 또는 구매자)
memberService.join(member);
} catch (IllegalStateException e) { //예외가 발생하면(회원 이메일이 중복)
model.addAttribute("errorMessage", e.getMessage());
return "members/createMemberForm";
}
return "redirect:/members";
}
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
타임 리프의 레이아웃을 사용하기 위해 build.gradle에 추가해 줍니다.
th:block : 동적인 처리가 필요할 때 사용됩니다. layout:fragment 속성에 이름을 지정해서 실제 컨텐츠 페이지의 내용을 채워줍니다.
자바스크립트 인라인 : 자바스크립트에서 타임리프를 편리하게 사용할 수 있는 기능입니다.
<head>
<th:block layout:fragment="script">
<script th:inline="javascript">
var error = [[${errorMessage}]];
if(error != null){
alert(error);
}
</script>
</th:block>
</head>
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
th:replace="~{layout/base :: layout(~{::section})}"
layout:decorate="~{layout/base}">
<head>
<th:block layout:fragment="script">
<script th:inline="javascript">
var error = [[${errorMessage}]];
if(error != null){
alert(error);
}
</script>
</th:block>
</head>
<section>
<div layout:fragnemt="content" style="padding:30px; padding-left:50px" >
<form th:action th:object="${memberForm}" method="post">
<div th:if="${#fields.hasGlobalErrors()}">
<p class="field-error" th:each="err : ${#fields.globalErrors()}"
th:text="${err}">전체 오류 메시지</p>
</div>
<div>
<label for="name">    이름     </label>
<input type="text" id="name" th:field="*{name}" class="form-control" placeholder="이름을 입력해주세요">
<div class="field-error" th:errors="*{name}" />
</div>
<br>
<div>
<label for="email">   이메일   </label>
<input type="text" id="email" th:field="*{email}" class="form-control" placeholder="이메일 형식으로 입력해주세요">
<div class="field-error" th:errors="*{email}" />
</div>
<div>
<label for="password">  비밀번호 </label>
<input type="password" id="password" th:field="*{password}" class="form-control" placeholder="비밀번호를 입력해주세요">
<div class="field-error" th:errors="*{password}" />
</div>
<br>
<div>
<label for="city">   지역명   </label>
<input type="text" id="city" th:field="*{city}"
class="formcontrol"
>
</div>
<div>
<label for="street">   도로명   </label>
<input type="text" id="street" th:field="*{street}"
class="formcontrol"
>
</div>
<div>
<label for="zipcode">  우편번호 </label>
<input type="text" id="zipcode" th:field="*{zipcode}"
class="formcontrol"
>
</div>
<br>
 
<select name="role" id="role" class="formcontrol">
<option value="">판매자, 구매자 등록</option>
<option th:each="roleCode : ${roleCodes}"
th:value="${roleCode.code}"
th:text="${roleCode.displayName}" />
</select>
<hr class="my-4">
<div class="row">
<div class="col" style="text-align: center">
<button class="w-100 btn btn-primary btn-lg" type="submit">
회원가입</button>
</div>
<div class="col" style="text-align: center">
<button class="w-100 btn btn-secondary btn-lg"
onclick="location.href='home.html'"
th:onclick="|location.href='@{/members}'|"
type="button">취소</button>
</div>
</div>
</form>
</div>
</section>
</html>