记一次response的坑:response.getWriter()失效问题

本文探讨了在Java Web开发中,如何处理使用void返回类型的Controller时,避免response.getWriter()未执行的问题。重点在于理解getOutputStream与writer的使用限制,以及提供正确处理下载和错误回写的示例代码,包括易错点和解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.背景

在开发中,都规定好了后端返回数据的格式,当我们需要使用void作为controller的返回类型时,之前的返回格式就没办法使用了,但为了更灵活的返回数据,可以使用response.getWriter()去返回指定的数据,然后在使用response.getWriter()后,发现根本就不执行,直接抛出异常

2.问题

如下程序,很简单的逻辑,但是真正执行时,response.getWriter()这一句根本就没有执行,而且catch语句都不会进行,直接finally

3.原因

 

该语句前使用了getOutputStream,就不能再用writer方式输出。只能使用一种

4.解决方案

4.1如果做的不是下载需求的话,删除getOutputStream即可

4.2一般在实际工作中,遇到这个问题,都是下载需求,因此getOutputStream不可省

可以继续利用response.getOutputStream()生成的OutputStreamWriter对象,把数据以JSON格式返回给前端,不能再使用writer对象进行回写!代码如下:

try(
    OutputStreamWriter writer =newOutputStreamWriter(outs,StandardCharsets.UTF_8);
   ) {
        //组装JSON
        Map<String, Object> map=new HashedMap<>();
        map.put("retCode", "9999");
        map.put("retMsg", "Excel下载失败:"+e.getMessage());
        String json = new ObjectMapper().writeValueAsString(map);
        writer.write(json);
        writer.flush();
     }catch (Exception e1) {
         throw new PortalException("response.getOutputStream()语句异常",e1);
     }

注意:outs对象是前面代码生成的,大致如下:

ServletOutputStream outs = response.getOutputStream();

5.易错点

在一次请求中,response是一次性的!当连接关闭,response就已经失效了!在我的代码中,由于response.getOutputStream()是用于处理下载的,而OutputStreamWriter是处理失败回写的,两个语句位于不同的代码块中,当我在调用response.getOutputStream()去处理下载后,调用以下代码进行关闭流:

outs.close();

由于关闭流与OutputStreamWriter失败回写不在同一层次,运行到outs.close()时,response也随之失效了,可以理解为“这一次请求已经结束了!”,因此,后续在调用回写代码时,导致回写失败:

OutputStreamWriter writer =newOutputStreamWriter(outs,StandardCharsets.UTF_8);

//outs来源于response.getOutputStream(),而response已经失效了

 解决办法:

生成outs对象并且关闭outs,与上述生成writer对象保持同一层次即可!

代码如下:

ServletOutputStream outs = response.getOutputStream();
try {
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setCharacterEncoding("utf-8");
    service.downExcel(outs);//业务代码
} catch (Exception e) {
    response.reset();
    response.setHeader("content-type", "text/html;charset=utf-8");
    try(
            OutputStreamWriter writer =newOutputStreamWriter(outs,StandardCharsets.UTF_8);
    ) {
        //组装JSON
        Map<String, Object> map=new HashedMap<>();
        map.put("retCode", "9999");
        map.put("retMsg", "Excel下载失败:"+e.getMessage());
        String json = new ObjectMapper().writeValueAsString(map);
        writer.write(json);
        writer.flush();
    } catch (Exception e1) {
        throw new PortalException("response.getOutputStream()语句异常",e1);
    }
}finally{
    //这里关闭流,与writer 对象保持同一级别,防止流关闭不去执行下载失败回调的代码
        outs.close();
}
``` package com.example.lab4; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; @WebServlet(name = "Servlet2", value = "/Servlet2") public class Servlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); request.setCharacterEncoding("utf-8");// 补齐,设置request的字符集编码 String username=request.getParameter("username");//获取参数username的结果赋值给username String password=request.getParameter("password"); InputStream is = request.getInputStream(); byte buff[] = new byte[1024]; StringBuilder sb = new StringBuilder(); int len = 0; while ((len = is.read(buff))!=-1){ sb.append(new String(buff,0,len)); } response.getWriter().println(sb.toString()); //__________________________ //获取参数hobby的结果赋值给hobbys // String hobStr=""; // for(int i=0;i<hobbys.length;i++){ // hobStr=hobStr+hobbys[i]+","; // } // response.getWriter().println("用户名是:"+username+ // ",密码是:"+password+",爱好是:"+hobStr); } } <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/html"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/lab4_war_exploded/Servlet2" method="post"> 用户名:<input type="text" name="username"> </br> 密码:<input type="password" name="password"> </br> <input type="submit" value="提交"> </form> </body> </html>```HttpServletRequest对象的getInputStream()和getReader()方法,输出用户名和密码后,能够获取到用户名和密码,并显示出来。但是上面的代码无法正确的显示出文本框和按钮
03-27
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

睡竹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值