经常有读者在公众号上问 JavaWeb 乱码的问题,昨天又有一个小伙伴问及此事,其实这个问题很简单,但是想要说清楚却并不容易,因为每个人乱码的原因都不一样,给每位小伙伴都把乱码的原因讲一遍也挺费时间的,因此,松哥今天决定写一篇文章,和大伙好好捋捋 JavaWeb 中的乱码问题。

对于一些老司机而言,其实并不太容易遇到乱码问题,但是对于一些新手来说,乱码几乎是家常便饭,而且每当乱码时,网上搜了一大堆解决方案,发现自己的问题还是没能解决,其实这就是平时研究代码不求甚解导致的,乱码问题,也要去分析,然后才能对症下药,才能药到病除。

整体思路

首先出现乱码之后,要先去确认乱码的地方,当一个网页上出现乱码,有可能是浏览器显示问题,也有可能是 Java 编码问题,也有可能数据库中的数据本身就是乱码的,所以我们要做的第一件事就是确认乱码发生的位置,缩小 bug 范围,通过打印日志或者 debug 首先去确认乱码发生的位置,然后再去进一步解决,一般来说,乱码的原因大致上可以分为两类:

  • 请求乱码
  • 响应乱码

请求乱码,可能是因为参数放在 URL 地址中乱码,也有可能是参数放在请求体中乱码,不同传参方案也对应了不同的乱码解决方案。如果是响应乱码,那么原因就会比较多了,一般来说,有如下几种可能的原因:

  • 数据库本身乱码
  • 数据在 Java 代码中乱码
  • 数据在浏览器显示的时候乱码
  • 数据在从 Java 应用传到数据库的过程中乱码

对于不同的乱码原因,会有不同的解决方案,对症下药,才能药到病除,所以当出现乱码时,大家要做的第一件事就是分析乱码发生的原因,找到原因了,才能找到解决方案。

基本原则

发生乱码是因为各自编码不同导致的,所以,大家首先要有一个良好的开发习惯,项目编码,文件编码都要统一起来,松哥有个同事就因为 Freemarker 乱码,找了半天没找到原因,后来在松哥建议下修改了项目编码,乱码问题才解决了,一般来说,公司制度稍微成熟一些,都会对项目编码,文件编码有硬性规定的。在Eclipse 中,设置项目编码方式如下(工程的编码要提前设置,如果项目已经开发一半再去设置,已有的中文就会乱码):

Window->Preferences->General

然后对于 JSP 文件也需要提前设置好编码方式,如下:

这是在 Eclipse 中设置文件编码,如果是在 IntelliJ IDEA中,则不需要设置JSP文件编码,因为默认就是 UTF-8,只需要提前设置下工程编码即可:

除了开发工具的编码,数据库的编码也要统一,一般来说,主要是设置一下数据库的编码和数据表的编码,如下:

设置数据库编码:

CREATE DATABASE `vhr` DEFAULT CHARACTER SET utf8;

设置数据表编码:

DROP TABLE IF EXISTS `adjustsalary`;
CREATE TABLE `adjustsalary` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`eid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这些是准备工作,这些工作做好了,还是有可能会遇到乱码问题,接下来我们就具体问题具体分析。

请求乱码

请求乱码,就是说数据在浏览器中显示是正常的,但是传到 Java 后端之后,就乱码了,这种乱码一般来说,分为两种:

  • 参数放在 URL 地址中导致的乱码
  • 参数放在请求体中导致的乱码

两种乱码原因,对应了两种不同的解决方案。分别来看。

URL 地址中的参数乱码

这种乱码主要发生在 GET 请求中,因为在 GET 请求中我们一般通过 URL 来传递参数,这个问题可以在代码中解决,但是太过于麻烦,因此一般我们直接在Tomcat配置中解决,修改 Tomcat的conf/server.xml 文件,修改 URL 编码格式,如下:

这样就可以搞定 URL 地址中的参数乱码。

请求体中的参数乱码

请求体中的参数乱码,我们可以在解析参数之前通过设置 HttpServletRequest 的编码来解决,如下:

request.setCharacterEncoding("UTF-8");

但是一样也太过于麻烦,所以如果是普通的 Servlet/JSP 项目,我们就可以直接定义一个过滤器来处理,如下:

public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
}

过滤器配置:

    <filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.sang.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

在工程编码和JSP/HTML编码都没问题的情况下,请求乱码基本上就是这两种情况。

响应乱码

如果在浏览器上加载页面看到了乱码,大家首先要确认在从服务端往浏览器写数据的前一刻,这个数据还没有乱码(即数据库中查询出来的数据是OK的,没有发生乱码的问题),那么对于这种乱码,我们只需要设置响应数据的 ContentType 就可以了,如下:

response.setContentType("text/html;charset=UTF-8");

如果从数据库中查询出来的数据就是乱码的,那么就需要去确认数据库中的编码是否 OK 。

框架处理

前面提到的方案,都是在 Servlet/JSP 项目中我们可以采用的方案,在 SSM 框架中当然也可以使用,但是,SpringMVC 框架本身也提供了一个过滤器,我们可以借用这个过滤器更加高效的解决响应乱码问题,如下:

<filter>
<filter-name>encoding</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>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

当然,上面这段配置并不能代替 Tomcat 中 conf/server.xml 中的编码配置,如果是在 Spring Boot 中,配置可以更加简单,只需要在 application.properties 中添加如下配置即可:

server.tomcat.uri-encoding=UTF-8
spring.http.encoding.force-request=true
spring.http.encoding.force-response=true

其他乱码

其他乱码主要是指使用一些第三方框架导致的乱码,例如使用 Alibaba 的 fastjson,开发者就需要在配置 HttpMessageConverter 时指定编码格式,否则就有可能出现乱码,这种第三方框架的乱码松哥没法穷举,大伙在使用时需要注意看官方文档,fastjson 的 HttpMessageConverter 配置如下:

@Bean
FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
config.setCharset(Charset.forName("UTF-8"));
converter.setFastJsonConfig(config);
converter.setDefaultCharset(Charset.forName("UTF-8"));
return converter;
}

一个隐蔽的乱码

除了前面介绍的这几种乱码之外,还有一个比较隐蔽的乱码,容易被很多初学者忽略的地方,就是数据在从 Java 应用传递到 MySQL 的过程中,发生了乱码,这种问题一般在 Windows 上不易发生,如果数据库装在 Linux 上,则这个问题就很容易发生,数据在代码中命名没有乱码,存到 MySQL 上就乱码了,但是如果直接使用 Navicat 等工具往 MySQL 上存储数据,又不会乱码,或者 MySQL 中数据没有乱码,但是用 Java 查询出来就乱码了,这种都是数据在 应用 和 数据库 之间传递时发生了乱码,解决方式很简单,在数据库连接地址上指定编码即可,如下:

db.url=jdbc:mysql:///yuetong?useUnicode=true&characterEncoding=UTF-8

大致就这些,还有一些非常偶尔的情况可能会用到 @RequestMapping 注解中的 produces 属性,在这里指定数据类型即可。

好了,差不多就这些,下次有人问你为啥我的又乱码了,直接把这篇文章甩给他。大伙有什么解决乱码的独门密器也可以一起来讨论。

关注公众号【江南一点雨】,专注于 Spring Boot+微服务以及前后端分离等全栈技术,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!

JavaWeb 乱码问题终极解决方案!的更多相关文章

  1. 【转】JSP中文乱码问题终极解决方案

    原文地址:http://blog.csdn.net/beijiguangyong/article/details/7414247 在介绍方法之前我们首先应该清楚具体的问题有哪些,笔者在本博客当中论述的 ...

  2. VIM、GVIM在WINDOWS下中文乱码的终极解决方案

    文章转自:http://www.liuhuadong.com/archives/68 vim.gvim在windows下中文乱码的终极解决方案在windows下vim的中文字体显示并不好,所以我们需要 ...

  3. JSP中文乱码问题终极解决方案

    在介绍方法之前我们首先应该清楚具体的问题有哪些,笔者在本博客当中论述的JSP中文乱码问题有如下几个方面:页面乱码.参数乱码.表单乱码.源文件乱码.下面来逐一解决其中的乱码问题. 一.JSP页面中文乱码 ...

  4. vim、gvim 在 windows 下中文乱码的终极解决方案

    vim.gvim 在 windows 下中文乱码的终极解决方案 vim ~/.vimrc 然后加入: " Gvim中文菜单乱码解决方案 " 设置文件编码格式 set encodin ...

  5. html 等页面防止中文出现乱码的终极解决方案

    网页UTF-8中文乱码问题解决方法 网页UTF-8中文乱码问题解决方法只有经过多方面测试的东西才有质量的保证和说服力,之前一直都是在本地做开发,经过本地测试也是通过的,但一发布到远程服务器上就问题百出 ...

  6. SecureCRT 下MySQL中文乱码问题终极解决方案-乾颐堂

    一.查看Linux主机系统字符集 命令: echo $LANG [root@pythontab.com ~]# echo $LANG [root@pythontab.com ~]# en_US.UTF ...

  7. Cygwin 各种情况下中文乱码--终极解决方案

    0.引言 本人从进公司以来一直负责公司Android平台下产品的NDK开发,用的工具: 01. Google的adt-bundle(集成了eclipse和sdk) 02. NDK 03. Cygwin ...

  8. php中文乱码问题的终极解决方案汇总

    乱码是我们在开发可能经常遇见,也是最让人头疼的一个问题了,下面这篇文章主要介绍了在php开发中,可能遇见中文乱码问题的终极解决方案,文中介绍好几个情况下的解决方法,需要的朋友可以参考借鉴,下面来一起看 ...

  9. 如何解决JavaWeb乱码问题

    作为一个合格的web开发人员应该是什么问题都遇到过的,尤其是乱码问题.大家也许都体会到了,我们中国人学编程,很大的一个不便就是程序的编码问题,无论学习什么技术,我们都需要探讨他的编码问题. 今天来讲一 ...

随机推荐

  1. java(一、概念和开发工具)

    Java 简介 Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称.由James Gosling和同事们共同研发,并在1995年正式 ...

  2. Java 标准 I/O 介绍

    一.Java标准I/O知识体系图: 二.I/O是什么 I/O 是Input/Output(输入.输出)的简称,输入流可以理解为向内存输入,输出流是从内存输出. 三.Java I/O 用途与对应的流一览 ...

  3. js中点与方括号及for...in

    中括号运算符总是能代替点运算符.但点运算符却不一定能全部代替中括号运算符. 当用中括号代替点时,属性名需加双引号. 中括号运算符可以用字符串变量的内容作为属性名.点运算符不能. 中括号运算符可以用纯数 ...

  4. Windows下配置 Nginx + PHP

    背景 经常倒腾系统,徘徊于 Windows 的便利和 Linux 的魔性,一旦折腾系统基本配置都要重弄,特此记录对 Nginx和PHP的基本启动.重启和退出 网上经验 网上这种东西一搜一大把,也有很多 ...

  5. Linux的文本处理工具浅谈-awk sed grep

    Linux的文本处理工具浅谈 awk   老大 [功能说明] 用于文本处理的语言(取行,过滤),支持正则 NR代表行数,$n取某一列,$NF最后一列 NR==20,NR==30 从20行到30行 FS ...

  6. Kali Linux远程连接Windows服务器

    前言: 为了在Kali上远程连接Windows系统的服务器我们需要安装两个工具,rdesktop和tsclient.另外,我们从主机服务商那里购买的Windows操作系统的服务器都是默认开启了远程连接 ...

  7. Java判断字符串是否为数字的自定义方法

    //方法一:用JAVA自带的函数 public static boolean isNumeric(String str){ for (int i = str.length();--i>=0;){ ...

  8. spring的依赖注入是什么意思

    最近学习spring框架,对依赖注入有些模糊,遂上网翻阅资料,做了下列总结,原博客为CSDN 南夏的 spring的依赖注入是什么意思,侵删! Spring 能有效地组织J2EE应用各层的对象.不管是 ...

  9. python获取操作系统平台、版本及架构

    platform模块提供了底层系统平台的相关信息 系统架构 32位还是64位 >>>import platform >>> platform.architectur ...

  10. Guns(开源后台管理系统框架)实战(一)——开发环境搭建

    1. 开发环境搭建 1.1. 开发环境要求 1.2. 配置Maven 1.3. 配置MySQL 1.4. Git克隆项目 1.5. Eclipse导入系统 2. 小结 3. 参考引用 1. 开发环境搭 ...