Spring Boot JSF 集成 [英] Spring Boot JSF Integration

查看:71
本文介绍了Spring Boot JSF 集成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

环境:

雄猫 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.

另见:

这篇关于Spring Boot JSF 集成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆