SpringMVC中Controller處理response.setContentType()及header爲applicationjsoncharsetutf-8無效問題分析

SpringMVC中Controller處理response.setContentType()及header爲"application/json;charset=utf-8"無效問題分析

一. 異常問題

我在SpringMVC中創建了一個處理器Controller,處理器方法內部利用response對象設置content-type,內容類型設置爲“application/json;charset=UTF-8”,在該方法對外輸出中文時,結果發現還是亂碼。代碼如下:

    @ResponseBody
    @RequestMapping(value = "/error",method = RequestMethod.GET)
    public String showError(HttpServletResponse response) throws IOException {
        //專門用來處理通過註解方式實現的處理器的!
        //RequestMappingHandlerMapping
        //RequestMappingHandlerAdapter--->invokeHandlerMethod()
        response.setContentType("application/json;charset=UTF-8");
       
        return "失敗";
    }

結果在請求時,發現依然亂碼:

二. 原因分析

後來經過追蹤源碼,發現是因爲SpringMVC源碼內部做了特殊處理,導致通過response.setContentType("application/json;charset=UTF-8")方法設置請求頭編碼無效。

SpringMVC中是通過RequestMappingHandlerAdapter來處理通過註解方式定義的請求處理器方法的,然後在該類中,有一個invokeHandlerMethod()方法,內部通過ServletInvocableHandlerMethod中的invokeAndHandle調用目標方法,並處理返回值。

如果return value != null,則通過returnvalueHandlers來處理,內部會調用MessageConverter轉換成相應的報文格式。

HttpOutputMessage中的outputMessage,對應的實例是 org.springframework.http.server.ServletServerHttpResponse。在寫入數據的同時,會設置response的header,包括content-type(根據RequestMapping 的 produces 屬性 計算出來)。也就是說,當請求方法在帶有返回值的情況下,在controller中設置content-type是無效的,會被消息轉換器覆蓋掉。

三.解決辦法

1.解決方式一,利用produces屬性

    @ResponseBody
    //@GetMapping("/show")
    @RequestMapping(value = "/show",method = RequestMethod.GET,produces = {"application/json;charset=UTF-8"})
    public String showCharacter(){

        return "成功";
    }

2. 解決方式二,請求方法不要帶返回值

    @ResponseBody
    @RequestMapping(value = "/error",method = RequestMethod.GET)
    public void showError(HttpServletResponse response) throws IOException {
        //
        //專門用來處理通過註解方式實現的處理器的!
        //RequestMappingHandlerMapping
        //RequestMappingHandlerAdapter--->invokeHandlerMethod()
        //AbstractHttpMessageConverter

        response.setContentType("application/json;charset=UTF-8");
        ServletOutputStream out = response.getOutputStream();
        IOUtils.write("失敗".getBytes("UTF-8"),out);
        //IOUtils.write("失敗",out);
        out.flush();
        //return "失敗";
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章