2008年8月27日 #

java 数据库缓冲池 使用c3p0

c3p0很容易使用的开源专业级jdbc数据库缓冲池。
它是sourceforge上的一个开源项目,
项目在
http://sourceforge.net/projects/c3p0
他的众多特性这里就不一一介绍了。
比较爽的一点就是
当Connection归还缓冲池时,c3p0会很小心的关闭
这条连接打开的Statement和ResultSet,免去了使用时
自己动手小心翼翼的关闭。

c3p0使用非常简单,这里给一个例子

package common.db;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;


import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mchange.v2.c3p0.DataSources;

public final class ConnectionManager {
 private static ConnectionManager instance;
 
 public ComboPooledDataSource ds;
 private static String c3p0Properties="c3p0.properties";
 
 private ConnectionManager() throws Exception {
  Properties p = new Properties();
  p.load(this.getClass().getResourceAsStream(c3p0Properties));
  ds = new ComboPooledDataSource();
 }
 
 public static final ConnectionManager getInstance() {
  if (instance == null) {
   try {
    instance = new ConnectionManager();
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
  return instance;
 }
 
 public synchronized final Connection getConnection() {
  try {
   return ds.getConnection();
  } catch (SQLException e) {
   e.printStackTrace();
  }
  return null;
 }

 protected void finalize() throws Throwable {
  DataSources.destroy(ds); //关闭datasource
  super.finalize();
 }
 
}

然后在ConnectionManager类的目录下再创建一个配置文件c3p0.properties
内容如下:
#db login parameters
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost/test?useUnicode=no&characterEncoding=GBK
user=test
password=test

#pool parameters
initialPoolSize=2
maxPoolSize=5
#maxIdleTime=10
#idleConnectionTestPeriod=5
autoCommitOnClose=true

完整的配置文件参数参看c3p0的文档

使用connection时很简单
Connection conn = ConnectionManager.getInstance().getConnection();
...
最后 conn.close() 即可,

posted @ 2008-10-23 10:24 金家寶 阅读(4335) | 评论 (2)编辑 收藏

JDBC也分2.0和3.0?

如题。研究中...以前没有注意过。

posted @ 2008-10-23 10:10 金家寶 阅读(285) | 评论 (0)编辑 收藏

鲤鱼论坛 研究笔记(未)

2008.10.21第一天
网站地址: http://www.liyunet.com/
源码下载: http://www.liyunet.com/bbs/download.jsp

我主要是利用该论坛的简易性来研究JSP技术,以及缓存技术。虽然说目前大部分论坛应用的都是主流框架技术,但说回来,这些框架也只是对JSP等相关技术的一个封装,而了解底部应用及其原理更容易让我理解主流框架的内部原理机制。不至于让框架把我们变成“傻子”。


那就开始吧
首先,和某些大虾一样的习惯,我们从WEB-INF下的web.xml开始,从以下代码中可以发现随着tomcat启动时,自动加载了InitServlet类。这是一个Servlet类。
WEB-INF\web.xml部分代码:
1
2<servlet-name>InitServlet</servlet-name>
3        <servlet-class>com.bcxy.servlet.InitServlet</servlet-class>
4        <load-on-startup>1</load-on-startup>
5      </servlet>
6

查看com.bcxy.servlet.InitServlet类,代码很简单:
开始做了一个对此类日志(log4j)的绑定。接着通过SystemConfig取得了系统配置中的连接类型conntype(查看classes目录下的SystemConfig.xml可知此变量是判断使用连接池的类型0:3P0; 1:Proxool)。接着是初始化操作,记录一些必要的启动信息(log4j)(其中做了本地地址和网络访问地址的转换)。
用DBUtil.close测试连接池是否加载成功。
最后是释放类所做的必要操作。判断使用的是哪一种连接池,然后关闭。这样我们的第一个类就分析完毕。
接着需要了解到
SystemConfig类是加载SystemConfig.xml配置文件,并设定方法去读取。其中有一定的类型转换。

此时似乎已经找不到头绪了。那这样吧。我们就开始访问我们自己搭建的论坛,从首页开始,也就是index.jsp页面。
浏览index.jsp代码,由上向下理解每一个语句的含义(整体分体)。

设定页面编码;导入IPLocalizer类(应该是做IP显示的工具类);插入INC/const.jsp页(过后会有分析);设定stats变量数值(通过阅读其他jsp页面发现,此变量的作用主要是在于在首页显示用户状态时,兼并显示当前用户做浏览的页面:也就是stats的值,这样我们可以在客户可访问的范围内对stats变量进行设置,就可以查看在线用户的当前行为);继续插入INC/theme.jsp(估计是定制论坛模板的文件);<table>标签内部就是连接到相关显示数据信息的jsp页面并附加了参数。其中的一些格式是通过上面引用文件中的变量设置,相对不难理解;论坛消息广播部分,通过一个可执行jsp页面vector显示在首页顶部,当中访问数据库的细节需要进一步研究代码);接着是帖子的遍历,也就是首页最关键的部分,这里看起来不是由jsp页面来负责获取数据,而是通过Forum类来获取一些过滤之后的数据:这里所说的过滤是例如置顶帖子,最新帖子等有一些特殊标记的数据:;
index.jsp的其他部分就都是大同小异了。都是通过一个遍历来展现具有相同特性的数据。;大家需要注意一些关于页面表现的而非java技术的部分,例如信息层的提示,和一些图片连接。
通过index.jsp的学习,我们大概已经了解了大部分jsp页面代码的表现形式和含义。当然,一定要注意在这个过程中,参数传递、参数获取的代码部分,不要遗漏。除了一些我们可以看到的页面之外,上面部分也讲到了一些并不用于显示给用户的页面,这里我们认为它是可执行页面,也就是说它对我们的数据和请求做了一些处理,或者说把我们的请求转交给了服务器(比如servlet)。

预计晚上要研究一下有关数据库方面的存取类JdbcWrapper以及连接获取和释放、数据查询插入。
2008.10.22
大概昨天写的已经忘的差不多了,那么我们还是从index.jsp文件开始,前几行没有什么问题,都是一些导入文件的标签,那么我们从SkinUtil.这个类入手。在查看SkinUtil类代码的时候我们发现里面应用了一些com\bcxy\bbs\util 包中类,其中含有三个工具类。(偷笑,看了文件大小,应该代码不多,我们看看里面都是什么)在开始之前我们应了解一下GCookie.java类的大概内容和作用。看导入包我们可以大概了解一下此类的作用:对URL的编码与解码,产生和读取Cookie,还有就是做一些日志记录(log4j)。
我们仔细阅读后,了解到,其中有一个重载方法,也就是setCookie方法,根据不同的参数,可以让我们选择直接赋予变量名和值的方法,或者是赋予变量名和值另外加上最大保存时间的方法。  类中的另一个方法是获取Cookie方法值。
ParamUtil类也很简单,是取得字符串和 取得整数的重载方法,其中的参数决定是否有默认值,是否需要转码。
SysUtil类中根据SystemConfig类中的读取方法读取配置文件systemconfig.properties,按照里面的设置,来判断是否对参数和数据库读取操作中的参数进行编码。其中还有一个方法是取得真实地址,当然这些都是根据systemconfig.properties文件中配置而定的。
BBSCconst.java类简单的设置了一些常量。作用是设置数据库表名的时候加上systemconfig.properties中设置的前缀。
回到SkinUtil.java类似乎看起来一些刚刚还陌生的类方法,显得明朗。前面设置了一个Cookie的变量名并赋了值。

ret = new JdbcWrapper().doIntSearch(sql, 0);

这里用到了新类,也就是我们昨天说过的要了解的关于数据库连接的类。也是今天要解决的重点。打开JdbcWrapper类,查看代码.(插一句,看代码的时候,我觉得先看包名,了解大概要用到的类和方法,去设想这个类要实现的功能),yi一眼看来,大概都熟悉,无非是连接数据库 读取,结果保存,异常,还有一些类似数组的HashMap还有遍历用得Iterator。想想,大概就是数据层的一些基础CRUD操作。但是其中有个类不是很熟悉,DatabaseMetaData类,查看sun公司的在线文档,发现这是个接口而且方法奇多,文档的第一句这么写,

Comprehensive information about the database as a whole. 

我也不能理解这句话包含了什么内容。不管他,在程序中慢慢体会吧。JdbcWrapper这个类有点长,不过,大部分方法都有类似的作用,也就是说真正不同功能的代码也只有几分之一而已。我看的都想睡觉了。

在网吧,因为不便,先离开咯
今天还好,自己有一台电脑,可以不限制时间。继续工作....
之前研究JdbcWrapper类的时候有一个小小的疑问。如下

 

 1     //######这里有一点不明白,为什么要判断getAutoClose()
 2    /*
 3     * 当需要事务支持时,需要设置autoClose=false,那就等到事务提交时再关闭数据库连接。
 4     * */

 5    public void closeConnection() {
 6        if (getAutoClose()) {
 7            DBUtil.close(pstmt, con);
 8        }

 9    }

10

今天看群里鲤鱼回答内容如下:

当需要事务支持时,需要设置autoClose=false,那就等到事务提交时再关闭数据库连接。


一时还没有理解开来。
看过来看过去,JdbcWrapper类对我来讲还是有一部分难以理解。索性不去管它,等在下面的代码中出现时,反复查阅应该会有更多的收获。

posted @ 2008-10-21 11:47 金家寶 阅读(348) | 评论 (0)编辑 收藏

关于正则表达式

*匹配除了换行之外的所有字符

合法IP的正则表达式 ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

\s匹配任意的空白符、(空格、制表符、换行符、中文全角空格)
\w匹配字母或数字或下划线或汉字

表1.常用的元字符
代码说明
.匹配除换行符以外的任意字符
\w匹配字母或数字或下划线或汉字
\s匹配任意的空白符
\d匹配数字
\b匹配单词的开始或结束
^匹配字符串的开始
$匹配字符串的结束


表2.常用的限定符
代码/语法说明
*重复零次或更多次
+重复一次或更多次
?重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次


后向引用

使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。

后向引用用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本。难以理解?请看示例:

\b(\w+)\b\s+\1\b可以用来匹配重复的单词,像go go, 或者kitty kitty。这个表达式首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(\b(\w+)\b),这个单词会被捕获到编号为1的分组中,然后是1个或几个空白符(\s+),最后是分组1中捕获的内容(也就是前面匹配的那个单词)(\1)。

你也可以自己指定子表达式的组名。要指定一个子表达式的组名,请使用这样的语法:(?<Word>\w+)(或者把尖括号换成'也行:(?'Word'\w+)),这样就把\w+的组名指定为Word了。要反向引用这个分组捕获的内容,你可以使用\k<Word>,所以上一个例子也可以写成这样:\b(?<Word>\w+)\b\s+\k<Word>\b

使用小括号的时候,还有很多特定用途的语法。下面列出了最常用的一些:

表4.常用分组语法
分类代码/语法说明
捕获(exp)匹配exp,并捕获文本到自动命名的组里
(?<name>exp)匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
(?:exp)匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言(?=exp)匹配exp前面的位置
(?<=exp)匹配exp后面的位置
(?!exp)匹配后面跟的不是exp的位置
(?<!exp)匹配前面不是exp的位置
注释(?#comment)这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读


表5.懒惰限定符
代码/语法说明
*?重复任意次,但尽可能少重复
+?重复1次或更多次,但尽可能少重复
??重复0次或1次,但尽可能少重复
{n,m}?重复n到m次,但尽可能少重复
{n,}?重复n次以上,但尽可能少重复


表6.常用的处理选项
名称说明
IgnoreCase(忽略大小写)匹配时不区分大小写。
Multiline(多行模式)更改^$的含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。(在此模式下,$的精确含意是:匹配\n之前的位置以及字符串结束前的位置.)
Singleline(单行模式)更改.的含义,使它与每一个字符匹配(包括换行符\n)。
IgnorePatternWhitespace(忽略空白)忽略表达式中的非转义空白并启用由#标记的注释。
RightToLeft(从右向左查找)匹配从右向左而不是从左向右进行。
ExplicitCapture(显式捕获)仅捕获已被显式命名的组。
ECMAScript(JavaScript兼容模式)使表达式的行为与它在JavaScript里的行为一致。
表7.尚未详细讨论的语法
代码/语法说明
\a报警字符(打印它的效果是电脑嘀一声)
\b通常是单词分界位置,但如果在字符类里使用代表退格
\t制表符,Tab
\r回车
\v竖向制表符
\f换页符
\n换行符
\eEscape
\0nnASCII代码中八进制代码为nn的字符
\xnnASCII代码中十六进制代码为nn的字符
\unnnnUnicode代码中十六进制代码为nnnn的字符
\cNASCII控制字符。比如\cC代表Ctrl+C
\A字符串开头(类似^,但不受处理多行选项的影响)
\Z字符串结尾或行尾(不受处理多行选项的影响)
\z字符串结尾(类似$,但不受处理多行选项的影响)
\G当前搜索的开头
\p{name}Unicode中命名为name的字符类,例如\p{IsGreek}
(?>exp)贪婪子表达式
(?<x>-<y>exp)平衡组
(?im-nsx:exp)在子表达式exp中改变处理选项
(?im-nsx)为表达式后面的部分改变处理选项
(?(exp)yes|no)把exp当作零宽正向先行断言,如果在这个位置能匹配,使用yes作为此组的表达式;否则使用no
(?(exp)yes)同上,只是使用空表达式作为no
(?(name)yes|no)如果命名为name的组捕获到了内容,使用yes作为表达式;否则使用no
(?(name)yes)同上,只是使用空表达式作为no

posted @ 2008-10-17 11:10 金家寶 阅读(313) | 评论 (1)编辑 收藏

Lucene倒排索引原理(转)

Lucene是一个高性能的java全文检索工具包,它使用的是倒排文件索引结构。该结构及相应的生成算法如下:

0)设有两篇文章1和2
文章1的内容为:Tom lives in Guangzhou,I live in Guangzhou too.
文章2的内容为:He once lived in Shanghai.

1)由于lucene是基于关键词索引和查询的,首先我们要取得这两篇文章的关键词,通常我们需要如下处理措施
a.我们现在有的是文章内容,即一个字符串,我们先要找出字符串中的所有单词,即分词。英文单词由于用空格分隔,比较好处理。中文单词间是连在一起的需要特殊的分词处理。
b.文章中的”in”, “once” “too”等词没有什么实际意义,中文中的“的”“是”等字通常也无具体含义,这些不代表概念的词可以过滤掉
c.用户通常希望查“He”时能把含“he”,“HE”的文章也找出来,所以所有单词需要统一大小写。
d.用户通常希望查“live”时能把含“lives”,“lived”的文章也找出来,所以需要把“lives”,“lived”还原成“live”
e.文章中的标点符号通常不表示某种概念,也可以过滤掉
在lucene中以上措施由Analyzer类完成

经过上面处理后
    文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou]
    文章2的所有关键词为:[he] [live] [shanghai]

2) 有了关键词后,我们就可以建立倒排索引了。上面的对应关系是:“文章号”对“文章中所有关键词”。倒排索引把这个关系倒过来,变成:“关键词”对“拥有该关键词的所有文章号”。文章1,2经过倒排后变成
关键词   文章号
guangzhou  1
he         2
i           1
live       1,2
shanghai   2
tom         1

通常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现次数和出现的位置,通常有两种位置:a)字符位置,即记录该词是文章中第几个字符(优点是关键词亮显时定位快);b)关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组(phase)查询快),lucene中记录的就是这种位置。

加上“出现频率”和“出现位置”信息后,我们的索引结构变为:
关键词   文章号[出现频率]   出现位置
guangzhou 1[2]               3,6
he       2[1]               1
i         1[1]               4
live      1[2],2[1]           2,5,2
shanghai  2[1]               3
tom      1[1]               1

以live 这行为例我们说明一下该结构:live在文章1中出现了2次,文章2中出现了一次,它的出现位置为“2,5,2”这表示什么呢?我们需要结合文章号和出现频率来分析,文章1中出现了2次,那么“2,5”就表示live在文章1中出现的两个位置,文章2中出现了一次,剩下的“2”就表示live是文章2中第 2个关键字。
    
以上就是lucene索引结构中最核心的部分。我们注意到关键字是按字符顺序排列的(lucene没有使用B树结构),因此lucene可以用二元搜索算法快速定位关键词。
    
实现时 lucene将上面三列分别作为词典文件(Term Dictionary)、频率文件(frequencies)、位置文件 (positions)保存。其中词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。

    Lucene中使用了field的概念,用于表达信息所在位置(如标题中,文章中,url中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)。

     为了减小索引文件的大小,Lucene对索引还使用了压缩技术。首先,对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后缀>,例如:当前词为“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<3,语>。其次大量用到的是对数字的压缩,数字只保存与上一个值的差值(这样可以减小数字的长度,进而减少保存该数字需要的字节数)。例如当前文章号是16389(不压缩要用3个字节保存),上一文章号是16382,压缩后保存7(只用一个字节)。
    
    下面我们可以通过对该索引的查询来解释一下为什么要建立索引。
假设要查询单词 “live”,lucene先对词典二元查找、找到该词,通过指向频率文件的指针读出所有文章号,然后返回结果。词典通常非常小,因而,整个过程的时间是毫秒级的。
而用普通的顺序匹配算法,不建索引,而是对所有文章的内容进行字符串匹配,这个过程将会相当缓慢,当文章数目很大时,时间往往是无法忍受的。

posted @ 2008-10-17 09:43 金家寶 阅读(2824) | 评论 (1)编辑 收藏

struts2标签

 

一、
写jsp页面的时候,在struts2中,用的是s标记,先引入标记:
<%@ taglib prefix="s" uri="/struts-tags"%>
二、
struts2的标签和1是完全不同的。
struts2的标签分为两大类:非UI标志和UI标志 struts1 将标志库按功能分成HTML、Tiles、Logic和Bean等几部分
下面就介绍strut2的具体标签:
1、UI
UI标志又可以分为表单UI和非表单UI两部分。表单UI部分基本与Struts 1.x相同,都是对HTML表单元素的包装。不过,Struts 2.0加了几个我们经常在项目中用到的控件如:datepicker、doubleselect、timepicker、optiontransferselect等。因为这些标志很多都经常用到,而且参数也很多,要在一篇文章详细说明并非易事。
下面主要是ui标签的一些用法
form:
<s:form action="exampleSubmit" method="post" enctype="multipart/form-data">
<s:submit />
    <s:reset />

</s:form>可以上传文件的form。
textfield:
<s:textfield
            label="姓名:"
            name="name"
            tooltip="Enter your Name here" />
datepicker:
<s:datepicker
            tooltip="Select Your Birthday"
            label="生日"
            name="birthday" />
textarea:
<s:textarea
            tooltip="Enter your remart"
            label="备注"
            name="remart"
            cols="20"
            rows="3"/>
select:
<s:select
            tooltip="Choose user_type"
            label=""
            list="#{'free':'免费','vip':'收费'}" value="#{'free':'免费'}"  
           name="bean.user_type"
            emptyOption="true"
            headerKey="None"
            headerValue="None"/>
<s:select
            tooltip="Choose user_type"
            label=""
            list="#{'free':'免费','vip':'收费'}" value="#{'free':'免费'}"  
           name="bean.user_type"
            emptyOption="true"
            headerKey="None"
            headerValue="None"/>
<s:select
list="venderList"
listKey="id"
listValue="name"
value="%{profile.companyName}"
name="companyName" cssClass="sel_style_w_180"/>  
挺好用的
checkboxlist:
<s:checkboxlist
            tooltip="Choose your Friends"
            label="朋友"
            list="{'Patrick', 'Jason', 'Jay', 'Toby', 'Rene'}"
            name="friends"/>
checkbox:
   <s:checkbox
            tooltip="Confirmed that your are Over 18"
            label="年龄"
            name="legalAge"
            value="18"/>
file:
   <s:file
            tooltip="Upload Your Picture"
            label="Picture"
            name="picture" />
a:
<s:a href="getP.jsp">超链接提交</s:a>
date :
<s:date name="ad_end_time" format="yyyy-MM-dd"/>


2、非UI
if、elseif和else 描述:
执行基本的条件流转。
参数:
名称必需默认类型描述备注test是Boolean决定标志里内容是否显示的表达式else标志没有这个参数id否Object/String用来标识元素的id。在UI和表单中为HTML的id属性 例子:
<%@ page c %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <title>Condition Flow</title>
    </head>
    <body>
        <h3>Condition Flow</h3>            
        <!--
            这里有点小技巧:
            本来可以用#parameters.name[0]来获得,请求中name的值。但是,在我实现include例子时,
            无论我用param标志给name赋任何值,#parameters里面不会含有任何值,所以#parameters.name也为空值。
            
            其原因为:
            当使用include标志时,被包含的页面(included)里#parameters拿到的是包含页面里的请求参数。
            
            因此,这里必须手工调用request.getParameter("name")。
        -->
    <s:iterator value="linkList" status="bean">
   <tr>
    <td class="data_tab_tdcl">
     <s:property value="#bean.Index+1" />    </td>
    <td class="data_tab_tdcl"><s:property value="link_title" /></td>
    <td class="data_tab_tdcl"><s:property value="link_url" /></td>
    <td class="data_tab_tdcl">
    <s:if test="link_type == 1">
                   文字
                </s:if>
                <s:elseif test="link_type == 2">
                   图片
                </s:elseif>
                 <s:else>
                 -----
               </s:else>   
    </td>

   
    </body>
</html>
例1 condition.jsp
iterator 描述:
用于遍历集合(java.util.Collection)或枚举值(java.util.Iterator)。
参数:
名称必需默认类型描述status否String如果设置此参数,一个IteratorStatus的实例将会压入每个遍历的堆栈value否Object/String要遍历的可枚举的(iteratable)数据源,或者将放入新列表(List)的对象id否Object/String用来标识元素的id。在UI和表单中为HTML的id属性 例子:
<%@ page c %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ taglib prefix="s" uri="/struts-tags" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
    List list = new ArrayList();
    list.add("Max");
    list.add("Scott");
    list.add("Jeffry");
    list.add("Joe");
    list.add("Kelvin");
    request.setAttribute("names", list);
%>
<html>
    <head>
        <title>Iterator</title>
    </head>
    <body>
        <h3>Names: </h3>
        <!--
            1、此处的空property元素用于获得当前iterator的值
            2、status被设成stuts,在iterator的里面就可以通过#stuts取得IteratorStatus的对象。IteratorStatus类包含当前序号信息,如是否第一个或最后一个,是否为奇数序号。这些信息在我们做格式化的时候,显得非常有用。
        -->
        <ol>
            <s:iterator value="#request.names" status="stuts">                
                <s:if test="#stuts.odd == true">
                    <li>White <s:property /></li>
                </s:if>
                <s:else>
                    <li style="background-color:gray"><s:property /></li>
                </s:else>
            </s:iterator>
        </ol>
    </body>
</html>

posted @ 2008-10-13 15:46 金家寶 阅读(514) | 评论 (1)编辑 收藏

Java笔试题(部分)

     摘要: EJB 方面   94 、 EJB2.0 ...  阅读全文

posted @ 2008-10-09 11:56 金家寶 阅读(712) | 评论 (0)编辑 收藏

安装WinCVS时Python不可用的问题

在我装完Wincvs之后,提示我没有安装python,但后来我又装了python2.4,可Wincvs还是说配置不对.到底要怎么配置python呢?期待着您的回复,谢谢你了!
   
TCL or Python are not available, shell is disabled。
有的网友说是版本的问题,我今天安装时也是一样,装了好三四个版本,都一样,最后在CSDN上找到了答案。

解决办法:

在admin-〉Preferences->wincvs中有关于python的设置,  
  其中python是指你的python虚拟机的位置,一般是python2X.dll的位置。在你来说就是python24.dll的位置,一般这个文件会在你的系统文件中找到。  
  Tcl则一般会在python文件架的dlls子文件架中找到,一般名称为tclxx.dll,在你大概就是tcl84.dll。如果是安装python2.3版本的话,会自动找到,不需要设置。

设置好了,WinCVS输出窗口:

Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on win32Tk is available, Tk-macros are enabledTCL is available, shell is enabled : help (select and press enter)

posted @ 2008-09-21 08:52 金家寶 阅读(3601) | 评论 (1)编辑 收藏

[设计模式]jive中的[abstract Factory]

  AbstractFactory模式和可扩展性
  假如要实现较好的可扩展性,AbstractFactory模式确实是一件利器。如上面所说,假如要创建的Forum接口的不同实现,而又不想更改代码的话,就需要用到抽象工厂了。再Jive中,AuthorizationFactory类是一个抽象类,用来创建Authorization对象。这是一个抽象工厂,可以通过不同的子类来创建不同的Authorization对象。这个工厂的实现方法是:
  
  在AuthorizationFactory中使用一个private static变量factory,用来引用具体的抽象工厂的实例:
  private static AuthorizationFactory factory = null;
  
  用一个private static的String,来指明具体的抽象工厂的子类类名:
  private static String className ="com.coolservlets.forum.database.DbAuthorizationFactory";
  
  然后是用一个private static的loadAuthorizationFactory方法来给这个factory变量赋值,生成具体的抽象工厂类:
  
    private static void loadAuthorizationFactory() {
      if (factory == null) {
        synchronized(className) {
          if (factory == null) {
            String classNameProp = PropertyManager.getProperty(
              "AuthorizationFactory.className"
            );
            if (classNameProp != null) {
              className = classNameProp;
            }
            try {
              Class c = Class.forName(className);
              factory = (AuthorizationFactory)c.newInstance();
            }
            catch (Exception e) {
              System.err.println("Exception loading class: " + e);
              e.printStackTrace();
            }
          }
        }
      }
  }
  
  在static的getAuthorization方法返回一个Authorization的过程中,先初始化工厂类factory变量,然后用factory的createAuthorization方法来创建:
  
    public static Authorization getAuthorization(String username,
        String passWord) throws UnauthorizedException
    {
      loadAuthorizationFactory();
      return factory.createAuthorization(username, password);
  }
  
  不同的子类有不同的createAuthorization方法的实现。比如在DbAuthorizationFactory这个AuthorizationFactory的数据库实现子类中,createAuthorization方法是这样实现的:
  
    public Authorization createAuthorization(String username, String password)
        throws UnauthorizedException
    {
      if (username == null password == null) {
        throw new UnauthorizedException();
      }
      password = StringUtils.hash(password);
      int userID = 0;
      Connection con = null;
      PreparedStatement pstmt = null;
      try {
        con = DbConnectionManager.getConnection();
        pstmt = con.prepareStatement(AUTHORIZE);
        pstmt.setString(1, username);
        pstmt.setString(2, password);
  
        ResultSet rs = pstmt.executeQuery();
        if (!rs.next()) {
          throw new UnauthorizedException();
        }
        userID = rs.getInt(1);
      }
      catch( SQLException sqle ) {
        System.err.println("Exception in DbAuthorizationFactory:" + sqle);
        sqle.printStackTrace();
        throw new UnauthorizedException();
      }
      finally {
        try { pstmt.close(); }
        catch (Exception e) { e.printStackTrace(); }
        try { con.close();  }
        catch (Exception e) { e.printStackTrace(); }
      }
      return new DbAuthorization(userID);
    }
  
  在这个类中,可以看到抽象类和具体的子类之间的关系,它们是如何协作的,又是如何划分抽象方法和非抽象方法的,这都是值得注重的地方。一般的,抽象方法需要子类来实现,而抽象类中的非抽象方法应该所有子类所能够共享的,或者可是说,是定义在抽象方法之上的较高层的方法。这确实是一个抽象工厂的好例子!虽然实现的方法已经和GOF中给出的实现相差较远了,但思想没变,这儿的实现,也确实是要巧妙的些。
  
  还有就是静态方法的使用,使得这个类看起来有些Singleton的意味。这使得对于AbstractFactory的创建变得简单。
  
  在AuthorizationFactory中定义的其它方法,涉及到具体的如何创建Authorization,都是作为abstract方法出现,具体实现留给子类来完成。
  
  这样,在需要生成一个Authorization的时候,只需要调用AuthorizationFactory的静态方法getAuthorization就可以了,由子类实现了具体的细节。
  
  其它的,如同上面讲到的,在创建Forum的时候用的ForumFactory,具有同上面一样的实现,这就是模式之所以称为模式的所在了。
资料引用:http://www.knowsky.com/365144.html

posted @ 2008-09-16 15:57 金家寶 阅读(255) | 评论 (0)编辑 收藏

题目: IOC 后台机制学习

 
题目: IOC 后台机制学习
给定:
配置文件 config.txt, 文件内容
className = test.JavaBean1
field = username
value = ABC

该文件中的三个值会随时可能变化, 唯一不变的是 className 指定的都是一个 JavaBean(为了简化, 我们假定里面已经有一个 username 属性, 例如:

class JavaBeanxxxx {
    private String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String uname) {
        this.username = uname;
    }
}

要求: 写一段代码, 读取配置文件 config.txt, 然后实现把 className 指定的 JavaBean 类加载(注意这个类名是可以修改的, 可配置的), 然后生成一个实例,
并把配置文件中field字段指定的值作为这个实例的属性名(这里是username)所对应的值设置为 ABC(字符串), 并且要读出最后设置的值.

此题已经被 TigerTian 解答出来, 欢迎学习, 也感谢 TigerTian:
package com.gcoresoft.ioc;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.beans.*;

public class IOCStudy {
    
    
//Load the properties file
    private Properties prop=new Properties();
    
    
public void loadPropFile(String filename)
    {
        
try
        {
            FileInputStream fin
=new FileInputStream(filename);
            prop.load(fin);
            fin.close();
        }
catch(Exception e){
            System.out.println(e.toString());
        }
    }
    
    
private String getValueByName(String Name)
    {
        
return prop.getProperty(Name);
    }
    
    
public static void main(String[] args)
    {
        IOCStudy ioc
=new IOCStudy();
        ioc.loadPropFile(
"E:\\Work\\GetInIOC\\src\\com\\gcoresoft\\ioc\\Config.txt");
        
try
        {
            Class bean
=Class.forName(ioc.getValueByName("className"));
            
try {
                java.beans.BeanInfo info
=java.beans.Introspector.getBeanInfo(bean);
                java.beans.PropertyDescriptor pd[]
=info.getPropertyDescriptors();
                
try {
                    Method mSet
=null,mRead=null;
                    Object obj
=bean.newInstance();
                    
for(int i=0;i<pd.length;i++)
                        
if(pd[i].getName().equalsIgnoreCase(ioc.getValueByName("field")))
                        {
                            mSet
=pd[i].getWriteMethod();
                            mRead
=pd[i].getReadMethod();                            
                        }
                    
try {
                        mSet.invoke(obj, ioc.getValueByName(
"value"));
                        String str
=(String)mRead.invoke(obj, null);
                        System.out.println(str);
                    } 
catch (IllegalArgumentException e) {
                        
// TODO Auto-generated catch block
                        e.printStackTrace();
                    } 
catch (InvocationTargetException e) {
                        
// TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                } 
catch (InstantiationException e) {
                    
// TODO Auto-generated catch block
                    e.printStackTrace();
                } 
catch (IllegalAccessException e) {
                    
// TODO Auto-generated catch block
                    e.printStackTrace();
                }

                
            } 
catch (IntrospectionException e) {
                
// TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            
        }
catch(ClassNotFoundException e){
            System.out.println(e.toString());
        }
        
    }
    
}

posted @ 2008-08-27 20:41 金家寶 阅读(286) | 评论 (0)编辑 收藏