Spring DM集成Strtus2(一)

要完成Spring DM与Struts2的集成,主要完成两件事

  • 将Struts2集成到OSGi环境中。
  • 将Spring DM与Struts2集成,使Struts2可以使用Spring DM中定义的Bean。

此文章采用的方法不是Spring DM Web Extender的方式,由Spring DM Web是将工程手动注册到Web容器中,暂时只支持tomcat与jetty。

 

Struts2集成到OSGi环境中

        这步的目的是让Struts2的bundle可以读到其实bundle下的Struts配置文件,由于Struts2本身只处理了classpath下面的三类配置文件,分别为struts-default.xml、struts-plugin.xml、struts.xml文件,所以首先我们要增加读取bundle下面配置文件的ConfigurationProvider,代码在org.apache.struts2.dispatcher.Dispatcher,将此类的源代码找出来,然后修改private void init_TraditionalXmlConfigurations()方法

 

 private void init_TraditionalXmlConfigurations() {
        String configPaths = initParams.get("config");
        if (configPaths == null) {
            configPaths = DEFAULT_CONFIGURATION_PATHS;
        }
        String[] files = configPaths.split("\\s*[,]\\s*");
        for (String file : files) {
            if (file.endsWith(".xml")) {
                if ("xwork.xml".equals(file)) {
                    configurationManager.addContainerProvider(createXmlConfigurationProvider(file, false));
                } else {
                    configurationManager.addContainerProvider(createStrutsXmlConfigurationProvider(file, false, servletContext));
                }
            } else {
                throw new IllegalArgumentException("Invalid configuration file name");
            }
        }
        //FIXME 增加读取bundle中配置文件的类。
        configurationManager.addContainerProvider(new OSGiXmlConfigurationProvider("struts_osgi.xml",false,servletContext));
    }

 

 其中OSGiXmlConfigurationProvider的代码见附件, 主要的代码在loadConfigurationFiles方法中

Bundle[] bundles=Activator.getContext().getBundles();
			ByteArrayOutputStream bos=new ByteArrayOutputStream();
			for(Bundle bundle:bundles){
				try {
					//不加载本bundle的struts.xml文件
					if(bundle.getSymbolicName().equals(Activator.getContext().getBundle().getSymbolicName())) continue;
					url=bundle.getEntry(DEFAULT_CONFIG_NAME);
					if(url==null) continue;
					is=url.openStream();
					IOUtils.copy(is, bos);
					is=new ByteArrayInputStream(bos.toByteArray());
					InputSource in = new InputSource(is);
					
					in.setSystemId(is.toString());
					Document doc=DomHelper.parse(in,dtdMappings);
					try{
						//增加默认名称空间
						addDefaultNamespace(doc,bundle.getHeaders().get(WEB_CONTEXT),HashFile.getHash(bos.toByteArray()),bundle.getBundleId());
					}catch(Exception e){
						LOG.error("增加包名到缓存失败", e, new String[]{});
					}
					docs.add(doc);
				} catch (IOException e) {
					LOG.error("加载ID为"+bundle.getBundleId()+" 的bundle中的配置文件失败!", e, new String[]{});
				}finally{
					if(is!=null){
						try {
							is.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
					if(bos!=null){
						try {
							bos.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			}

 接下来就是注册Struts2的servlet,由于采用的是Equinox的http实现,所以要用HttpService来注册

package com.yinhai.osgi.web.struts2;

import javax.servlet.Servlet;
import javax.servlet.ServletException;

import org.apache.log4j.Logger;
import org.apache.struts2.dispatcher.ng.servlet.StrutsServlet;
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.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.osgi.util.tracker.ServiceTracker;

/**
 * 用于注册struts2的servlet和web bundle的上下文。
 * @author Dream.Lee
 * @version 2013-6-5
 */
public class StrutsController implements BundleListener {
	
	private static Logger logger=Logger.getLogger(StrutsController.class);
	public static final String WEB_CONTEXT="Web-Context";
	
	public static final String STATIC_SUBFIX="_res";

	private HttpService httpService;
	
	public static final String WEB_CONTENT_PATH = "/WebContent";

	public void activate(ComponentContext context) {
		registerController("/*.do");
		//对已有的bundle进行web上下文注册
		Bundle[] bundles=Activator.getContext().getBundles();
		for(Bundle bundle:bundles){
			if(bundle.getHeaders().get(WEB_CONTEXT)!=null&&bundle.getState()==Bundle.ACTIVE){
				try {
					ServiceTracker<HttpService, HttpService> sTracker=new ServiceTracker<HttpService, HttpService>(bundle.getBundleContext(), HttpService.class.getName(), null);
					sTracker.open();
					HttpService httpService=sTracker.getService();
					if(httpService!=null){
						httpService.registerResources(bundle.getHeaders().get(WEB_CONTEXT)+STATIC_SUBFIX,WEB_CONTENT_PATH,
								 null);
						// 注册JSP文件
						HttpContext commonContext = new BundleEntryHttpContext(
								bundle, WEB_CONTENT_PATH);
						Servlet adaptedJspServlet = new ContextPathServletAdaptor(
								new JspServlet(bundle,
										WEB_CONTENT_PATH), bundle.getHeaders().get(
										WEB_CONTEXT));
						httpService.registerServlet(
								bundle.getHeaders().get(WEB_CONTEXT) + "/*.jsp",
								adaptedJspServlet, null, commonContext);
					}
//					sTracker.close();
				} catch (NamespaceException e) {
					e.printStackTrace();
				} catch (ServletException e) {
					e.printStackTrace();
				}
			}
		}
		Activator.getContext().addBundleListener(this);
		Activator.getContext().addBundleListener(new SynchronousBundleListener() {
			
			@SuppressWarnings({ "rawtypes", "unchecked" })
			@Override
			public void bundleChanged(BundleEvent event) {
				Bundle bundle=event.getBundle();
				if (bundle.getHeaders().get(WEB_CONTEXT) != null) {
					switch(event.getType()){
						case BundleEvent.STOPPING:
							ServiceReference sf=bundle.getBundleContext().getServiceReference(HttpService.class.getName());
							HttpService httpService = (HttpService) bundle
									.getBundleContext().getService(sf);
							try{
								httpService.unregister(bundle.getHeaders().get(WEB_CONTEXT)+STATIC_SUBFIX);
								logger.info("卸载"+bundle.getHeaders().get(WEB_CONTEXT));
							}catch(Exception e){
								logger.info("卸载失败:"+bundle.getHeaders().get(WEB_CONTEXT), e);
							}finally{
								bundle.getBundleContext().ungetService(sf);
							}
							break;
					}
				}
			}
		});
	}

	public void setHttpService(HttpService httpService) {
		this.httpService = httpService;
	}


	private void registerController(String webcontext) {
		try {
			StrutsServlet controller = new StrutsServlet();
			httpService.registerServlet(webcontext, controller, null, null);
			controller.init();
			logger.info("已注册:" + webcontext);
		} catch (Exception e) {
			logger.error("注册扩展的:" + webcontext + "失败", e);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public void bundleChanged(BundleEvent event) {
		Bundle bundle = event.getBundle();
		if (bundle.getHeaders().get(WEB_CONTEXT) != null) {
			if (event.getType() == BundleEvent.STARTED) {
				logger.info("注册 "
						+ bundle.getHeaders().get(WEB_CONTEXT)+STATIC_SUBFIX + ","
						+ bundle.getHeaders().get(WEB_CONTEXT)
						+ "/*.jsp");
				BundleContext context = bundle.getBundleContext();
				ServiceReference sf=context.getServiceReference(HttpService.class.getName());
				HttpService httpService = (HttpService) bundle
						.getBundleContext().getService(sf);
				try {
					// 注册静态文件
					httpService.registerResources(bundle.getHeaders().get(WEB_CONTEXT)+STATIC_SUBFIX,
					 WEB_CONTENT_PATH, null);

					// 注册JSP文件
					Servlet adaptedJspServlet = new ContextPathServletAdaptor(
							new JspServlet(bundle,
									WEB_CONTENT_PATH), bundle
									.getHeaders().get(WEB_CONTEXT));
					httpService.registerServlet(bundle.getHeaders()
							.get(WEB_CONTEXT) + "/*.jsp",
							adaptedJspServlet, null, null);
				} catch (NamespaceException e) {
					e.printStackTrace();
				} catch (ServletException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

 此类采用声明式的方式发布,配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<component name="strutscontroller">
	<implementation class="com.yinhai.osgi.web.struts2.StrutsController"/>
	<reference name="HttpService" interface="org.osgi.service.http.HttpService" bind="setHttpService" unbind="unsetHttpService" policy="dynamic"/>
</component>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 【优秀课程设计】主要针对计算机相
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值