知識庫 / Spring / Spring MVC RSS 訂閱

Spring 與 JavaServer Faces (JSF) 集成開發指南

Spring MVC
HongKong
5
02:50 PM · Dec 06 ,2025

1. 概述

本文將探討如何從 JSF 管理 Bean 和 JSF 頁面中訪問 Spring 中定義的 Bean,以便將業務邏輯的執行委託給 Spring Bean。

本文假設讀者已對 JSF 和 Spring 獨立了解。本文基於 Mojarra 實現 的 JSF。

2. 在 Spring 中

以下 Bean 在 Spring 中已定義。<em>UserManagementDAO</em> Bean 將用户名添加到內存存儲中,並由以下接口定義:

public interface UserManagementDAO {
    boolean createUser(String newUserData);
}

使用以下 Java 配置來配置 Bean 的實現:

public class SpringCoreConfig {
    @Bean
    public UserManagementDAO userManagementDAO() {
        return new UserManagementDAOImpl();
    }
}

或者使用以下 XML 配置:

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<bean class="com.baeldung.dao.UserManagementDAOImpl" id="userManagementDAO"/>

我們通過 XML 定義 Bean,並註冊 CommonAnnotationBeanPostProcessor 以確保 @PostConstruct 註解能夠被識別。

3. 配置

以下部分解釋了用於啓用 Spring 和 JSF 環境集成的配置項。

3.1. 使用 Java 配置而不使用 web.xml

通過實現 WebApplicationInitializer,我們能夠程序化地配置 ServletContext。以下是 MainWebAppInitializer 類中 onStartup() 方法的實現:

public void onStartup(ServletContext sc) throws ServletException {
    AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
    root.register(SpringCoreConfig.class);
    sc.addListener(new ContextLoaderListener(root));
}

AnnotationConfigWebApplicationContext 啓動 Spring 的上下文,並通過註冊SpringCoreConfig 類添加 Bean。

類似地,在 Mojarra 實現中,有一個FacesInitializer 類,用於配置FacesServlet。要使用此配置,只需擴展FacesInitializer 即可。MainWebAppInitializer 的完整實現如下所示:

public class MainWebAppInitializer extends FacesInitializer implements WebApplicationInitializer {
    public void onStartup(ServletContext sc) throws ServletException {
        AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
        root.register(SpringCoreConfig.class);
        sc.addListener(new ContextLoaderListener(root));
    }
}

3.2. 使用 web.xml

我們將首先在應用程序的 web.xml 文件中配置 ContextLoaderListener

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

這個監聽器負責在 Web 應用程序啓動時啓動 Spring 應用上下文。 默認情況下,它會查找名為 applicationContext.xml 的 Spring 配置文件。

3.3. faces-config.xml

我們現在在 faces-config.xml 文件中配置 SpringBeanFacesELResolver

<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>

EL 解決器是 JSF 框架中支持的插件組件,允許我們自定義 JSF 運行時對錶達式語言 (EL) 表達式的評估行為。此 EL 解決器將允許 JSF 運行時通過 JSF 中定義的 EL 表達式訪問 Spring 組件。

4. 通過 JSF 訪問 Spring Bean

到目前為止,我們的 JSF Web 應用程序已經準備好可以從 JSF 後台 bean 或 JSF 頁面訪問我們的 Spring Bean。

<h3><strong>4.1. 從 Backing Bean JSF 2.0 中訪問 Spring Bean</strong></h3>
<p>Spring Bean 現在可以從 JSF Backing Bean 中訪問。根據您運行的 JSF 版本,有以下兩種方法。對於 JSF 2.0,您需要在 JSF 管理 Bean 上使用 <em >@ManagedProperty</em> 註解。</p>
@ManagedBean(name = "registration")
@RequestScoped
public class RegistrationBean implements Serializable {
    @ManagedProperty(value = "#{userManagementDAO}")
    transient private IUserManagementDAO theUserDao;

    private String userName;
    // getters and setters
}

請注意,在使用 @ManagedProperty 時,獲取器和設置器是必選的。 現在 – 為了驗證從管理 Bean 訪問 Spring Bean 的可訪問性,我們將添加 createNewUser() 方法:

public void createNewUser() {
    FacesContext context = FacesContext.getCurrentInstance();
    boolean operationStatus = userDao.createUser(userName);
    context.isValidationFailed();
    if (operationStatus) {
        operationMessage = "User " + userName + " created";
    }
}

該方法的關鍵在於使用 userDao Spring Bean,並訪問其功能。

4.2. 從 JSF 2.2 中的後置Bean

另一種方法,僅在 JSF 2.2 及更高版本中有效,是使用 CDI 的 <em >@Inject</em> 註解。此方法適用於 JSF 管理Bean(帶有 <em >@ManagedBean</em> 註解)和 CDI 管理Bean(帶有 <em >@Named</em> 註解)。

實際上,使用 CDI 註解,這是唯一有效的注入Bean的方法。

@Named( "registration")
@RequestScoped
public class RegistrationBean implements Serializable {
    @Inject
    UserManagementDAO theUserDao;
}

採用這種方法,getter 和 setter 就沒有必要。此外,EL 表達式也不存在。

4.3. 從 JSF 視圖出發

createNewUser() 方法將從以下 JSF 頁面觸發:

<h:form>
    <h:panelGrid id="theGrid" columns="3">
        <h:outputText value="Username"/>
        <h:inputText id="firstName" binding="#{userName}" required="true"
          requiredMessage="#{msg['message.valueRequired']}" value="#{registration.userName}"/>
        <h:message for="firstName" style="color:red;"/>
        <h:commandButton value="#{msg['label.saveButton']}" action="#{registration.createNewUser}"
          process="@this"/>
        <h:outputText value="#{registration.operationMessage}" style="color:green;"/>
    </h:panelGrid>
</h:form>

要渲染頁面,請啓動服務器並導航到:

http://localhost:8080/jsf/index.jsf

我們還可以使用 EL 在 JSF 視圖中訪問 Spring Bean。要測試它,只需將之前引入的 JSF 頁面的第 7 行更改為:

<h:commandButton value="Save"
  action="#{registration.userDao.createUser(userName.value)}"/>

在這裏,我們直接調用 createUser 方法,從 JSF 頁面將 userName 的綁定值傳遞給該方法,從而繞過所有託管 Bean。

5. 結論

我們考察了 Spring 和 JSF 之間的一般集成,在此集成中,我們可以在 JSF bean 和頁面中訪問 Spring bean。

值得注意的是,雖然 JSF 運行時提供了可插拔的架構,從而使 Spring 框架能夠提供集成組件,但 Spring 框架的註解在 JSF 上下文中無法使用,反之亦然。

這意味着您無法在 JSF 管理 bean 中使用諸如 @Autowired@Component 等註解,或者在 Spring 管理 bean 上使用 @ManagedBean 註解。但是,您可以使用 @Inject 註解,既可以在 JSF 2.2+ 管理 bean 中使用,也可以在 Spring bean 中使用(因為 Spring 支持 JSR-330)。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.