我正在尝试实现一个“通用”视图,其中显示的内容(部分)取决于URL。 E.g。
如果/somepath/somepage.xhtml
指向非现有文件,而不是直接转到404错误,我想尝试使用通用视图{{1}从数据库中检索/somepath/somepage.xhtml
的内容我有类似的东西:
/genericview.xhtml
,如果由支持bean找到,将从<h:outputText value="#{genericViewBean.content_lg}"
escape="false" />
表输出数据库条目的内容,具体取决于最初请求的viewId:
tgenericcontent
如果在该表中未找到视图内容,则将返回标准404错误。
我最接近克隆 webpath | content
/somepath/somepage.xhtml | <p>This is a test</p>
/someotherpath/someotherpage.xhtml | <p>A different test</p>
只更改文件路径(例如,更改为/genericview.xhtml
)。但是这给了我一个每个视图的文件的精确副本,它非常混乱,并且它不允许我仅通过向我的数据库添加条目来创建新的URL。
如何在不克隆/somepath/somepage.xhtml
的情况下获得相同的结果?
(P.S:我读过关于漂亮的脸,但是有没有更简单的解决方案?)
答案 0 :(得分:9)
为此,通常使用servlet filter。 PrettyFaces,UrlRewriteFilter和FacesViews也是这样做的。
您可以通过HttpServletRequest#getRequestURI()
获取请求URI。您可以通过ServletContext#getResource()
检查是否存在Web资源,该资源将在不存在的资源上返回null
。如果资源存在,只需按FilterChain#doFilter()
继续请求,否则通过RequestDispatcher#forward()
将请求转发到通用视图。
总而言之,这就是过滤器的样子:
@WebFilter("/*")
public class GenericViewFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String relativeRequestURI = request.getRequestURI().substring(request.getContextPath().length());
boolean resourceExists = request.getServletContext().getResource(relativeRequestURI) != null;
boolean facesResourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER));
if (resourceExists || facesResourceRequest) {
chain.doFilter(request, response);
}
else {
request.getRequestDispatcher("/genericview.xhtml").forward(request, response);
}
}
// ...
}
在/genericview.xhtml
中,原始请求URI可用作RequestDispatcher#FORWARD_REQUEST_URI
键入的请求属性。您可以在与视图关联的支持bean的@PostConstruct
中使用它,以便从数据库中提取正确的内容。
String originalRequestURI = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);
// ...