JSF作为如今JavaEE标准之一,基于组件的设计为Java的web开发带来了极大的便利性。然而在设计上,JSF抛弃了传统的GET请求方式,所有JSF的表单都已post方式提交。这样虽然在安全性等方面有一定好处,但是也带来了一些不便,比如,由JSF开发的web应用难以为每个单元定位。
上述单元定位的意思是,比如你开发了一个project.faces用于动态显示project的内容。由于是post提交表单,那么一个叫dollyCal的项目和一个叫nirvana的项目将同样显示为project.faces,这样每次用户都需要通过导航浏览自己需要的项目,而不能通过对固定网页的收藏来一次性浏览。
解决上述问题可以通过filter来模拟get请求。
以下还是以dollyCal举例:
GET请求下url形式为project.faces?name=dollyCal
则通过filter拦截该请求,取出dollyCal字段,然后调用FacesContext,初始化相应的managed-bean,从数据库中读出dollyCal的相关信息填充到managed-bean中,再通过dispatcher导航到相应页面即可。这样用户可以project.faces?name=dollyCal形式轻松访问一个项目,方便其收藏和订阅
if (request instanceof HttpServletRequest) {
HttpServletRequest r = (HttpServletRequest) request;
String s = r.getQueryString();
if (s != null && s.startsWith("project=") && s.length() > 8) {
String name = s.substring(8);
if (!PersistenceUtil.validateProject(name)) {
FacesContext fcg = getFacesContext(request,response);
ProjectViewBean pjv=(ProjectViewBean)fcg.getApplication().getVariableResolver().resolveVariable(fcg,"pjv");
try {
ProjectBean p=PersistenceUtil.getProjectByName(name);
pjv.setProject(p);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
RequestDispatcher rd=request.getRequestDispatcher("/projectView.faces");
rd.forward(request, response);
}
} 唯一需要注意的问题是,filter实际上处于JSF的管理区域之外,因此不能调用FacesContext.getCurrentInstance方法来获得JSF上下文,而需要通过request, response来创建当前JSF上下文。再从该上下文中查出managed-bean,进行数据填充,
以下是完整代码,说明如下:
ProjectViewBean是projectView.faces页面的managed-bean, 首先解析url中要查询的项目名称,从数据库中读出相应信息,再从上下文中查询出该bean,填充信息即可。这样再访问该页面时就会得到想要的结果。
package org.myibm;
import java.io.IOException;
import javax.faces.FactoryFinder;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.myibm.beans.ProjectViewBean;
import org.myibm.persistence.bean.ProjectBean;
import org.myibm.utils.PersistenceUtil;
public class ParserFilter implements Filter {
private FilterConfig filterConfig = null;
public void destroy() {
// TODO Auto-generated method stub
filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
if (request instanceof HttpServletRequest) {
HttpServletRequest r = (HttpServletRequest) request;
String s = r.getQueryString();
if (s != null && s.startsWith("project=") && s.length() > 8) {
String name = s.substring(8);
if (!PersistenceUtil.validateProject(name)) {
FacesContext fcg = getFacesContext(request,response);
ProjectViewBean pjv=(ProjectViewBean)fcg.getApplication().getVariableResolver().resolveVariable(fcg,"pjv");
try {
ProjectBean p=PersistenceUtil.getProjectByName(name);
pjv.setProject(p);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
RequestDispatcher rd=request.getRequestDispatcher("/projectView.faces");
rd.forward(request, response);
}
}
}
try {
// System.out.print("filter begins!");
chain.doFilter(request, response);
// System.out.print("filter works!");
} finally {
}
}
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
this.filterConfig = arg0;
}
private abstract static class InnerFacesContext extends FacesContext {
protected static void setFacesContextAsCurrentInstance(
FacesContext facesContext) {
FacesContext.setCurrentInstance(facesContext);
}
}
private FacesContext getFacesContext(ServletRequest request,
ServletResponse response) {
// Try to get it first
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext != null)
return facesContext;
FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder
.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifecycle lifecycle = lifecycleFactory
.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
// Either set a private member servletContext =
// filterConfig.getServletContext();
// in you filter init() method or set it here like this:
// ServletContext servletContext =
// ((HttpServletRequest)request).getSession().getServletContext();
// Note that the above line would fail if you are using any other
// protocol than http
ServletContext servletContext = ((HttpServletRequest) request)
.getSession().getServletContext();
// Doesn't set this instance as the current instance of
// FacesContext.getCurrentInstance
facesContext = contextFactory.getFacesContext(servletContext, request,
response, lifecycle);
// Set using our inner class
InnerFacesContext.setFacesContextAsCurrentInstance(facesContext);
// set a new viewRoot, otherwise context.getViewRoot returns null
// UIViewRoot view =
// facesContext.getApplication().getViewHandler().createView(facesContext,
// "yourOwnID");
// facesContext.setViewRoot(view);
return facesContext;
}
}