12

我有如下的 Web.xml:

 <servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>mvc-dispatcher</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>/api/secure/*</url-pattern>
</filter-mapping>

[编辑]

添加弹簧安全后,我得到了错误!

java.lang.IllegalStateException:未找到 WebApplicationContext:未注册 ContextLoaderListener?

然后我添加了

 <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/mvc-dispatcher-servlet.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

那么它似乎工作正常,但是 1)问题是 bean 被创建了两次!

如果我只删除它:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/mvc-dispatcher-servlet.xml
    </param-value>
</context-param>

但是离开<listener>然后Web应用程序根本不运行

[额外的]

完整的 Web.xml 如下:

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>Spring MVC Application</display-name>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc-dispatcher</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>/api/secure/*</url-pattern>
    </filter-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/mvc-dispatcher-servlet.xml
        </param-value>
    </context-param>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

</web-app>

这是我的 mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:security="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
                            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
                            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
                            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">

    <mvc:annotation-driven/>
    <context:annotation-config/>
    <context:component-scan base-package="com.ge.wtracker"/>
    <context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--Java Persistence API config-->
    <jpa:repositories base-package="com.ge.wtracker.repository"/>

    <!--JPA and Database Config-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="defaultPersistenceUnit"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
        <property name="driverClassName" value="${database.driverClassName}"/>
        <property name="url" value="${database.url}"/>
        <property name="username" value="${database.username}"/>
        <property name="password" value="${database.password}"/>
        <property name="testOnBorrow" value="true"/>
        <property name="testOnReturn" value="true"/>
        <property name="testWhileIdle" value="true"/>
        <property name="timeBetweenEvictionRunsMillis" value="1800000"/>
        <property name="numTestsPerEvictionRun" value="3"/>
        <property name="minEvictableIdleTimeMillis" value="1800000"/>
        <property name="validationQuery" value="SELECT 1"/>
    </bean>

    <!--Spring Security-->
    <security:http create-session="stateless" entry-point-ref="restAuthenticationEntryPoint" authentication-manager-ref="authenticationManager">
        <security:intercept-url pattern="/api/secure/**" access="ROLE_USER" />
        <security:custom-filter ref="customRestFilter" position="BASIC_AUTH_FILTER" />
    </security:http>
    <!-- Configures the authentication entry point that returns HTTP status code 401 -->
    <bean id="restAuthenticationEntryPoint" class="com.ge.wtracker.web.security.RestAuthenticationEntryPoint">
        <property name="realmName" value="Not Authorized" />
    </bean>
    <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider ref="restAuthenticationProvider" />
    </security:authentication-manager>

    <!--The customRestFilter responsibles for retrieving and manipulating any request data to pass to the authentication
        provider to authenticate.-->
    <bean id="customRestFilter" class="com.ge.wtracker.web.security.RestSecurityFilter">
        <constructor-arg name="authenticationManager" ref="authenticationManager" />
        <constructor-arg name="authenticationEntryPoint" ref="restAuthenticationEntryPoint" />
    </bean>
    <bean id="restAuthenticationProvider" class="com.ge.wtracker.web.security.RestAuthenticationProvider" />

</beans>
4

3 回答 3

39

在 servlet 容器生命周期中,容器首先初始化ServletContextListener,然后初始化FilterServlet实例。

Spring Web 应用程序通常加载两个上下文:根上下文和调度程序 servlet 上下文。该类ContextLoaderListenerServletContextListener加载应用程序(或根)上下文的类。它通过web.xml 中给出context-param的名称标识要加载的文件,如下所示contextConfigLocation

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/mvc-dispatcher-servlet.xml
    </param-value>
</context-param>

或者,默认情况下,通过在/WEB-INF/applicationContext.xml. 由于您已指定/WEB-INF/mvc-dispatcher-servlet.xmlcontextConfigLocation,因此将加载该上下文。

完成此操作后,容器将初始化DispatcherServlet,它还会加载上下文。它通过具有以下 web.xml 中给出init-param的名称的元素来标识文件加载contextConfigLocation

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/some-random-location.xml</param-value>
    </init-param>
</servlet>

或者,默认情况下,通过在/WEB-INF/name-of-your-servlet-servlet.xml. 换句话说,它获取<servlet-name>元素的值并附-servlet.xml加到它并在WEB-INF.

由于您没有指定init-paramwith name contextConfigLocation,因此DispatcherServlet将上下文文件加载到/WEB-INF/mvc-dispatcher-servlet.xml,因为它的名称是mvc-dispatcher。由 加载的上下文DispatcherServlet可以访问由 加载的 bean ContextLoaderListener,这就是我们称其为根上下文(以及其他子上下文)的原因。

所有这一切都说明您ContextLoaderListener和您都通过从同一文件中加载 aDispatcherServlet来创建自己的 a 副本。ApplicationContextXmlWebApplicationContext/WEB-INF/mvc-dispatcher-servlet.xml

确定您认为应该对整个应用程序可用的 bean 或配置,并将它们放入将由ContextLoaderListener. 确定您认为应该可用的 bean 或配置DispatcherServlet,并将它们放在其上下文文件中。

于 2013-11-08T03:05:50.677 回答
3

http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch16s02.html

The framework will, on initialization of a DispatcherServlet, look for a file named [servlet-name]-servlet.xml in the WEB-INF directory of your web application and create the beans defined there (overriding the definitions of any beans defined with the same name in the global scope).

So you can remove the context-param:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/mvc-dispatcher-servlet.xml
    </param-value>
</context-param>
于 2013-11-07T01:29:12.237 回答
0

Spring MVC 然后创建一个新的 any-name.xml 并放置特定于上下文的 bean,如 Spring-security.xml 并让您的安全 bean 加载。

新的xml会是这样的

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/beans     
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.1.xsd">

 <mvc:annotation-driven/>
  <context:component-scan base-package="com"/>
<task:annotation-driven/> 
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.
config.PropertyPlaceholderConfigurer">
 <property name="location" value=""/>
    <property name="locations">
           <list>
               <value>/WEB-INF/jdbc.properties</value>
           </list>
        </property>
</bean>
<bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.databaseurl}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>            
</bean>
</beans>

现在将其包含在 web.xml 中

  <context-param>
   <param-name>contextConfigLocation</param-name>
    <param-value>  
      /WEB-INF/login-security.xml,
      /WEB-INF/application-context.xml
   </param-value>
 </context-param>

希望这会帮助你。

于 2017-12-04T05:14:20.373 回答