spring-session是否用HttpSession保存bean?

时间:2018-09-11 22:49:56

标签: java spring jsf redis spring-session

我正在与Redis一起在我的JEE项目中实现spring-session。 HttpSession正在我的Redis服务器上保存和更新,在节点故障转移的情况下,我可以使用它。

问题是,我的会话范围的bean不会与Redis中的会话一起保存,因此,我不能在集群上使用,因为用户需要存储在bean上的信息才能使用许多功能(坚定)。

我想念什么吗?我找不到很多有关此方面的信息,而且由于我是Spring的新手,所以变得令人困惑。会话中是否将bean(或者可以将其存储)存储在Redis中?这是我的实现:

web.xml:     

<context-param>
    <param-name>primefaces.THEME</param-name>
    <param-value>bootstrap</param-value>
</context-param>

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Production</param-value>
</context-param>

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.faces</url-pattern>
</servlet-mapping>

<session-config>
    <session-timeout>30</session-timeout>
</session-config>
<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>

<context-param>
    <param-name>
        javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE
    </param-name>
    <param-value>true</param-value>
</context-param>

<context-param>
    <param-name>com.sun.faces.expressionFactory</param-name>
    <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>

<welcome-file-list>
    <welcome-file>login.faces</welcome-file>
</welcome-file-list>

<error-page>
    <exception-type>com.exception.InvalidPasswordException</exception-type>
    <location>/ErroServlet</location>
</error-page>
<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/login.faces</location>
</error-page>
<error-page>
    <!-- Missing login -->
    <error-code>401</error-code>
    <location>/error.jsp</location>
</error-page>
<error-page>
    <!-- Forbidden directory listing -->
    <error-code>403</error-code>
    <location>/error.jsp</location>
</error-page>
<error-page>  
    <error-code>404</error-code>  
    <location>/error404.jsp</location>  
</error-page> 
<error-page>
    <!-- Uncaught exception -->
    <error-code>500</error-code>
    <location>/error.jsp</location>
</error-page>
<error-page>
    <!-- Unsupported servlet method -->
    <error-code>503</error-code>
    <location>/error.jsp</location>
</error-page>
<error-page>  
    <exception-type>java.lang.Exception</exception-type>  
    <location>/error.jsp</location>  
</error-page>

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

<listener>
    <listener-class>
        org.springframework.web.context.request.RequestContextListener
    </listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/*.xml
    </param-value>
</context-param>
<listener>

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

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

<filter>
    <filter-name>UserCheckFilter</filter-name>
    <filter-class>com.servlet.UserCheckFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>UserCheckFilter</filter-name>
    <url-pattern>/admin/*</url-pattern>
    <url-pattern>/dashboard/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>UserLogCheckFilter</filter-name>
    <filter-class>com.servlet.UserLogCheckFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>UserLogCheckFilter</filter-name>
    <url-pattern>/login.faces</url-pattern>
</filter-mapping>


<filter>
    <filter-name>AWSXRayServletFilter</filter-name>
    <filter-class>com.amazonaws.xray.javax.servlet.AWSXRayServletFilter</filter-class>
    <init-param>
        <param-name>fixedName</param-name>
        <param-value>app</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>AWSXRayServletFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

session.xml:      

<context:annotation-config/>

<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration" />

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

pom.xml:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session</artifactId>
        <version>1.3.3.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
        <version>1.3.3.RELEASE</version>
        <type>pom</type>
    </dependency>

控制器:(抽象控制器实现Serializable)

...

@Named
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Controller extends AbstractController {

    // EJB to access database using JPA
    @EJB(mappedName = "java:global/app/app-ejb/ControllerService!com.service.ControllerService")
    ControllerService controllerService;

    // A class with my JPA Entity used in the form and some other properties
    private FormFields formFields;

...

1 个答案:

答案 0 :(得分:1)

如果要从请求中获取会话,则应在springSessionRepositoryFilter之后添加此过滤器

<filter>
    <filter-name>requestContextFilter</filter-name>
    <filter-class>org.springframework.web.filter.RequestContextFilter
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>requestContextFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

我也没有在您的web.xml中看到此配置,这对于在集群中使用很重要

<context-param>
    <param-name>org.apache.myfaces.USE_ENCRYPTION</param-name>
    <param-value>false</param-value>
</context-param>

因此,当您将USE_ENCRYPTION设置为false时,群集中的节点可以检索会话中的数据。

P.S。在使用客户端状态保存而不是禁用加密时,使用https://stackoverflow.com/a/35626681/4431053很重要。感谢@Kukeltje。

对于Myfaces,您还可以使用以下配置进行加密:

 <context-param>
        <param-name>org.apache.myfaces.ALGORITHM</param-name>
        <param-value>AES</param-value>
    </context-param>
    <!-- Defines the secret (Base64 encoded) used to initialize the secret key
         for encryption algorithm. The size of it depends on the algorithm used for encryption -->
    <context-param>
        <param-name>org.apache.myfaces.SECRET</param-name>
        <param-value>MoH3NzQ1Njc4OTAxMjM0NTY3ODkwMTIz</param-value>
    </context-param>
    <!-- Define the initialization code (Bas64 encoded) that are used to initialize the secret key used
         on the Message Authentication Code algorithm. The size of it depends on the algorithm used for mac calculation -->
    <context-param>
        <param-name>org.apache.myfaces.MAC_SECRET</param-name>
        <param-value>SaEiDiEyMzQ=</param-value>
    </context-param>