我的第一个问题,我会尽量具体。我是相当新的Spring,我试图创建相当简单的预订系统(但这实际上并不重要).重要的是,我创建一些基本的模板,然后我会填写真实的的网页.应用程序在hibernate,mysql,我还设置了i18 n和spring安全。问题是我不能改变我的语言环境。唯一有效的是改变默认的。首先,我浏览了很多Web,我发现使用i18 n和Spring Security 比通常更复杂。我发现我需要额外的过滤器:
<filter>
<filter-name>localizationFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>localizationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
我发现这个过滤器确实是在安全过滤器之前处理的,但是它并没有以一种形式解析请求:http://someserver.com/bla/home?locale=en
,我调试了一下,好像不是为了这个目的创建的(这就是我需要的)。这是从spring示例“contacts”中提取的,但是在这个例子中,我找不到任何实际针对更改语言的代码。结果是它根本不起作用。它总是试图将locale更改为我的默认语言。好消息是,如果在调试模式下,我手动将本地设置更改为其他设置,它工作得很好,所以我感到希望在我的心中…;- )
然后我找到了一些其他的方法-通过创建我们自己的过滤器。我所做的是将找到的示例(不记得作者)与RequestContextFilter
的创建方式合并在一起。毕竟RequestContextFilter
工作正常-只是不要解析我的请求。这是新过滤器的代码:
public class InternationalizationFilter extends OncePerRequestFilter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
protected void doFilterInternal(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain filterChain)
throws ServletException, IOException {
final String newLocale = request.getParameter("locale");
if (newLocale != null) {
final Locale locale = StringUtils.parseLocaleString(newLocale
.toLowerCase());
LocaleContextHolder.setLocale(locale);
}
try {
filterChain.doFilter(request, response);
} finally {
LocaleContextHolder.resetLocaleContext();
}
}
}
正如你所看到的,请求参数locale被解析并设置了locale。有2个问题:1.在发送请求xxxxx?locale=en
后,它创建了没有“country”属性的Locale(只设置了语言).说实话我不知道这是否有问题-也许没有.2.更严重的问题是它不起作用...我的意思是它在过滤器链中的正确位置(在安全设置之前),它会产生正确的locale,并以与RequestContextFilter
相同的方式设置它...但它根本不起作用。
如果有人能让我知道如何让i18 n在spring-security中工作,我会非常高兴,基于我给出的示例或任何其他示例。
谢谢!
其他信息:我做了一些实验,看起来request中的Locale示例在某种程度上是特定的。
查看以下代码(修改了RequestContextFilter
类):
@Override
protected void doFilterInternal(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain filterChain)
throws ServletException, IOException {
final ServletRequestAttributes attributes = new ServletRequestAttributes(
request);
final Locale l = Locale.GERMAN;
final Locale l2 = request.getLocale();
LocaleContextHolder.setLocale(l,
this.threadContextInheritable);
RequestContextHolder.setRequestAttributes(attributes,
this.threadContextInheritable);
if (logger.isDebugEnabled()) {
logger.debug("Bound request context to thread: " + request);
}
(...)
如果对此方法:LocaleContextHolder.setLocale(l, this.threadContextInheritable);
我传递locale 'l'它根本不起作用。我的意思是,即使显式更改,locale也不会更改。另一方面,如果我传递Locale 'l2',它被修改为德语(在调试模式下),它可以正常工作!
这意味着由于某种原因,request.getLocale()
中的Locale示例在某种程度上受到了青睐,也许代码中稍后发生了一些我不知道/不理解的事情...
请让我知道我应该如何使用这个i18 n与安全的原因,我到了一点,我必须承认,我不知道发生了什么事...
-====-======-======--=======-====
最终解决方案/答案(但仍然有一点问题)感谢Ralph,我设法解决了我的问题。以前我走错了方向,但roo生成的项目推动了我前进。似乎我一直以错误/不准确的方式添加拦截器(以前的代码):
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
</bean>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="pl"/>
</bean>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
这样,拦截器就不会因为某种原因而被调用。
将拦截器def更改为:
<mvc:interceptors>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
</bean>
</mvc:interceptors>
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="defaultLocale" value="pl"/>
</bean>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
</bean>
...它开始正常工作,无需对security/web.xml进行任何其他更改。
现在问题解决了,但是我不确定发生了什么。从我在第二个例子中的理解(工作的那个),我使拦截器“全局”。但是为什么在第一个例子中定义的拦截器不工作?任何提示?
再次感谢您的帮助!
3条答案
按热度按时间lmyy7pcs1#
1.在发送请求xxxxx?locale=en之后,它创建了没有“country”属性的Locale(只设置了语言)。
这是预期的行为。在java中有某种层次结构。语言比国家更通用。
背后的想法是,你可以有例如文本在更常见的语言,但一些单位(如货币)在国家特定的文件。
@见:http://java.sun.com/developer/technicalArticles/Intl/IntlIntro/
1.更严重的问题是它不起作用…
它应该工作没有任何手工制作的实施!
需要注册Local Change Interceptor,并在登录页面设置permitAll。
要查看此示例的运行情况,请使用该roo脚本创建一个roo项目:
然后你必须只改变安全过滤器intersept-url模式,就像我上面展示的(
applicationContext-security.xml
)!现在您有了一个应用程序,用户可以通过应用程序中的本地更改拦截器更改其本地(当用户登录时)以及当他未登录时(在登录页面中)
lg40wkob2#
我在使用GWT应用程序时遇到过类似的本地化问题。
到过滤器,甚至图像请求被路由到过滤器.这些请求有时会忽略locale参数,因此当多个请求命中过滤器时,Locale参数不会.因此,一旦我收到locale参数,我就把它放在一个会话中.记录所有请求头和值,你可能会找到根本原因.
z9zf31ra3#
使用Spring 6,这对我来说很有用:
Spring安全不允许使用 *?lang= parameter。我不得不将以下内容添加到过滤器链中:
我创建了配置类并在其中定义了beans:
然后我可以使用Thymeleaf从任何端点发出请求: