2016-08-03 81 views
0

我需要手動將請求從其他servlet的服務方法轉發/處理到另一個servlet。這個調用另一個servlet的servlet應該從其他servlet的響應中提取數據,並將它自己的響應發送給客戶端。如何實現這種功能?如何在另一個servlet中使用其他servlet服務?

Client <-----> Servlet1 <-----> Servlet2

我知道這是不好的設計,但由於具體情況我們來介紹Servlet2的功能Servlet1

+0

'response.sendRedirect();'怎麼辦? – Kartic

+0

是的,您可以通過使用請求調度程序的Forward或Include方法(可用'request'對象)或Send Redirect方法(可用'response'對象)來實現。 'ServletContext'也是實現'servlet'協作的方式之一,因爲它是提供所有servlet信息的協議。 – Mihir

回答

1

你需要使用HttpServletResponseWrapper並覆蓋其getOutputStream方法。

CustomHttpServletResponseWrapperCustomServletOutputStream正在爲此執行。

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"; 
    } 
+0

這也行不通,因爲S1的回答將根據S2 –

+0

@TuomasToivonen的回覆計算,根據您的評論修改答案。 – Suraj

+0

不幸的是,我們的項目有舊的Java平臺,它不支持HttpServletResponseWrapper。這看起來像一個裝飾模式,所以也許我可以自己實現它。無論如何,感謝您的詳細答案,我必須在我的個人項目上進行測試。 –

相關問題