背景
webflux 采用 gateway 集成的微服务 默认session.timeout=30min
但是修改yml配置文件之后 发现session.timout并不生效
server:
servler:
session:
timeout: PT10M
调试源码,发现时间参数是传过去了
package org.springframework.boot.web.servlet.server;
public class Session {
public void setTimeout(Duration timeout) {
this.timeout = timeout;
}
}
继续调试发现执行了context.clearConfigurationProperty();但是不确定是不是这个原因导致yml失效
package org.springframework.boot.context.properties.bind;
class JavaBeanBinder implements DataObjectBinder {
private <T> boolean bind(DataObjectPropertyBinder propertyBinder, Bean<T> bean, BeanSupplier<T> beanSupplier,
Context context) {
boolean bound = false;
for (BeanProperty beanProperty : bean.getProperties().values()) {
bound |= bind(beanSupplier, propertyBinder, beanProperty);
// 发现timeout属性调用了这个方法,里面的value被清空
context.clearConfigurationProperty();
}
return bound;
}
}
寻找相应的方法修改
1、获取登出的WebSession查看管理的session对象,发现管理类InMemoryWebSessionStore
public class InMemoryWebSessionStore implements WebSessionStore {
private class InMemoryWebSession implements WebSession {
//默认值30min
private volatile Duration maxIdleTime = Duration.ofMinutes(30);
public InMemoryWebSession(Instant creationTime) {
this.creationTime = creationTime;
this.lastAccessTime = this.creationTime;
}
@Override
public Duration getMaxIdleTime() {
return this.maxIdleTime;
}
}
}
//此处找不到其他地方调用的方法,而且只有构造方法
2、通过过滤器获取相应的webSession
@Component
@Order(Ordered.LOWEST_PRECEDENCE)
public class SessionGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
private static final Logger LOGGER = LoggerFactory.getLogger(SessionGatewayFilterFactory.class);
@Value("${server.servlet.session.timeout}") //配置文件读取数据
private Long min;
@Override
public GatewayFilter apply(Object config) {
return new innerFilter(config);
}
private class innerFilter implements GatewayFilter {
private Object config;
public innerFilter(Object config) {
this.config = config;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//由于webflux是非阻塞式编程,切记此处采用非阻塞方式获取Mono里面的对象,采用block()会抛出异常
exchange.getSession().doOnNext(res -> res.setMaxIdleTime(Duration.ofMinutes(min))).subscribe(); //修改session时间
return chain.filter(exchange);
}
}
}
参考:如何在Reactive Java中从Mono流获取字符串/对象?https://www.bilibili.com/read/cv5787745/
3、yml加上filter
#服务器相关配置
spring:
cloud:
gateway:
default-filters:
- TokenRelay
- Session
server:
port: 28180
servlet:
session:
timeout: 80