您已經可以很輕松地使用帶有JSF的Spring,Spring可以管理bean和JSF來處理屏幕。 Spring Web Flow中還對JSF提供了一些非常好的支持,如果您正在做任何基于流的應用程序,那么您確實應該使用Web Flow。 Web Flow還提供org.springframework.faces.mvc.
JsfView類,使您可以從Spring MVC呈現JSF頁面。 不幸的是, JsfView
僅呈現瞬態(無狀態)視圖,如果您想處理回發,則JsfView
走運。
允許Spring MVC渲染可以處理回發的JSF視圖一直是我啟動該項目的主要動力。 得益于MVC和JSF的靈活性,完全可以集成這些技術(盡管關于如何最好地保存其他帖子的確切細節)。 我想在本文的其余部分中討論如何創建非常好的JSF導航。
如果您使用了標準的JSF導航,那么您可能已經習慣了faces-config.xml
的以下類型的事情:
<navigation-rule><from-view-id>/pages/list.xhtml</from-view-id><navigation-case><from-outcome>select</from-outcome><to-view-id>/pages/details.xhtml</to-view-id><redirect/></navigation-case>
</navigation-rule>
雖然很容易理解,但是對于標準方法來說,標準方法存在一些明顯的缺點,因為它非常冗長。 大多數時候,我想重定向我的用戶,而不是讓他們困惑為什么URL顯示與當前頁面不同的內容。 實際上在每個元素上都需要<redirect/>
確實很煩人。 XML的數量顯然使JSF的開發人員感到不安,幸運的是,JSF 2.0引入了隱式導航的概念。 這是我們稍后將使用的東西。 如果您想閱讀有關JSF導航的非常好的文章,請使用Dan Allen撰寫的JSF 2中的Fluent Navigation 。
導航實際上是關于目的地的,將某人重定向到404 page not found
錯誤沒有多大意義。 對于JSF而言,創建漂亮的可讀URL目標始終是一件艱辛的事情。 現在,在不開發自己的代碼的情況下,創建可讀URL的最佳選擇可能是使用PrettyFaces 。 當然,通過將JSF和Spring很好地集成在一起,您不需要使用@RequestMapping
注釋以外的任何其他東西來創建可讀的URL。 下面的示例演示如何映射一個可讀的URL,以顯示ID中的酒店詳細信息。
@Controller
public class HotelsController {@RequestMapping(value = "/hotels/{id}", method = RequestMethod.GET)public String show(@PathVariable Long id, Model model) {model.addAttribute(bookingService.findHotelById(id));return "hotels/show";}
}
有了@RequestMapping
批注,我們可以再次考慮導航。 通常, <h:commandButton>
, <h:button>
, <h:commandLink>
或<h:link>
組件將用于觸發導航,例如:
<h:commandButton value="Go" action="select">
在此,當用戶單擊"Go"
按鈕時, "select"
動作開始,并且導航規則用于查找目的地。 當我們要遠離定義導航XML時,我們需要另一種方法來查找MVC目標。 稍微顛覆JSF對隱式導航的支持為我們提供了一種很好的方法。 通過一些集成代碼,我們可以支持特殊的"spring:"
前綴,該前綴告訴JSF使用Spring MVC解析目標。
<h:commandButton value="Go" action="spring:redirect:/spring/hotels/123"/>
上面的示例將使用在Spring MVC中注冊的ViewResolver
解析"redirect:/spring/hotel/123"
。 在這種情況下, UrlBasedViewResolver
將選擇"redirect:"
并將使用RedirectView
。
很好,但是將酒店ID "123"
硬編碼到視圖名稱中并不是很實際。 幸運的是有一個答案:
<h:commandButton value="Go" action="spring:redirect:/spring/hotels/{id}"><f:param name="id" value="#{resultItem.id}/>
</h:commandButton>
commandButton
所有<f:param>
子標記將用于構造MVC視圖的模型。 在這種情況下,我們得到一個包含“ id=#{resultItem.id}
”的模型。 EL值表達式#{resultItem.id}
將在呈現視圖之前解析。 Spring 3.1中的RedirectView
類將處理URL模板變量,因此“ /spring/hotels/{id}
”將選擇“ id
”以呈現完整的URL。
使用上述方法的一點煩惱是您需要在XHTML文件以及@RequestMapping
批注中定義URL。 作為替代方案,您可以使用特殊的“ @bean.method
”符號表示您要導航至指定控制器bean方法上的@RequestMapping
的值:
<h:commandButton value="Go" action="spring:@hotelsController.show"><f:param name="id" value="#{resultItem.id}/>
</h:commandButton>
如果在控制器bean上有多個@RequestMapping
方法,則可以使用更短的語法“ @method
”(此處假定該bean是當前處理程序)在它們之間進行導航。 當然,并非每種類型的@RequestMapping
都可以反向轉換為URL,例如,如果您使用通配符,則此操作將無效。 建議是使您的映射盡可能簡單。
這種方法的最后一個好處是我們還可以逆轉DataBinder
過程。 例如:
public class SearchCriteria implements Serializable {private String searchString;private int page;// ... getters / setters
}
@RequestMapping(value = "/hotels")
public String list(SearchCriteria criteria, Model model) {// ...
}
<h:link outcome="spring:@list"><f:param name="sc" value="#{searchCriteria}"/>
</h:link>
假定#{searchCriteria}
EL表達式解析為包含字符串"California"
的SearchCriteria
對象,并且所構建的URL的整數10
將為"/spring/hotels?searchString=California&page=10"
。
如果您想查看該項目的代碼,可以在http://github.com/philwebb/springfaces上找到它。 如文章頂部所述,此代碼尚在開發中,因此請注意一些問題。 路線圖上的下一個任務是支持@NavigationMapping
批注,該批注將允許以編程方式進行導航。
參考: 集成Spring和JavaServer Faces: JCG合作伙伴 Phillip Webb的 導航 ? 在Phil Webb的Blog上 。
翻譯自: https://www.javacodegeeks.com/2012/03/spring-jsf-integration-navigation.html