1. Обзор
В этой статье мы рассмотрим рецепт доступа к bean-компонентам, определенным в Spring, из управляемого bean-компонента JSF и страницы JSF с целью делегирования выполнения бизнес-логики bean-компонентам Spring.
В этой статье предполагается, что читатель имеет предварительное представление о JSF и Spring по отдельности. Статья основана на реализации JSF в Mojarra.
2. Весной
Давайте определим следующий bean-компонент в Spring. Бин UserManagementDAO
добавляет имя пользователя в хранилище в памяти и определяется следующим интерфейсом:
public interface UserManagementDAO {
boolean createUser(String newUserData);
}
Реализация bean-компонента настраивается с использованием следующей конфигурации Java:
public class SpringCoreConfig {
@Bean
public UserManagementDAO userManagementDAO() {
return new UserManagementDAOImpl();
}
}
Или используя следующую конфигурацию XML:
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<bean class="com.foreach.dao.UserManagementDAOImpl" id="userManagementDAO"/>
Мы определяем bean-компонент в XML и регистрируем CommonAnnotationBeanPostProcessor
, чтобы гарантировать получение аннотации @PostConstruct .
3. Конфигурация
В следующих разделах объясняются элементы конфигурации, обеспечивающие интеграцию контекстов Spring и JSF.
3.1. Конфигурация Java без web.xml
Реализуя WebApplicationInitializer
, мы можем программно настроить ServletContext.
Ниже приведена реализация onStartup()
внутри класса MainWebAppInitializer
:
public void onStartup(ServletContext sc) throws ServletException {
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
root.register(SpringCoreConfig.class);
sc.addListener(new ContextLoaderListener(root));
}
AnnotationConfigWebApplicationContext
загружает контекст Spring'g и добавляет компоненты, регистрируя класс SpringCoreConfig
.
Точно так же в реализации 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. С веб.xml
Мы начнем с настройки ContextLoaderListener
в файле web.xml
приложения:
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
Этот прослушиватель отвечает за запуск контекста приложения Spring при запуске веб-приложения. Этот слушатель будет искать файл конфигурации spring с именем applicationContext.xml
по умолчанию.
3.3. лица-config.xml
Теперь мы настраиваем SpringBeanFacesELResolver
в файле face-config.xml
:
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
Преобразователь EL — это подключаемый компонент, поддерживаемый инфраструктурой JSF, позволяющий нам настраивать поведение среды выполнения JSF при оценке выражений языка выражений (EL). Этот преобразователь EL позволит среде выполнения JSF получать доступ к компонентам Spring через выражения EL, определенные в JSF.
4. Доступ к Spring Beans в JSF
На данный момент наше веб-приложение JSF подготовлено для доступа к нашему компоненту Spring либо из вспомогательного компонента JSF, либо со страницы JSF.
4.1. Из резервного компонента JSF 2.0
Доступ к компоненту Spring теперь можно получить из вспомогательного компонента JSF. В зависимости от версии JSF, которую вы используете, есть два возможных метода. В JSF 2.0 вы используете аннотацию @ManagedProperty
для управляемого компонента JSF.
@ManagedBean(name = "registration")
@RequestScoped
public class RegistrationBean implements Serializable {
@ManagedProperty(value = "#{userManagementDAO}")
transient private IUserManagementDAO theUserDao;
private String userName;
// getters and setters
}
Обратите внимание, что геттер и сеттер являются обязательными при использовании @ManagedProperty.
Теперь, чтобы подтвердить доступность компонента Spring из управляемого компонента, мы добавим метод createNewUser()
:
public void createNewUser() {
FacesContext context = FacesContext.getCurrentInstance();
boolean operationStatus = userDao.createUser(userName);
context.isValidationFailed();
if (operationStatus) {
operationMessage = "User " + userName + " created";
}
}
Суть метода заключается в использовании bean- компонента userDao
Spring и доступе к его функциям.
4.2. Из резервного компонента в JSF 2.2
Другой подход, допустимый только в JSF2.2 и выше, заключается в использовании аннотации CDI @Inject
. Это применимо к управляемым компонентам JSF (с аннотацией @ManagedBean
) и компонентам, управляемым CDI (с аннотацией @Named
).
Действительно, с аннотацией CDI это единственный допустимый метод внедрения bean-компонента:
@Named( "registration")
@RequestScoped
public class RegistrationBean implements Serializable {
@Inject
UserManagementDAO theUserDao;
}
При таком подходе геттер и сеттер не нужны. Также обратите внимание, что выражение 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. Для проверки достаточно изменить строку номер 7 из введенной ранее JSF-страницы на:
<h:commandButton value="Save"
action="#{registration.userDao.createUser(userName.value)}"/>
Здесь мы вызываем метод createUser
непосредственно в Spring DAO, передавая значение привязки userName
методу со страницы JSF, полностью обходя управляемый компонент.
5. Вывод
Мы рассмотрели базовую интеграцию между контекстами Spring и JSF, где мы можем получить доступ к bean-компоненту Spring в bean-компоненте и странице JSF.
Стоит отметить, что, хотя среда выполнения JSF предоставляет подключаемую архитектуру, которая позволяет платформе Spring предоставлять компоненты интеграции, аннотации из среды Spring нельзя использовать в контексте JSF и наоборот.
Это означает, что вы не сможете использовать такие аннотации, как @Autowired
или @Component
и т. д ., в управляемом компоненте JSF или использовать аннотацию @ManagedBean
в управляемом компоненте Spring. Однако вы можете использовать аннотацию @Inject
как в управляемом компоненте JSF 2.2+, так и в компоненте Spring (поскольку Spring поддерживает JSR-330).
Исходный код, сопровождающий эту статью, доступен на GitHub .