【问题标题】:Customize FacesServlet <url-pattern> to get rid of .xhtml extension自定义 FacesServlet <url-pattern> 以摆脱 .xhtml 扩展名
【发布时间】:2013-09-01 17:34:46
【问题描述】:

我有Login.xhtmlHome.xhtml。我在web.xml中配置了url模式如下

<servlet-mapping>
   <servlet-name>Faces Servlet</servlet-name>
   <url-pattern>/faces/*</url-pattern>
</servlet-mapping>

<welcome-file-list>
  <welcome-file>Login.xhtml</welcome-file>
</welcome-file-list>

当我运行整个项目时,登录页面URL是这样的http://localhost:8080/fran/Login.xhtml,这里fran是我的项目名称..

但是,我希望它是 http://localhost:8080/fran/Login/ 而不是 http://localhost:8080/fran/Login.xhtml

我怎样才能做到这一点?是否可以为每个页面自定义&lt;url-pattern&gt; 以摆脱.xhtml 扩展?

【问题讨论】:

  • 看看ocpsoft.org/prettyfaces,看看2。在主页面创建 pretty-config.xml 示例
  • @Daniel ..ya ocpsoft.org/prettyfaces 是一个不错的选择。在pretty faces 中是否需要在web.xml 中配置Pretty filter
  • OmniFaces FacesViews 提供了一种摆脱.xhtml 扩展的零配置方式。它已在 showcase.omnifaces.orgzeef.com 中使用。
  • @BalusC ..感谢您的回答..这很容易配置...并且绘制的文档非常棒..任何人都可以理解...我很高兴使用这个插件...感谢您的建议..

标签: jsf jsf-2 friendly-url


【解决方案1】:

如果您的唯一原因是摆脱 .xhtml 扩展,那么根据您使用的 JSF 版本,有多种方法。

JSF 2.3+

JSF 2.3 提供了一个新的 API 来收集所有视图:ViewHandler#getViews()。将其与ServletRegistration#addMapping() 结合到ServletContextListener 中,如下所示。

@FacesConfig
@WebListener
public class ApplicationConfig implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        addExtensionLessMappings(event.getServletContext(), FacesContext.getCurrentInstance());
    }

    private void addExtensionLessMappings(ServletContext servletContext, FacesContext facesContext) {
        servletContext
            .getServletRegistrations().values().stream()
            .filter(servlet -> servlet.getClassName().equals(FacesServlet.class.getName()))
            .findAny()
            .ifPresent(facesServlet -> facesContext
                .getApplication()
                .getViewHandler()
                .getViews(facesContext, "/", ViewVisitOption.RETURN_AS_MINIMAL_IMPLICIT_OUTCOME)
                .forEach(view -> facesServlet.addMapping(view))
        );
    }
}

实际上,这是一个单线。来源:Arjan Tijms' BlogThe Definitive Guide to JSF

如果您使用 MyFaces 作为 JSF 2.3 实现,则可以仅通过以下 web.xml 上下文参数透明地激活它:

<context-param>
    <param-name>org.apache.myfaces.AUTOMATIC_EXTENSIONLESS_MAPPING</param-name>
    <param-value>true</param-value>
</context-param>

Mojarra 还没有等价物。

JSF 2.2-

使用OmniFaces FacesViews。它通过将视图文件放在/WEB-INF/faces-views/ 文件夹中提供了一种零配置方式来实现这一目标。否则,如果您不打算修改项目结构并希望将视图文件保留在通常的位置并仍然受益于无扩展 URL,那么只需添加以下上下文参数:

<context-param>
    <param-name>org.omnifaces.FACES_VIEWS_SCAN_PATHS</param-name>
    <param-value>/*.xhtml</param-value>
</context-param>

如果您不想使用 OmniFaces,而是想自己开发,只需查看 OmniFaces 的source code。它在 Apache 2.0 许可下开源。它只是不是单线器。

【讨论】:

  • FacesContext.getCurrentInstance() 为我返回 null
【解决方案2】:

看看prettyfaces: Pretty URLs for JavaServer Faces

看看2。在主页面创建 pretty-config.xml 示例

看看Chapter 2. Get Started

【讨论】:

  • ya.. 没错.. 我的问题,是否需要在 web.xml 中配置 Pretty 过滤器 .. 在第 2 步中(如您所述)仅适用于 pretty-config.xmlconfiguration,这部分是只有一个人..?
  • @Daniel 感谢您指出漂亮的面孔——看起来它可以解决我遇到的问题,即使 URL 更加用户友好
【解决方案3】:

只是对先生的一点补充。 @balusc 关于 JSF 2.3 上 MyFaces 的出色回答...(编辑:并不是真正的补充,因为不能补充完整的内容,而只是 tomcat/tomee 用户处理此 tomcat 错误的一种解决方法)。

使用 MyFaces 2.3.6,我收到一个关于 servlet 规范和 ServletContextListener 的异常:

java.lang.UnsupportedOperationException: Section 4.4 of the Servlet 3.0 specification does not permit this method to be called from a ServletContextListener that was not defined in web.xml, a web-fragment.xml file nor annotated with @WebListener

在堆栈之后我看到了这一行:

at org.apache.myfaces.webapp.StartupServletContextListener.contextInitialized(StartupServletContextListener.java:103)

将该监听器添加到 web.xml 后一切正常:

<listener>
    <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>

【讨论】:

  • 只有当你使用 Tomcat 而不是普通的 JEE 服务器时才会发生这种情况,这实际上是 Tomcat 本身的一个错误。
  • 令人印象深刻!我使用的是 TomEE 8.0.5。确实。我检查了。 MyFaces 具有正确的网络片段,带有这个精确的侦听器。真的是一个tomcat错误。谢谢你,先生。
猜你喜欢
  • 1970-01-01
  • 2015-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-25
  • 2012-05-14
  • 2015-09-24
相关资源
最近更新 更多