使用Spring会话将会话属性存储在Redis中

时间:2019-07-17 10:14:20

标签: java netflix-zuul spring-data-redis spring-session

我已经无休止地循环了一周,试图找到一种方法来将本地会话管理替换为存储在Redis这样的数据存储中的会话。

这是我的用例,我有一个微服务架构,使用zuul作为api网关,客户端通过API网关调用了micro-service-1中的rest API。

ApiGateway的配置如下:

@EnableZuulProxy
@EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE)
public class GatewayApplication {

@Bean
public StaticFilter staticFilter() {
    return new StaticFilter();
}

@Bean
public LogFilter logFilter() {
    return new LogFilter();
}

@Bean
public AddResponseHeaderFilter addResponseHeaderFilter() {
    return new AddResponseHeaderFilter();
}

@Bean
public SessionSavingZuulPreFilter sessionSavingZuulPreFilter() {

    return new SessionSavingZuulPreFilter();
}

具有以下依赖性:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
    </dependency>

遵循以下答案:https://stackoverflow.com/a/38867506/8398143

我做了以下事情:

@Component
public class SessionSavingZuulPreFilter extends ZuulFilter {

private static final Logger log = 
LoggerFactory.getLogger(SessionSavingZuulPreFilter.class);

@Autowired
private SessionRepository<?> repository;

@Override
public String filterType() {
    return "pre";
}

@Override
public int filterOrder() {
    return 0;
}

@Override
public Object run() {

    RequestContext context = RequestContext.getCurrentContext();
    HttpSession httpSession = null;
    if (context.getRequest().getSession(false) == null) {
        httpSession = context.getRequest().getSession();
        log.info("******** new session created with ID =" + httpSession.getId() + "************");
    } else {
        httpSession = context.getRequest().getSession(false);
        log.info("========== old session with ID =" + httpSession.getId() + "==============");
    }

    // Session session = repository.findById(httpSession.getId());

    context.addZuulRequestHeader("Cookie", "SESSION=" + httpSession.getId());

    log.info("ZuulPreFilter session proxy: {}", httpSession.getId());

    return null;
}

@Override
public boolean shouldFilter() {

    // return RequestContext.getCurrentContext().getRequest().getSession(false) == null;
    return true;
}

}

问题是,当我第一次点击网关时,它在redis中创建了一个新会话并显示消息“ new session created”,当我在micro-service-1中调用设置属性的方法时,我可以看到设置属性并返回它。

当我尝试通过另一个请求(另一个调用)声明该属性的值时,它说它为null!并显示消息“旧会话”,但其ID与旧ID不同!当我显示redis ** keys **时,我发现该密钥已更改并成为从上一个请求返回的新密钥!

我想知道该属性是否已在第一个请求中存储在redis中,然后被第二个覆盖,还是首先没有存储在redis中。

这是微服务1的控制器的代码:

    @RequestMapping(value = "/add/attribute", method = RequestMethod.GET)
    @PreAuthorize("hasAuthority('AUTH_HELLO')")
    public String addSessionAttribute(HttpSession session) {
    session.setAttribute("attr", "value");

    return session.getAttribute("attr").toString();
}

public static HttpSession getRequestedSession() {
    try {
        return ((ServletRequestAttributes) 
RequestContextHolder.getRequestAttributes()).getRequest().getSession();
    } catch (Exception e) {
        return null;
    }
}

@RequestMapping(value = "/get/attribute", method = RequestMethod.GET)
@PreAuthorize("hasAuthority('AUTH_HELLO')")
public String getSessionAttribute() {
    HttpSession session = getRequestedSession();
    return session.getAttribute("attr").toString();
}

0 个答案:

没有答案