使用 Spring 会话数据 redis 将 Spring 会话范围的 bean 放入 Spring Session

问题描述

我使用的是 Spring 5.3、Spring session 2.4.x、spring-data-redis 2.4.x 和 Spring security 5.3。我们正在使用一个使用 JSP 的旧应用程序。我们想将会话数据存储在 Redis 中。使用代码片段 <jsp:useBean id="context" scope="session" class="com.xxx.yyy.SessionControl"/> 在 jsp 中使用的所有 bean 都被持久化到 Redis 中。我还有一个会话范围的 bean,创建如下,但这不会持久化到 Redis 中。你能告诉我如何自动将这个 bean 推送到 Redis 中吗?

@Bean
@Scope(value = "session"/*,proxyMode = ScopedProxyMode.TARGET_CLASS */)
public UserCacheData UserCacheData() {
    UserCacheData data = new UserCacheData();
    
    return data;
}

此外,我尝试了以下代码将 bean 放入 Session 但这不起作用,因为使用此方法获得的 session-id(下面代码中的 id1、id2 和 id3)与实际 servlet 请求的会话 id 不同(从org.springframework.session.web.http.SessionRepositoryFilter<S>获得)

@Autowired
ObjectFactory<HttpSession> httpSessionFactory;

@Autowired 
private HttpSession httpSession;

@Autowired
public RedisIndexedSessionRepository sessionRepository;


public static HttpSession currentSession() {
    ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();

    return attr.getRequest().getSession(false); // true == allow create
}

@Bean
@Scope(value = "session"/*,proxyMode = ScopedProxyMode.TARGET_CLASS */)
public UserCacheData UserCacheData() {
    UserCacheData data = new UserCacheData();
        
    HttpSession session = currentSession();
    if(null != session) {
        String id = session.getId();
        String id1 = (null !=httpSessionFactory) ?httpSessionFactory.getobject().getId():"";
        String id2 = (null !=httpSession) ?httpSession.getId():"";
        HttpServletRequest request =  ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        String id3 = (null != request) ? request.getSession(false).getId():"";
        session.setAttribute(UserCacheData.class.getName(),data);
    }

    return data;
}

Spring 会话配置

import java.io.IOException;

import javax.xml.datatype.XMLGregorianCalendar;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec.ThrowableMixIn;
import org.redisson.config.Config;
import org.redisson.spring.data.connection.RedissonConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.jackson2.CoreJackson2Module;
import org.springframework.security.jackson2.SecurityJackson2Modules;
import org.springframework.session.SaveMode;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.SessionRepositoryFilter;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonGenerator.Feature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTypeResolverBuilder;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.test.besystem.bapi.api.CustomDeserializer;
import com.test.besystem.bapi.api.CustomSerializer;
import com.test.besystem.bapi.api.UserCacheData;
import com.test.besystem.bapi.api.UserData;
import com.test.besystem.config.RedisConfig;
/**
 * @author dpoddar
 *
 */
@Configuration
@EnableRedisHttpSession(saveMode = SaveMode.ALWAYS)
//@EnableRedissonHttpSession
public class RedisSessionConfig {
    
    private static final String REdis_PROTOCOL_PREFIX = "redis://";
    
    @Value("${redis.host:127.0.0.1}")
    private String host;
    
    @Value("${redis.port:6379}")
    private int port;
    
    @Value("${redis.timeout:10000}")
    private int timeout;
    
    
    @Bean("springSessionDefaultRedisSerializer")
    public RedisSerializer genericJackson2RedisSerializer() {
        
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
                .withIsGetterVisibility(com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE)
                .withFieldVisibility(com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY)
                .withGetterVisibility(com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE)
                .withSetterVisibility(com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE)
                .withCreatorVisibility(com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE));
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNowN_PROPERTIES,false);
        
        mapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES,false);
        //initTypeInclusion(mapper);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.PROPERTY);
        mapper.registerModules(SecurityJackson2Modules.getModules(this.getClass().getClassLoader()));
        
        mapper.setSerializationInclusion(Include.NON_EMPTY);
        
        TypeResolverBuilder<?> typeBuilder = mapper.getDeserializationConfig().getDefaultTyper(null);
        Class clzz = typeBuilder.getDefaultImpl();
        

        mapper.getRegisteredModuleIds();
        SimpleModule simpleModule = new SimpleModule("cachemodule");
        simpleModule.addDeserializer(UserData.class,new CustomDeserializer<UserData>(UserData.class));
        simpleModule.addDeserializer(UserCacheData.class,new CustomDeserializer<UserCacheData>(UserCacheData.class));
        
        simpleModule.addSerializer(UserCacheData.class,new CustomSerializer<UserCacheData>(UserCacheData.class));
        mapper.registerModule(simpleModule);
        
        return new GenericJackson2JsonRedisSerializer(mapper);
    }
    
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)