해당 포스트는 초보 웹 개발자를 위한 스프링 5 프로그래밍 입문 [최범균 저] 책 내용을 참고하였습니다.
홈페이지를 개발할 때 다국어 지원이 필요하다면 우리는 각 언어별로 사용할 문자열을 파일에 보관하고 알맞을 때 꺼내 쓸 필요가 있다. 스프링은 이 기능을 <spring: message> 태그로 제공하고 있다. 전체적인 방법은 다음과 같다.
메시지 파일은 프로퍼티 파일 형식으로 작성한다.
src/main/resources 에 message 폴더를 생성하고 label.properties 파일을 생성한다. 인코딩은 'UTF-8'로 설정해야 한다.
member.register=회원가입
term=약관
term.agree=약관동의
next.btn=다음단계
member.info=회원정보
email=이메일
name=이름
password=비밀번호
password.confirm=비밀번호 확인
register.btn=가입 완료
register.done=<strong>{0}님 ({1})</strong>, 회원 가입을 완료했습니다.
go.main=메인으로 이동
MvcConfig 설정 클래스에 MessageSource 타입의 빈을 추가하자.
import org.springframework.context.MessageSource;
import org.springframework.context.support.ResourceBundleMessageSource;
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource ms = new ResourceBundleMessageSource();
ms.setBasenames("message.label"); // message 패키지 내에 label 프로퍼티 파일을 불러옴
ms.setDefaultEncoding("UTF-8");
resturn ms;
}
다음과 같이 작성해주면 된다.
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<!-- <spring:message> 커스텀 태그를 사용하기 위해 태그 라이브러리 설정 추가 -->
...
<head>
<title><spring:message code="member.register"/></title>
</head>
...
<body>
<p>
<spring:message code="register.done"
arguments="${registerRequest.name}, ${registerRequest.email}" />
</p>
public interface MessageSource {
String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
String getMessage(String code, Object[] args, Locale locale)
throws NoSuchMessageException;
....
}
회원 가입 처리를 할 때 비정상 값이 입력될 경우를 대비하여 우리는 입력한 값을 검증해야 할 필요가 있다.
값을 검증하고, 잘못된 값일 경우 적절한 에러 메시지를 출력하는 방법을 알아보자. 다음과 같은 방법으로 진행된다.
다음의 두 인터페이스를 활용하여 커맨드 객체의 값을 검사할 수 있다.
RegisterRequestValidator.java
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
...
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;
// clazz 객체가 RegisterRequest 클래스로 타입 변환이 가능한지 확인한다
@Override
public boolean supports(Class<?> clazz) {
retrn RegisterRequest.class.isAssignableFrom(clazz);
}
// target 파라미터 : 검사 대상 객체
// errors 파라미터 : 검사 결과 에러 코드를 설정하기 위한 객체
@Override
public void validate(Object target, Errors errors) {
RegisterRequest regReq = (RegisterRequest) target;
// "email"프로퍼티의 값이 유효한지 검사
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"); // 에러 코드 저장
}
}
// "name" 프로퍼티가 null이거나 공백이면 에러코드로 "required" 추가
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");
}
}
}
}
@PostMapping("/register/step3")
// Errors 객체는 커맨드 객체의 특정 프로터리 값을 구할 수 있는 getFieldValue() 메서드 제공
// ValidationUtils.rejectIfEmptyOrWhitespace() 메서드는 커맨드 객체를 전달받지 않아도
// Errors 객체의 getFieldValue("name") 메서드를 실행하여 프로퍼티 값 접근 가능
public String handleStep3(RegisterRequest regReq, Errors errors) {
// 검사
new RegisterRequestValidator().validate(regReq, errors);
// 한번이라도 유효하지 않은 값이 존재하면 실행
if(errors.hasErrors())
return "register/step2";
참고 : Errors 타입 파라미터는 반드시 커맨드 객체를 위한 파라미터 다음에 위치해야 한다.
Erros 인터페이스의 에러 코드 추가 메서드
인덱스 기반 변수를 포함하고 있으면 Object 타입의 errorArgs 파라미터를 이용하면 된다.
defaultMessage는 에러 코드가 존재하지 않을 때 해당 메시지를 출력한다.
ValidationUtils 클래스의 메서드
rejectIfEmpty는 field 값이 null이거나 빈 문자열이면 errorCode 추가
rejectIfEmptyOrWhitespace는 field값이 null이거나 빈 문자열, 공백문자로만 구성된 문자열일 경우에 errorCode를 추가한다.
스프링 MVC는 모든 컨트롤러에 적용할 수 있는 글로벌 Validator와 단일 컨트롤러에만 적용할 수 있는 Validator를 설정할 수 있게 하였다.
두 가지를 선행해야 한다.
WebMvcConfigurer
@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
@Override
public Validator getValidator() {
return new RegisterRequestValidator();
}
적용 방법
import javax.validation.Valid;
@PostMapping("/register/step3")
public String functions(@Valid RegsterRequest regReq, Errors errors) {
...
@Valid 애노테이션 사용 시 Errors 타입 파라미터가 없으면 검증 실패 시 http 400 에러를 발생시킨다.
import javax.validation.Valid;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
@PostMapping("/register/step3")
public String functions(@Valid RegsterRequest regReq, Errors errors) {
...
@initBinder
protected void initBinder(WebDataBinder binder) {
binder.setValidator(new RegisterRequestValidator());
}
매핑 요청을 처리하기 전에 initBinder가 실행되어 Validator를 설정한다.
Bean Validation이 제공하는 애노테이션을 이용하면 굳이 Validator를 작성하지 않더라도 커맨드 객체 값을 검증할 수 있다.
방법은 다음과 같다.
pom.xml
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.2.Final</version>
</dependency>
public class RegisterRequest {
@NotBlank
@Email
private String email;
@Size(min=6)
private String password;
@NotEmpty
private String confirmPassword;
@NotEmpty
private String name;
이전처럼 @Valid 애노테이션을 붙인 클래스에 한해 자동으로 직접 작성한 RegisterRequest가 연결된다.
Spring 1
EDITOR: PORO
[스프링1] 14장.MVC4 : 날짜 값 변환, @PathVariable, 익셉션 처리 (0) | 2022.12.08 |
---|---|
[스프링1] 13장. MVC3: 세션, 인터셉터, 쿠키 (0) | 2022.12.01 |
[스프링 1] 11장. MVC1: 요청 매핑, 커맨드 객체, 리다이렉트, 폼 태그, 모델 (0) | 2022.11.24 |
[스프링 1] 10장. 스프링 MVC 프레임워크 동작 방식 (0) | 2022.11.17 |
[스프링 1] 9장. 스프링 MVC 시작하기 (0) | 2022.11.17 |