HttpServletResponse乱码问题_动力节点Java学院整理

发布时间 - 2026-01-11 02:30:16    点击率:

一个完整的http响应包括响应行,若干响应头和响应数据主体三部分构成。如果我们能用响应对象来进行这三部分的处理,就能向客户发送特定的响应数据包。

先从HttpServletResponse对象的方法中可以看到有如下方法(部分):

这只是一部分,但是我们却可以看出,通过响应对象的方法,我们就能设置响应客户端数据的一些信息。比如setStatus(int sc)方法,我们从HttpServletResponse的API中的字段定义可找到已经设置好的响应码(部分):

我们通过setHeader或者addHeader就能对一些数据进行跟客户端的告知,比如我想让某个页面的数据在客户端保存一天,也就是如果客户端再向我请求的话,则它应该去缓存中获取,直到一天之后才能重新向我请求,那么我就必须使用到了“Expires”响应头,将这个响应头的值设为一天后的时间告诉给客户端:

在MyEclipse中的【myservlet】web工程下,创建名为ServletDemo1的Servlet,代码如下:

 

public class ServletDemo extends HttpServlet {
   public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {
 
     long expiresTime = System.currentTimeMillis()+1*24*60*60*1000; //将缓存截止时间设置为一天后
     response.setDateHeader("expires", expiresTime);
     
   }
 } 

这时候用浏览器来访问这个Servlet(访问之前最好现将浏览器中的缓冲清除干净),访问之后我们再来看看这个缓存的页面文件:

右键查看其属性:

可以看到我们是在9月28日访问的这个文件,而服务器已经将这个文件的缓冲时间设置为了29日。

注意:对于”Expires”响应头的设置必须使用setDateHeader方法,使用setHeader方法无效。

使用响应对象可以向客户端写入数据,我们采用获取响应对象的输出流,将数据用write方法写,这些数据是写入到响应对象中,而服务器再将这些响应对象回传给客户端进行解析。而这些数据在响应对象中正是处于HTTP协议的响应数据实体中。

通过HttpServletResponse对象的父类ServletResponse对象的getOutputStream方法和getWriter方法可以获取向响应对象的数据实体中写入数据。这里如果传送的是英文数据一般都没有什么问题,而中文编码则是会令人头疼的。

首先我们来看响应对象的getOutputStream方法,我们在一个Servlet程序中代码如下:

   String data = "银魂";
   OutputStream out = response.getOutputStream();
   out.write(data.getBytes());

而在浏览器中访问这个Servlet,看到的是:

是的,没有出现乱码的问题,这主要有两点原因:

一个是浏览器本身的解码方式是根据平台语言环境来设置的,我的操作系统是Windows的中文版本,因此浏览器的解码采用的编码表为“GB2312”:

另一个原因是因为,在将字符串转为字节数组时,采用了getBytes()方法,这个方法在String类的API文档中明确说明了采用平台默认的字符集,根据我的系统这个方法也采用了“GB2312”编码表。

因此服务器编码和客户端解码都采用同一编码表这就不会出现中文乱码问题。

如果我在getBytes方法中采用UTF-8编码,那么结果自然会出错:

   String data = "银魂";
   OutputStream out = response.getOutputStream();
   out.write(data.getBytes("UTF-8"));

除非你也在浏览器中更改编码方式,改成UTF-8就可以重新看到正确的中文数据了:

当然这肯定不适合给用户这么操作,毕竟不是谁都懂浏览器的编码。

如果我们一定要将中文数据采用“UTF-8”的方式(UTF-8有利于国际化),有这么两种解决采用UTF-8编码方式的中文乱码问题:

第一种解决方式:使用HttpServletResponse响应对象的setHeader的方法,将“Content-type”这个响应头中设置编码方式。同时,sun公司也提供了更便捷的代码语句setContentType给编程人员使用。

在Servlet中的代码:

   response.setHeader("content-type", "text/html;charset=UTF-8");
   //response.setContentType("text/html;charset=UTF-8");  //这句功能同上一句
   String data = "银魂";
   OutputStream out = response.getOutputStream();
   out.write(data.getBytes("UTF-8"));

这样在浏览器中可以看到正确的中文数据,并且浏览器自动将编码方式采用UTF-8:

附带从HttpWatch中观察到的数据包:

注意:如果response.setHeader("content-type", "text/html;charset=UTF-8");中将"text/html;charset=UTF-8"中的分号“;”写成了逗号“,”就会变成下载该Servlet文件。

所以书写要注意。

第二种解决方式:我们不直接在响应对象中设置“Content-type”这个响应头,而是通过HTML的<meta>标签,该标签的作用就是模拟一个响应头,这样在回传的响应对象中,某些响应头就不会被设置,但是还是有这个响应头的功能,例如我们在HTML页面中经常能见到的<meta http-equiv="content-type" content="text/html;charset=utf-8">这个标签,是不是和第一种方式很像。相关代码为:

   String data = "银魂";
   OutputStream out = response.getOutputStream();
   out.write("<meta http-equiv='content-type' content='text/html;charset=utf-8'>".getBytes());
   out.write(data.getBytes("UTF-8"));

这时候在浏览器中同样能观察到正确的中文数据,同时可以看到浏览器已经自动采用“UTF-8”编码方式:

同时,在浏览器浏览源代码和观察HttpWatch窗口:

从上面可以看出,服务器发回的响应中没有“Content-type”这个响应头,但是在响应数据实体中有<meta>标签,浏览器能解析这个HTML语言,得到这个标签中设置的“Content-type”模拟响应头,因此能根据这个模拟响应头中的编码方式来设置浏览器应该采用的码表。

如果我们用输出流直接输出数字的话,会是输出这个数字在编码表中代表的字符,如代码为:

 public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {
     
    response.getOutputStream().write(97);
   }  

在浏览器中得到:a。

说完了从响应对象中得到OutputSteam对象,接着我们来讨论从响应对象中得到Writer对象,众所周知,字符流是由字节流加编码表组成,那么在响应对象中的字符流采用什么编码表方式呢?我们来看看HttpServletResponse对象的getWriter()方法的API手册说明:

从这里面看出如果没有为这个getWriter()方法设置编码表,那么则默认采用 “ISO-8859-1”编码表。或者采用响应对象的getCharacterEncoding()方法查看也可以。

那么在服务器端如果要改变对封装数据的编码格式可以有两种方式:

第一种:使用响应对象的setCharacterEncoding()方法来设置服务器采用的编码表,接着使用setContendType或者setHeader告知客户端服务器采用的编码表,后者在上面已经说过。

示例代码:

 public class ServletResponse extends HttpServlet {
 
   public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {
     
     response.setCharacterEncoding("UTF-8");
     response.setContentType("text/html;charset=UTF-8");
     PrintWriter writer = response.getWriter();
     String data = "银魂";
     writer.write(data);  
   }
 }

注意,光只有setCharacterEncoding()方法只能改变服务器端采用的编码表,而没能通知客户端,所以需要setContentType设置“Content-type”响应头,或者如之前所说的写入<meta>标签来模拟“Content-type”响应头。

第二种:直接使用setContentType方法,通过这种方法,可以在服务器和客户端同时设置编码表,也就是第一种方式中两个方法的结合,因此上述示例的代码如下:

 public void doGet(HttpServletRequest request, HttpServletResponse response)
       throws ServletException, IOException {
     response.setContentType("text/html;charset=UTF-8");
     
     PrintWriter writer = response.getWriter();
     String data = "银魂";
     writer.write(data);  
 }
 }

以上分别从响应对象HttpServletResponse中根据获取的字节流或者字符流向客户端输出数据时会碰到的中文乱码问题做出了分析和解决。


# HttpServletResponse乱码问题  # HttpServletResponse乱码  # Java Servlet响应httpServletResponse过程详解  # 使用HttpServletResponse对象获取请求行信息  # 如何使用spring ResponseEntity处理http响应  # 解决golang处理http response碰到的问题和需要注意的点  # Java HttpServletResponse响应实现过程详解  # Java中HttpServletResponse响应中文出现乱码问题  # NoHttpResponseException问题分析解决记录  # 客户端  # 可以看到  # 器中  # 第一种  # 象中  # 的是  # 就能  # 采用了  # 可以看出  # 第二种  # 数据包  # 中得  # 回传  # 这时候  # 有什么  # 我就  # 就会  # 是在  # 是因为  # 我在 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何在IIS中配置站点IP、端口及主机头?  Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能  Laravel如何使用Livewire构建动态组件?(入门代码)  Laravel怎么进行数据库回滚_Laravel Migration数据库版本控制与回滚操作  南京网站制作费用,南京远驱官方网站?  如何在IIS管理器中快速创建并配置网站?  绝密ChatGPT指令:手把手教你生成HR无法拒绝的求职信  香港服务器建站指南:免备案优势与SEO优化技巧全解析  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  网站页面设计需要考虑到这些问题  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?  Laravel如何与Pusher实现实时通信?(WebSocket示例)  如何续费美橙建站之星域名及服务?  怎么用AI帮你设计一套个性化的手机App图标?  桂林网站制作公司有哪些,桂林马拉松怎么报名?  Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南  弹幕视频网站制作教程下载,弹幕视频网站是什么意思?  Laravel如何实现用户注册和登录?(Auth脚手架指南)  如何用PHP快速搭建高效网站?分步指南  齐河建站公司:营销型网站建设与SEO优化双核驱动策略  nodejs redis 发布订阅机制封装实现方法及实例代码  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  如何在建站之星网店版论坛获取技术支持?  如何挑选高效建站主机与优质域名?  网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?  网页制作模板网站推荐,网页设计海报之类的素材哪里好?  标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析  昵图网官方站入口 昵图网素材图库官网入口  黑客入侵网站服务器的常见手法有哪些?  装修招标网站设计制作流程,装修招标流程?  Laravel路由怎么定义_Laravel核心路由系统完全入门指南  如何用狗爹虚拟主机快速搭建网站?  nginx修改上传文件大小限制的方法  Windows10如何更改计算机工作组_Win10系统属性修改Workgroup  如何在阿里云虚拟主机上快速搭建个人网站?  Laravel如何使用Guzzle调用外部接口_Laravel发起HTTP请求与JSON数据解析【详解】  如何确保FTP站点访问权限与数据传输安全?  DeepSeek是免费使用的吗 DeepSeek收费模式与Pro版本功能详解  如何快速选择适合个人网站的云服务器配置?  什么是JavaScript解构赋值_解构赋值有哪些实用技巧  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  Laravel如何为API编写文档_Laravel API文档生成与维护方法  使用豆包 AI 辅助进行简单网页 HTML 结构设计  如何快速登录WAP自助建站平台?  如何用IIS7快速搭建并优化网站站点?  laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法  如何撰写建站申请书?关键要点有哪些?  网站图片在线制作软件,怎么在图片上做链接?  Laravel如何实现API版本控制_Laravel版本化API设计方案