Locale
DispatcherServlet을 사용하면 클라이언트의 Locale을 사용하여 메시지를 자동으로 확인할 수 있다. 이는 LocalResolver 객체를 사용한다. request가 들어오면 DispatcherServlet이 LocalResolver를 찾아 이를 설정해준다. RequestContext.getLocale()을 사용하면 LocalResolver를 통해 찾아진 Locale을 찾을 수 있다. 또한 특정 상황에 따라 Locale을 변경할 수 있는 Interceptor도 등록 가능하다.
- AcceptHeaderLocaleContextResolver : 요청 헤더의 accept-launguage 이용
Cookie Resolver
@Bean
public LocaleResolver localeResolver {
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setCookieName("_locale");
cookieLocaleResolver.setCookieMaxAge(0);
cookieLocaleResolver.setCookiePath("/");
cookieLocaleResolver.setDefaultLocale(new Locale("ja"));
return cookieLocaleResolver;
}
쿠키 값을 이용해서 Locale을 설정할 수 있다.
LocaleChangeInterceptor
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
final LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("_locale");
return localeChangeInterceptor;
}
LocaleChangeInterceptor를 빈으로 등록하여 Locale 변경을 활성화 할 수 있다. 매개변수를 감지하여 이에따라 Locale을 변경하도록 dispatcher's application context에서 LocaleResolver의 setLocale 메서드를 실행한다.
LocaleContextHolder
LocaleContext를 현재 쓰레드에 유지시켜주는 기능을 한다.
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = this.buildLocaleContext(request);
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
this.initContextHolders(request, localeContext, requestAttributes);
try {
this.doService(request, response);
} catch (IOException | ServletException var16) {
failureCause = var16;
throw var16;
} catch (Throwable var17) {
failureCause = var17;
throw new NestedServletException("Request processing failed", var17);
} finally {
this.resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
this.logResult(request, response, (Throwable)failureCause, asyncManager);
this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
}
}
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);
}
}
}
요청이 들어오면 FrameworkServlet 클래스의 processRequest 메서드 내부에서 initContextHolders 메서드를 실행해 contextHolder들을 셋팅해준다.
LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable);
threadContextInheritable 를 true로 셋팅해주면 자식 스레드에게 상속이 가능하다.
@Async 어노테이션이나 AOP를 이용하여 멀티 스레드 사용 시 사용할 수 있다.