怎样在架构中合理的设置request中的Lcoale

相信很多朋友在做J2EE国际化的时候,很可能遇到这个问题。因为request中的Locale是非常重要的,它代表着用户浏览器的设置,同时,很多应用都是在这里读取用户Locale然后进行国际化的。

但是问题就在于,如果我们的应用中很多地方都适应request.getLocale()来获取Locale,但是我们希望使用自己的Locale,比如说是User信息中包含了一个叫Locale的字段。那么我们怎样使用比较方便呢?有人说把Locale存在Session中比较合适。其实这个要视情况而定,我们应用中很多使用request.getLocale(),如果我们放在Session中,那么要去改很多getLocale的方法,很不合算。

如果不需要浏览器的Locale或者说,需要让request的getLocale返回一个Locale是我们设置的User.getLcoale()字段的话,怎么解决这一问题,request没有setLocale()这一方法。

 

  • 在web.xml中使用filter,给request包装,重写getLocale()方法

1.使用HttpServletRequestWrapper包装用户的request,在这里可以构造自己想要的方法:

 

[java]  view plain copy print ?
  1. public class LocaleRequestWrapper extends HttpServletRequestWrapper{  
  2.     public LocaleRequestWrapper(HttpServletRequest request) {  
  3.         super(request);  
  4.     }  
  5.   
  6.     public Enumeration getLocales() {  
  7.         Vector v = new Vector(1);  
  8.         v.add(getLocale());  
  9.         return v.elements();  
  10.     }  
  11.   
  12.     public Locale getLocale() {  
  13.         String localeStr = ((HttpServletRequest) getRequest()).getSession().getAttribute("locale").toString();  
  14.   
  15.         Locale locale =  new Locale(localeStr);  
  16.         return locale;  
  17.     }  
  18. }  

这里,locale变量被设置在了Session中,在request中提取,并包装了改Locale并向下传递。

 

getLocales()返回的是browser中用户所选的所有languages的一个list。而默认情况下,getLocale()返回的是第一个,对该方法进行重写之后,返回的就是我们放在Session中的locale了。

2.在I18NFilter 中提取用户的request并包装为LocaleRequestWrapper,向下传递:
[java]  view plain copy print ?
  1. public class I18NFilter implements Filter {  
  2.     transient static protected MessageLogger LOG = MessageLogger.getLogger(I18NFilter.class);  
  3.     @Override  
  4.     public void init(FilterConfig filterConfig) throws ServletException {  
  5.   
  6.     }  
  7.   
  8.     @Override  
  9.     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {  
  10.         if (servletRequest instanceof HttpServletRequest && ((HttpServletRequest) servletRequest).getSession().getAttribute("locale") != null) {  
  11.             LOG.debug("I18N filter processing...");  
  12.             HttpServletRequest req = (HttpServletRequest)servletRequest;  
  13.             LocaleRequestWrapper wrapper = new LocaleRequestWrapper(req);  
  14.             filterChain.doFilter(wrapper, servletResponse);  
  15.         } else {  
  16.             filterChain.doFilter(servletRequest, servletResponse);  
  17.         }  
  18.     }  
  19.   
  20.     @Override  
  21.     public void destroy() {  
  22.     }  
  23. }  
3.在web.xml中配置该filter

 

 

[html]  view plain copy print ?
  1. <filter>  
  2.         <filter-name>I18NFilter</filter-name>  
  3.         <filter-class>com.rsi.uif.filter.I18NFilter</filter-class>  
  4.     </filter>  
  5. <filter>  
别忘了配置filter-mapping:

 

 

[html]  view plain copy print ?
  1. <filter-mapping>  
  2.         <filter-name>I18NFilter</filter-name>  
  3.         <url-pattern>/route/*</url-pattern>  
  4. </filter-mapping>  

 

这种方案是可行的,但是它有一个明显的问题:当用户第一层登陆进来的时候,由于初次访问server,session中的locale还没有设置(及可能是filter拦截的locale的时候,要访问的页面还没有还是执行,session中没有locale),这时候会出现整个架构使用了浏览器的lcoale。

 

根据我自己的具体应用,做了如下修改:

 

  • 抛开filter,在核心的servlet中的适当位置,对request进行wrap:
        在我们的Framework中,其实使用request.getLocale()来获取locale进行国际化操作的地方主要集中于view上,有一个view的Utility类,用于将request传递给view(JSP\JSF, etc).那么我们找到了合适的位置,在这里,我们不需要去读session中的lcoale,由于在核心servlet中,context是必须的,而且通过context肯定可以获得user的相关信息。比如context.getUser().getLocale().

 

        好了,再按照刚才的第一个方案中使用的wrapper,对locale封装。这样user Locale 就进入我们的系统啦,融合默契。

 

[java]  view plain copy print ?
  1. public class LocaleRequestWrapper extends HttpServletRequestWrapper{  
  2.     private Locale locale;  
  3.   
  4.     public LocaleRequestWrapper(HttpServletRequest request,Locale locale) {  
  5.         super(request);  
  6.         this.locale = locale;  
  7.     }  
  8.   
  9.     public Enumeration getLocales() {  
  10.         Vector v = new Vector(1);  
  11.         v.add(getLocale());  
  12.         return v.elements();  
  13.     }  
  14.   
  15.     public Locale getLocale() {  
  16.         return this.locale;  
  17.     }  
  18. }  
这里可以看到,我们新添加了一个字段,叫做locale,在wrap用户的Lcoale的时候要进行初始化:

 

 

[java]  view plain copy print ?
  1. LocaleRequestWrapper lrw = new LocaleRequestWrapper((HttpServletRequest)request,context.getUserContext().getUser().getLocale());//封装  
  2. dispatcher.forward(lrw, response);//转发给view  

 

后记--值得改进一下的地方:
其实不应该把request的getLocales()给简单的重写掉,保留browser的locale在某些情况下是非常有用的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值