摘要:經(jīng)常有讀者在公眾號上問亂碼的問題,昨天又有一個小伙伴問及此事,其實這個問題很簡單,但是想要說清楚卻并不容易,因為每個人亂碼的原因都不一樣,給每位小伙伴都把亂碼的原因講一遍也挺費時間的,因此,松哥今天決定寫一篇文章,和大伙好好捋捋中的亂碼問題
經(jīng)常有讀者在公眾號上問 JavaWeb 亂碼的問題,昨天又有一個小伙伴問及此事,其實這個問題很簡單,但是想要說清楚卻并不容易,因為每個人亂碼的原因都不一樣,給每位小伙伴都把亂碼的原因講一遍也挺費時間的,因此,松哥今天決定寫一篇文章,和大伙好好捋捋 JavaWeb 中的亂碼問題。
對于一些老司機而言,其實并不太容易遇到亂碼問題,但是對于一些新手來說,亂碼幾乎是家常便飯,而且每當亂碼時,網(wǎng)上搜了一大堆解決方案,發(fā)現(xiàn)自己的問題還是沒能解決,其實這就是平時研究代碼不求甚解導(dǎo)致的,亂碼問題,也要去分析,然后才能對癥下藥,才能藥到病除。
整體思路首先出現(xiàn)亂碼之后,要先去確認亂碼的地方,當一個網(wǎng)頁上出現(xiàn)亂碼,有可能是瀏覽器顯示問題,也有可能是 Java 編碼問題,也有可能數(shù)據(jù)庫中的數(shù)據(jù)本身就是亂碼的,所以我們要做的第一件事就是確認亂碼發(fā)生的位置,縮小 bug 范圍,通過打印日志或者 debug 首先去確認亂碼發(fā)生的位置,然后再去進一步解決,一般來說,亂碼的原因大致上可以分為兩類:
請求亂碼
響應(yīng)亂碼
請求亂碼,可能是因為參數(shù)放在 URL 地址中亂碼,也有可能是參數(shù)放在請求體中亂碼,不同傳參方案也對應(yīng)了不同的亂碼解決方案。如果是響應(yīng)亂碼,那么原因就會比較多了,一般來說,有如下幾種可能的原因:
數(shù)據(jù)庫本身亂碼
數(shù)據(jù)在 Java 代碼中亂碼
數(shù)據(jù)在瀏覽器顯示的時候亂碼
數(shù)據(jù)在從 Java 應(yīng)用傳到數(shù)據(jù)庫的過程中亂碼
對于不同的亂碼原因,會有不同的解決方案,對癥下藥,才能藥到病除,所以當出現(xiàn)亂碼時,大家要做的第一件事就是分析亂碼發(fā)生的原因,找到原因了,才能找到解決方案。
基本原則發(fā)生亂碼是因為各自編碼不同導(dǎo)致的,所以,大家首先要有一個良好的開發(fā)習(xí)慣,項目編碼,文件編碼都要統(tǒng)一起來,松哥有個同事就因為 Freemarker 亂碼,找了半天沒找到原因,后來在松哥建議下修改了項目編碼,亂碼問題才解決了,一般來說,公司制度稍微成熟一些,都會對項目編碼,文件編碼有硬性規(guī)定的。在Eclipse 中,設(shè)置項目編碼方式如下(工程的編碼要提前設(shè)置,如果項目已經(jīng)開發(fā)一半再去設(shè)置,已有的中文就會亂碼):
Window->Preferences->General
然后對于 JSP 文件也需要提前設(shè)置好編碼方式,如下:
這是在 Eclipse 中設(shè)置文件編碼,如果是在 IntelliJ IDEA中,則不需要設(shè)置JSP文件編碼,因為默認就是 UTF-8,只需要提前設(shè)置下工程編碼即可:
除了開發(fā)工具的編碼,數(shù)據(jù)庫的編碼也要統(tǒng)一,一般來說,主要是設(shè)置一下數(shù)據(jù)庫的編碼和數(shù)據(jù)表的編碼,如下:
設(shè)置數(shù)據(jù)庫編碼:
CREATE DATABASE `vhr` DEFAULT CHARACTER SET utf8;
設(shè)置數(shù)據(jù)表編碼:
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;
這些是準備工作,這些工作做好了,還是有可能會遇到亂碼問題,接下來我們就具體問題具體分析。
請求亂碼請求亂碼,就是說數(shù)據(jù)在瀏覽器中顯示是正常的,但是傳到 Java 后端之后,就亂碼了,這種亂碼一般來說,分為兩種:
參數(shù)放在 URL 地址中導(dǎo)致的亂碼
參數(shù)放在請求體中導(dǎo)致的亂碼
兩種亂碼原因,對應(yīng)了兩種不同的解決方案。分別來看。
URL 地址中的參數(shù)亂碼這種亂碼主要發(fā)生在 GET 請求中,因為在 GET 請求中我們一般通過 URL 來傳遞參數(shù),這個問題可以在代碼中解決,但是太過于麻煩,因此一般我們直接在Tomcat配置中解決,修改 Tomcat的conf/server.xml 文件,修改 URL 編碼格式,如下:
這樣就可以搞定 URL 地址中的參數(shù)亂碼。
請求體中的參數(shù)亂碼請求體中的參數(shù)亂碼,我們可以在解析參數(shù)之前通過設(shè)置 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); } }
過濾器配置:
encodingFilter org.sang.filter.EncodingFilter encodingFilter /*
在工程編碼和JSP/HTML編碼都沒問題的情況下,請求亂碼基本上就是這兩種情況。
響應(yīng)亂碼如果在瀏覽器上加載頁面看到了亂碼,大家首先要確認在從服務(wù)端往瀏覽器寫數(shù)據(jù)的前一刻,這個數(shù)據(jù)還沒有亂碼(即數(shù)據(jù)庫中查詢出來的數(shù)據(jù)是OK的,沒有發(fā)生亂碼的問題),那么對于這種亂碼,我們只需要設(shè)置響應(yīng)數(shù)據(jù)的 ContentType 就可以了,如下:
response.setContentType("text/html;charset=UTF-8");
如果從數(shù)據(jù)庫中查詢出來的數(shù)據(jù)就是亂碼的,那么就需要去確認數(shù)據(jù)庫中的編碼是否 OK 。
框架處理前面提到的方案,都是在 Servlet/JSP 項目中我們可以采用的方案,在 SSM 框架中當然也可以使用,但是,SpringMVC 框架本身也提供了一個過濾器,我們可以借用這個過濾器更加高效的解決響應(yīng)亂碼問題,如下:
encoding org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 forceRequestEncoding true forceResponseEncoding true encoding /*
當然,上面這段配置并不能代替 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其他亂碼
其他亂碼主要是指使用一些第三方框架導(dǎo)致的亂碼,例如使用 Alibaba 的 fastjson,開發(fā)者就需要在配置 HttpMessageConverter 時指定編碼格式,否則就有可能出現(xiàn)亂碼,這種第三方框架的亂碼松哥沒法窮舉,大伙在使用時需要注意看官方文檔,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; }一個隱蔽的亂碼
除了前面介紹的這幾種亂碼之外,還有一個比較隱蔽的亂碼,容易被很多初學(xué)者忽略的地方,就是數(shù)據(jù)在從 Java 應(yīng)用傳遞到 MySQL 的過程中,發(fā)生了亂碼,這種問題一般在 Windows 上不易發(fā)生,如果數(shù)據(jù)庫裝在 Linux 上,則這個問題就很容易發(fā)生,數(shù)據(jù)在代碼中命名沒有亂碼,存到 MySQL 上就亂碼了,但是如果直接使用 Navicat 等工具往 MySQL 上存儲數(shù)據(jù),又不會亂碼,或者 MySQL 中數(shù)據(jù)沒有亂碼,但是用 Java 查詢出來就亂碼了,這種都是數(shù)據(jù)在 應(yīng)用 和 數(shù)據(jù)庫 之間傳遞時發(fā)生了亂碼,解決方式很簡單,在數(shù)據(jù)庫連接地址上指定編碼即可,如下:
db.url=jdbc:mysql:///yuetong?useUnicode=true&characterEncoding=UTF-8
大致就這些,還有一些非常偶爾的情況可能會用到 @RequestMapping 注解中的 produces 屬性,在這里指定數(shù)據(jù)類型即可。
好了,差不多就這些,下次有人問你為啥我的又亂碼了,直接把這篇文章甩給他。大伙有什么解決亂碼的獨門密器也可以一起來討論。
關(guān)注公眾號【江南一點雨】,專注于 Spring Boot+微服務(wù)以及前后端分離等全棧技術(shù),定期視頻教程分享,關(guān)注后回復(fù) Java ,領(lǐng)取松哥為你精心準備的 Java 干貨!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/77496.html
摘要:一前言在開發(fā)的過程中,難免會出現(xiàn)中文亂碼的問題。接下來寫的是我在解決中文亂碼問題時的學(xué)習(xí)心得,一是為了能加深印象,二是希望能幫初學(xué)者們解決一些疑惑。二正文之所以會出現(xiàn)中文亂碼,是因為在進行時的編碼方式不正確。 一、前言 在開發(fā)JavaWeb的過程中,難免會出現(xiàn)中文亂碼的問題。接下來寫的是我在解決中文亂碼問題時的學(xué)習(xí)心得,一是為了能加深印象,二是希望能幫初學(xué)者們解決一些疑惑。如有說的不...
摘要:關(guān)于解決亂碼問題的終極解決方案有個特別好玩的現(xiàn)象,當我們?yōu)榱司幋a頭疼的時候,幾乎搜索到所有的文章都會先發(fā)一通牢騷。另外,關(guān)于的亂碼問題,又是一個新的較長篇章。 關(guān)于解決Python亂碼問題的終極解決方案 (TL;DR) showImg(https://segmentfault.com/img/remote/1460000013229494?w=809&h=184); 有個特別好玩的現(xiàn)象...
摘要:創(chuàng)建與銷毀對象是發(fā)送請求服務(wù)器就會創(chuàng)建它,當響應(yīng)產(chǎn)生時,對象就會銷毀。是容器為開發(fā)人員提供的對象,它提供了對某一資源的已過濾請求調(diào)用鏈的視圖。 一、Listener監(jiān)聽器 Javaweb開發(fā)中的監(jiān)聽器,是用于監(jiān)聽web常見對象 HttpServletRequest HttpSession ServletContext 監(jiān)聽它們的創(chuàng)建與銷毀 屬性變化 session綁...
摘要:方法的參數(shù)不但可以使相對于上下文根的路徑,而且可以是相對于當前的路徑。如和都是合法的路徑。 轉(zhuǎn)發(fā)與重定向區(qū)別是什么 在調(diào)用方法上 轉(zhuǎn)發(fā) 調(diào)用 HttpServletRequest 對象的方法 request.getRequestDispatcher(test.jsp).forward(req, resp); 重定向 調(diào)用 HttpServletResponse 對象的方法 res...
摘要:文件拷貝的模板代碼會自動關(guān)閉但是,如果下載中文文件,頁面在下載時會出現(xiàn)中文亂碼或不能顯示文件名的情況,原因是不同的瀏覽器默認對下載文件的編碼方式不同,是編碼方式,而火狐瀏覽器是編碼方式。 1.HttpServletResponse概述 我們在創(chuàng)建Servlet時會覆蓋service()方法,或doGet()/doPost(),這些方法都有兩個參數(shù),一個為代表請求的request和代表...
閱讀 2871·2021-10-14 09:43
閱讀 1657·2021-09-29 09:34
閱讀 1743·2021-07-28 00:16
閱讀 2962·2019-08-30 15:53
閱讀 2905·2019-08-30 13:59
閱讀 2961·2019-08-30 13:57
閱讀 1091·2019-08-26 13:38
閱讀 1893·2019-08-26 13:25