由于最近一个项目的MVC层框架用的是JSF,所以在摸索中遇到了不少的问题,其中有一项就是关于国际化的的问题。
小弟在网上找了很多的资料,其实无外乎内容就都那样,可不知是小弟人品太差还是由于确实技术上有问题,按照网上的配置老是会出现如下情况。
页面上有一个选择语言栏的下拉框,当小弟选择不同语言的时候,由于调用(action或者actionlistener)的方法没有返回值,页面会出现在当前页面刷新的状况,可是页面刷新之后,上面的输出依旧没有改变,是中文的还是中文,但是在浏览器重新打开一个窗口访问当前URL的时候,就会发现语言已经切换了,不知道大家明白我说的没有。简单说就是点击更换语言后页面有刷新动作,但实际在页面上看不出变化,一旦重新打开一个窗口(new window 不是 new session),就可以看到变化后的结果。
后来小弟发现,其实只要在点击语言选择栏后,为调用的方法增加返回值(也就是返回一个String),在配置文件中跳转回当前页面并加上<redirect/>标签,也就是说在你每次选择完语言后,页面会重定向到当前页面,一切就显示正常了。
但这里出现了一个问题,如果有十个甚至一百个页面,那岂不是要写上成百上千个导航配置,那样是很麻烦的。
因此,我想起了servert中的HttpServletResponse的重定向方法,那么我只需要在更改语言的方法中,每次更改完语言地区后利用HttpServletResponse重定向会当前的请求发起页面不就解决了吗,因此我写了如下代码。
首先,为了可扩展性,我定义了一个abstract的父类BaseBo,这个类主要就是用于在JSF框架中取得HttpServert的一些内置对象,以及sping的一个获取bean的方法。
import javax.faces.application.Application; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; public abstract class BaseBO { // Get FacesContext protected FacesContext getFacesContext() { return FacesContext.getCurrentInstance(); } // Get Application protected Application getApplication() { return getFacesContext().getApplication(); } // Get HttpServletRequest protected HttpServletRequest getRequest() { return (HttpServletRequest) getFacesContext().getExternalContext() .getRequest(); } // Get HttpServletResponse protected HttpServletResponse getResponse() { return (HttpServletResponse) getFacesContext().getExternalContext() .getResponse(); } // Get HttpSession protected HttpSession getSession() { ExternalContext extContext = FacesContext.getCurrentInstance() .getExternalContext(); HttpSession session = (HttpSession) extContext.getSession(false); return session; } // Get Bean protected Object getBeanObject(String beanName) { ApplicationContext ctx = WebApplicationContextUtils .getWebApplicationContext(getSession().getServletContext()); return ctx.getBean(beanName); } }
然后我有一个专门用于控制loacle的类和方法,并继承了BaseBo,如下代码(PS, locale属性已经通过spring容器默认注入了"cn")
import java.io.IOException; import javax.faces.event.ValueChangeEvent; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LocaleBo extends BaseBO { private String locale; public String getLocale() { return locale; } public void setLocale(String locale) { this.locale = locale; } // Change locale setting. public void changeLocale(ValueChangeEvent e) throws IOException { HttpServletRequest request = this.getRequest(); HttpServletResponse response = this.getResponse(); if (locale.equals("cn")) { locale = "en"; } else { locale = "cn"; } String reqURL = request.getRequestURI(); System.out.println(reqURL); response.sendRedirect(reqURL); } }
页面选择语言的下拉代码如下(managed-bean配置以及properties文件的配置就不多讲了,不懂的可以问问谷大哥或者百大哥)
<f:view locale="#{localeSetting.locale}"> <f:loadBundle basename="resources.messages" var="msgs" /> <h:form> <h:selectOneMenu styleClass="toplink" immediate="true" onchange="this.form.submit();" value="#{localeSetting.locale}" valueChangeListener="#{localeSetting.changeLocale}"> <f:selectItem itemValue="en" itemLabel="#{msgs.LBL_EN_LANGUAGE}" /> <f:selectItem itemValue="cn" itemLabel="#{msgs.LBL_CN_LANGUAGE}" /> </h:selectOneMenu> </h:form> </f:view>
支持,当你每次选择下拉菜单的时候,都会调用changeLocale方法去改变locale值,并且在执行完成后会重定向到请求的页面,也就解决了,页面无法显示正常语言的问题了。
可能之前看文章不仔细才造成小弟不得不这样“瞎搞”,还望各位高手指出,但请勿喷我啊,小弟会流泪的,哈哈,感谢了。