过滤器中的LocaleResolver null显示它已自动装配! Spring MVC 3.1.1 / Spring Security 3.1.0

时间:2012-04-24 15:39:09

标签: spring spring-mvc localization filter spring-security

我正在使用Spring Security 3.1.0和Spring MVC 3.1.1。 我希望能够根据URL更改语言环境,即:

http://localhost:8080/abc?lang=fr

现在,这可以在“正常”情况下工作,即从一个页面到另一个页面然而,在我的应用程序中,如果我从非安全页面转到安全页面,它首先点击我的登录页面,礼貌Spring Security在它到达我想要的页面之前。

这是正常的Spring Security行为(拦截安全资源),因此这种行为没有问题。

问题是当我到达安全页面时,语言环境不会改变!它保留为默认语言环境。我...... lang = fr没有被解析出来。

我在appat-file文件中定义了与dispale-servlet.xml和outside之外的语言环境相关的bean,以执行以下操作:

<mvc:interceptors>
    <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang" />
</mvc:interceptors>

<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver" p:defaultLocale="en" />

我还试图在app-context配置中拆分上面的两个bean,只有 localResolver

我已经对此进行了很多研究,基本上,我理解我需要手动更改语言环境。

即使Spring Springs for Spring Security 3.1.0也说你需要自己的“过滤器”,或者你可以使用RequestContextFilter。但是,RequestContextFilter不会解析查询字符串中的语言环境参数。

Spring Security relies on Spring's localization support in order to actually lookup   
the appropriate message. In order for this to work, you have to make sure that the 
locale from the incoming request is stored in Spring's 
org.springframework.context.i18n.LocaleContextHolder. Spring MVC's DispatcherServlet 
does this for your application automatically, but since Spring Security's filters are 
invoked before this, the LocaleContextHolder needs to be set up to contain the correct 
Locale before the filters are called.  You can either do this in a filter yourself 
(which must come before the Spring Security filters in web.xml) or you can use 
Spring's RequestContextFilter.

我想拦截请求,然后才能触及控制器,所以我编写了自己的过滤器。

我的解决方案,基于其他人所做的,是自动装配LocaleResolver。当tomcat启动时,它在我的日志中显示“localeResolver”已经自动装配(否则应用程序将在那里失败)但是在运行时,localeResolver为NULL。

同样,有一些帖子说要在应用程序上下文中定义LocaleResolver ...我已经这样做了但是当请求发生时我仍然得到一个空的LocaleResolver。

任何想法?非常感谢。

P.S。我定义的过滤器出现在Spring Security过滤器之前。我可以调试它,它首先命中它然后它因为LocaleResolver上的NPE而死掉。

感谢,谢谢。

1 个答案:

答案 0 :(得分:4)

您是否在web.xml中定义了过滤器?如果是这样,那么过滤器类不会被Spring实例化,它由servlet容器实例化。 Spring无法自动发送它不知道的东西。

这里的一般解决方案是将web.xml中的<filter-class>声明为org.springframework.web.filter.DelegatingFilterProxy,并将targetBeanName指向您上下文中的bean,例如:

<filter>
    <filter-name>My Locale Filter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetBeanName</param-name>
        <param-value>myLocaleFilter</param-value>
    </init-param>
</filter>

在你的Spring上下文中,<bean id="myLocaleFilter">应该指向你的Filter类。

您可能还发现自定义Filter类可以方便地扩展GenericFilterBean,而不是直接实现Filter接口。