Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将OutputStream与InputStream连接_Java_Servlets_Stream - Fatal编程技术网

Java 将OutputStream与InputStream连接

Java 将OutputStream与InputStream连接,java,servlets,stream,Java,Servlets,Stream,我正在试验一个小的web框架,偶然发现了一个关于streams的问题。有一些处理程序方法,如Response-get(HttpServletRequest)。从框架的角度来看,响应应该为响应主体提供一个输入流。框架读取该流并将数据写入ServletAPI的底层OutputStream。但是从用户的角度来看,需要写入一个OutputStream 框架的观点: public interface Response { InputStream getInputStream(); } public

我正在试验一个小的web框架,偶然发现了一个关于streams的问题。有一些处理程序方法,如
Response-get(HttpServletRequest)
。从框架的角度来看,响应应该为响应主体提供一个输入流。框架读取该流并将数据写入ServletAPI的底层OutputStream。但是从用户的角度来看,需要写入一个OutputStream

框架的观点:

public interface Response {
  InputStream getInputStream();
}
public interface Response {
  InputStream getOutputStream();
}
用户视角:

public interface Response {
  InputStream getInputStream();
}
public interface Response {
  InputStream getOutputStream();
}
应该这样使用:

public void get(HttpServletRequest request) {
  Response response = new Response(OK);
  response.getOutputStream().write(...);
  return response;
}
public class RequestImpl implements Request {
    private HttpServletRequest request;
    private HttpServletResponse response;

    public RequestImpl(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    public Response newResponse(Status status) {
        return new ResponseImpl(response, status);
        // Add a boolean responseCreated to avoid creation of multiple responses? Illegal state!
    }

    public String getParameter(String name) { // Just another example of decorated method.
        return request.getParameter(name);
    }

    // ...
}
public class ResponseImpl implements Response {
    private HttpServletResponse response;

    public ResponseImpl(HttpServletResponse response, Status status) {
        this.response = response;
        this.response.setStatus(status.getCode());
    }

    public OutputStream getOutputStream() {
        return response.getOutputStream();
    }

    // ...
}
问题是我无法创建没有输出目标的outputstream(并且不想写入ByteArray缓冲区)


你知道如何给用户一个OutputStream而不像ServletAPI那样传入一个吗?我希望避免使用输出参数。

当您给客户端一个OutputStream时,它必须连接到某个东西,缓冲区、套接字、文件或其他可以处理写入它的数据的东西


一个选项可能是将其设置为连接到处理数据的另一个线程中的PipedInputStream的PipedOutStream。但是,如果处理线程不能跟上客户端线程的速度,这将遇到问题。

正如Jim Garrison所说,
输出流必须连接到某个东西。。。写入其中的字节必须转移到某个地方,否则将被丢弃

在我看来,您需要做的是让
Response
直接包装
InputStream
。在
响应
上可能有如下方法:

void setContent(InputStream content);
然后,用户可以提供他们想要的任何类型的
InputStream
,而不是写入您提供的
OutputStream
,您的框架只需将其复制到servlet
OutputStream

您还可以允许他们提供一些实现类似以下接口的东西:

interface OutputProducer {
   void writeTo(OutputStream out) throws IOException;
}
在这两种情况下,您基本上都允许用户提供一个用于写入
OutputStream
的回调,这样您就不需要传入它


为了避免使用输出参数,我真的不知道这些是否值得,但这些都是选项。

也提取/修饰
请求,并从中获取
响应

例如,在前端控制器servlet中:

protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    Request request = new RequestImpl(req, res);
    Action action = ActionFactory.getAction(req); // Do whatever way you do to locate the `Action`.
    Response = action.get(request);
    // ...
}
其中,
RequestImpl
如下所示:

public void get(HttpServletRequest request) {
  Response response = new Response(OK);
  response.getOutputStream().write(...);
  return response;
}
public class RequestImpl implements Request {
    private HttpServletRequest request;
    private HttpServletResponse response;

    public RequestImpl(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    public Response newResponse(Status status) {
        return new ResponseImpl(response, status);
        // Add a boolean responseCreated to avoid creation of multiple responses? Illegal state!
    }

    public String getParameter(String name) { // Just another example of decorated method.
        return request.getParameter(name);
    }

    // ...
}
public class ResponseImpl implements Response {
    private HttpServletResponse response;

    public ResponseImpl(HttpServletResponse response, Status status) {
        this.response = response;
        this.response.setStatus(status.getCode());
    }

    public OutputStream getOutputStream() {
        return response.getOutputStream();
    }

    // ...
}
ResponseImpl
如下所示:

public void get(HttpServletRequest request) {
  Response response = new Response(OK);
  response.getOutputStream().write(...);
  return response;
}
public class RequestImpl implements Request {
    private HttpServletRequest request;
    private HttpServletResponse response;

    public RequestImpl(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    public Response newResponse(Status status) {
        return new ResponseImpl(response, status);
        // Add a boolean responseCreated to avoid creation of multiple responses? Illegal state!
    }

    public String getParameter(String name) { // Just another example of decorated method.
        return request.getParameter(name);
    }

    // ...
}
public class ResponseImpl implements Response {
    private HttpServletResponse response;

    public ResponseImpl(HttpServletResponse response, Status status) {
        this.response = response;
        this.response.setStatus(status.getCode());
    }

    public OutputStream getOutputStream() {
        return response.getOutputStream();
    }

    // ...
}
您最终在
操作中使用了以下内容:

public ActionImpl implements Action {
    public Response get(Request request) {
        Response response = request.newResponse(OK);
        response.getOutputStream().write("body");
        return response;
    }
}

或者,您也可以创建一个
上下文
,该上下文接受
HttpServletRequest
HttpServletResponse
,并将其传入,而不是
Request
。这也是一般MVC框架所做的事情。例如

protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    Context context = new ContextImpl(req, res);
    Action action = ActionFactory.getAction(req); // Do whatever way you do to locate the `Action`.
    action.execute(context);
    context.render(); // Do here whatever you'd initially to do with the obtained Response.
}


这就是说,我建议您也看看现有的API,而不是重新设计。根据您想要做什么,JSF、JAX-RS或JAX-WS可能是您真正想要的。除非这纯粹是出于爱好;)