www.91084.com

GVKun编程网logo

Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?(java:需要)

10

此处将为大家介绍关于Java是否应该在HttpServletResponse.getOutputStream的详细内容,并且为您解答有关/。getWriter的相关问题,此外,我们还将为您介绍关于ge

此处将为大家介绍关于Java 是否应该在HttpServletResponse.getOutputStream的详细内容,并且为您解答有关/。getWriter的相关问题,此外,我们还将为您介绍关于getOutputStream() has already been called for this response、groovy servlet java.lang.NoSuchMethodError: javax.servlet.http.HttpServletResponse.getStatus()I、HttpServletRequest.getInputStream()多次读取问题、HttpServletRequest.getParameterValues()中值的排序的有用信息。

本文目录一览:

Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?(java:需要)

Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?(java:需要)

我无法通过一些Google搜索找到权威的答案。在Java Servlet中,可以通过response.getOutputStream()或response.getWriter()访问响应主体。写入流后,是否应该在此流上调用.close()?

一方面,Blochian鼓励始终关闭输出流。另一方面,我不认为在这种情况下有需要关闭的基础资源。套接字的打开/关闭在HTTP级别进行管理,以允许诸如持久连接之类的事情。

答案1

小编典典

通常,你不应该关闭流。在Servlet完成作为Servlet请求生命周期的一部分运行之后,Servlet容器将自动关闭流。

例如,如果你关闭流,那么在实现Filter的情况下将不可用。

说了这么多,只要你关闭它,只要你不尝试再次使用它,都不会发生任何不良情况。

编辑:另一个筛选器链接

EDIT2:adrian.tarau是正确的,因为如果你想在Servlet完成其操作后更改响应,则应创建一个扩展HttpServletResponseWrapper的包装器并缓冲输出。这是为了防止输出直接进入客户端,还允许你保护servlet是否关闭流,如以下摘录(强调我的话):

修改响应的过滤器通常必须 在将响应返回给客户端之前捕获该响应。实现此目的的方法是将生成响应的servlet传递给替代流。替身流阻止servlet在完成时关闭原始响应流,并允许过滤器修改servlet的响应。

getOutputStream() has already been called for this response

getOutputStream() has already been called for this response

getOutputStream() has already been called for this response 博客分类: 异常

.tomcat6.0下jsp呈现getOutputStream() has already been called for this response异常的原因和解决办法

  在tomcat6.0下jsp中呈现此错误一般都是在jsp中应用了输出流(如输出图片验证码,文件下载等),没有妥当处理惩罚好的原因。

 

  具体的原因就是:
  在tomcat中jsp编译成servlet之后在函数_jspService(HttpServletRequest request, HttpServletResponse response)的最后有一段如许的代码

 


1 finally {

2       if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);

3 }

 

  这里是在开释在jsp中应用的对象,会调用response.getWriter(),因为这个办法是和response.getOutputStream()相冲突的!所以会呈现以上这个异常。

 

  然后当然是要提出解决的办法,其实挺简单的(并不是和某些伴侣说的那样--将jsp内的所有空格和回车符号所有都删除掉),在应用完输出流今后调用以下两行代码即可:

 


1 out.clear();


2 out = pageContext.pushBody();

struts2中
报错: java.lang.IllegalStateException: getOutputStream() has already been called for this response的错误. Struts方法之间调用引起的。 
因为:每个方法都返回的是一个ActionForward对象,而response是ActionForward对象参数,所以就会使response冲突! 故,将最后的return "SUCCESS"改为 return null .不将其交由sturts管理.
如:

Java代码 复制代码 收藏代码
  1. /**
  2. * 查看图片
  3. * @return
  4. * @throws Exception
  5. */
  6. public String view() throws Exception {
  7. png= workFlowManager.getPngByte(workFlow.getPdID());
  8. response.reset();
  9. response.setContentType("image/png");
  10. response.getOutputStream().write(png.getFileData());
  11. response.getOutputStream().flush();
  12. response.getOutputStream().close();
  13. returnnull;

groovy servlet java.lang.NoSuchMethodError: javax.servlet.http.HttpServletResponse.getStatus()I

groovy servlet java.lang.NoSuchMethodError: javax.servlet.http.HttpServletResponse.getStatus()I

java.lang.NoSuchMethodError: javax.servlet.http.HttpServletResponse.getStatus()I
at org.eclipse.jetty.server.handler.ErrorHandler.handle(ErrorHandler.java:111)
at org.eclipse.jetty.server.Response.sendError(Response.java:597)
at javax.servlet.http.HttpServlet.doGet(HttpServlet.java:187)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:769)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1125)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1059)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:497)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311)
at org.eclipse.jetty.server.httpconnection.onFillable(httpconnection.java:248)
at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:610)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:539)

at java.lang.Thread.run(Thread.java:745)


问题原因: groovy libraries 中有个servlet api 那个是比较老的.而且被优先加载了.

解决方法: 将自己引用的servlet api 放在前面 

HttpServletRequest.getInputStream()多次读取问题

HttpServletRequest.getInputStream()多次读取问题

转自:https://www.jianshu.com/p/85feeb30c1ed

HttpServletRequest.getInputStream()多次读取问题

 

背景

使用POST方法发送数据时,我们习惯于把数据包装成json格式。

 

 
image.png

有些情况下,我们会在Filter中读取body数据进行数据校验,
GET方法获取参数比较简单。对于POST方法,可使用如下方法从request中获取body参数:

 private String getBody(HttpServletRequest request) throws IOException { InputStream in = request.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in, Charset.forName("UTF-8"))); StringBuffer sb = new StringBuffer(""); String temp; while ((temp = br.readLine()) != null) { sb.append(temp); } if (in != null) { in.close(); } if (br != null) { br.close(); } return sb.toString(); } 

注意,这里有了一次request.getInputStream()调用。

但是在测试时,一直报JSON格式不正确的错误。经调查发现,项目中使用了公司基础组件中的Filter,而该Filter中也解析了body。同时,不出所料,也是通过调用getInputStream()方法获取的。

原来:

  • 一个InputStream对象在被读取完成后,将无法被再次读取,始终返回-1;
  • InputStream并没有实现reset方法(可以重置首次读取的位置),无法实现重置操作;

因此,当自己写的Filter中调用了一次getInputStream()后,后面再调用getInputStream()读取的数据都为空,所以才报JSON格式不正确的错误。

解决方法

  1. 缓存数据
  2. 使用HttpServletRequestWrapper进行包装

缓存数据
所谓缓存数据,其实就是调用ServletRequestsetAttribute(String s, Object o)来存储数据。

  1. 获取到body后,直接缓存
String body = getBody(request); request.setAttribute("body", body); 

优点:
方便
缺点:
不能控制第三方Filter

  1. 其他地方需要使用body时,只需调用getAttribute方法就能获取数据了:
request.getAttribute("body"); 

HttpServletRequestWrapper包装

public class RequestWrapper extends HttpServletRequestWrapper { private final byte[] body; public RequestWrapper(HttpServletRequest request) throws IOException { super(request); body = getBodyStringFromReq(request).getBytes(Charset.forName("UTF-8")); } public String getBodyString() { try { return new String(body, "UTF-8"); } catch (UnsupportedEncodingException ex) { return new String(body); } } private String getBodyStringFromReq(ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = request.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } } 

在Filter中使用时,FilterChain.doFilter()传入Wrapper对象:

public class TestFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { RequestWrapper requestWrapper = new RequestWrapper((HttpServletRequest)request); String body = requestWrapper.getBodyString(); chain.doFilter(requestWrapper, response); //传入Wrapper对象 } @Override public void init(FilterConfig arg0) throws ServletException { } } 

这样,位于后面的Filter就可以拥有唯一一次调用HttpServletRequest.getInputStream()的机会了。

优点:
不影响第三方Filter

缺点:
多写了这么多代码,麻烦了一些

参考

HttpServletRequest.getParameterValues()中值的排序

HttpServletRequest.getParameterValues()中值的排序

HttpServletRequest.getParameterValues()返回一个String[]包含给定HTTP请求参数的所有值的。有人知道规范中是否保证此数组中值的顺序与请求中这些值的传递顺序相同?

例如,如果我有GET查询字符串x=1&x=2&x=3,那么我 保证String[] {"1", "2","3"}在致电时会收到getParameterValues()吗?它似乎在实践中可行,但是我找不到任何可以说明这种情况的东西,因此我不愿意依靠它。

答案1

小编典典

ServletRequest的javadoc(v2.5
javadoc)没有提及有关该方法的值顺序的任何内容。因此,我不会依赖保留的顺序。


更新:还检查了规范文档中的2.5,其中包含与getParameterValues()有关的以下信息。它没有提及有关查询字符串排序的任何内容,因此我认为您所看到的行为是实现细节,而不是定义为接口的一部分。

参数存储为一组名称/值对。对于任何给定的参数名称,可以存在多个参数值。ServletRequest接口的以下方法可用于访问参数:

  • getParameter
  • getParameterNames
  • getParameterValues
  • getParameterMap

getParameterValues方法返回一个String对象数组,其中包含与参数名称关联的所有参数值。从getParameter方法返回的值必须是getParameterValues返回的String对象数组中的第一个值。getParameterMap方法返回请求参数的java.util.Map,该名称包含名称(作为键)和参数值(作为映射值)。

为了将来参考,可以从Sun(即Oracle的网站)下载Java
Servlet规范。您可以在此处再次检查您感兴趣的特定servlet版本。

我们今天的关于Java 是否应该在HttpServletResponse.getOutputStream/。getWriter的分享就到这里,谢谢您的阅读,如果想了解更多关于getOutputStream() has already been called for this response、groovy servlet java.lang.NoSuchMethodError: javax.servlet.http.HttpServletResponse.getStatus()I、HttpServletRequest.getInputStream()多次读取问题、HttpServletRequest.getParameterValues()中值的排序的相关信息,可以在本站进行搜索。

本文标签: