메시지 파일은 주로 resources에 넣어준다.


@Configuration
public class MessageConfig {
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource ms = new ResourceBundleMessageSource();
ms.addBasenames("messages.commons"); //classpath 기준
ms.setDefaultEncoding("UTF-8");
return ms;
}
}
3) 다국어 지원 위한 메시지 파일 -> properties 파일


메시지 가져오기
code: property의 이름값
defaultMessage: 대체 할 메시지
...
테스트해보자잇〜( ̄▽ ̄〜)



언어코드!



언어변경

//상수로..
@Test
void test2() throws Exception {
mockMvc.perform(get("/member/join")
.header("Accept-Language", Locale.KOREAN)
)
.andDo(print());
}
보이는 페이지인 뷰, join.jsp에서 많이 쓰일것이다..
스프링은 message라는 태그를 지원해줌
properties에 있는 형태를 태그로 가져올 수있다.
🔽
property파일

상단에 태그 추가
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

만약에 properties에 추가한 코드가 없는경우 대체할 수 있는 방식이 있다.
MessageConfig 클래스


양이 많을땐 태그안에 넣어서 동작 가능

스프링에서 검증에 대한 틀을 제공해준다.
supports(): 검증하는 커맨드 객체 한정 설정

@Component
@RequiredArgsConstructor
public class JoinValidator implements Validator {
private final MemberMapper mapper;
@Override
public boolean supports(Class<?> clazz) { //커맨드 객체에 제한
return clazz.isAssignableFrom(RequestJoin.class); //requestjoin 커맨드 객체만 검증하도록 제한
}
@Override
public void validate(Object target, Errors errors) { //검증
}
}
reject("에러코드");reject("에러코드", "기본 메세지")-> 개별 프로퍼티가 아닌 객체 자체에 에러코드를 추가하므로 글로벌 에러라 부른다
-> 커맨드 객체의 특정 프로퍼티에 대한 에러가 아님
예를들어 로그인 아이디와 비밀번호를 잘못 입력한 경우 아이디와 비밀번호가 불일치 한다는 메시지를 보여줘야함 -> 특정 프로퍼티 에러 아님, 커맨드 객체 자체 에러임
⭐rejectValue("필드명", "에러코드");
⭐rejectValue("필드명", "에러코드", "기본메세지");
-> 특정 필드에 관한 에러 ex) 이메일 형식에 맞지 않습니다, 비밀번호는 8자리 이상입니다 등
hasErrors() : 한개라도 reject 또는 rejectValue가 호출되면 true -> 검증 한개라도 실패시 true
검증에 이상이 없을 경우 페이지 이동~ 검증 실패시 form 페이지에 머물고있을거임
참고)
StringUtils - org.springframework.util 패키지의 StringUtils 클래스에는 손쉽게 문자열을 다룰 수 있는 다양한 메서드를 제공하고 있다.
hasText(): 문자열이 Text형태인지 확인 -> null, 빈값(공백)일 경우 False 반환
JoinValidator

스프링 프레임워크에서 제공하는게 있다! 앞으로 그걸 쓰도록..
🔽


타임리프
#fields.errors("필드명") : -> errors 객체 담긴 메세지를 필드명으로 조회 -> 배열
<form:errors path="필드명"/>
element="태그명" 직접 태그 지정 가능 - 기본 태그는 spandelimiter="에러와 에러 메시지 사이에 추가될 태그"
필드에 해당하는 오류 출력

필수항목 검증 코드를 더 간편하게 쓸 수 있는 편의 메서드가 있다
🔽
rejectIfEmpty(...): 값이 null 또는 "(빈값)인 경우 에러 체크rejectIfEmptyOrWhitespace(...) : 값이 null 이거나 길이가 0(빈값)이거나 공백문자로 구성되어 있는 경우 체크
근데 이거보다 더 좋은게 있다는 사실.....ㅋㅋ
@Component
@RequiredArgsConstructor
public class JoinValidator implements Validator {
private final MemberMapper mapper;
@Override
public boolean supports(Class<?> clazz) { //커맨드 객체에 제한
return clazz.isAssignableFrom(RequestJoin.class); //requestjoin 커맨드 객체만 검증하도록 제한
}
@Override
public void validate(Object target, Errors errors) { //검증
/**
* 1. 필수 항목 검증
* 2. 이메일 중복 여부(회원이 가입되어 있는지 체크
* 3. 비밀번호 자리수 체크(8자리)
* 4. 비밀번호 확인, 일치여부 체크
*/
RequestJoin form = (RequestJoin) target;
String email = form.getEmail();
String password = form.getPassword();
String confirmPassword = form.getConfirmPassword();
String userName = form.getUserName();
boolean agree = form.isAgree();
//필수 항목 검증
ValidationUtils.rejectIfEmptyOrWhitespace(errors,"email","Required","이메일을 입력하세요.");
ValidationUtils.rejectIfEmptyOrWhitespace(errors,"password","Required","비밀번호를 입력하세요.");
ValidationUtils.rejectIfEmptyOrWhitespace(errors,"confirmPassword","Required","비밀번호를 확인하세요.");
ValidationUtils.rejectIfEmptyOrWhitespace(errors,"userName","Required","회원명을 입력하세요.");
}
}
나중에 더 좋은거 배울땐 이 코드도 사라질것*^^*...-> Bean Validation API
나머지 검증 기능도 추가

defaultMessage: 에러코드에 해당하는 메시지가 존재하지 않을때 익셉션을 발생시키는 대신 defaultMessage 출력



현재 메시지는 Required에 정의된 메시지만 출력되고있다.
특정 필드를 한정해서 나오는 메시지를 지정해줘야한다.
매칭이 안될경우 Required로 매칭
참고) 태그의 name값이 필드명임

agree의 경우 다른 페이지에서 사용 가능성이 있다. 범위를 좁혀서 한정해줘야함
에러코드 + "." + 필드명

에러코드 + "." + 필드타입
에러코드 (제일 넓은 범위)
Required=필수 입력항목 입니다.
Required.email=이메일을 입력하세요.
Required.password=비밀번호를 입력하세요.
Required.confirmPassword=비밀번호를 확인하세요.
Required.userName=회원명을 입력하세요.
Mismatch.confirmPassword=비밀번호가 일치하지 않습니다.
# 회원가입 검증 메시지로 한정 - requestJoin
Required.requestJoin.agree=회원가입 약관에 동의하세요.
Duplicated.requestJoin.email=이미 가입된 회원입니다.
Length.requestJoin.password=비밀번호를 8자리 이상 입력하세요.
🚩프로퍼티 파일에서 requestJoin이 붙은 이유는 해당 메시지들이 특정 컨텍스트나 폼에 대한 것임을 명확히 하기 위해서이다.
예를 들어, 이메일 필드에 대해 다른 폼(예: 로그인 폼)에서도 검증 메시지를 제공할 수 있다. 이때, requestJoin 접두어를 붙여 회원가입 폼과 구분할 수 있다.
에러코드 + "." + 커맨드객체이름 + "." + 필드명[인덱스].중첩필드명
에러코드 + "." + 커맨드객체이름 + "." + 필드명.중첩필드명
에러코드 + "." + 필드명[인덱스].중첩필드명
에러코드 + "." + 필드명.중첩필드명
에러코드 + "." + 중첩필드명
에러코드 + "." + 필드타입
에러코드
Email=이메일 형식이 아닙니다.
NotBlank=필수 입력항목 입니다.
#범위 한정
NotBlank.email=이메일을 입력하세요.
NotBlank.password=비밀번호를 입력하세요.
NotBlank.confirmPassword=비밀번호를 확인하세요.
NotBlank.userName=회원명을 입력하세요.
AssertTrue.requestJoin.agree=회원가입 약관에 동의합니다.
Size.requestJoin.password=비밀번호는 8자리 이상 입력하세요.
1) 글로벌 범위 Validator 설정과 @Valid 애노테이션
WebMvcConfigurer의 getValidator()
모든 컨트롤러의 공통적인 검증이 필요한 경우


🔼단, 전역 validator(getValidator) 사용시 컨트롤러에 커맨드 객체에 해당하는 파라미터에 @Valid 애노테이션은 꼭 존재해야함
@Valid 사용시 Errors타입 파라미터가 없으면 검증실패시 400에러를 응답한다.
JoinValidator 클래스는 RequestJoin 타입의 객체만 검증할 수 있으므로 모든 컨트롤러에 적용할 수 있는 글로벌 범위 Validator로는 적합하지않다.
스프링 MVC는 자체적으로 제공하는 글로벌 Validator가 있는데 이 Validator를 사용하면 BeanValidator이 제공하는 애노테이션을 이용해 값을 검증 할 수 있다.
2) @InitBinder 애노테이션을 이용한 컨트롤러 범위 설정
Validator
@InitBinder
protected void InitBinder(WebDataBinder binder) {
binder.setValidator(new RegisterRequestValidator());
}
WebDataBinder는 내부적으로 Validator목록을 갖는데 이 목록에는 글로벌 범위 Validator가 기본으로 포함된다.

3) 컨트롤러 범위 Validator > 글로벌 범위 Validator
setValidator를 사용하면 글로벌 범위 대신 컨트롤러 범위 Validator를 사용하게된다.
Bean Validation API
구현체 -> hibernate Validator
1) 설정


implementation'jakarta.validation:jakarta.validation-api:3.0.2'
implementation 'org.hibernate.validator:hibernate-validator:8.0.1.Final'



필수항목검증 끝났다....
애노테이션이름이 에러코드 이름이 된다!
@NotBlank -> null과 "", " " 허용하지 않음
@Email -> 이메일 형식을 준수하는지 검증
@Size -> 문자열 길이 확인
@AssertTrue -> true를 반환했을때는 검증 성공 false를 반환하면 검증 실패
이메일, 비밀번호 자리수 형식 검증

MemberController에 검증 대상임을 알려주는 애노테이션을 붙여줘야한다.

@Valid -> 검증할 대상 앞에 붙여주고 해당 객체에 대해 유효성을 검증하겠다고 지시해주는 용도
반드시Valid 애노테이션 이후,(커맨드 객체 뒤!!!)에 Errors객체가 정의되어야 한다.
** 만약 따로 설정한 글로벌 범위 Validator가 있다면 해당 설정을 삭제해야한다.
스프링 MVC는 별도로 설정한 글로벌범위 Validator가 없을때 OptionalValidatorFactoryBean를 글로벌 범위 Validator로 사용한다. (@EnableWebMvc등록 했다면 추가로 설정 필요X)

검증 항목에 따라 메시지 코드도 직접 설정 할 수 있다.



기본 구현이 없기때문에 없는 항목만 남겨둠
애노테이션 이름 => 에러코드


2) Bean Validation의 주요 애노테이션
@AssertTrue
@AssertFalse
@DecimalMax
@DecimalMin
@Max
@Min
@Digits
@Size
@Null
@NonNull
@Pattern

@NotEmpty
⭐@NotBlank
@Positive
@PositiveOrZero
⭐@Email
@Future
@FutureOrPresent
@Past
@PastOrPresent


@Controller
@RequestMapping("/member")
@RequiredArgsConstructor
public class MemberController {
private final JoinValidator joinValidator; //의존성
private final JoinService joinService;
@GetMapping("/join")
public String join(@ModelAttribute RequestJoin form){ //회원가입 양식
return "member/join";
}
@PostMapping("/join")
public String joinPs(@Valid RequestJoin form, Errors errors){ //양식 제출
//회원가입 form 에서 post 요청시 검증
//회원가입 데이터 검증
// joinValidator.validate(form, errors);
if(errors.hasErrors()){ //reject, rejectValue가 한번이라도 호출되면 true
//검증 실패시 다시 양식 보여줌
return "member/join";
}
joinService.process(form); //회원가입 처리
//검증 이상 없으면 이동
return "redirect:/member/login"; //회원가입 양식 제출 시 로그인 페이지로 리다이렉트
}
// @InitBinder
// public void initBinder(WebDataBinder binder){
// binder.setValidator(joinValidator);
// }
}
🎀로그인 페이지 검증도 각자 해보자!🎀
컨트롤러 -로그인 URL 처리 메서드(@GetMapping- 양식, @PostMapping -처리)
커맨드 객체 검증 - RequestLogin
1). Bean Validation Api - 기본 검증
2). Validator 정의 검증