2017-08-31 176 views
0

我已經繼承了一個使用Spring組件的現有Web應用程序,包括Spring Security。使用現有的Spring安全性通過XML設置Spring會話和Redis

我需要添加使應用程序無需會話的功能,以便在雲中託管,因此我試圖爲此應用程序啓用Spring會話。不過,作爲一個相對的春季新人,我在做這件事上有些困難。

使用Redis將Spring Data設置爲Spring Session的前身工作沒有任何問題,但在Spring會話文檔https://docs.spring.io/spring-session/docs/current/reference/html5/#httpsession-xml-spring-configuration之後導致我失敗了一連串異常或內部服務器錯誤。

我發佈了pom.xml,applicationContext.xml,servlet-context.xml和web.xml文件的所有/相關部分,希望有人能告訴我我做錯了什麼,需要配置不同,或者我錯過了,仍然需要添加。

我看到的錯誤是:

SEVERE [http-nio-8093-exec-42] org.apache.catalina.core.ApplicationContext.log StandardWrapper.Throwable 
java.lang.NoClassDefFoundError: com/lambdaworks/redis/RedisException 
    at java.lang.Class.getDeclaredMethods0(Native Method) 
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) 
    at java.lang.Class.getDeclaredMethods(Class.java:1975) 
    at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:609) 
    at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:521) 
    at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:507) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:241) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1069) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1042) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) 
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:667) 
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:633) 
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:681) 
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:552) 
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:493) 
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136) 
    at javax.servlet.GenericServlet.init(GenericServlet.java:158) 
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1183) 
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1099) 
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:779) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:133) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) 
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) 
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) 
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) 
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:748) 
Caused by: java.lang.ClassNotFoundException: com.lambdaworks.redis.RedisException 
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1285) 
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119) 
    ... 45 more 

我發現了一個建議,在網上,我應該在我的pom.xml萵苣的依賴,以解決此問題:

<dependency> 
    <groupId>biz.paluch.redis</groupId> 
    <artifactId>lettuce</artifactId> 
    <version>4.4.0.Final</version> 
</dependency> 

但包括依賴關係會產生不同的異常,這說明我現在有多個RedisConnectionFactory實例:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.data.redis.connection.RedisConnectionFactory] is defined: expected single matching bean but found 2: org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory#0,redisConnectionFactory) 

如果有人能幫我弄清楚我做錯了什麼,我將不勝感激!

的pom.xml(相關部分)

<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd"> 

<properties> 
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
    <httpcomponents-client.version>4.3.3</httpcomponents-client.version> 
    <httpcomponents-core.version>4.3.3</httpcomponents-core.version> 
    <spring.framework.version>4.2.5.RELEASE</spring.framework.version> 
    <spring.security.version>4.1.0.RELEASE</spring.security.version> 
</properties> 

<repositories> 
    <repository> 
     <id>spring-milestones</id> 
     <name>Spring Milestones</name> 
     <url>https://repo.spring.io/libs-milestone</url> 
     <snapshots> 
      <enabled>false</enabled> 
     </snapshots> 
    </repository> 
</repositories> 

<dependencies> 
    <!-- SPRING SECURITY --> 
    <dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-core</artifactId> 
     <version>${spring.security.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-web</artifactId> 
     <version>${spring.security.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-config</artifactId> 
     <version>${spring.security.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-taglibs</artifactId> 
     <version>${spring.security.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-ldap</artifactId> 
     <version>${spring.security.version}</version> 
    </dependency> 

    <!-- SPRING --> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-core</artifactId> 
     <version>${spring.framework.version}</version> 
     <exclusions> 
      <exclusion> 
       <groupId>commons-logging</groupId> 
       <artifactId>commons-logging</artifactId> 
      </exclusion> 
     </exclusions> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-context</artifactId> 
     <version>${spring.framework.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-context-support</artifactId> 
     <version>${spring.framework.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-jdbc</artifactId> 
     <version>${spring.framework.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-beans</artifactId> 
     <version>${spring.framework.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-aop</artifactId> 
     <version>${spring.framework.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-tx</artifactId> 
     <version>${spring.framework.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-expression</artifactId> 
     <version>${spring.framework.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-web</artifactId> 
     <version>${spring.framework.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-webmvc</artifactId> 
     <version>${spring.framework.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-aspects</artifactId> 
     <version>${spring.framework.version}</version> 
    </dependency> 

    <!-- SPRING DATA --> 
    <dependency> 
     <groupId>org.springframework.data</groupId> 
     <artifactId>spring-data-jpa</artifactId> 
     <version>1.10.1.RELEASE</version> 
     <exclusions> 
      <exclusion> 
       <groupId>org.springframework</groupId> 
       <artifactId>spring-core</artifactId> 
      </exclusion> 
      <exclusion> 
       <artifactId>spring-context</artifactId> 
       <groupId>org.springframework</groupId> 
      </exclusion> 
      <exclusion> 
       <groupId>org.springframework</groupId> 
       <artifactId>spring-aop</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>org.slf4j</groupId> 
       <artifactId>slf4j-api</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>org.slf4j</groupId> 
       <artifactId>jcl-over-slf4j</artifactId> 
      </exclusion> 
     </exclusions> 
    </dependency> 

    <!-- SPRING DATA WITH REDIS --> 
    <dependency> 
     <groupId>org.springframework.data</groupId> 
     <artifactId>spring-data-redis</artifactId> 
     <version>1.8.6.RELEASE</version> 
    </dependency> 
    <dependency> 
     <groupId>redis.clients</groupId> 
     <artifactId>jedis</artifactId> 
     <version>2.9.0</version> 
    </dependency> 

    <!-- SPRING SESSION --> 
    <dependency> 
     <groupId>org.springframework.session</groupId> 
     <artifactId>spring-session</artifactId> 
     <version>1.3.1.RELEASE</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.session</groupId> 
     <artifactId>spring-session-data-redis</artifactId> 
     <version>1.3.1.RELEASE</version> 
     <type>pom</type> 
    </dependency> 
    </dependencies> 
</project> 

的applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?> 
<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:mvc="http://www.springframework.org/schema/mvc" 
     xmlns:p="http://www.springframework.org/schema/p" 
     xmlns:security="http://www.springframework.org/schema/security" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 
     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/security http://www.springframework.org/schema/security/spring-security.xsd 
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> 

    <context:property-placeholder location="classpath:app.properties" /> 

    <bean id="usingAuthentication" class="java.lang.Boolean"> 
     <description>Flag indicating if authentication is being used.</description> 
     <constructor-arg> 
      <value>${usingAuthentication}</value> 
     </constructor-arg> 
    </bean> 

    <bean id="jaasmineAppName" class="java.lang.String"> 
     <description>The name of the JAAS configuration to use when sending requests to the web api.</description> 
     <constructor-arg> 
      <value>jaasmine.login</value> 
     </constructor-arg> 
    </bean> 

    <bean id="authenticationService" class="com.logiclander.jaasmine.authentication.KeyTabAuthenticationService"> 
     <description>Obtains kerberos tickets when the kerberosClientPrincipal sends requests to the web api.</description> 
     <constructor-arg ref="jaasmineAppName"/> 
    </bean> 

    <!-- HTTP CLIENT --> 
    <bean id="poolingConnectionManager" 
     class="jaxrs.ext.http4client.CustomClientConnectionManager"> 
     <property name="maxTotalConnection" value="200" /> 
     <property name="maxTotalPerRoute" value="20" /> 
    </bean> 

    <bean id="restHttpClient" 
     class="jaxrs.ext.http4client.CustomHttpClient" 
     scope="prototype"> 
     <constructor-arg name="connManager" ref="poolingConnectionManager" /> 
     <property name="sslv3" value="false"/> 
    </bean> 

    <bean id="clientExecutor" class="org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor"> 
     <constructor-arg name="httpClient" ref="restHttpClient"/> 
    </bean> 

    <!-- HTTP CLIENT FOR NVPAPI --> 
    <bean id="nvpUserPwdCredential" 
     class="org.apache.http.auth.UsernamePasswordCredentials"> 
     <constructor-arg name="userName"> <value>xyzf</value> </constructor-arg> 
     <constructor-arg name="password"> <value>xxxx</value> </constructor-arg> 
    </bean> 

    <bean id="nvpPoolingConnectionManager" 
      class="jaxrs.ext.http4client.CustomClientConnectionManager"> 
     <property name="maxTotalConnection" value="200" /> 
     <property name="maxTotalPerRoute" value="20" /> 
    </bean> 

    <bean id="nvpRestHttpClient" 
     class="jaxrs.ext.http4client.CustomHttpClient" 
     scope="prototype"> 
     <constructor-arg name="connManager" ref="nvpPoolingConnectionManager" /> 
     <property name="credentials" ref="nvpUserPwdCredential"/> 
     <property name="sslv3" value="false"/> 
    </bean> 

    <bean id="nvpClientExecutor" 
     class="org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor"> 
     <constructor-arg name="httpClient" ref="nvpRestHttpClient"/> 
    </bean> 

    <!-- 
    | 
    | REDIS 
    | 
    --> 
    <bean id="stringSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/> 

    <bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="localhost" p:port="6379" /> 

    <!-- redis template definition --> 
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="redisConnectionFactory"> 
     <property name="keySerializer" ref="stringSerializer"/> 
     <property name="valueSerializer" ref="stringSerializer"/> 
    </bean> 

    <!-- 
    | 
    | SPRING SECURITY 
    | 
    --> 

    <bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" /> 

    <security:http auto-config="false" entry-point-ref="http403EntryPoint" use-expressions="true" disable-url-rewriting="true"> 
     <security:intercept-url pattern="/logout/**" access="permitAll" requires-channel="${securityChannel}" /> 
     <security:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" requires-channel="${securityChannel}"/> 
     <security:intercept-url pattern="/user/**" access="hasAnyRole('ROLE_STUDENT','ROLE_STAFF')" requires-channel="${securityChannel}"/> 
     <security:intercept-url pattern="/**" access="permitAll" requires-channel="${securityChannel}"/> 
     <security:custom-filter position="PRE_AUTH_FILTER" ref="${cPreAuthFilter}" /> 
     <security:custom-filter position="LOGOUT_FILTER" ref="logoutFilter" /> 
     <security:csrf disabled="true" /> 
    </security:http> 

    <bean id="workstationFilter" 
      class="webmvc.security.WorkstationPreAuthFilter"> 
     <property name="authenticationManager" ref="authenticationManager"/> 
    </bean> 

    <security:authentication-manager alias="authenticationManager"> 
     <security:authentication-provider ref="preauthAuthProvider"/> 
    </security:authentication-manager> 

    <bean id="preauthAuthProvider" 
      class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider"> 
     <property name="preAuthenticatedUserDetailsService"> 
      <bean id="userDetailsServiceWrapper" 
        class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"> 
       <property name="userDetailsService" ref="${appUserDetailsService}"/> 
      </bean> 
     </property> 
    </bean> 

    <bean id="mockUserDetailsService" 
     class="webmvc.security.MockAdUserDetailsService"> 
    </bean> 

    <bean id="adUserDetailsService" 
     class="org.springframework.security.ldap.userdetails.LdapUserDetailsService"> 
     <constructor-arg ref="ldapSearch"/> 
     <constructor-arg ref="ldapAuthoritiesPopulator"/> 
     <property name="userDetailsMapper" ref="activeDirectoryUserDetailsContextMapper"/> 
    </bean> 

    <bean id="ldapSearch" 
       class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch"> 
     <constructor-arg value="OU=People,dc=ad,dc=uil,dc=edu"/> <!-- use-search-base --> 
     <constructor-arg value="(sAMAccountName={0})"/> <!-- user-search-filter --> 
     <constructor-arg ref="ldapServer"/> 
    </bean> 

    <bean id="ldapAuthoritiesPopulator" 
       class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator"> 
     <constructor-arg ref="ldapServer"/> 
     <constructor-arg value="ou=ci,ou=georgia,ou=Services,ou=SERVICES,ou=City,dc=ad,dc=uil,dc=edu"/> <!-- group search base --> 
     <property name="groupRoleAttribute" value="cn"/> <!-- cn is default --> 
     <property name="rolePrefix" value="" /> <!-- default is ROLE_ --> 
     <property name="convertToUpperCase" value="false"/> 
     <property name="searchSubtree" value="true"/> <!-- deep search --> 
     <property name="groupSearchFilter" value="(member:1.2.840.113556.1.4.1941:={0})"/> <!-- MAGIC --> 
    </bean> 

    <bean id="ldapServer" 
       class="org.springframework.security.ldap.DefaultSpringSecurityContextSource"> 
     <constructor-arg value="ldaps://ad.business.com:636"/> 
     <property name="userDn" value="cn=c-webmvc,ou=service-accounts,ou=georgia,ou=CI-Services,ou=CI,ou=City,dc=ad,dc=uil,dc=edu"/> 
     <property name="password" value="xxxx"/> 
    </bean> 

    <bean id="activeDirectoryUserDetailsContextMapper" 
      class="webmvc.security.ActiveDirectoryUserDetailsContextMapper"> 
    </bean> 

    <!-- 
    | 
    | LOGOUT CONFIGS 
    | 
    --> 
    <bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter"> 
     <constructor-arg index="0" value="${cLogoutUri}" /> 
     <constructor-arg index="1"> 
      <list> 
       <ref bean="securityContextLogoutHandler" /> 
       <ref bean="cookieClearingLogoutHandler" /> 
      </list> 
     </constructor-arg> 
     <property name="filterProcessesUrl" value="/logout" /> 
    </bean> 

    <bean id="securityContextLogoutHandler" 
       class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"> 
     <property name="invalidateHttpSession" value="true"/> 
    </bean> 

    <bean id="cookieClearingLogoutHandler" class="org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler"> 
     <constructor-arg> 
      <!-- Names of the cookies you want to remove when user logs out --> 
      <list> 
       <value>JSESSIONID</value> 
      </list> 
     </constructor-arg> 
    </bean> 

</beans> 

servlet的context.xml中

<?xml version="1.0" encoding="UTF-8"?> 
<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:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 
    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/util http://www.springframework.org/schema/util/spring-util.xsd"> 

<context:annotation-config /> 

<context:component-scan base-package="edu.illinois.cis.webmvc" /> 

<!-- expose property file to controllers --> 
<util:properties id="defaultProps" location="classpath:default.properties"/> 
<util:properties id="appProps" location="classpath:app.properties"/>   

<mvc:annotation-driven /> 
<mvc:resources mapping="/static/**" location="/static/" cache-period="3600"/> 

<bean id="viewProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> 
    <property name="locations"> 
     <list> 
      <value>classpath:default.properties</value> 
      <value>classpath:gened.properties</value> 
      <value>classpath:app.properties</value> 
     </list> 
    </property> 
</bean> 

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="prefix" value="/WEB-INF/views/"/> 
    <property name="suffix" value=".jsp"/> 
    <property name="exposedContextBeanNames"> 
     <list> 
      <value>viewProps</value> 
     </list> 
    </property> 
</bean> 

<bean id="messageSource" 
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 
    <property name="basename" value="classpath:messages" /> 
    <property name="defaultEncoding" value="UTF-8" /> 
    <property name="cacheSeconds" value="5" /> 
</bean> 

<!-- Use the combination of <context:annotation-config/> (above) and RedisHttpSessionConfiguration because 
    Spring Session does not yet provide XML Namespace support (see gh-104). This creates a Spring Bean with 
    the name of springSessionRepositoryFilter that implements Filter. The filter is what is in charge of replacing the HttpSession implementation to be backed by Spring Session. In this instance Spring Session is backed by Redis. --> 
    <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/> 

    <!-- Create a RedisConnectionFactory that connects Spring Session to the Redis Server. 
    Configure the connection to connect to localhost on the default port (6379) --> 
    <bean class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/> 
</beans> 

的web.xml

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

<servlet> 
    <servlet-name>courses</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
    <init-param> 
    <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/spring/servlet-context.xml</param-value> 
    </init-param> 
</servlet> 

<servlet-mapping> 
    <servlet-name>courses</servlet-name> 
    <url-pattern>/</url-pattern> 
</servlet-mapping> 

<!-- load applicationContext.xml --> 
<listener> 
    <listener-class> 
     org.springframework.web.context.ContextLoaderListener 
    </listener-class> 
</listener> 

<!-- ensure that the Servlet Container (i.e. Tomcat) uses the springSessionRepositoryFilter for every request --> 
<!-- DelegatingFilterProxy will look up a Bean by the name of springSessionRepositoryFilter and cast it to a Filter --> 
<!-- For every request that DelegatingFilterProxy is invoked, the springSessionRepositoryFilter will be invoked --> 
<filter> 
    <filter-name>springSessionRepositoryFilter</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>springSessionRepositoryFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
    <dispatcher>REQUEST</dispatcher> 
    <dispatcher>ERROR</dispatcher> 
</filter-mapping> 

<!-- Spring Security --> 
<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> 

<error-page> 
    <error-code>404</error-code> 
    <location>/error/404</location> 
</error-page> 
<error-page> 
    <error-code>403</error-code> 
    <location>/error/403</location> 
</error-page> 

+0

謝謝Daniel。你的解決方案適用於我 - 我只需要刪除創建RedisConnectionFactory接口的雙重實例的額外bean。 – rls

回答

1
org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type 
[org.springframework.data.redis.connection.RedisConnectionFactory] is 
defined: expected single matching bean but found 2: 
org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory#0 
,redisConnectionFactory) 

異常意味着彈簧等待RedisConnectionFactory類型的豆,但沒有的方式來定義,其中一個是使用豆,那麼我認爲這是在applicationContext.xml因爲發生的事情是在0清除,這

<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="localhost" p:port="6379" /> 

也是一個bean有聲明爲一個bean:

<bean class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/> 

並根據JedisConnectionFactoryLettuceConnectionFactory的Javadoc他們都實現了RedisConnectionFactory接口。

我的結論是,RedisHttpSessionConfiguration期待一個RedisConnectionFactory類型的bean,但它不能被注入,因爲有兩個RedisConnectionFactory bean。基於此,您可以嘗試從servlet-context.xml刪除LettuceConnectionFactory bean,因爲redisConnectionFactory bean的類型爲RedisConnectionFactory,並且已經從applicationContext.xml創建。

我希望這個信息可以幫助你解決這個問題。