WEB-INF 目录中的 JSF 文件,我如何访问它们?
Posted
技术标签:
【中文标题】WEB-INF 目录中的 JSF 文件,我如何访问它们?【英文标题】:JSF files inside WEB-INF directory, how do I access them? 【发布时间】:2011-03-31 13:06:41 【问题描述】:我想将我的 JSF 2.0 xhtml 文件放在 WEB-INF\jsf 下。那我该如何访问它们?我知道 WEB-INF 内部的任何东西都不会暴露在外部,所以我需要一个控制器来将我重定向到相应的 JSP,对吧? (这也是模型 2 模式 iirc)。
我可以通过 web.xml/faces-config.xml 中的参数来实现吗?我认为 FacesServlet 是我的 webapp 的控制器,所以它应该服务于这个目的?
还有一个关于理解 Model 2 模式的问题。是否每个操作都必须首先进入一个 servlet,然后由该 servlet 处理下一个可能的步骤?因此,在这种模式中禁止使用简单的<a href="anotherPage.html" />
,因为它不会进入控制 servlet?
【问题讨论】:
【参考方案1】:我想将我的 JSF 2.0 xhtml 文件放在 WEB-INF\jsf 下。那我该如何访问它们呢?
你不能。无法直接访问/WEB-INF
文件夹中的文件。
有两种方法可以解决 JSF 源文件可公开访问的问题。
将FacesServlet
映射到*.xhtml
而不是*.jsf
。
或者,通过web.xml
中的<security-constraint>
限制对*.xhtml
的直接访问。
<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>
另见:
Which XHTML files do I need to put in /WEB-INF and which not? JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why?关于理解 Model 2 模式的另一个问题。是否每个操作都必须首先进入一个 servlet,然后由该 servlet 处理下一个可能的步骤?
FacesServlet
已经这样做了。是控制器。使用 JSF,您已经得到了一个简单的 javabean 作为模型和 JSP/Facelets 文件作为视图。 FacesServlet
作为控制器,已经从您手中承担了请求参数收集、验证、转换、模型更新和导航的所有令人讨厌的工作。
另见:
What components are MVC in JSF MVC framework? JSF Controller, Service and DAO所以在这种模式中禁止使用简单的
<a href="anotherPage.html" />
,因为它不会进入控制 servlet?
不,完全没问题。控制器将在需要时启动。如果资源不需要控制器(即静态资源),那么您也不需要让它通过某个控制器。
以后,请在不同的 Stack Overflow 问题中提出多个问题。
【讨论】:
感谢您的回复。我已经只映射了 *.xhtml 文件(选项 1)。我已经读过,在某些框架(Struts、Spring Webflow、..)中,将 jsp 文件(=动态内容)放在 WEB-INF 下是可能的/首选方式,控制器在那里访问它们并将它们显示给用户。我只是想问一下 JSF 是否也可以这样做。但是如果我没看错的话,没有人可以通过浏览器查看 xhtml 文件的源代码,因为它们总是通过控制器呈现,对吧?【参考方案2】:要访问WEB-INF/jsf
文件夹中的xhtml
页面,您可以执行以下操作:
-
将
xhtml
pages 文件夹从webapp root
移动到WEB-INF
在项目中引入“Dispatcher View”模式
根据应用程序的页面将“Front Controller”servlet 映射到url
将Faces Servlet映射到“.xhtml
”
在“Dispatcher”内部将请求转发到来自“WEB-INF/jsf/<name>.xhtml
”的页面
覆盖 jsf ViewHandler getActionUrl
以从生成的 action
url
(form, link, button
)中排除“WEB-INF
”
例如,xhtml
页面位于 webapp 根文件夹“jsf
”中。页面之间的所有url
类似于jsf/<pageName>.xhtml
。所以我们下一步:
将<webapp root>/jsf
移动到<webapp root>/WEB-INF/jsf
创建 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);
-
基于页面将
web.xml
中的 Front Controller servlet 映射到 url
:
<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>
-
将
web.xml
中的Faces Servlet映射到.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>
-
创建Dispatcher,将
request
转发到更正xhtml
页面:
``
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);
因此,如果页面的 url 是 /myapp/jsf/home.xhtml
,那么 Dispatcher 会将其转发到 myapp/WEB-INF/jsf/home.xhtml
。 Faces Servlet 将处理“.xhtml
”请求。但是,如果在页面上使用jsf
组件,如h:form, h:link, h:button
等生成action
或url
,那么url
将真正包括“/WEB-INF
”。所以要排除它,我们需要下一步。
从jsf
生成的url
中排除“/WEB-INF
”(用于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 配置jsf
使用指定的ViewHandler
。在faces-config.xml
中添加下一个:
<application> ... <view-handler> controllers.HiddenPageViewHandler </view-handler> </application>
【讨论】:
不好的建议。这引入了一个安全漏洞:将所有 WEB-INF 内容直接公开。 为了简单起见,调度程序只是在请求的 url 之前添加 WEB-INF。当然,调度员可能会根据需要完成复杂的工作。如何实现它只是一个想法。 编辑了 Dispatcher 示例,使其仅从 WEB-INF/jsf 转发到页面,并增加了页面查找逻辑,包括安全检查或转发到错误页面 在使用非 XHTML 映射的情况下隐藏公共页面的 JSF 源代码文件的具体问题仍然是一个相当笨拙的解决方案。当前的最佳答案显示了如何以更简单的方式解决它。 当然,以上答案提供了更简单的方法。但我的解决方案只是展示使用 JSF 的 Dispatcher View 的好处。它的一个好处是可以从 WEB-INF 访问 jsf 文件。 Dispatcher View 模式也允许对 JSF 页面使用逻辑映射策略。在 Dispatcher 中,可以分析像 /myapp/jsf/home 这样的 url 并将其转发到 /WEB-INF/jsf/home.xhtml(对于 Faces Servlet)。在 ViewHandler 中,可以从 jsf 生成的 url 中删除 .xhtml 扩展名: if (actionUrl != null && actionUrl.contains(".xhtml")) actionUrl = actionUrl.replace(".xhtml", "");以上是关于WEB-INF 目录中的 JSF 文件,我如何访问它们?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 JSF 的 /WEB-INF 文件夹中获取属性文件?
警告:有人试图访问安全资源:/WEB-INF/login.xhtml