2013年1月8日 星期二

在Struts2利用Cookie記錄使用者Language Preference

Struts2本身提供了com.opensymphony.xwork2.interceptor.I18nInterceptor,預設它會以瀏覽器的設定來決定locale,並且可以利用request parameter來變更,但是缺點是當瀏覽器關閉後,它並不會記得之前使用者偏好的語系是什麼,為了解決這個問題,我們使用cookie來記錄使用者的設定。

我們繼承I18nInterceptor後,只要處理cookie的部分,剩下的事情還是交給Struts2原本的邏輯來處理。
代碼:
import static org.springframework.web.util.WebUtils.getCookie;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.I18nInterceptor;

/**
 * @author linus_chien
 * 
 */
public class CookieI18nInterceptor extends I18nInterceptor {

    private static final long serialVersionUID = 3719918634789553868L;

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        Map<String, Object> params = invocation.getInvocationContext().getParameters();

        Object requestedLocale = findLocaleParameter(params);
        if (requestedLocale == null) {
            Cookie cookieLocale = findLocaleCookie();
            if (cookieLocale != null) {
                addLocaleParameter(params, cookieLocale.getValue());
            }
        } else {
            addLocaleCookie(requestedLocale.toString());
        }

        return super.intercept(invocation);
    }

    private Object findLocaleParameter(Map<String, Object> params) {
        Object locale = params.get(parameterName);
        if (locale != null && locale.getClass().isArray() && ((Object[]) locale).length == 1) {
            locale = ((Object[]) locale)[0];
        }
        return locale;
    }

    private void addLocaleParameter(Map<String, Object> params, String locale) {
        params.put(parameterName, locale);
    }

    private Cookie findLocaleCookie() {
        return getCookie(ServletActionContext.getRequest(), attributeName);
    }

    private void addLocaleCookie(String locale) {
        HttpServletResponse reponse = ServletActionContext.getResponse();
        Cookie cookieLocale = new Cookie(attributeName, locale);
        cookieLocale.setPath("/");
        cookieLocale.setMaxAge(Integer.MAX_VALUE);
        reponse.addCookie(cookieLocale);
    }
}
用這個新的CookieI18nInterceptor取代原本的I18nInterceptor即可。