에러 메세지를 웹에 표출하기 위한 여러방법 (properties 이용하기 등등) 이 존재한다.
그 중 가장 간편하게(내 기준) 메세지를 띄우는 방법인 Entity 클래스의 검증 어노테이션을 이용하는 방법을 살펴보자아
결과
Gradle 라이브러리 추가하기
implementation 'org.springframework.boot:spring-boot-starter-validation'
spring-boot-starter-validation을 추가하면 여러 검증 어노테이션을 사용할 수 있게된다.
- @NotBlank : 공백 또는 빈값만 있는 경우 허용하지 않음
- @NotNull : null 허용 하지 않음
- @Range(min = num1, max = num2) : num1 ~ num2 안의 값이여야함
- @Max( num ) : 최대 num 까지만 허용
- @Pattern(regexp = "정규식") : 패턴에 대한 허용 또는 허용하지 않음을 나타낼 때
Entity 클래스
Member.java
@NoArgsConstructor
@Getter
@Setter
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@NotBlank(message = "빈 값일 수 없습니다.")
@NotNull
@Pattern(regexp="^[\\S]*$", message="아이디에 공백문자를 입력할 수 없습니다.")
private String user;
@NotNull
@NotBlank(message = "빈 값일 수 없습니다.")
private String password;
}
null이 허용될 수 없는 필드 값에 빈 값이 들어 왔을 때 : "빈 값일 수 없습니다."
공백이 허용될 수 없는 필드 값에 공백 값이 들어 왔을 때 : "공백일 수 없습니다."
라는 메세지를 보여주기 위해 위 와 같이 작성해 주기
Controller
MemberController
@GetMapping("/login")
public String loginView(Model model, Member member){
model.addAttribute("member", member);
return "login";
}
@PostMapping("/login")
public String login(@Validated @ModelAttribute("member") Member member,BindingResult bindingResult){
// 에러 처리
if(bindingResult.hasErrors()){
return "/login";
}
//글로벌 에러 처리
boolean result = memberService.login(member);
Member user = memberService.findByUser(member.getUser());
if(user == null || !result){
bindingResult.reject("loginFail","아이디 또는 비밀번호가 맞지 않습니다.");
return "/login";
}
//로그인 성공
else{
return "redirect:/board/list";
}
}
login메서드를 살펴보자.
1. 매개변수
검증 대상(Member) 앞에 붙는 @Validated
@Validated 는 검증을 실행하는 어노테이션이고, Member클래스를 검증하게 된다.
검증 대상(Member) 뒤에 붙는 BindingResult
BindingResult는 @Validated에서 실행한 검증의 결과를 가지게 된다.
그렇기 때문에 꼬옥 아래 순서대로 코드를 작성해야한다..!
@Validated Member member BindingResult bindingResult
2. 로직
bindingResult.hasErrors() 는 에러의 결과가 존재 하는지를 확인하는 메서드다.
만약 null값이 들어와 에러가 발생했다면, bindingResult 에 검증 결과가 담겨 bindingResult.hasErrors() 는 true가 되고
login.html을 return하게 된다.
bindingResult.reject() 또는 bindingResult.rejectValue() 는 글로벌 에러를 추가해 준다.
에러코드에 대한 메세지를 설정하지 않았을 경우 defaultMessage를 사용해 오류 메세지를 보여주게 된다.
이렇게 생성한 글로벌 에러는 html에서 ${#fields.hasGlobalErrors()} 와 같이 사용 할 수 있게 된다.
html 파일 수정하기
login.html
<form action="/login" method="post" th:object="${member}">
<div>
ID :
<input placeholder="ID를 입력하세요" type="text" th:field="*{user}" th:errorclass="error-class">
<p class="error-class" th:errors="${member.user}"></p>
PW :
<input type="password" placeholder="PW를 입력하세요" th:field="*{password}" th:errorclass="error-class" >
<p class="error-class" th:errors="${member.password}"></p>
<!-- 글로벌 에러 -->
<div th:if="${#fields.hasGlobalErrors()}">
<p class="error-class" th:each="err : ${#fields.globalErrors()}" th:text="${err}"/>
</div>
</div>
<input type="submit" value="login">
</form>
<form th:action="@{/sign}" method="get">
<input type="submit" value="sign">
</form>
th:errorclass="error-class" 는 bindingResult에 결과가 있는 경우 "error-class" 로 input 요소의 클래스 이름을 변경하게 한다. (에러가 발생할 때 html style 적용에 유용함!)
th:errors="${member.user}" 는 bindingResult에 결과를 text로 보여줄 때 사용한다. Member 클래스의 필드에 대한 검증을 하고, 바인딩 된 객체의 오류 메세지를 표시할때 사용한다.
th:if="${#fields.hasGlobalErrors()}" 는 Controller에서 생성한 글로벌 오류(bindingResult.reject 등)가 있는지 확인한다.
th:each="err : ${#fields.globalErrors()}" th:text="${err}" 는 #fields 에서 가져온 글로벌 오류 메세지들을 순회하고 그 메세지를 text로 나타내게 한다.
(참고) th:field
더보기
th:field는 필드의 값과 오류 메세지를 자동으로 매칭하고 처리해준다.
( 참고로 th:field가 있으면 html에서 id="user" name="user" 코드를 생략할 수 있다. )
th:field 를 사용하려면 꼭 th:object 를 정의해야 한다.
th:object는 바인딩할 객체를 지정하는 데 사용된다. th:field는 th:object에 지정된 객체(member)의 필드(user, password)와 입력 요소를 연결한다.
'Spring' 카테고리의 다른 글
[ Springboot ] Swagger 설정 및 접속 ( + Swagger Spring Security 설정 ) (0) | 2023.10.17 |
---|---|
[ SpringBoot - JUnit 5 ] Dev , Test DB 분리 ( feat. h2 ) (3) | 2023.10.09 |
[ Spring ] application.properties에 DB 정보 추가하기 (0) | 2023.05.24 |
[Thymeleaf] 타임리프 문법 (0) | 2023.04.16 |
[Spring] Port 8080 was already in use , Port 에러 해결하기 2 (0) | 2023.03.27 |