问题描述
公司需要部署一个周报管理系统,该系统目前在Windows环境下运行良好。现在,计划将其迁移到服务器上进行部署,故将这个活交给我部署,但由于系统较为陈旧,依然使用的是JSP技术栈。同时,还需要拉取tomcat:7-jre8的Docker镜像。更棘手的问题是,系统使用的是MySQL 5.7+版本,而不是当前主流的MySQL 8+,这导致在适配新的UTF-8编码格式时遇到了一些挑战。在使用Docker部署该周报管理系统后,虽然容器成功启动,但访问应用页面时却发现中文内容出现了乱码:
æ ´å°±å>>ºç<< 工程å'Œå...±å>>ºé¡¹ç›®ç®¡ç�†ç³>>ç>>Ÿ
同时,应用能够正常访问,但部分功能可能受到影响。

问题分析
通过查看应用日志和配置,我们逐步排查了可能导致乱码的原因:
- 应用编码配置:应用的JSP页面和web.xml已经配置了UTF-8编码
- Tomcat编码配置:默认Tomcat配置可能没有启用UTF-8编码支持
- MySQL字符集配置:数据库初始化和连接可能存在编码不一致问题
- 数据库连接参数:使用了不兼容的JDBC连接参数
解决方案
1. 检查应用编码配置
首先确认应用本身已经配置了UTF-8编码:
- JSP页面 :所有JSP页面都包含
<%@ page contentType="text/html;charset=UTF-8"%> - web.xml:配置了CharacterEncodingFilter,强制使用UTF-8编码
xml
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2. 调整Tomcat编码设置
修改Dockerfile的文件,为Tomcat添加UTF-8编码支持:
dockerfile
# 设置环境变量,添加UTF-8编码支持
ENV JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
# 配置Tomcat URI编码为UTF-8
RUN sed -i 's/<Connector port="8080" protocol="HTTP\/1.1"/<Connector port="8080" protocol="HTTP\/1.1" URIEncoding="UTF-8"/' /usr/local/tomcat/conf/server.xml
以下为我完整的Dockerfile的文件配置
dockerfile
# 使用官方Tomcat 7镜像作为基础镜像
FROM tomcat:7-jre8
# 维护者信息
LABEL maintainer="周报管理系统"
# 移除Tomcat默认的ROOT应用
RUN rm -rf /usr/local/tomcat/webapps/ROOT
# 将打包好的WAR文件复制到Tomcat的webapps/weekly目录
COPY ./tomcat /usr/local/tomcat/webapps/weekly
# 暴露Tomcat端口
EXPOSE 8080
# 设置环境变量,添加UTF-8编码支持
ENV JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8"
# 配置Tomcat URI编码为UTF-8
RUN sed -i 's/<Connector port="8080" protocol="HTTP\/1.1"/<Connector port="8080" protocol="HTTP\/1.1" URIEncoding="UTF-8"/' /usr/local/tomcat/conf/server.xml
# 启动Tomcat
CMD ["catalina.sh", "run"]
3. 优化MySQL配置
在docker-compose.yml中添加完整的MySQL字符集配置:
yaml
command: >
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
--init-connect='SET NAMES utf8mb4'
--skip-character-set-client-handshake
--sql-mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
4. 修复数据库连接参数
检查并修复jeeplus.properties中的数据库连接参数。旧版本MySQL驱动不支持某些参数,导致连接失败:
错误配置:
properties
jdbc.url=jdbc:mysql://mysql:3306/weekly?useUnicode=true&characterEncoding=utf-8&useSSL=false&connectionCollation=utf8mb4_unicode_ci&serverTimezone=Asia/Shanghai
正确配置:
properties
jdbc.url=jdbc:mysql://mysql:3306/weekly?useUnicode=true&characterEncoding=utf-8&useSSL=false
正确配置的修改:
- 去掉了
connectionCollation=utf8mb4_unicode_ci:这个参数与字符集的选择有关,但它通常不需要在 JDBC URL 中显式指定,除非有特别的需求,通常 MySQL 默认就会使用 utf8mb4 编码。 - 去掉了
serverTimezone=Asia/Shanghai:这个参数用于设置时区,可能在某些情况下需要,但它并不是必须的,特别是如果 MySQL 服务器的时区配置正确的话。去掉这个参数有时能避免时区冲突问题,尤其是在使用容器或者跨时区部署时。
总结,正确配置 去除了多余的配置项,确保了简单且有效的连接配置。
重新部署验证
-
停止并移除旧容器:
bashdocker-compose down -
删除旧数据卷(如果需要重新初始化数据):
bashdocker volume rm weekly_mysql_data -
重新构建镜像并启动容器:
bashdocker-compose up -d --build -
验证部署结果:
bash# 查看容器状态 docker-compose ps # 查看应用日志 docker-compose logs -f tomcat -
访问应用验证:
http://172.16.xxx.xxx:8082/weekly/a/login

分享一下
docker-compose.yml的配置
yml
# 创建一个新的用户定义网络,手动指定一个未被占用的子网
networks:
weekly_network:
driver: bridge
ipam:
config:
- subnet: 10.0.0.0/24 # 使用一个未被占用的私有网络子网
services:
# MySQL数据库服务
mysql:
image: mysql:5.7.44
container_name: weekly_mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: root_password # 替换为你的根密码
MYSQL_DATABASE: weekly # 数据库名
MYSQL_USER: weekly_user # 数据库用户名
MYSQL_PASSWORD: weekly_password # 数据库密码
ports:
- "3308:3306"
volumes:
- ./mysql/weekly.sql:/docker-entrypoint-initdb.d/init.sql # 初始化脚本
- mysql_data:/var/lib/mysql # 数据持久化
command: >
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
--init-connect='SET NAMES utf8mb4'
--skip-character-set-client-handshake
--sql-mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
networks:
- weekly_network
# Tomcat应用服务
tomcat:
build: .
container_name: weekly_tomcat
restart: always
depends_on:
- mysql
ports:
- "8082:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
volumes:
- tomcat_logs:/usr/local/tomcat/logs # 日志持久化
networks:
- weekly_network
volumes:
mysql_data:
driver: local
tomcat_logs:
driver: local
预防措施
- 统一编码标准:确保应用、Tomcat、MySQL和数据库连接都使用UTF-8编码
- 适配驱动版本:根据MySQL版本选择合适的JDBC驱动,避免使用不兼容的连接参数
- 详细日志记录:启用应用和数据库的详细日志,便于排查问题
- 定期备份数据:确保数据安全,便于恢复
- 测试编码兼容性:在开发环境中测试多语言支持,确保编码正确
- 使用utf8mb4字符集:支持完整的Unicode字符,包括emoji表情
总结
通过系统性地排查和解决,我们成功解决了周报管理系统Docker部署中的乱码问题。主要解决步骤包括:
- 调整Tomcat配置,确保启用UTF-8编码支持
- 优化MySQL配置,统一字符集设置
- 修复数据库连接参数,确保与驱动版本兼容
- 重新部署验证,确认问题解决
如果觉得有帮助,欢迎点赞收藏!有问题欢迎评论区交流~