Java 将OutputStream与InputStream连接
我正在试验一个小的web框架,偶然发现了一个关于streams的问题。有一些处理程序方法,如Java 将OutputStream与InputStream连接,java,servlets,stream,Java,Servlets,Stream,我正在试验一个小的web框架,偶然发现了一个关于streams的问题。有一些处理程序方法,如Response-get(HttpServletRequest)。从框架的角度来看,响应应该为响应主体提供一个输入流。框架读取该流并将数据写入ServletAPI的底层OutputStream。但是从用户的角度来看,需要写入一个OutputStream 框架的观点: public interface Response { InputStream getInputStream(); } public
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
,您的框架只需将其复制到servletOutputStream
您还可以允许他们提供一些实现类似以下接口的东西:
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可能是您真正想要的。除非这纯粹是出于爱好;)