JSF files inside WEB-INF directory, how do I access them?

后端 未结 2 1123
无人共我
无人共我 2020-11-29 08:42

I want to put my JSF 2.0 xhtml files under WEB-INF\\jsf. How do I access them then? I know that anything inside WEB-INF isn\'t exposed to the outside, so I need a controller

2条回答
  •  Happy的楠姐
    2020-11-29 09:13

    To access xhtml pages inside WEB-INF/jsf folder you may do next:

    1. Move xhtml pages folder from webapp root to WEB-INF
    2. Introduce "Dispatcher View" pattern to the project
    3. Map "Front Controller" servlet to url based to pages from application
    4. Map Faces Servlet to ".xhtml"
    5. Inside "Dispatcher" forward request to page from "WEB-INF/jsf/.xhtml"
    6. Override jsf ViewHandler getActionUrl to exclude "WEB-INF" from generated action url (of form, link, button)

    For example, xhtml pages are in webapp root folder "jsf". All url between pages are like jsf/.xhtml. So we do next:

    1. move /jsf to /WEB-INF/jsf

    2. create FrontController servlet:

    ``

    public class FrontController extends HttpServlet {
    
            @Override
            protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                process(req, resp);
            }
    
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                process(req, resp);
            }    
    
            private void process(HttpServletRequest request, HttpServletResponse response) {
                 Dispatcher dispatcher = Dispatcher.getInstance();
                 dispatcher.dispatch(request, response);
            }
    }
    
    1. map Front Controller servlet in web.xml to url based for pages:
    
        Front Controller
        controllers.FrontController
    
    
        Front Controller
        /jsf/*
    
    
    1. map Faces Servlet in web.xml to .xhtml
    
        Faces Servlet
        javax.faces.webapp.FacesServlet
        1
    
    
        Faces Servlet
        *.xhtml
    
    
    1. create Dispatcher which forwards request to correct xhtml page:

    ``

    public class Dispatcher {
    
        public void dispatch(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String pageBase = "/WEB-INF/jsf/";
            String pagePath = null;
            String errorPage = "/WEB-INF/jsf/error.xthml";
    
            //here could be complicated logic to analyze if the page should be visible for security reasons, authorisation etc, business logic            
           //requested page could be taken from parsing requested URI
            //pageName = findPageNameFromURI(request.getRequestURI());
    
            pagePath = pageBase + pageName;
    
            //if page should not be visible
            pagePath = errorPage;            
    
            //forward to page inside WEB-INF/jsf
            request.getServletContext().getRequestDispatcher(pagePath).
                                       forward(request, response);        
        }   
    
    }
    

    So if url for page was /myapp/jsf/home.xhtml then Dispatcher will forward it to myapp/WEB-INF/jsf/home.xhtml. And Faces Servlet will handle ".xhtml" request. But if on a page are used jsf components like h:form, h:link, h:button etc which generate action or url then the url will be really including "/WEB-INF". So to exclude it we need next step.

    1. Exclude "/WEB-INF" from jsf generated url (for jsf form, link, button). For that:

      6.1 create subclass of jsf ViewHandler and override getActionUrl:

    ``

    public class HiddenPageViewHandler extends ViewHandlerWrapper {
    
        private static final String WEB_INF = "/WEB-INF";
    
        private ViewHandler parent;
    
        public HiddenPageViewHandler(ViewHandler parent) {
            this.parent = parent;
        }
    
        @Override
        public String getActionURL(FacesContext context, String viewId) {
            String actionUrl = super.getActionURL(context, viewId);
    
            if (actionUrl != null && actionUrl.contains(WEB_INF)) {
                actionUrl = actionUrl.replace(WEB_INF, "");
            }        
    
            return actionUrl;
        }
    
        @Override
        public ViewHandler getWrapped() {
            return parent;
        }
    
    }
    

    6.2 configure jsf to use the specified ViewHandler. In faces-config.xml add next:

       
        ...
            
                controllers.HiddenPageViewHandler
            
       
    

提交回复
热议问题