Chapter 12 내용
- 메시지 처리
- 커맨드 객체 검증
<spring:message>태그로 메시지 출력, 다국어 처리하기
- 이메일과 같은 문자열은 로그인, 회원가입, 회원 정보 등 반복되 사용할 떄 전 세계를 대상으로 다국어 지원을 해야하는데 언어별로 뷰 코드를 따로 만들수는 없다.
- 다국어 지원을 위해 뷰 코드에서 사용할 문자열을 언어별로 파일에 보관해 뷰 코드가 언어에 따라 알맞은 파일을 읽어와 출력하게 한다.
- 문자열을 담은 메시지 파일 작성하기
- 메시지 파일에서 값을 읽어오는 MessageSource 빈 설정
- JSP 코드에서 <spring:message>태그를 사용
1. 메시지 파일을 작성
- 메시지 파일을 보관하기 위해 src/main/resources에 message 폴더를 생성하고 label.properties파일을 작성한다.
member.register=회원가입
term=약관
term.agree=약관동의
next.btn=다음단계
member.info=회원정보
email=이메일
name=이름
password=비밀번호
password.confirm=비밀번호 확인
register.btn=가입 완료
register.done=<strong>{0}님 ({1})</strong>, 회원 가입을 완료했습니다.
2. MessageSource 타입의 빈을 추가한다.
스프링 설정파일에서 MessageSource 타입의 빈을 등록한다.
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource ms =
new ResourceBundleMessageSource();
ms.setBasenames("message.label");
ms.setDefaultEncoding("UTF-8");
return ms;
}
|
cs |
ms.setBasenames("message.label")
- message 패키지에 속한 label 프로퍼티 파일로부터 메시지를 읽어온다고 설정
3. 뷰 파일 수정
메시지 파일과 빈으로 등록했다면 <spring:message> 태그를 사용해서 꺼내쓰면 된다.
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html>
<html>
<head>
<title><spring:message code="member.register" /></title>
</head>
<body>
<h2><spring:message code="term" /></h2>
<p>약관 내용</p>
<form action="step2" method="post">
<label>
<input type="checkbox" name="agree" value="true">
<spring:message code="term.agree" />
</label>
<input type="submit" value="<spring:message code="next.btn" />" />
</form>
</body>
</html>
|
cs |
다국어 지원을 위한 메시지 파일 - label_ko.properties - label_en.properties label 뒤에 '_언어' 형식의 언어 구분자를 작성해 주면 된다. 언어 구분자는 , 브라우저가 서버에 요청을 전송할 때 Accept-Language 헤더에 언어 정보를 담아 전송하는데, 한글인 경우에는 ko를 전송한다. 스프링 MVC는 웹 브라우저가 전송한 Accept-Langauge 헤더를 이용해서 Locale를 구하고, Locale을 MessageSource에서 메시지를 구할 때 사용한다. |
<spring:message> 태그는 스프링 설정에 등록된 'messageSource' 빈을 이용해 메시지를 구하는데, 내부적으로 messageSource의 getMessage()메서드를 실행해서 필요한 메시지를 구하는 방식이다.
4. <spring:message> 태그의 메시지 인자 처리
register.done=<strong>{0}님 ({1})</strong>, 회원 가입을 완료했습니다.
위와 같이 인덱스로 메시지를 출력 할 수 있다.
- 콤마로 구분한 문자열
- 객체 배열
- <spring:argument> 태그 사용
위 3가지 방식을 사용하면 된다.
<p>
<spring:message code="register.done">
<spring:argument value="${registerRequest.name}" />
<spring:argument value="${registerRequest.email}" />
</spring:message>
</p>
<p>
<spring:message code="register.done" argument= "${registerRequest.name}","${registerRequest.email}"/>
</p>
|
cs |
커맨드 객체의 값 검증과 에러 메시지 처리
- 코드가 동작은 하지만, 비정상적인 값을 입력했을때는 동작하지 않아야된다.
- 비정상적인 값을 체크하기 위해 객체 검증을 한다.
객체 검증 인터페이스
- org.strpingframework.validation.Validator
- org.springframework.validation.Errors
public class RegisterRequestValidator implements Validator {
private static final String emailRegExp = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
private Pattern pattern;
public RegisterRequestValidator() {
pattern = Pattern.compile(emailRegExp);
System.out.println("RegisterRequestValidator#new(): " + this);
}
@Override public boolean supports(Class <?> clazz) {
return RegisterRequest.class.isAssignableFrom(clazz);
}
@Override public void validate(Object target, Errors errors) {
System.out.println("RegisterRequestValidator#validate(): " + this);
RegisterRequest regReq = (RegisterRequest)target;
if (regReq.getEmail() == null || regReq
.getEmail()
.trim()
.isEmpty()) {
errors.rejectValue("email", "required");
} else {
Matcher matcher = pattern.matcher(regReq.getEmail());
if (!matcher.matches()) {
errors.rejectValue("email", "bad");
}
}
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required");
ValidationUtils.rejectIfEmpty(errors, "password", "required");
ValidationUtils.rejectIfEmpty(errors, "confirmPassword", "required");
if (!regReq.getPassword().isEmpty()) {
if (!regReq.isPasswordEqualToConfirmPassword()) {
errors.rejectValue("confirmPassword", "nomatch");
}
}
}
}
if (regReq.getEmail() == null || regReq
.getEmail()
.trim()
.isEmpty()) {
errors.rejectValue("email", "required");
} else {
Matcher matcher = pattern.matcher(regReq.getEmail());
if (!matcher.matches()) {
errors.rejectValue("email", "bad");
}
}
ValudationUtils 검증 코드 간결
- 객체의 값 검증 코드를 간결하게 작성할 수 있다.
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required");
ValidationUtils.rejectIfEmpty(errors, "password", "required");
ValidationUtils.rejectIfEmpty(errors, "confirmPassword", "required");
유효성 검사해주는 클래스를 생성하고, 이 클래스를 사용해서 객체를 검증해주면 된다.
@PostMapping("/register/step3")
public String handleStep3(RegisterRequest regReq, Errors errors) {
new RegisterRequestValidator().validate(regReq, errors);
if (errors.hasErrors())
return "register/step2";
try {
memberRegisterService.regist(regReq);
return "register/step3";
} catch (DuplicateMemberException ex) {
errors.rejectValue("email", "duplicate");
return "register/step2";
}
}
|
cs |
public String handleStep3(RegisterRequest regReq, Errors errors) 처럼 Errors 타입 파라미터가 커맨드 객체 뒤에 위치하면, 스프링 MVC에서 메서드를 호출할 때 커맨드 객체와 연결된 Errors 객체를 생성해서 파라미터로 전달한다.
위의 코드에서 new RegisterRequestValidator().validate로 객체 생성, validate()메서드를 실행하고, 커맨드 객체의 값이 올바른지 검사 후 결과를 Error객체에 담았다.
REFERENCE
초보 웹 개발자를 위한 스프링 5 프로그래밍 입문(최범균)
'공부 > Spring' 카테고리의 다른 글
[Spring] Chapter 15 - 간단한 웹 어플리케이션의 구조 (0) | 2021.07.23 |
---|---|
[Spring] Chapter 14 - Date 타입 변환, @PathVariable 경로 변수 처리, 익셉션 처리하기 (0) | 2021.07.17 |
[Spring]Chapter 11 - 요청 매핑, 커맨드 객체, 리다이렉트, 폼 태그, 모델 (0) | 2021.07.11 |
[Spring] Chapter 9-10장 Intellij에서 스프링 MVC 시작하기(Spring+ Gradle + MVC) (3) | 2021.07.11 |
[Spring] Chapter 08 - DB 연동(MySQL + Gradle + JDBC) (0) | 2021.07.03 |