shiro spring mvc國際化選擇登陸語言

    項目中有一個國際化的需求:用戶登陸系統時選擇語言,登陸後所有文本信息包括頁面都轉換爲相應的語言,每個頁面不能單獨切換語言,只能登錄時選一次。項目基於shiro spring mvc搭建,下面描述一下實現思路。

    首先,spring國際化的過程:

STEP 1.

在beans.xml中配置messageSource bean:

	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<!-- <property name="basename" value="classpath:i18n/messages" /> -->
		<!-- <property name="defaultEncoding" value="UTF-8"></property> -->
		<property name="basenames">
			<list>
				<value>classpath:i18n/messages</value>
			</list>
		</property>
	</bean>

i18n/下應該有messages_en_US.properties和messages_zh_CN.properties之類的國際化文件。這樣,XmlWebApplicationContext就有了基本的國際化能力了,調用getMessage()方法即可獲取默認語言的文本了,要想獲取其他語言,還需要提供Locale參數。

STEP 2.

配置spring-mvc.xml中localeResolver bean:

	<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
	    <property name="defaultLocale" value="en_US" />
	</bean>

這樣,DispatcherServlet就裝配上了localeResolver。SessionLocaleResolver的功能是在session中查找一個特殊的屬性值,這個值是用戶選擇的Locale,如果發現了,就以這個Locale作爲本次請求的Locale。實現中,可以在登陸時向session中設置用戶所選擇的Locale,配上SessionLocaleResolver就可以讓DispatcherServlet在這個用戶每次請求時都使用這個Locale了,這樣,getMessage()的Locale參數就有了。

STEP 3.

前兩步不算難,難的是如何跟shiro集成起來。

我使用了

	<bean id="localeFilter" class="mycustom.LocaleFilter"/>
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<property name="loginUrl" value="/login" />
		<property name="successUrl" value="/" />
		<property name="unauthorizedUrl" value="/unauthorized" />
		<property name="filterChainDefinitions">
			<value>
			    /login = localeFilter, authc
			    /** = user
			</value>
		</property>
	</bean>

ShiroFilterFactoryBean有個功能,可以自動發現Filter,並將其加入Filter鏈中。這裏有個感念,shiro中認證是用javax.servlet.Filter接口實現的,因此web中普通的Filter可以跟shiro的認證鏈集成的很好,至少接口很熟悉。上面自定義了一個localeFilter bean,並配置爲/login = localeFilter, authc,這就是說先執行我們的localeFilter,再執行shiro默認的authc,這樣,就找到了一個向session中存用戶選擇的語言的地方----localeFilter。

代碼很簡單:

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		if (request.getParameter("locale") != null){
			
			HttpServletRequest req = (HttpServletRequest) request;
			HttpSession session = req.getSession();
			Locale locale = null;
			switch (request.getParameter("locale")){
			case "zh_CN":
				locale = Locale.CHINA;
				break;
			case "en_US":
				locale = Locale.US;
				break;
			}
			session.setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, locale);
		}
		chain.doFilter(request, response);
	}

代碼的功能是向session中設置用戶選擇的語言。注意,localeFilter不能放在authc後面,因爲默認的authc實現當登陸成功後,後面的Filter鏈不會執行,只能放在前面。這樣,當用戶登陸時,就可以選擇語言了。

    爲什麼要這麼麻煩呢,直接從request獲取locale參數不就好了嗎?這是不行的,因爲當shiro登陸成功後,會重定向請求,定向到登陸成功頁url,重定向之後request就獲取不到在登陸時傳的locale參數了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章