spring+webwork的动态加载实现osgi的插件思想

来源:互联网 发布:织梦cms视频教程下载 编辑:程序博客网 时间:2024/05/01 07:06

 

 

OSGI的思想与现有的成熟WEB框架还是有点隔阂,希望下一个版真的能像官方所说的,原有的框架平滑过度到OSGI.由于公司要求不打破原有的WEB框架,所以...
需求:
网站有好几个功能模块,后台管理员要实现模块的动态的增删查改,每个功能模块,有自己对应的action,dao,service,ibatis,ftl,validation,model等等
当主网站启动后,管理员如何通过web界面来动态管理这些功能模块?

解决如下:

1.spring动态加载bean
webwork.properties中的webwork.objectFactory = com.bbs.PluginObjectFactory
原来为spring,是与spring结合,实际是使用com.opensymphony.xwork.spring.SpringObjectFactory来加载webwork的bean
自已写个PluginObjectFactory(代码见最下面)手动生成ApplicationContext,手动编写读取spring配置文件的方法。

 

2.文件如何放置
将需要添加的功能模块放在站点的对应目录下。

考虑管理员如何上传问题?主要分两部分

a.功能模块站点编译后生成的文件打包后上传

b.ftl的view层页面打包上传
 将生成好的class文件及对应的配置文件等,放到本网站的编译的目录下
 将xwork的相关链接文件放编译目录下
 将新的ftl链接文件放站点的目录下
 
3.webwork及相关配置文件的自动加载
原来想是重写ConfigurationManager,及ConfigurationProvider,但webwork.properties中的webwork.configuration.xml.reload=true可以很好的解决动态加载xwork.xml的问题
这样管理员可以将模块对应的*-xwork.xml的配置文件用include方法添加到站点的xwork.xml中。并由webwork自动重新加载。
这里的相关配置文件,主要指i18n的国际化配置,同样在webwork.properties中的webwork.i18n.reload=true属性也可以解决
管理员只需要更新最终的i18n的国际化配置文件即可。

 

4.需要注意的问题
上传所有的文件后,要保证是一个完整可运行的站点,可以在原先的系统上开发,然后上传相应的文件
文件名的命名不要与原来的系统中的文件冲突,管理员也可以通过这样的方法替换原有的文件.

 

5.小结
模块:SPRING的配置文件,WEBWORK的总的配置文件名称,模块的名称,描述,页面处理地址,
停用模块:
   删除bean中的SPRING的配置文件,并重新设置ApplicationContext
   删除总站点下的xwork.xml中相关的链接
启用模块:与停用模块相反.
   管理员上传功能模块:
   编译的目录下生成的所有文件,打包上传后,将直接上传到总站点的WEB-INF/classes的目录下面
   FTL的页面文件,将放到站点的WEBAPP下,与WEB-INF处于同一目录.


6.示例  
  如:在bin(站点运行时应在WEB-INF/classes)的目录下面
  com.bbs.RegisterAction2.class及RegisterAction2-validation.xml为后加的东西,对应的配置文件
  spring:bin/test/applicationContext.xml
  xwork:bin/test-plugin-xwork.xml,将这个文件用include进入xwork.xml
  管理员动态修改上面的三个东西(主要是重新加载spring配置,xwork.xml中添加或删除include会自动识别),实现模块的插卸.

gaoqs 2008.2.28

 

com.bbs.PluginObjectFactory代码:

package com.bbs;

import java.util.HashMap;
import java.util.Map;

import ognl.OgnlContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.opensymphony.xwork.ObjectFactory;
import com.opensymphony.xwork.spring.SpringObjectFactory;

public class PluginObjectFactory extends SpringObjectFactory {
 private static final Log log = LogFactory.getLog(PluginObjectFactory.class);

 public static ApplicationContext app;

 public Object buildBean(String beanName, Map extraContext) throws Exception {
  try {
   if (appContext == null) {// 加载默认的初始化
    log.debug("加载getDefaultConfigLocations()中指定的初始化");
    this.setApplicationContext(this.loadDefinedConfigFile(this
      .getDefaultConfigLocations()));
    // this.setApplicationContext(this.loadDefinedConfigFile(this.getDefaultConfigLocations2()));
    this.app = appContext;// static,以便外面的service层调用,appContext的引用
   }
   return appContext.getBean(beanName);
  } catch (NoSuchBeanDefinitionException e) {
   Class beanClazz = getClassInstance(beanName);
   return buildBean(beanClazz, extraContext);
  }
 }

 public ApplicationContext loadDefinedConfigFile(String path[]) {
  ApplicationContext context = new ClassPathXmlApplicationContext(path);
  return context;
 }

 public String[] getDefaultConfigLocations() {// spring的配置文件
  return new String[] { "classpath*:applicationContext.xml",
    "classpath*:applicationContext-*.xml",
    "classpath*:applicationContext-*.xml",
    "classpath*:test/applicationContext.xml" };// 管理员重新修改后,根据配置文件重新生成一个applicationContext,并设置本类,即可.
 }

 public String[] getDefaultConfigLocations2() {// spring的配置文件
  return new String[] { "classpath*:applicationContext.xml",
    "classpath*:applicationContext-*.xml",
    "classpath*:applicationContext-*.xml" };// 管理员重新修改后,根据配置文件重新生成一个applicationContext,并设置本类,即可.
 }
}

需要demo完整源码,及相关问题发我邮箱 gaoqs1984@163.com

 

 

 

转自:http://blog.sina.com.cn/s/blog_50af6d3801008q3f.html

原创粉丝点击