DWR+OSGi整合v2.0

前天发表了一篇DWR+OSGi整合的文章,那篇文章对DWR+OSGi的整合还不是很完善,现在这里提供一种比较完善的方法。也算是对上篇后面提出问题的解答。
  在这之前,都还是建立在要修改dwr.jar源码的基础上。这个版本,可以在不修改dwr.jar的基础上进行。这样可以很方便地升级dwr,对于使用者也减少了很多的工作量。好了,让我们去看一看:

  首先,创建一个普通的Plug-in工程。建个lib目录,导入用到的jar文件。然后修改启动文件Activator.java。与上一篇《 [原创]DWR与OSGi的整合》一样。然后再创建 DWR-AJAX目录,把dwr.jar/org/directwebremoting 里面的dwr.xml文件拷到此目录。再次,创建一个DwrLoador.java,源代码也与《[原创]DWR与OSGi的整合》一模一样。好了,再配置一下项目的MANIFEST.MF文件,添加DWR-AJAX: /USYS-INF/dwr.xml,/USYS-INF/testAjax.xml

  这里,testAjax.xml是我们的测试文件,可以添加N个DWR的配置文件,以,隔开。当然,可以分布在不同的Bundle里面了。测试文件自己编写。
2007 - 9 - 19   10 : 39 : 19  org.directwebremoting.util.CommonsLoggingOutput info
信息: DWR Version 
2.0.1  starting.
2007 - 9 - 19   10 : 39 : 19  org.directwebremoting.util.CommonsLoggingOutput info
信息: - Servlet Engine: Equinox HttpService/
1.0
2007 - 9 - 19   10 : 39 : 19  org.directwebremoting.util.CommonsLoggingOutput info
信息: - Java Version:   
1.5 .0_ 12
2007 - 9 - 19   10 : 39 : 19  org.directwebremoting.util.CommonsLoggingOutput info
信息: - Java Vendor:    Sun Microsystems Inc.
/ajax/about>>>>>>>>>>>>>>>>>>>
===================================
<html><head><title>DWR - Easy Ajax for Java</title></head><body><h1 style
= 'font-size: 100 % ; font-weight:normal;'>This site is using <a href='http://getahead.org/dwr'>DWR - Easy Ajax for Java</a>.</body></html>
===================================

Feedback

#1楼 [楼主]   回复  引用  查看    

2007-10-11 13:46 by YCOE

经过几天的测试,发现上面的还有一些地方要修改的:
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(), nullnull);
            }
 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将在下一个回复中写明  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值