2010-01-27 55 views
3

我使用@WebService批註創建了一個Java Web服務,並將該服務部署到位於代理服務器後面的Glassfish服務器。我可以在Glassfish(或任何應用程序服務器)上攔截對我的WSDL的調用嗎?

問題是,當有人訪問我們的WSDL和服務端點地址位置看起來他們看到

http://app server url/service... 

,而不是

http://proxy server url/service... 

我想有代理服務器的URL中返回WSDL的服務端點地址位置,而不是應用服務器url。

我想知道的是,我可以編寫一個Filter或Listener來偵聽對WSDL的請求,然後使用代理服務器URL修改WSDL服務端點地址嗎?建議如何做到這一點 - 我認爲過濾器是最佳選擇,但並非100%確定?

順便說一句 - 我以爲這可能是一個簡單的設置在Glassfish做到這一點,但I haven't been able to locate one that works

+0

你有沒有試過在'@ WebService'註釋使用'wsdlLocation'屬性?你可以指定WSDL返回給客戶端。 – ewernli 2010-01-27 20:24:28

+0

CXF有一個特別的功能。 – bmargulies 2010-01-27 20:39:17

+0

@ewernli - 謝謝,但容器(Glassfish)似乎仍然覆蓋了端點地址。它似乎沒有工作。 – Vinnie 2010-01-27 21:01:48

回答

1

我採取了過濾方法,這就是我想出的。它似乎工作。

我已經包含了我的FilterdoFilter方法的代碼。我也寫了一個自定義HttpServletResponseWrapper,但是這個實現非常簡單。

Apache reverse-proxyx-forwarded-host值添加到HTTP標頭(並且是我用來替換應用程序服務器名稱的名稱)。我想到的另一種選擇是將代理服務器的地址作爲應用服務器上的一個屬性,並抓住它。最終,我認爲這是一個更清潔的方式。

/* 
* Replace the server URL with the proxy server URL when called from a proxy server 
*/ 
@Override 
public void doFilter(
    ServletRequest request, 
    ServletResponse response, 
    FilterChain filterChain) throws IOException, ServletException 
{ 
    WsdlResponseWrapper myResponse = new WsdlResponseWrapper((HttpServletResponse) response); 
    filterChain.doFilter(request, myResponse); 
    boolean isResponseOutputStream = myResponse.getOutputStreamContent().length > 0; 

    /* 
    * The servlet response sent into this method only allows access to 
    * getOutputStream or getWriter, not both. It will throw an 
    * exception if an attempt is made to to access both. 
    * 
    * If this reason, I'm checking the output stream first and writing 
    * that content if it exists, then printing to the writer only if 
    * the output stream is empty. 
    */ 
    StringBuffer responseBuffer; 
    if (isResponseOutputStream) { 
     responseBuffer = new StringBuffer(new String(myResponse.getOutputStreamContent())); 
    } else { 
     responseBuffer = new StringBuffer(myResponse.getWriterContent()); 
    } 

    // Change the URL when called from a proxy server 
    if (request instanceof HttpServletRequest) { 
     HttpServletRequest httpServletRequest = (HttpServletRequest) request; 

     String requestedHostname = httpServletRequest.getHeader("x-forwarded-host"); 
     if ((null != requestedHostname) && !requestedHostname.isEmpty()) { 
      String myHostname = httpServletRequest.getHeader("host"); 
      int myPort = httpServletRequest.getLocalPort(); 

      // change the hostname 
      int index = responseBuffer.indexOf(myHostname); 
      int length = myHostname.length(); 
      while (index > -1) { 
       responseBuffer.replace(index, index+length, requestedHostname); 
       index = responseBuffer.indexOf(myHostname); 
      } 

      // remove the port 
      String portString = ":" + myPort; 
      length = portString.length(); 
      index = responseBuffer.indexOf(portString); 
      while (index > -1) { 
       responseBuffer.replace(index, index+length, ""); 
       index = responseBuffer.indexOf(portString); 
      } 
     } 
    } 

    // forward the response 
    if (isResponseOutputStream) { 
     response.getOutputStream().write(responseBuffer.toString().getBytes()); 
    } else { 
     response.getWriter().print(responseBuffer); 
    } 
} 
1

Javaboutique article on servlet-filters

public final class TimerFilter implements Filter 
{ 

    public void doFilter(ServletRequest request, 
         ServletResponse response, 
         FilterChain chain) 
    throws IOException, ServletException 
{ 

    long startTime = System.currentTimeMillis(); 
    chain.doFilter(request, response); 
    long stopTime = System.currentTimeMillis(); 
    System.out.println("Time to execute request: " + (stopTime - startTime) + 
     " milliseconds"); 

} 
... 

調用chain.doFilter會打電話給你的情況正常的servlet(我假設@WebService是通過servlet API提供的),然後就可以讀取結果從原始Web服務中修改它並將其傳回給您自己的客戶端。

1

您是否考慮過使用網絡服務註冊表

glassfish文檔有關Web服務註冊表說:

如果您使用的是負載平衡器, 輸入負載平衡器主機名, 端口號和SSL端口號。 如果要發佈Web服務 到外部註冊表,其中 WSDL可以在互聯網上找到, 這些選項將替換 WSDL中指定負載 平衡器的一個 主機名和端口名。

因此,這也應該爲您的代理工作。

這裏有兩個資源可能很有趣:glassfish ws management頁面,文章aobut如何set up the registry

我從來沒有使用過註冊表,並且認同它對於你想達到的目標有點重要,但它似乎是向消費者發佈Web服務端點信息的一種可能方式。

相關問題