Docker容器tomcat中文名文件404错误不一定是URIEncoding,有可能是LANG=zh_CN.UTF-8引起

文章讲述了作者在使用Docker部署Tomcat时遇到中文文件名无法读取的问题,发现是由于启动时设置了LANG环境变量为zh_CN.UTF-8导致file.encoding变为ANSI_X3.4-1968。通过对比不同Tomcat版本和排除法,确定问题在于启动参数。最后建议在不影响功能的情况下,暂不设置LANG环境变量以解决问题。
摘要由CSDN通过智能技术生成

使用Docker部署tomcat,出现中文名文件无法读取,访问就是404错误。在网上搜索一通,都说是在tomcat的配置文件server.xml中修改一下URIEncoding为utf-8就行,但是我怎么测试都不行。最终发现,是Docker启动时,传入了环境变量LANG="zh_CN.UTF-8"导致。

先说网上通用处理方式。在tomcat根目录的conf文件夹下,修改server.xml文件,增加URIEncoding="UTF-8"配置。变成如下:

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
                URIEncoding="UTF-8" useBodyEncodingForURI="true"
               redirectPort="8443" />

但是我测试后,还是不行。中文文件访问,依然是无法找到文件,404错误。

继续寻找各种资料和解决方案,都不行。继续折腾好久,仍然没有解决。网上说的各种都试过。

最后,想想是不是tomcat版本问题。

于是用Docker启动一个最新版本的tomcat 11,啥环境变量和文件映射都不做,一测试,居然没问题。也就是tomcat 11默认就是支持中文文件名。

那么全新的tomcat9呢?什么环境变量和文件映射都不做,一测试,居然也行。原来tomcat本身是没有问题的,问题出在启动容器时的传参。现在采用排除法,找到问题参数。

当前启动传参如下。

docker run -it --name tomcat-test  --rm -p 8888:8080 \
-e TZ="Asia/Shanghai" \
-e LANG="zh_CN.UTF-8" \
-e JAVA_OPTS="-Dfile.encoding=utf-8" \
tomcat:9.0.16-jre8

逐一排查后,发现传参-e LANG="zh_CN.UTF-8"后,会导致file.encoding变成ANSI_X3.4-1968,而不是默认的UTF-8。

写个test.jsp文件,拷贝到容器内tomcat的ROOT目录下,直接访问,输出一下各种参数。

<%@ page language="java" contentType="text/html;charset=UTF-8"
		 pageEncoding="UTF-8" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.util.TimeZone" %>
<%@ page import="javax.servlet.ServletContext" %>

<!DOCTYPE html>
<html lang="zh-cn">
<head>
	<meta charset="UTF-8">
	<title>容器环境测试测试</title>
</head>
<body>

<%
	// 获取当前时间
	Date currentDate = new Date();

	// 获取当前时区
	TimeZone timeZone = TimeZone.getDefault();

	// 获取ServletContext对象
	ServletContext context = request.getServletContext();

	// 获取当前JSP页面的真实路径
	String realPath = context.getRealPath("/");
	String contextPath = context.getContextPath();
	String serverInfo = context.getServerInfo();
	String virtualServerName = context.getVirtualServerName();
%>


<p>当前时间:<%= currentDate.toString() %></p>
<p>当前时区: <%= timeZone.getDisplayName() %></p>
<p>物理路径RealPath: <%= realPath %></p>
<p>环境路径ContextPath: <%= contextPath %></p>
<p>服务端容器: <%= serverInfo %></p>
<p>虚拟服务名称: <%= virtualServerName %></p>
<p>当前字符集编码file.encoding: <%= System.getProperty("file.encoding")  %></p>
<p>Java环境变量java.opts: <%= System.getenv("JAVA_OPTS") %></p>
<p>Java环境变量sun.jnu.encoding: <%= System.getProperty("sun.jnu.encoding") %></p>
</body>
</html>

输出结果,如下图所示。 文本编码不是UTF-8,变成了ANSI_X3.4-1968。

当启动容器时,去掉该环境变量传入,就可以识别中文名文件了。

由于这个问题折腾了太久,暂时也就不想去深究为什么。想想这个LANG变量对目前功能没啥影响,就先不传入了吧。后面遇到影响了再说。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值