经过几天的测试,发现上面的还有一些地方要修改的:
1.ClassLoader问题,还是老问题,在DWR被调用的时候,会去加载定义中的类,因此,如果此类不在DWR Bundle同一个ClassLoader的时候会出现找不到类的错误。想过几个解决方法:a.模仿Declarative Services b.在DWR Bundle中引入所需包。目前还没有实现比较好的方法。
2.在DWR2.0的包里,有时会出现以下警告信息:
2007
-
10
-
11
0
:
10
:
11
org.directwebremoting.util.CommonsLoggingOutput error
严重: A request has been denied as a potential CSRF attack.
这可能是由于我自己实现的Session还不完善引起的,可以参考它这一段的代码:
org.directwebremoting.dwrp.Batch
private
void
checkNotCsrfAttack(HttpServletRequest request, String sessionCookieName)

{
// A check to see that this isn't a csrf attack
// http://en.wikipedia.org/wiki/Cross-site_request_forgery
// http://www.tux.org/~peterw/csrf.txt
if (request.isRequestedSessionIdValid() && request.isRequestedSessionIdFromCookie())

{
String headerSessionId = request.getRequestedSessionId();
if (headerSessionId.length() > 0)

{
String bodySessionId = getHttpSessionId();

// Normal case; if same session cookie is supplied by DWR and
// in HTTP header then all is ok
if (headerSessionId.equals(bodySessionId))

{
return;
}

// Weblogic adds creation time to the end of the incoming
// session cookie string (even for request.getRequestedSessionId()).
// Use the raw cookie instead
Cookie[] cookies = request.getCookies();
for (int i = 0; i < cookies.length; i++)

{
Cookie cookie = cookies[i];
if (cookie.getName().equals(sessionCookieName) &&
cookie.getValue().equals(bodySessionId))

{
return;
}
}

// Otherwise error
log.error("A request has been denied as a potential CSRF attack.");
throw new SecurityException("Session Error");
}
}
}
而调用这段代码的是:同一文件里的:
if
(crossDomainSessionSecurity)

{
checkNotCsrfAttack(request, sessionCookieName);
}
也就是说crossDomainSessionSecurity=false;即可了
那么在初始化这值的地方是:
org.directwebremoting.dwrp.BaseCallMarshaller:
Batch batch
=
(Batch) request.getAttribute(ATTRIBUTE_BATCH);
if
(batch
==
null
)

{
batch = new Batch(request, crossDomainSessionSecurity, allowGetForSafariButMakeForgeryEasier, sessionCookieName);

// Save calls for retry exception
request.setAttribute(ATTRIBUTE_BATCH, batch);
}
可见,我们只要在request的attribute中放一个Batch实例就可以了。所以我们会在Activator里面多一段代码:
//
=================这一段防止DWR禁止站外远程方法
Batch batch
=
null
;

try
{
batch = new Batch(request,false,true,null);
request.setAttribute("org.directwebremoting.dwrp.batch", batch);

}
catch
(ServerException e)
{}
//
=================
因此完整的代码应该是:
com.ycoe.dwr.Activator
package
com.ycoe.dwr;

import
java.io.IOException;
import
java.io.InputStream;
import
java.net.URL;
import
java.net.URLConnection;

import
javax.servlet.ServletConfig;
import
javax.servlet.ServletContext;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;

import
org.directwebremoting.Container;
import
org.directwebremoting.WebContextFactory.WebContextBuilder;
import
org.directwebremoting.dwrp.Batch;
import
org.directwebremoting.extend.ServerException;
import
org.directwebremoting.extend.ServerLoadMonitor;
import
org.directwebremoting.impl.ContainerUtil;
import
org.directwebremoting.impl.DefaultContainer;
import
org.directwebremoting.impl.DwrXmlConfigurator;
import
org.directwebremoting.impl.StartupUtil;
import
org.directwebremoting.servlet.UrlProcessor;
import
org.directwebremoting.util.ServletLoggingOutput;
import
org.osgi.framework.Bundle;
import
org.osgi.framework.BundleActivator;
import
org.osgi.framework.BundleContext;
import
org.osgi.framework.ServiceEvent;
import
org.osgi.framework.ServiceListener;
import
org.osgi.framework.ServiceReference;
import
org.osgi.service.http.HttpService;

import
com.usys.server.Log;

public
class
Activator
extends
HttpServlet
implements
BundleActivator,

ServiceListener
{
private static final long serialVersionUID = 8907913737153048789L;

private BundleContext bc;

private ServiceReference ref;

private static Bundle bundle;

/** *//**
* Accessor for the DWR IoC container.
*
* @return DWR's IoC container
*/

public Container getContainer()
{
return container;
}


/** *//**
* Our IoC container
*/
private DefaultContainer container;


/** *//**
* The WebContext that keeps http objects local to a thread
*/
private WebContextBuilder webContextBuilder;


/** *//**
* The log stream
*/
public static final Log log = Log.getLog(Activator.class.getName());


/**//*
* Bundle启动时动作,初始化DWR
* 注册/ajax过滤器
*
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/

public void start(BundleContext context) throws Exception
{
bundle = context.getBundle();
bc = context;
registerServlet();
context.addServiceListener(this, "(objectClass="
+ HttpService.class.getName() + ")");

try
{
// 初始化DWR
URL url = new URL("HTTP", "127.0.0.1", 80, "/ajax/about");
URLConnection c = url.openConnection();
c.connect();
url = null;

} catch (Exception e)
{
}
}


/**//*
*
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/

public void stop(BundleContext context) throws Exception
{

try
{
unregisterServlet();

} catch (Throwable t)
{
t.printStackTrace();
}
bc = null;
ref = null;
}


/**//*
* 注册Web应用
*/

private void registerServlet()
{

if (ref == null)
{
ref = bc.getServiceReference(HttpService.class.getName());
}


if (ref != null)
{

try
{
HttpService http = (HttpService) bc.getService(ref);
http.registerServlet("/ajax", new Activator(), null, null);

} catch (Exception e)
{
e.printStackTrace();
}
}
}


public void serviceChanged(ServiceEvent event)
{

}


/**//*
* 卸载Web应用
*/

private void unregisterServlet()
{

if (ref != null)
{

try
{
HttpService http = (HttpService) bc.getService(ref);
http.unregister("/ajax");

} catch (Exception e)
{
e.printStackTrace();
}
}
}


/**//*
* 除了Servlet常规的初始化以外,还要进行DWR的初始化,加载各个有效配置文件
* @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
*/
@Override

public void init(ServletConfig servletConfig) throws ServletException
{
super.init(servletConfig);
ServletContext servletContext = servletConfig.getServletContext();

try
{
container = ContainerUtil.createDefaultContainer(servletConfig);
ContainerUtil.setupDefaultContainer(container, servletConfig);
webContextBuilder = StartupUtil.initWebContext(servletConfig,
servletContext, container);
StartupUtil.initServerContext(servletConfig, servletContext,
container);

ContainerUtil.prepareForWebContextFilter(servletContext,
servletConfig, container, webContextBuilder, this);
//===========================以下加载DWR核心配置,以保证核心配置最先加载
URL url = bundle.getEntry("/AJAX-INF/ajaxCore.xml");
log.info("加载DWR核心配置:/AJAX-INF/ajaxCore.xml");
InputStream is = url.openStream();
DwrXmlConfigurator system = new DwrXmlConfigurator();

try
{
system.setClassResourceName("/AJAX-INF/ajaxCore.xml");

}catch(Exception e)
{
system.setInputStream(is);
}
system.configure(container);
//===========================
DwrLoader.loadDwrConfig(container);
ContainerUtil.publishContainer(container, servletConfig);

} catch (ExceptionInInitializerError ex)
{
log.fatal("ExceptionInInitializerError. Nested exception:", ex
.getException());
throw new ServletException(ex);

} catch (Exception ex)
{
log.fatal("DwrServlet.init() failed", ex);
throw new ServletException(ex);

} finally
{

if (webContextBuilder != null)
{
webContextBuilder.unset();
}

ServletLoggingOutput.unsetExecutionContext();
}
}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException
{
//=================这一段防止DWR禁止站外远程方法
Batch batch = null;

try
{
batch = new Batch(request,false,true,null);
request.setAttribute("org.directwebremoting.dwrp.batch", batch);

} catch (ServerException e)
{}
//=================

try
{
webContextBuilder.set(request, response, getServletConfig(),
getServletContext(), container);
ServletLoggingOutput.setExecutionContext(this);
UrlProcessor processor = (UrlProcessor) container
.getBean(UrlProcessor.class.getName());
processor.handle(request, response);

} finally
{
webContextBuilder.unset();
ServletLoggingOutput.unsetExecutionContext();
}
}

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException
{
doPost(request, response);
}


public void destroy()
{
shutdown();
super.destroy();
}


public void shutdown()
{
ServerLoadMonitor monitor = (ServerLoadMonitor) container
.getBean(ServerLoadMonitor.class.getName());
monitor.shutdown();
}
}
另一个类com.ycoe.dwr.DwrLoader
package
com.ycoe.dwr;

import
java.io.IOException;
import
java.io.InputStream;
import
java.net.URL;
import
java.util.Dictionary;
import
javax.xml.parsers.ParserConfigurationException;

import
org.directwebremoting.impl.DefaultContainer;
import
org.directwebremoting.impl.DwrXmlConfigurator;
import
org.osgi.framework.Bundle;
import
org.osgi.framework.BundleContext;
import
org.xml.sax.SAXException;
import
com.ycoe.core.BundleContext;



public
class
DwrLoader
{

/** *//**
* 权限配置文件
*/
private static final String DWR_CONFIG_FILE = "AJAX";
@SuppressWarnings("unchecked")
public static void loadDwrConfig(

DefaultContainer container) throws IOException, ParserConfigurationException, SAXException
{
BundleContext context = BundleContext.getBundleContext().getContext();
Bundle[] bundles = context.getBundles();

for (Bundle bundle : bundles)
{
Dictionary headers = bundle.getHeaders();
String config = (String) headers.get(DWR_CONFIG_FILE);
// 如果配置文件存在

if (null != config)
{
String[] configXmls = config.split(",");

for (String configXml : configXmls)
{
URL url = bundle.getEntry(configXml);
System.out.println("加载DWR:"+configXml);
InputStream is = url.openStream();
DwrXmlConfigurator system = new DwrXmlConfigurator();

try
{
system.setClassResourceName(configXml);

}catch(Exception e)
{
system.setInputStream(is);
}
system.configure(container);
}
}
}
}
}
这样就完成了我们的加载代码了。
然后再在Bundle项目的最上层建一个AJAX-INF目录,将dwr.jar里的dwr.xml复制出来,重新命名为ajaxCore.xml
创建lib目录,dwr及其所需的jar文件。
打开META/MANIFEST.MF文件。
添加所需的包:
Bundle-ClassPath: bin/
,
lib/easymock.jar
,
lib/junit.jar
,
lib/dom4j-
1.6.1
.jar
,
.
,
lib/commons-logging-
1.0.4
.jar
,
lib/bsf-
2.3
.jar
,
lib/jdom-
1.0
.jar
,
lib/backport-util-concurrent.jar
,
lib/xom-
1.1
.jar
,
lib/dwr-
2.0.1
.jar
这样就完成了。
然后另一个Bundle中要使用dwr Bundle将在下一个回复中写明