有没有一种简单的方法在JSF中实现路由?

Not*_*aeL 5 jsf url-routing jsf-2 url-redirection

我正在尝试实现一个"通用"视图,其中显示的内容(部分)取决于URL.例如

如果/somepath/somepage.xhtml指向一个非现有文件,而不是直接转到404错误,我想尝试/somepath/somepage.xhtml使用通用视图从数据库中检索内容/genericview.xhtml,我有类似的东西:

<h:outputText value="#{genericViewBean.content_lg}"
                escape="false" />
Run Code Online (Sandbox Code Playgroud)

如果由backing bean找到,它将从tgenericcontent表中输出数据库条目的内容,具体取决于最初请求的viewId:

 webpath                              | content
 /somepath/somepage.xhtml             | <p>This is a test</p>
 /someotherpath/someotherpage.xhtml   | <p>A different test</p>
Run Code Online (Sandbox Code Playgroud)

如果在该表中未找到视图内容,则将返回标准404错误.

我最接近克隆/genericview.xhtml只更改文件路径(例如,到/somepath/somepage.xhtml).但是这给我带来了每个视图的文件的一个精确副本,它非常混乱,并且它不允许我仅通过向数据库添加条目来创建新URL.

如何在没有克隆的情况下获得相同的结果/genericview.xhtml

(PS:我读过关于prettyfaces的内容,但是有没有更简单的解决方案?)

Bal*_*usC 9

为此,通常使用servlet过滤器.PrettyFaces,UrlRewriteFilterFacesViews也是这样做的.

您可以通过获取请求URI HttpServletRequest#getRequestURI().您可以检查是否存在ServletContext#getResource()将返回null不存在的资源的Web 资源.如果资源存在,则只需继续请求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);
        }
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

/genericview.xhtml,原始请求URI可用作键入的请求属性RequestDispatcher#FORWARD_REQUEST_URI.您可以在@PostConstruct与视图关联的辅助bean中使用它,以便从数据库中提取正确的内容.

String originalRequestURI = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);
// ...
Run Code Online (Sandbox Code Playgroud)