2012-03-28 52 views
7

假設下面的應用景觀:JSF。 URL重寫解決方案所需

+-----------------+ 
| App server  | 
+-----------------+ 
|     |         +-------+ 
| ear1   |         |  | 
| +-web1 (/ctx1) +--<-- http://localhost/ctx1/xxx/ --+  +--<-- http://www.domain.com/xxx/ 
|     |         |  | 
|     |         | proxy | 
| ear2   |         |  | 
| +-web2 (/ctx2) +--<-- http://localhost/ctx2/yyy/ --+  +--<-- http://abc.domain.com/yyy/ 
|     |         |  | 
+-----------------+         +-------+ 

正如你所看到的,代理(nginx在我的情況)將請求轉發到一個應用程序服務器實例,而這又與多個網絡模塊不同的環境路徑。當然,我不希望我的公共服務器暴露內部上下文根,並且代理服務器很好地工作,打包和解包http請求等。但是仍然存在一個大問題:JSF生成的html代碼(鏈接,css,js資源,表單行動)包含上下文路徑,/ctx1/ctx2在我的情況。這就是我想要避免的。

中堂我在這一刻的時間內沒有解決,除了使用應用程序服務器的越來越多的不同實例(域),導致我的硬件資源逐漸消失的。據我瞭解,我需要擴展我的JSF應用程序與一些包裝,可能註冊在faces-config.xml,這將刪除生成的HTML中的上下文前綴。任何其他解決方案也受到歡迎。

請指點我正確的方向。

回答

4

我張貼的解決方案可能是爲他人面臨同樣的問題很有幫助。所有我需要做的就是實現我自己的javax.faces.application.ViewHandler,並將其註冊在faces-config.xml

public class CustomViewHandler extends ViewHandlerWrapper { 
    private ViewHandler wrappped; 

    public CustomViewHandler(ViewHandler wrappped) { 
    super(); 
    this.wrappped = wrappped; 
    } 

    @Override 
    public ViewHandler getWrapped() { 
    return wrappped; 
    } 

    @Override 
    public String getActionURL(FacesContext context, String viewId) { 
    String url = super.getActionURL(context, viewId); 
    return removeContextPath(context, url); 
    } 

    @Override 
    public String getRedirectURL(FacesContext context, String viewId, Map<String, List<String>> parameters, boolean includeViewParams) { 
    String url = super.getRedirectURL(context, viewId, parameters, includeViewParams); 
    return removeContextPath(context, url); 
    } 

    @Override 
    public String getResourceURL(FacesContext context, String path) { 
    String url = super.getResourceURL(context, path); 
    return removeContextPath(context, url); 
    } 

    private String removeContextPath(FacesContext context, String url) { 
    ServletContext servletContext = (ServletContext) context.getExternalContext().getContext(); 
    String contextPath = servletContext.getContextPath(); 
    if("".equals(contextPath)) return url; // root context path, nothing to remove 
    return url.startsWith(contextPath) ? url.substring(contextPath.length()) : url; 
    } 
} 

faces-config.xml中:

<faces-config xmlns="http://java.sun.com/xml/ns/javaee" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" 
       version="2.0"> 
    <application> 
    <view-handler>test.CustomViewHandler</view-handler> 
    </application> 
</faces-config> 
+2

注:這也可以用'Filter'完成不到一半的代碼。 – BalusC 2012-03-29 20:22:04

+0

@BalusC,今天我即將實施您的過濾器解決方案,但被您的帖子被刪除的事實嚇跑了)) – Osw 2012-03-29 20:32:23

+0

我只是將其刪除,因爲它畢竟不值得付出努力。 – BalusC 2012-03-30 15:29:50

5

您可以使用OCPsoft Rewrite URLRewriteFilter這個(不PrettyFaces目前,但你可以同時使用它們,直到它們在PrettyFaces 4發佈後正式聯合在一起 - 重寫是PrettyFaces 4的核心項目)

做這樣的事情應該是相當直接的使用罪gle配置規則。如果這個規則過於嚴格或過於籠統,你顯然可能會弄亂。

.defineRule() 
.when(URL.matches("{prefix}" + context.getContextPath() + "{suffix}") 
.perform(Substitute.with("{prefix}{suffix}")) 

查看重寫網站。這很容易設置。 http://ocpsoft.org/rewrite/

+0

嗨,林肯!它是否也適用於我的網頁上的CSS,JS和其他資源? – Osw 2012-03-29 19:06:41

+0

只要這些鏈接是通過JSF呈現的,而不是在HTML中進行硬編碼的,那麼絕對是。否則,您可以設置其他規則來處理該情況。 – Lincoln 2012-03-30 03:47:19

1

我面臨同樣的問題,並試圖解決方案。雖然它或多或少的工作,但仍有一些小故障。說實話,感覺更像是與症狀對抗,而不是治療疾病。

那麼這裏就是終於爲我工作:

而不是通過路徑分開設置的部署,我分配每個部署到自己的端口:

foo.war <-- http://localhost:8080/ -- | Proxy | <-- http://www.foo.com -- | Client | 
bar.war <-- http://localhost:8181/ -- | Proxy | <-- http://www.bar.com -- | Client | 

這樣一來,無論是部署能夠使用/作爲它們的上下文路徑,因此不需要編輯上下文路徑。

要做到這一點,你不必同時運行兩個應用程序服務器。在我的情況(Wildfly 10.0),這是足以確定在wildfly配置的兩個暗流服務器,每個服務器都有自己的虛擬主機和HTTP偵聽器,像這樣:

<server name="foo-server"> 
    <http-listener name="foo-listener" proxy-address-forwarding="true" socket-binding="foo-http"/> 
    <host name="foo-host" default-web-module="foo.war" alias="localhost, foo.com, wwww.foo.com"/> 
</server> 
<server name="bar-server"> 
    <http-listener name="bar-listener" proxy-address-forwarding="true" socket-binding="bar-http"/> 
    <host name="bar-host" default-web-module="bar.war" alias="localhost, bar.com, wwww.bar.com"/> 
</server> 

<socket-binding name="foo-http" port="${jboss.http.port:8080}"/> 
<socket-binding name="bar-http" port="${jboss.http.port:8181}"/> 

您還需要一個JBoss的Web。xml在您的項目中:

<?xml version="1.0" encoding="UTF-8"?> 
<jboss-web> 
    <server-instance>foo-server</server-instance> 
    <virtual-host>foo-host</virtual-host> 
    <context-root>/</context-root> 
</jboss-web> 

這兩個服務器是必需的,因爲您無法將套接字綁定添加到虛擬主機。所以這裏有一些小的開銷,但與運行兩個完整的應用程序服務器相比微不足道。

編輯1:

它只是發生,我認爲這是可能甚至沒有必要使用不同的端口和使用每一個deplyoment暗潮服務器可能是多餘的,因爲好。

由於代理能夠將客戶端請求的主機轉發到應用程序服務器,因此承運人應該能夠通過別名參數挑選合適的虛擬主機。

所以基本上,代理服務器會將任何請求轉發到foo.com或bar.com到localhost:8080,然後讓AS進行排序。

我沒有測試過這,但這裏是它如何可以工作(同樣,這是Wildfly 10.0):

<server name="default-server"> 
    <http-listener name="http" proxy-address-forwarding="true" socket-binding="http"/> 
    <host name="foo-host" default-web-module="foo.war" alias="foo.com, wwww.foo.com"/> 
    <host name="bar-host" default-web-module="bar.war" alias="bar.com, wwww.bar.com"/> 
</server> 

和JBoss-web.xml中就輸了服務器標籤:

<?xml version="1.0" encoding="UTF-8"?> 
<jboss-web> 
    <virtual-host>foo-host</virtual-host> 
    <context-root>/</context-root> 
</jboss-web> 

在這種情況下,根本不會有任何開銷。

編輯2:

剛剛測試過的簡單的方法 - 是的,它的工作原理:)