setCharacterEncoding和setContentType有什么不同

news/2024/9/18 10:45:46

如果仅仅从服务器的角度来看,这两个方法其实本质是一样的,以下内容是摘抄自oracle的官网:

Defines an object to assist a servlet in sending a response to the client. The servlet container creates a ServletResponse object and passes it as an argument to the servlet's service method.
To send binary data in a MIME body response, use the ServletOutputStream returned by getOutputStream(). To send character data, use the PrintWriter object returned by getWriter(). To mix binary and text data, for example, to create a multipart response, use a ServletOutputStream and manage the character sections manually.

The charset for the MIME body response can be specified explicitly using the setCharacterEncoding(java.lang.String) and setContentType(java.lang.String) methods, or implicitly using the setLocale(java.util.Locale) method. Explicit specifications take precedence over implicit specifications. If no charset is specified, ISO-8859-1 will be used. The setCharacterEncoding, setContentType, or setLocale method must be called before getWriter and before committing the response for the character encoding to be used.

从服务器端角度看,两个方法就是给服务器返回前端的内容进行编码设置。

但是,再次强调,内容是要在平台上展示的,而平台也是有自己的charset的。如果平台用来展示内容的charset与内容不符合时,出现的依然是乱码。

看例子:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("utf-8");
        ServletOutputStream stream = response.getOutputStream();
        stream.write("<h1>AC米兰足球队</h1>".getBytes("utf-8"));
        stream.close();
    }

 那根据前面的解释,这段代码就是从服务器发给客户端一个响应,响应的内容是用UTF8编码的字符串<h1>AC米兰足球队</h1>。

代码运行,通过chrome浏览器发起请求,访问/test得到的页面是:

用F12打开开发者工具,分别看一下网络的响应和预览:

 首先是响应中看到的内容:

 然后是预览中看到的内容:

 

 发现不同之处了吗?那么背后的原因呢?

说明浏览器收到了正经UTF8编码的内容,但是浏览器并没有得到任何提示或者要求用什么编码方式来呈现这段内容!所以浏览器使用的是默认编码方式。那么Windows系统下的中文Chrome默认的编码方式是什么?猜也猜到了:GBK。

通过Chrome的Charset插件,就可以证明这一点:

好了,那我们如何告知浏览器用什么编码集来呈现内容呢?只要在响应头中加入contentType,浏览器会遵照contentType的指示来使用编辑呈现内容。如何在响应头中加入contentType,当然就是使用setContentType喽。

修改上面Servlet的doGet方法:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        ServletOutputStream stream = response.getOutputStream();
        stream.write("<h1>AC米兰足球队</h1>".getBytes("utf-8"));
        stream.close();
    }

这回使用了setContentType,用标准的MIME格式设置了服务器响应内容的字符集是UTF8,并且添加了响应头,告诉浏览器该使用什么编码集来显示内容:

 这一次浏览器遵守contentType的指示,知道了收到的内容格式是text/html,要使用utf8字符集进行显示。

---------------------------------------------------------------------------------------------------------------------------------

所以,对于服务端来说,setCharacterEncoding和setContentType这两个方法的作用是一样的,都是显示的为服务器响应内容指定一个编码方案。

但是对于浏览器来说,setContentType是会添加响应头的,会指导浏览器用正确的字符集来显示服务器的响应内容,而setCharacterEncoding做不到这一点。

不过,现在你知道了Chrome的默认字符集是GBK,所以你完全可以用setCharacterEncoding("GBK")用GBK作为服务器响应内容的编码方案,这样也可以正常显示中文:

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("GBK");
        //response.setContentType("text/html;charset=utf-8");
        ServletOutputStream stream = response.getOutputStream();
        stream.write("<h1>AC米兰足球队</h1>".getBytes("GBK"));
        stream.close();
    }

 

 相较于setContentType来说,这种设置方式就是“巧了”,浏览器的默认编码方案碰巧是服务器响应内容的编码方案。

---------------------------------------------------------------------------------------------------------------------------------

还有一种代码编写风格是同时使用setContentType和setCharacterEncoding方法。同时使用者两种方法的效果是:setCharacterEncoding会补充或覆盖setContentType的内容。

1.补充:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("gb2312");
        response.setContentType("text/html");
        ServletOutputStream stream = response.getOutputStream();
        stream.write("<h1>AC米兰足球队</h1>".getBytes("gb2312"));
        stream.close();
    }

setContentType提供的MIME只有类型没有编码方案,此时setCharacterEncoding的内容就称为了contentType中charset的内容。所以,浏览器收到的内容是有一个形如text/html;charset=gb2312这样的contentType响应头的。

 按照ContentType的指示,浏览器正确显示了服务器响应内容。

2.覆盖:

如果setContentType和setCharacterEncoding都设置了完整内容,那么setCharacterEncoding提供的编码方案将作为服务器内容的编码方案,但是浏览器会在收到响应内容的同时会收到由setContentType设置的请求头:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("gb2312");
        response.setContentType("text/html;charset=UTF-8");
        ServletOutputStream stream = response.getOutputStream();
        stream.write("<h1>AC米兰足球队</h1>".getBytes("gb2312"));
        stream.close();
    }

gb2312编码的内容,浏览器会使用请求头指示的UTF-8来显示,结果可想而知:

 --------------------------------------------------------------------------------------------------------------------------------

以上就是对setContentType和setCharacterEncoding方法的使用说明。显然,我个人更倾向于使用setContentType,同时兼顾了服务端内容编码和浏览器端解码的问题。


http://lihuaxi.xjx100.cn/news/295580.html

相关文章

Linux资产管理与服务器运行状态监控脚本

一、dmidecode简介 DMI(Desktop Management Interface,DMI)就是帮助收集电脑系统信息的管理系统,DMI信息的收集必须在严格遵照SMBIOS规范的前提下进行。SMBIOS(System Management BIOS)是主板或系统制造者以标准格式显示产品管理信息所需遵循的统一规范。SMBIOS和DMI是由…

贪心算法(三)——最佳合并模式

问题描述 给定n个有序文件&#xff0c;每个文件的记录数分别为w1~wn&#xff0c;请给出一种两两合并的方案&#xff0c;使得总合并次数最少。 注意&#xff1a; 1. 外排序算法是将多个有序文件合并成一个有序文件的过程。 2. 在一次合并的过程中&#xff0c;两个文件中的所有记…

数据采集的数据源有哪些?

从数据采集角度来说&#xff0c;都有哪些数据源呢&#xff1f; 这四类数据源包括了&#xff1a;开放数据源、爬虫抓取、传感器和日志采集 开放数据源一般是针对行业的数据库。国内&#xff0c;贵州做了不少大胆尝试&#xff0c;搭建了云平台&#xff0c;逐年开放了旅游、交通、…

Vue3类与样式绑定

官网&#xff1a;https://cn.vuejs.org/guide/essentials/class-and-style.html#binding-inline-styles 绑定 HTML class 绑定对象 const isActive ref(true) const hasError ref(false)<divclass"static":class"{ active: isActive, text-danger: hasEr…

数苹果-第12届蓝桥杯Scratch选拔赛真题精选

[导读]&#xff1a;超平老师计划推出Scratch蓝桥杯真题解析100讲&#xff0c;这是超平老师解读Scratch蓝桥真题系列的第91讲。 蓝桥杯选拔赛每一届都要举行4~5次&#xff0c;和省赛、国赛相比&#xff0c;题目要简单不少&#xff0c;再加上篇幅有限&#xff0c;因此我精挑细选…

(四) 共享模型之管程【Monitor 概念】

一、Java 对象头&#xff08;P75&#xff09; 二、原理之 Monitor(锁) Monitor 被翻译为监视器或管程。 每个 Java 对象都可以关联一个 Monitor 对象&#xff0c;如果使用 synchronized 给对象上锁&#xff08;重量级&#xff09;之后&#xff0c;该对象头的 Mark Word 中就被设…

Kotlin高仿微信-第27篇-朋友圈-相册选择图片或小视频

Kotlin高仿微信-项目实践58篇详细讲解了各个功能点&#xff0c;包括&#xff1a;注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…

计算机毕业设计Java高校防疫物资管理系统(源码+系统+mysql数据库+lw文档)

计算机毕业设计Java高校防疫物资管理系统&#xff08;源码系统mysql数据库lw文档&#xff09; 计算机毕业设计Java高校防疫物资管理系统&#xff08;源码系统mysql数据库lw文档&#xff09;本源码技术栈&#xff1a; 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语…