【问题标题】:JSF render template to text/plainJSF 将模板渲染为文本/纯文本
【发布时间】:2016-06-24 02:02:48
【问题描述】:

我有一个(工作的)JSF 应用程序。现在我希望使用 JSF 表达式语言扩展一个 不是 页面资源的文档(假设是纯文本文档)(因为我需要来自我的 bean 的状态,这看起来很“自然”)。但似乎我没有完全了解机制......

为了处理“*.txt”文件(如果 web.xml 中有)

<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)

浏览器页面只是白色的..

编辑二

还有另一个信息:失败并不是真正的不确定性(这会稍微损害我的信仰......)但仍然很奇怪。对于我有同名资源但结尾为“.xhtml”的所有资源,渲染成功。

服务器似乎在内部重定向到“.xhtml”版本,渲染这个内容并以“.txt”版本的名称返回它(忽略后者的内容)。这是怎么回事?

【问题讨论】:

    标签: jsf text-files infinite-loop myfaces servlet-mapping


    【解决方案1】:

    问题是:以这种方式使用模板是“最佳实践”还是“意外的副作用”(并且不应该真正起作用)?

    它不应该真的起作用。 JSF 作为基于 HTML 表单的 MVC 框架首先不支持 text/plain 内容,而仅支持基于 HTML 的内容,例如 text/html。在 Mojarra 而不是 MyFaces 上尝试您的用例时(在将 plain.txt 重命名为 plain.xhtml 后,请参见下文),我得到以下异常:

    java.lang.IllegalArgumentException:无法识别的内容类型。

    关于视图解析,从技术上讲,您应该将您的 plain.txt 文件命名为 plain.xhtml,并且只将 *.txt URL 模式添加到 FacesServlet。 FacesServlet 即在将 URL 模式中的任何文件扩展名重新映射到默认为 .xhtml 的上下文参数 javax.faces.DEFAULT_SUFFIX 后定位物理视图。当物理文件不存在时,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 表达式 #{},因为 JSP 不支持这一点。

    最简单的方法是将 servlet 名称更改为 Tomcat 自己的 JSP servlet 之一:jsp(&lt;servlet&gt; 条目不是必需的,因为 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 容器都具有相同的“事实上”名称)使用普通的 vanilla servlet甚至可能是您想到的任务的 JAX-RS (RESTful) 资源。将其映射到所需的/plain.txt 的 URL 模式,让它准备所需的模型,最后转发到“真实的”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} 的形式提供。

    另见:

    【讨论】:

    • 一如既往的合理、深入和清晰的分析。感谢您和您在本网站所做的宝贵贡献。
    • 澄清一下:映射到扩展名 .txt 是请求的 hack 的一部分。在现实世界中,我们谈论的是动态 .jnlp,并且以不那么明显的方式,不同的平台、浏览器和安全设置启动此文件,“下载”时正确的扩展名很重要。如果将这种快速而肮脏的“挤压”到 JSF 中是不正确的,我将恢复为干净的 JaxRS 解决方案。如果我无论如何都要编码,也许基于另一个模板引擎(freemarker)......
    • 我认为普通的 Servlet(+JSP) 最适合这项工作,因为 JAX-RS 暗示了一个“Web 服务”API,它以 XML/JSON/CSV/etc 的形式返回一个或多个实体,而不是文件上的“文件资源”API,您只需要访问 EL 上下文。
    • 我会考虑这个...这是一个暮光之城,像 PDF 这样的复杂文档很可能会使用服务来提供。那么为什么不是一个“简单”的文档,因为它不是 webapp 本身的控制流的一部分,而是一个松散相关过程中的技术工件。
    • 我可以想象在基于字符的内容(HTML/CSS/JS/TXT/等)中需要 EL 上下文,但是 PDF?也许这有帮助:stackoverflow.com/q/9391838 和 stackoverflow.com/q/13015410
    【解决方案2】:

    我不太确定那里发生了什么,但我是这样做的...

    保留您已有的 web.xml 文件。

    像plain.xhtml这样创建xhtm文件...

    <ui:composition
        xmlns:ui="http://java.sun.com/jsf/facelets">
        hi #{request.contextPath}/
    </ui:composition>
    

    现在转到 .../plain.txt

    应该没问题

    【讨论】:

    • 这会产生错误的内容类型标头作为响应。 OP 明确想要text/plain。
    • 你可以监听 preRenderView 事件,比如... 然后 FacesContext fc = FacesContext.getCurrentInstance(); ExternalContext ec = fc.getExternalContext(); Map 参数 = ec.getRequestParameterMap(); ec.setResponseContentType("text/plain"); ec.getResponseOutputWriter().write("一些文本内容"); //或从文件中读取... String y = ec.getRealPath(((HttpServletRequest) ec.getRequest()).getRequestUrl()); fc.responseComplete();但我想有很多工作
    猜你喜欢
    • 2011-11-02
    • 2016-07-05
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 2015-09-21
    • 2018-03-18
    • 1970-01-01
    • 2022-10-02
    相关资源
    最近更新 更多