자바 서블릿에서 하나를 통해 응답 본문에 액세스 할 수 있습니다 response.getOutputStream()
또는 response.getWriter()
. 작성된 후 .close()
이것에 대해 OutputStream
한 번 전화해야합니까 ?
한편으로는 항상 OutputStream
s를 닫으라는 Blochian 권고가 있습니다. 반면에이 경우에는 닫아야하는 기본 리소스가 있다고 생각하지 않습니다. 소켓의 열기 / 닫기는 HTTP 수준에서 관리되어 지속적인 연결 등을 허용합니다.
답변
일반적으로 스트림을 닫으면 안됩니다. 서블릿 컨테이너는 서블릿 요청 수명주기의 일부로 서블릿 실행이 완료된 후 자동으로 스트림을 닫습니다.
예를 들어 스트림을 닫은 경우 Filter 를 구현하면 사용할 수 없습니다 .
모든 것을 말했듯이, 닫으면 다시 사용하지 않는 한 나쁜 일이 발생하지 않습니다.
편집 : 다른 필터 링크
EDIT2 : adrian.tarau는 서블릿이 작업을 수행 한 후 응답을 변경하려면 HttpServletResponseWrapper를 확장하는 래퍼를 만들고 출력을 버퍼링해야한다는 점에서 정확합니다. 이것은 출력이 클라이언트로 직접 전달되는 것을 막기위한 것이지만이 발췌문 (강조 내)에 따라 서블릿이 스트림을 닫는 경우 보호 할 수도 있습니다.
응답을 수정하는 필터는 일반적으로 클라이언트로 반환되기 전에 응답을 캡처 해야합니다
. 이를 수행하는 방법은 응답을 생성하는 서블릿을 대기 스트림으로 전달하는 것입니다. 대기 스트림은 서블릿이 완료 될 때 원래 응답 스트림을 닫는 것을 방지하고 필터가 서블릿의 응답을 수정할 수 있도록합니다.
공식 Sun 기사 OutputStream
에서 서블릿에서 를 닫는 것은 정상적인 현상이지만 필수는 아니라는 것을 추론 할 수 있습니다 .
답변
일반적인 규칙은 다음과 같습니다. 스트림을 열었다면 닫아야합니다. 하지 않았다면하지 말아야합니다. 코드가 대칭인지 확인하십시오.
의 경우 HttpServletResponse
호출이 경우는 명확하지이기 때문에, 그것은 조금 덜 명확한의 getOutputStream()
스트림을 여는 작업입니다. Javadoc은 ” Returns a ServletOutputStream
” 라고 말합니다 . 유사하게 getWriter()
. 어느 쪽이든 분명한 것은 HttpServletResponse
스트림 / 라이터 를 “소유”하고 해당 스트림 / 라이터를 다시 닫을 책임이 있다는 것입니다.
따라서 귀하의 질문에 대답하려면-아니요,이 경우 스트림을 닫으면 안됩니다. 컨테이너는이를 수행해야하며 그 전에 거기에 들어가면 애플리케이션에 미묘한 버그가 발생할 위험이 있습니다.
답변
필터는 ‘포함’자원 호출 할 수있는 기회, 당신이해야 확실히있는 경우 하지 가까운 스트림. 이로 인해 포함 리소스가 ‘스트림 종료’예외와 함께 실패합니다.
답변
스트림을 닫아야합니다. getOutputStream ()을 호출하고 스트림이 매개 변수로 전달되지 않기 때문에 코드가 더 깔끔합니다. 일반적으로 스트림을 사용하고 닫으려고하지 않을 때입니다. Servlet API는 출력 스트림을 닫을 수 있거나 닫지 말아야한다고 명시하지 않습니다.이 경우 스트림을 안전하게 닫을 수 있으며, 서블릿에 의해 닫히지 않은 경우 외부 컨테이너가 스트림을 닫는 작업을 처리합니다.
Jetty의 close () 메서드는 스트림이 닫히지 않으면 닫습니다.
public void close() throws IOException
{
if (_closed)
return;
if (!isIncluding() && !_generator.isCommitted())
commitResponse(HttpGenerator.LAST);
else
flushResponse();
super.close();
}
또한 필터 개발자로서 OutputStream이 닫혀 있지 않다고 가정해서는 안되며, 서블릿이 작업을 완료 한 후 콘텐츠를 변경하려면 항상 다른 OutputStream을 전달해야합니다.
편집 : 나는 항상 스트림을 닫고 있으며 Tomcat / Jetty에 문제가 없었습니다. 나는 당신이 오래되거나 새 컨테이너에 어떤 문제가 있어야한다고 생각하지 않습니다.
답변
을 닫는에 대한 또 다른 인수 OutputStream
. 이 서블릿을보십시오. 예외가 발생합니다. 예외는 web.xml에서 오류 JSP로 매핑됩니다.
package ser;
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet(name = "Erroneous", urlPatterns = {"/Erroneous"})
public class Erroneous extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
try {
throw new IOException("An error");
} finally {
// out.close();
}
}
}
web.xml 파일에는 다음이 포함됩니다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<error-page>
<exception-type>java.io.IOException</exception-type>
<location>/error.jsp</location>
</error-page>
</web-app>
그리고 error.jsp :
<%@page contentType="text/html" pageEncoding="UTF-8" isErrorPage="true"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Error Page</title>
</head>
<body>
<h1><%= exception.getMessage()%></h1>
</body>
</html>
/Erroneous
브라우저에서 로드하면 “오류”를 표시하는 오류 페이지가 표시됩니다. 그러나 out.close()
위의 서블릿에서 주석을 제거하고 응용 프로그램을 다시 배포 한 다음 다시로드 /Erroneous
하면 브라우저에 아무것도 표시되지 않습니다. 나는 실제로 무슨 일이 일어나고 있는지에 대한 단서가 없지만 out.close()
오류 처리 를 방해 한다고 생각합니다 .
Netbeans 7.4를 사용하여 Tomcat 7.0.50, Java EE 6에서 테스트되었습니다.