Spring MVC 使用介紹(十)—— 編碼

1、概述html

客戶端與服務器端在交互過程當中,須要將字符以某種編碼方式轉化爲字節流進行傳輸,所以涉及字符的編碼和解碼。某一方以編碼方案A編碼,另外一方須以一樣的編碼方案解碼,不然會出現亂碼。java

客戶端與服務器端的交互可分爲三種:web

  • 服務端向客戶端傳遞數據
  • 客戶端向服務端傳遞數據(POST)
  • 客戶端向服務端傳遞數據(GET)

服務端在不指定編碼方式時,默認使用 ISO-8859-1 解碼spring

客戶端在使用 encodeURIComponent() 方法時,使用 UTF-8 編碼瀏覽器

 

2、服務端向客戶端傳遞數據服務器

服務端向客戶端傳遞數據依賴HttpServletResponse類提供的方法,須要兩步:java-web

一、以某種編碼寫數據app

response.getOutputStream().write("異常處理hello".getBytes("UTF-8"));

或者ide

response.setCharacterEncoding("UTF-8"); response.getWriter().write("異常處理hello");

二、添加響應頭,告知客戶端解碼方式學習

response.addHeader("content-type", "text/html;charset=UTF-8");

 

3、客戶端向服務端傳遞數據(POST)

客戶端向服務端傳遞數據依賴HttpServletRequest類提供的方法,須要兩步:

一、設置解碼方式

request.setCharacterEncoding("UTF-8");

二、讀取參數

String name = request.getParameter("name"); Integer age = Integer.valueOf(request.getParameter("age"));

測試請求包(使用Fiddler發起)

POST http://localhost:8080/java-web-test/encoding/1 HTTP/1.1
Content-Type: application/x-www-form-urlencoded

name=%E9%80%89%E6%8B%A9%E5%A4%A7%E4%BA%8E%E5%8A%AA%E5%8A%9B&age=859

 

4、客戶端向服務端傳遞數據(GET)

客戶端經過GET方式(即經過url)傳遞參數,須以以下方式解析:

String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "UTF-8");

測試:http://localhost:8080/java-web-test/encoding/1?name=%E9%80%89%E6%8B%A9&age=52

即服務端默認以 ISO-8859-1 編碼方式解析,解析時須以 ISO-8859-1 編碼方式還原爲字節碼,再在以 UTF-8 編碼方式解碼

補充:

瀏覽器的encodeURIComponent()編碼方式是將特定字符以 UTF-8 方式編碼爲二進制,再以%爲分隔、以十六進制方式展現,如:

encodeURIComponent('選擇'); // 輸出:%E9%80%89%E6%8B%A9

java等價代碼:

String str = URLEncoder.encode("選擇", "UTF-8");

一樣,decodeURIComponent() 解碼方式是將以%爲分隔的十六進制字符轉換爲二進制,再以 UTF-8 方式解碼

decodeURIComponent("%E9%80%89%E6%8B%A9") // 輸出:選擇

java等價代碼:

String str = URLDecoder.decode("%E9%80%89%E6%8B%A9", "UTF-8");

 

5、web.xml中設置編碼方式

web.xml中,編碼方式的設置可經過添加過濾器實現:

<filter>
     <filter-name>encodingFilter</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>forceEncoding</param-name>
         <param-value>true</param-value>
   </init-param>
 </filter>
 <filter-mapping>
     <filter-name>encodingFilter</filter-name>
     <url-pattern>/*</url-pattern>
 </filter-mapping>

過濾器的部分源碼以下:

 @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); }

即設置了請求與響應內容區的編碼方式,但對GET請求無處理,所以仍然須要另外處理,以下:

@RestController public class TestController { @RequestMapping(value = "/hello") public Map<String, Object> helloWorld(@RequestParam("name") String name) throws UnsupportedEncodingException { Map<String, Object> map = new HashMap<String, Object>(); map.put("name", new String(name.getBytes("ISO-8859-1"), "UTF-8")); return map; } }

測試:http://localhost:8080/myweb/hello?name=%E7%A8%8B%E5%90%9B&age=29

例外一種解決方法爲添加過濾器,詳細可參考javaweb學習總結(四十三)——Filter高級開發

 

 

參考:

javaweb學習總結(七)——HttpServletResponse對象(一)

javaweb學習總結(十)——HttpServletRequest對象(一)

javaweb學習總結(四十三)——Filter高級開發

相關文章
相關標籤/搜索