Spring Boot JSF 集成 [英] Spring Boot JSF Integration
问题描述
环境:
雄猫 8
Spring Boot 1.5
Spring Boot 1.5
JSF 2.2
Apache MyFaces
Apache MyFaces
Spring MVC
Spring MVC
代码:
我正在 Servlet 3.0 环境中集成 Spring Boot 和 JSF 2.2.
I am integrating Spring Boot and JSF 2.2 in Servlet 3.0 environment.
配置类:
JSFConfig.java - JSF 的配置.
JSFConfig.java - Config for JSF.
@Configuration
@ComponentScan({"com.atul.jsf"})
public class JSFConfig {
@Bean
public ServletRegistrationBean servletRegistrationBean() {
FacesServlet servlet = new FacesServlet();
return new ServletRegistrationBean(servlet, "*.jsf");
}
}
Spring Boot 主类:
Spring Boot Main Class :
@SpringBootApplication
@Import({ // @formatter:off
JPAConfig.class,
ServiceConfig.class, // this contains UserServiceImpl.java class.
WebConfig.class,
JSFConfig.class,
})
public class SpringbootJpaApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(SpringbootJpaApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringbootJpaApplication.class);
}
}
托管 Bean:
UserBean.java - JSF 的托管 Bean
UserBean.java - Managed Bean for JSF
@ManagedBean
@SessionScoped
public class UserBean implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
@ManagedProperty(value="#{userServiceImpl}")
private UserServiceImpl userServiceImpl;
public void addUser(){
System.out.println("User Gets added "+this.name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public UserServiceImpl getUserServiceImpl() {
return userServiceImpl;
}
public void setUserServiceImpl(UserServiceImpl userServiceImpl) {
this.userServiceImpl = userServiceImpl;
}
}
小面:
home.xhtml - 主页
home.xhtml - home page
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>JSF 2.0 Hello World</title>
</h:head>
<h:body>
<h2>JSF 2.0 Hello World Example - hello.xhtml</h2>
<h:form>
<h:inputText value="#{userBean.name}"></h:inputText>
<h:commandButton value="Submit" action="#{userBean.addUser}"></h:commandButton>
</h:form>
</h:body>
</html>
faces-config.xml :
faces-config.xml :
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
<lifecycle>
<phase-listener>org.springframework.web.jsf.DelegatingPhaseListenerMulticaster</phase-listener>
</lifecycle>
</faces-config>
问题:
1) 当我在 home.xhtml 提交表单时, userBean.addUser
被调用.2)userBean.name
使用用户输入的值进行设置.3) 但是 userServiceImpl
为 NULL.4) 这是否意味着 Spring 和 JSF 没有集成?我还注册了 SpringBeanFacesELResolver
如
1)when I submit form in home.xhtml , userBean.addUser
gets called.
2)userBean.name
gets set with values entered by user.
3)But userServiceImpl
is NULL.
4)Does that mean that Spring and JSF is not getting integrated ? I have also registered SpringBeanFacesELResolver
as mentioned in
faces-config.xml
我还尝试从 UserBean.java 中删除所有 JSF 特定的注释,并仅使用 Spring 特定的注释,如下所示 -
I also tried removing all JSF specific annotations from UserBean.java and used only Spring specific annotations like below -
@Component
@SessionScoped
public class UserBean implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
@Autowired
private UserServiceImpl userServiceImpl;
}
但是当我提交表单时,我收到 #{userBean)
的目标无法访问错误.这意味着 userBean
对于 Spring
But when I submit form , I am getting target Unreachable error for #{userBean)
. That means userBean
is not discoverable for Spring
5) 我在这里遗漏了什么吗?6) 我没有使用 Spring Boot 提供的嵌入式 tomcat
5)Am I missing anything here ? 6)I am not using embedded tomcat provided with Spring Boot
推荐答案
这是我让 JSF 使用 Spring Boot 的方式(完整的 Github 示例项目,更新为 JSF 2.3 和 Spring Boot 2):
This is the way I have JSF working with Spring Boot (full sample project at Github, updated with JSF 2.3 and Spring Boot 2):
1.依赖
除了标准的 web starter 依赖项之外,您还需要包含标记为提供的 tomcat 嵌入式 jasper(感谢@Fencer 在 此处).否则,您将在应用程序启动时遇到异常,因为 JSF 取决于 JSP 处理器(另请参阅我的答案末尾的第一个链接).
In addition to the standard web starter dependency, you'll need to include the tomcat embedded jasper marked as provided (thanks @Fencer for commenting in here). Otherwise you'll get an exception at application startup, because of JSF depending on JSP processor (see also the first link at the end of my answer).
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.Servlet 注册
注册 JSF servlet 并将其配置为在启动时加载(不需要 web.xml).如果使用 JSF 2.2,最好使用 *.xhtml
映射,至少在使用 facelets 时:
Register the JSF servlet and configure it to load on startup (no need of web.xml). If working with JSF 2.2, your best is to use *.xhtml
mapping, at least when using facelets:
@Bean
public ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
new FacesServlet(), "*.xhtml");
servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean;
}
让你的配置类实现ServletContextAware
以便您可以设置初始化参数.这里必须强制JSF加载配置:
Make your configuration class implement ServletContextAware
so that you can set your init parameters. Here you must force JSF to load configuration:
@Override
public void setServletContext(ServletContext servletContext) {
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration",
Boolean.TRUE.toString());
servletContext.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", "true");
//More parameters...
}
3.EL 集成
声明 EL 解析器 在faces-config.xml 中.这将成为您的视图文件和托管 bean 属性和方法之间的粘合剂:
Declare the EL resolver in the faces-config.xml. This is going to be the glue between your view files and your managed bean properties and methods:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
</faces-config>
4.视图范围
编写一个自定义 Spring 范围来模拟 JSF 视图范围(请记住,您的 bean 将由 Spring 管理,而不是由 JSF 管理).它应该看起来像这样:
Write a custom Spring scope to emulate the JSF view scope (keep in mind your beans are going to be managed by Spring, not JSF). It should look some way like this:
public class ViewScope implements Scope {
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Map<String, Object> viewMap = FacesContext.getCurrentInstance()
.getViewRoot().getViewMap();
if (viewMap.containsKey(name)) {
return viewMap.get(name);
} else {
Object object = objectFactory.getObject();
viewMap.put(name, object);
return object;
}
}
@Override
public String getConversationId() {
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object remove(String name) {
return FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(name);
}
@Override
public Object resolveContextualObject(String arg0) {
return null;
}
}
并在您的配置类中注册它:
And register it in your configuration class:
@Bean
public static CustomScopeConfigurer viewScope() {
CustomScopeConfigurer configurer = new CustomScopeConfigurer();
configurer.setScopes(
new ImmutableMap.Builder<String, Object>().put("view", new ViewScope()).build());
return configurer;
}
5.准备出发!
现在您可以通过以下方式声明您的托管 bean.请记住使用 @Autowired
(最好在构造函数中)而不是 @ManagedProperty
,因为您正在处理 Spring Bean.
Now you can declare your managed beans the way below. Remember to use @Autowired
(preferably in constructors) instead of @ManagedProperty
, because you're dealing with Spring Beans.
@Component
@Scope("view")
public class MyBean {
//Ready to go!
}
<小时>
仍有待实现
我无法在 Spring Boot 上下文中使用 JSF 特定的注释.所以@FacesValidator
、@FacesConverter
、@FacesComponent
等都不能使用.尽管如此,仍有机会在 faces-config.xml 中声明它们(参见 xsd),老式的方式.
I couldn't get JSF specific annotations work in the Spring Boot context. So @FacesValidator
, @FacesConverter
, @FacesComponent
, and so on can't be used. Still, there's the chance to declare them in faces-config.xml (see the xsd), the old-fashioned way.
另见:
- 带有 JSF 的 Spring Boot;找不到工厂 javax.faces.context.FacesContextFactory 的备份
- 将 JSF 2.0 的 ViewScope 移植到春季 3.0
- 未在 Spring Boot Web 应用程序中呈现的 JSP 文件一个>
这篇关于Spring Boot JSF 集成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!