包含包含来自流的 JSF 标签/组件的动态内容

问题描述 投票:0回答:2

我正在开发一个应用程序,我想在其中包含来自流的动态 XHTML 内容。为了处理这个问题,我编写了一个标记处理程序扩展,它将动态 XHTML 内容转储到输出组件,如下所示:

UIOutput htmlChild = (UIOutput) ctx.getFacesContext().getApplication().createComponent(UIOutput.COMPONENT_TYPE); htmlChild.setValue(new String(outputStream.toByteArray(), "utf-8"));

这对于没有 JSF 标签的 XHTML 内容效果很好。如果我的动态 XHTML 内容中有 JSF 标记(如

<h:inputText value="#{bean.item}"/>

),那么它们会以纯文本形式打印。我希望它们呈现为输入字段。我怎样才能实现这个目标? 

jsf-2 facelets jsf-2.2 dynamic-content
2个回答
4
投票
本质上,您应该将

<ui:include>

 与自定义 
ResourceHandler
 结合使用,它能够以 
URL
 的方式返回资源。因此,当有 
OutputStream
 时,您确实应该将其写入(临时)文件,以便可以从中获取 
URL

例如

<ui:include src="/dynamic.xhtml" />

public class DynamicResourceHandler extends ResourceHandlerWrapper { private ResourceHandler wrapped; public DynamicResourceHandler(ResourceHandler wrapped) { this.wrapped = wrapped; } @Override public ViewResource createViewResource(FacesContext context, String resourceName) { if (resourceName.equals("/dynamic.xhtml")) { try { File file = File.createTempFile("dynamic-", ".xhtml"); try (Writer writer = new FileWriter(file)) { writer .append("<ui:composition") .append(" xmlns:ui='http://java.sun.com/jsf/facelets'") .append(" xmlns:h='http://java.sun.com/jsf/html'") .append(">") .append("<p>Hello from a dynamic include!</p>") .append("<p>The below should render as a real input field:</p>") .append("<p><h:inputText /></p>") .append("</ui:composition>"); } final URL url = file.toURI().toURL(); return new ViewResource(){ @Override public URL getURL() { return url; } }; } catch (IOException e) { throw new FacesException(e); } } return super.createViewResource(context, resourceName); } @Override public ResourceHandler getWrapped() { return wrapped; } }

(警告:基本启动示例!这会在每个请求上创建一个新的临时文件,您应该自己发明一个重用/缓存系统)

faces-config.xml

中注册如下

<application> <resource-handler>com.example.DynamicResourceHandler</resource-handler> </application>


注意:以上所有内容都是针对 JSF 2.2 的。对于偶然发现此答案的 JSF 2.0/2.1 用户,您应该使用

ResourceResolver

 来代替,此答案中提供了一个示例:
从外部文件系统或数据库获取 Facelets 模板/文件。重要提示:JSF 2.2 中ResourceResolver
已被
弃用,取而代之的是ResourceHandler#createViewResource()


0
投票
我的 JSF 2.2 和自定义 URLStream 处理程序的解决方案

public class DatabaseResourceHandlerWrapper extends ResourceHandlerWrapper { private ResourceHandler wrapped; @Inject UserSessionBean userBeean; public DatabaseResourceHandlerWrapper(ResourceHandler wrapped) { this.wrapped = wrapped; } @Override public Resource createResource(String resourceName, String libraryName) { return super.createResource(resourceName, libraryName); //To change body of generated methods, choose Tools | Templates. } @Override public ViewResource createViewResource(FacesContext context, String resourceName) { if (resourceName.startsWith("/dynamic.xhtml?")) { try { String query = resourceName.substring("/dynamic.xhtml?".length()); Map<String, String> params = splitQuery(query); //do some query to get content String content = "<ui:composition" + " xmlns='http://www.w3.org/1999/xhtml' xmlns:ui='http://java.sun.com/jsf/facelets'" + " xmlns:h='http://java.sun.com/jsf/html'> MY CONTENT" + "</ui:composition>"; final URL url = new URL(null, "string://helloworld", new MyCustomHandler(content)); return new ViewResource() { @Override public URL getURL() { return url; } }; } catch (IOException e) { throw new FacesException(e); } } return super.createViewResource(context, resourceName); } public static Map<String, String> splitQuery(String query) throws UnsupportedEncodingException { Map<String, String> params = new LinkedHashMap<>(); String[] pairs = query.split("&"); for (String pair : pairs) { int idx = pair.indexOf("="); params.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8")); } return params; } @Override public ResourceHandler getWrapped() { return wrapped; } static class MyCustomHandler extends URLStreamHandler { private String content; public MyCustomHandler(String content) { this.content = content; } @Override protected URLConnection openConnection(URL u) throws IOException { return new UserURLConnection(u, content); } private static class UserURLConnection extends URLConnection { private String content; public UserURLConnection(URL url, String content) { super(url); this.content = content; } @Override public void connect() throws IOException { } @Override public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(content.getBytes("UTF-8")); } } } }
    
© www.soinside.com 2019 - 2024. All rights reserved.