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不同的问题的更多相关文章

  1. 【nginx】解决Nginx重启时提示nginx: [emerg] bind() to 0.0.0.0:80错误

    Nginx是一款轻量级的Web服务器,特点是占有内存少,并发能力强,因而使用比较广泛,蜗牛今天在一个VPS上重启Nginx时提示“nginx: [emerg] bind() to 0.0.0.0:80 ...

  2. 解决Nginx重启时提示nginx: [emerg] bind() to 0.0.0.0:80错误

    Nginx是一款轻量级的Web服务器,特点是占有内存少,并发能力强,因而使用比较广泛,蜗牛今天在一个VPS上重启Nginx时提示“nginx: [emerg] bind() to 0.0.0.0:80 ...

  3. 解决启动Tomcat时遇到INFO: Destroying ProtocolHandler ["ajp-apr-8009"]

    问题描述: 启动Tomcat时,出现INFO: Destroying ProtocolHandler ["ajp-apr-8009"]等信息 这说明端口号被占用了... 解决方法: ...

  4. 解决nginx启动时域名解析失败而导致服务启动失败的问题

    问题: nginx启动或者reload的时候,会对proxy_pass后面的域名进行DNS解析,如果解析失败,启动就会失败或者reload失败. 我们是to B的产品,客户的环境可能是不通公网的,因此 ...

  5. 解决Nginx+Tomcat下客户端https请求跳转成http的问题

    Nginx上开启https,  后端使用Tomcat,  两者间走http协议, 但发现如果tomcat应用存在跳转时, 则客户端浏览器会出现400 Bad Request的错误, 通过抓包发现原因是 ...

  6. 解决Nginx+Tomcat中https转http请求问题---解决js加载使用http的问题

    解决js加载使用http的问题 控制台错误提示: Mixed Content: The page at '' was loaded over HTTPS, but requested an insec ...

  7. Nginx+tomcat负载均衡时静态页面报404

    百度到的问题解决BLOG http://os.51cto.com/art/201204/326843.htm nginx+2台tomcat负载均衡,应用程序已部署,单独访问tomcat时,可以访问到所 ...

  8. 解决eclipse配置Tomcat时找不到server选项(Mac通用)

    集成Eclipse和Tomcat时找不到server选项: 按照网上的步骤如下: 在Eclipse中,窗口(window)——首选项(preferences)——服务器(Server)——运行时环境( ...

  9. [转]Eclipse启动Tomcat时45秒超时解决方法

    原文地址:http://it.oyksoft.com/post/6577/ Eclipse启动Tomcat时,默认配置的启动超时时长为45秒.假若项目启动超过45秒将会报错.两种解决方法:1.改XML ...

随机推荐

  1. 201521123002 《Java程序设计》第1周学习总结

    1. 本章学习总结 学习使用Markdown编写文章 jdk的安装和环境变量的设置 java的历史,目前java有三大平台,javaSE,javaEE及javaME.其中javaSE我们会经常用到,由 ...

  2. Junit4学习(二)测试失败的情况

    一,前言 首先理解: 1,测试用例不是证明你是对的,而是证明你没有错 2,测试用例用来达到想要的预期结果,但对于逻辑错误无能为力 二,两种测试失败:error And Failure 1,Failur ...

  3. Java多线程高并发学习笔记(一)——Thread&Runnable

    进程与线程 首先来看百度百科关于进程的介绍: 进程是一个具有独立功能的程序关于某个数据集合的一次运行活动.它可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体.它不只是程序的代码,还包括当前的 ...

  4. Day-17: 网络编程

    ---恢复内容开始--- 现有的互联网通讯方式,是服务器端的进程与客户端进程的通信.Python中进行网络编程,就是在Python程序本身这个进程内,连接别的服务器进程的通信端口进行通信. 互联网协议 ...

  5. WPF(C#) 矩阵拖动、矩阵动画、边缘展开动画处理。

    最近在研发新的项目,遇到了一个桌面模式下的难点--展开动画.之前动画这方面没做过,也许很多人开始做的时候也会遇到相关问题,因此我把几个重点及实际效果图总结展示出来: 我的开发环境是在VS2017下进行 ...

  6. TypeMismatchException: Provided id of the wrong type for class zhongfucheng.user.entity.User.

    今天在使用SSH框架做项目的时候出现了这个错误,找了我非常非常多的时间!!!!!!! Struts Problem Report Struts has detected an unhandled ex ...

  7. 虚拟WEB目录的映射原理

    一个文件系统目录可以被映射成为多个虚拟WEB目录,虚拟WEB目录名称可以是多级目录结构的形式,tomca按照最长路径匹配原则处理请求的URL 设置WEB站点的根目录: <Host>元素的a ...

  8. mysql 安装-zip版

    1.千万不要自己新建data,使用命令:mysqld --initialize会自动生成一大堆文件 2.没有ini文件就自己新建:

  9. “==”与"equals(object)"的区别

    一.对于基本数据类型而言只能用“==”,不能用equals来进行比较,若使用equals来进行比较,则不能通过编译 二.在非字符串的对象的比较中: “==”与“equals()”比较的均是对象在堆内存 ...

  10. Temperature hdu 3477

    Temperature Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...