我正在尝试在Spring MVC中自定义LocaleContext以存储一些其他信息。
我已经设置了一个自定义的localeResolver,到目前为止工作正常。但我不确定如何自定义区域设置上下文。
我写了这堂课:
/**
* Creates a store aware localisation context
*/
public class SimpleStoreAwareLocaleContext extends SimpleTimeZoneAwareLocaleContext {
private Location location;
public SimpleStoreAwareLocaleContext(Locale locale, TimeZone timeZone) {
super(locale, timeZone);
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
}
但是如何让它成为LocaleContextHolder上的默认LocaleContext?
所以当我调用它时,我希望得到一个我的语言环境上下文的实例。
LocaleContextHolder.getLocaleContext();
是否有过滤器或我需要覆盖的东西?
另外,我确保我的理解是正确的 - LocaleContext线程是否是本地的?那么每个用户应该有所不同吗?
谢谢!
答案 0 :(得分:1)
好的,没有答案,但我主要有这个工作所以这就是我做的。我基本上复制&粘贴了大量CookieLocaleResolver
,因为我需要私有方法,还有其他一些原因。但我想出了我自己的cookie解析器版本,并修改了cookie值中的格式以支持更多参数:
/**
* <p>The custom locale resolver will also handle setting up the customer's local store in the
* locale context.</p>
*
*
*/
public class StoreLocaleResolver extends CookieLocaleResolver {
private static Logger logger = LogManager.getLogger(StoreLocaleResolver.class.getName());
private Location defaultLocation;
private Location location;
@Autowired
private LocationService locationService;
/**
* The name of the request attribute that holds the Location Information.
* <p>Only used for overriding a cookie value if the locale has been
* changed in the course of the current request!
* <p>Use {@code RequestContext(Utils).getTimeZone()}
* to retrieve the current time zone in controllers or views.
* @see org.springframework.web.servlet.support.RequestContext#getTimeZone
* @see org.springframework.web.servlet.support.RequestContextUtils#getTimeZone
*/
public static final String LOCAL_STORE_REQUEST_ATTRIBUTE_NAME = CookieLocaleResolver.class.getName() + ".LOCAL_STORE";
@Override
public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) {
//super.setLocaleContext(request, response, localeContext);
Locale locale = null;
TimeZone timeZone = null;
Location location = null;
if (localeContext != null) {
removeCookie(response);
if (localeContext instanceof SimpleStoreAwareLocaleContext) {
locale = localeContext.getLocale();
location = ((SimpleStoreAwareLocaleContext) localeContext).getLocation();
timeZone = ((TimeZoneAwareLocaleContext) localeContext).getTimeZone();
}
StringBuilder bud = new StringBuilder();
if (locale != null)
bud.append("locale:" + locale);
if (timeZone != null)
{
bud.append("::");
bud.append("timezone:" + timeZone.getID());
}
if (location != null)
{
bud.append("::");
bud.append("location:" + location.getExternalIdentifier());
}
String cookieValue = bud.toString();
addCookie(response, bud.toString());
}
else {
removeCookie(response);
}
request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,
(locale != null ? locale: determineDefaultLocale(request)));
request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,
(timeZone != null ? timeZone : determineDefaultTimeZone(request)));
request.setAttribute(LOCAL_STORE_REQUEST_ATTRIBUTE_NAME,
(location != null ? location: determineDefaultLocalStore(request)));
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
SimpleStoreAwareLocaleContext localeContext = new SimpleStoreAwareLocaleContext(locale, null);
Location loc = (Location)request.getAttribute(StoreLocaleResolver.LOCAL_STORE_REQUEST_ATTRIBUTE_NAME);
if (loc != null)
{
localeContext.setLocation(loc);
}
setLocaleContext(request, response, (locale != null ? localeContext : null));
}
@Override
public Locale resolveLocale(HttpServletRequest request) {
parseLocaleCookieIfNecessary(request);
return (Locale) request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);
}
@Override
public LocaleContext resolveLocaleContext(final HttpServletRequest request) {
parseLocaleCookieIfNecessary(request);
return new StoreAwareLocaleContext() {
@Override
public Locale getLocale() {
return (Locale) request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);
}
@Override
public TimeZone getTimeZone() {
return (TimeZone) request.getAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME);
}
@Override
public Location getLocation() {
return (Location) request.getAttribute(LOCAL_STORE_REQUEST_ATTRIBUTE_NAME);
}
};
}
// copied from the parent class and extended to support parsing out the store location.
private void parseLocaleCookieIfNecessary(HttpServletRequest request) {
if (request.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME) == null) {
// Retrieve and parse cookie value.
Cookie cookie = WebUtils.getCookie(request, getCookieName());
Locale locale = null;
TimeZone timeZone = null;
if (cookie != null) {
String value = cookie.getValue();
Map<String, String> params = new HashMap<String, String>();
String[] tokens1 = value.split("::");
for (String token: tokens1){
String[] tokens2 = token.split(":");
params.put(tokens2[0], tokens2[1]);
}
String localeString = params.get("locale");
String timezoneString = params.get("timezone");
String locationString = params.get("location");
if (localeString != null)
{
locale = StringUtils.parseLocaleString(localeString);
}
if (timezoneString != null)
{
timeZone = StringUtils.parseTimeZoneString(timezoneString);
}
if (locationString != null)
{
location = locationService.findForLocaleContext(locationString, false);
}
if (logger.isDebugEnabled()) {
logger.debug("Parsed cookie value [" + cookie.getValue() + "] into locale '" + locale +
"'" + (timeZone != null ? " and time zone '" + timeZone.getID() + "'" : ""));
}
}
request.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME,
(locale != null ? locale: determineDefaultLocale(request)));
request.setAttribute(TIME_ZONE_REQUEST_ATTRIBUTE_NAME,
(timeZone != null ? timeZone : determineDefaultTimeZone(request)));
request.setAttribute(LOCAL_STORE_REQUEST_ATTRIBUTE_NAME,
(location != null ? location : determineDefaultLocalStore(request)));
}
}
/**
* Determine the default time zone for the given request,
* Called if no TimeZone cookie has been found.
* <p>The default implementation returns the specified default time zone,
* if any, or {@code null} otherwise.
* @param request the request to resolve the time zone for
* @return the default time zone (or {@code null} if none defined)
* @see #setDefaultTimeZone
*/
protected Location determineDefaultLocalStore(HttpServletRequest request) {
return getDefaultLocation();
}
@Override
protected Locale getDefaultLocale() {
logger.debug("Getting the default locale");
LocaleContextHolder.getLocaleContext();
return super.getDefaultLocale();
}
public Location getDefaultLocation() {
return defaultLocation;
}
public void setDefaultLocation(Location defaultLocation) {
this.defaultLocation = defaultLocation;
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
}
另一个主要类是扩展LocaleChangeInterceptor
,它允许我通过向任何控制器URL添加参数来更改本地存储。
/**
* <p>The custom locale resolver will also handle setting up the customer's local store in the
* locale context.</p>
*
*
*/
@Component
public class StoreLocaleChangeInterceptor extends LocaleChangeInterceptor {
private static Logger logger = LogManager.getLogger(StoreLocaleChangeInterceptor.class.getName());
/**
* Default name of the store locale specification parameter: "store".
*/
public static final String DEFAULT_STORE_PARAM_NAME = "store";
private String storeParamName = DEFAULT_STORE_PARAM_NAME;
@Autowired
private LocationService locationService;
public String getStoreParamName() {
return storeParamName;
}
public void setStoreParamName(String storeParamName) {
this.storeParamName = storeParamName;
}
public LocationService getLocationService() {
return locationService;
}
public void setLocationService(LocationService locationService) {
this.locationService = locationService;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws ServletException {
String newLocale = request.getParameter(getParamName());
String newStore = request.getParameter(this.storeParamName);
if (newStore != null || newLocale != null) {
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
if (localeResolver instanceof StoreLocaleResolver)
{
Location location = locationService.findByIdentifier(newStore);
if (location != null) {
((StoreLocaleResolver) localeResolver).setLocation(location);
request.setAttribute(StoreLocaleResolver.LOCAL_STORE_REQUEST_ATTRIBUTE_NAME, location);
}
if (newLocale != null)
{
localeResolver.setLocale(request, response, StringUtils.parseLocaleString(newLocale));
}else
{
Locale currentLocale = localeResolver.resolveLocale(request);
localeResolver.setLocale(request, response, currentLocale);
}
}
}
// Proceed in any case.
return true;
}
}
然后从LocaleContextHolder
我必须转发到上下文类型(现在是一个接口)。
@ModelAttribute("myStore")
protected Location getCurrentStore() {
LocaleContext ctx = LocaleContextHolder.getLocaleContext();
if (StoreAwareLocaleContext.class.isAssignableFrom(ctx.getClass())){
return ((StoreAwareLocaleContext) ctx).getLocation();
}else
{
return null;
}
}