要访问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>