get请求中文乱码的一次小坑历险记——工作笔记

探讨了在前后端分离的项目中,GET请求出现中文乱码的原因及解决方案。通过对比不同环境的Tomcat版本,揭示了编码格式差异导致的问题,并深入分析了CharacterEncodingFilter在POST与GET请求中的作用差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

公司代码以前是前后端整合在一起的,由于要升级技术栈,现在做前后端分离。原本没有问题,前端童鞋拆分完后中文乱码的问题来了,一个导出的接口多个参数用的get请求,其中有个字段 产品名称 前端传中文到后台出现了中文乱码。
why? 询问前端同学改了什么字符集编码没?答:没有啊!
测试同学催的厉害,明天要上线了今晚必须结束测试(工期短,需求长啊)。奈何前端同学又回家了,作为后端的我只能硬着头皮去修改了,于是我尝试将其转码。
做了如下骚操作:

productName = productName == null ? null : new String(productName.getBytes("iso-8859-1"), "utf-8");

手动发布到开发环境验证,通过
提交代码,走流水线(测试环境是不允许开发插手的)发布到测试环境,等待测试同学验证,通过
测试同学高兴,前端同学高兴,我也高兴,问题“完美解决”。

第二天晚上上线,不输入产品名称可以导出。输入产品名称,无数据可导出!!!
扒开生产环境日志,心里很难受,为毛呢,生产环境日志数据级为info,在没有抛异常或错误的情况下,能看到的仅仅只有接口调用短短一两行日志。告诉自己冷静,仔细思考着为什么。这时我心里一咯噔,中文乱码!!!因为产品名称中文乱码,传输到后台执行sql后查询不到任何数据,因此返回:无数据可导出!虽然没有日志,但是凭借着经验,应该就是这个问题了。

但是话又说回来了,WTF!什么鬼啊这是!我明明做了转码了,开发、测试环境都可以,生产环境不行?
确认运维是否打了旧包,确认结果:版本无误,包没问题。这时候我已经把注意力转移到环境的问题上了。想到了我们运行的容器tomcat身上了。问了下运维生产环境tomcat版本号:tomcat 8.5.31,至此问题已经基本找到了。再次确认下开发和测试环境tomcat版本号均为:7.0.77,问题已经完全定位了:

tomcat 8 默认编码格式:utf-8, tomcat 7 默认编码格式:iso-8859-1

恰巧因为文章开头我为了修复开发和测试环境的中文乱码问题做的一次后台转码才导致在生产环境上出现了乱码。OMG,宝宝心里苦,宝宝还想说出来呢。至此后续就是内部沟通、解释等事情了。

再把话题转回来,为什么get请求会出现中文乱码而post请求没事呢?
抱着刨根问底的心态继续探索:我们的项目在web.xml中用了filter:

<filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <async-supported>true</async-supported>
        <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>

既然用了filter为毛post请求可以get请求不行呢?搞歧视?
翻看CharacterEncodingFilter源码:


	@Override
	protected void doFilterInternal(
			HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
		
		if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
			request.setCharacterEncoding(this.encoding);
			if (this.forceEncoding) {
				response.setCharacterEncoding(this.encoding);
			}
		}
		filterChain.doFilter(request, response);
	}

看了源码之后doFilterInternal方法仿佛给了我答案,原来过滤器是通过request.setCharacterEncoding(this.encoding);方式来设置编码方式的。这种方式显然post请求提交的数据,是可以通过设置生效的。但是get请求提交的内容在url中,一开始就已经按照编码分析提交内容,因此request.setCharacterEncoding(this.encoding);对其无效。

至此,疑惑已经基本解开完了,忙里偷闲记个笔记。告诫自己,帮助他人!
如文中出现错误或不准确的地方还请各位大佬不吝赐教,毕竟我菜啊(手动滑稽)!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值