java WEB-INF 目录中的 JSF 文件,我如何访问它们?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3512234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 02:11:17  来源:igfitidea点击:

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

javamodel-view-controllerjsf-2web-inf

提问by Tim

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 to redirect me to the corresponding JSP, right? (This is also the model 2 pattern iirc).

我想将我的 JSF 2.0 xhtml 文件放在 WEB-INF\jsf 下。那我如何访问它们?我知道 WEB-INF 里面的任何东西都不会暴露在外面,所以我需要一个控制器来将我重定向到相应的 JSP,对吗?(这也是模型 2 模式 iirc)。

Can I achieve this with a parameter inside web.xml/faces-config.xml? I think the FacesServlet is the controller of my webapp so it should serve this purpose?

我可以使用 web.xml/faces-config.xml 中的参数来实现这一点吗?我认为 FacesServlet 是我的 webapp 的控制器,所以它应该用于这个目的?

And another question for understanding the Model 2 Pattern. Does every action have to go first to a servlet which then handles the next possible step? So a simple <a href="anotherPage.html" />is forbidden in this pattern since it doesn't go to the controlling servlet?

另一个理解模型 2 模式的问题。是否每个动作都必须首先进入 servlet,然后由它处理下一个可能的步骤?所以<a href="anotherPage.html" />在这种模式中禁止简单,因为它不去控制 servlet?

回答by BalusC

I want to put my JSF 2.0 xhtml files under WEB-INF\jsf. How do I access them then?

我想将我的 JSF 2.0 xhtml 文件放在 WEB-INF\jsf 下。那我如何访问它们?

You cannot. Files in /WEB-INFfolder are not directly accessible.

你不能。文件/WEB-INF夹中的文件不能直接访问。

There are two options to workaround the problem of JSF source files being public accessible.

有两个选项可以解决 JSF 源文件可公开访问的问题。

  1. Map the FacesServleton *.xhtmlinstead of *.jsf.

  2. Or, restrict direct access on *.xhtmlby a <security-constraint>in web.xml.

    <security-constraint>
        <display-name>Restrict direct access to XHTML files</display-name>
        <web-resource-collection>
            <web-resource-name>XHTML files</web-resource-name>
            <url-pattern>*.xhtml</url-pattern>
        </web-resource-collection>
        <auth-constraint />
    </security-constraint> 
    
  1. 映射FacesServleton*.xhtml而不是*.jsf

  2. 或者,*.xhtml通过<security-constraint>in限制直接访问web.xml

    <security-constraint>
        <display-name>Restrict direct access to XHTML files</display-name>
        <web-resource-collection>
            <web-resource-name>XHTML files</web-resource-name>
            <url-pattern>*.xhtml</url-pattern>
        </web-resource-collection>
        <auth-constraint />
    </security-constraint> 
    

See also:

也可以看看:



And another question for understanding the Model 2 Pattern. Does every action have to go first to a servlet which then handles the next possible step?

另一个理解模型 2 模式的问题。是否每个动作都必须首先进入 servlet,然后由它处理下一个可能的步骤?

The FacesServletalready does that. It's the controller. With JSF you already end up with a simple javabean as model and JSP/Facelets file as view. The FacesServletas being the controller has already taken all the nasty work of request parameter gathering, validation, conversion, model updating and navigation from your hands.

FacesServlet已经做到这一点。是控制器。使用 JSF,您已经以一个简单的 javabean 作为模型和 JSP/Facelets 文件作为视图结束。在FacesServlet作为控制器已经采取了请求参数的采集,验证,转换,模型更新和导航的所有肮脏的工作,从你的手中。

See also:

也可以看看:



So a simple <a href="anotherPage.html" />is forbidden in this pattern since it doesn't go to the controlling servlet?

所以<a href="anotherPage.html" />在这种模式中禁止简单,因为它不去控制 servlet?

No, it's perfectly fine. The controller will kick in whenever needed. If the resource doesn't need a controller (i.e. static resource), then you also don't need to let it pass through some controller.

不,完全没问题。控制器将在需要时启动。如果资源不需要控制器(即静态资源),那么您也不需要让它通过某个控制器。



In the future, please ask multiple questions in separate Stack Overflow questions.

将来,请在单独的 Stack Overflow 问题中提出多个问题。

回答by Oleksandr Tsurika

To access xhtmlpages inside WEB-INF/jsffolder you may do next:

要访问文件夹xhtml内的页面,WEB-INF/jsf您可以执行以下操作:

  1. Move xhtmlpages folder from webapp rootto WEB-INF
  2. Introduce "Dispatcher View" pattern to the project
  3. Map "Front Controller" servlet to urlbased to pages from application
  4. Map Faces Servletto ".xhtml"
  5. Inside "Dispatcher" forward request to page from "WEB-INF/jsf/<name>.xhtml"
  6. Override jsf ViewHandler getActionUrlto exclude "WEB-INF" from generated actionurl(of form, link, button)
  1. xhtmlpages 文件夹从移动webapp rootWEB-INF
  2. 在项目中引入“ Dispatcher View”模式
  3. 将“前端控制器”servlet映射到url基于应用程序的页面
  4. Faces Servlet映射到“ .xhtml
  5. 在“ Dispatcher”中将请求从“ WEB-INF/jsf/<name>.xhtml”转发到页面
  6. 覆盖jsf ViewHandler getActionUrlWEB-INF从生成的actionurl(的form, link, button)中排除“ ”

For example, xhtmlpages are in webapp root folder "jsf". All urlbetween pages are like jsf/<pageName>.xhtml. So we do next:

例如,xhtml页面在 webapp 根文件夹“ jsf”中。url页面之间的所有内容都像jsf/<pageName>.xhtml. 所以我们接下来做:

  1. move <webapp root>/jsfto <webapp root>/WEB-INF/jsf

  2. create FrontControllerservlet:

  1. 移动<webapp root>/jsf<webapp root>/WEB-INF/jsf

  2. 创建FrontControllerservlet:

``

``

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.xmlto urlbased for pages:
  1. 将 Front Controller servlet 映射web.xmlurl基于页面:
<servlet>
    <servlet-name>Front Controller</servlet-name>
    <servlet-class>controllers.FrontController</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Front Controller</servlet-name>
    <url-pattern>/jsf/*</url-pattern>
</servlet-mapping>
<servlet>
    <servlet-name>Front Controller</servlet-name>
    <servlet-class>controllers.FrontController</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Front Controller</servlet-name>
    <url-pattern>/jsf/*</url-pattern>
</servlet-mapping>
  1. map Faces Servletin web.xmlto .xhtml
  1. 地图面临的Servletweb.xml.xhtml
<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
  1. create Dispatcherwhich forwards requestto correct xhtmlpage:
  1. 创建转发到正确页面的调度程序requestxhtml

``

``

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.xhtmlthen Dispatcherwill forward it to myapp/WEB-INF/jsf/home.xhtml. And Faces Servlet will handle ".xhtml" request. But if on a page are used jsfcomponents like h:form, h:link, h:buttonetc which generate actionor urlthen the urlwill be really including "/WEB-INF". So to exclude it we need next step.

因此,如果页面的 url 是/myapp/jsf/home.xhtml那么Dispatcher会将其转发到myapp/WEB-INF/jsf/home.xhtml. 而 Faces Servlet 将处理“ .xhtml”请求。但是,如果在页面上使用了jsf诸如h:form, h:link, h:buttonetc 之类的组件,它们会生成actionurl那么url将真正包含“ /WEB-INF”。所以要排除它,我们需要下一步。

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

    6.1 create subclass of jsf ViewHandlerand override getActionUrl:

  1. /WEB-INFjsf生成的url(对于 jsf 表单、链接、按钮)中排除“ ” 。为了那个原因:

    6.1 创建jsf ViewHandler和覆盖的子类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 jsfto use the specified ViewHandler. In faces-config.xmladd next:

6.2 配置jsf使用指定的ViewHandler. 在faces-config.xml旁边的添加:

   <application>
    ...
        <view-handler>
            controllers.HiddenPageViewHandler
        </view-handler>
   </application>
   <application>
    ...
        <view-handler>
            controllers.HiddenPageViewHandler
        </view-handler>
   </application>