常常有读者在公众号上问 JavaWeb 乱码的问题,昨天又有一个小伙伴问及此事,其实这个问题很简单,可是想要说清楚却并不容易,由于每一个人乱码的缘由都不同,给每位小伙伴都把乱码的缘由讲一遍也挺费时间的,所以,松哥今天决定写一篇文章,和大伙好好捋捋 JavaWeb 中的乱码问题。 html
对于一些老司机而言,其实并不太容易遇到乱码问题,可是对于一些新手来讲,乱码几乎是屡见不鲜,并且每当乱码时,网上搜了一大堆解决方案,发现本身的问题仍是没能解决,其实这就是平时研究代码不求甚解致使的,乱码问题,也要去分析,而后才能对症下药,才能药到病除。 java
首先出现乱码以后,要先去确认乱码的地方,当一个网页上出现乱码,有多是浏览器显示问题,也有多是 Java 编码问题,也有可能数据库中的数据自己就是乱码的,因此咱们要作的第一件事就是确认乱码发生的位置,缩小 bug 范围,经过打印日志或者 debug 首先去确认乱码发生的位置,而后再去进一步解决,通常来讲,乱码的缘由大体上能够分为两类: mysql
请求乱码,多是由于参数放在 URL 地址中乱码,也有多是参数放在请求体中乱码,不一样传参方案也对应了不一样的乱码解决方案。若是是响应乱码,那么缘由就会比较多了,通常来讲,有以下几种可能的缘由: web
对于不一样的乱码缘由,会有不一样的解决方案,对症下药,才能药到病除,因此当出现乱码时,你们要作的第一件事就是分析乱码发生的缘由,找到缘由了,才能找到解决方案。 spring
发生乱码是由于各自编码不一样致使的,因此,你们首先要有一个良好的开发习惯,项目编码,文件编码都要统一块儿来,松哥有个同事就由于 Freemarker 乱码,找了半天没找到缘由,后来在松哥建议下修改了项目编码,乱码问题才解决了,通常来讲,公司制度稍微成熟一些,都会对项目编码,文件编码有硬性规定的。在Eclipse 中,设置项目编码方式以下(工程的编码要提早设置,若是项目已经开发一半再去设置,已有的中文就会乱码): sql
Window->Preferences->General 数据库
而后对于 JSP 文件也须要提早设置好编码方式,以下: json
这是在 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 后端以后,就乱码了,这种乱码通常来讲,分为两种:
两种乱码缘由,对应了两种不一样的解决方案。分别来看。
这种乱码主要发生在 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 干货!