解决Nginx+Tomcat时ContextPath不同的问题
1 问题描述
项目前端模板使用Thymeleaf,在对各种URL进行格式化输出时,都使用@{uri}代码。它会自动读取项目部署的虚拟路径,添加到URI的前端输出。
真实测试和生产环境中,我们使用nginx+Tomcat的部署模式,这就会部署带来一个限制:ngxin配置proxy时,需要同后端application使用相同的context path。
一个比较典型的测试场景:同一个Tomcat,部署多个应用;同一个nginx,配置这三个应用的proxy,但要求都使用独立域名进行访问,不能添加 context path。如图:

2 Thymeleaf实现原理
仔细读Thymeleaf的源码,它对uri的封装,是通过 LinkBuilder类实现的。在SpringBoot项目中,相关的代码。

有几点需要注意:
1、 最终是在 StandardLinkBuilder中调用request.getContextPath()获取部署context.
2、 SpringTemplateEngine的构造函数中,直接new StandardLinkBuilder对象。
3、 ThymeleafAutoConfiguration的代码和相应的配置定义中,没有发现对LinkBuilder的配置参数。
3 解决方案
根据项目情况,可以有几个解决方案可供选择。
3.1 Filter + HttpServletRequestWrapper
思路:最终代码使用request.getContextPath(),我们只要重新封装一下Request,重写getContextPath()方法即可。

并在项目中添加一个Filer,核心代码为:
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { CustomContextPathRequest requestWrapper = new CustomContextPathRequest( (HttpServletRequest) request, this.contextPath); filterChain.doFilter(requestWrapper, response); } |
3.2 扩展 AutoConfiguration
咱重点介绍一下这个方法,借此机会熟悉SpringBoot的机制。
思路:SpringBoot缺省的AutoConfiguration没有提供配置LinkBuilder,我们自己实现一个AutoConfiguration,在Spring完成SpringTemplateEngine成功之后,再替换器LinkBuilder实现。

3.2.1 ManualContextLinkBuilder
例子是将context path写死为 /demo ,实际代码中,可以通过在application.propertis中的变量来实现,并配合maven profile,实现不同运行环境的差异化实现。
|
public class ManualContextLinkBuilder extends StandardLinkBuilder { private String nginxContextPath = “/demo”; @Override protected String computeContextPath(final IExpressionContext context, final String base, final Map<String, Object> parameters) { return nginxContextPath; } } |
3.2.2 ManualContextLinkBuilderConfiguration
|
@Configuration @AutoConfigureAfter(WebMvcAutoConfiguration.class) public class ManualContextLinkBuilderConfiguration { @Autowired SpringTemplateEngine springTemplateEngine; @Bean public ILinkBuilder linkBuilder() { ILinkBuilder linkBuilder = new ManualContextLinkBuilder(); springTemplateEngine.setLinkBuilder(linkBuilder); return linkBuilder; } } |
3.2.3 META-INF/spring.factories
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ tech.codestory.ManualContextLinkBuilderConfiguration |
解决Nginx+Tomcat时ContextPath不同的问题的更多相关文章
- 【nginx】解决Nginx重启时提示nginx: [emerg] bind() to 0.0.0.0:80错误
Nginx是一款轻量级的Web服务器,特点是占有内存少,并发能力强,因而使用比较广泛,蜗牛今天在一个VPS上重启Nginx时提示“nginx: [emerg] bind() to 0.0.0.0:80 ...
- 解决Nginx重启时提示nginx: [emerg] bind() to 0.0.0.0:80错误
Nginx是一款轻量级的Web服务器,特点是占有内存少,并发能力强,因而使用比较广泛,蜗牛今天在一个VPS上重启Nginx时提示“nginx: [emerg] bind() to 0.0.0.0:80 ...
- 解决启动Tomcat时遇到INFO: Destroying ProtocolHandler ["ajp-apr-8009"]
问题描述: 启动Tomcat时,出现INFO: Destroying ProtocolHandler ["ajp-apr-8009"]等信息 这说明端口号被占用了... 解决方法: ...
- 解决nginx启动时域名解析失败而导致服务启动失败的问题
问题: nginx启动或者reload的时候,会对proxy_pass后面的域名进行DNS解析,如果解析失败,启动就会失败或者reload失败. 我们是to B的产品,客户的环境可能是不通公网的,因此 ...
- 解决Nginx+Tomcat下客户端https请求跳转成http的问题
Nginx上开启https, 后端使用Tomcat, 两者间走http协议, 但发现如果tomcat应用存在跳转时, 则客户端浏览器会出现400 Bad Request的错误, 通过抓包发现原因是 ...
- 解决Nginx+Tomcat中https转http请求问题---解决js加载使用http的问题
解决js加载使用http的问题 控制台错误提示: Mixed Content: The page at '' was loaded over HTTPS, but requested an insec ...
- Nginx+tomcat负载均衡时静态页面报404
百度到的问题解决BLOG http://os.51cto.com/art/201204/326843.htm nginx+2台tomcat负载均衡,应用程序已部署,单独访问tomcat时,可以访问到所 ...
- 解决eclipse配置Tomcat时找不到server选项(Mac通用)
集成Eclipse和Tomcat时找不到server选项: 按照网上的步骤如下: 在Eclipse中,窗口(window)——首选项(preferences)——服务器(Server)——运行时环境( ...
- [转]Eclipse启动Tomcat时45秒超时解决方法
原文地址:http://it.oyksoft.com/post/6577/ Eclipse启动Tomcat时,默认配置的启动超时时长为45秒.假若项目启动超过45秒将会报错.两种解决方法:1.改XML ...
随机推荐
- 201521123045 《Java程序设计》第4周学习总结
第4周作业-面向对象设计与继承 1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 2. 书面作业 Q1.注释的应用使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclip ...
- 自定义win8资源管理器左侧导航窗格的方法
Win8自定义资源管理器左侧导航窗格: 快捷键Win+R – 输入regedit: 删除“网络”项目 HKEY_CLASSES_ROOTCLSID{F02C1A0D-BE21-4350-88B0-73 ...
- MarkDown模板
一个例子: 例子开始 1. 本章学习总结 今天主要学习了三个知识点 封装 继承 多态 2. 书面作业 Q1. java HelloWorld命令中,HelloWorld这个参数是什么含义? 今天学了一 ...
- Q:哪里可以注册hk域名?A:这里!这里!(小白绢挥手)
注意!前方有一条比你妈手中的竹板还硬的推文出没······ 咳咳,清清喉咙,预备唱! (请自动代入甜蜜蜜的曲调) 甜蜜蜜你笑的甜蜜蜜 好像花儿开在春风里 开在春风里 在哪里在哪里见过你 .HK域 ...
- python基础之字典、赋值补充
字典常用操作: 存/取info_dic={'name':'egon','age':18,'sex':'male'} print(info_dic['name11111111']) print(info ...
- 《MATLAB从入门到放弃》打通 “矩阵” 障碍
目录: » 矩阵的生成与大小 > 简单矩阵的生成 > 随机矩阵的生成 > 矩阵的大小 » 矩阵的索引与访问 » 矩阵的拼接与裁剪 > 矩阵的拼接 &g ...
- 移动端touch事件实现页面弹动--小插件
动手之前的打盹 说实话真的是好久没有更新博客了,最近一直赶项目,身心疲惫:最关键的是晚上还要回去上一波王者,实在是忙啊! 这周下来,清闲了些许,或许是因为要到国庆的缘故吧,大家都显得无精打采.俗话说的 ...
- Tomcat启动错误【Error listenerStart】
今天启动Tomcat启动不了,报以下错: org.apache.catalina.core.StandardContext startInternal SEVERE: Error listenerSt ...
- 《深入浅出设计模式》读书笔记 C#版(第一章)
原始需求和设计 事情是这样开始的,公司需要做一套程序,鸭子,设计如下: 一个鸭子父类,多个派生类,三个可override的方法. 第一次需求变更 我们要会飞的鸭子!!!!! 所以我们做了如下的更改: ...
- 18.Llinux-触摸屏驱动(详解)
本节的触摸屏驱动也是使用之前的输入子系统 1.先来回忆之前第12节分析的输入子系统 其中输入子系统层次如下图所示, 其中事件处理层的函数都是通过input_register_handler()函数注册 ...