SpringBoot集成Thymeleaf,自动在请求URL后加了jsessionid

Thymeleaf自动在URL后加了;jsessionid=的问题

今天在使用Thymeleaf生成HTML文件时,发现某些情况下生成的文件内js、css、图片等资源URL后面被添加上了 ;jsessionid=… 的后缀,导致访问404,HTML页面也无法正确的显示和加载。

问题场景
我在集成了Thymeleaf的Spring Boot项目中,定义了一个 .html 模板文件,并通过以下方式引用了一个css资源:

<link rel="stylesheet" type="text/css" th:href="@{/static/style/qzy.im.css}" />

然后在Controller中添加了一个接口,用来手动将模版渲染成静态HTML文件。
接下来问题就出现了:当我第一次手动调用这个接口后,在生成的静态HTML文件中,css资源的URL后被自动添加上了 ;jsessionid=… 的后缀:

<link rel="stylesheet" type="text/css" href="/static/style/qzy.im.css;jsessionid=AAB59EB2412C150C80EB1F03E2266641" />

这导致这个css请求404,页面无法正确显示样式。
但是,当我第二次调用接口后,;jsessionid=… 的后缀又不见了:

<link rel="stylesheet" type="text/css" href="/static/style/qzy.im.css" />

一切又莫名其妙地恢复了正常😂那么前面的问题是怎么出现的呢?

原因分析
熟悉Java Web开发的人都知道 jsessionid 是Tomcat容器用来维护会话信息的一个东西,我们经常会在请求的Cookie里发现它的身影。但是,为什么它会出现在Thymeleaf渲染后的URL上面呢?

我们只需要跟踪Thymeleaf的渲染过程,在其源码中就能发现端倪:
在这里插入图片描述
上图是渲染过程中的调用栈,最下面是Thymeleaf进入渲染过程,最上面就是执行到了处理URL的地方,我们看一下 StandardLinkBuilder.processLink(IExpressionContext context, String link) 函数的源码:

protected String processLink(final IExpressionContext context, final String link) {
    if (!(context instanceof IWebContext)) {
        return link;
    }
    final HttpServletResponse response = ((IWebContext)context).getResponse();
    return (response != null? response.encodeURL(link) : link);
}

从第5行可见,Thymeleaf调用了 HttpServletResponse 的 encodeURL 函数进行URL的重写。而在 HttpServletResponse 的实现类 org.apache.catalina.connector.Response 中我们可以找到具体的实现:
在这里插入图片描述

上面的第1176到1183行就是最关键的部分。其中第1176行通过 isEncodeable 函数来判断是否需要对URL进行替换,如果需要,那么就在第1183行调用 toEncoded 函数在URL中添加了 ;jsessionid=… 的内容:
在这里插入图片描述
因此,我们需要重点看一下 isEncodeable 函数的内容以及注释,看看其中具体做了什么判断:
在这里插入图片描述在这里插入图片描述
结合函数内容和注释我们可以知道,如果Tomcat容器无法从Cookie中获取当前的Session ID,并且上下文配置中支持从URL中获取会话信息(第1510、1511行),那么就会在URL中添加一个Session ID,即 JSESSIONID。

因此,当浏览器禁用了Cookie、或者我们首次请求没有Cookie时,Thymeleaf渲染后的HTML文件中,URL就会被自动添加上 ;jsessionid=…,这样容器就能通过URL来获取会话信息。但是这并不是我们想要的效果,如何解决这个问题呢?

解决办法

Tomcat可以通过三种方式获取会话信息,这三种方式定义在枚举 javax.servlet.SessionTrackingMode 中:

public enum SessionTrackingMode {
    COOKIE,
    URL,
    SSL
}

那么,我们只需要禁止Tomcat从URL中获取会话信息即可,在Spring Boot中,我们只需要在配置文件中添加一个配置:

server.servlet.session.tracking-modes=COOKIE

让Tomcat只能从COOKIE中获取会话信息,这样,当没有Cookie时,URL也就不会被自动添加上 ;jsessionid=… 了。

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值