복붙노트

[SPRING] 스프링 부트 JSF 통합

SPRING

스프링 부트 JSF 통합

환경 :

톰캣 8

봄 부팅 1.5

JSF 2.2

Apache MyFaces

스프링 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");
        }

}

스프링 부트 메인 클래스 :

@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);
    }
}

관리 빈 :

JSF 용 UserBean.java - Managed 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;
    }
}

Facelets :

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) 스프링과 JSF가 통합되지 않는다는 의미입니까? 앞서 언급 한 것처럼 SpringBeanFacesELResolver도 등록했습니다.

faces-config.xml 

또한 UserBean.java에서 모든 JSF 특정 주석을 제거하고 아래처럼 특정 스프링 주석 만 사용했습니다.

 @Component
    @SessionScoped 
    public class UserBean implements Serializable{

        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private String name;
        @Autowired
        private UserServiceImpl userServiceImpl;


    }

하지만 양식을 제출할 때 # {userBean}에 대한 도달 할 수없는 오류가 발생합니다. 즉, Spring에서 userBean을 검색 할 수 없다는 의미입니다.

5) 내가 여기서 아무것도 놓치고 있니? 6) 스프링 부트와 함께 제공되는 임베디드 tomcat을 사용하지 않습니다.

해결법

  1. ==============================

    1.이것은 JSF가 Spring Boot로 작업하는 방식입니다 (Github의 전체 샘플 프로젝트, JSF 2.3 및 Spring Boot 2로 업데이트 됨).

    이것은 JSF가 Spring Boot로 작업하는 방식입니다 (Github의 전체 샘플 프로젝트, JSF 2.3 및 Spring Boot 2로 업데이트 됨).

    1. 종속성

    표준 웹 스타터 종속성 외에도 제공되는 것으로 표시된 Tomcat 내장형 벽옥을 포함시켜야합니다 (여기서 주석을 달아 주시면 감사하겠습니다). 그렇지 않으면 JSP 프로세서에 따라 JSF로 인해 응용 프로그램 시작시 예외가 발생합니다 (내 대답 끝의 첫 번째 링크 참조).

    <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. 서블릿 등록

    JSF 서블릿을 등록하고 시작시로드되도록 구성하십시오 (web.xml 필요 없음). JSF 2.2를 사용하는 경우 적어도 facelet을 사용할 때 * .xhtml 매핑을 사용하는 것이 가장 좋습니다.

    @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. 통합

    faces-config.xml에서 EL 해결 프로그램을 선언하십시오. 이것은 뷰 파일과 관리 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. 전망 범위

    JSF 뷰 범위를 에뮬레이트하기 위해 커스텀 스프링 스코프를 작성한다 (빈이 JSF가 아니라 Spring에 의해 관리 될 것이라는 점을 명심하라). 다음과 같이 보일 것입니다 :

    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을 아래에 선언 할 수 있습니다. Spring Beans를 다루기 때문에 @ManagedProperty 대신 @Autowired (바람직하게는 생성자에서)를 사용하는 것을 잊지 마십시오.

    @Component
    @Scope("view")
    public class MyBean {
    
        //Ready to go!
    
    }
    

    아직 달성하기 위해 대기 중

    스프링 부트 컨텍스트에서 JSF 특정 주석을 사용할 수 없습니다. 따라서 @FacesValidator, @FacesConverter, @FacesComponent 등은 사용할 수 없습니다. 그래도 old-fashioned 방식 인 faces-config.xml (xsd 참조)에서 선언 할 수있는 기회가 있습니다.

    참조 :

  2. from https://stackoverflow.com/questions/46187725/spring-boot-jsf-integration by cc-by-sa and MIT license