我几天来一直在努力解决这个问题,将带有独立tomcat服务器的旧Spring迁移到带有嵌入式tomcat服务器的SpringBoot(1.5.22.RELEASE),并且不确定我到底做错了什么,因为我仍然不能让它启动。
这就是 web.xml 的样子(位于 src/main/webapp/WEB-INF):
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>facelets.REFRESH_PERIOD</param-name>
<param-value>1</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.validateXml</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>facelets.SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/facelets/custom.taglib.xml</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.preferXHTML</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/META-INF/spring/root-context.xml
</param-value>
</context-param>
<context-param>
<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
<param-value>com.sun.facelets.FaceletViewHandler</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>blueSky</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.CONTROL_SKINNING</param-name>
<param-value>enable</param-value>
</context-param> <context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>1000</param-value>
</context-param>
<filter>
<filter-name>richfaces</filter-name>
<display-name>RichFaces Filter</display-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>richfaces</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<filter>
<filter-name>openEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/META-INF/spring/root-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>MyService.xhtml</welcome-file>
</welcome-file-list> </web-app>
经过大量谷歌搜索后,我最终决定实现 ServletContextInitializer:
@Configuration
public class WebConfiguration implements ServletContextInitializer {
private static final String FACES_SERVLET = "Faces Servlet";
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
TomcatContextCustomizer contextCustomizer = context -> context.addWelcomeFile("/MyService.xhtml");
factory.addContextCustomizers(contextCustomizer);
return factory;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
// Parameters
servletContext.setInitParameter("javax.faces.STATE_SAVING_METHOD", "client");
servletContext.setInitParameter("facelets.REFRESH_PERIOD", "1");
servletContext.setInitParameter("com.sun.faces.validateXml", "true");
servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX", ".xhtml");
servletContext.setInitParameter("facelets.DEVELOPMENT", "true");
servletContext.setInitParameter("facelets.SKIP_COMMENTS", "true");
servletContext.setInitParameter("facelets.LIBRARIES", "/WEB-INF/facelets/custom.taglib.xml");
servletContext.setInitParameter("com.sun.faces.preferXHTML", "true");
servletContext.setInitParameter("com.sun.faces.expressionFactory", "com.sun.el.ExpressionFactoryImpl");
servletContext.setInitParameter("org.ajax4jsf.VIEW_HANDLERS", "com.sun.facelets.FaceletViewHandler");
servletContext.setInitParameter("org.richfaces.SKIN", "blueSky");
servletContext.setInitParameter("org.richfaces.CONTROL_SKINNING", "enable");
servletContext.setInitParameter("log4jRefreshInterval", "1000");
// Filters
FilterRegistration.Dynamic richfacesFilter = servletContext.addFilter("richfaces", Filter.class);
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE);
richfacesFilter.addMappingForServletNames(dispatcherTypes, true, FACES_SERVLET);
FilterRegistration.Dynamic openEntityManagerInViewFilter = servletContext.addFilter("openEntityManagerInViewFilter", OpenEntityManagerInViewFilter.class);
openEntityManagerInViewFilter.addMappingForUrlPatterns(null, true, "/*");
// Listeners
servletContext.addListener(new ContextLoaderListener(rootContext));
servletContext.addListener(new RequestContextListener());
servletContext.addListener(new Log4jConfigListener());
// Servlet
ServletRegistration.Dynamic restServlet = servletContext.addServlet("rest", new DispatcherServlet(rootContext));
restServlet.setLoadOnStartup(1);
restServlet.addMapping("/rest/*");
ServletRegistration.Dynamic dispatcherServlet = servletContext.addServlet("dispatcherServlet", new DispatcherServlet(rootContext));
dispatcherServlet.setLoadOnStartup(1);
dispatcherServlet.setInitParameter("contextAttribute", "org.springframework.web.context.WebApplicationContext.ROOT");
dispatcherServlet.addMapping("/");
ServletRegistration.Dynamic facesServlet = servletContext.addServlet(FACES_SERVLET, new FacesServlet());
facesServlet.setLoadOnStartup(1);
facesServlet.addMapping("*.xhtml", "*.html", "/faces/*", "*.faces");
}
}
现在我的问题,首先是侦听器,因为在启动过程中会抛出以下错误:
ERROR --- [ost-startStop-1] o.a.c.c.C.[.[.[/].log:182 - Exception sending context initialized event to listener instance of class [org.springframework.web.context.ContextLoaderListener]
java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:296)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4697)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5165)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1412)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1402)
ERROR --- [ost-startStop-1] o.a.c.c.C.[.[.[/].log:182 - Exception sending context initialized event to listener instance of class [org.springframework.web.util.Log4jConfigListener]
java.lang.IllegalStateException: Cannot set web app root system property when WAR file is not expanded
at org.springframework.web.util.WebUtils.setWebAppRootSystemProperty(WebUtils.java:156)
at org.springframework.web.util.Log4jWebConfigurer.initLogging(Log4jWebConfigurer.java:119)
at org.springframework.web.util.Log4jConfigListener.contextInitialized(Log4jConfigListener.java:49)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4697)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5165)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1412)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1402)
ERROR --- [ost-startStop-1] o.a.c.c.StandardContext.log:180 - One or more listeners failed to start. Full details will be found in the appropriate container log file
ERROR --- [ost-startStop-1] o.a.c.c.StandardContext.log:180 - Context [] startup failed due to previous errors
INFO --- [ost-startStop-1] o.a.c.c.C.[.[.[/].log:180 - Shutting down log4j
ERROR --- [ost-startStop-1] o.a.c.c.C.[.[.[/].log:182 - Exception sending context destroyed event to listener instance of class [org.springframework.web.util.Log4jConfigListener]
java.lang.NoClassDefFoundError: org/apache/log4j/LogManager
at org.springframework.util.Log4jConfigurer.shutdownLogging(Log4jConfigurer.java:123)
at org.springframework.web.util.Log4jWebConfigurer.shutdownLogging(Log4jWebConfigurer.java:172)
at org.springframework.web.util.Log4jConfigListener.contextDestroyed(Log4jConfigListener.java:54)
at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4744)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5403)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1412)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1402)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.LogManager
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:94)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
我认为SpringBoot已经运行了一个ContextLoaderListener,所以我删除了它,并且在阅读了这里的问题后还删除了Log4jConfigListener:严重:异常org.springframework.web.util.Log4jConfigListener
现在它进一步启动,但卡在此处:
ERROR --- [ main] o.a.c.c.C.[.[.[/].log:182 - StandardWrapper.Throwable
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239)
at javax.faces.webapp.FacesServlet.init(FacesServlet.java:164)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1132)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:976)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4885)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedContext.deferredLoadOnStartup(TomcatEmbeddedContext.java:77)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.performDeferredLoadOnStartup(TomcatEmbeddedServletContainer.java:279)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.start(TomcatEmbeddedServletContainer.java:206)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.startEmbeddedServletContainer(EmbeddedWebApplicationContext.java:289)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:145)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:123)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:666)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:353)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:300)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1082)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1071)
at com.foo.Application.main(Application.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)
at org.springframework.boot.loader.WarLauncher.main(WarLauncher.java:59)
ERROR --- [ main] o.a.c.c.C.[.[.[/].log:182 - Servlet [Faces Servlet] in web application [] threw load() exception
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239)
at javax.faces.webapp.FacesServlet.init(FacesServlet.java:164)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1132)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:976)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4885)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedContext.deferredLoadOnStartup(TomcatEmbeddedContext.java:77)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.performDeferredLoadOnStartup(TomcatEmbeddedServletContainer.java:279)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.start(TomcatEmbeddedServletContainer.java:206)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.startEmbeddedServletContainer(EmbeddedWebApplicationContext.java:289)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:145)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:123)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:666)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:353)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:300)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1082)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1071)
at com.foo.Application.main(Application.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)
at org.springframework.boot.loader.WarLauncher.main(WarLauncher.java:59)
不记得在哪里找到它,但我看到一条建议,添加 com.sun.faces.config.ConfigureListener 作为监听器可以解决它。这足以让应用程序启动而不会出现任何错误,但是在尝试访问 Web-ui 时,我现在遇到了过滤器问题:
ERROR --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].log:182 - StandardWrapper.Throwable
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239)
at javax.faces.webapp.FacesServlet.init(FacesServlet.java:164)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1132)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:779)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:134)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
ERROR --- [nio-8080-exec-3] o.a.c.c.C.[.[.[.[Faces Servlet].log:182 - Allocate exception for servlet [Faces Servlet]
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:725)
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:239)
at javax.faces.webapp.FacesServlet.init(FacesServlet.java:164)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1132)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:779)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:134)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
尝试在没有过滤器的情况下运行,只是为了看看它是否可以启动,如果我可以解决它们,我最终遇到了这个错误,我目前所处的位置:
ERROR --- [nio-8080-exec-1] f.viewhandler.handleRenderException:667 - Error Rendering View[/login.xhtml]
javax.faces.FacesException: Resources framework is not initialised, check web.xml for Filter configuration
at org.ajax4jsf.resource.ResourceBuilderImpl.getWebXml(ResourceBuilderImpl.java:118)
at org.ajax4jsf.resource.ResourceBuilderImpl.getUri(ResourceBuilderImpl.java:325)
at org.ajax4jsf.resource.InternetResourceBase.getUri(InternetResourceBase.java:218)
at org.richfaces.renderkit.html.MenuItemRendererBase.initializeResources(MenuItemRendererBase.java:188)
at org.richfaces.renderkit.html.MenuItemRenderer.doEncodeEnd(MenuItemRenderer.java:191)
at org.richfaces.renderkit.html.MenuItemRenderer.doEncodeEnd(MenuItemRenderer.java:319)
at org.ajax4jsf.renderkit.RendererBase.encodeEnd(RendererBase.java:134)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:861)
at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:281)
at org.richfaces.renderkit.html.AbstractMenuRenderer.encodeItems(AbstractMenuRenderer.java:279)
at org.richfaces.renderkit.html.AbstractMenuRenderer.processLayer(AbstractMenuRenderer.java:246)
at org.richfaces.renderkit.html.AbstractMenuRenderer.encodeChildren(AbstractMenuRenderer.java:219)
at org.richfaces.renderkit.html.DropDownMenuRendererBase.encodeChildren(DropDownMenuRendererBase.java:62)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:277)
at org.richfaces.renderkit.html.ToolBarGroupRenderer.renderChild(ToolBarGroupRenderer.java:74)
at org.richfaces.renderkit.html.ToolBarGroupRenderer.encodeChildren(ToolBarGroupRenderer.java:56)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:277)
at org.richfaces.renderkit.html.ToolBarRendererBase.encodeChildren(ToolBarRendererBase.java:103)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:930)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:933)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:933)
at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:578)
at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100)
at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
这似乎几乎可以工作,因为我可以看到很多库正在加载,并且页面确实尝试渲染,但它到底缺少什么我不知道。
注意到 richface 包中的 WebXml.java 正在表面下执行,这似乎需要 web.xml 来从中读取属性。找不到它的任何替换类,所以我将 faces 组件留在了 web.xml 中:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!-- TODO - Not used by SpringBoot! But needed for richface 3.x with faces components for WebXml.java to set properties correctly. Bump to higher version then remove web.xml-->
<filter>
<filter-name>richfaces</filter-name>
<display-name>RichFaces Filter</display-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>richfaces</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
</web-app>
但还将以下内容迁移(并在启动时删除不必要的组件)到 WebConfiguration:
public class WebConfiguration implements ServletContextInitializer {
private static final String FACES_SERVLET = "Faces Servlet";
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
TomcatContextCustomizer contextCustomizer = context -> context.addWelcomeFile("/MyService.xhtml");
factory.addContextCustomizers(contextCustomizer);
return factory;
}
@Override
public void onStartup(ServletContext servletContext) {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
// Parameters
servletContext.setInitParameter("javax.faces.STATE_SAVING_METHOD", "client");
servletContext.setInitParameter("facelets.REFRESH_PERIOD", "1");
servletContext.setInitParameter("com.sun.faces.validateXml", "true");
servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX", ".xhtml");
servletContext.setInitParameter("facelets.DEVELOPMENT", "true");
servletContext.setInitParameter("facelets.SKIP_COMMENTS", "true");
servletContext.setInitParameter("facelets.LIBRARIES", "/WEB-INF/facelets/custom.taglib.xml");
servletContext.setInitParameter("com.sun.faces.preferXHTML", "true");
servletContext.setInitParameter("com.sun.faces.expressionFactory", "com.sun.el.ExpressionFactoryImpl");
servletContext.setInitParameter("org.ajax4jsf.VIEW_HANDLERS", "com.sun.facelets.FaceletViewHandler");
servletContext.setInitParameter("org.richfaces.SKIN", "blueSky");
servletContext.setInitParameter("org.richfaces.CONTROL_SKINNING", "enable");
servletContext.setInitParameter("log4jRefreshInterval", "1000");
// Filters
servletContext
.addFilter("richfaces", new Filter())
.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, FACES_SERVLET);
servletContext
.addFilter("openEntityManagerInViewFilter", new OpenEntityManagerInViewFilter())
.addMappingForUrlPatterns(null, false, "/*");
// Listeners
servletContext.addListener(new RequestContextListener());
servletContext.addListener(new ConfigureListener());
// Servlets
ServletRegistration.Dynamic restServlet = servletContext.addServlet("rest", new DispatcherServlet(rootContext));
restServlet.setLoadOnStartup(1);
restServlet.addMapping("/rest/*");
ServletRegistration.Dynamic dispatcherServlet = servletContext.addServlet("dispatcherServlet", new DispatcherServlet(rootContext));
dispatcherServlet.setLoadOnStartup(1);
dispatcherServlet.setInitParameter("contextAttribute", "org.springframework.web.context.WebApplicationContext.ROOT");
dispatcherServlet.addMapping("/");
ServletRegistration.Dynamic facesServlet = servletContext.addServlet(FACES_SERVLET, new FacesServlet());
facesServlet.setLoadOnStartup(1);
facesServlet.addMapping("*.xhtml", "*.html", "/faces/*", "*.faces");
}
}
如果我将 richface 升级到 4.x 甚至 5.x,也许可以完全不需要 web.xml,但目前没有时间进行测试。