我需要手動將請求從其他servlet的服務方法轉發/處理到另一個servlet。這個調用另一個servlet的servlet應該從其他servlet的響應中提取數據,並將它自己的響應發送給客戶端。如何實現這種功能?如何在另一個servlet中使用其他servlet服務?
Client <-----> Servlet1 <-----> Servlet2
我知道這是不好的設計,但由於具體情況我們來介紹Servlet2的功能Servlet1
我需要手動將請求從其他servlet的服務方法轉發/處理到另一個servlet。這個調用另一個servlet的servlet應該從其他servlet的響應中提取數據,並將它自己的響應發送給客戶端。如何實現這種功能?如何在另一個servlet中使用其他servlet服務?
Client <-----> Servlet1 <-----> Servlet2
我知道這是不好的設計,但由於具體情況我們來介紹Servlet2的功能Servlet1
你需要使用HttpServletResponseWrapper並覆蓋其getOutputStream方法。
CustomHttpServletResponseWrapper
和CustomServletOutputStream
正在爲此執行。
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class CustomHttpServletResponseWrapper extends HttpServletResponseWrapper {
private ServletOutputStream outputStream;
private PrintWriter writer;
private CustomServletOutputStream os;
public CustomHttpServletResponseWrapper(HttpServletResponse response) throws IOException {
super(response);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (writer != null) {
throw new IllegalStateException("getWriter() has already been called on this response.");
}
if (outputStream == null) {
outputStream = getResponse().getOutputStream();
os = new CustomServletOutputStream(outputStream);
}
return os;
}
@Override
public PrintWriter getWriter() throws IOException {
if (outputStream != null) {
throw new IllegalStateException("getOutputStream() has already been called on this response.");
}
if (writer == null) {
os = new CustomServletOutputStream(getResponse().getOutputStream());
writer = new PrintWriter(new OutputStreamWriter(os, getResponse().getCharacterEncoding()), true);
}
return writer;
}
@Override
public void flushBuffer() throws IOException {
if (writer != null) {
writer.flush();
} else if (outputStream != null) {
os.flush();
}
}
public byte[] getContent() {
if (os != null) {
return os.getContent();
} else {
return new byte[0];
}
}
}
customServletOutputStream.java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
public class CustomServletOutputStream extends ServletOutputStream {
private OutputStream outputStream;
private ByteArrayOutputStream content;
public CustomServletOutputStream(OutputStream outputStream) {
this.outputStream = outputStream;
this.content = new ByteArrayOutputStream(1024);
}
@Override
public void write(int b) throws IOException {
outputStream.write(b);
content.write(b);
}
public byte[] getContent() {
return content.toByteArray();
}
@Override
public boolean isReady() {
// TODO Auto-generated method stub
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {
// TODO Auto-generated method stub
}
}
主類: 使用RequestDespetcher.include()
重定向請求S2並通過CustomHttpServletResponseWrapper
。
@ResponseBody
@RequestMapping("/s1")
public String s1(HttpServletRequest req, HttpServletResponse res) throws Exception{
RequestDispatcher rd = req.getRequestDispatcher("/oauth2/s2");
CustomHttpServletResponseWrapper wrappedResponse = new CustomHttpServletResponseWrapper(res);
rd.include(req, wrappedResponse);
wrappedResponse.flushBuffer();
byte[] result = wrappedResponse.getContent();
System.out.println("result of servlet 2 "+new String(result));
// here you got the result of servlet 2. manipulate it as you want.
return new String(result);
}
@ResponseBody
@RequestMapping("/s2")
public String s2(HttpServletRequest req, HttpServletResponse res){
return "hello from s2";
}
這也行不通,因爲S1的回答將根據S2 –
@TuomasToivonen的回覆計算,根據您的評論修改答案。 – Suraj
不幸的是,我們的項目有舊的Java平臺,它不支持HttpServletResponseWrapper。這看起來像一個裝飾模式,所以也許我可以自己實現它。無論如何,感謝您的詳細答案,我必須在我的個人項目上進行測試。 –
'response.sendRedirect();'怎麼辦? – Kartic
是的,您可以通過使用請求調度程序的Forward或Include方法(可用'request'對象)或Send Redirect方法(可用'response'對象)來實現。 'ServletContext'也是實現'servlet'協作的方式之一,因爲它是提供所有servlet信息的協議。 – Mihir