JavaServer Faces (JSF) with Spring – 使用Spring的JavaServer Faces(JSF)

最后修改: 2016年 6月 3日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this article we will look at a recipe for accessing beans defined in Spring from within a JSF managed bean and a JSF page, for the purposes of delegating the execution of business logic to the Spring beans.

在这篇文章中,我们将看一下从JSF管理的Bean和JSF页面中访问Spring中定义的Bean的配方,以便将业务逻辑的执行委托给Spring Bean。

This article presumes the reader has a prior understanding of both JSF and Spring separately. The article is based on the Mojarra implementation of JSF.

本文假定读者事先对JSF和Spring都有一定的了解。本文是基于JSF的Mojarra实现

2. In Spring

2.在Spring

Let’s have the following bean defined in Spring. The UserManagementDAO bean adds a username to an in-memory store, and it’s defined by the following interface:

让我们在Spring中定义以下Bean。UserManagementDAO bean将用户名添加到内存存储中,它由以下接口定义。

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

The implementation of the bean is configured using the following Java config:

Bean的实现是用以下Java配置的。

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

Or using the following XML configuration:

或者使用以下XML配置。

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

We define the bean in XML, and register CommonAnnotationBeanPostProcessor to ensure that the @PostConstruct annotation is picked up.

我们在XML中定义Bean,并注册CommonAnnotationBeanPostProcessor以确保@PostConstruct注释被接收。

3. Configuration

3.配置

The following sections explain the configuration items that enable the integration of the Spring and JSF contexts.

下面几节解释了实现Spring和JSF上下文集成的配置项。

3.1. Java Configuration Without web.xml

3.1.没有web.xml的Java配置

By implementing the WebApplicationInitializer we are able to programatically configure the ServletContext. The following is the onStartup() implementation inside the MainWebAppInitializer class:

通过实现WebApplicationInitializer,我们能够以编程方式配置ServletContext。MainWebAppInitializer类中的onStartup()实现。

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

The AnnotationConfigWebApplicationContext bootstraps the Spring’g context and adds the beans by registering the SpringCoreConfig class.

AnnotationConfigWebApplicationContext引导Spring’g上下文,并通过注册SpringCoreConfig类来添加bean。

Similarly, in the Mojarra implementation there is a FacesInitializer class that configures the FacesServlet. To use this configuration it is enough to extend the FacesInitializer. The complete implementation of the MainWebAppInitializer, is now as follows:

同样,在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. With web.xml

3.2.使用web.xml

We’ll start by configuring the ContextLoaderListener in web.xml file of the application:

我们将首先在应用程序的web.xml文件中配置ContextLoaderListener

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

This listener is responsible for starting up the Spring application context when the web application starts up. This listener will look for a spring configuration file named applicationContext.xml by default.

这个监听器负责在Web应用启动时启动Spring应用上下文。这个监听器将寻找一个名为applicationContext.xml的默认的Spring配置文件。

3.3. faces-config.xml

3.3.faces-config.xml

We now configure the SpringBeanFacesELResolver in the face-config.xml file:

我们现在在face-config.xml文件中配置了SpringBeanFacesELResolver

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

An EL resolver is a pluggable component supported by the JSF framework, allowing us to customize the behavior of the JSF runtime when evaluating Expression Language (EL) expressions. This EL resolver will allow the JSF runtime access Spring components via EL expressions defined in JSF.

EL解析器是JSF框架支持的一个可插拔组件,允许我们在评估表达式语言(EL)表达式时自定义JSF运行时的行为。这个EL解析器将允许JSF运行时通过JSF中定义的EL表达式访问Spring组件。

4. Accessing Spring Beans in JSF

4.在JSF中访问Spring Bean

At this point, our JSF web application is primed to access our Spring bean from either a JSF backing bean, or from a JSF page.

在这一点上,我们的JSF网络应用已经准备好了,可以从JSF支持的Bean或JSF页面中访问我们的Spring Bean。

4.1. From a Backing Bean JSF 2.0

4.1.从后盾BeanJSF 2.0

The Spring bean can now be accessed from a JSF backing bean. Depending on the version of JSF you’re running, there are two possible methods. With JSF 2.0, you use the @ManagedProperty annotation on the JSF managed bean.

现在可以通过JSF的支持Bean来访问Spring Bean。根据你所运行的JSF的版本,有两种可能的方法。对于JSF 2.0,你可以使用JSF托管Bean上的@ManagedProperty注解。

@ManagedBean(name = "registration")
@RequestScoped
public class RegistrationBean implements Serializable {
    @ManagedProperty(value = "#{userManagementDAO}")
    transient private IUserManagementDAO theUserDao;

    private String userName;
    // getters and setters
}

Note that the getter and setter are mandatory when using the @ManagedProperty.
Now – to assert the accessibility of a Spring bean from a managed bean, we will add the createNewUser() method:

注意,在使用@ManagedProperty时,getter和setter是必须的。
现在–为了断言一个Spring Bean对托管Bean的可访问性,我们将添加createNewUser()方法。

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

The gist of the method is using the userDao Spring bean, and accessing its functionality.

该方法的要点是使用userDao Spring Bean,并访问其功能。

4.2. From a Backing Bean in JSF 2.2

4.2.来自JSF 2.2中的后援Bean

Another approach, valid only in JSF2.2 and above, is to use CDI’s @Inject annotation. This is applicable to JSF managed beans (with the @ManagedBean annotation), and CDI-managed beans (with the @Named annotation).

另一种方法是使用CDI的@Inject注解,该方法仅在JSF2.2及以上版本中有效。这适用于JSF管理的Bean(带有@ManagedBean注解),以及CDI管理的Bean(带有@Named注解)。

Indeed, with a CDI annotation, this is the only valid method of injecting the bean:

事实上,在CDI注解下,这是注入Bean的唯一有效方法。

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

With this approach, the getter and setter are not necessary. Also note that the EL expression is absent.

使用这种方法,getter和setter就没有必要了。还要注意的是,EL表达式是不存在的。

4.3. From a JSF View

4.3.来自JSF视图

The createNewUser() method will be triggered from the following JSF page:

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>

To render the page, start the server and navigate to:

要渲染该页面,启动服务器并导航到。

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

We can also use EL in the JSF view, to access the Spring bean. To test it it is enough to change the line number 7 from the previously introduced JSF page to:

我们也可以在JSF视图中使用EL,来访问Spring Bean。为了测试它,只需将之前介绍的JSF页面中的第7行改为。

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

Here, we call the createUser method directly on the Spring DAO, passing the bind value of the userName to the method from within the JSF page, circumventing the managed bean all together.

在这里,我们直接在Spring DAO上调用createUser方法,将userName的绑定值从JSF页面中传递给该方法,完全避开了托管Bean。

5. Conclusion

5.结论

We examined a basic integration between the Spring and JSF contexts, where we’re able to access a Spring bean in a JSF bean and page.

我们研究了Spring和JSF上下文之间的基本集成,我们能够在JSF Bean和页面中访问Spring Bean。

It’s worth noting that while the JSF runtime provides the pluggable architecture that enables the Spring framework to provide integration components, the annotations from the Spring framework cannot be used in a JSF context and vice versa.

值得注意的是,虽然JSF运行时提供了可插拔的架构,使Spring框架能够提供集成组件,但Spring框架的注释不能在JSF上下文中使用,反之亦然。

What this means is that you’ll not be able to use annotations like @Autowired or @Component etc. in a JSF managed bean, or use the @ManagedBean annotation on a Spring managed bean. You can however, use the @Inject annotation in both a JSF 2.2+ managed bean, and a Spring bean (because Spring supports JSR-330).

这意味着你不能在JSF托管Bean中使用@Autowired@Component等注解,或在Spring托管Bean上使用@ManagedBean注解。然而,你可以在JSF 2.2+托管Bean和Spring Bean中使用@Inject注解(因为Spring支持JSR-330)。

The source code that accompanies this article is available at GitHub.

伴随着这篇文章的源代码可在GitHub获得。