随笔 - 11, 文章 - 1, 评论 - 20, 引用 - 0
数据加载中……

2006年4月20日

小经验两则

1.Oracle 8i 下使用最新的oracle thin driver时用DatabaseMetaData获取主键等信息时,需要将
connection.getMetaData().getPrimaryKeys(connection.getCatalog(),null,tableName);
中的tableName转为大写,否则无法得到数据。

2.正则表达式中,需要以","分割字符串,但是要分割的字串中含有","号,为了避免冲突,引入前置转义字符"\",这样的正则怎么写呢?
例如:
String txt = "STATE_COUNTY=kj\\\\,,ADDR_LINE1=l=j,ADDR_LINE2=mj\n\n,ADDR_LINE3=n\\,o,\n\nADDR_LINE4=\np";
需要把键值对切分出来:
 Pattern.compile("[^\\\\],)");
这个是不行的,会将","号前一个字符消耗掉。

 Pattern.compile("(?![\\\\]),)");
也不行
Pattern p = Pattern.compile,",(?![\\\\])");
倒是可以,但是把转义字符放后面似乎有点诡异。
找了一个折衷办法,不切割使用正则获取"键=值"子串:
Pattern p = Pattern.compile("\\w+\\s*=.*?[,]*.*?(?=,|$)",Pattern.DOTALL);
但是还是带来了子串中不能含有"="的问题。
最后查了一个JDK1.4 DOC,发现了一个反向的非匹配串写法:
Pattern p = Pattern.compile("(?<!\\\\),\\s*");
这样一来就解决了以上问题。

posted @ 2006-08-03 09:54 wolfsquare 阅读(542) | 评论 (0)编辑 收藏

回复 乱弹权限系统续一

乱弹权限系统续一
原文在这:http://www.blogjava.net/RongHao/archive/2006/07/03/56258.html

仔细分析一,二,三,四权限背后的实质可以发现:
一系统权限的概念有一些冗余,很难想象这样一种情况:你已经有了子系统下的很多权限,结果因为没有模块权限而使得无法使用该模块进行任何操作,分配权限的人要非常小心才行.这个世界已经够复杂了,不要再给开发,部署人员增加复杂度了.很明白的,这个权限是不需要资源的权限
二数据库操作权限的概念,有一点疑惑,不知道为什么要建立这样的一个概念,和行级权限有什么区别呢? 从你的上下文理解来看,似乎是这样子的:有操作X表的业务,如果用户有增加权限,则可以任意增加数据,如果用户有编辑权限,则可以编辑任意数据.实际上对应标准权限模型为:不需要限定资源的操作,即不需要资源标识的权限.
三行级数据权限,这个概念很直白,对应标准权限模型就是: 资源(行数据)+操作
四列级数据权限,由于不是针对某特定行数据,所以它也是无资源型权限
就这样,所有的权限最终可划为需要资源标识和不需要资源标识,换句话说,所有权限可划分为控制某些集合的权限和控制单体的权限两种,在某些时候,也称之为 功能权限和数据权限


谈到把权限分给别人,很自然的就是如何控制权限的权限的问题了,很拗口,是吧?仔细想想,这样很直观,也没有什么后遗症,权限自递归控制和自解释,真是一个完美的循环.
有爱思考的同学想深了,会觉得非常麻烦,难实现.当然,概念上一回事,具体实现上可以是另一回事,可以做很多的变通来达到目的.只要保持概念上的简单性,就足以使得非常多的人得以解脱了。

另外,作为架构设计者,非常非常不赞成动辄就把很底层的概念扯进高层设计中(例如行级,数据库什么的),很容易把自己和别人搞胡涂。
可以最近状态不好,要不好好blog一篇,8过,有句话怎么说来着:“都素那浮云而已。。。”

posted @ 2006-07-04 22:45 wolfsquare 阅读(1911) | 评论 (1)编辑 收藏

不完美的世界-看到了IOC工具的又一个发展方向

     摘要: 在本篇文章中,作者在一个系统的构建中深度地被各种配置逻辑所困扰,由此发现了IOC工具(如Spring,Nuts等)的又一个发展方向。  阅读全文

posted @ 2006-06-08 00:30 wolfsquare 阅读(1926) | 评论 (7)编辑 收藏

结合WebWork实现高复用度系统的探索(上)

需求: 某机构体系下,机构类型分为子公司,部门,人员等,以后可能在某机构或者其子孙机构下可能会再分出其他子机构类型,希望在增加新类型过程中,尽可能的避免修改已有代码。

情况:子公司,部分,人员等已完成所有编码(界面,商业逻辑,数据逻辑)
变化:需要把这个机构体系组成为一颗树状结构
策略:鉴于除了树结构外的其他部分代码已经完成,那么应该首先保持这些代码不予改动。复用修改的优先级从高到低的顺序如下:
  界面×JSP,Action层
  商业逻辑 Service层
  数据逻辑层
  数据物理层
有经验的人知道,大部分情况下,越是下层的改动,越是影响越广泛(注意不是修改难度),所以我们只有在无计可施的情况下,才进行低层的修改。

分析: 回到我们的需求,从功能上看,维护一个组织机构的需求,已经涵盖了每一个子结构的维护需求,以部门的建立为例,在新建一个部门时,同时也必须建立机构树上的节点,
 这样,如果需要直接使用原有的创建部门的所有代码,需要在其上加上创建组织机构所需要的父节点,以及当前节点名称信息(在这里department的增加界 面JSP是需要修改的,不过实际上我没有修改该文件,而是利用DHTML来动态加入需要新增加的信息),然后提交给原创建部门的URI (departmentSave.action)和组织机构创建URI(orgCreate.action),在这里我们利用ww提供的action chain功能来完成这两个操作。
 这里需要修改department.action的配置,拦截save方法使其执行完后跳过原来的relist结果页面转向组织结构的创建orgCreate.action:
 <action name="unitSave" class="com.wolfsquare.ibase.org.action.UnitAction" method="save">
   <result name="input">/org/unit/input.jsp</result>
   <result name="relist" type="chain">
       <param name="actionName">orgCreate</param>
                <param name="namespace">/org</param>  
            </result>
   <result name="xxx" type="redirect">/org/unit.action?start=${start}</result>
   <interceptor-ref name="validationStack"/>
  </action>
可能有同学看到这里会问:创建组织节点时应该还需要关联前面创建的部门对象啊,这个操作是如何实现的?信息是如何传递的?
在这里,由于整个架构体系并没有支持这种信息传递的功能,所以只好以一种比较”脏“的方式实现:
        在department.action类里增加了一个方法getModel()返回刚刚创建的部门对象,然后在org.action类中增加一个接收的方法setModel(object o)这样在整action chain执行的时候,ww会自动将getModel后的数据填入setModel中,这样做的后果是以后增加新的机构类型的功能时,action必须也照这样的语意设置getModel方法。(如果要解决这个问题,这能需要使用一个特定的Context,然后拦截指定Service的创建方法,把创建结果放入Context,不过这又带来如何清除Context的问题,于是又要求助与ww的interspector,专门写一个拦截器来擦屁股,够麻烦。。。)

        就这样,我们完成了新增,修改组织机构的功能合成,虽然有点拖沓,但是还是达到了复用,少修改原有代码,而且扩展性也很好的目标。这上篇说的是两个简单业务的功能揉合问题,下篇我们来看看稍微复杂点的情况,看看还能不能继续依葫芦画瓢来完成功能合的成
  
(未完待续)  

posted @ 2006-05-17 23:40 wolfsquare 阅读(1205) | 评论 (0)编辑 收藏

log4j配置简要说明

虽然以前一直在用log4j,但是对其配置不甚了了,突然间因为需解决某些问题,要理解log4j的配置,
然而用google搜了一下,却发现网上没有一个简单直观的说明,于是只好看log4j的官方介绍,终于
理解了log4j的配置用法,以下是我对log4j配置的一点认识,如有谬误还请不吝赐教.

首先我们搞清楚log4j能干什么,简单来说就是提供一个记录不同级别信息内容的日志工具,
可以把不同级别,不同包路径的信息,以指定格式输出到多种设备(控制台,文件等)
在程序中,可以以以下方式来使用
   Log log = org.apache.commons.logging.LogFactory.LogFactory.getLog(yourClassName.class);
  log.debug("debug message -------------------");
  log.info("info message ******************");
  log.warn("warn message +++++++++++++++");
  log.error("error msg=================");
  
本文主要讲的是如何配置log4j,先让我们先看看一个典型的log4j配置:  

==========log4j.properties==================

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
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=org.apache.log4j.RollingFileAppender
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
===================================

这个文件可以划为三小块

===========第一块定义了一个名为 stdout 的appender和layout (appender,layout的概念后面再解释,目前先记着有这样两个名词):

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
定义stdout的实际输出实现类,从这个appender实现类名可以猜到,这个类是负责控制台输出的。
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
定义stdout的输出装饰器
log4j.appender.stdout.layout.ConversionPattern=%d{MM-dd HH\:mm\:ss.SSS} %-5p [%F\:%L]%x %m%n
装饰器参数配置


============第二块定义了一个名为 fileout 的appender和layout:
log4j.appender.fileout=org.apache.log4j.RollingFileAppender
同理可猜这个实现类是输出到文件的
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

============第三块定义了名字分别为rootCategory,log4j.logger.com.wolfsquare.log2的两个logger
log4j.rootCategory=INFO, stdout, fileout
log4j.logger.com.wolfsquare.log2=DEBUG,stdout

rootCategory logger是缺省的logger,记录所有的包的信息输出。
第二个logger是只输出指定包com.wolfsquare.log2下的日志信息。
那么INFO,DEBUG又是什么意思呢,他们是信息的分级标识,通过继承实现这个实现自定义级别的分级。
第三块配置两句的意思是这样的:
rootCategory 把所有类的INFO级别以上的信息输出到stdout和fileout两个appender中,
logger.com.wolfsquare.log2,把com.wolfsquare.log2包中的所有类(包括子包)DEBUG级别(含)以上的信息输出到stdout 中
一个logger可以输出到很多个设备中(appender),如果需要增加输出设备则用分号分隔开appender名称即可。

输出信息的分类级别是DEBUG > INFO > WARN > ERROR,信息细节由细到粗,指定输出某一级别的信息时,
过细的信息输出将会被忽略

如果一个配置中有多个logger,他们之间会有什么关系呢?答案是,在输出上,他们没有任何关系,都是独立运作的,
不相关的,但是在配置上,父包的配置会传给子包,如果子包没有另外定义配置的话。
例如上面配置文件中的两个logger:
log4j.logger.com.wolfsquare
log4j.logger.com.wolfsquare.log2

这里认为 log4j.logger.com.wolfsquare.log2 继承自 log4j.logger.com.wolfsquare,他们的配置声明如下:
log4j.rootCategory=INFO, stdout, fileout
log4j.logger.com.wolfsquare.log2=,stdout
注意第二句没有指定输出级别,那么根据配置继承规则会继承父logger的配置,在这里就是INFO。

同时需要强调的是,如果两个logger有继承关系,且输出到同一个appender,根据输出独立原则,那么将会出现两行一样的信息,
例如上面的两个logger定义会导致这样的情况。
最后以一幅图来概括:

posted @ 2006-04-20 23:21 wolfsquare 阅读(963) | 评论 (0)编辑 收藏