복붙노트

[SPRING] 스프링 웹, 보안 + web.xml + mvc 디스패처 + Bean이 두 번 생성됨

SPRING

스프링 웹, 보안 + web.xml + mvc 디스패처 + Bean이 두 번 생성됨

아래 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>

[편집하다]

스프링 보안을 추가 한 후에 오류가 발생합니다!

그 때 나는 덧붙였다.

 <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) 문제는 빈이 두 번 생성된다는 것입니다.

내가 그걸 제거 만한다면 :

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

그러나 를 남겨두면 웹 애플리케이션이 전혀 실행되지 않습니다.

[특별한]

전체 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>

해결법

  1. ==============================

    1.서블릿 컨테이너 라이프 사이클 동안 컨테이너는 먼저 ServletContextListener를 초기화 한 다음 필터 및 서블릿 인스턴스를 초기화합니다.

    서블릿 컨테이너 라이프 사이클 동안 컨테이너는 먼저 ServletContextListener를 초기화 한 다음 필터 및 서블릿 인스턴스를 초기화합니다.

    Spring 웹 애플리케이션은 일반적으로 루트 컨텍스트와 디스패처 서블릿 컨텍스트의 두 컨텍스트를로드한다. ContextLoaderListener 클래스는 응용 프로그램 (또는 루트) 컨텍스트를로드하는 ServletContextListener입니다. 아래와 같이 web.xml에 주어진대로 contextConfigLocation이라는 컨텍스트 매개 변수를 통해로드 할 파일을 식별합니다

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

    또는 기본적으로 /WEB-INF/applicationContext.xml에서 파일을 찾는다. contextConfigLocation으로 /WEB-INF/mvc-dispatcher-servlet.xml을 지정 했으므로 해당 컨텍스트가로드됩니다.

    이 작업이 완료되면 컨테이너는 DispatcherServlet을 초기화합니다. DispatcherServlet은 컨텍스트도로드합니다. 아래의 web.xml에 주어진대로 contextConfigLocation이라는 이름을 가진 init-param 요소를 통해 파일로드를 식별합니다

    <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.xml을 추가하고 WEB-INF에서 찾습니다.

    contextConfigLocation이라는 이름으로 init-param을 지정하지 않았으므로 이름이 mvc-dispatcher이므로 DispatcherServlet은 /WEB-INF/mvc-dispatcher-servlet.xml에 컨텍스트 파일을로드합니다. DispatcherServlet에 의해로드 된 컨텍스트는 ContextLoaderListener에 의해로드 된 Bean에 액세스 할 수 있으므로 그 이유를 루트 컨텍스트 (및 기타 자식)라고합니다.

    이 모든 것은 ContextLoaderListener와 DispatcherServlet이 /WEB-INF/mvc-dispatcher-servlet.xml의 같은 ​​파일에서 XmlWebApplicationContext를로드 할 때마다 ApplicationContext의 복사본을 생성하고 있다고 말할 수 있습니다.

    전체 응용 프로그램에서 사용할 수 있어야한다고 생각되는 bean 또는 구성을 식별하고 ContextLoaderListener가로드 할 파일에 넣으십시오. DispatcherServlet에 사용할 수 있어야한다고 생각하는 bean 또는 구성을 식별하여 해당 컨텍스트 파일에 넣으십시오.

  2. ==============================

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

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

    따라서 컨텍스트 매개 변수를 제거 할 수 있습니다.

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

    3.그런 다음 Spring MVC는 새로운 any-name.xml을 만들고 context specific beans를 배치한다. Spring-security.xml 및 보안 Bean로드.

    그런 다음 Spring MVC는 새로운 any-name.xml을 만들고 context specific beans를 배치한다. 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>
    

    이것이 당신을 도울 수 있기를 바랍니다.

  4. from https://stackoverflow.com/questions/19826228/spring-web-security-web-xml-mvc-dispatcher-bean-is-created-twice by cc-by-sa and MIT license