[spring-session-jdbc]浏览器刷新过快,session值为null

464 阅读2分钟

问题描述

SpringBoot项目中集成spring-session-jdbc后,

配置拦截器,拦截http请求,检查是否存在session值, 如果session不为null,返回true,继续当前http请求; 如果session为null,返回false,并且返回500

但是现在有一个场景会出现session为null的情况, 浏览器从入口url进来的时候会创建一次新的会话,并且在session里面写入值 但是当浏览器刷新过快或者请求次数过多的时候,会出现session为null的情况 求指点怎么解决这个bug,为什么会出现这个bug?**

代码

创建session

这部分代码是浏览器通过第一个接口去创建appid,并且通过spring-session-jdbc创建了一个session

@RequestMapping(value = "/init", method = RequestMethod.POST)
public ResponseEntity<ApplicationIdResponse> createApplicationId(String source, HttpServletRequest request) {
    LOGGER.info("create appid started...");
    ApplicationIdResponse response = personalInfoService.createApplicationId(sourceChannel);
    // Params:create – true to create a new session for this request if necessary; false to return null if there's no current session
    HttpSession checkSession = request.getSession(false);
    log.info("[session] checkSession result: {}", checkSession);
    if (checkSession != null) {
        checkSession.invalidate();
        //request.changeSessionId();
        log.info("[session] invalidate and changeSessionId: {}", checkSession);
    }
    HttpSession session = request.getSession(true);
    session.setAttribute("refer_id", response.getApplicationId());
    return new ResponseEntity<>(response, HttpStatus.OK);
}

配置拦截器

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Resource
    BeanFactory beanFactory;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new PreRequestIntercept()).addPathPatterns(
                "/getInfo",
        );
    }
}

实现拦截器

这里只是单一的去检查session是不是null,并不做其他业务逻辑处理

当请求/init接口生成session后,在浏览器中不断刷新请求/getInfo接口的时候,偶尔会出现session为null 这个地方求指点,如何解决?

只有一个实例,不存在负载均衡问题

public class PreRequestIntercept extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try {
            HttpSession session = request.getSession(false);
            log.info("[intercept check session: {}]", session);
            if (session != null) {
                log.info("[intercept check session is not null: {}]", session);
                return true;
            } else {
                response.setStatus(response.SC_INTERNAL_SERVER_ERROR);
                log.info("[intercept check session is null and return 500: {}]", session);
                return false;
            }
        } catch(Exception e) {
            log.info("[intercept check error: {}]", e);
            return false;
        }
    }
}

yml文件配置

spring:
  session:
    store-type: jdbc
    time-out: 7200
    jdbc:
      initialize-schema: always
      cleanup-cron: 0 * * * * *
  datasource:
    minPoolSize: 100
    maxPoolSize: 100
    maxWaitTime: 30000
    url: jdbc:test-db
    username: test
    password: test
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver