??xml version="1.0" encoding="utf-8" standalone="yes"?>
另外Q作为架构设计者,非常非常不赞成动辄就把很底层的概忉|q高层设计中Q例如行U,数据库什么的Q,很容易把自己和别人搞胡涂?br />可以最q状态不好,要不好好blog一,8q,有句话怎么说来着Q“都素那云而已。。。?/p>
情况Q子公司Q部分,人员{已完成所有编码(界面Q商业逻辑Q数据逻辑Q?br />变化Q需要把q个机构体系l成Z颗树(wi)状结?br />{略Q鉴于除?jin)?wi)l构外的其他部分代码已经完成Q那么应该首先保持这些代码不予改动。复用修改的优先U从高到低的序如下Q?br /> (tng) 界面×JSPQAction?br /> (tng) 商业逻辑 Service?br /> (tng) 数据逻辑?br /> (tng) 数据物理?br />有经验的人知道,大部分情况下Q越是下层的改动Q越是媄(jing)响越q泛Q注意不是修攚w度)(j)Q所以我们只有在无计可施的情况下Q才q行低层的修攏V?/p>
分析: 回到我们的需?从功能上看,l护一个组l机构的需求,已经늛?jin)每一个子l构的维护需求,以部门的建立ZQ在新徏一个部门时Q同时也必须建立机构?wi)上的节点?br /> (tng)q样Q如果需要直接用原有的创徏部门的所有代码,需要在其上加上创徏l织机构所需要的父节点,以及(qing)当前节点名称信息(在这里department的增加界 面JSP是需要修改的,不过实际上我没有修改该文?而是利用DHTML来动态加入需要新增加的信?,然后提交l原创徏部门的URI QdepartmentSave.actionQ和l织机构创徏URI(orgCreate.action)Q在q里我们利用ww提供的action chain功能来完成这两个操作?br /> (tng)q里需要修改department.action的配|?拦截saveҎ(gu)使其执行完后跌原来的relistl果面转向l织l构的创建orgCreate.actionQ?br /> (tng)<action name="unitSave" class="com.wolfsquare.ibase.org.action.UnitAction" method="save"> (tng) (tng) (tng) (tng) (tng) (tng) (tng) p?我们完成?jin)新增,修改l织机构的功能合?虽然有点拖沓,但是q是辑ֈ?jin)复?修改原有代?而且扩展性也很好的目标。这上篇说的是两个简单业务的功能揉合问题,下篇我们来看看稍微复杂点的情?看看q能不能l箋(hu)依葫芦画瓢来完成功能合的?br /> (tng) (tng) 首先我们搞清楚log4j能干什么,单来说就是提供一个记录不同别信息内容的日志工具Q?br />可以把不同别,不同包\径的信息Q以指定格式输出到多U设备(控制収ͼ文g{)(j) ==========log4j.properties================== log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.fileout=org.apache.log4j.RollingFileAppender log4j.rootCategory=INFO, stdout, fileout q个文g可以划ؓ(f)三小?/p> ===========W一块定义了(jin)一个名?stdout 的appender和layout (appender,layout的概念后面再解释Q目前先记着有这样两个名?Q?/p> log4j.appender.stdout=org.apache.log4j.ConsoleAppender ============W三块定义了(jin)名字分别为rootCategory,log4j.logger.com.wolfsquare.log2的两个logger rootCategory logger是缺省的loggerQ记录所有的包的信息输出?br />W二个logger是只输出指定包com.wolfsquare.log2下的日志信息?br />那么INFO,DEBUG又是什么意思呢Q他们是信息的分U标识,通过l承实现q个实现自定义别的分?br />W三块配|两句的意思是q样的:(x) 输出信息的分cȝ别是DEBUG > INFO > WARN > ERROR,信息l节q到粗Q指定输出某一U别的信息时Q?br />q细的信息输出将?x)被忽?/p> 如果一个配|中有多个loggerQ他们之间会(x)有什么关pdQ答案是Q在输出上,他们没有M关系Q都是独立运作的Q?br />不相关的Q但是在配置上,父包的配|会(x)传给子包Q如果子包没有另外定义配|的话?br />例如上面配置文g中的两个loggerQ?br />log4j.logger.com.wolfsquare q里认ؓ(f) log4j.logger.com.wolfsquare.log2 l承?log4j.logger.com.wolfsquareQ他们的配置声明如下Q?br />log4j.rootCategory=INFO, stdout, fileout 同时需要强调的是,如果两个logger有(h)承关p,且输出到同一个appenderQ根据输出独立原则,那么会(x)出现两行一L(fng)信息Q?br />例如上面的两个logger定义?x)导致这L(fng)情况?br />最后以一q图来概括:(x) <bean id="serviceA" class="A" autowire="byName" lazy-init="true"> ׃两个业务服务互相调用的\径是不相交的Q所以采用了(jin)一U变通的Ҏ(gu)Q在声明serviceAӞ
原文在这:http://www.aygfsteel.com/RongHao/archive/2006/07/03/56258.html
仔细分析一,??四权限背后的实质可以发现:
一pȝ权限的概忉|一些冗?很难惌q样一U情?你已l有?jin)子pȝ下的很多权限,l果因ؓ(f)没有模块权限而得无法用该模块q行M操作,分配权限的h要非常小?j)才?q个世界已经够复杂了(jin),不要再给开?部v人员增加复杂度了(jin).很明白的,q个权限是不需要资源的权限
二数据库操作权限的概?有一点疑?不知道ؓ(f)什么要建立q样的一个概?和行U权限有什么区别呢? 从你的上下文理解来看,g是这样子?有操作X表的业务,如果用户有增加权?则可以Q意增加数?如果用户有编辑权?则可以编辑Q意数?实际上对应标准权限模型ؓ(f):不需要限定资源的操作,即不需要资源标识的权限.
三行U数据权?q个概念很直?对应标准权限模型是: 资源(行数?+操作
四列U数据权?׃不是针对某特定行数据,所以它也是无资源型权限
p?所有的权限最l可划ؓ(f)需要资源标识和不需要资源标?换句话说,所有权限可划分为控制某些集合的权限和控制单体的权限两种,在某些时?也称之ؓ(f) 功能权限和数据权?/p>
谈到把权限分l别?很自然的是如何控制权限的权限的问题?sh)?很拗?是吧?仔细x(chng),q样很直?也没有什么后遗症,权限自递归控制和自解释,真是一个完的循环.
有爱思考的同学x(chng)??x)觉得非帔R?隑֮?当然,概念上一回事,具体实现上可以是另一回事,可以做很多的变通来辑ֈ目的.只要保持概念上的单?p以得非常多的h得以解脱?jin)?/p>
(tng) (tng) <result name="input">/org/unit/input.jsp</result>
(tng) (tng) <result name="relist" type="chain">
(tng) (tng) (tng) (tng) (tng) (tng) <param name="actionName">orgCreate</param>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <param name="namespace">/org</param> (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </result>
(tng) (tng) <result name="xxx" type="redirect">/org/unit.action?start=${start}</result>
(tng) (tng) <interceptor-ref name="validationStack"/>
(tng) </action>
可能有同学看到这里会(x)问:(x)创徏l织节点时应该还需要关联前面创建的部门对象啊,q个操作是如何实现的Q信息是如何传递的Q?br />在这里,׃整个架构体系q没有支持这U信息传递的功能Q所以只好以一U比较”脏“的方式实现Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) 在department.actionc里增加?jin)一个方法getModel()q回刚刚创徏的部门对象,然后在org.actioncM增加一个接收的Ҏ(gu)setModel(object o)q样在整action chain执行的时候,ww?x)自动将getModel后的数据填入setModel中,q样做的后果是以后增加新的机构类型的功能Ӟaction必须也照q样的语意设|getModelҎ(gu)。(如果要解册个问题,q能需要用一个特定的ContextQ然后拦截指定Service的创建方法,把创建结果放入ContextQ不q这又带来如何清除Context的问题,于是又要求助与ww的interspectorQ专门写一个拦截器来擦屁股Q够ȝ(ch)。。。)(j)
(未完待箋(hu)) (tng) (tng)
理解?jin)log4j的配|用法,以下是我对log4j配置的一点认识,如有谬误q请不吝赐教.
在程序中Q可以以以下方式来?br /> (tng) (tng) Log log = org.apache.commons.logging.LogFactory.LogFactory.getLog(yourClassName.class);
(tng) (tng)log.debug("debug message -------------------");
(tng) (tng)log.info("info message ******************");
(tng) (tng)log.warn("warn message +++++++++++++++");
(tng) (tng)log.error("error msg=================");
(tng) (tng)
本文主要讲的是如何配|log4jQ先让我们先看看一个典型的log4j配置Q?tng)?
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{MM-dd HH\:mm\:ss.SSS} %-5p [%F\:%L]%x %m%n
log4j.appender.fileout.File=D:/workspace/log4jtest/log/application.log
log4j.appender.fileout.MaxFileSize=10000KB
log4j.appender.fileout.MaxBackupIndex=10
log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
log4j.appender.fileout.layout.ConversionPattern=%d{MM-dd HH:mm:ss.SSS}[%24F:%-3L:%-5p]%x %m%n
log4j.logger.com.wolfsquare.log2=DEBUG,stdout
===================================
定义stdout的实际输出实现类Q从q个appender实现cd可以猜到Q这个类是负责控制台输出的?br />log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
定义stdout的输?gu)饰?br />log4j.appender.stdout.layout.ConversionPattern=%d{MM-dd HH\:mm\:ss.SSS} %-5p [%F\:%L]%x %m%n
装饰器参数配|?/p>
============W二块定义了(jin)一个名?fileout 的appender和layout:
log4j.appender.fileout=org.apache.log4j.RollingFileAppender
同理可猜q个实现cL输出到文件的
log4j.appender.fileout.File=D:/workspace/log4jtest/log/application.log
log4j.appender.fileout.MaxFileSize=10000KB
log4j.appender.fileout.MaxBackupIndex=10
log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
log4j.appender.fileout.layout.ConversionPattern=%d{MM-dd HH:mm:ss.SSS}[%24F:%-3L:%-5p]%x %m%n
log4j.rootCategory=INFO, stdout, fileout
log4j.logger.com.wolfsquare.log2=DEBUG,stdout
rootCategory 把所有类的INFOU别以上的信息输出到stdout和fileout两个appender中,
logger.com.wolfsquare.log2Q把com.wolfsquare.log2包中的所有类Q包括子包)(j)DEBUGU别Q含Q以上的信息输出到stdout ?br />一个logger可以输出到很多个讑֤中(appenderQ?如果需要增加输?gu)备则用分号分隔开appender名称卛_?/p>
log4j.logger.com.wolfsquare.log2
log4j.logger.com.wolfsquare.log2=,stdout
注意W二句没有指定输出?那么Ҏ(gu)配置l承规则?x)?h)承父logger的配|,在这里就是INFO?/p>
<property name="serviceB"><ref local="serviceB"/></property>
</bean>
<bean id="serviceB" class="B" autowire="byName" lazy-init="true">
<property name="serviceA"><ref bean="serviceA"/></property>
</bean>
但是作ؓ(f)一个业务接口,它应该是不需要关?j)事务,回滚q些无关的东西,
但现实又有这L(fng)需求,所以我们必M证透明的实现这个功能,于是?BR>入了(jin)AOP方式解决该问题,利用的是Spring自带的org.springframework.t
ransaction.interceptor.TransactionProxyFactoryBean.
重新声明文g如下Q?BR> <bean id="baseTxProxy" lazy-init="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyTargetClass"><value>true</value></property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="serviceA" parent="baseTxProxy">
<property name="target"><ref local="serviceAImpl"/></property>
</bean>
<bean id="serviceAImpl" class="serviceA" autowire="byName" lazy-init="true">
<property name="serviceB">
<ref bean="serviceB"/>
</property>
</bean>
<bean id="serviceB" parent="baseTxProxy" lazy-init="true">
<property name="target"><ref local="serviceBImpl"/></property>
</bean>
<bean id="serviceBImpl" class="D" lazy-init="true">
<property name="serviceA">
<ref bean="serviceA"/>
</property>
</bean>
于是问题出C(jin)QSpring报了(jin)FactoryBeanCircularReferenceExceptionQ无法(h)l完成设|工作?BR>查看TransactionProxyFactoryBean源码Q其实现?jin)FactoryBean和InitializingBean接口Q应该是
做了(jin)代理之后Q两个代理Bean需要等待所有Bean讄完成后才?x)标识状态ؓ(f)初始化完毕,于是造成?BR>冲突?/P>
直接定义serviceBQ?BR> <bean id="serviceAImpl" class="serviceA" autowire="byName" lazy-init="true">
<property name="serviceB">
<bean class="B" autowire="byName"/>
</property>
</bean>
相当于serviceB和serviceA中用的serviceB不是同一个实例?BR>
但是如果实调用重合时怎么办?
解决Ҏ(gu)是这L(fng)Q?BR>
<bean id="serviceAImpl" class="serviceA" autowire="byName" lazy-init="true">
<property name="serviceB">
<ref bean="serviceBImpl"/>
</property>
</bean>
非常单,serviceAImpl调用Ӟ可能已经在事务环境中?jin),不需再用serviceB代理的事务支持,
于是直接引用serviceB实例。这个方法是我写q篇文章时想到的Q?_-!!!Q看来知识果真还是好?BR> 整理呀?/P>
hbm文g采用通配W获取:(x)
问题症状Q?/P>
应用启动报错说不能重复定义某c,L该类后仍然报下一个类重复定义?/P>
仔细查看Log输出发现Q所有的hbm文g均找C(jin)两䆾 -_-!!!
目l认为应该是websphere不太厚道Q在classpath中用了(jin)多处目录(web-inf & classes)Qƈ以这些目录ؓ(f)根进行递归搜烦(ch)匚w文gQ可是如果这些目录有包含关系QW(xu)ebSphere没有处理重复查扄文g?jin)?/P>
于是在以上配|中改ؓ(f)Q?/P>
问题虽然解决?jin),可是tomcat中却又无效了(jin)?Q(
什么时候,企业应用才能一ơ拷贝,到处q行啊~?/P>
环境Q?JDBC驱动inet tds驱动(版本不明),SQLServer2K
问题症状Q对于数据库声明为varchar的长度大?56的字D,可以正常保存Q但是无法取出多?56字符以后的内?/P>
问题2Q用Hibernate映射?长度字符串保存后Q取出多加了(jin)一个空?/P>
环境Qinet tds驱动Hibernate2.1.8,SQL Server2K
问题症状Q保?长度字符串后Q取出增加了(jin)多余的空根{?/P>
以上两个问题都是因ؓ(f)没有使用最新的通讯协议引v的,修改URL声明方式如下Q?/P>
jdbc:inetdae7:127.0.0.1:1433?database=xxx
问题解决Q收工?/P>
ps:发现协议inetdaeӞ数据库字Dؓ(f)NullӞHibernate取出声明为基本类型(例如booleanQ的对象属性ƈ不会(x)报错Q实际上在其他数据库如Oracle和新协议上是?x)报错的。ؓ(f)?jin)避免此c问题出玎ͼ最好还是严格遵守:(x)Hibernate声明对象的基本类型属性,一定不能在数据库端|ؓ(f)I倹{?/P>
ps2:在解决以上问题(sh)发现,Oracle居然对传?长度字符Ԍ?x){为空?不知道是Z(jin)节省I间q是别的什么理由?_-!!!
Q?STRONG>全文?/FONT>Q?/P>
以上做法形象的说应该是这P(x)把需要生的囑Ş对象先放大,d一张“纸上”,然后整体~小Q这L(fng)度就提高?sh)(jin)?/P>
tips 1Q在一般企业报表表格打CQ?44DPI得到的表格线的宽度看h最舒服?BR> tips 2Q现在号U?00DPI的打印机其实?76DPIQ如果想使用q个分L率的_ֺQ需要用好一点的U张Q因为已l到极限?jin),U张E差点,打印墨粉沾不上Q导致线体残(hu)~?/P>
附源码(修改分L率就改动变量iResMul好Q:(x)
Q?STRONG>全文?/FONT>Q?nbsp;
// 订单服务只负责做好自q?BR>
而ؓ(f)?jin)拦截Q何的Ҏ(gu)调用Q则实现?jin)拦截器EventBrocasterQ?BR>
事g侦听器:(x)
然后Q在Spring配置里将q些lg全部q接hQ?/P>
1.OrderService实现:
<bean id="orderServiceImpl" class="OrderService" autowire="byName">
</bean>
2. 声明OrderService代理:
<bean id="orderService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="orderServiceImpl"/>
</property>
<property name="interceptorNames"> <!--拦截器列?->
<list>
<value>eventBrocaster</value>
</list>
</property>
<property name="singleton">
<value>true</value>
</property>
</bean>
3.事gq播拦截?BR> <bean id="eventBrocaster" class="com.wolfsquare.core.service.EventBrocaster" singleton="true">
<property name="lifecycleListeners">
<list>
<ref bean="orderEventListener"/>
</list>
</property>
</bean>
4.具体的胦(ch)务子pȝ的侦听器实现与胦(ch)务系l的通讯Q?BR> <bean id="orderEventListener" class="OrderEventListener" autowire="byName">
<propety name="financialService"><ref bean="financialService"/></property>
</bean>
q样Q我们与具体实现无关的事件广播就做到?jin),聪明的朋友看到这里,肯定惛_?jin)拦截器方式不仅仅适用与事件广播,q可以实C务的l一理Q事实上Spring的事务管理就是这样完成的Q还可以实现权限的控制例如AcegiQ简直有点象万能的胶_(d)呵呵?/P>
从两文章的逐步探讨下,同一个机器,同一个虚拟机之内的数据通讯都可以实C(jin)Q那么异构系l和多虚拟机间的通讯又如何处理呢Q于是ESBQ企业服务ȝQ的概念慢慢Q现出来了(jin)Q不q这个不在本文探讨的范畴?jin),也许在不久的来Q我?x)补上这一?/P>
Q全文完Q?/STRONG>