Spring MVC, Spring Security и Hibernate не могут автоматически связывать свойства между контекстами
Я использую Spring MVC 3.0.6 и Spring security 3.0.7. Я не могу @Autowire класса RoleDao для моего пользовательского класса, когда в контексте безопасности.
мой файл web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml
/WEB-INF/security-app-context.xml
</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Security-app-context.xml:
<beans:bean id="chineseCheckersEntryPoint" class="com.nike.golf.security.ChineseCheckersAuthenticationEntryPoint" />
<beans:bean id="chineseCheckersFilter" class="com.nike.golf.security.ChineseCheckersAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
</beans:bean>
<http use-expressions="true" auto-config="false" entry-point-ref="chineseCheckersEntryPoint">
<intercept-url pattern="/secure/extreme/**" access="hasRole('supervisor')" />
<intercept-url pattern="/user/**" access="permitAll" />
<intercept-url pattern="/profile/**" access="isAuthenticated()" />
<intercept-url pattern="/secure/**" access="isAuthenticated()" />
<custom-filter position="PRE_AUTH_FILTER" ref="chineseCheckersFilter" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="chineseCheckersAuthenticationProvider" />
</authentication-manager>
<beans:bean id="chineseCheckersAuthenticationProvider" class="com.nike.golf.security.ChineseCheckersAuthenticationProvider" />
В моем пользовательском объекте, где он использует roleDao, он нулевой. Он не был подключен автоматически. Из всех исследований, которые я провел в Интернете, похоже, что они связаны с различными контекстами и невозможностью автоматической связи между ними.
Может ли кто-нибудь помочь мне понять эти контексты и как я могу привести их в один и тот же контекст?
2 ответа
Спасибо всем за вашу помощь. Мне удалось это выяснить.
Этот вопрос был похож на мой и заставил меня двигаться в правильном направлении: объявление Spring Bean в родительском контексте против дочернего контекста
Этот пост на форуме действительно упростил эту идею для меня.
В вашем файле web.xml вы определяете контекст сервлета и контекст приложения. Контекст приложения настраивается с помощью этих частей XML:
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml
/WEB-INF/security-app-context.xml
</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
любое количество файлов *context.xml, которые вы передаете в context-param> contextConfigLocation, находится в контексте приложения. Это родительский контекст.
Контекст сервлета создается в файле web.xml следующим битом xml:
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Контекст сервлета как дочерний контекст имеет доступ к контексту приложения (родительский).
Это было ключевым для меня, чтобы понять. Поэтому я перенес всю конфигурацию, которая была у меня в контексте сервлета, в контекст приложения.
Как и ответ на другой вопрос, на который я ссылался выше, @Autowired все еще не работает. Кто-нибудь знает причину этого? Таким образом, чтобы обойти это, я определил bean-компоненты и свойства в xml от самого свойства, которым я занимался, до sessionFactory.
Дело в том, что теперь я мог подключить компоненты, которые мне были нужны в xml, по всей иерархии к sessionFactory, потому что это было в том же контексте, так как я переместил его в контекст приложения из контекста сервлета, где он был раньше.
В моем вопросе я даже не опубликовал файл servlet-context.xml, потому что не думал, что к нему нужно прикасаться, но на самом деле мне нужно было перенести конфигурацию в контекст приложения, если я хочу подключить что-то к мои бобы безопасности.
Я надеюсь, что в этом есть смысл.
Вы можете представить контекст как набор бобов Spring.
Контексты могут быть вложенными, так что внешний контекст может получить доступ к bean-компонентам из внутреннего, но не наоборот. Примером этого являются типичные веб-приложения, которые имеют два контекста: внутренний, указанный с помощью contextConfigLocation
и загружен ContextLoaderListener
и внешний настроен с DispatcherServlet
,
Один из способов объединения двух XML-файлов в один контекст - введение третьего XML-файла конфигурации приложения, который включает только другие XML-файлы, используя bean:include
, И тогда вам остается только указать этот третий xml-файл для загрузчика. Но я не уверен, что вы действительно настроили 2 контекста приложения для ContextLoaderListener
, - В любом случае вы можете попробовать трюк с 3. XML-файлом.