Spring Boot JSF 集成
Posted
技术标签:
【中文标题】Spring Boot JSF 集成【英文标题】:Spring Boot JSF Integration 【发布时间】:2018-02-21 14:03:25 【问题描述】:环境:
雄猫 8
Spring Boot 1.5
JSF 2.2
Apache MyFaces
Spring MVC
代码:
我正在 Servlet 3.0 环境中集成 Spring Boot 和 JSF 2.2。
配置类:
JSFConfig.java - JSF 的配置。
@Configuration
@ComponentScan("com.atul.jsf")
public class JSFConfig
@Bean
public ServletRegistrationBean servletRegistrationBean()
FacesServlet servlet = new FacesServlet();
return new ServletRegistrationBean(servlet, "*.jsf");
Spring Boot 主类:
@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
@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 - 主页
<?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:
<?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
,如
faces-config.xml
我还尝试从 UserBean.java 中删除所有 JSF 特定注解,并仅使用 Spring 特定注解,如下所示 -
@Component
@SessionScoped
public class UserBean implements Serializable
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
@Autowired
private UserServiceImpl userServiceImpl;
但是当我提交表单时,我收到 #userBean)
的目标无法访问错误。这意味着 userBean
对于 Spring 是不可发现的
5)我在这里遗漏了什么吗? 6)我没有使用 Spring Boot 提供的嵌入式 tomcat
【问题讨论】:
【参考方案1】:这就是我让 JSF 使用 Spring Boot 的方式(完整的 sample project at Github, updated with JSF 2.3 and Spring Boot 2):
1.依赖关系
除了标准的 web starter 依赖项之外,您还需要包含标记为已提供的 tomcat 嵌入式 jasper(感谢@Fencer 在here 中的评论)。否则,您将在应用程序启动时遇到异常,因为 JSF 取决于 JSP 处理器(另请参阅我的答案末尾的第一个链接)。
<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 时:
@Bean
public ServletRegistrationBean servletRegistrationBean()
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
new FacesServlet(), "*.xhtml");
servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean;
让你的配置类实现ServletContextAware
,这样你就可以设置你的初始化参数。这里你必须强制 JSF 加载配置:
@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 集成
在 faces-config.xml 中声明 EL resolver。这将成为您的视图文件和托管 bean 属性和方法之间的粘合剂:
<?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)。它应该看起来像这样:
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;
并将其注册到您的配置类中:
@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 Beans。
@Component
@Scope("view")
public class MyBean
//Ready to go!
仍有待实现
我无法让 JSF 特定的注释在 Spring Boot 上下文中工作。所以@FacesValidator
、@FacesConverter
、@FacesComponent
等不能用。尽管如此,还是有机会在 faces-config.xml 中声明它们(参见 xsd),这是老式的方式。
另请参阅:
Spring Boot with JSF; Could not find backup for factory javax.faces.context.FacesContextFactory Porting JSF 2.0’s ViewScope to Spring 3.0 JSP file not rendering in Spring Boot web application【讨论】:
Xtreme Biker 您是否找到了让 JSF 注释工作的方法?也许是 Spring Boot 2.0? 不,但是自从我写了这个答案以来,我还没有挖掘太多。由于是 Spring 在这里管理你的 bean,你可以尝试一些注释生成单例,如 @Component。 @XtremeBiker 真的需要 Jasper 依赖项吗? @John 确实如此。删除它会抛出异常。 该应用程序还依赖于starter-web
。该依赖项已经提供了嵌入式 tomcat。这里的问题与嵌入式 tomcat 在编译时不提供 jasper 功能有关,这似乎是 JSF 所要求的。因此,添加该依赖项可以解决它。另见:***.com/a/25777709/1199132以上是关于Spring Boot JSF 集成的主要内容,如果未能解决你的问题,请参考以下文章
Spring JSF 集成:如何在 JSF 托管 bean 中注入 Spring 组件/服务?
如何在 JSF-Spring 集成应用中启用 CSRF 保护