有没有一种简单的方法可以在 JSF 中实现路由?
Is there a simple way to implement routing in JSF?
我正在尝试实现一个 "generic" 视图,其中显示的(部分)内容取决于 URL。例如
如果 /somepath/somepage.xhtml
指向一个不存在的文件,而不是直接进入 404 错误,我想尝试使用通用视图从数据库中检索 /somepath/somepage.xhtml
的内容,/genericview.xhtml
,我有类似的东西:
<h:outputText value="#{genericViewBean.content_lg}"
escape="false" />
如果被支持 bean 找到,将从 tgenericcontent
table 输出数据库条目的内容,具体取决于最初请求的 viewId:
webpath | content
/somepath/somepage.xhtml | <p>This is a test</p>
/someotherpath/someotherpage.xhtml | <p>A different test</p>
如果在那个 table 中找不到视图内容,那么将返回标准 404 错误。
我最接近的是克隆 /genericview.xhtml
,仅更改文件路径(例如,更改为 /somepath/somepage.xhtml
)。但这让我得到了每个视图的文件的一个精确副本,它非常混乱,并且不允许我通过向我的数据库添加一个条目来创建一个新的 url。
如何在不克隆的情况下获得相同的结果/genericview.xhtml
?
(P.S: 我已经阅读了有关漂亮脸孔的内容,但是没有更简单的解决方案吗?)
为此,通常 servlet filter is being used. PrettyFaces, UrlRewriteFilter and FacesViews 也会这样做。
您可以通过HttpServletRequest#getRequestURI()
. You can check the existence of a web resource by ServletContext#getResource()
which will return null
on non-existent resources. If the resource exists, just continue the request by FilterChain#doFilter()
, else forward the request to the generic view by RequestDispatcher#forward()
获取请求URI。
总而言之,过滤器可能是这样的:
@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);
// ...
我正在尝试实现一个 "generic" 视图,其中显示的(部分)内容取决于 URL。例如
如果 /somepath/somepage.xhtml
指向一个不存在的文件,而不是直接进入 404 错误,我想尝试使用通用视图从数据库中检索 /somepath/somepage.xhtml
的内容,/genericview.xhtml
,我有类似的东西:
<h:outputText value="#{genericViewBean.content_lg}"
escape="false" />
如果被支持 bean 找到,将从 tgenericcontent
table 输出数据库条目的内容,具体取决于最初请求的 viewId:
webpath | content
/somepath/somepage.xhtml | <p>This is a test</p>
/someotherpath/someotherpage.xhtml | <p>A different test</p>
如果在那个 table 中找不到视图内容,那么将返回标准 404 错误。
我最接近的是克隆 /genericview.xhtml
,仅更改文件路径(例如,更改为 /somepath/somepage.xhtml
)。但这让我得到了每个视图的文件的一个精确副本,它非常混乱,并且不允许我通过向我的数据库添加一个条目来创建一个新的 url。
如何在不克隆的情况下获得相同的结果/genericview.xhtml
?
(P.S: 我已经阅读了有关漂亮脸孔的内容,但是没有更简单的解决方案吗?)
为此,通常 servlet filter is being used. PrettyFaces, UrlRewriteFilter and FacesViews 也会这样做。
您可以通过HttpServletRequest#getRequestURI()
. You can check the existence of a web resource by ServletContext#getResource()
which will return null
on non-existent resources. If the resource exists, just continue the request by FilterChain#doFilter()
, else forward the request to the generic view by RequestDispatcher#forward()
获取请求URI。
总而言之,过滤器可能是这样的:
@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);
// ...