怎樣在架構中合理的設定request中的Lcoale

來源:互聯網
上載者:User

相信很多朋友在做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,在這裡可以構造自己想要的方法:

public class LocaleRequestWrapper extends HttpServletRequestWrapper{    public LocaleRequestWrapper(HttpServletRequest request) {        super(request);    }    public Enumeration getLocales() {        Vector v = new Vector(1);        v.add(getLocale());        return v.elements();    }    public Locale getLocale() {        String localeStr = ((HttpServletRequest) getRequest()).getSession().getAttribute("locale").toString();        Locale locale =  new Locale(localeStr);        return locale;    }}

這裡,locale變數被設定在了Session中,在request中提取,並封裝了改Locale並向下傳遞。

getLocales()返回的是browser中使用者所選的所有languages的一個list。而預設情況下,getLocale()返回的是第一個,對該方法進行重寫之後,返回的就是我們放在Session中的locale了。

2.在I18NFilter 中提取使用者的request並封裝為LocaleRequestWrapper,向下傳遞:

public class I18NFilter implements Filter {    transient static protected MessageLogger LOG = MessageLogger.getLogger(I18NFilter.class);    @Override    public void init(FilterConfig filterConfig) throws ServletException {    }    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {        if (servletRequest instanceof HttpServletRequest && ((HttpServletRequest) servletRequest).getSession().getAttribute("locale") != null) {            LOG.debug("I18N filter processing...");            HttpServletRequest req = (HttpServletRequest)servletRequest;            LocaleRequestWrapper wrapper = new LocaleRequestWrapper(req);            filterChain.doFilter(wrapper, servletResponse);        } else {            filterChain.doFilter(servletRequest, servletResponse);        }    }    @Override    public void destroy() {    }}

3.在web.xml中配置該filter

<filter>        <filter-name>I18NFilter</filter-name>        <filter-class>com.rsi.uif.filter.I18NFilter</filter-class>    </filter><filter>

別忘了配置filter-mapping:

<filter-mapping>        <filter-name>I18NFilter</filter-name>        <url-pattern>/route/*</url-pattern></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 就進入我們的系統啦,融合默契。

public class LocaleRequestWrapper extends HttpServletRequestWrapper{    private Locale locale;    public LocaleRequestWrapper(HttpServletRequest request,Locale locale) {        super(request);        this.locale = locale;    }    public Enumeration getLocales() {        Vector v = new Vector(1);        v.add(getLocale());        return v.elements();    }    public Locale getLocale() {        return this.locale;    }}

這裡可以看到,我們新添加了一個欄位,叫做locale,在wrap使用者的Lcoale的時候要進行初始化:

LocaleRequestWrapper lrw = new LocaleRequestWrapper((HttpServletRequest)request,context.getUserContext().getUser().getLocale());//封裝dispatcher.forward(lrw, response);//轉寄給view

後記--值得改進一下的地方:
其實不應該把request的getLocales()給簡單的重寫掉,保留browser的locale在某些情況下是非常有用的。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.