// 生成 Res
Res res = I18n.use(this.getBaseName(), localLanguage);
try {
    //  ThreadLocal 方案,给 Service 用
    I18nContext.set(res);
    // 视图层需要 _res 的话,保持你现在的时机
    if (!this.isSwitchView){
        c.setAttr(this.getResName(), res);
    }
    // invoke 前后都打印一下
    Res before = (Res) c.getAttr("_res");
    System.out.println("[i18n] BEFORE invoke _res=" + (before==null?null:before.get("button.importing")));
    inv.invoke();
    Res after = (Res) c.getAttr("_res");
    System.out.println("[i18n] AFTER  invoke _res=" + (after==null?null:after.get("button.importing")));
    System.out.println("[i18n] SAME OBJ? " + (before == after));
    if (this.isSwitchView) {
        this.switchView(localLanguage, c);
    }
} finally {
    // 避免线程复用导致串语言
    I18nContext.clear();
}我有一个国际化代码是这样的,我想在control层也取到国际化语言,然后我就在invoke之前
c.setAttr(this.getResName(), res);
但是有个问题前端渲染界面的
TemplateRender
public void render() {
    this.response.setContentType(this.getContentType());
    Map<Object, Object> data = new HashMap();
    Enumeration<String> attrs = this.request.getAttributeNames();
    while(attrs.hasMoreElements()) {
        String attrName = (String)attrs.nextElement();
        data.put(attrName, this.request.getAttribute(attrName));
    }
    try {
        OutputStream os = this.response.getOutputStream();
        engine.getTemplate(this.view).render(data, os);
    } catch (Exception var4) {
        throw new RenderException(var4);
    }
}这段render方法里面吧Request里面的请求参数都放到data里面,这里也有一个国际化参数_res,他取到的值是旧的(用户第一次登录选择英语,第二次登录选择中文,这个_res的值就是英语),这是什么原因呢?
解决是解决了,把serAttr放到invoke之后就正常了,我想知道,是谁改了这个参数,不是invoke之前设置了,之后肯定也能用吗??
 
 
 
 
 
 
 
 
 
@Before(CustomerCacheInterceptor.class)
@CacheName("getMenu")
public void menu() {
}
protected void useCacheDataAndRender(Map cacheData, Controller controller) {
HttpServletRequest request = controller.getRequest();
Set> set = cacheData.entrySet();
Iterator> it = set.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
request.setAttribute((String)entry.getKey(), entry.getValue());
}
request.removeAttribute("_renderKey");
RenderInfo renderInfo = (RenderInfo)cacheData.get("_renderKey");
if (renderInfo != null) {
controller.render(renderInfo.createRender());
}
}
CustomerCacheInterceptor程序将页面缓存后,如果命中缓存会从缓存中取得信息。并覆盖掉res的国际化信息。这就导致他缓存的界面是第一次请求界面的信息,用户选的什么语言就是什么语言。另外这个还是不分用户的,其他用户进来时候取出来的语言也会是这个第一次缓存的语言数据。
当把c.setAttr(this.getResName(), res);放在了invoke之后,就表示他会执行完其他所有拦截器之后,从新把attr设置进去。
然后在TemplateRender会从新从Request里面取得新的res。
PS:这是作者有意这么控制的还是无意的啊。 I18nInterceptor故意吧c.setAttr(this.getResName(), res);放在invoke之后,然后TemplateRender,又故意从this.request.getAttributeNames();取得设置的国际化参数,再使用render方法实现的国际化。
算是国际化里面一个巨难查的隐藏BUG?