我有一个(工作)JSF应用程序。现在我想要一个不的页面资源文档(比如一个纯文本文档),使用JSF表达式语言进行扩展(因为我需要从我的bean中获取状态,这似乎是“自然的”)。但似乎我没有完全掌握机制......
如果有web.xml
,则处理“* .txt”文件<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>*.txt</url-pattern>
</servlet-mapping>
我添加了一个“plain.txt”资源
<f:view contentType="text/plain" xmlns:f="http://java.sun.com/jsf/core" >
hi #{request.contextPath}/
</f:view>
请求
http://myServer/myApp/plain.txt
使用myfaces 2.1.10在服务器上无限循环失败。将资源重命名为“plain.xhtml”并请求它正常工作。
更新到myfaces 2.1.17(同样在2.2.9)后,服务“plain.txt”也有效!
问题是:这样使用模板“最佳实践”或“意外副作用”(并且不应该真正起作用)?有没有更好的方法来实现这样的模板化任务?
修改
经过多次尝试后,似乎更奇怪了。服务扩展内容似乎随机失败(2.1.17和2.2.9)。重新启动后,我在服务器端获取一个资源“res1.txt”的“循环”,但不是资源“res2.txt”的完全副本。还发生了“res1.txt”成功呈现的问题。也许服务器跟踪可以提供一些提示:
首先,有一个很长的“递归”
Mär 09, 2016 5:06:20 PM org.apache.catalina.core.ApplicationDispatcher invoke
SCHWERWIEGEND: Servlet.service() for servlet Faces Servlet threw exception
java.lang.NullPointerException
at org.apache.myfaces.shared.context.flash.FlashImpl.isKeepMessages(FlashImpl.java:388)
at org.apache.myfaces.shared.context.flash.FlashImpl._saveMessages(FlashImpl.java:668)
at org.apache.myfaces.shared.context.flash.FlashImpl.doPostPhaseActions(FlashImpl.java:269)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:254)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:369)
at org.apache.myfaces.view.jsp.JspViewDeclarationLanguage.buildView(JspViewDeclarationLanguage.java:99)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:78)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:369)
at org.apache.myfaces.view.jsp.JspViewDeclarationLanguage.buildView(JspViewDeclarationLanguage.java:99)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:78)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:369)
at org.apache.myfaces.view.jsp.JspViewDeclarationLanguage.buildView(JspViewDeclarationLanguage.java:99)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:78)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:369)
at org.apache.myfaces.view.jsp.JspViewDeclarationLanguage.buildView(JspViewDeclarationLanguage.java:99)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:78)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:369)
at org.apache.myfaces.view.jsp.JspViewDeclarationLanguage.buildView(JspViewDeclarationLanguage.java:99)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:78)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:369)
at org.apache.myfaces.view.jsp.JspViewDeclarationLanguage.buildView(JspViewDeclarationLanguage.java:99)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:78)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:369)
at org.apache.myfaces.view.jsp.JspViewDeclarationLanguage.buildView(JspViewDeclarationLanguage.java:99)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:78)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
at org.apache.myfaces.context.servlet.ServletExternalContextImpl.dispatch(ServletExternalContextImpl.java:369)
at org.apache.myfaces.view.jsp.JspViewDeclarationLanguage.buildView(JspViewDeclarationLanguage.java:99)
at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:78)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
每次重复此跟踪并缩短,直到最终结束:
Mär 09, 2016 5:06:20 PM org.apache.catalina.core.StandardWrapperValve invoke
SCHWERWIEGEND: Servlet.service() for servlet [Faces Servlet] in context with path [/cloudsuite-snippets] threw exception
java.lang.NullPointerException
at org.apache.myfaces.shared.context.flash.FlashImpl.isKeepMessages(FlashImpl.java:388)
at org.apache.myfaces.shared.context.flash.FlashImpl._saveMessages(FlashImpl.java:668)
at org.apache.myfaces.shared.context.flash.FlashImpl.doPostPhaseActions(FlashImpl.java:269)
at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:254)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
浏览器页面只是白色..
编辑II
另一个信息:失败并不是真正的不确定性(这会使我的信仰受到一点损害......)但仍然很奇怪。对于我拥有相同名称的资源但结尾为“.xhtml”的所有资源,渲染成功。
服务器似乎在内部重定向到“.xhtml”版本,呈现此内容并将其返回为“.txt”版本的名称(忽略后者的内容)。这是怎么回事?
答案 0 :(得分:2)
问题是:以这种方式使用模板&#34;最佳实践&#34;或&#34;偶然的副作用&#34; (并且不应该真的有效)?
它应该不起作用。 JSF作为基于HTML表单的MVC框架首先不支持text/plain
内容,而只支持基于HTML的内容,例如text/html
。在Mojarra而不是MyFaces上尝试使用案例时(在将plain.txt
重命名为plain.xhtml
之后,请参阅后面的内容),我将获得以下异常:
java.lang.IllegalArgumentException:无法识别的内容类型。
至于查看解析,从技术上讲,您应该将plain.txt
文件命名为plain.xhtml
,并且只将*.txt
网址格式添加到FacesServlet
。 FacesServlet
即在以URL模式重新映射任何文件扩展名后,根据javax.faces.DEFAULT_SUFFIX
上下文参数(默认为.xhtml
)查找物理视图。当物理文件不存在时,JSF将从Facelets视图回退到JSP视图(由堆栈跟踪中存在JspViewDeclarationLanguage
确认)但由于plain.jsp
也不存在且URL不存在仍然匹配FacesServlet
映射,这反过来在无限循环中运行,以寻找和渲染物理资源。
有关JSF视图解析的内部工作原理的详细解释,另请参阅JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why?关于dispatch()
上的无限循环,这在技术上是JSF中的一个错误,因为它应该真的返回改为404。
有没有更好的方法来实现这样的模板化任务?
如果唯一目的是评估EL表达式,那么最好使用JSP servlet而不是JSF servlet,并且只使用只读EL表达式${}
而不是可写EL表达式#{}
,因为这不是&#39 ; t支持JSP。
最简单的方法是将servlet名称更改为Tomcat自己的JSP servlet之一:jsp
(不需要<servlet>
条目,因为Tomcat已经在其中定义了它拥有/conf/web.xml
)。
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.txt</url-pattern>
</servlet-mapping>
然后将/plain.txt
更改为JSP视图,如下所示。请注意,${request}
在JSP中不存在,它仅作为${pageContext}
的属性提供。另请参阅our EL wiki page。
<%@page contentType="text/plain" %>
hi ${pageContext.request.contextPath}/
至于解析托管bean,它只是没有发现JSF @ManagedBean
,但它可以发现CDI @Named
。因此,当您install CDI on Tomcat并将感兴趣的托管bean重新编写为CDI托管bean而不是JSF托管bean时,它们将可用。
另一种替代方案需要更多工作,但保证可以跨servlet容器移植(因为jsp
的servlet名称是特定于Tomcat的,尽管几乎所有servlet容器都具有相同的&#34;事实上的名称)正在使用普通的vanilla servlet或甚至是JAX-RS(RESTful)资源来完成您的任务。将其映射到所需的/plain.txt
网址模式,让它准备所需的模型,最后转发到真实的#34; JSP文件the usual way。
@WebServlet("/plain.txt")
public class PlainTxtServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/plain.jsp").forward(request, response);
}
}
并且使用/WEB-INF/plain.jsp
作为物理文件,仍然使用上述JSP语法。请注意,它位于/WEB-INF
内,因为您不希望最终用户能够直接请求/plain.jsp
而不是/plain.txt
。
另外一个优点是,这并不一定需要CDI来管理bean,因为您可以手动管理bean,如下所示:
Bean bean = new Bean();
request.setAttribute("bean", bean);
它将在EL中以${bean}
的形式提供。
答案 1 :(得分:0)
我不太确定那里发生了什么,但这是我做的...
保留您已有的web.xml文件。
创建类似于plain.xhtml的xhtm文件,如此......
<ui:composition
xmlns:ui="http://java.sun.com/jsf/facelets">
hi #{request.contextPath}/
</ui:composition>
现在转到... / plain.txt
它应该可以正常工作