经过几天的测试,发现上面的还有一些地方要修改的:
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还不完善引起的,可以参考它这一段的代码:
严重: A request has been denied as a potential CSRF attack.
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");
}
}
}
{
// 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;即可了
{
checkNotCsrfAttack(request, sessionCookieName);
}
那么在初始化这值的地方是:
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里面多一段代码:
if (batch == null )
{
batch = new Batch(request, crossDomainSessionSecurity, allowGetForSafariButMakeForgeryEasier, sessionCookieName);
// Save calls for retry exception
request.setAttribute(ATTRIBUTE_BATCH, batch);
}
//
=================这一段防止DWR禁止站外远程方法
Batch batch = null ;
try {
batch = new Batch(request,false,true,null);
request.setAttribute("org.directwebremoting.dwrp.batch", batch);
} catch (ServerException e) {}
// =================
因此完整的代码应该是:
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
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();
}
}
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);
}
}
}
}
}
这样就完成了我们的加载代码了。
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
这样就完成了。
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将在下一个回复中写明