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. JAVA课程设计个人博客 学生成绩管理 201521145048 林健

    1. 团队课程设计博客链接 http://www.cnblogs.com/kawajiang/p/7062407.html 2.个人负责模块或任务说明 本人主要负责支持用户登录.验证操作,显示设计界面 ...

  2. java课程设计(团队)-五子棋

    单机五子棋小游戏 一:团队介绍 组长:网络1511,毛卓 组员:网络1511,朱潞潞 组员:网络1511,范阳斌 二:项目git提交记录截图 三:项目使用主要技术 netBeans,GUI 四:项目特 ...

  3. 201521123029《Java程序设计》第十三周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1.网络基础 1.1 比较ping www.baidu.com与ping cec.jmu. ...

  4. Linux SDK之uClinux、Broadcom、Atheros、Realtek、Ralink、Marvell、Intel

    接触的Linux SDK越来越多,整理整理,分享分享,不求系统全面,对您有帮助便足矣 文中大部分是与AP/Router SoC解决方案(单芯片WIFI 路由器解决方案)相关的Linux SDK SDK ...

  5. HashMap、HashTable、ArrayList、LinkedList、Vector区别

    HashTable和HashMap区别 ①继承不同. public class Hashtable extends Dictionary implements Map public class Has ...

  6. JDBC在javaweb中的应用之分页数据查询

    分页查询 分页查询是java web开发中经常使用到的技术.在数据库中数据量非常大的情况下,不适合将所有的数据全部显示到一个页面中,同时为了节约程序以及数据库的资源,就需要对数据进行分页查询操作. 通 ...

  7. 文件的inode号操作

    linux给每个文件生成了一个唯一的inode编号,命令行下操作文件需要输入文件名,如果遇到文件名特别难输入(或者包含特殊符号)的情况,可以用inode号操作文件. 可以用这个命令查看inode号: ...

  8. 作为一个新人,怎样学习嵌入式Linux

    作为一个新人,怎样学习嵌入式Linux?被问过太多次,特写这篇文章来回答一下. 在学习嵌入式Linux之前,肯定要有C语言基础.汇编基础有没有无所谓(就那么几条汇编指令,用到了一看就会). C语言要学 ...

  9. Openlayers系列(一)关于地图投影的理解

    背景 近期开发以MongoDB为基础的分布式地理数据管理平台系统,被要求做一个简单的demo给客户进行演示.于是笔者便打算向数据库中存储一部分瓦片数据,写一个简单的存取服务器,使用Openlayers ...

  10. python 库之lxml安装 坑一个

    error: command 'C:\\Users\\Admin\\AppData\\Local\\Programs\\Common\\Microsoft\\Visual C++ for Python ...