论坛登陆 用户名:  密 码:
设为首页  加入收藏
08年北京名校秋季招生
名牌院校免试入学宽进严出,突破考分限制,名校与你零距离,以下院校按报名先后顺序录取,24小时网上报名覆盖全国
  您现在的位置: 中国教育招生在线 >> IT >> JAVA认证 >> IT正文
专家教您如何避免重启你的应用程序
 作者:佚名     2007-3-14 16:34:50        来源:不详  浏览次数:

 

 

 

 

 

 

 

 

在开发测试阶段,某个功能模块出错或者功能需求改变,这时候程序员通常会修改源代码,然后重新编译,停止应用程序,重起应用程序。然后检测修改得功能是否正确,是否满足需求。很好,这一切在开发测试阶段都没有问题,无可厚非。不过到了应用正式上线就出现麻烦了。

重启应用会导致系统不可用,或者导致用户请求、响应丢失。甚至有的系统本生就要求为系统动态添加功能,在没有为你的应用添加防止重启动的策略前,通常能做的是到凌晨2点趁用户少的时候重启你的应用或者是暂时切换到备份系统。

如果你的系统也遇到过或者将不可避免的遇到这样的问题,那在这篇文章里,几个解决办法可以供你选择使用。

一、在启动前,保存未被处理的请求和未发给用户的响应。较好的方式是将接收请求,发送响应的模块与你处理应用逻辑的模块分开设计。如现在的web服务器,可以在你重新部署(redploy)的时候暂把用户的请求保存到队列,等到部署成功后在提交给处理逻辑的模块。

又如,接收请求,发送响应的模块是不同的应用。与应用逻辑模块之间通过文件(把请求序列化成一个文件)等方式交换数据,这样在你的逻辑应用重启后,仍然可以继续读取请求。

二、如果更新的功能是纯数据的,那么,采用动态配置,避免重启动。比如,一个web系统,提供reloadConfig界面,重新从配置文件里读取数据。一个java应用程序,你可以在你的应用程序里启动一个检测线程,检测文件是否被改变,如果改变,则自动重新转载配置。如下例子:

public ConfigChecker extends Thread
  {
      SystemManager sm = null;
      long time ;
      public ConfigChecker(SystemManager sm)
	  throws ApplicationException
      {
          this.sm = sm;
          time = getConfigFileTime();
      }
      pulblic void run()
      {
          
           while(!interrupted())
           {
                   try
              {
                  long newTime  
				  = getConfigFileTime();
                  if(newTime!=time)
                  {
                      time = newTime;
                      //重新装载配置
                      sm.reloadConfig();
                  
                  }
                  Thread.sleep(1000*3)
              }
              catch(Exception ex)
              {
                  return ;
              }
                   
           }
      }
      
      public long getConfigFileTime()
	  throws ApplicationException
      {
          try
          {
              File f = new File
			  (sm.getConfigFile());
              return f.lastModified()
          }
          catch(IOException ex)
          {
              throw new 
			  ApplicationException
			  (ex.getMessage())
          }
          
      }
  }

这种方式适合你要动态改变的是纯数据,它要求你应用中的数据不能写死在代码里,而是通过文件配置。通过重新从配置文件里读取数据避免重启动

三、如果更新的功能包括应用逻辑,也就是class改变了,那就稍微麻烦点,你需要了解ClassLoader的原理。使用你定制的ClassLoader重新Load已经编译好的class,就好比你重启应用一样。下面将简单介绍ClassLoader原理,以及举出一个例子来说明如何避免重启应用程序。

虚拟机通过Classloader来转载类。bootstrap loader 负责load jdk的class(java.*,javax.*), system class loader是bootstrap的子类,负责load 所有在chasspath指定的变量。ClassLoader将字节流转化为Class类,这些字节流可能来源文件,也可能来源于网络或者数据库。

转化方法是调用ClassLoader提供的final defineClass(className, classBytes, 0, classBytes.length)方法来实现。需要记住的是虚拟机里一个类的唯一标识是通过类的包名+类名+装载此类的ClassLoader。同一个ClassLoader实例只能装载Class一次,重复装载将抛出重复类定义异常。

如下自定义ClassLoader将从classpath里转载指定的类,来说明如上对ClassLoader的介绍,同时,我们用此ClassLoader演示如何避免重启动应用程序

public class DyLoader extends ClassLoader
{
    public DyLoader()
    {
        super(DyLoader.class.getClassLoader());
    }
 
    public Class loadFromCustomRepository
	(String className)
	{
    /**取环境变量*/
    String classPath = 
	System.getProperty("java.class.path");
    List classRepository = new ArrayList();
    /**取得该路径下的所有文件夹 */
    if ( (classPath != null) && ! 
	(classPath.equals("")))
	{
      StringTokenizer tokenizer = 
	  new StringTokenizer(classPath,
          File.pathSeparator);
      while (tokenizer.hasMoreTokens())
	  {
        classRepository.add
		(tokenizer.nextToken());
      }
    }
    Iterator dirs = classRepository.iterator();
    byte[] classBytes = null;
    /**在类路径上查找该名称的类是否存在,
	如果不存在继续查找*/
    while (dirs.hasNext()) 
	{
      String dir = (String)
	  dirs.next();
      //replace '.' in the
	  class name with File.separatorChar &
	  append .class to the name
      String classFileName = 
	  className.replace('.', File.separatorChar);
      classFileName += ".class";
      try {
        File file = new File
		(dir + File.separatorChar + classFileName);
        if (file.exists())
		{
          InputStream is = new FileInputStream(file);
          /**把文件读到字节文件*/
          classBytes = new byte[is.available()];
          is.read(classBytes);
          break;
        }
      }
      catch (IOException ex)
	  {
        System.out.println
		("IOException raised while 
		reading class file data");
        ex.printStackTrace();
        return null;
      }
    }
    return this.defineClass
	(className, classBytes, 0,
	classBytes.length);
	//加载类
  }
 
}

如下调用:

DyLoader loader = new DyLoader();
Class a  = loader.loadFromCustomRepository
("com.lijz.SampleDyService"); 
Class b = loader.loadFromCustomRepository
("com.lijz.SampleDyService");

第三行代码将会抛出:

java.lang.LinkageError: 
duplicate class definition:
com/lijz/SampleDyService

如果如下调用,则一切正常,这是因为你使用新的ClassLoader实例来装载com.lijz.SampleDyService"

DyLoader loader= new DyLoader();
Class a loader.loadFromCustomRepository
("com.lijz.SampleDyService"); 
DyLoader newLoader = new DyLoader();
Class b = newLoader.loadFromCustomRepository
("com.lijz.SampleDyService");


1 2 下一页>>

责任编辑:lss
  相关新闻
专家指点:MCP考试新题型一一剖析
CCIE-互连网络专家 考试疑难解答
专家谈如何准备二级VFP上机考试
专家认为:灰鸽子的危害远远超过熊猫烧香
网上叫卖银行卡复制器 专家称市民无需恐慌
专家讲述J2EE中的多字节字符的处理
教您怎样在Web应用中动态创建PDF文件
台湾J2ME专家王森北京讲座---掌上开发专业研讨
教您怎样部署基于WebSphere的J2EE应用
初学入门:教您如何快速开发Hibernate
专家谈如何准备二级VFP上机考试
专家指点:MCP考试新题型一一剖析
CCIE-互连网络专家 考试疑难解答
专家认为:灰鸽子的危害远远超过熊猫烧香
网上叫卖银行卡复制器 专家称市民无需恐慌
教您如何用Struts向数据库中储存图片
教您怎样部署基于WebSphere的J2EE应用
教您在J2ME中访问dotnet Web Services
教您怎样在Web应用中动态创建PDF文件
速食时代:教您三分钟开发一个J2EE应用
  评论
现在有100人对本文发表评论
查看所有评论
 
推  荐
 
100本成功必读热销书
热门招生
  北京文理研修学院   前进大学
  北京明园大学   北京建设大学
  北京邮电大学世纪学院   北方工商管理学院
  联想软件定向委培班   香港数码动画学院
  青年企业管理研修学院   北京华夏管理学院
热门培训
网络化办公专家培训认证 电子科技大学软件学院
软件测试工程师培训认证 北大青鸟十大授权培训
IT硬件工程师培训认证班 北京环球雅思荷兰预科
JAVA开发工程师培训 潜能时代IT服务管理培训
网络信息化工程师培训 清华大学继续教育学院
论坛精选
 
有些细节是男人也该注意的风度!最容易读错的字
某强人手机里保存的30条短信 中国十大高薪职业
最感人的十大韩剧经典台词 嫁给工程师的N个理由
爆强!只有一句话的鬼故事 转贴教你如何做妖精
 女人一定要記住的話 女人最好别嫁给最爱的男人
城市联盟
 大连 上海 天津 广州 西安 深圳  天津  青岛  大连  福州  沈阳  青海  连云港  南京  吉林  厦门  威海  辽宁  呼和浩特
Copyright © 2006   www.edu999.com   All rights reserved. 中国教育招生在线  版权所有
北京市通信管理局[2004]字第552号函    京ICP证040442号