posts - 8, comments - 13, trackbacks - 0, articles - 43
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2011年5月22日

先简单回顾下sql语言的几种语言:ddl,dml,dcl,它们分别是:

ddl即data definition language,例如常用的:create,alter,drop,truncate,grant,revoke,comment;

dml即data manipulation language,我们经常使用的:select,insert,update,delete等都是数据操作语言。

dcl即data control language,数据控制语言,平时基本用不到,如commit,savepoint,rollback,set transaction。

 

所以区别主要在:

  • delete是dml语句,这个操作使用放在rollback segement里,事务提交后才生效,是可以回滚的;truncate是ddl语句,它不在rollback segement里的,事务自动提交,操作立即生效,没有回滚一说,除非自身失败;
  • 还有一个关键,虽然truncate是数据定义语言,但是truncate和delete操作一样,都只删除数据不删除表结构,两者的主要区别在于,truncate操作是没有备份的,所以它执行速度比delete快;而另一个ddl语句drop,将删除的是结构包括被依赖的触发器,索引,约束,依赖该表的存储过程会被保留。刚才又搜索了下truncate和drop操作之后数据也还是可以找回来的:http://dbsnake.com/2010/06/truncate-drop-recovery.html

posted @ 2011-05-22 12:12 kangaroo 阅读(273) | 评论 (0)编辑 收藏

1。xml背景

格式良好的(web-fromed)xml可以不需要文档类型定义(DTD),只要满足基本的xml格式规范就可以认为是格式良好的xml文档。但是格式标准,只能说明元素、标签、格式是合法的,并不能说明元素是有意义的,或者说规范的。

有效的xml文档,首先要求是格式良好的文档,同时遵守相应的DTD文件约束。

2。xml解析

xml文档解析的大致使用过程如下图:

 

 

 

由xml解析器解析和操作指定的xml文档,然后提供接口供应用程序使用。如果解析器不同,那么提供的接口就有可能不同。庆幸的是,目前所有的xml解析器对两套标准的api提供了支持,这两套标准api就是dom和sax。

dom:即document object model,文档对象模型,它是w3c组织推荐的处理xml的标准接口。dom是基于xml文档结构树的解析。

sax:即simple api for xml,它是非官方的、xml社区事实上的标准。sax是基于事件流的解析。

dom和sax只是定义了一些接口以及某些接口的缺省实现,应用程序要想利用dom或sax访问xml文档,还需要真正实现dom或sax接口的xml解析器。apache的xerces是一个使用非常广泛的解析器,它实现了dom和sax的调用接口,并提供了多种语言的实现版本。

3。java语言对xml文档的解析

首先介绍jaxp:

基于dom或sax提供的api接口,使用相应的解析器实现类我们已经可以对xml进行解析处理了。如下所示:

org.xml.sax.XMLReader sp=new org.apache.xerces.parser.SAXParser();

FileInputStream fis=new FileInputStream(“hello.xml”);

InputSource is=new InputSource(fis);

sp.setContentHandler(new MyConentHandler());

sp.parse(is);

为了屏蔽xml解析器的变化对代码的影响,java提供了一套标准的处理xml文件的接口(实际上是一些抽象的工厂类),使得java开发人员以一种标准的方式对xml进行编程,即jaxp(java api for xml processing)。jaxp没有提供解析xml的新方法,只是在解析器之上封装一个抽象层。在jdk1.6的文档中,我们可以看到javax.xml,org.w3c.dom,org.xml.sax包及其子包都属于jaxp的部分。jaxp由接口、抽象类和一些辅助类组成,符合jaxp规范的解析器实现其中的接口和抽象类,开发时只需要使用jaxp的api编程,底层的解析器对开发者时透明的,可以随意的切换。

那么jaxp出现后,java应用程序处理xml文档的过程就如下图:

 

那实际采用哪种解析器的jaxp实现,可以通过系统属性、properties文件等方式来配置。

下面具体介绍几种java解析xml的方法:

3.1 DOM方式(jaxp)

在javax.xml.parsers包中,定义了dom的抽象工厂类DocumentBuilderFactory,在这个类中有一个静态的方法newInstance(),通过它产生一个DocumentBuilderFactory的实例。前面提到过jaxp编程,解析器提供商必须继承该抽象类产生一个具体的解析器工厂,然后由这个工厂类实例出一个解析器对象,再通过该解析器对象处理xml文档。那么这个newInstance方法就是用来产生一个具体的解析器工厂类实例,查找生成解析器工厂类实例的方式可参考jdk文档。

在获取到解析器工厂类实例类之后,就可以调用newDocumentBuilder()方法创建一个dom解析器实例;dom解析器实例就可以调用parser()方法获取整个xml问答的Document对象。

3 .2 SAX方式(jaxp)

sax是基于事件驱动的api,sax解析xml文档时会向事件处理器发送不同的事件。sax解析器接口和事件处理器接口都在org.xml.sax包中定义。XMLReader即为sax定义的解析器接口,由解析器提供商实现该借口,应用程序需要做的是编写一个事件处理器。可以通过XMLReader的setContentHandler()方法来设置一个事件处理器的实例。

与dom类似,jaxp也为sax解析器提供了抽象工厂类SAXParserFactory类,sax解析器工厂类的实例与dom解析器工厂类的实例类似,都是通过newInstance()方法来创建,不同的是SAXParserFactory的newInstance()方法查找的工厂类属性是:javax.xml.parsers.SAXParserFactory。同样,获取sax解析器实例的方法,可以通过调用newSAXParser()。

使用SAXParser和XMLReader都可以用来对xml文档进行解析,前者只是对后者又一次的包装。

3.3 JDOM

dom被设计用于完成几乎所有的xml操作任务,同时又是与语言无关的,这就导致dom的api庞大而且复杂。为了使java程序员更方便地处理xml文档,两位国外的java技术专家创建了jdom。用developerworks上的一句话,“延续开源社群有需要就创建工具的历史传统,Java 技术专家 Jason Hunter 和 Brett McLaughlin 缔造了 JDOM”。所以可以认为,jdom是一种专门用于java语言解析xml文档的开放源代码框架。

jdom也使用对象树来表示xml文档,底层使用sax解析器分析xml文档,形成jdom树。

3.4 DOM4J

同jdom一样,dom4j也是应用于java平台,提供简单、灵活的处理xml文档的开发源代码库。很有意思的是,dom4j是由早期开发jdom的人分离出来而后独立开发的,(利益或意见不和?呵呵)与jdom相比,dom4j提供了更好的灵活性。从网上的评论可以看出,dom4j从性能、功能、易用性上都优于jdom,可以作为解析xml文件的首选。(看来后来分离出的那拨人选择还是正确的!)流行的hibernate,jaxm都采用了dom4j处理xml文件。

dom4j也使用sax解析器来分析xml文档,形成dom4j树;它也提供了用于大文档的基于事件的处理模型。

所以可以看出,jdom和dom4j只是开源社区产生出来的方便地解析xml的框架或工具,并没有创造新的xml解析方式。如果拿

拿以上四种解析xml的方法比较,用孙鑫老师的话,如果你需要频繁更换解析器就是jaxp方式,否则推荐使用dom4j。

posted @ 2011-05-22 11:25 kangaroo 阅读(717) | 评论 (0)编辑 收藏

2011年4月24日

netstat -an 查询所有连接和监听端口

lsof -i :port,使用lsof -i :port就能看见所指定端口运行的程序,同时还有当前连接。 


posted @ 2011-04-24 15:10 kangaroo 阅读(233) | 评论 (0)编辑 收藏

2011年4月23日

OAuth通过应用和微博授权页面之间的跳转来进行授权. 其步骤为

  1. 应用向微博平台发起请求,获得一个临时的oauth_token,和oauth_token_secret(A),这套key被称为request token.
  2. 应用将用户转向到微博授权页面,同时带上这个token和一个回调页面地址
  3. 用户在微博上同意授权后,会生成oauth_verifier(B),并在转向到回调页面是带上这个值.
  4. 应用通过$_REQUEST得到oauth_verifier,再加上之前(A)处的oauth_token和oauth_token_secret,向微博发起最后一次请求.
  5. 微博平台验证无误后,发给应用另外一套oauth_token和oauth_token_secret(C),这套key被成为access token.
  6. 拿到access token意味着应用已经获得了授权.之后应用就可以通过access token获取和发送微博了.

access token不用每次都去取,可以把它保存下来,供下次使用.这样性能更高.

posted @ 2011-04-23 19:57 kangaroo 阅读(573) | 评论 (0)编辑 收藏

2011年4月20日

pwd

posted @ 2011-04-20 21:08 kangaroo 阅读(413) | 评论 (0)编辑 收藏

2011年4月18日

sudo mysqld_safe 
sudo mysqladmin shutdown

posted @ 2011-04-18 22:24 kangaroo 阅读(1225) | 评论 (0)编辑 收藏

2011年3月31日

ll 命令查询出来的文件大小 单位是byte,
要想方便的查看出大小,使用“ll -h”

posted @ 2011-03-31 19:05 kangaroo 阅读(321) | 评论 (0)编辑 收藏

2011年3月29日

ctrl+shift+j:类似firebug的功能,开发时很实用
如果觉得太过复杂,可以使用firebug for chrome的插件,快捷F12,相当方便!

posted @ 2011-03-29 22:31 kangaroo 阅读(268) | 评论 (0)编辑 收藏

2011年2月17日

自动换行:ctrl+shift+w

posted @ 2011-02-17 11:47 kangaroo 阅读(218) | 评论 (0)编辑 收藏

2011年1月10日

XMind 快捷键

快捷鍵(Windows)

快捷鍵(Mac)

描述

Ctrl+N Command+N 建立新工作簿
Ctrl+O Command+O 開啟工作簿
Ctrl+S Command+S 儲存目前工作簿
Ctrl+Shift+S Command+Shift+S 儲存全部工作簿
Ctrl+W Command+W 關閉目前工作簿
Ctrl+Shift+W Command+Shift+W 關閉全部工作簿
Ctrl+P Command+P 列印
Ctrl+Z Command+Z 復原
Ctrl+Y Command+Y 重做
Ctrl+X Command+X 剪切
Ctrl+C Command+C 複製
Ctrl+V Command+V 貼上
Delete Delete 刪除
Ctrl+Home Command+Home 返回中心主題
Ctrl+A Command+A 選擇全部主題
Ctrl+Shift+A Command+Shift+A 選擇同層級主題
Ctrl+Alt+A Command+Alt+A 選擇子主題
Ctrl+F Command+F 尋找/取代
Ctrl++ Command++ 放大
Ctrl+- Command+- 縮小
Ctrl+= Command+= 正常大小
Ctrl+] Command+] 插入摘要
Alt+Enter Alt+Enter 屬性內容
Enter Enter 插入主題
Tab Tab 插入子主題
Shift+Enter Shift+Enter 在目前主題前插入主題
Ctrl+Enter Command+Enter 插入目前主題父主題
Ctrl+Shift+L Command+Shift+L 快捷鍵助手
Ctrl+I Ctrl+I 插入圖片
Ctrl+Shift+H Command+Shift+H 插入超連結
Ctrl+B Command+B 添加外框
Ctrl+L Command+L 添加關連
F2 F2 編輯主題
F3 F3 添加/編輯標籤
F4 F4 添加/編輯備註
F5 F5 簡報演示
F6 F6 下鑽
Shift+F6 Shift+F6 上鑽
F7 F7 智慧擷取圖面
+ + 展開目前分支
- - 收縮目前分支
* * 展開所有分支
/ / 收縮所有分支
Alt+Up Alt+Up 向前移動
Alt+Down Alt+Down 向後移動
Ctrl+T Command+T 建立新心智圖
Ctrl+1,2,3,4,5,6 Command+1,2,3,4,5,6 快速添加優先等級圖標
Esc Esc 關閉跳出的備註對話框 / 取消擷圖
Ctrl+滑鼠滾輪 Command+滑鼠滾輪 放大縮小目前的圖面

posted @ 2011-01-10 09:55 kangaroo 阅读(5592) | 评论 (0)编辑 收藏

2010年12月17日

ASCII是最初的计算机指定的一套符号编码,使用一个字节其中的7位,128个数值代表不同字符,对于英语这个已经是足够,
但是对于其他国家的语言,却远远不够,如汉语,日语,韩语,所以就出现了非ASCII的字符编码,如gbk2312,gbk的汉字编码。这些非ascii的编码都是兼容ascii128个符号编码的。

------------------------------------------------------------------------------------------------------------------------------------------------------

UNICODE首先只是一个字符集,它的出现就是因为各个国家出台自己的语言编码,为了统一这些所有语言,可以理解unicode是涵盖各个国家字符的集合,现在的规模可以容纳100多万个符号。需要说明的是,定长编码便于计算机处理(注意GB2312/GBK不是定长编码),而unicode又可以用来表示所有字符,所以在很多软件内部是使用unicode编码来处理的,比如java。
unicode只是一个符号集,只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储,即编码方式,常见的有utf-8和utf-16。
(如果unicode规定,每个符号用三个字节表示,那么英文字母只占用一个字节,就浪费很多存储空间。)
UTF-8就是一种变长的编码方式,它使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。


我们常用的记事本功能,在"save as"的时候,可以选择不同的编码方式,里面有四个选择:ansi,unicode,unicode big endian,utf-8:
1.ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,如果是繁体中文版会采用Big5码)。
2.Unicode编码指的是UCS-2编码方式,即直接用两个字节存入字符的Unicode码。这个选项用的little endian格式。

3.Unicode big endian编码与上一个选项相对应。我在下一节会解释little endian和big endian的涵义。

4.UTF-8编码,也就是上一节谈到的编码方法。



参考:

http://www.cnblogs.com/pony/archive/2009/02/05/1384323.html
http://blog.chinaunix.net/u1/56156/showart_2245355.html
http://liaoshaoyao.javaeye.com/blog/667056

posted @ 2010-12-17 10:50 kangaroo 阅读(1212) | 评论 (0)编辑 收藏

2010年12月16日

MD5是一种摘要生成算法,本来不能用于签名,但是在待签名数据之后加上一串私密内容,即散列码,就可以用于签名了。但是md5只能做到防篡改的功能,不能做到防抵赖,因为这串私密内容双方是都知道的。

DSA和RSA是一种非对称加密算发,签名密钥分为公钥和私钥。私钥用于加密,公钥用于验证签名。使用这种算法的签名即起到防篡改的功能,又起到防抵赖的作用。因为私钥只有签名者自己独有。

posted @ 2010-12-16 11:43 kangaroo 阅读(4942) | 评论 (1)编辑 收藏

2010年12月14日

/*给创建bitmap index分配的内存空间参数,以加速建索引*/

show parameter create_bit;

/*改变索引的存储参数*/

alter index index_name pctfree 30 storage(initial 200k next 200k);

/*给索引手工分配一个分区*/

alter index index_name allocate extent (size 200k datafile '$ORACLE/oradata/..');

/*释放索引中没用的空间*/

alter index index_name deallocate unused;

/*索引重建*/

alter index index_name rebuild tablespace tablespace_name;

/*普通索引和反转索引的互换*/

alter index index_name rebuild tablespace tablespace_name reverse;

/*重建索引时,不锁表*/

alter index index_name rebuild online;

/*给索引整理碎片*/

alter index index_name COALESCE;

/*分析索引,事实上是更新统计的过程*/

analyze index index_name validate structure;

desc index_state;

drop index index_name;

alter index index_name monitoring usage;-----监视索引是否被用到

alter index index_name nomonitoring usage;----取消监视

/*有关索引信息的视图*/

select * from dba_indexes/dba_ind_columns/dbs_ind_eXPressions/v$object_usage;

########## 数据完整性的治理(Maintaining data integrity) ##########

alter table table_name drop constraint constraint_name;----drop 约束

alter table table_name add constraint constraint_name primary key(column_name1,column_name2);-----创建主键

alter table table_name add constraint constraint_name unique(column_name1,column_name2);---创建唯一约束

/*创建外键约束*/

alter table table_name add constraint constraint_name foreign key(column_name1) references table_name(column_name1);

/*不效验老数据,只约束新的数据[enable/disable:约束/不约束新数据;novalidate/validate:不对/对老数据进行验证]*/

alter table table_name add constraint constraint_name check(column_name like 'B%') enable/disable novalidate/validate;

/*修改约束条件,延时验证,commit时验证*/

alter table table_name modify constraint constraint_name initially deferred;

/*修改约束条件,立即验证*/

alter table table_name modify constraint constraint_name initially immediate;

alter session set constraints=deferred/immediate;

/*drop一个有外键的主键表,带cascade constraints参数级联删除*/

drop table table_name cascade constraints;

/*当truncate外键表时,先将外键设为无效,再truncate;*/

truncate table table_name;

/*设约束条件无效*/

alter table table_name disable constraint constraint_name;

alter table table_name enable novalidate constraint constraint_name;


简洁实用,谢谢http://wfly2004.blog.163.com/blog/static/11764272010629114155174/

http://hi.baidu.com/zhangcheng1/blog/item/54deb0cc9ab69d1701e9281e.html

posted @ 2010-12-14 17:45 kangaroo 阅读(10010) | 评论 (0)编辑 收藏

2010年12月12日


找到一份比较清楚的文章:
同事写过的记录数组的用法,很棒!
|grep ","|awk -F ","  '{print $10}'| awk -F ":" '{hist[$1]++} END{for(i in hist) printf "%s %d\n", i, hist[i]}'

posted @ 2010-12-12 20:44 kangaroo 阅读(931) | 评论 (0)编辑 收藏

早上去博库看了一会PHP+Mysql核心开发的书,研一的时候就是这本书搞定的课程设计。
php,服务器端脚本语言。每次请求之后,先由web服务器解释执行后,在以html输出到客户端。
相对于java sverlet容器的tomcat,php的编译引擎可以嵌入到apache或iis这类web服务器中。

posted @ 2010-12-12 15:57 kangaroo 阅读(260) | 评论 (0)编辑 收藏

2010年10月12日

今天在使用淘宝openapi做试验,通过nick查询用户的其他公开信息,在eclipse中java application运行测试类没有问题,但是放在web工程中就不行了,jetty启动工程后报错:一些taobao.api中的类如DefaultTaobaoClient,UserGetRequest不存在。

 
研究一下发现,因为在eclipse里面,淘宝api的jar包是以第三方jar的形式导入进来的,所以在eclipse中访问是没有问题的,但是如果是web工程打包时,是不包括第三方jar包的,所以结果是,不论是jetty还是tomcat中启动都会出现第三方jar的类无法找到的错误。

解决的办法是,将这些第三方jar包install到本地maven库,命令如:
mvn install:install-file -Dfile=E:/08_library/taobao_sdk/taobao-sdk-java/taobao-sdk-java.jar -DgroupId=tanlun.taobao.openapi -DartifactId=taobaosdk -Dversion=0.2 -Dpackaging=jar
之后在web工程的pom.xml文件中加入对该jar的依赖,这样重新mvn eclipse:eclipse,之后再mvn jetty:run就没有问题了。

posted @ 2010-10-12 16:09 kangaroo 阅读(1630) | 评论 (0)编辑 收藏

2010年10月9日

简单的说,jvm的堆是存放对象的地方,栈存放的是基本数据类型和对象的引用。jvm栈是运行时的单位,jvm堆是存储的单位。java中每个线程都有一个栈与之对应,这个很容易理解,每一个线程都有其特殊的执行流程逻辑,因此需要一个独立的线程栈与之对应。jvm栈因为是运行时单位,所以里面存储的信息都是跟当前线程相关的东西,如局部变量、运行时状态,返回值等。而jvm堆是真正存放数据的地方,多个jvm栈可以共享堆中的数据。
jvm堆和栈分离的好处,从软件设计的角度看,栈代表处理逻辑,堆代表数据,分而治之,逻辑更加清楚。因为堆中的内容可以被共享,节省了空间。从面向对象的角度,对象的属性,即数据,被存放在堆中,而对象中的方法,则是运行逻辑,存放在栈中。
平时我们在eclipse启动程序,我们可以通过-Xms,-Xmx来设置大小,其实是在设置初始堆空间,和最大堆空间的大小。

posted @ 2010-10-09 17:19 kangaroo 阅读(530) | 评论 (0)编辑 收藏

2010年9月25日

本想就OAUTH进行一下流程分析,看到原网站的内容已经足够简明,请访问:
然后看下中文的:

明白了OAUTH的工作原理之后,我就在想,现在原有的webservice的方式,不是也可以实现不同网站之间通过api的形式来资源共享吗,那OAUTH又有什么好处了。
看了一些文章之后,我的认识可能是,在跨语言的webservice调用时,实现细节上还是有很多差异,特别是复杂的对象类型。
转换成REST方式的服务之后,对服务的发布者和使用者来说都是轻量级的。
那OAUTH正是在REST基础上api的安全校验和授权的一种方式。

posted @ 2010-09-25 16:00 kangaroo 阅读(1155) | 评论 (0)编辑 收藏

spring给我们提供了非常简便的线程池管理的包装类ThreadPoolTaskExecutor,本地启动一个为异步任务创建线程池的方法:
 
1<bean id="threadPoolTaskExecutor"
2        class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
3        <property name="corePoolSize" value="5" />
4        <property name="maxPoolSize" value="10" />
5        <property name="queueCapacity" value="25" />
6    </bean>
corePoolSize:默认开启线程数;maxPoolSize:最大线程数;queueCapacity:缓冲任务队列的长度;
创建线程的方式:
1threadPoolTaskExecutor.execute(new Runnable() {
2                public void run() {
3                   //异步任务
4                }
5            });

posted @ 2010-09-25 11:29 kangaroo 阅读(7917) | 评论 (0)编辑 收藏

2010年9月9日

本地起tomcat之后,配置服务器也可以使用https协议访问的方式是方便:

1. 创建证书
    进入到你的jre/bin文件夹下,键入“keytool -genkey -alias tomcat -keyalg RSA -keystore c:/.keystore”,默认将把证书保存在你的C盘根目录下。在申请的过程中密码请填写“changeit”,这是tomcat的默认密码。
2. 修改server.xml
    进入到你的$CATALINA_HOME/conf/server.xml,打开后寻找:
<!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
    
<!--
    <Connector port="8443" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />
-->
    修改如下:
<!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
    
    
<Connector port="8443" maxHttpHeaderSize="8192"
               maxThreads
="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups
="false" disableUploadTimeout="true"
               acceptCount
="100" scheme="https" secure="true"
               clientAuth
="false" sslProtocol="TLS" keystoreFile="c:\.keystore"/>
3. 重启你的tomcat,使用端口8443访问即可。

posted @ 2010-09-09 10:45 kangaroo 阅读(661) | 评论 (0)编辑 收藏

2010年9月5日

刚开始的时候经常会把这两类的方法搞混了,慢慢接触多了,一定要弄清楚了。
(1)管理线程的方法
start:不用多说,启动一个线程的方法。调用该方法后,线程即进入可运行状态,也就是进入可运行的线程池了。
sleep:线程休眠,将一个运行时的线程,将其状态变为可运行状态,然后加入到和其他处于可运行状态下的线程抢夺运行机会。换句话说,sleep的时间是该线程不执行的最短时间。
yield:使得当前线程进入可运行状态,以允许具有相同状态优先级的其他线程获得运行机会。但是不保证,刚进入可运行状态,又被选中进入运行状态。
join:非静态方法join,有点抢线程的意思。一旦某个线程实例t调用join方法,则当前线程变为可运行状态,直到线程t运行完毕为止。
(2)线程间协作的方法

posted @ 2010-09-05 23:06 kangaroo 阅读(507) | 评论 (0)编辑 收藏

在平时开发中,我们经常采用HashMap来作为本地缓存的一种实现方式,将一些如系统变量等数据量比较少的参数保存在HashMap中,并将其作为单例类的一个属性。在系统运行中,使用到这些缓存数据,都可以直接从该单例中获取该属性集合。但是,最近发现,HashMap并不是线程安全的,如果你的单例类没有做代码同步或对象锁的控制,就可能出现异常。

首先看下在多线程的访问下,非现场安全的HashMap的表现如何,在网上看了一些资料,自己也做了一下测试:

 1public class MainClass {
 2    
 3    public static final HashMap<String, String> firstHashMap=new HashMap<String, String>();
 4    
 5    public static void main(String[] args) throws InterruptedException {
 6        
 7        //线程一
 8        Thread t1=new Thread(){
 9            public void run() {
10                for(int i=0;i<25;i++){
11                    firstHashMap.put(String.valueOf(i), String.valueOf(i));
12                }

13            }

14        }
;
15        
16        //线程二
17        Thread t2=new Thread(){
18            public void run() {
19                for(int j=25;j<50;j++){
20                    firstHashMap.put(String.valueOf(j), String.valueOf(j));
21                }

22            }

23        }
;
24        
25        t1.start();
26        t2.start();
27        
28        //主线程休眠1秒钟,以便t1和t2两个线程将firstHashMap填装完毕。
29        Thread.currentThread().sleep(1000);
30        
31        for(int l=0;l<50;l++){
32            //如果key和value不同,说明在两个线程put的过程中出现异常。
33            if(!String.valueOf(l).equals(firstHashMap.get(String.valueOf(l)))){
34                System.err.println(String.valueOf(l)+":"+firstHashMap.get(String.valueOf(l)));
35            }

36        }

37        
38    }

39
40}

上面的代码在多次执行后,发现表现很不稳定,有时没有异常文案打出,有时则有个异常出现:


为什么会出现这种情况,主要看下HashMap的实现:
 1public V put(K key, V value) {
 2    if (key == null)
 3        return putForNullKey(value);
 4        int hash = hash(key.hashCode());
 5        int i = indexFor(hash, table.length);
 6        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
 7            Object k;
 8            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
 9                V oldValue = e.value;
10                e.value = value;
11                e.recordAccess(this);
12                return oldValue;
13            }

14        }

15
16        modCount++;
17        addEntry(hash, key, value, i);
18        return null;
19    }

我觉得问题主要出现在方法addEntry,继续看:
1void addEntry(int hash, K key, V value, int bucketIndex) {
2    Entry<K,V> e = table[bucketIndex];
3        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
4        if (size++ >= threshold)
5            resize(2 * table.length);
6    }

从代码中,可以看到,如果发现哈希表的大小超过阀值threshold,就会调用resize方法,扩大容量为原来的两倍,而扩大容量的做法是新建一个Entry[]:
 1void resize(int newCapacity) {
 2        Entry[] oldTable = table;
 3        int oldCapacity = oldTable.length;
 4        if (oldCapacity == MAXIMUM_CAPACITY) {
 5            threshold = Integer.MAX_VALUE;
 6            return;
 7        }

 8
 9        Entry[] newTable = new Entry[newCapacity];
10        transfer(newTable);
11        table = newTable;
12        threshold = (int)(newCapacity * loadFactor);
13    }

一般我们声明HashMap时,使用的都是默认的构造方法:HashMap<K,V>,看了代码你会发现,它还有其它的构造方法:HashMap(int initialCapacity, float loadFactor),其中参数initialCapacity为初始容量,loadFactor为加载因子,而之前我们看到的threshold = (int)(capacity * loadFactor); 如果在默认情况下,一个HashMap的容量为16,加载因子为0.75,那么阀值就是12,所以在往HashMap中put的值到达12时,它将自动扩容两倍,如果两个线程同时遇到HashMap的大小达到12的倍数时,就很有可能会出现在将oldTable转移到newTable的过程中遇到问题,从而导致最终的HashMap的值存储异常。

JDK1.0引入了第一个关联的集合类HashTable,它是线程安全的。HashTable的所有方法都是同步的。
JDK2.0引入了HashMap,它提供了一个不同步的基类和一个同步的包装器synchronizedMap。synchronizedMap被称为有条件的线程安全类。
JDK5.0util.concurrent包中引入对Map线程安全的实现ConcurrentHashMap,比起synchronizedMap,它提供了更高的灵活性。同时进行的读和写操作都可以并发地执行。

所以在开始的测试中,如果我们采用ConcurrentHashMap,它的表现就很稳定,所以以后如果使用Map实现本地缓存,为了提高并发时的稳定性,还是建议使用ConcurrentHashMap。


====================================================================

另外,还有一个我们经常使用的ArrayList也是非线程安全的,网上看到的有一个解释是这样:
一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。
在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也将元素放在位置0,(因为size还未增长),完了之后,两个线程都是size++,结果size变成2,而只有items[0]有元素。
util.concurrent包也提供了一个线程安全的ArrayList替代者CopyOnWriteArrayList。



posted @ 2010-09-05 17:12 kangaroo 阅读(12165) | 评论 (5)编辑 收藏

2010年8月17日

基本:
1. find -name #filename#:按文件名在本目录下的所有文件里查找指定名字的文件,可用正则。
2. more #filename#:更方面的查看文件的命令。进入后命令,"d":向下滚动;"b":向上滚动。
3. vi #filename#:一般的文件编辑命令。进入后命令
    "/abc":查找"abc",所有匹配"abc"的地方都会高亮显示。

4. vi替换文件中所有“abc”为“def”命令:

   %s/abc/def/g 其中%表示替换所有行,g表示替换每一行所有匹配的字符串

技巧:
1. ll -t:按修改时间的先后排序文件。

posted @ 2010-08-17 13:53 kangaroo 阅读(556) | 评论 (0)编辑 收藏

2010年8月6日

持续记录下自己遇到的java编码技巧:

1. java.util.List.addAll(Collection<? extends String> c)

public static void main(String[] args) {

        List
<String> firstList = new ArrayList<String>();
        firstList.add(
"a");
        firstList.add(
"b");
        firstList.add(
"c");

        List
<String> secondList = new ArrayList<String>();
        secondList.addAll(firstList);

        
for (String s : secondList) {
            System.out.println(s);
        }

    }

posted @ 2010-08-06 19:15 kangaroo 阅读(317) | 评论 (0)编辑 收藏

2010年8月3日

1. 前言
2. webservice的由来
3. java领域可用于实现远程通讯的开源框架或library
4. 基于XFire的webservice的本地实现


附件下载:
(1)http://www.blogjava.net/Files/lukangping/webservice.pdf
(2)......

posted @ 2010-08-03 19:22 kangaroo 阅读(233) | 评论 (0)编辑 收藏

2010年8月1日

记得在当时学习uml总是不好分清聚合与组合的关系,找工作时特地复习了这块的内容,结果正巧被面试官问道,这两天又在搞这块的内容,对聚合与组合有了更清楚的了解:

聚合:表示两个对象之间是整体和部分的关系,部分的生命周期可以超越整体。如电脑和鼠标,就可以用一下图形表示:



组合:表示两个对象之间是整体和部分的关系,部分的生命周期不能超越整体,或者说不能脱离整体而存在。组合关系的“部分”,是不能在整体之间进行共享的。如人和眼睛的关系:

不过,如果你要说,眼睛可以移植,是不是说可以脱离人而存在,它们就不是组合关系了?其实,UML中对象的关系都是在相应的软件环境或实际场景下定义的,这里区别聚合和组合的关系,关键还是在于它们之中整体和部分的关系强、弱,以及它们之间的依附关系。如果刚才说眼睛可以移植给别人,那你也可以把它认为是聚合,这都要结合实际场景来说明。

另外两个比较重要的关系是关联和依赖:
关联:简单的可以认为,如果一个类作为了另外一个类的属性,那一定是关联关系。但你要知道,聚合是一种特殊的关联,而组合又是一种特殊的聚合。一般的关联我们认为是平级的、无整体部分关系的,如朋友关系。

依赖:对象之间的临时关系,临时性体现在不超越方法的周期。简单的说,在方法使用到的,如参数类,就一定是依赖关系。

最后想说一句,实际工作中,我并没有发现区分这四种关系有多么大的用处,也许自己还没有碰到,只是觉得可能每个学习它的同学总想把它搞清楚,但实际工作中作用并不明显。

posted @ 2010-08-01 14:17 kangaroo 阅读(27050) | 评论 (5)编辑 收藏

打开visio想创建一个类图,却发现没有找到UML Model Diagram,从网上看到可以在UML Static Structure里找到“Class”,但是发现使用起来很不方便,甚至不好增加类名,就在网上搜索一下,中文的没有提到,就搜索了一下“uml model diagram  template download”,在
http://softwarestencils.com/uml/index.html#Visio2007
找到了需要的template,然后解压到"C:\Documents and Settings\<user name>\My Documents\My Shapes",重新启动Visio,默认的快速创建页面就有UML Model Diagram。That is it!

posted @ 2010-08-01 13:41 kangaroo 阅读(2184) | 评论 (1)编辑 收藏

2010年7月29日

同标题,持续记录一些eclipse的高级快捷键,提高你的“专业性”,成为快捷键达人:

慢慢发现很多软件的快捷键都是相似的,用得多了,你就不用费脑子记了,这个很不错。

1. ctrl+滚轮:加快浏览速度;
2. ctrl+w:关闭当前的Editor;
3. ctrl+e:显示隐藏的Editor;
4. ctrl+f6:切换editor;
5. ctrl+f7:切换view;
6. ctrl+f8:切换perspectives;
7. ctrl+shift+x:小写变大写;ctrl+shift+y:大写变小写
8. ctrl+1:出现红叉时,鼠标放置在该行,使用这个快捷键迅速弹出错误提示

9. ctrl+shift+c:注释xml里配置

SecureCRT中常用的快捷键:

1. ctrl+tab:标签直接的切换;
2. alt+1/2/3..:切换至第n个标签;


Chrome必会快捷键 bravo chrome! i like so much!
1. ctrl+t:新建标签;ctrl+n:新开窗口
2. ctrl+w:关闭当前标签页
3. ctrl+tab:切换到下个标签;ctrl+shift+tab:切换到上一个标签
4. ctrl+1/2/../8:切换至指定标签
5. f6:聚焦鼠标至地址栏,这个各个浏览器都一样。

more:http://news.xinhuanet.com/internet/2008-09/07/content_9822978.htm
existing: 新建标签打开后,你会看到8个最近访问的网站,首先,可以用tab切换,另外,它们的位置可以拖拽、可以删改,还不让你兴奋吗?


posted @ 2010-07-29 14:09 kangaroo 阅读(2104) | 评论 (0)编辑 收藏

2010年7月28日

Exception in thread “main” org.codehaus.xfire.XFireRuntimeException: Could not  invoke service.. Nested exception is org.codehaus.xfire.fault.XFireFault: There must be a method name element.

解决办法还是很简单:将wsdlURL后面的”?wsdl”去掉即可:

Service serviceModel = new ObjectServiceFactory().create(MyService.class);
MyService service = (MyService) new XFireProxyFactory().create(serviceModel,
            “http://localhost:8080/ninthDemo/services/myService“);

posted @ 2010-07-28 13:25 kangaroo 阅读(819) | 评论 (0)编辑 收藏

2010-07-19 16:17:42.670::WARN:  failed HandlerCollection@7f8922
java.lang.UnsupportedClassVersionError: Bad version number in .class file

使用mvn clean情况一下编译好的文件,重新mvn jetty:run就好了。

posted @ 2010-07-28 13:24 kangaroo 阅读(392) | 评论 (0)编辑 收藏

通常我们听到的代理大致有三类:http/s proxy, socks proxy and VPN (实际上不是代理)。

其中http/s proxy, socks proxy属一类,作为代理服务器,它们类似一种网络访问的中介,每次我们访问一个web网站时,实际上时先去访问代理服务器,再由代理服务器访问目标网站。而且这样是匿名,也就是说被请求的网站并不知道你的原始的访问地点在哪里。网上流传的gappproxy翻墙就是一个典型的例子,在gae上建立一个代理服务器fetchserver后,然后在本机开启gappproxy的代理程序,每次访问任何网站时,其实是把请求发给代理服务器,然后由代理服务器去请求目标网站,因为gae都是在美国的服务器,同时目前访问gae还是ok的,所以整个过程都是没问题的。(我们知道GFW是通过黑名单来过滤访问指定网站的数据包,如果把gae服务器也纳入黑名单,那就杯具了。)

如果只是网上冲浪或者通过浏览器使用的活动,那样的话http/s proxy就可以了,像GAE中的gappproxy就是其中的一个例子。如果你需要做更多的事情,而不仅仅是websurf,那样就需要使用socks proxy,它能更灵活地为你提供除了网页浏览其他的一些功能。那VPN又是什么呢?VPN,Virtual private Network,中文名是“虚拟专用网络”。一个简单的解释就是,在公共网络中建立的两点之间的专用的虚拟隧道。也可以理解为虚拟出来的企业内部专线。安全通信是通过加密来保证的,加密算法运用运用于你的实时通信中,保证在公用的网络中两点之间的数据通信不被其他人截取或访问,也就是说,在两点之间建立了一个专用的“隧道”。

相比较来看,proxy server有很多的免费的解决方案,它也能提供匿名的web browsing。但是,安全性就差很多,你和代理服务器之间的通讯是完全透明的。(SSL proxy可以进行适当的保护),与VPN相比,代理的速率也比较低。VPN比http/s proxy和socks proxy的安全性就高很多了。VPN需要更多的硬件和软件来支持,所以它是需要付费的。当然它的速率也是最高。除此之外,VPN加密本台机器上的所有网络通信,包括你的browsing,email,voip,chat等所有网络传输。而不像http/s proxy只对你的浏览器访问web网站做代理。

以上文字参考:

《Proxy vs VPN… Who wins?》

《what is a VPN service?》

posted @ 2010-07-28 13:23 kangaroo 阅读(2637) | 评论 (0)编辑 收藏

2010年7月27日

blogjava的博客半年前玩的,后来忙了就忘了,发现有些内容之前写下的,现在都不认识,学到的知识没有延续,所以今天特意整理一下文章分类,慢慢使得自己在技术方面的积累不断的形成体系。

posted @ 2010-07-27 22:53 kangaroo 阅读(214) | 评论 (0)编辑 收藏

2009年11月1日

Pure Pleasure - Reborn © 2008 - 转载本文时请保留此链接。

1. 培养耐心

自信确实需要培养,所谓的“培养”,即是说并非朝夕可达。所以,培养自信的最重要前提就是要具备耐心,如若缺乏耐心就要培养耐心。没有耐心的话就什么都做不成,更别提什么“自信了”。有所成就,就会伴随着自信的增长,而一事无成的人穿得再整齐也只不过草包一个。

2. 习得并精通一种技能

具备学习能力的人通常都很自信,反过来也一样,真正自信的人通常是因为相信自己的学习能力。所以面对挑战的时候他们不会怕,不会心虚,因为他们知道“大不了去学么”。自学能力的基础是耐心,而习得任何一种技能都会让人更加懂得耐心的重要,并且同时因为具备耐心与学习能力而更加自信。只要花时间真正精通了一种技能,那么学会其他一种技能的时候就会变得更轻松——这是良性循环。

--遇到枯燥,不好玩的东西,能够静下心来,耐心地去学习、去体会,这个应该是学习能力强和弱的差别之处吧。
--久而久之,学习快的人,会将这种经验不断推广,一门通,样样通。而在一方面没有成就的人,会慢慢产生了厌烦的情绪,在拒绝学习的同时,也就表现出在这个方面的自卑了。

3. 相信积累的力量
再大的石头也无法阻挡种子发芽,只因为种子一旦开始发芽,那细胞的分裂尽管速度不快但却不见天日永不终止。滴水可以穿石的道理谁都懂但又好像谁都不相信—— 处于起点的人就好像是一粒细胞或者一滴水,但大多数人却误以为或者希望自己在起点上就强大锋利犹如一束激光,但这不现实。要通过学习培养耐心,运用耐心去等待长期积累之后可以获得的难以想象的好处与力量。


--如果在某一方面学习的时候,就是不顺利,或者就是理解不好的时候,这个时候,就是需要坚持的时候了。
--记得自己学游泳,换气总是不好,曾一度觉得我这辈子都学不会游泳了。但是总觉得好玩,虽然每次游都被会游的伙伴笑话,还不敢去深水呀?但也是当个玩笑听了。后来,终于有一次,自己突然地发现,换气换得很自然了,鼓足了勇气去深水区游了一趟,那一天自己感觉到很开心,自信得很多。
--任何事物的学习应该都有个“窍”,当一次,两次,三次不理解时候,不需要急躁,明白看来这个东西不是那么简单的,需要以后更多的阅读或实践才来理解透彻。

4. 了解自己的局限

没有人无所不能。就算拥有真正强大学习能力的人也无法做到无所不能——因为时间不够。有些领域确实必需天分。在自己确实不擅长的地方该自卑就要自卑——这没有什么不好意思的。该自卑的时候不自卑,就多了一个心理负担——并且还是永远摆脱不掉的负担,最终,肯定会拖累自信。凡事儿做得好必然容易自信,做得不好就很难自信,但是还没上阵呢,就背着一个又一个的包袱,能走多远?能做多好?

--哎呀,这个东西实在跟我不投缘,这样的话会让自己轻松很多。(当然,这样的话要在你坚持努力尝试多次之后说了才有用)

5. 凡事儿都要提前做足功课

大声说话也好,穿着正式也罢,最多只能让一个人“显得”自信,而非真正自信。“坐在第一排”可能是因为近视,“快速走路”往往是因为时间观念不强——这些都与自信没关系。做任何事情,提前做足了功课,想不自信都难。自信不等于自以为是,自以为是的人最终都会被现实砸烂。中国人说“成事在天,谋事在人”,西方人说“上帝的归上帝,凯撒的归凯撒”,某个层面上都是一回事儿:不要理会运气(该来的时候它自然会来),重要的是专心做好功课。

--查看线上错误日志的方法,会了吗?还不赶紧去找?

posted @ 2009-11-01 12:17 kangaroo 阅读(425) | 评论 (0)编辑 收藏

iBatis是一个中层的框架,它比jdbc的层次高一些(可以说,iBatis就是以XML的形式描述的jdbc代码,它拥有许多jdbc所没有的架构级的优点),但是对于对象/关系映射工具,层次又要低一些。

1. 释放数据库资源
使用jdbc时,很容易犯的错误就是获取资源之后忘记正确地释放它们。虽然垃圾收集进程最终可以释放掉这些资源,但是这种做法非常耗时,并且无法得到保证。如果对象没有别真正释放,那应用程序最终将会因为耗尽了资源而崩溃。iBATIS框架能帮助管理这些资源,从而减轻应用程序对开发人员们的负担

2. SQL注入
如果某个应用程序使用字符串拼接的方式来创建SQL语句,但是没有正确地对参数进行转义,那么恶意的用户就可以通过传递一些特殊的参数来改变查询原本的意图。
例如:select * from product where id = 5.
如果5是用户传递过来的参数,拼接到 id = 之后的。那么用户就可以输入"5 or 1 = 1",从而改变了整个SQL语句的意图。如果用户更坏一些,输入"5;delete from orders",结果就是你的订单表被清空了。
由于ibatis使用了preparedStatement,而PreparedStatement是不会受到此类攻击影响的,所以使用ibatis可以使得你对应用程序的保护变得更加容易。

3. 降低复杂度

posted @ 2009-11-01 11:28 kangaroo 阅读(516) | 评论 (1)编辑 收藏

2009年8月26日

1. 发现你上司的性格和脾气,向他的性格和行为方式靠拢。
2. 如果上司对下面的人有什么小小的要求和帮助,作为下属你一定要非常非常重视,这个很重要!

posted @ 2009-08-26 09:21 kangaroo 阅读(249) | 评论 (0)编辑 收藏

2009年8月15日

这篇文章写在我研究J2SE、J2EE近三年后。前3年我研究了J2SE的Swing、Applet、Net、RMI、Collections、IO、JNI……研究了J2EE的JDBC、Sevlet、JSP、JNDI…..不久我发现这些好像太浮浅了:首先,我发现自己知道的仅仅是java提供的大量的API,根本不能很好地使用它; 其次,我根本就没有学到任何有助于写程序的知识,此时我也只不过能写个几页的小程序。出于这个幼稚的想法我研究了JDK中Collections、Logger、IO…..的源代码,发现这个世界真的很神奇,竟然有如此的高手――利用java语言最最基本的语法,创造了这些优秀的Framework。

从此一发不可收拾,我继续研究了J2EE的部分,又发现这是一个我根本不能理解的方向(曾经有半年停滞不前),为什么只有接口没有实现啊!后来由于一直使用Tomcat、Derby等软件突然发现:哦!原来J2EE仅仅是一个标准,只是一个架构。真正的实现是不同提供商提供的。

接着我研究了MOM4J、OpenJMS、Mocki、HSQLD……发现这些就是J2EE的实现啊!原来软件竟会如此复杂,竟会如此做….规范和实现又是如何成为一体的呢?通过上面的研究发现:原来J2EE后面竟然有太多太多理念、太多太多的相似!这些相似就是其背后的理念――设计模式!(很幸运,在我学java的时候,我一般学java的一个方向就会读一些关于设计模式的书!很幸运,到能领略一点的时候能真正知道这是为什么!)其实模式就是一种思维方式、就是一种理念……模式是要运用到程序中的,只有从真正的项目中才能领会模式的含义……
学得越多,发现懂得越少!在学习过程中发现一些很有用,很值得学习的开源项目,今天在此推荐给大家。

一、JavaServlet和JSP方向

很多人都是从Servlet和JSP步入J2EE的。它就是J2EE的表现层,用于向客户呈现服务器上的内容。J2EE很重要的方面。不罗嗦了!大家都知道的!下面就开始推荐吧!

1. Jakarta Tomcat

Apache基金会提供的免费的开源的Serlvet容器,它是的Jakarta项目中的一个核心项目,由Apache、Sun和其它一些公司(都是IT界的大鳄哦)及个人共同开发而成,全世界绝大部分Servlet和Jsp的容器都是使用它哦!由于Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中得到体现。

不过它是一个非常非常全的Serlvet容器,全部源码可能有4000页,对于初学者或者一般的老手可能还是比较大了!在你有能力时推荐研究!下载地址:http://jakarta.apache.org/tomcat/index.html

下面推荐两个小一点的吧!

2. Jetty

Jetty是一个开放源码的HTTP服务器和Java serverlet容器。源代码只有1000页左右,很值得研究。有兴趣可以去http://jetty.mortbay.com/下载看看。我曾经翻了一下,只是目前没有时间。(都化在博客上了,等博客基本定型,且内容完整了,再干我热衷的事件吧!)

3. Jigsaw

Jigsaw是W3C开发的HTTP,基于Java 的服务器,提供了未来 Web 技术发展的蓝图。W3C知道吧!(太有名气了,很多标准都是它制订的!有空经常去看看吧!)下载网址:http://www.w3.org/Jigsaw代码仅仅1000页左右。

4. Jo!

Jo!是一个纯Java的实现了Servlet API 2.2, JSP 1.1, 和HTTP/1.1的Web服务器。它的特性包括支持servlet tag,支持SSI,高级线程管理,虚拟主机,数据缓存,自动压缩text或HTML文件进行传输,国际化支持,自动重新加载Servlet、Jsp,自动重新加载web工程文件(WARs),支持WAR热部署和一个Swing控制台。jo!可以被用做jboss和jakarta avalon-phoenix的web容器。下载地址http://www.tagtraum.com/ 。我极力推荐大家在研究Tomcat之前研究该软件,主要是其比Tomcat小多了,且开发者提供比较全的手册。该方向研究这两个也就可以了!

二、JDBC方向

很多人都喜欢JDBC,数据库吗!很深奥的东西,一听就可以糊弄人。其实等你真正研究了数据库的实现后发现,接口其实真的太简单,太完美了!要想设计如此优秀的框架还是需要学习的。下面就推荐几个数据库的实现吧!

1. Hypersonic SQL

Hypersonic SQL开源数据库方向比较流行的纯Java开发的关系型数据库。好像不是JDBC兼容的,JDBC的很多高级的特性都没有支持,不过幸好支持ANSI-92 标准 SQL语法。我推荐它主要是它的代码比较少1600页左右,如此小的数据库值得研究,而且他占的空间很小,大约只有160K,拥有快速的数据库引擎。推荐你的第一个开源数据库。下载地址:http://hsqldb.sourceforge.net/。

2. Mckoi DataBase

McKoiDB 和Hypersonic SQL差不多,它是GPL 的license的纯Java开发的数据库。他的 JDBC Driver 是使用 JDBC version 3 的 Specifaction。 他也是遵循 SQL-92 的标准,也尽量支持新的 SQL 特色, 并且支持 Transaction 的功能。两个可以选一个吧!下载地址:http://mckoi.com/database/。

3. Apache Derby

学Java的数据库我建议使用Apache Derby ,研究数据库想成为一个数据库的高手我建议你先研究Apache Derby。Apache Derby是一个高质量的、纯 Java开发的嵌入式关系数据库引擎,IBM® 将其捐献给Apache开放源码社区,同时IBM的产品CloudSpace是它对应的产品。Derby是基于文件系统,具有高度的可移植性,并且是轻量级的,这使得它非常便于发布。主要是没有商业用户的很好的界面,没有其太多的功能。不过对于我们使用数据库、研究数据库还是极其有用的。对于中小型的企业说老实话你也不要用什么Oracle、SqlServer了,用Derby就可以了,何况是开源的呢!只要能发挥其长处也不容易啊!下载地址:http://incubator.apache.org/derby。

不过在没有足够的能力前,不要试图读懂它!注释和源代码15000页左右,我一年的阅读量!能读下来并且能真正领会它,绝对高手!你能读完Derby的源代码只有两种可能:1.你成为顶尖的高手――至少是数据库这部分; 2.你疯了。选择吧!!!!作为我自己我先选择Hypersonic SQL这样的数据库先研究,能过这一关,再继续研究Derby!不就是一年的阅读量吗!我可以化3年去研究如何做一个数据库其实还是很值得的!有的人搞IT一辈子自己什么都没有做,也根本没有研究别人的东西!

作为一个IT落后于别国若干年的、从事IT的下游产业“外包”的国家的IT从业人员,我认为还是先研究别人的优秀的东西比较好!可以先研究别人的,然后消化,学为己用!一心闭门造车实在遗憾!

三、JMS方向

JMS可能对大家来说是一个比较陌生的方向!其实JMS是一个比较容易理解,容易上手的方向。主要是Java消息服务,API也是相当简单的。不过在企业应用中相当广泛。下面就介绍几个吧!

1. MOM4J

MOM4J是一个完全实现JMS1.1规范的消息中间件并且向下兼容JMS1.0与1.02。它提供了自己的消息处理存储使它独立于关系数据与语言,它的客户端可以用任何语言开发。它可以算是一个小麻雀,很全实现也比较简单!它包含一个命名服务器,一个消息服务器,同时提供自己的持续层。设计也相当的巧妙,完全利用操作系统中文件系统设计的观念。代码也很少,250页左右,最近我在写该实现的源代码阅读方面的书,希望明年年中能与大家见面!下载地址:http://mom4j.sourceforge.net/index.html。

2. OpenJMS

OpenJMS是一个开源的Java Message Service API 1.0.2 规范的实现,它包含有以下特性:
1. 它既支持点到点(point-to-point)(PTP)模型和发布/订阅(Pub/Sub)模型。

2. 支持同步与异步消息发送 。

3. JDBC持久性管理使用数据库表来存储消息 。

4. 可视化管理界面。

5. Applet支持。

6. 能够与Jakarta Tomcat这样的Servlet容器结合。

7. 支持RMI, TCP, HTTP 与SSL协议。

8. 客户端验证 。

9. 提供可靠消息传输、事务和消息过滤。

很好的JMS方向的开源项目!我目前也在研究它的源代码!学习它可以顺便研究JNDI的实现、以及网络通信的细节。这是我JMS方向研究的第二个开源项目。代码量1600页左右吧!下载地址:http://openjms.sourceforge.net/index.html

3. ActiveMQ

ActiveMQ是一个开放源码基于Apache 2.0 licenced 发布并实现了JMS 1.1。它能够与Geronimo,轻量级容器和任Java应用程序无缝的给合。主要是Apache的可以任意的使用和发布哦!个人比较喜欢Apache的源代码!下载地址:http://activemq.codehaus.org/

4. JORAM

JORAM一个类似于openJMS分布在ObjectWeb之下的JMS消息中间件。ObjectWeb的产品也是非常值得研究的!下面我还会给大家另外一个ObjectWeb的产品。下载地址:http://joram.objectweb.org/

我个人推荐:OpenJMS和ActiveMQ!

四、EJB方向

EJB一个比较“高级”的方向。Sun公司曾经以此在分布式计算领域重拳出击。不过自从出现了Spring、Hibernation……后似乎没落了!这个方向单独开源的也比较少,主要EJB是和JNDI、JDBC、JMS、JTS、JTA结合在一起的是以很少有单独的。下面推荐两个不过好像也要下载其它类库。

1. EasyBeans

ObjectWeb的一个新的项目,一个轻量级的EJB3容器,虽然还没有正式发布,但是已经可以从它们的subversion仓库中检出代码。代码量比较小600页左右,熟读它可以对网络编程、架构、RMI、容器的状态设计比较了解了!即学会EJB又能学习其它设计方法何乐而不为哦!下载地址:http://easybeans.objectweb.org/
2. OpenEJB

OpenEJB是一个预生成的、自包含的、可移植的EJB容器系统,可以被插入到任意的服务器环境,包括应用程序服务器,Web服务器,J2EE平台, CORBA ORB和数据库等等。OpenEJB 被用于 Apple的WebObjects。听起来很好,我目前没有研究过。不知道我就不推荐了。下载地址:http://www.openejb.org/

五、J2EE容器

上面谈了这么多,都是J2EE的各个方向的。其实J2EE是一个规范,J2EE的产品一般要求专业提供商必须提供它们的实现。这些实现本身就是J2EE容器。市场上流行的J2EE容器很多,在开源领域流行的只有很少,很少。其中最著名的是JBoss。

1. JBoss

在J2EE应用服务器领域,Jboss是发展最为迅速的应用服务器。由于Jboss遵循商业友好的LGPL授权分发,并且由开源社区开发,这使得Jboss广为流行。另外,Jboss应用服务器还具有许多优秀的特质。

其一,它将具有革命性的JMX微内核服务作为其总线结构;

其二,它本身就是面向服务的架构(Service-Oriented Architecture,SOA);

其三,它还具有统一的类装载器,从而能够实现应用的热部署和热卸载能力。因此,它是高度模块化的和松耦合的。Jboss用户的积极反馈告诉我们,Jboss应用服务器是健壮的、高质量的,而且还具有良好的性能。为满足企业级市场日益增长的需求,Jboss公司从2003年开始就推出了24*7、专业级产品支持服务。同时,为拓展Jboss的企业级市场,Jboss公司还签订了许多渠道合作伙伴。比如,Jboss公司同HP、Novell、Computer Associates、Unisys等都是合作伙伴。

在2004年6月,Jboss公司宣布,Jboss应用服务器通过了Sun公司的J2EE认证。这是Jboss应用服务器发展史上至今为止最重要的里程碑。与此同时,Jboss一直在紧跟最新的J2EE规范,而且在某些技术领域引领J2EE规范的开发。因此,无论在商业领域,还是在开源社区,Jboss成为了第一个通过J2EE 1.4认证的主流应用服务器。现在,Jboss应用服务器已经真正发展成具有企业强度(即,支持关键级任务的应用)的应用服务器。

Jboss 4.0作为J2EE认证的重要成果之一,已经于2004年9月顺利发布了。同时,Jboss 4.0还提供了Jboss AOP(Aspect-Oriented Programming,面向方面编程)组件。近来,AOP吸引了大量开发者的关注。它提供的新的编程模式使得用户能够将方面(比如,事务)从底层业务逻辑中分离出来,从而能够缩短软件开发周期。用户能够单独使用Jboss AOP,即能够在Jboss应用服务器外部使用它。或者,用户也可以在应用服务器环境中使用它。Jboss AOP 1.0已经在2004年10月发布了。 很有名吧!可以下载一个用一下,下载地址:http://www.jboss.org/

关于JBoss的使用资料也非常多,甚至比商业软件的还多。有机会研究吧!

2. JOnAS

JOnAS是一个开放源代码的J2EE实现,在ObjectWeb协会中开发。整合了Tomcat或Jetty成为它的Web容器,以确保符合Servlet 2.3和JSP 1.2规范。JOnAS服务器依赖或实现以下的Java API:JCA、JDBC、JTA 、JMS、JMX、JNDI、JAAS、JavaMail 。下载地址:http://jonas.objectweb.org/
3.Apache Geronimo

Apache Geronimo 是 Apache 软件基金会的开放源码J2EE服务器,它集成了众多先进技术和设计理念。 这些技术和理念大多源自独立的项目,配置和部署模型也各不相同。 Geronimo能将这些项目和方法的配置及部署完全整合到一个统一、易用的模型中。作为符合J2EE标准的服务器,Geronimo提供了丰富的功能集和无责任 Apache 许可,具备“立即部署”式J2EE 1.4容器的各种优点,其中包括:

1. 符合J2EE1.4标准的服务器 。

2. 预集成的开放源码项目 。

3. 统一的集成模型 。

4. 可伸缩性、可管理性和配置管理功能。

我一直比较推荐Apache的产品。主要是可以任意自由地使用。下载地址:http://incubator.apache.org/projects/geronimo/

六、其它

讲了这么多大家可能很厌烦了!是不是很多很多啊!其实不然,我们不会的太多太多了!不会的太多太多了。不管你是不是J2EE高手,还是J2SE高手,有些东西你要绝对很精明的。例如:1.Java的Collections Framework就是java的数据结构了,不仅要吃透它,还要能按照需要扩展它,利用其思想创建一个自己的数据结构。2.网络编程肯定要会吧,现在以及以后很多程序都是不在同一台机器上的,不会网络怎么行哦!3.IO肯定要会的吧!你的程序难道不用输入输出数据啊!整个IO包加NIO也有600多页的源代码哦!4.JDBC你要会吧!数据库都不会,在你的企业应用中你的数据又保存到哪里啊!文件中――太落后了吧!典型的没有学过J2EE。尽管数据库背后也是采用文件保存的。5.Serverlet、JSp你要是做网页做网站,肯定要做到。问你一个简单的问题,网页中如何实现分页啊!有具体方法的就在本文章后发言吧!6. Ant要会吧!java语言中发布的工具,类似与c中的make工具。7.JUnit用过吧!单元测试软件。你不要啊!你的软件就没有bug!你牛!(建议大家研究研究其源代码,很有用的框架,包含大量的设计模式,源代码不到100页!看了只能感叹――高手就是高手)细心的朋友可以看到在你使用的很多IDE工具中都有JUnit哦!就是它。

一切的一切才刚刚开始!有兴趣,有需要你可以研究数据库连接池的框架,如:C3P0、Jakarta DBCP、 DBPool….可以研究J2EE框架Spring……. Web框架Struts……持久层框架Hibernate…..甚至开发工具Eclipse…..Sun领导的点对点通信的JXTA…..报表工具JFreeChart、JasperReports…..分布式网络编程的CORBA、网络通信的JGROUPS、XML解析的xerces…..(在不经意间开源已经步入你的电脑,不信啊!你JDK的安装目录jdk1.6.0 src com sun org apache就是Xerces,一个XML解析的著名的开源 项目)

不管怎么样我还是建议从基本的做起,学精J2SE,熟读它的源码,准确了解其设计理念,然后分头击破J2EE――一口吃不成一个胖子!不要贪多贪广!脚踏实地就可以了!

摘自CSDN:《J2EE值得学习的开源项目》

posted @ 2009-08-15 21:49 kangaroo 阅读(263) | 评论 (0)编辑 收藏

1、语法:必须比较熟悉,在写代码的时候IDE的编辑器对某一行报错应该能够根据报错信息知道是什么样的语法错误并且知道任何修正。

2、命令:必须熟悉JDK带的一些常用命令及其常用选项,命令至少需要熟悉:appletviewer、 HtmlConverter、jar、 java、javac、javadoc、javap、javaw、native2ascii、serialver,如果这些命令你没有全部使用过,那么你对java实际上还很不了解。

3、工具:必须至少熟练使用一种IDE的开发工具,例如Eclipse、Netbeans、JBuilder、Jdeveloper、IDEA、JCreator或者Workshop,包括进行工程管理、常用选项的设置、插件的安装配置以及进行调试。

4、API:Java的核心API是非常庞大的,但是有一些内容笔者认为是必须熟悉的,否则不可能熟练的运用Java,包括:
◆java.lang包下的80%以上的类的功能的灵活运用。

◆java.util包下的80%以上的类的灵活运用,特别是集合类体系、规则表达式、zip、以及时间、随机数、属性、资源和Timer.

◆java.io包下的60%以上的类的使用,理解IO体系的基于管道模型的设计思路以及常用IO类的特性和使用场合。

◆java.math包下的100%的内容。

◆java.net包下的60%以上的内容,对各个类的功能比较熟悉。

◆java.text包下的60%以上的内容,特别是各种格式化类。

◆熟练运用JDBC. 8)、java.security包下40%以上的内容,如果对于安全没有接触的话根本就不可能掌握java.

◆AWT的基本内容,包括各种组件事件、监听器、布局管理器、常用组件、打印。

◆Swing的基本内容,和AWT的要求类似。

◆XML处理,熟悉SAX、DOM以及JDOM的优缺点并且能够使用其中的一种完成XML的解析及内容处理。

5、测试:必须熟悉使用junit编写测试用例完成代码的自动测试。

6、管理:必须熟悉使用ant完成工程管理的常用任务,例如工程编译、生成javadoc、生成jar、版本控制、自动测试。

7、排错:应该可以根据异常信息比较快速的定位问题的原因和大致位置。

8、思想:必须掌握OOP的主要要求,这样使用Java开发的系统才能是真正的Java系统。

9、规范:编写的代码必须符合流行的编码规范,例如类名首字母大写,成员和方法名首字母小写,方法名的第一个单词一般是动词,包名全部小写等,这样程序的可读性才比较好。

10、博学:掌握J2EE 、Oracle 、WebLogic、Jboss、Spring、Struts、Hibernate 等流行技术,掌握软件架构设计思想、搜索引擎优化、缓存系统设计、网站负载均衡、系统性能调优等实用技术。

摘录自CSDN:
《一个java程序员的10项技能》

posted @ 2009-08-15 21:40 kangaroo 阅读(271) | 评论 (0)编辑 收藏

2009年8月9日

  • 关注点concern:一个关注点可以是一个特定的问题、概念、或是应用程序的兴趣区间。这是一个概念上的名词,就是应用程序必须达到的一个目标。比如前面提到的安全性检查,事务管理,性能检测都是系统常见的关注点。
  • 横切关注点crosscutting concern:如果一个关注点的实现代码(哪怕就一句)散落在很多类或方法之中,我们就称其为横切关注点。
  • 方面aspect :一个方面是对一个横切关注点的模块化,它将原本散落在各处的用于实现这个关注点的代码规整在一起。如果“关注点”是个概念上的名词,“方面”就是实在的代码。
  • 连接点join point:程序执行过程中的一点,例如:方法调用method invocation(对方法的调用)、字段访问field access(读或写字段)、异常抛出throws(特定的异常被抛出)
  • 增强advice:在特定连接点执行的动作。很多AOP框架都以拦截器interceptor的形式来表现增强。拦截器是一种增强,还有别的形式的增强。所谓拦截器是这样一个对象,当连接点被调用时,它会收到一个回调消息。增强的例子包括:在方法调用之前,进行安全性的检查;在执行某个方法的连接点之前开启事务,在方法执行完毕之后提交或回滚事务。
  • 切入点:一组连接点的总称,用于指定某个增强应该在何时被调用。切入点常用正则表达式或别的通配符来描述。
  • 前增强:在连接点调用之前,首先调用增强。
  • 后增强:在连接点调用之后,再调用增强。
  • 环绕增强:   
  • 拦截器:很多AOP框架(如Spring和JBoss4,但不包括AspectJ)用它来实现字段和方法的拦截。随之而来就是在连接点处挂一个拦截器链。拦截只是一种AOP的实现策略,不是AOP的核心概念。
  • 目标对象:位于拦截器链末端的对象实例。显然这个概念只存在使用拦截器的AOP框架中。
  • AOP代理:被增强的对象引用。也就是,AOP增强将在其上执行的这样一个对象引用。和“拦截器”一样,“AOP代理”只是对于使用拦截机制的AOP框架,而且是其立身之本。

讲了这么多概念,举个例子,把它们串起来,还是以“AOP学习笔记一”里面的“安全性检查”为例:
我们把“安全性检查”作为一个方面
那么实现安全性检查的拦截器就是一种增强
方法businessMethod1,businessMethod2,businessMethod3就是连接点,
但是只有businessMethod1和businessMethod2需要增强,所以需要一个切入点,使其只匹配前两个方法。
当我们的业务对象和拦截器都配置到spring之后,spring会在运行时织入,并且生成一个AOP代理
这个AOP代理将是一个JDK动态代理,将在完成安全性检查之后,调用目标对象

posted @ 2009-08-09 00:35 kangaroo 阅读(287) | 评论 (0)编辑 收藏

2009年8月8日

用于实现AOP技术的主要策略,按照功能由弱到强排列:
-J2SE动态代理
-动态字节码生成
-java代码生成
-使用定制的类加载期
-语言扩展

1.J2SE动态代理
动态代理是一种强大的语言结构,它使我们可以为一个或多个接口“凭空”地创建实现对象,而不需要预先有一个实现类。
动态代理最大的好处在于:这是一种标准的Java语言特性。除了AOP框架之外不需要第三方库,也不回受到应用程序的任何影响。
动态代理的最大局限性在于:它只能针对接口进行代理,不能针对类。一般情况下,这种限制不是坏事,因为AOP主要针对业务对象,而业务对象通常是放在业务接口之后。
动态代理在java1.4和更高的版本性能表现地相对好,不过,一旦使用动态代理的实习策略,便不可避免地招致反射调用的开销。

2.动态字节码生成
为了针对Java类提供代理,我们需要动态代理之外的工具,就是动态字节码生成。应该庆幸,Java的反射和类装载机制都非常开发,因此实现动态字节码生成库并不复杂。
在这方面,最流行的工具就是CGLIB(Code Generation Library)。在spring中,如果需要针对类(而不是接口)提供代理,就会用到CGLIB。它可以针对制定的类动态生成一个子类,并覆盖其中的方法,从而实现方法的拦截。CGLIB风格的字节码增强并应用在Hibernate2.X版本中,并被证明是一种成熟的技术。Hibernate的成功表明,在应用服务器环境下CGLIB没有给最终用户带来任何困扰。
不过CGLIB有个小问题就是,因为它是通过生成类的子类来实现代理的,所以无法为final方法提供代理。

3.java代码生成
逐渐退出流行。

4.使用定制的类加载器

5.语言扩展
AspectJ就对java进行了扩展,将AOP概念作为一等公民来对待。

posted @ 2009-08-08 22:01 kangaroo 阅读(259) | 评论 (0)编辑 收藏

AOP,全称Aspect Oriented Programming,面向方面的编程。那么就要问了,什么是方面,为什么引入AOP?
一般情况下,OOP能够很好的避免代码重复。具体继承可以帮助我们在不同类型之间共享相同的行为;多态让我们可以用同样的方式处理不同类型的对象,将注意力集中在它们的共同之处。但是,有些时候,OOP也避免不了代码的重复,比如下面的例子:

public class MyBusinessObject extends BusinessObject {
 
    
public void businessMethod1() throws UnanthorizedException {
        doSecurityCheck();
    }


    
public void businessMethod2() throws UnanthorizedException {
        doSecurityCheck();
    }

       
    
public void businessMethod3(){
        
//do not need check security.
    }



    
protected void doSecurityCheck() throws UnanthorizedException {
        
//implement the security check.
    }

}


上面是安全性检查的例子,我们希望检查用户是否有权限执行某个方法,如果没有就抛出异常。我们把安全检查的工作放在一个方法中实现,但是这个仍无法避免一行重复代码的编写。另外,当开发者添加一个新的业务方法时,它完全有可能忘记调用安全检查的方法,从而破坏了应用程序的安全性。为了在方法执行的过程中识别出“应该调用安全性检查”的那一点,我们需要用一种高全新的方式来看待程序结构,而OO的层次模型无法提供这种新的视角。对于这个问题,继承爱莫能助,“安全性检查”在这里是一个具有横切性的问题,需要进行安全性检查的方法都是彼此独立的,无法从某个通用的方法继承下去。
AOP的目标就是将横切型crosscutting的问题以一种更加通用的方式模块化,从而提升程序的模块化程度。在AOP中,我们可以单独编写“安全性检查”的代码,并将其包装为一个方面aspect。(方面的概念出现喽!)然后,我们可以告诉AOP实现产品如何在运行时将方面织入到程序流程之中,具体的实现策略,请看下篇AOP的实现策略。


 

posted @ 2009-08-08 21:55 kangaroo 阅读(218) | 评论 (0)编辑 收藏