lijj

构客网首页  博客  论坛

 
  用户信息
 
帐号:  新手必读
密码: 保存密码
 
  分类列表
全部类别(20 篇)
我的文章(20 篇)
  按月归档
2005年-03月(1 篇)
2005年-11月(3 篇)
2006年-09月(2 篇)
2006年-11月(1 篇)
2007年-01月(1 篇)
2007年-11月(2 篇)
2008年-01月(7 篇)
2009年-05月(3 篇)
  SOA2007 - SOA实践
我们何时迈向SOA
——SOA在中国的整体发展现状究竟如何?
我们如何迈向SOA
——中国企业如何迈出实施SOA的第一步?
我们应采用何种技术
——SOA国际标准SCA/SDO的具体内涵?
我们还需要何种技能
——SOA将如何改变系统架构设计以及项目管理过程?

显示第 1-10 条记录,共 20 条记录 首页 前页 后页 尾页  到第 页,共 2

白话解说Spring 容器设计理念

发布时间:2009年05月13日 作者:lijj

阅读次数:1701次 类别:我的文章 永久链接 Trackback 
概述
Spring是为了解决企业应用程序开发复杂性而创建的开源框架,书店上关于Spring的书籍汗牛充栋,网上相关的文章连篇累牍,其中有很多写的很不错的,有入门例子的,有问题解决方案的,有环境设置的,有源代码分析的,有spring与其他开源系统集成的,不一而足。本文通过生活白话,不拘泥于Spring源代码和专业术语的束缚,不拘泥于具体的实现细节,类比介绍Spring容器的宏观的设计理念。
让Spring容器走下神坛
Spring容器提供 Spring 框架的基本功能,是工厂模式的实现。换句话说,Spring就是Bean的工厂,管理Bean的生命周期。那如何来设计呢?Spring源代码虽不说是浩如烟海,也让人头晕目眩,如下图所示,我们让Spring容器走下神坛,既然是面向接口编程,用接口来描述框架,不必拘泥于具体实现可能更清晰些。
任何的设计都是这样,有原料,有入口,有加工,也有出口。既然Spring是Bean的容器,是Bean的工厂,那么生产Bean流程是:
1)        原料:bean的配置文件
2)        进料:通过ResourceLoaderxml文本文件读入
3)        初加工:通过BeanDefinitionReader把原料加工成半成品BeanDefinition
4)        精加工:Bean的生产车间BeanFactory把半成品BeanDefinition加工成Bean
5)        入库:成品库SingletonRegistry保存成品Bean,及Bean的标签(beanId),呵呵!你也知道这就是Map的工作了
 
 
 
IOC是Sprng 核心?关键?
Spring容器使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开,控制反转(IOC)模式是基于java反射的基本原理。
通常的软件设计,肯定把IOC作为容器的核心,其他外围的功能如bean 的Scope都是基于IOC展开,而Spring设计却只把它放如工具类BeanUtil,这正是Spring的高明之处,虽然IOC是Spring的创建bean的基础,但创建一个bean需要判断是否静态工厂创建,是否有含参数的构造方法,而这些参数也可能是其他对象的实例,创建bean的初始化方法等等,这些不仅仅是bean的IOC所能涵盖的,并且在创建一个bean的过程中可能需要多次迭代调用IOC程序。
综上所述,IOC虽然是Spring的创建Bean的基本原理,但仅是及其重要的一部分,并不是Spring容器的核心,是Spring创建bean的比不可少的工具。IOC是Spring容器的关键,而不是核心。
Interface分级设计
接口的分级设计,是针对不同的客户给予不同级别的产品。不同等级的接口关注点也各有不同,就像产品也分为多个级别,如高级产品、中级产品、初级产品分别对应于不同的客户群,或者如同银行的客户渠道有银行卡,柜台,网银,手机终端,ATM机等等。同样接口也分为内部接口和外部接口,就如同有些接口可能永远不被外部用户所知,仅仅是内部使用,就像工厂内部多个车间之间的内部产品。
org.springframework.beans.factory. BeanFactory是Spring的顶级Interface,其中只有getBean系列,containsBean,isPrototype,isSingleton,getType等成品Bean的基本方法。
org.springframework.beans.factory. ListableBeanFactory是Factory的管理方法如containsBeanDefinition,getBeanDefinitionCount,getBeanDefinitionNames,getBeanNamesForType系列,getBeansOfType系列,ListableBeanFactory是针对BeanDefinition半成品的。
而ApplicationContext接口除了集成ListableBeanFactory接口外,还继承了ResourcePatternResolver,HierarchicalBeanFactory,ApplicationEventPublisher,MessageSource的功能,如在资源处理(国际化处理),事件传递,及各应用层之间的context实现。同样是对外的接口,Spring更建议采用ApplicationContext的原因也就在这儿,ApplicationContext更像是针对VIP客户的产品。
 
  
 
  
 
Interface扩展设计
       Spring设计是开放性的设计思路,是值得我们做架构设计人员学习的,如下图所示:
com.springframework.beans.factory
(淡黄色背景)
|BeanFactory
|ListableBeanFactory
|ConfigrableListableBeanFactory
|DefaultListableBeanFactory
 
 
com.springframework.context
(棕红色背景)
ApplicationContext
                                           ConfigrableApplicationContext     
 
 
org.springframework.context
(黄色背景)
.support
AbstractApplicationContext
                               AbstractRefreshableApplicationContext
                               AbstractXmlApplicationContext
                               ClassPathXmlApplicationContext
 
org.springframework.web.context
(绿色背景)
WebApplicationContext
                            ConfigrableWebApplicationContext
 
org.springframework.web.context
(浅蓝色背景)
.support
AbstractRefreshableWebApplicationContext
                                  XmlWebApplicationContext
 
 
  
  
 
  
总结如下:
1) 不同的包下面放不同的东西,好像是废话啊!上层包放接口,下层包放实现的抽象类及实体类。如contex.support包下面放实现context包下面的接口的抽象类及实现类。
2) 为了适应WEB级别的ApplicationContext,创建了WebApplicationContext的接口,该接口继承了ApplicationContext,又添加了WEB层的个性化方法如getServletContext及属性。现在终于明白了在接口间的“extends”的含义,绝对是对上层接口的“扩展“,扩展的目的是适应更具体化的环境。就如同因为国家大,情况复杂,中央的政策相对都是比较抽象的,而地方政策必须结合地方的特色,既要满足中央政策的要求,即实现中央政策的接口,又要根据本地特殊情况,扩展个性化的政策,即地方政策接口,从而更具有可操作性。
3) org.springframework.web.context.support.AbstractRefreshableWebAppplicationContext类是既实现了ConfigrableWebApplicationContext接口,即实现WEB的个性化特色,又继承了org.springframework.context.support.AbstractRefreshableApplicationContext类。借助了已有的类,实现了架构上的复用,这就像制定政策既要满足地方上的特色,又可以参照其他地区现成的政策经验。呵呵!在实际工作中,也会常常有这样的设计。
 
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
联系作者:lijj_72@hotmail.com

Spring 模板方法 vs 经典模板方法设计模式

发布时间:2009年05月12日 作者:lijj

阅读次数:2293次 类别:我的文章 永久链接 Trackback 
概述
模板方法模式是GOF设计模式中很典型的设计模式,其意图是由抽象父类控制顶级逻辑,并把基本操作的实现推迟到子类去实现,这是通过继承的手段来达到对象的复用。Spring模板方法模式实际是模板方法模式和回调模式的结合,Spring几乎所有的外接扩展都采用这种模式,如JNDI,JMS,JCA的 CCI,JDBC,ORM中的Hiberate3、jdo、Toplink等扩展都采用模板方法模式来扩展。
 
经典的模板方法设计模式
开闭原则是指一个软件实体应该对扩展开放,对修改关闭。先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。如图所示,面向接口编程,client只需调用Template接口中的execute方法,在AbstractTemplate抽象类的示例代码所示,实现execute()方法,但在execute()方法中制定所需的大的步骤,调用如subExecute1(),subExecute2(),subExecute3()方法来完成,但AbstractTemplate抽象类把subExecute1(),subExecute2()设置为抽象方法,由子类来实现,subExecute3()给出了缺省实现,也可由子类来覆盖,如SubTemplateImpl2类。
 
 
public abstract class AbstractTemplate implements TemplateInterface
{
       public void execute()
       {
              subExecute1();
              subExecute2();
              subExecute3();
       }
       protected abstract void subExecute1();
       protected abstract void subExecute2();
       protected void subExecute3()
       {
 
       }
 
}
 
在Spring中也有对经典模板方法模式的运用,以Hibernate3为例说明
AbstractSessionFactoryBean模板方法afterPropertiesSet(),调用抽象方法buildSessionFactory()和缺省实现方法afterSessionFactoryCreation()

publicvoid afterPropertiesSet() throws Exception {
       SessionFactory rawSf = buildSessionFactory();
       this.sessionFactory = wrapSessionFactoryIfNecessary(rawSf);
       afterSessionFactoryCreation();
    }
protectedabstract SessionFactory buildSessionFactory() throws Exception;
    protectedvoid afterSessionFactoryCreation() throws Exception {
    }

在其子类中LocalSessionFactoryBean中则有相关子步骤方法的实现

protected SessionFactory buildSessionFactory() throws Exception {
     … … //代码太长了
    return newSessionFactory(config);
}
protectedvoid afterSessionFactoryCreation() throws Exception {
       if (this.schemaUpdate) {
           DataSource dataSource = getDataSource();
           if (dataSource != null) {             
              configTimeDataSourceHolder.set(dataSource);
           }
           try {
              updateDatabaseSchema();
           }
           finally {
              if (dataSource != null) {
                  // Reset DataSource holder.
                  configTimeDataSourceHolder.set(null);
              }
           }
       }
    }

Spring模板方法模式的运用
Spring几乎所有的外接扩展,都采用模板方法模式,为了说明的更清楚些,用Hiberate3的扩展举例说明。
回调函数接口HibernateCallback
HibernateCallback接口,在该接口中只声明了一个方法doInHibernate(Session session),这个方法其实是由子类来实现的子步骤方法
publicinterface HibernateCallback {
    Object doInHibernate(Session session) throws HibernateException, SQLException;
}
模板方法类HibernateTemplate的模板方法execute()
HibernateTemplate类的execute()方法,值得注意的是execute()方法的一个参数是HibernateCallback接口,这就是Spring模板方法模式的核心和前提,为了清楚模板方法模式,把相关的事务处理及异常处理等代码去掉,这样可以清楚地看出HibernateCallback接口的action.doInHibernate(sessionToExpose)仅仅是其中的一个步骤,并且action就是execute模板方法方法的第一个参数HibernateCallback接口的实际实现类。
public Object execute(HibernateCallback action, boolean exposeNativeSession) throws DataAccessException {       
              previousFlushMode = applyFlushMode(session,existingTransaction);
           enableFilters(session);
           Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));
           Object result = action.doInHibernate(sessionToExpose);
           flushIfNecessary(session, existingTransaction);
           return result;
      
    }
模板方法类HibernateTemplate的其他对外方法的匿名类方法实现回调
在HibernateTemplate类中实现HibernateCallback接口的却是匿名类,如get方法
public Object get(final String entityName, final Serializable id, final LockMode lockMode)
           throws DataAccessException {
 
       return execute(new HibernateCallback() {
           public Object doInHibernate(Session session) throws HibernateException {
              if (lockMode != null) {
                  return session.get(entityName, id, lockMode);
              }
              else {
                  return session.get(entityName, id);
              }
           }
       }, true);
    }
如load方法
public Object load(final Class entityClass, final Serializable id, final LockMode lockMode)
           throws DataAccessException {
 
       return execute(new HibernateCallback() {
           public Object doInHibernate(Session session) throws HibernateException {
              if (lockMode != null) {
                  return session.load(entityClass, id, lockMode);
              }
              else {
                  return session.load(entityClass, id);
              }
           }
       }, true);
    }
从get(),load()方法中可以看出其实现HiberateCallback接口的方法都很简单,都是封装Hiberate的session的同名方法。这样有效地减少了子类的个数(如LoadHibernateCallback,GetHibernateCallback,同时当你调用get(),load()方法时要先new或者配置好相应的子类),这时候使用匿名类来实现回调则很方便。
Client来调用get方法,get方法调用模板方法时,就先塞进去一个匿名子类作为参数,由匿名子类来完成相关的子步骤的逻辑,通过模板方法回调匿名子类的方法来实现模板方法模式。
Spring模板方法模式扩展
Spring模板方法的扩展,不像经典的模板方法模式那样需要继承模板方法抽象类,而是通过实现回调函数HibernateCallback 接口的doInHibernate方法的匿名类作为参数,直接调用HibernateTemplate的execute()模板方法,这样其实也是Spring的无侵入设计思想的体现,同时也是“依赖优于继承”设计理念的体现。
public Object sqlExecute(String sql)
{
       return getHibernateTemplate().execute(new HibernateCallback(){
              public Object doInHibernate(Session session)
              {
                     //write youself business logic, using your parameters certainly.
                     return null;
              }
      
       }, true);
}
 
Spring模板方法设计模式的适用范围
Spring模板方法设计模式适用于模板类有很多方法,如HibernateTemplate,数据库操作使用的如此频繁,一个操作就需要通过继承一个子类,这显然不可能,这时使用经典的模板方法模式则显笨重。Spring使用Callback模式与模板方法模式配合,既达到了代码复用的效果,同时增加了灵活性,只需实现某些CallBack就可轻松订制Template。
经典的模板方法设计模式适用于如果每个具体的步骤都需要真正去具体实现,而不是简单的改变参数或设置某个对象就ok的话,使用Callback很难去订制,因为你可能需要传递多个Callback作为参数,并让用户去实现,使用Java的内部类本来就是一个比较丑陋的语法,更何况参数是多个。
 
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
联系作者:lijj_72@hotmail.com

数据权限设计初探

发布时间:2009年05月12日 作者:lijj

阅读次数:706次 类别:我的文章 永久链接 Trackback 
概述
在许多项目中,都会涉及到数据权限问题,所谓数据权限是表示,在系统中即使角色相同,都有操作权限,但业务操作时受风险、额度、销售区域等业务属性限制。
如销售人员可以看到自己的销售列表,而销售经理可以看到其管辖范围内的销售人员的销售列表,而高级销售经理能看到其下辖的销售经理的销售列表,更进一步,只看金额超过1000万的单子,小于1000万的单子不看。如销售人员是销售产品的,但由于产品属性的不同,如产品属性中销售地区在“苏杭地区”,则北京地区的销售人员则不能销售。如产品属性中风险属性高,则销售人员的级别也要求高,则低级别的销售人员则不能销售该产品;进一步来讲,随着时间或形势的发展,该种产品的风险并没有那么大,低级别的销售人员也可以销售;或者该种产品低级别的销售人员销售该种产品的金额小于100w,而高级别的人员销售100w等等。
架构分析及设计
在设计之初就确定了数据权限所处的位置,和操作权限类似,操作权限一般是放在MVC的controller层,作为插件来控制是否有操作权限。数据权限也可以这样设计,但数据权限更多地是和业务逻辑纠缠在一起,因此数据权限可以作为插件放在业务层(Model),更优雅的设计是以模板模式在业务缺省实现基类中,作为过滤。如下图所示,BizClass其实代表业务层的复杂设计,在做分析设计的过程中,我的经验是尽最大可能理解需求,并尽最大可能直白地把需求展现出来,而不是在设计之初先定义什么设计模式,设计模式是在搞清楚需求并能够给出较完整的设计思路后才考虑的。当然,在设计之初也要首先定义其所在软件架构的位置。
     从需求方面讲,要达到根据操作人就能够给出该操作人的数据权限,包括查询的详细程度及数据操作规则等。从这儿我们就可以分析出来要获取数据权限,有两个参数userId,
bizName。
其实任何业务需求的设计的途径都是类似的,都是“来料加工”,有原材料,有目标成品,然后把原材料加工成目标成品。当然在其中要考虑很多因素,面向对象的设计思想很重要,不要在设计之初就考虑要多少个表,表之间的关联关系,什么一对多,多对多,关联表。首先要考虑需要业务上有那些需求,这些业务功能如何转变成某些用例,这些用例是如何转换成若干的业务类,这些类有那些属性或方法来实现这些业务功能。而表仅仅是某些实体类的数据存储,不能表现为业务逻辑。也很难体现设计者的思路。
 
 
组织机构与(岗位VS角色)
系统设计中,往往会把操作权限和数据权限混为一谈,使用角色权限来控制,这其实就走入了误区,因为操作权限是解决能不能做的问题,数据权限是解决做多大幅度问题。因为角色是没有级别概念的,也就是说没有上下级概念的。
因此在计了“岗位”的概念,岗位是分级别的,且上下级汇报关系的,在这儿还设计了区域(region)属性,是基于某些需求需要,这样设计是基于有些公司的管理是分为矩阵式管理,既有部门,也根据产品线分为事业群管理的。
如下图所示,组织机构是分上下级的,组织机构中包含若干岗位,因工作职责定岗,用户是属于某个岗位的。这就和原来的设计中组织机构和人的关系中增加了岗位的中间层,也就是说,组织机构中只包含其业务中需要设置的岗位,这些岗位由人员来充实,换句话说,组织机构中不养闲人,呵呵!
岗位中一个重要的概念是资源管理,为了简化设计,某一个岗位只是为处理单一的某个业务所设置的,其中bizes属性表示该岗位所涉及的业务有若干的资源。
 
业务资源与数据权限规则
这组类的主要功能是完成原材料的准备及数据规则与岗位的映射,其中并没有实体类参与,这些类背后需要数据的支撑,到这时再考虑数据存储不迟。例如BizDatRuler后面就需要实体类,可能是多个相关表的数据。
类Resource中包含多个产品的数据权限规则,在ProductInfo其中dataRulers表示(key=positionGrades value=BizRuler),在类BizDataRuler 属性positionGrades 如:3,4,5,6,以逗号分隔,表示某个规则适用与某些级别的岗位,属性productRulers的HashMap<String productAttr,String scope>,其中scope中关于数字范围用“[()]”表示,“[”表示大于等于,“(”表示大于,“)”表示小于,"]"表示小于等于,如“[300,550)”表示大于等于300,小于500。如果是散列数,用“{}”表示,如“{30,50,70}”表示只有属性等于30,40,50的才有数据权限,如“{上海,苏州,杭州}”在表示只在上海,苏州,杭州有效。这就类似与格式化文本的处理方式,简化了文本解析。
   
 
 
附录:数据权限模块设计类图:
 
 
 
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
联系作者:lijj_72@hotmail.com

JPA 与 Websphere的兼容性问题解决方案

发布时间:2008年09月18日 作者:lijj

阅读次数:548次 类别:我的文章 永久链接 Trackback 
考虑到OR映射的产品多样化,为了更富有柔性化的设计,我们的产品采用JPA作为Persistence layer的持久化技术,hibernate3.2(hibernate3.2才支持JPA),spring2.0作为IOC和AOP的工具。产品的运行环境为Websphere6.1(因为我们的产品是基于jdk1.5)。JPA(Java Persistence API)作为Java EE 5.0平台标准的ORM规范,得到所有Java EE服务器的支持,是一个易于使用、伸缩性强的ORM规范。目前Hibernate 3.2、TopLink 10.1.3以及OpenJpa都提供了JPA的实现。
概述
考虑到OR映射的产品多样化,为了更富有柔性化的设计,我们的产品采用JPA作为Persistence layer的持久化技术,hibernate3.2(hibernate3.2才支持JPA),spring2.0作为IOC和AOP的工具。产品的运行环境为Websphere6.1(因为我们的产品是基于jdk1.5)。JPA(Java Persistence API)作为Java EE 5.0平台标准的ORM规范,得到所有Java EE服务器的支持,是一个易于使用、伸缩性强的ORM规范。目前Hibernate 3.2、TopLink 10.1.3以及OpenJpa都提供了JPA的实现。
错误信息
org.springframework.beans.factory.BeanCreationException: Error creating bean with name "entityManagerFactory" defined in ServletContext resource [/WEB-INF/context/rdf/applicationContext-dao.xml]: Invocation of init method failed; nested exception is java.lang.ArrayStoreException
错误原因
这个错误是IBM JVM 的bug,同样的程序在tomcat5.5,和jboss4.03上都没有问题,迁移到WebSphere上就有如上的错误。
解决方案
下载WebSphere软件升级包,升级Websphere。
下载Websphere升级软件
地址:http://www-1.ibm.com/support/docview.wss?rs=180&uid=swg24012718  ,下载download.updii.61017.windows.ia32,可以根据具体的操作环境和Websphere版本下载相应的升级软件。
下载支持操作系统及sdk的补丁
地址:http://www-1.ibm.com/support/docview.wss?rs=180&uid=swg27007951,下载操作系统的补丁:6.1.0-WS-WAS-WinX32-FP0000017.pak,根据具体的操作系统下载相应的补丁;
下载sdk补丁:6.1.0-WS-WASSDK-WinX32-FP0000017.pak。也要根据具体的操作系统和sdk要求来下载。
升级Websphere
升级WebSphere,这儿是使用Windows的升级程序来作为例子。
1) 解压并到download.updii.61017.windows.ia32\UpdateInstaller目录下,点击install.exe
点击next,选中I accept选项
校验此升级软件是否支持该操作系统
输入WebSphere安装地址
下面的地址你不用修改,是升级软件自动给出的,升级软件会创建这个目录并把相关需要的文件copy到该目录下。
确认升级包安装地址及大小。
创建升级目录并把相关文件copy到该目录下
升级软件copy文件结束
2) 点击finish,则开始安装具体的升级包
输入要升级的WebSphere的AppServer目录
默认选择安装升级包
输入那两个升级补丁所在的位置,最好把这两个升级包copy到如图的目录下
选择两个需要升级的包
确认升级包和升级的应用服务器
开始升级
升级成功结束
 
这样重新启动WebSphere,应用系统正常运行。
 
 
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
   
联系作者:lijj_72@hotmail.com

JPA 与 Websphere的兼容性问题解决方案

发布时间:2008年09月11日 作者:lijj

阅读次数:1088次 类别:我的文章 永久链接 Trackback 
考虑到OR映射的产品多样化,为了更富有柔性化的设计,我们的产品采用JPA作为Persistence layer的持久化技术,hibernate3.2(hibernate3.2才支持JPA),spring2.0作为IOC和AOP的工具。产品的运行环境为Websphere6.1(因为我们的产品是基于jdk1.5)。JPA(Java Persistence API)作为Java EE 5.0平台标准的ORM规范,得到所有Java EE服务器的支持,是一个易于使用、伸缩性强的ORM规范。目前Hibernate 3.2、TopLink 10.1.3以及OpenJpa都提供了JPA的实现。
概述
考虑到OR映射的产品多样化,为了更富有柔性化的设计,我们的产品采用JPA作为Persistence layer的持久化技术,hibernate3.2(hibernate3.2才支持JPA),spring2.0作为IOC和AOP的工具。产品的运行环境为Websphere6.1(因为我们的产品是基于jdk1.5)。JPA(Java Persistence API)作为Java EE 5.0平台标准的ORM规范,得到所有Java EE服务器的支持,是一个易于使用、伸缩性强的ORM规范。目前Hibernate 3.2、TopLink 10.1.3以及OpenJpa都提供了JPA的实现。
错误信息
org.springframework.beans.factory.BeanCreationException: Error creating bean with name "entityManagerFactory" defined in ServletContext resource [/WEB-INF/context/rdf/applicationContext-dao.xml]: Invocation of init method failed; nested exception is java.lang.ArrayStoreException
错误原因
这个错误是IBM JVM 的bug,同样的程序在tomcat5.5,和jboss4.03上都没有问题,迁移到WebSphere上就有如上的错误。
解决方案
下载WebSphere软件升级包,升级Websphere。
下载Websphere升级软件
地址:http://www-1.ibm.com/support/docview.wss?rs=180&uid=swg24012718  ,下载download.updii.61017.windows.ia32,可以根据具体的操作环境和Websphere版本下载相应的升级软件。
下载支持操作系统及sdk的补丁
地址:http://www-1.ibm.com/support/docview.wss?rs=180&uid=swg27007951,下载操作系统的补丁:6.1.0-WS-WAS-WinX32-FP0000017.pak,根据具体的操作系统下载相应的补丁;
下载sdk补丁:6.1.0-WS-WASSDK-WinX32-FP0000017.pak。也要根据具体的操作系统和sdk要求来下载。
升级Websphere
升级WebSphere,这儿是使用Windows的升级程序来作为例子。
1) 解压并到download.updii.61017.windows.ia32\UpdateInstaller目录下,点击install.exe
点击next,选中I accept选项
校验此升级软件是否支持该操作系统
输入WebSphere安装地址
下面的地址你不用修改,是升级软件自动给出的,升级软件会创建这个目录并把相关需要的文件copy到该目录下。
确认升级包安装地址及大小。
创建升级目录并把相关文件copy到该目录下
升级软件copy文件结束
2) 点击finish,则开始安装具体的升级包
输入要升级的WebSphere的AppServer目录
默认选择安装升级包
输入那两个升级补丁所在的位置,最好把这两个升级包copy到如图的目录下
选择两个需要升级的包
确认升级包和升级的应用服务器
开始升级
升级成功结束
 
这样重新启动WebSphere,应用系统正常运行。
 
 
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
   
联系作者:lijj_72@hotmail.com

PureMVC软件架构分析与鉴赏

发布时间:2008年08月06日 作者:lijj

阅读次数:789次 类别:我的文章 永久链接 Trackback 1条评论
概述
随着客户端程序的风起云涌,Adobe公司收购了Macromedia公司,针对Flesh的客户端进行研发,推出了Flex语言。Flex语言是类似与java的面向对象语言,编码格式又吸收了Delphi的编码风格,尽管Flex可以展现Flesh的炫目的客户端效果,全新的用户体验,但针对企业化的应用,仅有Flex是远远不够的,需要有合理的软件架构规范,于是Flex世界的MVC框架就应运而生了,PureMVC是Flex世界中的MVC模式的具体实现,相对于adobe官方的Cairngorm的Flex MVC框架,PureMVC更加简单实用。
PureMVC的整体架构
从使用者角度上讲,PureMVC设计的非常合理,对外的接口是Façade,由Façade来组织整个应用,其命名规范也显而易见,可以望文生义。其中Controller,Model,View是管理ICommand,IProxy,IMediator的容器,而ICommand,IProxy,IMediato是应用系统要扩展的MVC各层的接口。
这样,使用者就可以方便地扩展Façade,Command,Proxy,Mediator,来完成MVC各层的功能,没有特殊的需要,一般无需关注Model,View,Controller核心代码。
PureMVC的分层设计理念
PureMVC的各个层次各负其责,Façade实现统一管理,定义了系统的统一接口,使用者无需了解底层代码的运作方式。 Model层是实现与后台交互的层次,由Model类来管理Proxy,当然在Flex中也支持直接访问数据库,但大多数业务系统中,都是Flex作为客户端程序,而后台由Java或者.net来完成真正的业务操作。View层是显示层,在PureMVC中由Mediator实现对Viewcomponent的操作,如界面的简单校验等功能。Controller层是控制层,主要来处理一些数据转换等工作。下面具体介绍各层的具体功能及设计
Façade,外部应用的接口界面
从下图可以看出,Façade是对外的接口,同时管理Model,View, Controller,同时Façade是singleton。
1)在Java中实现singleton模式,构造方法都使用private方法,而这儿使用了public,但看第一句代码,呵呵!效果是一样的。但最好不要直接调用这个public方法
public function Facade( ) {
                     if (instance != null) throw Error(SINGLETON_MSG);
                     instance = this;
                     initializeFacade();   
              }
2)模板模式的应用
protected function initializeFacade( ):void {
                     initializeModel();
                     initializeController();
                     initializeView();
              }
在Façade的构造方法中使用了模板模式,虽然Façade本身也实现了这些初始化方法,但都是获得Model,Controller,View,在具体应用中就可以initializeController()这三个方法,来注册相关的Proxy,Command,Mediator等。注意,实际上override initializeController()方法是比较常见的,而不常override initializeModel()和initializeView(), 最常见的是在Command的execute()中创建并注册Proxy,或者创建并注册Mediator。
3)如下的IFacade接口中,其中的Proxy,Command,Mediator管理方法都是借助于Model,Controller,View的管理方法来实现的。
4)Façade是实现INotifier接口的,所以Façade可以向系统发出消息或者通知,因为Flex是客户端的程序语言,其调用方式也是类似与Windows方式的观察者(observer)模式,Façade是统一的接口界面,所以几乎所有的外部调用都是通过sendNotification()方法。这个方法的调用的是notifyObservers()方法,而这个方法是如下的:
public function notifyObservers ( notification:INotification ):void {
                     if ( view != null ) view.notifyObservers( notification );
              }
通常你只需要调用sendNotification()。
下面具体介绍PureMVC的MVC各层的架构设计:
Model与 Proxy
1)如上所述,Model也是Singleton设计模式,也无需使用new的方式创建,另外在企业应用中也很少直接扩展这个类,如果需要扩展,可以扩展initializeModel(),就相当于对Model的扩展了。
public function Model( )
              {
                     if (instance != null) throw Error(SINGLETON_MSG);
                     instance = this;
                     proxyMap = new Array();    
                     initializeModel();    
              }
2)Model是管理Proxy的容器类,使用类似与Java中的HashMap的数据类Array,来管理Proxy,代码类似:
protected var proxyMap : Array;
proxyMap[ proxy.getProxyName() ] = proxy;
包括后面谈到的Controller及View,都是这样管理其对象的,如获取某个值对象,
return proxyMap[ proxyName ];//简单吧,呵呵!
3)在registerProxy()和removeProxy()方法中,分别调用了Proxy的onRegister(),onRemove()方法,看到这儿,你是不是感到很熟悉。onXxxx()的命名规则,表示由子类实现详细内容来override父类的内容。抽象的原则是:共性化的东西向上(父类)抽象,个性化的东西向下(子类)延伸。即在实际应用中Proxy的onRegister(),onRemove()这两个方法是用来扩展我们自己的功能代码的。
Model:
public function registerProxy( proxy:IProxy ) : void
            {
                   proxyMap[ proxy.getProxyName() ] = proxy;
                   proxy.onRegister();
            }
Proxy:
public function onRegister( ):void {}
4)Proxy是我们要扩展的类,可以看出Proxy类实现了数据的交互,setData()和getData()方法实现数据的装载和获取,onRegister( )和onRemove( )可以实现相关Proxy注册和注销时的功能。
5)proxyName,是唯一表示系统中这个Proxy的名称,如上所述,Model管理Proxy是依赖类似与Java中HashMap的Array,所以必须是key->value(名值对),类似这样的设计还包括Mediator,Command,Façade等。
6)Proxy还实现了INotifier接口,所以也可以向外发送通知(消息),后面会具体讲解观察者模式在Flex中的广泛应用。
7)Proxy继承了Notifier类,在Notifier类中有Protected属性façade,这个Façade是系统中单例,所以可以通过这个Façade来注册相关的Mediator。
View与 Mediator
1)类似于Model ,View是管理Mediator的容器类,但View除了管理Mediator以外,还管理Observer,后面会专门讲Observer,其他如Mediator,Command,Proxy,Façade对Observer的注册都最终到View中来管理。
2)View作为管理Mediator和Observer的容器,利用的就是Flex的Array对象,Array对象如上面所说的Java的HashMap,也类似与Java中的Stack,其有push(), pop()等方法,
public function registerObserver ( notificationName:String, observer:IObserver ) : void
              {
                     var observers:Array = observerMap[ notificationName ];
                     if( observers ) {
                            observers.push( observer );
                     } else {
                            observerMap[ notificationName ] = [ observer ];
                     }
              }
这儿使用了push()方法,可以看出和Java 的HashMap的差异,HashMap是key/value,而Flex Array中一个key,可以对应多个Value,事实上是一个通知(消息),对应多个观察者(1..n)。
3)Mediator作为应用中要扩展的对象,被View容器管理,根据Flex的Array特性,每个Mediator必须有唯一的名称mediatorName,作为key,保存在Array中,同样Mediator也是继承了Notifier类,这样拥有Façade protected属性,可以注册相关Command,Proxy;同时又实现了INotifier接口,可以向外发送通知(消息)。
4)Mediator作为容器来管理ViewComponent,这样就可以把方便地控制界面展现。
Controller与 Command
1) 类似于Model和View,Controller也是Command的容器,通过Flex的Array来管理Command,同时Controller也是单例模式。
2) 在Command管理中,涉及到Observer监听的问题。
public function registerCommand( notificationName : String, commandClassRef : Class ) : void
              {
                     if ( commandMap[ notificationName ] == null ) {
                            view.registerObserver( notificationName, new Observer( executeCommand, this ) );
                     }
                     commandMap[ notificationName ] = commandClassRef;
              }
从这儿可以看出,凡是需要提供Observer监听功能的,都需要通过View来注册。
3) 的执行方法,即当Command被通知时,是调用Command的execute方法Command
public function executeCommand( note : INotification ) : void
              {
                     var commandClassRef : Class = commandMap[ note.getName() ];
                     if ( commandClassRef == null ) return;
 
                     var commandInstance : ICommand = new commandClassRef();
                     commandInstance.execute( note );
              }
4) 与SimpleComman都实现了ICommand接口,其中MacroCommand实现了对ICommand的递归调用,这儿采用了类似于树的设计。MacroCommand
public final function execute( notification:INotification ) : void
              {
                     while ( subCommands.length > 0) {
                            var commandClassRef : Class = subCommands.shift();
                            var commandInstance : ICommand = new commandClassRef();
                            commandInstance.execute( notification );
                     }
              }
其中subCommands就是一个Command数组。
5) 可以在protected function initializeMacroCommand():void中做如下扩展
override protected function initializeMacroCommand( ) : void
                            {
                            addSubCommand( com.me.myapp.controller.FirstCommand );
                            addSubCommand( com.me.myapp.controller.SecondCommand );
                            addSubCommand( com.me.myapp.controller.ThirdCommand );
                            }
这样,当Command初始化时就会来调用这个方法,因为你加入到Command数组中可能是SimpleCommand,那在执行时就直接执行它的execute方法,如果你加入的是MacroCommand对象,则执行MacroCommand的execute的递归方法。
 
观察者模式的应用
1)在PureMVC中大量使用了Notifier来完成发通知(消息)的机制,类似与java的调用,但和java的直接调用不同,是依赖观察者模式来实现的。
2)在Observer类中实现了设置上下文(调用哪个类?)和设置处理通知(消息)方法,这样一旦有消息发出,则捕获该消息,调用相应的类的某个方法来响应这个消息。
public function Observer( notifyMethod:Function, notifyContext:Object )
              {
                     setNotifyMethod( notifyMethod );
                     setNotifyContext( notifyContext );
              }
这个构造方法来初始化哪个类的那个方法来响应消息,就相当于把某个类封装到Observer内部。
3)如何来应用呢?我们来看Controller类中关于注册Command的一段代码
view.registerObserver( notificationName, new Observer( executeCommand, this ) );
View作为系统内部的唯一实例,来注册Observer,第一个参数是要响应的通知名称(如“Login”),第二个参数是创建一个Observer对象,该对象封装了响应的类是this(Controller)的方法“executeCommand”,而executeCommand方法从参数INotification中获取通知的名称,再根据名称从Controller中找到相应的Command来执行它的execute方法。
调用例子简介
上面讲了Observer的基本原理,为了更清晰地表现观察者模式的调用,如下图所示,调用的流程如下:
1) 创建ActionFacade的实例_facade,ActionFacade是Façade的实现类,并注册相关的Command,如在观察者模式讲到的,把相关的Command封装到Observer中,并注册到View内,其响应的通知名称为“login”
override protected function initializeController( ) : void
        {
            super.initializeController();
                    
            registerCommand( STARTUP, StratCommand );
            this.registerCommand( LOGIN, LoginCommand );
          
        }
2) 调用_facade.login(user)
public function login( user:UserVo ):void
        {
               sendNotification( LOGIN, user );
        }
3) 实际上是调用父类Façade的sendNotification方法
public function sendNotification( notificationName:String, body:Object=null, type:String=null ):void
              {
                     notifyObservers( new Notification( notificationName, body, type ) );
              }
而Façade方法notifyObservers
public function notifyObservers ( notification:INotification ):void {
                     if ( view != null ) view.notifyObservers( notification );
              }
也就是说要调用View的notifyObservers方法
4) 的notifyObservers方法如下,遍历所有关注这个通知(名称)的Observer,依次执行这些Observer的notifyObserver方法。View
   public function notifyObservers( notification:INotification ) : void
              {
                     if( observerMap[ notification.getName() ] != null ) {
                            var observers:Array = observerMap[ notification.getName() ] as Array;
                            for (var i:Number = 0; i < observers.length; i++) {
                                   var observer:IObserver = observers[ i ] as IObserver;
                                   observer.notifyObserver( notification );
                            }
                     }
              }
5) 下面来看Observer的notifyObserver方法
public function notifyObserver( notification:INotification ):void
              {
                     this.getNotifyMethod().apply(this.getNotifyContext(),[notification]);
              }
这个方法很简单,获取这个Observer封装的响应通知的方法(如exectue()),并把对应的上下文(如Controller),和通知作为参数来执行,呵呵!很像java中的反射机制。
6) 如在观察者模式的应用中讲到的,执行了Controller的executeCommand方法,从而遍历Command数组,找到响应这个通知的Command(如LoginCommand),并执行这个Command的exectue方法。
总结
PureMVC相对来说,比较简单,对于初学者来说比较容易理解和应用,也可以作为学习设计模式的简易教材。同时作为Flex的框架性代码,从另外的角度可以学习Flex编程思想及设计思路。
 
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
   
联系作者:lijj_72@hotmail.com

航海日志(2) ----from Oracle to DB2

发布时间:2008年05月28日 作者:lijj

阅读次数:920次 类别:我的文章 永久链接 Trackback 
---DB2锁表及 ResultSet Closed
 
                                李俊杰
概述
我们原有的系统是架构在Oracle数据库服务器之上的,现在要迁移到DB2数据库服务器上,Websphere作为应用服务器。在原有的系统中后来集成了工作流系统,该工作流系统的持久层是使用Hibernate,这就造成工作流使用工作流系统的数据库连接,而业务系统使用Type4的数据库连接。在迁移过程中发现锁表现象,修改Hibernate的配置文件后,在本地的jboss服务器上没问题(程序员在本地使用的是jboss服务器),但在websphere服务器上调用工作流时出现“result set closed”的错误。下面我将详细介绍其原因及解决方案。
DB2数据库锁表
锁表问题现象及原因分析
数据库操作几次即出现锁表现象,无法继续操作,分析log得出锁表信息“LOCK_ESCALATION”和“LOCK TIMEOUT”等字眼,就可以肯定是锁表了。我们又分析了我们的系统,发现业务系统使用的是Type4数据源连接数据库,而hibernate.cfg.xml文件中定义的是JDBC连接,所以出现了锁表现象。
<property name="connection.driver_class">com.ibm.db2.jcc.DB2Driver</property>
  <property name="connection.url">jdbc:db2://10.10.19.169:50000/sinochem</property>
  <property name="connection.username">db2admin</property>
  <property name="connection.password">db2admin</property>
而业务系统使用的数据库连接的定义是在oracle-ds.xml这样的:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
 <local-tx-datasource>
    <jndi-name> jdbc/cpf/type4</jndi-name>
    <connection-url>jdbc:db2://10.10.19.169:50000/sinochem</connection-url>
    <driver-class>com.ibm.db2.jcc.DB2Driver</driver-class>
    <user-name>db2admin</user-name>
    <password>db2admin</password>
    <min-pool-size>3</min-pool-size>
    <max-pool-size>6</max-pool-size>
    <idle-timeout-minutes>5</idle-timeout-minutes>
 </local-tx-datasource>
</datasources>
应用服务器在启动的过程中,通过servlet把该文件的内容读入内存,并使用了JDBC的连接。
锁表解决方法
<property name="connection.datasource">java:comp/env/jdbc/cpf/type4</property>
其中“jdbc/cpf/type4为数据源名称,这样业务系统和工作流系统采用统一的数据源,则解决了锁表问题。这样的解决方法jboss上面是没有问题的,因为jboss上使用的是本地的配置文件oracle-ds.xml创建的数据源。
Websphere问题(result set closed)原因分析
当我们的系统部署到Websphere上,并配置JNDI为“jdbc/cpf/type4的数据源,在调用工作流(工作流后台是Hibernate)时出现“com.ibm.db2.jcc.b.SqlException: Invalid operation: result set closed
”,根据网上的资料说是ResultSet嵌套调用,但我们分析代码,并没有出现ResultSet嵌套调用的可能性,又采用了其他方式证明了Hibernate是调用的Websphere配置的数据源。最后发现是DB2的JDBC驱动存在bug,原因是多线程运行的线程安全问题,Statement与ResultSet共享线程引起的问题,正常情况下如果使用Statement执行完一个查询,又去执行另一个查询时这时候第一个查询的结果集就会被关闭,也就是说,所有的Statement的查询对应的结果集是一个,如果调用Connection的commit()方法也会关闭结果集。可保持性就是指当ResultSet的结果被提交时,是被关闭还是不被关闭。JDBC2.0和1.0提供的都是提交后ResultSet就会被关闭。 
resultSetHoldability表示在结果集提交后结果集是否打开,取值有两个:
ResultSet.HOLD_CURSORS_OVER_COMMIT:表示修改提交时,不关闭数据库。
ResultSet.CLOSE_CURSORS_AT_COMMIT:表示修改提交时ResultSet关闭。
在websphere的数据源连接池的配置过程中缺省是第2中方式,这就是造成错误的原因。
 
修改步骤如下所示:
  根据上面的错误原因分析,是websphere的数据源连接池的resultSetHoldability配置参数需要修改,则在websphere控制台上资源->JDBC提供者,如下:
 
 
点击DB2 Universal JDBC Driver Provider->数据源 ,如下图所示:
选择你要修改参数的数据源,如下图所示“jdbc/cpf/type4
数据源详细配置页面,上面有具体的数据源配置,点击右侧的“定制属性”,如下图所示
 
在下面的数据源的定制属性中选择“resultSetHoldability”参数,如下图所示:
 
如下图所示,修改“resultSetHoldability”属性的值,缺省是2,修改为1
 
修改属性后保存,并重启Websphere应用服务器,则大功告成!
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
   
联系作者:lijj_72@hotmail.com

航海日志(1) ----from Oracle to DB2

发布时间:2008年04月21日 作者:lijj

阅读次数:980次 类别:我的文章 永久链接 Trackback 
概述
Oracle和DB2是不同的数据库系统,从展现到内部实现机理都有比较大的差异,下面是结合财务公司项目具体情况及数据迁移中涉及到的问题给出具体的解决方案。本次迁移是从Oracle10g 迁移到DB2 9.1。本文并不是系统地介绍Oracle与DB2的差异性分析,也不是详细罗列转换过程SQL迁移如何转换,仅仅是我们在迁移中遇到这样或那样的问题,给出解决的方案。希望给读者以启发并能达到举一反三的效果。
数据库环境准备
数据库本身迁移及IBM数据迁移工具MTK
数据库表,视图,序列,索引等数据库本身的特性由IBM的数据迁移工具主要由完成,
Migration Toolkit (MTK) 都是从非 IBM 数据库迁移到 IBM 产品的一种强大的工具。使用IBM的MTK迁移工具,首先连接源数据源(oracle),获取数据源的表,视图,序列,index等数据库元信息,生成元数据脚本文件。把oracle的脚本文件转换成响应的DB2脚本,这儿要指定相应的字段类型映射,这个过程可以需要迭代几次,最终才能转换成合适的DB2数据库脚本。连接DB2数据库环境,执行数据库DB2脚本,创建相关的表、视图等。最后抽取oracle数据,生成相应的SQL脚本,把数据导入到DB2的环境中。下面是具体执行步骤:
MTK数据迁移工具指定数据源
MTK 支持直接从源数据库提取源对象,或者导入包含要转换的 SQL 的脚本。一般在windows上需要首先创建数据库连接,如ODBC或者JDBC,配置Oracle数据源的IP,User,password,测试连接成功后,打开MTK,把相应的Oracle数据源配置到MTK。MTK(Migration Toolkit)是迁移工具,必须有原材料,经过加工,生成产品,那么原材料就是Oracle数据源,类似于我们常用的Oracle的PLSQL等数据库工具,MTK连接上Oracle数据库后,就可以看到Oracle数据库表,视图,序列,索引等信息。
选择要导出的数据库表,视图,序列等数据库源信息,然后导出相关的文本文件,其内容是类似于“create table”等Oracle创建语句。
 
Oracle创建语句的远信息转换DB2类型的创建语句
将数据提取到文件之后,在这里可以查看被提取到文件的 Oracle 信息。通过单击 Convert转换 按钮,可以将该脚本转换成能由 IDS 使用的脚本。
在转换之前,将 Oracle 数据类型的默认映射更改为任何被允许的 IDS 映射。Advanced Options 可用于更改转换后的输出的格式,在这儿可以修改字段类型映射(Map)信息,因为Oracle和DB2的字段类型定义存在差异,如我们在Oracle设计表字段时,采用了Number类型,后面没有指定Number的大小,所以在转换成DB2的过程中就根据实际业务的需要,修改为“smallint, integer, bigint”。用户可以选择一个包含转换文件时所依赖的信息的上下文文件。
MTK 转换完 Oracle 文件后,会生成一个 IDS(.ids)文件和一个报告(.rpt)文件。.ids 文件包含在转换期间从 Oracle DDL 语句转换而来的 IDS DDL 语句。报告文件则包含一个错误列表,这些错误是在转换期间发现的。
 
 
用户可以查看转换得到的输出,找到错误消息,并更改转换后得到的文件。可以通过单击源(Oracle)或目标(IDS)选项卡来进行这样的更改。如果在这一步作出了更改,那么必须重复转换(Convert)步骤,以便使这些更改在转换得到的文件中生效。
表空间设置问题,我们在迁移过程中发现,我们大多数表的行大小都在4k,而有少数几张表在行大小32K以上,因为根据DB2的规定,表空间应该在4k页表空间,8k页表空间,16k页表空间, 32k页表空间,在迁移初期,为了简单,都按32K页建立表空间,但这就可能带来很大的性能问题,浪费缓冲区,后期我们将改变表空间的创建策略,创建4k页的表空间放置大多数4k的表,创建32K页的表空间放置32K的表,并且放置和该表业务逻辑非常密切的4k行大小的表,因为当查询或操作这些32K的表的同时,也会操作与之相关的4k行大小的表,有些4k行大小的表,虽然和32K的表也有外键的关系,但在业务操作上同时操作的几率很小,也会把这些表放置到4k页的表空间内。这样在数据库性能优化阶段将会做的工作,就表空间的页大小设置与缓冲区设置结合,减少IO次数,提高性能。
缩表的问题,因为我们老系统在Oracle数据库上操作,所以当时在表的设计中存在一些问题,如为了使表的扩展性更强,在一个表的多个字段都使用VARCHAR2(1000)这样的数据类型定义,后来我了解到,因为原来设计表时定义的字段类型长度短,所以在后来的实际操作中经常会超过字段的长度,经常修改字段长度,为了少修改字段的长度,都缺少的把这些业务表的大多数字符字段定义为VARCHAR2(1000),物极必反,当我们再做迁移的过程中就发现这些表的行大小都大于32K,根据DB2的要求,无法创建这样的表空间,为此,不得不分析这些大表,并结合业务需求,把不必要定义这么长的字段缩小,这样就解决了某些表的字段类型过大的问题,当然,如果该字段必须很大,那么我们可以采取Blob,CLob字段类型来替换,因为在数据库内部的逻辑上,所谓的Blob,Clob字段,实际该字段存储的是该字段内容的一个地址。
 
 
生成用于提取数据的脚本,并且可以选择用于部署的客户机,您将通过该客户机将 SQL 脚本和生成的数据部署到目标服务器上。
这种情况发生在,我们的应用系统在上线前,先会使用Oracle数据库做业务演示和培训,当应用熟练后,就可能在上面也做些业务,这样Oracle数据库中就保留有真实的业务数据,并且Oracle系统与DB2的系统会并行一段时间,这样当完全迁移过去后,就有必要把原来在Oracle中的数据导入到DB2中,导入成功后会停掉Oracle数据库,完全依赖于DB2数据库。
 
部署到DB2数据库(DB2建表,Oracle数据脚本,DB2装载数据),在这个过程中如下图所示,可以把这个部署过程一起完成,也可以单独完成某一个,根据实际情况而定。
MTK工具在代码迁移阶段的使用
在开发过程中,即在代码迁移的阶段利用MTK工具也能提高生产效率,如下所示, 但有时工具也不是完全可靠,需要手工去修改,但总体上说,还是有很大的进步,再修改的量也不会很大。
 
创建视图的SQL问题
在创建视图(View)时发现了一些问题,哈哈!有时候工具也靠不住啊!因为创建View的SQL比较复杂,单独拿出来说一说,可能挂一漏万。
1) 没有用to_number(ID),ID本身就是数字型, DB2转换是去掉了to_number();
Oracle:“CREATE VIEW…from … where…and naccounttypeId in (select to_number(ID)…)”。
DB2:“CREATE VIEW…from … where…and naccounttypeId in (select ID…)”。
2)日期转换成指定格式的字符串,转换工具转成“ORA.TO_CHAR(a.DTSTARTDATE, "yyyymmdd")”,需要手工修改,成如下形式
Oracle: TO_CHAR(a.dtStartDate,"yyyymmdd") 
DB2:replace(substr(VARCHAR_FORMAT(a.DTSTARTDATE, "YYYY-MM-DD HH24:MI:SS"),1,10),"-","")
3)用MTK工具转换的时候 A.NACCOUNTID 被转换成了 A.NACCOUNTID1,这就直接改过来就行了。
4)Oracle : to_number(b.ClassID) 
 DB2   dec(b.ClassID)
5)Oracle: decode(TransactionTypeID,"1301","1101","1201") TransactionTypeID
DB2 :   CASE TRANSACTIONTYPEID WHEN 1301 THEN 1101 ELSE 1201 END AS TransactionTypeID
6)取的系统时间sysdate并设置为timestamp类型
Oracle:to_date(to_char(sysdate,"yyyy-mm-dd"),"yyyy-mm-dd") TransactionDate
DB2:CURRENT TIMESTAMP AS TransactionDate     (DB2在转换的时候日期类型都缺省设置为:TimeStamp 类型)
7)别名问题,Oracle 在进行Union的时候只要数据类型一样,名称可以不一样,DB2必须都一样,如果不一样则必须使用as
Oracle: mSuretyFeeRate SecutyFeeRate
DB2:MSURETYFEERATE AS SecutyFeeRate
8)Oracle    to_char(n.executedate,"yyyy-mm-dd")  PRDate
MTK 生成:ORA.TO_CHAR(n.EXECUTEDATE, "yyyy-mm-dd") AS PRDate
DB2修改 :substr(VARCHAR_FORMAT(n.EXECUTEDATE, "YYYY-MM-DD HH24:MI:SS"),1,10) AS PRDate
9)tis.MINTEREST -->-- -tis.MINTEREST AS MINTEREST 加了一个别名
10)名称问题
 用MTK工具转换的时候 aa.contractid 被转换成了 aa.contractid1 ,aa.contractid2
11)Oracle : where lr.ncontractid = lc.id  
 DB2    : WHERE dec(lr.NCONTRACTID) = lc.ID   因为 lr.ncontractid是字符型

 

 
 
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
   
联系作者:lijj_72@hotmail.com

HP Unix 与 Websphere 集成问题解决方案

发布时间:2008年04月09日 作者:lijj

阅读次数:3739次 类别:我的文章 永久链接 Trackback 

HP Unix Websphere 集成问题解决方案

李俊杰

概述
某资金管理信息系统的操作系统是HP Unix , 应用服务器为IBM Websphere。在系统开发应用中,偶尔出现启动死机现象,具体的说就是,当修改文件后,copy到应用服务器的相应位置,然后停止该服务,重启该服务,在重启服务的过程中偶尔会出现停滞现象。
错误原因及解决方案
错误信息
查看后台Systemout..xml,错误信息如下:
SRVE0100E: 未识别出由 servlet context 抛出的 init() 异常:java.lang.OutOfMemoryError: PermGen space
错误原因
PermGen space,全称是Permanent Generation space,就是说是永久保存的区域,用于存放Class和Meta信息,Class在被Load的时候被放入该区域从字面看,和存放Instance的Heap区域不同,GC(Garbage Collection)应该不会对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。由于HP Unix 操作系统 设置PermGen space缺省参数相对较小则出现这种问题。每次启动服务时就会在 PermGen space中划分一块区域保存Class和Meta信息,所以随着启动服务次数的递增,则PermGen space剩余的空间就越来越小,直到不能支持某次重启服务所需要的空间。即报出了“java.lang.OutOfMemoryError: PermGen space”异常。
解决方案
调大PermGen space参数即可,服务器->应用服务器->server1->进程定义->java虚拟机,在该页面下面有“通用JVM参数”输入框,添加“ -XX:PermSize=512M”,注意和前面的参数要有空格分割。
建议
我们每次重启时,最好是重启Websphere应用服务器,而不是仅仅重启某个应用,这样就不会发生这种现象。XX:PermSize参数也不能调得过大,因为这块区域是不受GC(Garbage Collection)控制的,所以如果调得太大,对你整个系统的性能会造成影响。
每次打补丁时,最好按正规的打包发布流程,重新启动Websphere应用服务器,并重新部署应用。
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
   
联系作者:lijj_72@hotmail.com

Websphere安全性设置方案

发布时间:2008年01月14日 作者:lijj

阅读次数:1135次 类别:我的文章 永久链接 Trackback 
概述
在Websphere的使用过程中,只要有控制台的地址,任何人都可以进入控制台操作,这在很大程度上带来安全隐患,根据客户的要求,需要加入全局安全性控制,在我们的系统中使用了JMS技术,利用了Websphere的总线设置我们的JMS队列,所以要对JMS总线进行相关的设置才能完成。
具体设置步骤
在Linux上创建Websphere控制台管理员用户
以root用户登录,在Linux上建立Websphere控制台管理员用户,如webadmin,密码:1q2w3e4r
命令:[root@cdttest ~]# useradd wasadmin
[root@cdttest ~]# passwd wasadmin
根据系统的提示信息输入两次密码,系统会显示:
passwd ::all authentication tokens updated successfully
表示你创建Linux用户成功。
添加控制台组
登陆到管理控制台,进入 ,"系统管理--控制台设置--控制台组",如下图所示:
添加控制台组,如下图所示:
添加控制台用户
进入"系统管理--控制台设置--控制台用户",如下图所示:
添加控制台用户,如下图所示:
安全性设置
到"安全性--全局安全性",如下图所示:
在右面的页面上找到用户注册表栏目,点击“本地OS“,如下图所示:
设置服务器的用户标识和密码,保存设置。
如下图所示,勾选“全局安全性”,把强制Java2安全性不选中(缺省当选中“启用全局安全性,就选中Java2的”)。其他采用默认设置就行。
 
总线安全性设置
因为总线安全性设置后,就会在启动JMS时进行安全性校验,所以有两种方案可以采纳,一是在建立JMS队列的代码中加入校验的内容,一是在Websphere的总线设置中不选中安全性设置。下面是Websphere总线安全性配置:
在“服务集成-总线”下,如下图所示
选中已有的总线,如点击“iTreasureBus”,出现如下图所示:
 
如上图说示,把安全性下面的“安全”选择框选为“不选中”。
 
以上所有的配置都需要“应用-保存”操作,呵呵,废话!
 
重新启动服务器
在Linux上打入如下命令:
停止Server1(因为已经有了安全性设置,所以停止服务器需要用户标识和密码)
./stopServer.sh server1
启动Server1
./startServer.sh server1
进入Websphere控制台
进入控制台,会出现如下图所示:
选择“是”,则进入下面的用户标识和密码的界面:
 
 
这样,Websphere全局安全性设置就圆满完成了。
 
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
   
联系作者:lijj_72@hotmail.com


显示第 1-10 条记录,共 20 条记录 首页 前页 后页 尾页  到第 页,共 2