request 로부터의 locale resolution 과 request-response 간 locale 수정 전략을 선언한 인터페이스.
resolveLocale
, setLocale
두 가지 메서드가 선언되어있다.
Locale resolveLocale(HttpServletRequest request)
void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale)
이렇게만 보면 잘 이해가 안가니, 기본값으로 Bean으로 등록되는 AcceptHeaderLocaleResolver
를 예시로 동작을 살펴보자.
AcceptHeaderLocaleResolver
는 LocaleResolver
를 구현하며, 다음과 같이 Http 헤더의 'accept-language'에 담겨오는 locale 정보를 얻어온다.
오버라이드 된 resolveLocale 메서드 코드를 보자
@Override
public Locale resolveLocale(HttpServletRequest request) {
Locale defaultLocale = getDefaultLocale();
if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
return defaultLocale;
}
Locale requestLocale = request.getLocale();
List<Locale> supportedLocales = getSupportedLocales();
if (supportedLocales.isEmpty() || supportedLocales.contains(requestLocale)) {
return requestLocale;
}
Locale supportedLocale = findSupportedLocale(request, supportedLocales);
if (supportedLocale != null) {
return supportedLocale;
}
return (defaultLocale != null ? defaultLocale : requestLocale);
}
localeResolver
메서드엔 locale을 어디 저장하는 로직이 없지만, 스프링에선 리졸빙한Locale을 LocaleContextHolder
에 저장한다
// DispatcherServlet.java
// buildLocaleContext: 등록된 리졸버에서 뽑은 locale을 LocaleContext로 만들어 반환하는 함수
...
@Override
protected LocaleContext buildLocaleContext(final HttpServletRequest request) {
LocaleResolver lr = this.localeResolver;
if (lr instanceof LocaleContextResolver) {
return ((LocaleContextResolver) lr).resolveLocaleContext(request);
}
else {
return () -> (lr != null ? lr.resolveLocale(request) : request.getLocale());
}
}
...
// FrameworkServlet.java
// initContextHolders: localeConetext를 받아서 LocaleContextHolder에 저장
...
private void initContextHolders(HttpServletRequest request,
@Nullable LocaleContext localeContext, @Nullable RequestAttributes requestAttributes) {
if (localeContext != null) {
LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable);
}
if (requestAttributes != null) {
RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
}
}
...
이렇게 LocaleResolver
를 통해 추출되어 LocaleContextHolder
에 저장된 Locale정보는, LocaleContextHolder
의 static getLocale()
메서드를 이용해 사용할 수 있다.