1. 按照以下代码改写你自己的Activator (或者将代码中的"/pages"改成你的jsf网页路径):
注意加粗的那段代码(使用当前的class loader来加载jsf的FacesServlet)
package net.andyluo.singlife.jsf.demo;

import java.io.IOException;
import java.util.Dictionary;
import java.util.Hashtable;

import javax.faces.webapp.FacesServlet;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.eclipse.equinox.http.helper.BundleEntryHttpContext;
import org.eclipse.equinox.http.helper.ContextPathServletAdaptor;
import org.eclipse.equinox.jsp.jasper.JspServlet;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.util.tracker.ServiceTracker;

import com.sun.faces.config.ConfigureListener;

public class Activator implements BundleActivator


{

private ServiceTracker httpServiceTracker;

public void start(BundleContext context) throws Exception

{
httpServiceTracker = new HttpServiceTracker(context);
httpServiceTracker.open();
}

public void stop(BundleContext context) throws Exception

{
httpServiceTracker.close();
}

private class HttpServiceTracker extends ServiceTracker

{

private static final String PATH = "/jsf";

public HttpServiceTracker(BundleContext context)

{
super(context, HttpService.class.getName(), null);
}

public Object addingService(ServiceReference reference)

{
final HttpService httpService = (HttpService) context
.getService(reference);
try

{
HttpContext commonContext = new BundleEntryHttpContext(context
.getBundle(), "/pages");
httpService.registerResources(PATH, "/", commonContext);

JspServlet jspServlet = new JspServlet(context.getBundle(),
"/pages");
Servlet adaptedJspServlet = new ContextPathServletAdaptor(
jspServlet, PATH);
httpService.registerServlet(PATH + "/*.jsp", adaptedJspServlet,
null, commonContext);

Dictionary initparams = new Hashtable();
initparams.put("servlet-name", "Faces Servlet");
Servlet adaptedFacesServlet = new ServletContextListenerServletAdaptor(
new ConfigureListener(), new FacesServlet(), jspServlet
.getJspLoader());
adaptedFacesServlet = new ContextPathServletAdaptor(
adaptedFacesServlet, PATH);
httpService.registerServlet(PATH + "/*.jsf",
adaptedFacesServlet, initparams, commonContext);

} catch (Exception e)

{
e.printStackTrace();
}
return httpService;
}

public void removedService(ServiceReference reference, Object service)

{
final HttpService httpService = (HttpService) service;
httpService.unregister(PATH); //$NON-NLS-1$
httpService.unregister(PATH + "/*.jsp"); //$NON-NLS-1$
httpService.unregister(PATH + "/*.jsf"); //$NON-NLS-1$
super.removedService(reference, service);
}
}

public class ServletContextListenerServletAdaptor implements Servlet

{
private ServletConfig config;

private ServletContextListener listener;

private Servlet delegate;

private ClassLoader jspLoader;

public ServletContextListenerServletAdaptor(
ServletContextListener listener, Servlet delegate,
ClassLoader jspLoader)

{
this.listener = listener;
this.delegate = delegate;
this.jspLoader = jspLoader;
}

public void init(ServletConfig config) throws ServletException

{
this.config = config;
ClassLoader original = Thread.currentThread()
.getContextClassLoader();
try

{
Thread.currentThread().setContextClassLoader(jspLoader);
listener.contextInitialized(new ServletContextEvent(config
.getServletContext()));
delegate.init(config);
} finally

{
Thread.currentThread().setContextClassLoader(original);
}
}

public void service(ServletRequest req, ServletResponse resp)
throws ServletException, IOException

{
ClassLoader original = Thread.currentThread()
.getContextClassLoader();
try

{
Thread.currentThread().setContextClassLoader(jspLoader);
delegate.service(req, resp);
} finally

{
Thread.currentThread().setContextClassLoader(original);
}
}

public void destroy()

{
ClassLoader original = Thread.currentThread()
.getContextClassLoader();
try

{
Thread.currentThread().setContextClassLoader(jspLoader);
delegate.destroy();
listener.contextDestroyed(new ServletContextEvent(config
.getServletContext()));
config = null;
} finally

{
Thread.currentThread().setContextClassLoader(original);
}
}

public ServletConfig getServletConfig()

{
return config;
}

public String getServletInfo()

{
return "";
}
}

}
2. 因为JspServlet中没有返回class loader的方法,所以我们要更改一下JspServlet的实现代码(hack一下):更改equinox的org.eclipse.equinox.jsp.jasper_*.jar中的org.eclipse.equinox.jsp.jasper.JspServlet类:(可以下载JspServlet的源代码,在本地更改编译成功后将class文件覆盖到org.eclipse.equinox.jsp.jasper_*.jar中)
添加以下方法:
public ClassLoader getJspLoader()
{
return this.jspLoader;
}
如此即可^_^, 其实就是让FacesServlet使用JspServlet的ClassLoader,这样就不会出现"Can't find FacesContext"错误了。
参考: [news.eclipse.technology.equinox]
JSF, Equinox & FactoryFinder
版权所有 罗明