Customize FacesServlet to get rid of .xhtml

2019-01-11 08:05发布

I have Login.xhtml and Home.xhtml. I configured the url pattern in web.xml as follows

<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>

When I run the whole project, the login page URL is like this http://localhost:8080/fran/Login.xhtml , here fran is my project name..

However, I would like it to be http://localhost:8080/fran/Login/ instead of http://localhost:8080/fran/Login.xhtml.

How can I achieve this? Is it possible to customize the <url-pattern> for every page to get rid of the .xhtml extension?


Solved

As BalusC mentioned below in comment... OmniFaces FacesViews is awesome. Here are the steps I did:

  • Place omnifaces-1.5.jar in /WEB-INF/lib folder.
  • Add below code to web.xml:

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

That's it in configuration. It's working perfectly well.

2条回答
劫难
2楼-- · 2019-01-11 08:22

Take a look at prettyfaces: Pretty URLs for JavaServer Faces ,

Look at the 2. Create pretty-config.xml example in the main page

And take a look at the Chapter 2. Get Started

查看更多
劫难
3楼-- · 2019-01-11 08:25

If your sole reason is to get rid of the .xhtml extension, then there are various ways depending on the JSF version you're using.

JSF 2.3+

JSF 2.3 offers a new API to collect all views: the ViewHandler#getViews(). Combine this with ServletRegistration#addMapping() in a ServletContextListener as below.

@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))
        );
    }
}

Effectively, this is an oneliner. Source: The Definitive Guide to JSF.

JSF 2.2-

Use OmniFaces FacesViews. It offers a zero-configuration way to achieve that by placing the view files in /WEB-INF/faces-views/ folder. Otherwise, if you intend to not modify your project structure and want to keep your view files at the usual place and still benefit of extensionless URLs, then it's a matter of adding the following context parameter:

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

In case you don't want to use OmniFaces, but rather want to homegrow your own, just look at source code of OmniFaces. It's open source under Apache 2.0 License. It's only not an oneliner.

查看更多
登录 后发表回答