大部分JavaWeb 亂碼問題都在這裡了

java閘瓦發表於2019-04-12

寫在前面

對於一些老司機而言,其實並不太容易遇到亂碼問題,但是對於一些新手來說,亂碼幾乎是家常便飯,而且每當亂碼時,網上搜了一大堆解決方案,發現自己的問題還是沒能解決,其實這就是平時研究程式碼不求甚解導致的,亂碼問題,也要去分析,然後才能對症下藥,才能藥到病除

整體思路

首先出現亂碼之後,要先去確認亂碼的地方,當一個網頁上出現亂碼,有可能是瀏覽器顯示問題,也有可能是 Java 編碼問題,也有可能資料庫中的資料本身就是亂碼的,所以我們要做的第一件事就是確認亂碼發生的位置,縮小 bug 範圍,通過列印日誌或者 debug 首先去確認亂碼發生的位置,然後再去進一步解決

一般來說,亂碼的原因大致上可以分為兩類:

  1. 請求亂碼:可能是因為引數放在 URL 地址中亂碼,也有可能是引數放在請求體中亂碼,不同傳參方案也對應了不同的亂碼解決方案
  2. 響應亂碼:
  • 資料庫本身亂碼
  • 資料在 Java 程式碼中亂碼
  • 資料在瀏覽器顯示的時候亂碼
  • 資料在從 Java 應用傳到資料庫的過程中亂碼

基本原則

發生亂碼是因為各自編碼不同導致的,所以,大家首先要有一個良好的開發習慣,專案編碼,檔案編碼都要統一起來

在Eclipse 中,設定專案編碼方式如下(工程的編碼要提前設定,如果專案已經開發一半再去設定,已有的中文就會亂碼)

大部分JavaWeb 亂碼問題都在這裡了

然後對於 JSP 檔案也需要提前設定好編碼方式,如下:

大部分JavaWeb 亂碼問題都在這裡了

這是在 Eclipse 中設定檔案編碼,如果是在 IntelliJ IDEA中則不需要設定JSP檔案編碼,因為預設就是 UTF-8,只需要提前設定下工程編碼即可

大部分JavaWeb 亂碼問題都在這裡了

除了開發工具的編碼,資料庫的編碼也要統一,一般來說,主要是設定一下資料庫的編碼和資料表的編碼,如下

設定資料庫編碼

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 後端之後,就亂碼了,這種亂碼一般來說,分為兩種

1. URL 地址中的引數亂碼

這種亂碼主要發生在 GET 請求中,因為在 GET 請求中我們一般通過 URL 來傳遞引數,這個問題可以在程式碼中解決,但是太過於麻煩,因此一般我們直接在Tomcat配置中解決,修改 Tomcat的conf/server.xml 檔案,修改 URL 編碼格式,如下

大部分JavaWeb 亂碼問題都在這裡了

2. 請求體中的引數亂碼

請求體中的引數亂碼,我們可以在解析引數之前通過設定 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>
複製程式碼

響應亂碼

如果在瀏覽器上載入頁面看到了亂碼,大家首先要確認在從服務端往瀏覽器寫資料的前一刻,這個資料還沒有亂碼(即資料庫中查詢出來的資料是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 上,則這個問題就很容易發生

這種都是資料在 應用 和 資料庫 之間傳遞時發生了亂碼,解決方式很簡單,在資料庫連線地址上指定編碼即可,如下

db.url=jdbc:mysql:///yuetong?useUnicode=true&characterEncoding=UTF-8
複製程式碼

最後給大家送點免費的東西

大部分JavaWeb 亂碼問題都在這裡了
現在開放資源免費領取,送給需要高清架構腦圖,架構視訊資料、架構電子書和Java面試檔案,以及想要提升技術的朋友。

獲取資料的方式:進群 571617441 即可領取!

都看到這裡了,別忘了點個關注喲。以後會持續分享更多幹貨!!

相關文章