我已经无休止地循环了一周,试图找到一种方法来将本地会话管理替换为存储在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();
}