??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲A∨无码一区二区三区,中中文字幕亚洲无线码,亚洲一区二区影视http://m.tkk7.com/terry-zj/category/5774.html<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"> </script> <script type="text/javascript"> _uacct = "UA-285051-1"; urchinTracker(); </script> zh-cnThu, 30 Aug 2007 16:53:57 GMTThu, 30 Aug 2007 16:53:57 GMT60sourceforge Top 25 Projectshttp://m.tkk7.com/terry-zj/archive/2007/08/30/141531.htmlTerry的BlogTerry的BlogThu, 30 Aug 2007 13:52:00 GMThttp://m.tkk7.com/terry-zj/archive/2007/08/30/141531.htmlhttp://m.tkk7.com/terry-zj/comments/141531.htmlhttp://m.tkk7.com/terry-zj/archive/2007/08/30/141531.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/141531.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/141531.htmlhttps://sourceforge.net/projects/azureus
Azureus is a powerful, full-featured, cross-platform bittorrent client.

2. phpMyAdmin
https://sourceforge.net/projects/phpmyadmin
phpMyAdmin is a tool written in PHP intended to handle the
administration of MySQL over the Web. Currently it can create and drop
databases, create/drop/alter tables, delete/edit/add fields, execute any
SQL statement, manage keys on fields.

3. Notepad++
https://sourceforge.net/projects/notepad-plus
Notepad++ is a generic source code editor (it tries to be anyway) and
Notepad replacement written in C++ with the win32 API. The aim of
Notepad++ is to offer a slim and efficient binary with a totally
customizable GUI.

4. OpenProj - Project Management
目理
https://sourceforge.net/projects/openproj
OpenProj by Projity is a desktop replacement of Microsoft Project.
OpenProj has equivalent functionality, a familiar user interface and
even opens existing MSProject files. OpenProj is interoperable with
Project, with a Gantt Chart and PERT chart etc.

5. ZK - Simply Ajax and Mobile
型 AJAX html/xul 应用
https://sourceforge.net/projects/zk1
ZK is Ajax framework enriching Web apps with little programming. With
event-driven and markup languages, development is as simple as
programming desktops and authoring HTML/XUL pages. ZK supports scripting
lang including Java, JavaScript, Ruby, Groovy...

6. dimdim meeting server
视频会议
https://sourceforge.net/projects/dimdim
Dimdim is an open source web meeting product with features like
Application, Desktop and Presentation sharing with A/V streaming and
chat. No attendee installation - all features are available through a
web browser. Dimdim can be integrated with Moodle.

7. ADempiere Bazaar
CRM{?br>https://sourceforge.net/projects/adempiere
Adempiere is an ERP Bazaar for Open Source Developers that contribute
improvements of Compiere, CRM, Shopfloor, POS, Helpdesk, Financials
Accounting, Supply Chain, Knowledge and Business apps in an open and
unabated fashion. Focus is on the Community.

8. Zenoss Core - Enterprise IT Monitoring
|关软g
https://sourceforge.net/projects/zenoss
Zenoss Core is an enterprise network and systems management application
written in Python/Zope. Zenoss provides an integrated product for
monitoring availability, performance, events and configuration across
layers and across platforms.

9. Openbravo ERP
ERP软g
https://sourceforge.net/projects/openbravo
Web based ERP for SMEs, built on proven MVC & MDD framework that
facilitate customization & maintenance of code. Already in production,
it encompasses a broad range of functionalities such as finance, supply
chain, project mgmt, manufacturing & much more

10. FreeCol
扑克游戏
https://sourceforge.net/projects/freecol
FreeCol is an open version of Colonization. It is a Civilization-like
game in which the player has to conquer the new world.

11. FileZilla
https://sourceforge.net/projects/filezilla
FileZilla is a fast FTP and SFTP client for Windows with a lot of
features. FileZilla Server is a reliable FTP server.

12. WebCalendar
https://sourceforge.net/projects/webcalendar
WebCalendar is a PHP application used to maintain a calendar for a
single user or an intranet group of users. It can also be configured as
an event calendar.

13. PhpGedView
???
https://sourceforge.net/projects/phpgedview
PhpGedView parses GEDCOM 5.5 genealogy files and displays them on the
internet in formats and charts that you are familiar with.It also allows
relatives to edit their genealogy online and collaborate together on
their research.

14. MediaInfo
多媒体管?br>https://sourceforge.net/projects/mediainfo
Get technical information and tags of a lot of multimedia files.
Supported formats : - Video : AVI/OGM/MKV/MPG/VOB/MP4/3GP/... - Audio :
MP3/OGG/MKA/MP4/AAC/...

15. 7-Zip
https://sourceforge.net/projects/sevenzip
7-Zip is a file archiver with the high compression ratio. The program
supports 7z, ZIP, CAB, RAR, ARJ, LZH, CHM, GZIP, BZIP2, Z, TAR, CPIO,
RPM and DEB formats. Compression ratio in the new 7z format is 30-50%
better than ratio in ZIP format.

16. KeePass Password Safe
密码保存工具QwindowsQ?br>https://sourceforge.net/projects/keepass
KeePass Password Safe is a free, open source, light-weight and
easy-to-use password manager for Windows. You can store your passwords
in a highly-encrypted database, which is locked with one master password
or key file.

17. MinGW - Minimalist GNU for Windows
GCC~程工具QwindowsQ?br>https://sourceforge.net/projects/mingw
MinGW: A native Win32 port of the GNU Compiler Collection (GCC), with
freely distributable import libraries and header files for building
native Windows applications; includes extensions to the MSVC runtime to
support C99 functionality.

18. XOOPS Dynamic Web CMS
https://sourceforge.net/projects/xoops
XOOPS is a dynamic web content management system written in PHP for the
MySQL database. Its object orientation makes it an ideal tool for
developing small or large community websites, intra company and
corporate portals, weblogs and much more.

19. FreeMind
知识和内容管理工?br>https://sourceforge.net/projects/freemind
A mind mapper, and at the same time an easy-to-operate hierarchical
editor with strong emphasis on folding. These two are not really two
different things, just two different descriptions of a single
application. Often used for knowledge and content mgmt.

20. Arianne RPG
RPG游戏
https://sourceforge.net/projects/arianne
Arianne is a multiplayer online engine to develop turn based and real
time games providing a simple way of creating the game server rules and
clients like Stendhal. Marauroa, our server, uses Java and MySQL for
hosting hundreds of players on a solo host.

21. OrangeHRM - Human Resource Management
人力资源理
https://sourceforge.net/projects/orangehrm
OrangeHRM developed by OrangeHRM Inc is an Open Source HR Information
Systems(HRIS) that assists you in managing company's human resources.
Through scalable modular architecture it covers main areas of Personnel
Management/HRM such as PIM, ESS & Leave.

22. Gallery
https://sourceforge.net/projects/gallery
A slick, intuitive web based photo gallery. Gallery is easy to install,
configure and use. Gallery photo management includes automatic
thumbnails, resizing, rotation, and more. Authenticated users and
privileged albums make this great for communities.

23. Pidgin
https://sourceforge.net/projects/pidgin
Pidgin is a GTK+ instant messaging application for Windows and Unix. It
supports AIM, ICQ, Jabber/XMPP, MSN, Yahoo!, Bonjour, Gadu-Gadu, IRC,
QQ, SILC, SIMPLE and more. See http://pidgin.im.sixxs.org/about.php for more
information.

24. XBMC (Xbox Media Center)
Xbox软g
https://sourceforge.net/projects/xbmc
XBMC (Xbox Media Center) is a free multimedia player jukebox for
Microsoft Xbox game console, it is capable of playing back almost all
known video, audio and picture formats from the Xbox harddrive, DVD-ROM
drive, a local-network, and even the internet.

25. JasperReports - Java Reporting
java 分析工具
https://sourceforge.net/projects/jasperreports
JasperReports, the market leading open source business intelligence and
reporting engine. This project is being moved to
http://www.jasperforge.org.sixxs.org/. This project is the home for all things
Jasper, Reports, Analysis, Server, and Intelligence.


http://www.newsmth.net/bbscon.php?bid=99&id=1138814

Terry的Blog 2007-08-30 21:52 发表评论
]]>
转发(forward)、包?include)及{?redirect)的区别与联系http://m.tkk7.com/terry-zj/archive/2006/10/11/74530.htmlTerry的BlogTerry的BlogWed, 11 Oct 2006 05:41:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/10/11/74530.htmlhttp://m.tkk7.com/terry-zj/comments/74530.htmlhttp://m.tkk7.com/terry-zj/archive/2006/10/11/74530.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/74530.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/74530.html说明Q?br />一、forward、include由javax.servlet.RequestDispatcher来封?由包容器container提供RequestDispatcher接口的实玎ͼ其中声明如下Q?br />void forward(ServletRequest req,ServletResponse res)
void include(ServeltRequest req,ServletResponse res)
可以通过两种方式得到RequestDispatcher:
1、ServletContext.getRequestDispatcher(String path);
其中q里的path必须开始ؓ"/"Q即q里的path必须相对于context的root.
2、ServeltRequest.getRequestDispatcher(String path)
q里的path可以为相对\?如果path开始ؓ"/",则也认ؓ是从context的root开始的?br />二、Redirect由HttpServletResponse.sendRedirect(String location)来支?br />差别Q?br />三个都可以对用户的requestq行转发Q但是还是有许多的不同,差别最主要集中在如下几个方面:
1、forward与include׃Request范围内的对象,而redirect则不行,卻I如果一个javabean被声明ؓrequest范围的话Q则被forward到的资源也可以访问这个javabean,而redriect则不行?br />2、forward与include基本上都是{发到context内部的资源,而redirect可以重定向到外部的资?如: req.sendRedriect("
以上来源
http://www.cn-java.com/target/news.php?news_id=3176

?br />struts-config.xml
<forward name="succ"  path="/pages/dynabean2.jsp" redirect="true"/>
讄redirect="true"?转向目标面时效果和redirect一致?br />

Terry的Blog 2006-10-11 13:41 发表评论
]]>
Web IMhttp://m.tkk7.com/terry-zj/archive/2006/10/10/74375.htmlTerry的BlogTerry的BlogTue, 10 Oct 2006 12:45:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/10/10/74375.htmlhttp://m.tkk7.com/terry-zj/comments/74375.htmlhttp://m.tkk7.com/terry-zj/archive/2006/10/10/74375.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/74375.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/74375.html meebo    http://www.meebo.com
比较早的Web IM,支持AIM、ICQ、Yahoo! Messenger、Jabber、Gtalk和MSN?

ebuddy    http://ebuddy.com/#BETA
支持MSN、Yahoo、AIMQ提供Wap登陆?

Web QQ    http://webqq.qq.com/
QQ ?Web IMQ已l可以用了?

mabber    http://www.mabber.com/
Beta?支持AIM、ICQ、Yahoo! Messenger、Jabber、Gtalk和MSNQ速度比较慢?

AIM    http://www.aim.com/get_aim/express/aim_expr.adp
AIM自己的Web IM?

MSN    http://webmessenger.msn.com/
Microsoft 自己的Web IM?

ICQ    http://www.icq.com/download/icq2go/
ICQ开发的的ICQ Web IM?

koolim    http://www.koolim.com/
支持AIM、ICQ、Yahoo! Messenger、Jabber、Gtalk、MSN?
imhaha    http://www.imhaha.com/
支持QQ哟,另外q支持MSN、Yahoo!MessengerQAIM?br /> 
radiusim    http://www.radiusim.com/
支持AIM、Yahoo messager!、MSN、Gtalk?/p>

Terry的Blog 2006-10-10 20:45 发表评论
]]>
AMV问题大全 (转蝲http://www.hao3gp.com/v_46520.html)http://m.tkk7.com/terry-zj/archive/2006/07/20/59165.htmlTerry的BlogTerry的BlogThu, 20 Jul 2006 05:03:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/07/20/59165.htmlhttp://m.tkk7.com/terry-zj/comments/59165.htmlhttp://m.tkk7.com/terry-zj/archive/2006/07/20/59165.html#Feedback30http://m.tkk7.com/terry-zj/comments/commentRss/59165.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/59165.html问题1Q什么是AMV视频
回答QAMV是MP3/MP4上播攄一U视频格式。AMV格式h较高压羃比例以及画面质量。通过AMV转换工具转换出来的媄x件一分钟的容量约?.8MB。你可以通过察看自己的MP3/MP4产品说明书来知道自己的机器是否支持AMV视频格式?/p>

 

问题2Q我的MP3能看多大的AMV
回答QMP3/MP4的屏q大尺寸如下:
1.0英寸 屏幕大小96×64
1.1英寸 屏幕大小96×64
1.2英寸 屏幕大小160×128
1.3英寸 屏幕大小160×128
1.5英寸 屏幕大小128×128
1.8英寸 屏幕大小128×160
目前市场上最常见的是1.5英寸?.8英寸的MP3/MP4?br />MP3/MP4只能播放比自己屏q尺寸小的AMV视频Q例?.8寸的可以播?6×64?28×96?60×120的视频。?.5寸的则无法播?60×120的AMV视频?/p>

 

问题3Qؓ什么我的AMV不能满屏播放
回答Q我们先来看下MP3/MP4的屏q大:
1.5寸屏q是128×128也就?:1
1.8寸屏q是160×128也就?:4
而我们知道,大部分的视频的标准比例是4:3Q而宽屏电影是16:9。这是Z么我们看宽屏电媄会有上下两条黑色的遮q?br />q样问题清楚了Q所有下载的视频都是4:3的标准比例,于是攑ֈ1.5寸的机器里就?28×96Q而放?.8寸机器里是160×120Q看h׃是满屏了。如果下载的是宽屏电q话,则上下会被遮挡的更多?/p>

 

问题4Qؓ什么我?28×128满屏会感觉画面不?br />回答Q?28×128的视频虽然看h是满屏的Q但其实是在170×128的视频上切割而成的,于是视频在宽度上׃别截掉很多。看h是满屏的Q其实是看不到全画面的?/p>

 


问题5Qؓ什么我播放一半会提示格式错误
回答Q因为现在MP3/MP4采用的解码芯片各不相同,而压制出来的AMVq不能保证兼Ҏ有的MP3/MP4机器。因此可能会出现播放一半提C错误的问题?/p>

 


问题6Q怎么制作AMV
回答Q如何制作AMV请参阅:http://www.go2tv.net/read.php?tid-1892.html

 


问题7Qؓ什么我制作RMVB时出错了
回答Q视频的转换本来是很复杂的一件事情。各U视频有着各种各样不同的视频音频编码(可参?a >http://www.go2tv.net/read.php?tid-215.htmlQ。要转换RMVB必要有RMVB的解码程序,需要安装real的解码器。但是有时虽然两个文件是同一个视频格式例如RMVB但其实它们采用的视频~码可能是完全不同的Q所以有的RMVB能够利的{成AMVQ有的就不行Q?br />对于不能转的RMVBQ有一个方法是先把它{?GP再{到AMV?/p>

 


问题8Qؓ什么我转换AMV时提C磁盘已?br />回答QAMV转换_在用过E中有一个很奇怪的BUGQ在转换较大的文件时会提C磁盘已满!
q个需要安装AMV转换_的那个磁盘空间大?GQ?/p>

 


问题9Qؓ什么我下蝲的AMV文g是RAR文档
回答Q不知道什么原因,在有些朋友的机器上AMV文g会被兌到RAR文g上。双d会调用WINRAR打开。解x式是改变AMV文g的关联,兌到AMV播放器即可。或者每ơ都用AMV播放器来打开Q而不是用双击Q?/p>

 


问题10Qؓ什么在电脑上不能看AMV文g
回答Q电脑上要看AMV文g需要特D的播放软gQAMV播放器!
可以在:http://www.go2tv.net/read.php?tid-1892.html 下蝲到{换器和播攑֙

 


问题11Q哪里有AMV制作工具下蝲
回答Q可以在Q?a >http://www.go2tv.net/read.php?tid-1892.html 下蝲到{换器和播攑֙以及有详l教E?/p>

 


问题12Q能不能?28×96 AMV转换?60×120的AMV
回答QAMV转换工具不支持AMV格式作ؓ源文Ӟ也就是无法从AMV转换到AMV?/p>

 

问题13Qؓ什么我的视频文件{成AMV后大了很多啊
回答Q视频文件的大小是由它的~码率来军_的,相同旉长度的视频有高的kbps׃有越大的文g。而AMV转换工具默认的图像品质是middleQ它的编码率比较高,如果选择high׃更高。同时还因ؓAMV压羃法的不同,以及声音~码的不同,所以会造成AMV文g比源文g要大的结果?/p>

 

问题14Q我转换出来的AMV文g上下颠倒,怎么办啊Q?br />回答Q找?AMVConverter的安装目录进入,打开 AmvTransform.ini 文gQ可用window自带的记事本打开Q,扑ֈBMPADJUST字段q修攏V?br />BMPADJUSTQ对应的意义如下Q?br />BMPADJUST=0 - 正常
BMPADJUST=1 - 画面垂直{
BMPADJUST=2 - 画面水^{
BMPADJUST=3 - 画面180 度旋?br />BMPADJUST=4 - 画面时?90 度旋?br />BMPADJUST=5 - 画面逆时?90 度旋?br />修改后保存退出,重新启动AMVConverter卛_?/p>

 

问题15Q哪里有1.8?60×120的AMV制作工具下蝲
回答Q?60×120转换器下载:http://www.go2tv.net/read.php?tid-3792.html

 


问题16Q如何在AMV里加入大一些的字幕Q?br />回答QAMV转换工具是无法加载字q的。想要在AMV中加载大字幕Q只有通过两次转换的方式。可以给q加蝲字幕的Y件很多,例如可以先用EO VIDEOQEasy RealMedia ProducerQSmartMovie Converter{工具ؓ源文件加上大的字q!再用AMV转换工具把加了大字幕的源文g转换成AMV文g



Terry的Blog 2006-07-20 13:03 发表评论
]]>
学习spring的好?/title><link>http://m.tkk7.com/terry-zj/archive/2006/07/07/57215.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Fri, 07 Jul 2006 15:48:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2006/07/07/57215.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/57215.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2006/07/07/57215.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/57215.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/57215.html</trackback:ping><description><![CDATA[http://www.javaworld.com.tw/confluence/display/opensrc/Spring<img src ="http://m.tkk7.com/terry-zj/aggbug/57215.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2006-07-07 23:48 <a href="http://m.tkk7.com/terry-zj/archive/2006/07/07/57215.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何写一份好的工E师?转蝲http://m.tkk7.com/terry-zj/archive/2006/06/23/54605.htmlTerry的BlogTerry的BlogFri, 23 Jun 2006 01:09:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/06/23/54605.htmlhttp://m.tkk7.com/terry-zj/comments/54605.htmlhttp://m.tkk7.com/terry-zj/archive/2006/06/23/54605.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/54605.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/54605.html转自 http://googlechinablog.com/2006/06/blog-post_14.html

如何写一份好的工E师?/p>

2006q??4?上午 10:15:00
发表者:王忻QGoogle 工程?

最q三q作?GoogleQ谷歌)的Y件工E师Q我每周会帮Z部门审查历,军_要不要给他们面试。Google q几q的发展让很多许多优U的工E师都前来申诗到目前为止Q我已经看了上千份简历,有些历留下的印象比别的好很多。尤其是最q亲戚朋友常帔R我如何修改他们的历,所以我U篏了一些常见的错误避免的提议,在此跟大家交一下?/p>

1Q谈C做过的技术时Q应该提到用的程序语a、你的个A献和产品l节?/p>

有时我看到有人把q去的经验在历上一W带q,比如_

?在三人小l里Qؓ电子邮g软g写了?features?/p>

q是q远不够的,看简历的人希望了解你做的工作的难度和Ҏ公司有多联p,所以你最好写的具体一些。譬如:

??C++ 语言写了|络电子邮g的自?backups。在三h组里,专门负责设计和写储存服务器。从设计开始, 一q后把这个功?feature 的用hC三千?/p>

2Q多讲事? 用形容词?/p>

看简历的你的历时Q需要做判断Q所以在历里需要事实和数目。如果你写“迅速的提高了Y件的操作效率”,看简历的人很隑ֈ断你成就的难度。但如果你写“在3个星期内Q把软g的操作效率提高了40%?好多了?/p>

有些谦虚的朋友们不愿意把话说满,所以你也可以用q个办法。你如果说自己“突出”或“在目上常常被请去救火”,听v来难免会有点骄傲。但你也可以用不能否认的事实来说明你的观点,如“《纽U日报》评q个产品为‘突出’”,或“加入了三个原本已落后于计划的项目小l,但经q努力和l员一h它们都按时完成了。?/p>

3Q你获得的奖、商业的荣誉或表扬、受用户Ƣ迎的品和你做q的有难度的业余目都该包括在简历里?/p>

我有位朋友在谷一个著名的g公司做了六年Q她设计?IP phoneQ网l电话)为公司赚了上亿的收入Q被公司与商业报道多ơ评了奖。我有一ơ在旧金q高速公路上驾RӞ看到路边有她产品的广告牌Q还有一ơ我M度假时Q竟然发C公路边上也有!

不久Q这位朋友决定换工作Q请我看看她的简历。我惊讶的发玎ͼ她居然轻描E写的写了一?- "1998 ?2004Q网l电话品的g工程师组? 和她的职责?/p>

"产品赢的奖呢Q它为公司赚的钱呢?" 我追问到?/p>

"那些也该写吗Q? 她说?/p>

当然该写?/p>

有h问,业余旉做的目可不可以写?我觉得只要你的项目有代表性能说明对你的能力,都该包括?/p>

4Q分清主ơ,删掉相比之下不v眼的成WQ以免冲淡更加突出的成W?/p>

有朋友问Q写历是不是写的多好Q譬如:

在甲公司做暑假实习生—?br />* 改善电子游戏的数值分cȝ法, 减少了内存要?10%?br />* ?Java 写了 3000 行用L面程序?br />* 每周做两时的h工测试?/p>

你在甌软g工程师的职位Ӟ我觉得前两点比较相关Q第三点其实׃必写了。有时我看到有的历里会提刎ͼ"按时完成了Q务,产品W合原计划规?。但ȝ历的人通常会认是理所当然的,而你把这些声明出来反而减q历的效果?/p>

写一份简历不ҎQ但写好了也会带来成感 Q和好工作!Q?Google Q谷歌)在中国广召各斚w的h才,你不妨可以给我们投个历!我们不但在信息检索方面招雇工E师Q还有计机囑Ş、用L面、硬件、Windows、质量保证员和系l管理员{方面。更多信息,h讉Kq里?/p>

谢谢阅读Q大家感兴趣的话Q下ơ我可以介绍“如何预备Y件工E师的面试”?/p>

Terry的Blog 2006-06-23 09:09 发表评论
]]>
Introducing to Spring FrameworkQ中文修订版Q?转蝲http://m.tkk7.com/terry-zj/archive/2006/06/21/54163.htmlTerry的BlogTerry的BlogWed, 21 Jun 2006 03:42:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/06/21/54163.htmlhttp://m.tkk7.com/terry-zj/comments/54163.htmlhttp://m.tkk7.com/terry-zj/archive/2006/06/21/54163.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/54163.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/54163.html阅读全文

Terry的Blog 2006-06-21 11:42 发表评论
]]>
代理模式(Proxy pattern) 转蝲http://m.tkk7.com/terry-zj/archive/2006/06/20/53937.htmlTerry的BlogTerry的BlogTue, 20 Jun 2006 03:46:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/06/20/53937.htmlhttp://m.tkk7.com/terry-zj/comments/53937.htmlhttp://m.tkk7.com/terry-zj/archive/2006/06/20/53937.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/53937.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/53937.html1. 代理模式
代理模式的作用是Qؓ其他对象提供一U代理以控制对这个对象的讉K。在某些情况下,一个客户不x者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用?
代理模式一般涉及到三个角色Q?
抽象角色Q声明真实对象和代理对象的共同接口;
代理角色Q代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在Q何时刻都能代替真实对象。同Ӟ代理对象可以在执行真实对象操作时Q附加其他的操作Q相当于对真实对象进行封装?
真实角色Q代理角色所代表的真实对象,是我们最l要引用的对象?/p>

以下以《Java与模式》中的示例ؓ例:

抽象角色Q?
abstract public class Subject {
   abstract public void request();

真实角色Q实CSubject的request()Ҏ?
public class RealSubject extends Subject {
    public RealSubject() { }
   
    public void request() {
        System.out.println("From real subject.");
    }
}

代理角色Q?
public class ProxySubject extends Subject {
    private RealSubject realSubject; //以真实角色作Z理角色的属?

    public ProxySubject() { }


    public void request() { //该方法封装了真实对象的requestҎ
        preRequest();

        if( realSubject == null ) {

            realSubject = new RealSubject();
        }

        realSubject.request(); //此处执行真实对象的requestҎ

        postRequest();
    }


    private void preRequest() {
        //something you want to do before requesting
    }

    private void postRequest() {
        //something you want to do after requesting
    }
}

客户端调用:
Subject sub=new ProxySubject();
Sub.request();

׃上代码可以看出,客户实际需要调用的是RealSubjectcȝrequest()ҎQ现在用ProxySubject来代?RealSubjectc,同样辑ֈ目的Q同时还装了其他方?preRequest(),postRequest())Q可以处理一些其他问题?

另外Q如果要按照上述的方法用代理模式,那么真实角色必须是事先已l存在的Qƈ其作ؓ代理对象的内部属性。但是实际用时Q一个真实角色必d应一?代理角色Q如果大量用会Dcȝ急剧膨胀Q此外,如果事先q不知道真实角色Q该如何使用代理呢?q个问题可以通过Java的动态代理类来解冟?br /> 
2.动态代理类

Java动态代理类位于Java.lang.reflect包下Q一般主要涉及到以下两个c:

(1). Interface InvocationHandlerQ该接口中仅定义了一个方法ObjectQinvoke(Object obj,Method method, Object[] args)。在实际使用ӞW一个参数obj一般是指代理类Qmethod是被代理的方法,如上例中的request()QargsҎ的参数数l?q个抽象Ҏ在代理类中动态实现?


(2).ProxyQ该cd为动态代理类Q作用类g上例中的ProxySubjectQ其中主要包含以下内容:

Protected Proxy(InvocationHandler h)Q构造函敎ͼ估计用于l内部的h赋倹{?

Static Class getProxyClass (ClassLoader loader, Class[] interfaces)Q获得一个代理类Q其中loader是类装蝲器,interfaces是真实类所拥有的全部接口的数组?

Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)Q返回代理类的一个实例,q回后的代理cd以当作被代理cM?可用被代理cȝ在Subject接口中声明过的方??

 

所谓Dynamic Proxy是这样一UclassQ它是在q行时生成的classQ在生成它时你必L供一linterfacel它Q然后该class宣U它实现了这?interface。你当然可以把该class的实例当作这些interface中的M一个来用。当然啦Q这个Dynamic Proxy其实是一个ProxyQ它不会替你作实质性的工作Q在生成它的实例时你必须提供一个handlerQ由它接实际的工作?/p>

在用动态代理类Ӟ我们必须实现InvocationHandler接口Q以W一节中的示例ؓ例:

抽象角色(之前是抽象类Q此处应改ؓ接口)Q?

public interface Subject {
   abstract public void request();
}

具体角色RealSubjectQ?br />public class RealSubject implements Subject{

  public RealSubject(){}

  public void request(){
    System.out.println("From real subject.");
  }

}


代理处理器:
import java.lang.reflect.Method;

import java.lang.reflect.InvocationHandler;

public class DynamicSubject implements InvocationHandler {
  private Object sub;
  public DynamicSubject() {}

  public DynamicSubject(Object obj) {
    sub = obj;
  }

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   System.out.println("before calling " + method);
   method.invoke(sub,args);

   System.out.println("after calling " + method);
   return null;
 }

}

 

该代理类的内部属性ؓObjectc,实际使用旉过该类的构造函数DynamicSubject(Object obj)对其赋|此外Q在该类q实CinvokeҎQ该Ҏ中的

method.invoke(sub,args);

其实是调用被代理对象的要被执行的ҎQ方法参数sub是实际的被代理对象,args为执行被代理对象相应操作所需的参数。通过动态代理类Q我们可以在调用之前或之后执行一些相x作?

客户端:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Client {

static public void main(String[] args) throws Throwable {

   RealSubject rs = new RealSubject(); //在这里指定被代理c?
   InvocationHandler ds = new DynamicSubject(rs);
   Class cls = rs.getClass();

   //以下是一ơ性生成代?br />   Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),ds );
   subject.request();

}

E序q行l果Q?br />before calling public abstract void Subject.request()
From real subject.
after calling public abstract void Subject.request()

通过q种方式Q被代理的对?RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变Q控制的方式(DynamicSubjectc?也可以动态改变,从而实C非常灉|的动态代理关pR?br /> 

转蝲地址Q?br />http://www.java3z.com/cwbwebhome/article/article2/2300.jsp?id=846
http://www.csdn.net/develop/Article/26/26750.shtm 



Terry的Blog 2006-06-20 11:46 发表评论
]]>
电子商务信函写作技?/title><link>http://m.tkk7.com/terry-zj/archive/2006/06/08/51405.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Thu, 08 Jun 2006 09:03:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2006/06/08/51405.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/51405.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2006/06/08/51405.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/51405.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/51405.html</trackback:ping><description><![CDATA[电子商务信函写作技?<br />转蝲<a >http://ec.icxo.com/htmlnews/2004/07/27/276390.htm</a><br /><br /><p><font class="font14">1Q跟C家徏立联p?<br /><br />Dear Mr. Jones: <br /><br />We understand from your information posted on Alibaba.com that you are in the market for textiles. We would like to take this opportunity to introduce our company and products, with the hope that we may work with Bright Ideas Imports in the future. <br /><br />We are a joint venture specializing in the manufacture and export of textiles. We have enclosed our catalog, which introduces our company in detail and covers the main products we supply at present. You may also visit our online company introduction at <a target="_blank"><font color="#003399">Http://xxxxxxxxxx.icxo.com</font></a> which includes our latest product line. <br /><br />Should any of these items be of interest to you, please let us know. We will be happy to give you a quotation upon receipt of your detailed requirements. <br /><br />We look forward to receiving your enquires soon. <br /><br />Sincerely, <br /><br />John Roberts <br /><br />Company:XXXXXXX <br />ADD:XXXXXXX <br />TEL:XXXXXXXX <br />FAX:XXXXXXXXX <br />EMAIL:XXXXXXXXX <a target="_blank"><font color="#003399">HTTP://WWW.XXXXXXXXXX</font></a><br /><br />2Q对C家要求徏立业务联pȝ回复 <br /><br />Dear Mr. Jones: <br /><br />We have received your letter of 9th April showing your interest in our complete product information. <br /><br />Our product lines mainly include high quality textile products. To give you a general idea of the various kinds of textiles now available for export, we have enclosed a catalogue and a price list. You may also visit our online company introduction at <a target="_blank"><font color="#003399">Http://xxxxxxxxxx.icxo.com</font></a> which includes our latest product line. <br /><br />We look forward to your specific enquiries and hope to have the opportunity to work together with you in the future. <br /><br />Sincerely, <br /><br />John Roberts <br /><br />Company:XXXXXXX <br />ADD:XXXXXXX <br />TEL:XXXXXXXX <br />FAX:XXXXXXXXX <br />EMAIL:XXXXXXXXX <a target="_blank"><font color="#003399">HTTP://WWW.XXXXXXXXXX</font></a><br /><br />3Q向老客户介l公司的最C品信?<br /><br />Dear Mr. Jones: <br /><br />We have refreshed our online catalog at <a target="_blank"><font color="#003399">http://xxxxxxxxxxx.com,</font></a> and now it covers the latest new products, which are now available from stock. <br /><br />We believe that you will find some attractive additions to our product line. Once you have had time to study the supplement, please let us know if you would like to take the matter further. We would be very happy to send samples to you for close inspection. <br /><br />We will keep you informed on our progress and look forward to hearing from you. <br /><br />Sincerely, <br /><br />John Roberts <br /><br />Company:XXXXXXX <br />ADD:XXXXXXX <br />TEL:XXXXXXXX <br />FAX:XXXXXXXXX <br />EMAIL:XXXXXXXXX <a target="_blank"><font color="#003399">HTTP://WWW.XXXXXXXXXX</font></a><br /></font></p><img src ="http://m.tkk7.com/terry-zj/aggbug/51405.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2006-06-08 17:03 <a href="http://m.tkk7.com/terry-zj/archive/2006/06/08/51405.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>讉K被屏蔽的Google搜烦引擎的常用方?/title><link>http://m.tkk7.com/terry-zj/archive/2006/06/05/50404.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Mon, 05 Jun 2006 00:35:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2006/06/05/50404.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/50404.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2006/06/05/50404.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/50404.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/50404.html</trackback:ping><description><![CDATA[ <p>本文给Z些能够正常访问被屏蔽的Google搜烦引擎的常用方法以及Google的IP地址表?/p> <p>  在Google.com里面q行搜烦的时候,l常会遇到突然出现“该|法显C”的提示Qƈ且之后的十多分钟都无法正常连接GoogleQ这里给Z些方法,可以解决大部分Google无法讉K或进不去的问题?/p> <p>  1、如果是搜烦q程中出现“该|法显C”的提示Q接着无法访问GoogleQ那么对于ADSL用户Q可以尝试断开|络q接Q然后重新拨号上|,q样你的IP地址发生了变化Q这时候就可以正常讉KGoogle了。(其原理是防火墙只是针对IP用P而不是针对独立电脑)</p> <p>  2、如果一开始就无法讉KGoogleQ那么请把下面这一行:</p> <p>  216.239.63.104 <a >www.google.com</a> ?64.233.171.99 <a >www.google.com</a> ?216.239.53.99 <a >www.google.com</a></p> <p>  d刎ͼC:\WINDOWS\system32\drivers\etc\hosts文g里,q讉KGoogle看看是否正常。(其原理是提供较ؓ用的Google镜像讉KQ?/p> <p>  3、用附录中的Google的镜像IP地址来访问GoogleQ那么多的IPQ应该不至于全都了吧?/p> <p>  4、用Google.cn来访问GoogleQ不q请注意QGoogle.cn服务器也在美国,因此搜烦词语的时候也会出现“该|法显C”的可能?/p> <p>  5、如果碰到DNS劫持的封锁方法,那么需要选择正确的DNS服务器,主DNS讄成国外根服务器的DNSQ然后辅助DNS讄成国外的DNS。具体做法:在拨Ll或|卡属性里讄Q主DNS设成 202.12.27.33Q辅助DNSQ?02.216 .228.18Q日本DNSQ大家还可以自己找一些快的国外DNS?Q其原理是DNS劫持只能够控制国内的DNS服务器,而对于国外的DNS服务器则无能为力Q因此只要不使用国内的DNS卛_Q?/p> <p>  6、对于GMailQ用http讉K讉K的话最好不要选择“带有聊天功能的标准视图”,否则Ҏ被封?/p> <p>  7、尽量?a >https://mail.google.com</a> 来访问GMailQ这极大提高访问的E_性,q且在GMail里用GTalk也不会被。(其原理是对于加密的httpsQ防火墙无能为力Q?/p> <p>  8、用加密的代理服务器Y件来讉KGoogleQ当然目前的一些加密的代理服务器都不是很稳定,速度也不是很理想?/p> <p>  当然Q上面的Ҏ有时可能会实效,我觉得最单的Ҏ应该是来自Google的,是提供一个支持https版本的Google搜烦Q这可以一x逸地解决目前几乎所有的问题Q而且我知道增加这个版本对于Google来说应该是D手之劳的事情Qƈ且GMail都已l提供了Q那么ؓ什么对于我们用的更多的Web搜烦不提供呢Qhttps是安全访问网站的一个重要的ҎQ目前还没有看到能截获https的加密数据的防火墙,那么与其提供Google.cnQ其实还不如提供一个https的Google更实用?/p> <p>  当然Q在大多数国Ӟ使用https讉KGoogle都显得很多余Q但请Google理解https对于中国用户的重要性,q且实现https讉K也是轻而易丄事情Q又何乐而不为呢?/p> <p>  附录QGoogle的IP地址一览表Q?a >http://216.239.37.103</a> <a >http://216.239.57.99</a> <a >http://64.233.187.107</a><br /><a >http://216.239.37.105</a> <a >http://216.239.59.103</a> <a >http://64.233.187.89</a><br /><a >http://216.239.37.106</a> <a >http://216.239.59.104</a> <a >http://64.233.187.99</a><br /><a >http://216.239.37.107</a> <a >http://216.239.59.105</a> <a >http://66.102.11.104</a><br /><a >http://216.239.39.100</a> <a >http://216.239.59.106</a> <a >http://66.102.11.105</a><br /><a >http://216.239.39.102</a> <a >http://216.239.59.107</a> <a >http://66.102.11.106</a><br /><a >http://216.239.39.103</a> <a >http://216.239.59.147</a> <a >http://66.102.11.107</a><br /><a >http://216.239.39.106</a> <a >http://216.239.59.98</a> <a >http://66.102.11.99</a><br /><a >http://216.239.39.107</a> <a >http://216.239.59.99</a> <a >http://66.102.7.104</a><br /><a >http://216.239.51.100</a> <a >http://216.239.63.104</a> <a >http://66.102.7.105</a><br /><a >http://216.239.51.103</a> <a >http://216.239.63.91</a> <a >http://66.102.7.106</a><br /><a >http://216.239.53.102</a> <a >http://216.239.63.93</a> <a >http://66.102.7.107</a><br /><a >http://216.239.53.103</a> <a >http://216.239.63.99</a> <a >http://66.102.7.147</a><br /><a >http://216.239.53.104</a> <a >http://64.233.161.104</a> <a >http://66.102.7.18</a><br /><a >http://216.239.53.106</a> <a >http://64.233.161.105</a> <a >http://66.102.7.19</a><br /><a >http://216.239.53.107</a> <a >http://64.233.161.106</a> <a >http://66.102.7.89</a><br /><a >http://216.239.53.99</a> <a >http://64.233.161.107</a> <a >http://66.102.7.91</a><br /><a >http://216.239.55.102</a> <a >http://64.233.161.89</a> <a >http://66.102.7.95</a><br /><a >http://216.239.57.103</a> <a >http://64.233.163.104</a> <a >http://66.102.7.99</a><br /><a >http://216.239.57.104</a> <a >http://64.233.163.106</a> <a >http://66.102.9.104</a><br /><a >http://216.239.57.105</a> <a >http://64.233.163.99</a> <a >http://66.102.9.105</a><br /><a >http://216.239.57.106</a> <a >http://64.233.183.91</a> <a >http://66.102.9.106</a><br /><a >http://216.239.57.107</a> <a >http://64.233.183.93</a> <a >http://66.102.9.107</a><br /><a >http://216.239.57.147</a> <a >http://64.233.183.99</a> <a >http://66.102.9.147</a><br /><a >http://216.239.57.98</a> <a >http://64.233.187.104</a> <a >http://66.102.9.99</a></p> <p>转蝲自月光博?[ <a >http://www.williamlong.info</a> ]</p> <img src ="http://m.tkk7.com/terry-zj/aggbug/50404.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2006-06-05 08:35 <a href="http://m.tkk7.com/terry-zj/archive/2006/06/05/50404.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL优化是重?转蝲)http://m.tkk7.com/terry-zj/archive/2006/03/30/38291.htmlTerry的BlogTerry的BlogThu, 30 Mar 2006 09:32:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/03/30/38291.htmlhttp://m.tkk7.com/terry-zj/comments/38291.htmlhttp://m.tkk7.com/terry-zj/archive/2006/03/30/38291.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/38291.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/38291.html信息pȝ讉K量又不大Q瓶颈一般不会出现在应用层,极有可能在数据库q一层,不用急着看程序。先扑և逻辑dơ数最多的SQLQ硬盘读取次数最多的SQLQ找到SQLQ对于SQLq行优化。看看有没有发生全表扫描的地斏V?
一般发生全表扫描,极有可能是没有徏立合理的索引Q或者烦引由于左边引用函数或其它原因造成索引失效?
对于q行一q多的系l,最好要自己写一个自动重建烦引的E序Q定旉建烦引?
或者用TOAD工具帮你重徏索引?

另外在看一下数据库的CPU占用率,如果占用率在l常?0%Q?00%Q那一定要是SQL或存储过E及trigger中写的不好?

不需要从应用层找SQLQ方向性错误,太篏Q也看不出效果?
而应当用pl/SQL, toad{工P分析出最bad的SQL语句Q一看到q些语句后,再修改应用层的查询就是了。又快又方便?

 

-- 逻辑d的SQL
select * from (select buffer_gets, sql_text
from v$sqlarea
where buffer_gets > 500000
order by buffer_gets desc) where rownum<=30;

-- 执行ơ数多的SQL
select sql_text,executions from
(select sql_text,executions from v$sqlarea order by executions desc)
where rownum<81;

-- ȝ盘多的SQL
select sql_text,disk_reads from
(select sql_text,disk_reads from v$sqlarea order by disk_reads desc)
where rownum<21;

-- 排序多的SQL
select sql_text,sorts from
(select sql_text,sorts from v$sqlarea order by sorts desc)
where rownum<21;

--分析的次数太多,执行的次数太,要用l变量的Ҏ来写sql
set pagesize 600;
set linesize 120;
select substr(sql_text,1,80) "sql", count(*), sum(executions) "totexecs"
from v$sqlarea
where executions < 5
group by substr(sql_text,1,80)
having count(*) > 30
order by 2;

转蝲地址 http://forum.javaeye.com/viewtopic.php?t=19464



Terry的Blog 2006-03-30 17:32 发表评论
]]>
最佛_源Y件一?转蝲)http://m.tkk7.com/terry-zj/archive/2006/01/09/27217.htmlTerry的BlogTerry的BlogMon, 09 Jan 2006 02:03:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/01/09/27217.htmlhttp://m.tkk7.com/terry-zj/comments/27217.htmlhttp://m.tkk7.com/terry-zj/archive/2006/01/09/27217.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/27217.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/27217.html最佛_源Y件一?BR>

 



Terry的Blog 2006-01-09 10:03 发表评论
]]>
一关于session的好文(转蝲Q?/title><link>http://m.tkk7.com/terry-zj/archive/2006/01/05/26749.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Thu, 05 Jan 2006 09:21:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2006/01/05/26749.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/26749.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2006/01/05/26749.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/26749.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/26749.html</trackback:ping><description><![CDATA[<P>作者:郎云鹏(dev2dev ID: hippiewolfQ?/P> <P>摘要Q虽然session机制在web应用E序中被采用已经很长旉了,但是仍然有很多h不清楚session机制的本质,以至不能正确的应用这一技术。本文将详细讨论session的工作机制ƈ且对在Java web application中应用session机制时常见的问题作出解答?/P> <P>目录Q?BR>一、术语session<BR>二、HTTP协议与状态保?BR>三、理解cookie机制<BR>四、理解session机制<BR>五、理解javax.servlet.http.HttpSession<BR>六、HttpSession常见问题<BR>七、跨应用E序的session׃n<BR>八、ȝ<BR>参考文?/P> <P>一、术语session<BR>在我的经验里Qsessionq个词被滥用的程度大概仅ơ于transactionQ更加有的是transaction与session在某些语境下的含义是相同的?/P> <P>sessionQ中文经常翻译ؓ会话Q其本来的含义是指有始有l的一pd动作/消息Q比如打电话时从拿v电话拨号到挂断电话这中间的一pdq程可以UCZ个session。有时候我们可以看到这L话“在一个浏览器会话期间Q?..”,q里的会话一词用的就是其本义Q是指从一个浏览器H口打开到关闭这个期间①。最混ؕ的是“用P客户端)在一ơ会话期间”这样一句话Q它可能指用L一pd动作Q一般情况下是同某个具体目的相关的一pd动作Q比如从d到选购商品到结账登样一个网上购物的q程Q有时候也被称Z个transactionQ,然而有时候也可能仅仅是指一ơ连接,也有可能是指含义①,其中的差别只能靠上下文来推断②?/P> <P>然而当session一词与|络协议相关联时Q它又往往隐含了“面向连接”和/或“保持状态”这样两个含义,“面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道,比如打电话,直到Ҏ接了电话通信才能开始,与此相对的是写信Q在你把信发出去的时候你q不能确认对方的地址是否正确Q通信渠道不一定能建立Q但对发信h来说Q通信已经开始了。“保持状态”则是指通信的一方能够把一pd的消息关联v来,使得消息之间可以互相依赖Q比如一个服务员能够认出再次光的老顾客ƈ且记得上ơ这个顾客还Ơ店里一块钱。这一cȝ例子有“一个TCP session”或者“一个POP3 session”③?/P> <P>而到了web服务器蓬勃发展的时代Qsession在web开发语境下的语义又有了新的扩展Q它的含义是指一cȝ来在客户端与服务器之间保持状态的解决Ҏ④。有时候session也用来指q种解决Ҏ的存储结构,如“把xxx保存在session里”⑤。由于各U用于web开发的语言在一定程度上都提供了对这U解x案的支持Q所以在某种特定语言的语境下Qsession也被用来指代该语a的解x案,比如l常把Java里提供的javax.servlet.http.HttpSessionUCؓsession⑥?/P> <P>鉴于q种混ؕ已不可改变,本文中session一词的q用也会Ҏ上下文有不同的含义,请大家注意分辨?BR>在本文中Q用中文“浏览器会话期间”来表达含义①,使用“session机制”来表达含义④,使用“session”表辑֐义⑤Q用具体的“HttpSession”来表达含义?/P> <P>二、HTTP协议与状态保?BR>HTTP协议本n是无状态的Q这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器h下蝲某些文gQ无论是客户端还是服务器都没有必要纪录彼此过ȝ行ؓQ每一ơ请求之间都是独立的Q好比一个顾客和一个自动售货机或者一个普通的Q非会员Ӟ大卖Z间的关系一栗?/P> <P>然而聪明(或者贪心?Q的Z很快发现如果能够提供一些按需生成的动态信息会使web变得更加有用Q就像给有线电视加上Ҏ功能一栗这U需求一斚wqHTML逐步d了表单、脚本、DOM{客L行ؓQ另一斚w在服务器端则出现了CGI规范以响应客L的动态请求,作ؓ传输载体的HTTP协议也添加了文g上蝲、cookieq些Ҏ。其中cookie的作用就是ؓ了解决HTTP协议无状态的~陷所作出的努力。至于后来出现的session机制则是又一U在客户端与服务器之间保持状态的解决Ҏ?/P> <P>让我们用几个例子来描qC下cookie和session机制之间的区别与联系。笔者曾l常ȝ一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠Q然而一ơ性消?杯咖啡的Z微乎其微Q这时就需要某U方式来U录某位֮的消Ҏ量。想象一下其实也无外乎下面的几种ҎQ?BR>1、该店的店员很厉宻I能记住每位顾客的消费数量Q只要顾客一走进咖啡店,店员q道该怎么对待了。这U做法就是协议本w支持状态?BR>2、发l顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每ơ消ҎQ如果顾客出C张卡片,则此ơ消费就会与以前或以后的消费相联pv来。这U做法就是在客户端保持状态?BR>3、发l顾客一张会员卡Q除了卡号之外什么信息也不纪录,每次消费Ӟ如果֮出示该卡片,则店员在店里的纪录本上找到这个卡号对应的U录d一些消费信息。这U做法就是在服务器端保持状态?/P> <P>׃HTTP协议是无状态的Q而出于种U考虑也不希望使之成ؓ有状态的Q因此,后面两种Ҏ成为现实的选择。具体来说cookie机制采用的是在客L保持状态的ҎQ而session机制采用的是在服务器端保持状态的Ҏ。同时我们也看到Q由于采用服务器端保持状态的Ҏ在客L也需要保存一个标识,所以session机制可能需要借助于cookie机制来达C存标识的目的Q但实际上它q有其他选择?/P> <P>三、理解cookie机制 <BR>cookie机制的基本原理就如上面的例子一L单,但是q有几个问题需要解冻I“会员卡”如何分发;“会员卡”的内容Q以及客户如何用“会员卡”?/P> <P>正统的cookie分发是通过扩展HTTP协议来实现的Q服务器通过在HTTP的响应头中加上一行特D的指示以提C浏览器按照指示生成相应的cookie。然而纯_的客户端脚本如Javascript或者VBscript也可以生成cookie?/P> <P>而cookie的用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器查所有存储的cookieQ如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置Q则把该cookie附在h资源的HTTPh头上发送给服务器。意思是麦当劳的会员卡只能在麦当劳的店里出示Q如果某家分店还发行了自q会员卡,那么q这家店的时候除了要出示麦当劳的会员卡,q要出示q家店的会员卡?/P> <P>cookie的内容主要包括:名字Q|q期旉Q\径和域?BR>其中域可以指定某一个域比如.google.comQ相当于d招牌Q比如宝z公司,也可以指定一个域下的具体某台机器比如<A >www.google.com</A>或者froogle.google.comQ可以用飘柔来做比?BR>路径是跟在域名后面的URL路径Q比?或?foo{等Q可以用某飘柔专柜做比?BR>路径与域合在一起就构成了cookie的作用范围?BR>如果不设|过期时_则表C个cookie的生命期为浏览器会话期间Q只要关闭浏览器H口Qcookie消׃。这U生命期为浏览器会话期的cookie被称Z话cookie。会话cookie一般不存储在硬盘上而是保存在内存里Q当然这U行为ƈ不是规范规定的。如果设|了q期旉Q浏览器׃把cookie保存到硬盘上Q关闭后再次打开览器,q些cookie仍然有效直到过讑֮的过期时间?/P> <P>存储在硬盘上的cookie可以在不同的览器进E间׃nQ比如两个IEH口。而对于保存在内存里的cookieQ不同的览器有不同的处理方式。对于IEQ在一个打开的窗口上按Ctrl-NQ或者从文g菜单Q打开的窗口可以与原窗口共享,而用其他方式新开的IEq程则不能共享已l打开的窗口的内存cookieQ对于Mozilla Firefox0.8Q所有的q程和标{N都可以共享同Lcookie。一般来说是用javascript的window.open打开的窗口会与原H口׃n内存cookie。浏览器对于会话cookie的这U只认cookie不认人的处理方式l常l采用session机制的web应用E序开发者造成很大的困扰?/P> <P>下面是一个goolge讄cookie的响应头的例?BR>HTTP/1.1 302 Found<BR>Location: <A >http://www.google.com/intl/zh-CN/</A><BR>Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com<BR>Content-Type: text/html</P> <P><IMG alt="" hspace=0 src="D:\home\200562922161847.jpg" align=baseline border=0></P> <P><BR>q是使用HTTPLookq个HTTP Sniffer软g来俘LHTTP通讯U录的一部分</P> <P><IMG alt="" hspace=0 src="D:\home\200562922167755.jpg" align=baseline border=0></P> <P><BR>览器在再次讉Kgoolge的资源时自动向外发送cookie</P> <P> <IMG alt="" hspace=0 src="D:\home\2005629221613750.jpg" align=baseline border=0></P> <P><BR>使用Firefox可以很容易的观察现有的cookie的?BR>使用HTTPLook配合Firefox可以很容易的理解cookie的工作原理?/P> <P><IMG alt="" hspace=0 src="D:\home\2005629221620917.jpg" align=baseline border=0></P> <P><BR>IE也可以设|在接受cookie前询?/P> <P> <IMG alt="" hspace=0 src="D:\home\2005629221623485.jpg" align=baseline border=0></P> <P><BR>q是一个询问接受cookie的对话框?/P> <P>四、理解session机制<BR>session机制是一U服务器端的机制Q服务器使用一U类g散列表的l构Q也可能是使用散列表)来保存信息?/P> <P>当程序需要ؓ某个客户端的h创徏一个session的时候,服务器首先检查这个客L的请求里是否已包含了一个session标识 - UCؓsession idQ如果已包含一个session id则说明以前已lؓ此客L创徏qsessionQ服务器按照session id把这个session索出来用(如果索不刎ͼ可能会新Z个)Q如果客Lh不包含session idQ则为此客户端创Z个sessionq且生成一个与此session相关联的session idQsession id的值应该是一个既不会重复Q又不容易被扑ֈ规律以仿造的字符Ԍq个session id被在本ơ响应中q回l客L保存?/P> <P>保存q个session id的方式可以采用cookieQ这样在交互q程中浏览器可以自动的按照规则把q个标识发挥l服务器。一般这个cookie的名字都是类gSEEESIONIDQ而。比如weblogic对于web应用E序生成的cookieQJSESSIONID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764Q它的名字就是JSESSIONID?/P> <P>׃cookie可以被h为的止Q必L其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一U技术叫做URL重写Q就是把session id直接附加在URL路径的后面,附加方式也有两种Q一U是作ؓURL路径的附加信息,表现形式?A href="http://...../xxx;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">http://...../xxx;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764</A><BR>另一U是作ؓ查询字符串附加在URL后面Q表现Ş式ؓ<A href="http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764</A><BR>q两U方式对于用h说是没有区别的,只是服务器在解析的时候处理的方式不同Q采用第一U方式也有利于把session id的信息和正常E序参数区分开来?BR>Z在整个交互过E中始终保持状态,必d每个客户端可能请求的路径后面都包含这个session id?/P> <P>另一U技术叫做表单隐藏字Dc就是服务器会自动修改表单,d一个隐藏字D,以便在表单提交时能够把session id传递回服务器。比如下面的表单<BR><form name="testform" action="/xxx"><BR><input type="text"><BR></form><BR>在被传递给客户端之前将被改写成<BR><form name="testform" action="/xxx"><BR><input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764"><BR><input type="text"><BR></form><BR>q种技术现在已较少应用Q笔者接触过的很古老的iPlanet6(SunONE应用服务器的前n)׃用了q种技术?BR>实际上这U技术可以简单的用对action应用URL重写来代ѝ?/P> <P>在谈论session机制的时候,常常听到q样一U误解“只要关闭浏览器Qsession消׃”。其实可以想象一下会员卡的例子,除非֮d对店家提出销卡,否则店家l对不会L删除֮的资料。对session来说也是一LQ除非程序通知服务器删除一个sessionQ否则服务器会一直保留,E序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会d在关闭之前通知服务器它要关闭Q因此服务器Ҏ不会有机会知道浏览器已经关闭Q之所以会有这U错觉,是大部分session机制都用会话cookie来保存session idQ而关闭浏览器后这个session id消׃Q再ơ连接服务器时也无法找到原来的session。如果服务器讄的cookie被保存到盘上,或者用某U手D|写浏览器发出的HTTPh_把原来的session id发送给服务器,则再ơ打开览器仍然能够找到原来的session?/P> <P>恰恰是由于关闭浏览器不会Dsession被删除,q服务器ؓseesion讄了一个失效时_当距dL上一ơ用session的时间超q这个失效时间时Q服务器可以认为客L已经停止了活动,才会把session删除以节省存储空间?/P> <P>五、理解javax.servlet.http.HttpSession<BR>HttpSession是Javaq_对session机制的实现规范,因ؓ它仅仅是个接口,具体到每个web应用服务器的提供商,除了对规范支持之外,仍然会有一些规范里没有规定的细微差异。这里我们以BEA的Weblogic Server8.1作ؓ例子来演C?/P> <P>首先QWeblogic Server提供了一pd的参数来控制它的HttpSession的实玎ͼ包括使用cookie的开关选项Q用URL重写的开关选项Qsession持久化的讄Qsession失效旉的设|,以及针对cookie的各U设|,比如讄cookie的名字、\径、域Qcookie的生存时间等?/P> <P>一般情况下Qsession都是存储在内存里Q当服务器进E被停止或者重启的时候,内存里的session也会被清I,如果讄了session的持久化Ҏ,服务器就会把session保存到硬盘上Q当服务器进E重新启动或q些信息能够被再次使用QWeblogic Server支持的持久性方式包括文件、数据库、客Lcookie保存和复制?/P> <P>复制严格说来不算持久化保存,因ؓsession实际上还是保存在内存里,不过同样的信息被复制到各个cluster内的服务器进E中Q这样即使某个服务器q程停止工作也仍然可以从其他q程中取得session?/P> <P>cookie生存旉的设|则会媄响浏览器生成的cookie是否是一个会话cookie。默认是使用会话cookie。有兴趣的可以用它来试验我们在第四节里提到的那个误解?/P> <P>cookie的\径对于web应用E序来说是一个非帔R要的选项QWeblogic Server对这个选项的默认处理方式得它与其他服务器有明昄区别。后面我们会专题讨论?/P> <P>关于session的设|参考[5] <A >http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869</A></P> <P>六、HttpSession常见问题<BR>Q在本小节中session的含义ؓ⑤和⑥的混合Q?/P> <P><BR>1、session在何时被创徏<BR>一个常见的误解是以为session在有客户端访问时p创徏Q然而事实是直到某server端程序调用HttpServletRequest.getSession(true)q样的语句时才被创徏Q注意如果JSP没有昄的?<<A href="mailto:%@page">%@page</A> session="false"%> 关闭sessionQ则JSP文g在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);q也是JSP中隐含的session对象的来历?/P> <P>׃session会消耗内存资源,因此Q如果不打算使用sessionQ应该在所有的JSP中关闭它?/P> <P>2、session何时被删?BR>l合前面的讨论,session在下列情况下被删除a.E序调用HttpSession.invalidate();或b.距离上一ơ收到客L发送的session id旉间隔过了session的超时设|?或c.服务器进E被停止Q非持久sessionQ?/P> <P>3、如何做到在览器关闭时删除session<BR>严格的讲Q做不到q一炏V可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进E这些非常规手段仍然无能为力?/P> <P>4、有个HttpSessionListener是怎么回事<BR>你可以创Llistenerȝ控session的创建和销毁事Ӟ使得在发生这L事g时你可以做一些相应的工作。注意是session的创建和销毁动作触发listenerQ而不是相反。类似的与HttpSession有关的listenerq有HttpSessionBindingListenerQHttpSessionActivationListener和HttpSessionAttributeListener?/P> <P>5、存攑֜session中的对象必须是可序列化的?BR>不是必需的。要求对象可序列化只是ؓ了session能够在集中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内存。在Weblogic Server的session中放|一个不可序列化的对象在控制C会收C个警告。我所用过的某个iPlanet版本如果session中有不可序列化的对象Q在session销毁时会有一个ExceptionQ很奇怪?/P> <P>6、如何才能正的应付客户端禁止cookie的可能?BR>Ҏ有的URL使用URL重写Q包括超链接Qform的actionQ和重定向的URLQ具体做法参见[6]<BR><A >http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770</A></P> <P>7、开两个览器窗口访问应用程序会使用同一个sessionq是不同的session<BR>参见W三节对cookie的讨论,对session来说是只认id不认人,因此不同的浏览器Q不同的H口打开方式以及不同的cookie存储方式都会对这个问题的{案有媄响?/P> <P>8、如何防止用h开两个览器窗口操作导致的session混ؕ<BR>q个问题与防止表单多ơ提交是cM的,可以通过讄客户端的令牌来解冟뀂就是在服务器每ơ生成一个不同的idq回l客LQ同时保存在session里,客户端提交表单时必须把这个id也返回服务器Q程序首先比较返回的id与保存在session里的值是否一_如果不一致则说明本次操作已经被提交过了。可以参看《J2EE核心模式》关于表C层模式的部分。需要注意的是对于用javascript window.open打开的窗口,一般不讄q个idQ或者用单独的idQ以防主H口无法操作Q徏议不要再window.open打开的窗口里做修Ҏ作,q样可以不用设|?/P> <P>9、ؓ什么在Weblogic Server中改变session的值后要重新调用一ơsession.setValue<BR>做这个动作主要是Z在集环境中提示Weblogic Server session中的值发生了改变Q需要向其他服务器进E复制新的session倹{?/P> <P>10、ؓ什么session不见?BR>排除session正常失效的因素之外,服务器本w的可能性应该是微乎其微的,虽然W者在iPlanet6SP1加若q补丁的Solaris版本上倒也遇到q;览器插件的可能性次之,W者也遇到q?721插g造成的问题;理论上防火墙或者代理服务器在cookie处理上也有可能会出现问题?BR>出现q一问题的大部分原因都是E序的错误,最常见的就是在一个应用程序中去访问另外一个应用程序。我们在下一节讨个问题?/P> <P>七、跨应用E序的session׃n</P> <P>常常有这L情况Q一个大目被分割成若干项目开发,Z能够互不q扰Q要求每个小目作ؓ一个单独的web应用E序开发,可是C最后突然发现某几个项目之间需要共享一些信息,或者想使用session来实现SSO(single sign on)Q在session中保存login的用户信息,最自然的要求是应用E序间能够访问彼此的session?/P> <P>然而按照Servlet规范Qsession的作用范围应该仅仅限于当前应用程序下Q不同的应用E序之间是不能够互相讉KҎ的session的。各个应用服务器从实际效果上都遵守了q一规范Q但是实现的l节却可能各有不同,因此解决跨应用程序session׃n的方法也各不相同?/P> <P>首先来看一下Tomcat是如何实现web应用E序之间session的隔ȝQ从Tomcat讄的cookie路径来看Q它对不同的应用E序讄的cookie路径是不同的Q这样不同的应用E序所用的session id是不同的Q因此即使在同一个浏览器H口里访问不同的应用E序Q发送给服务器的session id也可以是不同的?/P> <P><IMG alt="" hspace=0 src="D:\home\2005629221626822.jpg" align=baseline border=0><BR>  </P> <P>Ҏq个Ҏ,我们可以推测Tomcat中session的内存结构大致如下?/P> <P><IMG alt="" hspace=0 src="D:\home\2005629221626479.jpg" align=baseline border=0><BR> </P> <P>W者以前用q的iPlanet也采用的是同L方式Q估计SunONE与iPlanet之间不会有太大的差别。对于这U方式的服务器,解决的思\很简单,实际实行h也不难。要么让所有的应用E序׃n一个session idQ要么让应用E序能够获得其他应用E序的session id?/P> <P>iPlanet中有一U很单的Ҏ来实现共享一个session idQ那是把各个应用程序的cookie路径都设?Q实际上应该?NASAppQ对于应用程序来讲它的作用相当于根)?BR><session-info><BR><path>/NASApp</path><BR></session-info></P> <P>需要注意的是,操作׃n的session应该遵@一些编E约定,比如在session attribute名字的前面加上应用程序的前缀Q得setAttribute("name", "neo")变成setAttribute("app1.name", "neo")Q以防止命名I间冲突Q导致互相覆盖?/P> <P><BR>在Tomcat中则没有q么方便的选择。在Tomcat版本3上,我们q可以有一些手D|׃nsession。对于版?以上的TomcatQ目前笔者尚未发现简单的办法。只能借助于第三方的力量,比如使用文g、数据库、JMS或者客LcookieQURL参数或者隐藏字D늭手段?/P> <P>我们再看一下Weblogic Server是如何处理session的?/P> <P><IMG alt="" hspace=0 src="D:\home\2005629221630550.jpg" align=baseline border=0><BR>  </P> <P>从截屏画面上可以看到Weblogic ServerҎ有的应用E序讄的cookie的\径都?Q这是不是意味着在Weblogic Server中默认的可以共享session了呢Q然而一个小实验卛_证明即不同的应用程序用的是同一个sessionQ各个应用程序仍然只能访问自己所讄的那些属性。这说明Weblogic Server中的session的内存结构可能如?/P> <P><IMG alt="" hspace=0 src="D:\home\2005629221630874.jpg" align=baseline border=0><BR> </P> <P>对于q样一U结构,在session机制本n上来解决session׃n的问题应该是不可能的了。除了借助于第三方的力量,比如使用文g、数据库、JMS或者客LcookieQURL参数或者隐藏字D늭手段Q还有一U较为方便的做法Q就是把一个应用程序的session攑ֈServletContext中,q样另外一个应用程序就可以从ServletContext中取得前一个应用程序的引用。示例代码如下,</P> <P>应用E序A<BR>context.setAttribute("appA", session); </P> <P>应用E序B<BR>contextA = context.getContext("/appA");<BR>HttpSession sessionA = (HttpSession)contextA.getAttribute("appA"); </P> <P>值得注意的是q种用法不可ULQ因为根据ServletContext的JavaDocQ应用服务器可以处于安全的原因对于context.getContext("/appA");q回I|以上做法在Weblogic Server 8.1中通过?/P> <P>那么Weblogic ServerZ么要把所有的应用E序的cookie路径都设?呢?原来是ؓ了SSOQ凡是共享这个session的应用程序都可以׃n认证的信息。一个简单的实验可以证明这一点,修改首先d的那个应用程序的描述Wweblogic.xmlQ把cookie路径修改?appA讉K另外一个应用程序会重新要求dQ即使是反过来,先访问cookie路径?的应用程序,再访问修改过路径的这个,虽然不再提示dQ但是登录的用户信息也会丢失。注意做q个实验时认证方式应该用FORMQ因为浏览器和web服务器对basic认证方式有其他的处理方式Q第二次h的认证不是通过session来实现的。具体请参看[7] secion 14.8 AuthorizationQ你可以修改所附的CZE序来做q些试验?/P> <P>八、ȝ<BR>session机制本nq不复杂Q然而其实现和配|上的灵zL却使得具体情况复杂多变。这也要求我们不能把仅仅某一ơ的l验或者某一个浏览器Q服务器的经验当作普遍适用的经验,而是始终需要具体情况具体分析?/P> <P>关于作者:<BR>郎云鹏(dev2dev ID: hippiewolfQ,软g工程师,从事J2EE开?BR>电子邮gQ?A href="mailto:langyunpeng@yahoo.com.cn">langyunpeng@yahoo.com.cn</A><BR>地址Q大qY件园?1L技大厦A座大q博涵咨询服务有限公?/P> <P>参考文档:<BR>[1] Preliminary Specification <A >http://wp.netscape.com/newsref/std/cookie_spec.html</A><BR>[2] RFC2109 <A >http://www.rfc-editor.org/rfc/rfc2109.txt</A><BR>[3] RFC2965 <A >http://www.rfc-editor.org/rfc/rfc2965.txt</A><BR>[4] The Unofficial Cookie FAQ <A >http://www.cookiecentral.com/faq/</A><BR>[5] <A >http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869</A><BR>[6] <A >http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770</A><BR>[7] RFC2616 <A >http://www.rfc-editor.org/rfc/rfc2616.txt</A></P> <P><BR>代码下蝲Q?A >http://dev2dev.bea.com.cn/images/paihang_article/041020/sampleApp.zip</A><BR><BR>转蝲地址Q?A >http://www.supcode.com/Article/html/4/43/2005/06/29/216335472190.shtml</A></P><img src ="http://m.tkk7.com/terry-zj/aggbug/26749.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2006-01-05 17:21 <a href="http://m.tkk7.com/terry-zj/archive/2006/01/05/26749.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>session功能实现原理(转蝲)http://m.tkk7.com/terry-zj/archive/2005/12/30/26078.htmlTerry的BlogTerry的BlogFri, 30 Dec 2005 08:11:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/30/26078.htmlhttp://m.tkk7.com/terry-zj/comments/26078.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/30/26078.html#Feedback1http://m.tkk7.com/terry-zj/comments/commentRss/26078.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/26078.htmlHTTP协议Q?A >http://www.w3.org/Protocols/Q是“一ơ性单向”协议?
服务端不能主动连接客LQ只能被动等待ƈ{复客户端请求。客Lq接服务端,发出一个HTTP RequestQ服务端处理hQƈ且返回一个HTTP Responsel客LQ本ơHTTP Request-Response Cyclel束?
我们看到QHTTP协议本nq不能支持服务端保存客户端的状态信息。于是,Web Server中引入了session的概念,用来保存客户端的状态信息?
q里用一个Ş象的比喻来解释session的工作方式。假设Web Server是一个商场的存包处,HTTP Request是一个顾客,W一ơ来到存包处Q管理员把顾客的物品存放在某一个柜子里面(q个柜子q当于SessionQ,然后把一个号码牌交给q个֮Q作为取包凭证(q个L牌就是Session IDQ。顾客(HTTP RequestQ下一ơ来的时候,p把号码牌QSession IDQ交l存包处QWeb ServerQ的理员。管理员ҎL牌(Session IDQ找到相应的柜子QSessionQ,Ҏ֮QHTTP RequestQ的hQWeb Server可以取出、更换、添加柜子(SessionQ中的物品,Web Server也可以让֮QHTTP RequestQ的L牌和L牌对应的柜子QSessionQ失效。顾客(HTTP RequestQ的忘性很大,理员在֮回去的时候(HTTP ResponseQ都要重新提醒顾客记住自qL牌(Session IDQ。这P֮QHTTP RequestQ下ơ来的时候,又带着L牌回来了?
我们可以看到QSession ID实际上是在客L和服务端之间通过HTTP Request和HTTP Response传来传去的?

我们看到Q号码牌QSession IDQ必d含在HTTP Request里面。关于HTTP Request的具体格式,请参见HTTP协议Q?A >http://www.w3.org/Protocols/Q。这里只做一个简单的介绍?
在Java Web ServerQ即Servlet/JSP ServerQ中QSession ID用jsessionid表示Q请参见Servlet规范Q?
HTTP Request一般由3部分l成Q?
Q?QRequest Line
q一行由HTTP MethodQ如GET或POSTQ、URL、和HTTP版本L成?
例如QGET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1
GET http://www.google.com/search?q=Tomcat HTTP/1.1
POST http://www.google.com/search HTTP/1.1
GET http://www.somsite.com/menu.do;jsessionid=1001 HTTP/1.1

Q?QRequest Headers
q部分定义了一些重要的头部信息Q如Q浏览器的种c,语言Q类型。Request Headers中还可以包括Cookie的定义。例如:
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
Accept-Language: en-us
Cookie: jsessionid=1001

Q?QMessage Body
如果HTTP Method是GETQ那么Message Body为空?
如果HTTP Method是POSTQ说明这个HTTP Request是submit一个HTML Form的结果,
那么Message Body为HTML Form里面定义的Input属性。例如,
user=guest
password=guest
jsessionid=1001
LQ如果把HTML Form元素的Method属性改为GET。那么,Message Body为空Q所有的Input属性都会加在URL的后面。你在浏览器的URL地址栏中会看到这些属性,cM?
http://www.somesite/login.do?user=guest&password=guest&jsessionid=1001

从理Z来说Q这3个部分(Request URLQCookie Header, Message BodyQ都可以用来存放Session ID。由于Message BodyҎ必须需要一个包含Session ID的HTML FormQ所以这U方法不通用?
一般用来实现Session的方法有两种Q?
Q?QURL重写?
Web Server在返回Response的时候,查页面中所有的URLQ包括所有的q接Q和HTML Form的Action属性,在这些URL后面加上?jsessionid=XXX”?
下一ơ,用户讉Kq个面中的URL。jsessionid׃传回到Web Server?
Q?QCookie?
如果客户端支持CookieQWeb Server在返回Response的时候,在Response的Header部分Q加入一个“set-cookie: jsessionid=XXXX”header属性,把jsessionid攑֜Cookie里传到客L?
客户端会把Cookie存放在本地文仉Q下一ơ访问Web Server的时候,再把Cookie的信息放到HTTP Request的“Cookie”header属性里面,q样jsessionid随着HTTP Requestq回lWeb Server?

我们来看Tomcat5的源代码如何支持jsessionid?
org.apache.coyote.tomcat5.CoyoteResponsecȝtoEncoded()Ҏ支持URL重写?
String toEncoded(String url, String sessionId) {
?
StringBuffer sb = new StringBuffer(path);
if( sb.length() > 0 ) { // jsessionid can't be first.
sb.append(";jsessionid=");
sb.append(sessionId);
}
sb.append(anchor);
sb.append(query);
return (sb.toString());
}

我们来看org.apache.coyote.tomcat5.CoyoteRequest的两个方法configureSessionCookie()
doGetSession()用Cookie支持jsessionid.

/**
* Configures the given JSESSIONID cookie.
*
* @param cookie The JSESSIONID cookie to be configured
*/
protected void configureSessionCookie(Cookie cookie) {
?
}

HttpSession doGetSession(boolean create){
?
// Creating a new session cookie based on that session
if ((session != null) && (getContext() != null)
&& getContext().getCookies()) {
Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME,
session.getId());
configureSessionCookie(cookie);
((HttpServletResponse) response).addCookie(cookie);
}
?
}

Session的典型应用是存放用户的Login信息Q如用户名,密码Q权限角色等信息Q应用程序(如Email服务、网上银行等pȝQ根据这些信息进行n份验证和权限验证



Terry的Blog 2005-12-30 16:11 发表评论
]]>
让JavaE序自带JREQ{载)http://m.tkk7.com/terry-zj/archive/2005/12/30/26023.htmlTerry的BlogTerry的BlogFri, 30 Dec 2005 03:23:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/30/26023.htmlhttp://m.tkk7.com/terry-zj/comments/26023.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/30/26023.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/26023.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/26023.html        用Java开发程序,发布时总要考虑的问题就是怎么在用者的机器上装好JRE。要考虑的问题很多:使用者有没有能力独自安装JREQ?BR>使用者已有的JRE和我们需要的版本是不是一_会不会出现版本问题,{等。?NET要考虑的问题就些。现?NET CLRg已经很普?BR>了,看好多D版的Win XP都会自己安装最新的.NET CLRQ而且g它的安装界面也比JRE友好些。彻底解军_装JRE的问题的ҎQ就是让?BR>们的应用E序自己背着JREQ这P我们的程序就像传l的Win32应用E序一P双击可以执行,不用所在的机器上是否有JREQ是什么版
本的JREQ无论怎样Q我有我自己的!要做到这一点,其实非常Ҏ?/FONT>


王森在他的《Java深度历险》(强力推荐q本书,内容而精Q的W一章就解释了JDKQJREQJVM之间的关pR解释了我们执行java.exe?BR>发生的事情。其中提刎ͼjava.exe依照一套逻辑来寻扑֏以用的JREQ首先查找自己�诘哪柯枷掠忻挥蠮REQ据王森讲这栯不确切,我没?BR>JDK全部的源代码Q在此无从考证Q;其次查找自己的父目录下有没有JREQ最后才是查询Windows的注册表?/FONT>


通常我们在安装好了JRE的机器上的Q何一个目录下都可以执行java.exe。因为它在安装时被复制到了windows的system32目录下,而后?BR>无论如何都会在path环境变量中。这个java.exe最l必然会讉K注册表来定真正的JRE的所在地。若我们要求每一个应用程序都自带JREQ?BR>必然不能走这条\。但Q逻辑的第二条Ԍjava.exe会在它的父目录下查找JREQ解x案就在这一条中?/FONT>


假设我们的应用程序打好了包,叫做MyApp.jarQ放在MyApp的目录下。我们在MyApp目录下,可以执行java –jar MyApp.jar来运行我?BR>的程序。我们安装的是JRE 1.5Q在C:\Program Files\Java\jre1.5.0下。现在,我们只需要简单的jre1.5.0目录搬到MyApp目录下,?BR>便改个容易写的名字比如叫jre。现在,我们的应用程序就象这P

MyApp

       MyApp.jar

       Jre

              Jre1.5.0目录下的全部内容

Java.exe在jre目录下的bin目录中。根据第二条逻辑Qjava.exe会在它的父目录中查找jreQ实验证实,它会查找lib目录Q而lib在jre?BR>录下。因此,q样java.exe׃定jre的所在然后正常执行javaE序Q不会去我们是否安装了JREQ注册表中是否有注册这些杂事了?/FONT>

试一下,在命令行下进入MyApp的目录下Q假讑֮在C盘,path指向MyApp下的JREQ?/FONT>

set path=c:\MyApp\jre\bin

然后q行Q?/FONT>

java –verbose –jar MyApp.jar

加上verbose参数以确定我们确实用了这一套被搬出了家的JRE?/FONT>

E序可以q行Qƈ且在命o行输出的前几行,可以看到Q?/FONT>

[Opened C:\MyApp\jre\lib\rt.jar]

[Opened C:\MyApp\jre\lib\jsse.jar]

[Opened C:\MyApp\jre\lib\jce.jar]

[Opened C:\MyApp\jre\lib\charsets.jar]

因此E序d的确实是它的U有的JRE?/FONT>

xQ我们似乎完成了d。但是现在我们的U有JRE仍不完美Q缺Ҏ太大。JRE 1.5有接q?0MBQ作为我们的U有的JREQ好多内定w?BR>可以抛弃的。Jre目录下的license都可以不要,bin下的执行文g只需要保留java.exe或者javaw.exeQlib下只要保?BR>rtQjsseQjceQcharsets几个库就可以了。除了i386和zi两个子目录外Q其余的子目录都可以不要。Zi下只需要保留自己地区的子目录和其下
的一些文件就可以。Lib下除了库之外的属性文件等{都要保留。这h理一番,JRE仍然有接q?0MB。还可以l箋清理几个库文仉面不需
要的内容Q这需要仔l的整理Q会很费功夫。最好能写出一个自动工具帮助我们整理它们。从Sun公司上下到的JMF里面附带的用Java写的?BR>体播攑֙p带了JREQ只有几个MB?/FONT>


清理q后需要运行几遍我们的应用E序Q以保我们的JRE不缺东ѝ?/FONT>

如果我们希望能有一个程序直接启动我们的应用E序Q那p要费些功夫。最单的Ҏ是弄Z个快h式来Q但是快h式的路径不能是相
对的Q不方便我们安装。我惛_的方案就是用Win32E序包装一下。在VS.NET下写一个Win32程序:

int PASCAL WinMain( HINSTANCE hInstance,

    HINSTANCE hPrevInstance,

    LPSTR lpszCmdLine,

    int nCmdShow )

{

    STARTUPINFO si;

    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );

    si.cb = sizeof(si);

    ZeroMemory( &pi, sizeof(pi) );

    // Start the child process.

    if( !CreateProcess( "jre\\bin\\javaw.exe",//执行的程序名

                        "jre\\bin\\javaw.exe -jar MyApp.jar", // 带参数的执行E序

            NULL,             // Process handle not inheritable.

            NULL,             // Thread handle not inheritable.

            FALSE,            // Set handle inheritance to FALSE.

            0,                // No creation flags.

            NULL,             // Use parent’s environment block.

            NULL,             // Use parent’s starting directory.

            &si,              // Pointer to STARTUPINFO structure.

            &pi )             // Pointer to PROCESS_INFORMATION structure.

    )

    {

            ErrorExit( "CreateProcess failed." );

    }

     // Wait until child process exits.

    WaitForSingleObject( pi.hProcess, INFINITE );

     // Close process and thread handles.

    CloseHandle( pi.hProcess );

    CloseHandle( pi.hThread );

}

基本上是按照MSDN文档中的例子照搬的。将它编译成一个EXE文gQ我们的d才全部完成。双击这个EXE文gQ我们的E序启动了,看v?BR>和传l的Win32E序没有两样QJRE完全被隐藏在底层?BR>
转蝲地址 
http://www.matrix.org.cn/resource/article/44/44085_java.html



Terry的Blog 2005-12-30 11:23 发表评论
]]>
介绍struts的新Ҏ?Lazy ActionFormQ{载)http://m.tkk7.com/terry-zj/archive/2005/12/09/23090.htmlTerry的BlogTerry的BlogFri, 09 Dec 2005 02:43:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/09/23090.htmlhttp://m.tkk7.com/terry-zj/comments/23090.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/09/23090.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/23090.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/23090.html STRUTS?ActionForm到现在ؓ?出现了最三U方?/span>: 普通的,动态的和懒?

所以你在你自已的开发中,可以有很多选择,如果你安全第一,可以用普通的.如果你更喜欢XML,则用动态的.

如果你很?那就用Lazy ActionForm.  available in Version 1.2.6 onwards

STRUTS提供的这三种ActionForm方式,要实际应用中你只要选择一U就可以?

下面说说Lazy ActionForm: 

如果你喜ƢSTRUTS的强大的功能的特?比如这个ActionForm有多U选择),又喜Ƣ快? Lazy ActionForm对你来说是一个好消息. q个有点cM于WW2中值得U道的一个特?可以减少~写ActionForm的麻?(STRUTS正在把WW2中好的东襉K吸收q来?难怪这两个东西以后会合qؓSTRUTS IT).

CZ代码如下:

struts-config.xml配置
<struts-config> 

  <form-beans> 
     <form-bean name="lazyForm" type="org.apache.struts.validator.LazyValidatorForm"/> 
  </form-beans> 

  <action-mappings> 
    <action path="/myActionPath" type="myPackage.MyAction" name="lazyForm" validate="true"/> 
  </action-mappings>

</struts-config>
JSP|页
<html:form action="/myActionPath"> 

  <h2>Simple Property Example</h2>
         
          Customer Number: <html:text property="custNo"/>
          Customer Name:   <html:text property="custName"/> 

  <h2>Mapped Property Example</h2>
         
          Street:  <html:text property="address(street)"/>
          Town:    <html:text property="address(town)"/>
          State:   <html:text property="address(state)"/>
          Country: <html:text property="address(country)"/> 

  <h2>Indexed Property Example</h2> 
          
  <logic:iterate id="products" property="products"> 
    Product Code:<html:text name="products" property="code" indexed="true"/> 
    Product Description:<html:text name="products" property="description" indexed="true"/> 
    Product Price:<html:text name="products" property="price" indexed="true"/> 
  </logic:iterate>

</html:form>
action调用
java代码: 
public ActionForward execute(ActionMapping mapping,
                                 ActionForm form,
                                 HttpServeletRequest request,
                                 HttpServletResponse response)throwsException{ 
    // Cast form to DynaBean 
    DynaBean dynaForm = (DynaBean)form; 

    // Use the DynaBean 
    String custNo = (String)dynaForm.get("custNo");   // simple 
    Map address   = (Map)dynaForm.get("address");     // mapped 
    List products = (List)dynaForm.get("products");   // indexed  
    //... etc
}
在ACTION?你可以?BeanUtils 1.7.0的特?把dynaForm一ơ性拷贝到HIBERNATE的POJO中去!

转蝲地址Qhttp://forum.javaeye.com/viewtopic.php?t=17441


Terry的Blog 2005-12-09 10:43 发表评论
]]>
java抽取word,pdf的四U武?转蝲)http://m.tkk7.com/terry-zj/archive/2005/12/07/22856.htmlTerry的BlogTerry的BlogWed, 07 Dec 2005 06:40:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/07/22856.htmlhttp://m.tkk7.com/terry-zj/comments/22856.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/07/22856.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/22856.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/22856.html摘要Q?BR>
转蝲Q{载请保留本信息,本文来自http://www.matrix.org.cn/resource/article/0/120.html
很多人问到如何抽取wordQexcelQpdfѝ这里我ȝ一下抽取word,pdf?BR>几种Ҏ?BR>1。用jacob.
其实jacob是一个bridageQ连接java和com或者win32函数的一个中间gQjacobq不能直接抽取word,excel{文Ӟ需要自己写dll哦,不过已经有ؓ你写好的了,是jacob的作者一q提供了?BR>jacob下蝲Qhttp://www.matrix.org.cn/down_view.asp?id=13
下蝲了jacobq放到指定的路径之后(dll攑ֈpath,jar文g攑ֈclasspath)Q就可以写你自己的抽取程序了Q下面是一个例子:
import java.io.File;
import com.jacob.com.*;
import com.jacob.activeX.*;

public class FileExtracter{

public static void main(String[] args) {

ActiveXComponent app = new ActiveXComponent("Word.Application");
String inFile = "c:\\test.doc";
String tpFile = "c:\\temp.htm";
String otFile = "c:\\temp.xml";
boolean flag = false;
try {
app.setProperty("Visible", new Variant(false));
Object docs = app.getProperty("Documents").toDispatch();
Object doc = Dispatch.invoke(docs,"Open", Dispatch.Method, new Object[]{inFile,new Variant(false), new Variant(true)}, new int[1]).toDispatch();
Dispatch.invoke(doc,"SaveAs", Dispatch.Method, new Object[]{tpFile,new Variant(8)}, new int[1]);
Variant f = new Variant(false);
Dispatch.call(doc, "Close", f);
flag = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
app.invoke("Quit", new Variant[] {});
}

}
}
2。用apache的poi来抽取wordQexcel?/SPAN>
poi是apache的一个项目,不过q用poi你可能都觉得很烦Q不q不要紧Q这里提供了更加单的一个接口给你:
下蝲l过装后的poi包:http://www.matrix.org.cn/down_view.asp?id=14
下蝲之后Q放C的classpath可以了Q下面是如何使用它的一个例子:
import java.io.*;
import org.textmining.text.extraction.WordExtractor;
/**
* <p>Title: pdf extraction</p>
* <p>Description: email:chris@matrix.org.cn</p>
* <p>Copyright: Matrix Copyright (c) 2003</p>
* <p>Company: Matrix.org.cn</p>
* @author chris
* @version 1.0,who use this example pls remain the declare
*/

public class PdfExtractor {
public PdfExtractor() {
}
public static void main(String args[]) throws Exception
{
FileInputStream in = new FileInputStream ("c:\\a.doc");
WordExtractor extractor = new WordExtractor();
String str = extractor.extractText(in);
System.out.println("the result length is"+str.length());
System.out.println("the result is"+str);
}
}

3。pdfbox-用来抽取pdf文g
但是pdfbox对中文支持还不好Q先下蝲pdfboxQhttp://www.matrix.org.cn/down_view.asp?id=12
下面是一个如何用pdfbox抽取pdf文g的例子:
import org.pdfbox.pdmodel.PDDocument;
import org.pdfbox.pdfparser.PDFParser;
import java.io.*;
import org.pdfbox.util.PDFTextStripper;
import java.util.Date;
/**
* <p>Title: pdf extraction</p>
* <p>Description: email:chris@matrix.org.cn</p>
* <p>Copyright: Matrix Copyright (c) 2003</p>
* <p>Company: Matrix.org.cn</p>
* @author chris
* @version 1.0,who use this example pls remain the declare
*/

public class PdfExtracter{

public PdfExtracter(){
}
public String GetTextFromPdf(String filename) throws Exception
{
String temp=null;
PDDocument pdfdocument=null;
FileInputStream is=new FileInputStream(filename);
PDFParser parser = new PDFParser( is );
parser.parse();
pdfdocument = parser.getPDDocument();
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter( out );
PDFTextStripper stripper = new PDFTextStripper();
stripper.writeText(pdfdocument.getDocument(), writer );
writer.close();
byte[] contents = out.toByteArray();

String ts=new String(contents);
System.out.println("the string length is"+contents.length+"\n");
return ts;
}
public static void main(String args[])
{
PdfExtracter pf=new PdfExtracter();
PDDocument pdfDocument = null;

try{
String ts=pf.GetTextFromPdf("c:\\a.pdf");
System.out.println(ts);
}
catch(Exception e)
{
e.printStackTrace();
}
}

}

4.抽取支持中文的pdf文gQxpdf
xpdf是一个开源项目,我们可以调用他的本地Ҏ来实现抽取中文pdf文g?BR>下蝲xpdf函数包:http://www.matrix.org.cn/down_view.asp?id=15
同时需要下载支持中文的补丁包:http://www.matrix.org.cn/down_view.asp?id=16
按照readme攑֥中文的patchQ就可以开始写调用本地Ҏ的javaE序?BR>下面是一个如何调用的例子Q?BR>import java.io.*;
/**
* <p>Title: pdf extraction</p>
* <p>Description: email:chris@matrix.org.cn</p>
* <p>Copyright: Matrix Copyright (c) 2003</p>
* <p>Company: Matrix.org.cn</p>
* @author chris
* @version 1.0,who use this example pls remain the declare
*/


public class PdfWin {
public PdfWin() {
}
public static void main(String args[]) throws Exception
{
String PATH_TO_XPDF="C:\\Program Files\\xpdf\\pdftotext.exe";
String filename="c:\\a.pdf";
String[] cmd = new String[] { PATH_TO_XPDF, "-enc", "UTF-8", "-q", filename, "-"};
Process p = Runtime.getRuntime().exec(cmd);
BufferedInputStream bis = new BufferedInputStream(p.getInputStream());
InputStreamReader reader = new InputStreamReader(bis, "UTF-8");
StringWriter out = new StringWriter();
char [] buf = new char[10000];
int len;
while((len = reader.read(buf))>= 0) {
//out.write(buf, 0, len);
System.out.println("the length is"+len);
}
reader.close();
String ts=new String(buf);
System.out.println("the str is"+ts);
}
}


Terry的Blog 2005-12-07 14:40 发表评论
]]>
解决Tomcat 5.0.19 中文参数传递问?转蝲)http://m.tkk7.com/terry-zj/archive/2005/12/07/22845.htmlTerry的BlogTerry的BlogWed, 07 Dec 2005 05:33:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/07/22845.htmlhttp://m.tkk7.com/terry-zj/comments/22845.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/07/22845.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/22845.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/22845.html        實際運用 Tomcat 5.0.19Q我們了解在不修?Tomcat 原始的狀況下Q用者透過 Form submit 的資料將一律以 ISO8859-1 處理Q程式設a師必須自行字串將轉換?Big5(J體中文) or GB2312/GBK(體中文)Q我們在應用E式中,所有的 request.getParameter("xx"); 作了 toBig5String() 的處理,理論上,所有的中文問題應該不會出現才對Q結果,還是發現某些狀況下Q中文還是變成亂|

E過分析整理Q我們發珑֕出?QueryString 的解析,以前?Tomcat 4.x 時代Q無?SUBMIT 時採?GET or POSTQTomcat server ?parameters 的處理都採用相同的編|但在 Tomcat 5.x 版,不知何故Q卻?QueryString 的解析獨立出來,目前QForm ?Method 採用 GET 及直接將參數寫在 URL 上的中文Q上傛_ Tomcat 時,無論如何轉碼Q都會變成亂|那怕你事先作過 URLEncode 也一樣?

E站上,有h針對這個問,所有中文改採用 base64 R碼Q到?server 上,E式自行土 base64 decode 回來Q確保中文不會發生問。這樣作法當然可以解決這個問,但是所有網頁變成限定要採用 POSTQ且E式a計師要隨時分清楚,那個參數是採用 GET 上傳Q那個參數是採用 POST 上傳Q然後再針對不同的方式採用不同的解析Q這樣的程式一點兒UL性都沒有Q更別提跨^台、跨國際語言了?

研究 Tomcat 的文件及原始|我們找C問題所在及解決的方法,只有按著以下的作法,才能?Form submit 的資料完全按?ISO8859-1 的編|當然Q若是全照著 Tomcat 的文件說明去作,肯定還是不行Q你還是得加上這個參數到 server.xml 中才行?

解決Ҏ

請先研究 $TOMCAT_HOME/webapps/tomcat-docs/config/http.html 這個說明檔Q擷錄重點如下:
URIEncodingQThis specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.

useBodyEncodingForURIQThis specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the URIEncoding. This setting is present for compatibility with Tomcat 4.1.x, where the encoding specified in the contentType, or explicitely set using Request.setCharacterEncoding method was also used for the parameters from the URL. The default value is false.

上述二?Tomcat 參數Q是a定?server.xml 中的 http <Connector /> 區塊,要解?QueryString 中文變成亂碼的問,你必須至設定這二個參數其中之一?
URIEncoding 請設定為 URIEncoding="ISO-8859-1" 指定?"ISO-8859-1" R碼Q讓 QueryString 的字元編D post body 相同?
useBodyEncodingForURI 這是用來相容 Tomcat 4.x 版的Q設定的值是 "true" or "false"Q意思是?"要不要讓 QueryString ?POST BODY 採用相同的字元編??"Q若是設?trueQ那也可達到 "ISO-8859-1" R碼的需求?
Q採?URIEncoding 的設定,畢竟 useBodyEncodingForURI 的作法是Z相容 Tomcat 4.X。不過若照原文的說明Q理論上這二個參敔R不設QTomcat 也該採用 "ISO-8859-1" 的編|那為什麼還是會有問呢 ? 我們由 Tomcat Source Code 來看清楚了?/FONT>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 這一D늢?Tomcat 用來?QueryString 的程式,
// ?org.apache.tomcat.util.http.Parameters 這?class 裡?/FONT>
private String urlDecode(ByteChunk bc, String enc)
  throws IOException {
  if( urlDec==null ) {
     urlDec=new UDecoder(); 
  }
  urlDec.convert(bc);
  String result = null;
  if (enc != null) {
    bc.setEncoding(enc);
    result = bc.toString();
  } 
  else {
    CharChunk cc = tmpNameC;
    cc.allocate(bc.getLength(), -1);
    // Default encoding: fast conversion
    byte[] bbuf = bc.getBuffer();
    char[] cbuf = cc.getBuffer();
    int start = bc.getStart();
    for (int i = 0; i < bc.getLength(); i++) {
      cbuf[i] = (char) (bbuf[i + start] & 0xff);
    }
    cc.setChars(cbuf, 0, bc.getLength());
    result = cc.toString();
    cc.recycle();
  }
  return result;
}

請特別注意紅色區塊,?Tomcat 發現 QueryString 並沒有設?encode 時,並非像文件中所說預a採?ISO-8859-1 的編|而是用一D?fast conversion 來處理,才會造成中文問題Q所以,還是必須?Server.xml 中,加上 URLEncoding 的參數設定才行哦?

Connector 的設定範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<Connector
debug="0"
acceptCount="100"
connectionTimeout="20000"
disableUploadTimeout="true"
port="80"
redirectPort="8443"
enableLookups="false"
minSpareThreads="25"
maxSpareThreads="75"
maxThreads="150"
maxPostSize="0"
URIEncoding="ISO-8859-1"
>
</Connector>

转蝲地址Q?BR>http://www.javaworld.com.tw/jute/post/view?bid=9&id=44042&sty=1&tpg=1&age=0

Terry的Blog 2005-12-07 13:33 发表评论
]]>
提交一个查询有必要用事务吗?(转蝲) http://m.tkk7.com/terry-zj/archive/2005/12/06/22792.htmlTerry的BlogTerry的BlogTue, 06 Dec 2005 14:25:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/06/22792.htmlhttp://m.tkk7.com/terry-zj/comments/22792.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/06/22792.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/22792.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/22792.html如果只提交一个查询,有必要用事务吗?q个问题之前已经讨论q?

http://forum.javaeye.com/viewtopic.php?t=1603

但是q没有得出明的l论。先让我们看看事务的定义Q?

引用:

Transactions are described in terms of ACID properties, which are as follows:
n Atomic: all changes to the database made in a transaction are rolled back if any
change fails.
n Consistent: the effects of a transaction take the database from one consistent
state to another consistent state.
n Isolated: the intermediate steps in a transaction are not visible to other users of
the database.
n Durable: when a transaction is completed (committed or rolled back), its effects
persist in the database.
 


即ACID的定义,从上面看来,g除了isolated之外Q和只读查询都没有关pR那么是否只L询不需要事务呢Q?

再看看Oracle对于只读事务的定义:

引用:
Read-Only Transactions
By default, Oracle guarantees statement-level read consistency. The set of data returned by a single query is consistent with respect to a single point in time. However, in some situations, you might also require transaction-level read consistency. This is the ability to run multiple queries within a single transaction, all of which are read-consistent with respect to the same point in time, so that queries in this transaction do not see the effects of intervening committed transactions.

If you want to run a number of queries against multiple tables and if you are not doing any updating, you prefer a read-only transaction. After indicating that your transaction is read-only, you can run as many queries as you like against any table, knowing that the results of each query are consistent with respect to the same point in time.


Oracle默认情况下保证了SQL语句U别的读一致性,卛_该条SQL语句执行期间Q它只会看到执行前点的数据状态,而不会看到执行期间数据被其他SQL改变的状态?

而Oracle的只L?read-only transaction)则保证了事务U别的读一致性,卛_该事务范围内执行的多条SQL都只会看到执行前点的数据状态,而不会看C务期间的M被其他SQL改变的状态?

因此我们可以得出l论Q?

如果你一ơ执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性;
如果你一ơ执行多条查询语句,例如l计查询Q报表查询,在这U场景下Q多条查询SQL必须保证整体的读一致性,否则Q在前条SQL查询之后Q后条SQL查询之前Q数据被其他用户改变Q则该次整体的统计查询将会出现读数据不一致的状态,此时Q应该启用事务支持?


只读事务与读写事务区?

对于只读查询Q可以指定事务类型ؓreadonlyQ即只读事务。由于只M务不存在数据的修改,因此数据库将会ؓ只读事务提供一些优化手D,例如Oracle对于只读事务Q不启动回滚D,不记录回滚log?

在JDBC中,指定只读事务的办法ؓQ?
connection.setReadOnly(true);

在Hibernate中,指定只读事务的办法ؓQ?
session.setFlushMode(FlushMode.NEVER);
此时QHibernate也会为只M务提供Session斚w的一些优化手D?

在Spring的Hibernate装中,指定只读事务的办法ؓQ?
bean配置文g中,prop属性增加“readOnly?/FONT>

 

我在MySQL4.1试验了一下,q程和结果如下:

数据库:MySQL4.1
表类型:InnoDB
SpringQ?.1.2
HibernateQ?.1.7

使用Spring的声明式事务理

试验q程如下Q?

不设|查询方法的事务cd(即不需要事?Q访问查询页面,后台执行Spring的BeanҎQ让Hibernate发送select语句Q然后手工在MySQL里面修改该记录某字段|再访问查询页面,发现被修改过的字D值ƈ没有变化QHibernate输出的log昄Q数据库q是把老的字段D回,而没有返回新的字D倹{?

讄查询Ҏ的事务类?只读事务)Q访问查询页面,后台执行Spring的BeanҎQ让Hibernate发送select语句Q然后手工在MySQL里面修改该记录某字段|再访问查询页面,发现被修改过的字D值已l变化,Hibernate输出的log昄Q数据库q回新的字段倹{?

q个试验说明Q至在MySQL4.1的InnoDB情况下,不用只M务的查询无法读取到数据更新|必须使用只读事务来保证读记录的数据一致性。这个结果非o我诧异,和我预期完全两样?

我将在Oracleq_上试试看会有什么样的结果?

BTW: 如果MySQL的表cd改ؓMyISAMQ那么即使不讄事务Q也不会出现L据不一致的现象?/FONT>


oracle有两U方法保证在事务U读数据一致?Transaction-Level Read Consistency)

一是用SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ,
当执行这条命令后L据时会生一些重复copy, 你也可以做数据修? 但在大量数据修改的情况下Ҏ造成deadlock或异? 用commit或rollback把ISOLATION LEVEL讑֛为缺省模式read committed,


二是用SET TRANSCATION READ ONLY
当执行这条命令时数据库会生成一个快照的latch, q个latch会耗费一些resource, 如果你想q行数据修改会导致异? 用commit或rollback会把latch释放? 也将把ISOLATION LEVEL讑֛为缺省模式read committed,



Terry的Blog 2005-12-06 22:25 发表评论
]]>
Oracle SQL依然无可替代--《Mastering Oracle SQL?转蝲)http://m.tkk7.com/terry-zj/archive/2005/12/06/22786.htmlTerry的BlogTerry的BlogTue, 06 Dec 2005 14:04:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/06/22786.htmlhttp://m.tkk7.com/terry-zj/comments/22786.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/06/22786.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/22786.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/22786.html转蝲 Oracle SQL依然无可替代--《Mastering Oracle SQL?/FONT>

选择?calvinxiu ?Blog  http://dev.csdn.net/user/calvinxiu

天寒地冻Q呆在家里又d了《Mastering Oracle SQL?ndQ发现Oracle的功能还是很强悍Q光函数有两百个,HSQL是很难比拟的。接下来的硬骨头Q看来要么冒险用Hibernate3.0 的SQL Mapping功能Q要么就自己跑JDBCl装VO了?

       1.报表合计专用的Rollup函数
         销售报?BR>  q州     1?nbsp;     2000?BR>  q州     2?nbsp;     2500?BR>  q州                 4500?BR>  深圳     1?nbsp;     1000?BR>  深圳     2?nbsp;     2000?BR>  深圳                 3000?BR>  所有地?nbsp;        7500?BR>

以往的查询SQL:
Select  area,month,sum(money) from SaleOrder group by area,month
然后q州Q深圳的合计和所有地区合计都需要在E序里自行篏?/FONT>

1.其实可以使用如下SQL:   Select area,month,sum(total_sale) from SaleOrder group by rollup(area,month)p产生和报表一模一LU录
 
2.如果year不想累加Q可以写?nbsp;  Select year,month,area,sum(total_sale) from SaleOrder group by year, rollup(month,area)   另外Oracle 9iq支持如下语?   Select year,month,area,sum(total_sale) from SaleOrder group by rollup((year,month),area)
 
3.如果使用Cube(area,month)而不是RollUp(area,month)Q除了获得每个地区的合计之外Q还获得每个月份的合计Q在报表最后显C?/FONT>
 
4.Grouping让合计列更好?BR>  RollUp在显C广州合计时Q月份列为NULLQ但更好的做法应该是昄?所有月?
  Grouping是用来判断当前Column是否是一个合计列Q?为yesQ然后用Decode把它转ؓ"所有月?  Select  Decode(Grouping(area),1,'所有地?,area) area,
          Decode(Grouping(month),1,'所有月?,month),
          sum(money)
  From SaleOrder 
  Group by RollUp(area,month);
 
2.对多U层ơ查询的start with.....connect by
   比如人员l织,产品cd,Oracle提供了很l典的方?/FONT>
SELECT LEVEL, name, emp_id,manager_emp_id
FROM employee
START WITH manager_emp_id is null
CONNECT BY PRIOR emp_id = manager_emp_id;
上面的语句demo了全部的应用,start with指明从哪里开始遍历树,如果从根开?那么它的manager应该是Null,如果从某个职员开?可以写成emp_id='11'
CONNECT BY 是指明父子关系,注意PRIOR位置
另外q有一个LEVEL?昄节点的层?/FONT>
 
3.更多报表/分析决策功能
3.1 分析功能的基本结?BR>     分析功能() over( partion子句,order by子句,H口子句)
     概念上很难讲清楚,q是用例子说话比较好.       
 
3.2 Row_Number ?Rank, DENSE_Rank
    用于选出Top 3 salesq样的报?BR>    当两个业务员可能有相同业l时,p使用Rank和Dense_Rank
    比如
              金额    RowNum  Rank  Dense_Rank
    张三 4000?nbsp;   1             1        1
    李四 3000?nbsp;   2             2        2
    ׃ 2000?nbsp;   3             3        3
    孙六 2000?nbsp;   4             3        3
    丁七 1000?nbsp;   5             5        4
    q时,应该把ƈ列第三的׃和孙六都选进?所以用Ranking功能比RowNumber保险.至于Desnseq是Rankingq具体情况了?/FONT>
    SELECT salesperson_id, SUM(tot_sales) sp_sales,
    RANK( ) OVER (ORDER BY SUM(tot_sales) DESC) sales_rank
    FROM orders
    GROUP BY salesperson_id
3.3 NTILE 把纪录^分成甲乙丙丁四等
        比如我想取得?5%的纪?或者把25%的纪录当作同一个levelq等对待,把另25%当作另一个Levelq等对待
    SELECT cust_nbr, SUM(tot_sales) cust_sales,
    NTILE(4) OVER (ORDER BY SUM(tot_sales) DESC) sales_quartile
    FROM orders
    GROUP BY cust_nbr
    ORDER BY 3,2 DESC;NTITLE(4)把纪录以 SUM(tot_sales)排序分成4?
 
3.4 辅助分析列和Windows Function
     报表除了基本事实数据?d望旁边多些全q总销?到目前ؓ止的累计销?前后三个月的q_销量这L列来参?
    q种前后三个月的q_和到目前为止的篏计销量就叫windows function, 见下?nbsp;   SELECT month, SUM(tot_sales) monthly_sales,
           SUM(SUM(tot_sales)) OVER (ORDER BY month
           ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) max_preceeding
    FROM orders
    GROUP BY month
    ORDER BY month;



    SELECT month, SUM(tot_sales) monthly_sales,
           AVG(SUM(tot_sales)) OVER (ORDER BY month
           ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) rolling_avg  
    FROM orders
    GROUP BY month
    ORDER BY month;
    Windows Function的关键就是Windows子句的几个取?BR>    1 PRECEDING 之前的一条记?BR>    1 FOLLOWING 之后的一条记?BR>    UNBOUNDED PRECEDING 之前的所有记?BR>    CURRENT ROW 当前U录
 
4.SubQueryȝ
  SubQuery天天用了,理论上ȝ一?SubQuery 分三U?BR>  1.Noncorrelated 子查?nbsp;  最普通的样式.
  2.Correlated Subqueries  把父查询的列拉到子查询里面去,头一回cyt教我的时候理解了半天.
  3.Inline View                           也被当成最普通的样式用了.
 
  然后Noncorrelated 子查询又有三U情?BR>  1.q回一行一?nbsp;   where price < (select max(price) from goods )
  2.q回多行一?nbsp;   where price>= ALL (select price from goods where type=2)
                          or where NOT price< ANY(select price from goods where type=2)
                              最常用的IN其实是=ANY()
  3.q回多行多列    一ơ返回多列当然就节省了查询时?          UPDATE monthly_orders 
          SET (tot_orders, max_order_amt) =
             (SELECT COUNT(*), MAX(sale_price)
          FROM cust_order)

         
DELETE FROM line_item
          WHERE (order_nbr, part_nbr) IN
           (SELECT order_nbr, part_nbr FROM cust_order c)


Terry的Blog 2005-12-06 22:04 发表评论
]]>
关于数据库名(db_name)、实例名(instance_name)、ORACLE_SID (转蝲)http://m.tkk7.com/terry-zj/archive/2005/12/06/22784.htmlTerry的BlogTerry的BlogTue, 06 Dec 2005 13:57:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/06/22784.htmlhttp://m.tkk7.com/terry-zj/comments/22784.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/06/22784.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/22784.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/22784.html数据库名(DB_NAME)、实例名(Instance_name)、以及操作系l环境变?ORACLE_SID)

在ORACLE7?数据库中只有数据库名(db_name)和数据库实例?instance_name)。在ORACLE8i?i中出C新的参数Q即数据库域?db_domain)、服务名(service_name)、以及操作系l环境变?ORACLE_SID)。这些都存在于同一个数据库中的标识Q用于区分不同数据库的参数?

一、什么是数据库名(db_name)? 数据库名是用于区分数据的内部标识Q是以二q制方式存储于数据库控制文g中的参数Q在数据安装或创Z后将不得修改。数据库安装完成后,该参数被写入数据库参数文件pfile中,格式如下Q?

db_name="orcl"
db_domain=dbcenter.toys.com
instance_name=orcl
service_names=orcl.dbcenter.toys.com
control_file=...............

在每一个运行的ORACLE8i数据库中都有一个数据库?db_name),如果一个服务器E序中创Z两个数据库,则有两个数据库名。其控制参数据分属在不同的pfile中控制着相关的数据库?

二、什么是数据库实例名(instance_name) 数据库实例名则用于和操作pȝ之间的联p,用于对外部连接时使用。在操作pȝ中要取得与数据库之间的交互,必须使用数据库实例名。例如,要和某一个数据库serverq接Q就必须知道其数据库实例名,只知道数据库名是没有用的Q与数据库名不同Q在数据安装或创建数据库之后Q实例名可以被修攏V数据库安装完成后,该实例名被写入数据库参数文gpfile中,格式如下Q?
db_name="orcl" #(不允怿?
db_domain=dbcenter.toys.com
instance_name=orcl #(可以修改,可以与db_name相同也可不同)
service_names=orcl.dbcenter.toys.com
control_file=...............
数据库名与实例名之间的关pR?数据库名与实例名之间的关pM般是一一对应关系Q有一个数据库名就有一个实例名Q如果在一个服务器中创Z个数据库Q则有两个数据库名,两个数据库实例名Q用两个标识定一个数据库Q用户和实例相连接?但在8i?i的ƈ行服务器l构中,数据库与实例之间不存在一一对应关系Q而是一对多关系Q?一个数据库对应多个实例Q同一旉内用户只一个实例相联系Q当某一实例出现故障Q其它实例自动服务,以保证数据库安全q行?

三、操作系l环境变?ORACLE_SID) 在实际中Q对于数据库实例名的描述有时使用实例?instance_name)参数Q有时用ORACLE_SID参数。这两个都是数据库实例名Q它们有什么区别呢Q?l常弄؜)

(ORACLE_SID) OS<----------------> ORACLE 数据?<--------(Instance_name(实例?)

上图表示实例名instance_name、ORACLE_SID与数据库及操作系l之间的关系Q虽然这里列出的两个参数都是数据库实例名Q但instance_name参数是ORACLE数据库的参数Q此参数可以在参数文件中查询刎ͼ而ORACLE_SID参数则是操作pȝ环境变量?操作pȝ环境变量ORACLE_SID用于和操作系l交互。也是_在操作系l中要想得到实例名,必M用ORACLE_SID。此参数与ORACLE_BASE、ORACLE_HOME{用法相同。在数据库安装之后,ORACLE_SID被用于定义数据库参数文g的名U。如Q?$ORACLE_BASE/admin/DB_NAME/pfile/init$ORACLE_SID.ora?定义Ҏ:  export ORACLE_SID=orcl

如果在同一服务器中创徏了多个数据库Q则必然同时存在多个数据库实?q时可以重复上述定义q程Q以选择不同实例?

q可以用 [oracle@Datacent]$ . oraenv 来切换不同的ORACLE_SID来通过操作pȝ来启动不同的实例(instance)



Terry的Blog 2005-12-06 21:57 发表评论
]]>
Tomcat 5.5 配置(转蝲)http://m.tkk7.com/terry-zj/archive/2005/12/06/22646.htmlTerry的BlogTerry的BlogMon, 05 Dec 2005 16:13:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/06/22646.htmlhttp://m.tkk7.com/terry-zj/comments/22646.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/06/22646.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/22646.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/22646.htmlTomcat 5.5 配置

 

1.?/SPAN>?/SPAN>Q?/SPAN>

Release Notes: http://tomcat.apache.org/tomcat-5.5-doc/RELEASE-NOTES
Change Log: http://tomcat.apache.org/tomcat-5.5-doc/changelog.html
Downloads: http://tomcat.apache.org/download-55.cgi

?/SPAN>jakarta-tomcat-5.5.x.zip

?/SPAN>jakarta-tomcat-5.5.x-compat.zip

?/SPAN>jakarta-tomcat-5.5.x-admin.zip
(Tomcat
?/SPAN>?/SPAN>是没有内|?/SPAN>admin?/SPAN>?/SPAN>?/SPAN>

Tomcat's administration web application is no longer installed by default. Download and install the "admin" package to use it. )

都解?/SPAN>到同一个目?/SPAN>下面。比如:D:\jakarta-tomcat-5.5.x\

(如果使用jdk1.4Q才需?/SPAN>compat.zip?/SPAN>jdk1.5可以免?/SPAN>q?/SPAN>个?/SPAN>)

 

2.修改jakarta-tomcat-5.5.x\conf\tomcat-users.xml.
d理员̎?/SPAN>lizongboQ密码ؓlizongbopass.
?/SPAN>xml如下Q?/SPAN>
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <role rolename="manager"/>
  <role rolename="admin"/>
  <user username="tomcat" password="tomcat" roles="tomcat"/>
  <user username="role1" password="tomcat" roles="role1"/>
  <user username="both" password="tomcat" roles="tomcat,role1"/>
  <user username="lizongbo" password="lizongbopass" roles="admin,manager"/>
</tomcat-users>

 

3.修改jakarta-tomcat-5.5.x\conf\server.xml来解?/SPAN>~码问题?SPAN lang=EN-US>

(l?/SPAN>Connector dURIEncoding参数
参?/SPAN>
http://blog.csdn.net/darkxie/archive/2004/10/25/TOMCATAPP.aspx)

(可以?/SPAN>|成GB18030)
    <Connector port="8080"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="200"
               connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="GBK"
               compression="on" compressionMinSize="2048"
      noCompressionUserAgents="gozilla, traviata"
      compressableMimeType="text/html,text/xml"/>

 

    <Connector port="8009"
               enableLookups="false" redirectPort="8443" protocol="AJP/1.3" URIEncoding="GBK"/>

 

4.启用支持gzip压羃.
(
http://www.linuxaid.com.cn/forum/showdoc.jsp?l=1&i=81169)
d下列属?/SPAN>
 compression="on"
      compressionMinSize="2048"
      noCompressionUserAgents="gozilla, traviata"
      compressableMimeType="text/html,text/xml"

 

5.?/SPAN>|虚?/SPAN>L?/SPAN>

?/SPAN>jakarta-tomcat-5.5.x\下徏立文?/SPAN>?/SPAN>vhost\www.mydomain.com?/SPAN>

然后修改jakarta-tomcat-5.5.x\conf\server.xml

 

<Engine defaultHost="localhost" name="Catalina">
      <Host appBase="vhost/www.mydomain.com" name="
www.mydomain.com">
      </Host>
      <Host appBase="webapps" name="localhost">
      </Host>
      <Realm className="org.apache.catalina.realm.UserDatabaseRealm"/>
    </Engine>

 

6.d数据库驱?/SPAN>,更新mail.jar?/SPAN>actiovation.jar

?/SPAN>?/SPAN>mysql-connector-java-3.0.16-ga-bin.jar,pg74.215.jdbc3.jar?/SPAN> jakarta-tomcat-5.5.x\common\lib\

q?/SPAN>?/SPAN>javamail 1.3.2?/SPAN>mail.jarQ?/SPAN>jaf-1_0_2?/SPAN> activation.jar

msSQl 2000 JDBC sp3Q?/SPAN>msbase.jar,msutil,jar,mssqlserver.jar

 

 

7.配置SSL

参?/SPAN> http://jakarta.apache.org/tomcat/tomcat-5.5-doc/ssl-howto.html

D:\j2sdk1.4.2_06\bin>%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA
?/SPAN>?/SPAN>keystore?/SPAN>?/SPAN>Q?/SPAN>  lizongbossl
您的名字与姓氏是什?/SPAN>Q?/SPAN>
 
[tomcat5.5.x]Q?/SPAN>  tomcat5.5.x
您的l织?/SPAN>位名U是什?/SPAN>Q?/SPAN>
 
[jakarta]Q?/SPAN>  jakarta
您的l织名称是什?/SPAN>Q?/SPAN>
  [apache]
Q?/SPAN>  apache
您所在的城市或区域名U是什?/SPAN>Q?/SPAN>
  [hzcity]
Q?/SPAN>  hzcity
您所在的州或省䆾名称是什?/SPAN>Q?/SPAN>
  [gdp]
Q?/SPAN>  gdp
该单位的两字母国家代?/SPAN>是什?/SPAN>
  [CN]
Q?/SPAN>  CN
CN=tomcat5.5.x, OU=jakarta, O=apache, L=hzcity, ST=gdp, C=CN
正确?/SPAN>Q?/SPAN>
 
[?/SPAN>]Q?/SPAN>  y

 

?/SPAN>?/SPAN><tomcat>的主?/SPAN>?/SPAN>
       
Q如果和 keystore ?/SPAN>?/SPAN>相同Q按?/SPAN>?/SPAN>Q:

(?/SPAN>?/SPAN>?/SPAN>?/SPAN>一_因此直接?/SPAN>?/SPAN>)

然后再把userhome(例如Q?/SPAN>C:\Documents and Settings\lizongbo\)下的.keystore?/SPAN>制到

tomcat?/SPAN>conf\?/SPAN>?/SPAN>下?/SPAN>

 (例如Q?/SPAN>D:\jakarta-tomcat-5.5.x\conf\.keystore )

配置jakarta-tomcat-5.5.x\conf\server.xml

加上

    <Connector port="8443"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
           keystoreFile="conf/.keystore"
           keystorePass="lizongbossl"> <!--
与先?/SPAN>?/SPAN>|的?/SPAN>?/SPAN>一?/SPAN>-->
    </Connector>

8.止文g?/SPAN>?/SPAN>列表Q?/SPAN>

修改jakarta-tomcat-5.5.x\conf\web.xmlQ把listing?/SPAN>|?/SPAN>?/SPAN>false

 

    <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

 

 9.指定了自qjavaEncoding

(参?/SPAN> http://gceclub.sun.com.cn/staticcontent/html/sunone/app7/app7-dg-webapp/ch6/ch6-4.html )


    <servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <init-param>
            <param-name>fork</param-name>
            <param-value>false</param-value>
        </init-param>
                <init-param>
            <param-name>javaEncoding</param-name>
            <param-value>GB18030</param-value>
        </init-param>
        <init-param>
            <param-name>xpoweredBy</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>3</load-on-startup>
    </servlet>

 10.drar,iso{的mime-type映射

避免?/SPAN>器里直接?/SPAN>?/SPAN>

<mime-mapping>
<extension>mht</extension>
<mime-type>text/x-mht</mime-type>
</mime-mapping>

<mime-mapping>
        <extension>rar</extension>
        <mime-type>application/octet-stream</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>iso</extension>
        <mime-type>application/octet-stream</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>ape</extension>
        <mime-type>application/octet-stream</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>rmvb</extension>
        <mime-type>application/octet-stream</mime-type>
    </mime-mapping>

    <mime-mapping>
        <extension>ico</extension>
        <mime-type>image/x-icon</mime-type>
    </mime-mapping>

10.1对html静态页面设|编?BR>    <!--  修改下面两行以支持静态超文本的自动编?-->
    <mime-mapping>
    <extension>htm</extension>
    <mime-type>text/html;charset=gb2312</mime-type>
    </mime-mapping>
    <mime-mapping>
    <extension>html</extension>
    <mime-type>text/html;charset=gb2312</mime-type>
    </mime-mapping>
  </web-app>

 

11.dwelcome-file-list?/SPAN>?/SPAN>?/SPAN>序?/SPAN>

 <welcome-file-list>   
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>

 



Terry的Blog 2005-12-06 00:13 发表评论
]]>
字符串中的正则表辑ּҎW号(转蝲)http://m.tkk7.com/terry-zj/archive/2005/12/05/22509.htmlTerry的BlogTerry的BlogMon, 05 Dec 2005 02:31:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/05/22509.htmlhttp://m.tkk7.com/terry-zj/comments/22509.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/05/22509.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/22509.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/22509.html字符串中的正则表辑ּҎW号

问题Q?br>String s1="111+222+333";
System.out.println(s1.split("+").length);
//输出时提C错误:
java.util.regex.PatternSyntaxException: Dangling meta character '+' near index
问题出现在加号附q,查询相关的资料显C,+?、|、\{符号在正则表达CZ有相应的不同意义?br>
正则表达式的基本用法 zt     
1、?”ؓ通配W,表示M一个字W,例如Q“a.c”可以匹配“anc”、“abc”、“acc”;
2、“[]”,在[]内可以指定要求匹配的字符Q例如:“a[nbc]c”可以匹配“anc”、“abc”、“accQ?br>但不可以匚w“ancc?a到z可以写成[a-z],0?可以写成[0-9];

3、数量限定符P表示匚wơ数Q或者叫做长度)的符P

包括Q?”—?ơ或者多?br>      ?”—?ơ或者多?br>      ?”—?ơ或??br>      “{n}”——匹配nơ,n为整?br>      “{n,m}”——匹配从n到m之间的某个数的次敎ͼn和m都是整数Q?br>      “{n,}”——匹配n到无Ih之间Lơ数Q?br>      “{,m}”——匹?到m之间Lơ数Q?br>他们攑ֈ匚w格式的后面:
例如Q?br>电话LQ?24Q?4820482Q?2484820482(假设前面3或?位,后面7或?位,q且中间的减号可有可?

都是W合规定的,那么可以用如下格式来匚wQ[0-9]{3,4} \-? [0-9]{7,8}Q?br>注意Q“\”ؓ转义字符Q因为?”在正则表达式用有代表一个范围的意义Q例如:前面所说的[0-9]Q?br>所以它需要{义字W“\”进行{义才可用;

4、“^”ؓ否符P表示不想匚w的符P例如Q[^z][a-z]+可以匚w所有除“z”开头的以外的所有字

W串Q长度大?Q因为?”表C大于等?的次敎ͼ从第二位开始都是小写英文字W)Q?br>如果^攑ֈ[]的外边则表示以[]开头的字符Ԍ^[az][a-z]+表示a或者z开头的长度大于{于2的英文字W串Q?br>
5、“|”或q算W,例如Qa[n|bc|cb]c可以匚w“abcc?“anc?“acbc”;
6、?”以它前面的字符l尾的;例如Qab+$可以被“abb”,“ab”匹配;

7、一些简单表C方法:
\d表示[0-9];\D表示[^0-9];\w表示[A-Z0-9];\W表示[^A-Z0-9];\s表示[\t\n\r\f],是I格字符包括tabQ空格等{?\S表示[^\t\n\r\f]Q就是非I格字符;


明白了这些以后,我们再返回头看看它们如何被运用呢Q一般来讲只需要加[]、或是\\卛_?br>
举例来讲Q?br>String s1="111+222+333";
System.out.println(s1.split("[+]").length);
或是
String s1="111+222+333";
System.out.println(s1.split("\\+").length);

其他用法cd?/font>

Terry的Blog 2005-12-05 10:31 发表评论
]]>
Calendar使用ҎQ{载)http://m.tkk7.com/terry-zj/archive/2005/12/05/22506.htmlTerry的BlogTerry的BlogMon, 05 Dec 2005 02:15:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/05/22506.htmlhttp://m.tkk7.com/terry-zj/comments/22506.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/05/22506.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/22506.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/22506.html明v文集之日期旉1.0

--------它不是原创,是一U思念

Java 语言的CalendarQGregorianCalendar (日历),Date(日期), 和DateFormat(日期格式)l成了Java标准的一个基本但是非帔R要的部分. 日期是商业逻辑计算一个关键的部分. 所有的开发者都应该能够计算未来的日? 定制日期的显C格? q将文本数据解析成日期对象。学习日? 日期格式, 日期的解析和日期的计?

我们讨Z面的c?

1?nbsp; 具体c?和抽象类相对)java.util.Date

2?nbsp; 抽象cjava.text.DateFormat 和它的一个具体子c?java.text.SimpleDateFormat

3?nbsp; 抽象cjava.util.Calendar 和它的一个具体子c?java.util.GregorianCalendar

具体cd以被实例? 但是抽象cd不能. 你首先必d现抽象类的一个具体子c?

1.   java.util.Date及其格式?br>Date cMJava 开发包(JDK) 1.0 开始进? 当时它只包含了几个取得或者设|一个日期数据的各个部分的方? 比如说月, ? 和年. q些Ҏ现在遭到了批评ƈ且已l被转移CCalendarc里M, 我们在本文中进一步讨论它. q种改进旨在更好的处理日期数据的国际化格? p在JDK 1.1中一? Date cd际上只是一个包裹类, 它包含的是一个长整型数据, 表示的是从GMT(格林治标准旉)1970q? 1 ?1?0:00:00q一M前或者是之后l历的毫U数.

1.1. 创徏java.util.Date
Javal计?970q??日v的毫U的数量表示日期。也是_例如Q?970q??日,是在1?日后?6Q?00Q?00毫秒。同LQ?969q?2?1日是?970q??日前86Q?00Q?00毫秒。Java的DatecM用longcdU录q些毫秒?因ؓlong是有W号整数Q所以日期可以在1970q??日之前,也可以在q之后。Longcd表示的最大正值和最大负值可以轻杄表示290Q?00Q?00q的旉Q这适合大多Ch的时间要求?br>
让我们看一个用系l的当前日期和时间创Z个日期对象ƈq回一个长整数的简单例? q个旉通常被称为Java 虚拟?JVM)L环境的系l时?
import java.util.Date;

public class DateExample1 {

public static void main(String[] args) {

// Get the system date/time

Date date = new Date();

// 打印出具体的q_月,日,时Q分钟,U钟以及时区

System.out.println(date.getTime());

}  

}

在星期六, 2001q??9? 下午大约?:50的样? 上面的例子在pȝ输出讑֤上显C的l果?1001803809710. 在这个例子中,值得注意的是我们使用了Date 构造函数创Z个日期对? q个构造函数没有接受Q何参? 而这个构造函数在内部使用了System.currentTimeMillis() Ҏ来从pȝ获取日期.

//1q前日期

   java.util.Date myDate=new java.util.Date(); 

   long myTime=(myDate.getTime()/1000)-60*60*24*365;

   myDate.setTime(myTime*1000);

   String mDate=formatter.format(myDate);

//明天日期

   myDate=new java.util.Date();

   myTime=(myDate.getTime()/1000)+60*60*24;

   myDate.setTime(myTime*1000);

   mDate=formatter.format(myDate);

//两个旉之间的天?br>
   SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");

   java.util.Date date= myFormatter.parse("2003-05-1");

   java.util.Date mydate= myFormatter.parse("1899-12-30");

   long  day=(date.getTime()-mydate.getTime())/(24*60*60*1000);

//加半时

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

java.util.Date date1 = format.parse("2002-02-28 23:16:00");

long Time=(date1.getTime()/1000)+60*30;

date1.setTime(Time*1000);

String mydate1=formatter.format(date1);

//q月周求日期

SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM F E");

java.util.Date date2= formatter2.parse("2003-05 5 星期?);

SimpleDateFormat formatter3 = new SimpleDateFormat("yyyy-MM-dd");

String mydate2=formatter3.format(date2);

//求是星期?br>
mydate= myFormatter.parse("2001-1-1");

SimpleDateFormat formatter4 = new SimpleDateFormat("E");

String mydate3=formatter4.format(mydate);

 
 

 

1.2. Date格式?br>能以一U用h白的格式来显C个日期呢? 在这里类java.text.SimpleDateFormat 和它的抽象基c?java.text.DateFormat。那? 现在我们已经知道了如何获取从1970q??日开始经历的毫秒C. 我们如何才format 派得上用场?

// 我们能不能用下面的代码构件出 2001/8/8 8:8
    import java.io.*;
    import java.util.*;
 
    public class WhatIsDate
    {
        public static void main(String[] args) {
            Date date = new Date(2001, 8, 8, 8, 8, 8);
            System.out.println(date);
        }
    }
 

Java 的编译器竟然报如下信?(Sun JDK1.3, Windows 2000 中文?

注意Q?br>WhatIsDate.java 使用或覆盖一个不鼓励使用的API?br>注意Q?br>使用-deprecation重新~译Q以得到详细信息。!
 

那么 Date 对象I竟是ؓ了满_个需求呢Q看来它不是用来实现Zq??日小?分钟 的时间表q。我们查?Java 的文档,我们看到?getTime() ҎQ它q回的竟然是一?long 倹{?br>
文档q一步又告诉我们q个g表了当前pȝ的时间离1970/1/1 0:0 的毫U差Q而且是在 GMT 时区?也被UCؓ EPOC)。如果我们指定的旉是在此之前的Q那它将q回一个负数倹{?br>
q个发现让我们对 Date 对象有了一个全新的认识-Date 存放的是?EPOC 的偏差倹{换而言之我们也可通过 long cd来表C时_对了Q这个猜x得到?Java 的支持:

   // W二U获得当前时间的Ҏ
    long dateInMilliSeconds = System.currentTimeMillis();
    // q时候打印出的只是一串数字而已
    System.out.println(dateInMilliSeconds);
 

对程序执行效率敏感的E序员可以发现这个方法只是生成一?Java 的原始类?(primitive type) long, 不需要实例化一个对象。因此如果我们对旉的处理只是在内部q行Ӟ可以?long 来代?Date 对象?br>
最典型的应用就是在一D代码开始和l束?分别获得pȝ当前的时?然后计算Z码执行所需的时?微秒U??br>
   long start = System.currentTimeMillis();
    // 代码D?br>    System.out.println("需?"+(System.currentTimeMillis()-start)+" 微秒");
 

那么当我们要把这?long 值已更ؓ友好的表现Ş式显C处理的时候,我们可以用它来构?Date 对象Q?br>
Date date = new Date(dateInMilliSeconds);

System.out.println(date);
 

我们看到了在 Java 中对旉最为基本的表示Q有通过对EPOC 的偏差D行处理。Date 对象是对它的一个对象的装。我们同时也看到了,在现时世界中我们Ҏ间的描述通常是通过"某年某月某日某时某分"来定义的。Date 的显C?实际上是 toString() Ҏ)描述了这些信息,?Java q不我们用这U方式直接来构g Date 对象。因此我们需要找出哪个对象可以实现这个需求。这是我们下面p讲述?Calendar 对象的功能?br>
在我们进一步研I?Calendar 之前Q请C Date 只是一个对 long ?Z GMT 时区)的对象封装。它所表现出来的年/?日小?分钟时区的时间表qͼ只是它的 toString() Ҏ所提供的。千万不要ؓq个假象所qh?br>
假如我们希望定制日期数据的格? 比方星期?9?29?2001q? 下面的例子展CZ如何完成q个工作:

import java.text.SimpleDateFormat;

import java.util.Date;

public class DateExample2 {

public static void main(String[] args) {

SimpleDateFormat bartDateFormat = new SimpleDateFormat("EEEE-MMMM-dd-yyyy"); Date date = new Date();

System.out.println(bartDateFormat.format(date));

}

}
 

只要通过向SimpleDateFormat 的构造函C递格式字W串"EEE-MMMM-dd-yyyy", 我们p够指明自己想要的格式. 你应该可以看? 格式字符串中的ASCII 字符告诉格式化函C面显C日期数据的哪一个部? EEEE是星? MMMM是月, dd是日, yyyy是年. 字符的个数决定了日期是如何格式化?传?EE-MM-dd-yy"会显C?Sat-09-29-01. 请察看Sun 公司的Web 站点获取日期格式化选项的完整的指示.

1.3. 文本数据解析成日期对?
假设我们有一个文本字W串包含了一个格式化了的日期对象, 而我们希望解析这个字W串q从文本日期数据创徏一个日期对? 我们再ơ以格式化字W串"MM-dd-yyyy" 调用SimpleDateFormatc? 但是q一? 我们使用格式化解析而不是生成一个文本日期数? 我们的例? 昄在下? 解析文本字W串"9-29-2001"q创Z个gؓ001736000000 的日期对?

通过parse()ҎQDateFormat能够以一个字W串创立一个Date对象。这个方法能抛出ParseException异常Q所以你必须使用适当的异常处理技术?br>
例子E序:

import java.text.SimpleDateFormat;

import java.util.Date;

public class DateExample3 {

public static void main(String[] args) {

// Create a date formatter that can parse dates of

// the form MM-dd-yyyy.

SimpleDateFormat bartDateFormat = new SimpleDateFormat("MM-dd-yyyy");

// Create a string containing a text date to be parsed.

String dateStringToParse = "9-29-2001";

try {

// Parse the text version of the date.

// We have to perform the parse method in a

// try-catch construct in case dateStringToParse

// does not contain a date in the format we are expecting.

Date date = bartDateFormat.parse(dateStringToParse);

// Now send the parsed date as a long value

// to the system output.

System.out.println(date.getTime());

}catch (Exception ex) {

System.out.println(ex.getMessage());

}

}

}
 

1.4. 使用标准的日期格式化q程
既然我们已经可以生成和解析定制的日期格式? 让我们来看一看如何用内建的格式化过E? Ҏ DateFormat.getDateTimeInstance() 让我们得以用几种不同的方法获得标准的日期格式化过E? 在下面的例子? 我们获取了四个内建的日期格式化过E? 它们包括一个短? 中等? 长的, 和完整的日期格式.

import java.text.DateFormat;

import java.util.Date;

public class DateExample4 {

public static void main(String[] args) {

Date date = new Date();

DateFormat shortDateFormat = DateFormat.getDateTimeInstance(

DateFormat.SHORT, DateFormat.SHORT);

DateFormat mediumDateFormat = DateFormat.getDateTimeInstance(

DateFormat.MEDIUM, DateFormat.MEDIUM);

DateFormat longDateFormat = DateFormat.getDateTimeInstance(

DateFormat.LONG, DateFormat.LONG);

DateFormat fullDateFormat = DateFormat.getDateTimeInstance(

DateFormat.FULL, DateFormat.FULL);

System.out.println(shortDateFormat.format(date)); System.out.println(mediumDateFormat.format(date)); System.out.println(longDateFormat.format(date)); System.out.println(fullDateFormat.format(date));

}

}

注意我们在对 getDateTimeInstance的每ơ调用中都传递了两个? W一个参数是日期风格, 而第二个参数是时间风? 它们都是基本数据cdint(整型). 考虑到可L? 我们使用了DateFormat cL供的帔R: SHORT, MEDIUM, LONG, ?FULL. 要知道获取时间和日期格式化过E的更多的方法和选项, LSun 公司Web 站点上的解释.

q行我们的例子程序的时? 它将向标准输备输Z面的内容:
9/29/01 8:44 PM
Sep 29, 2001 8:44:45 PM
September 29, 2001 8:44:45 PM EDT
Saturday, September 29, 2001 8:44:45 PM EDT

2.   Calendar 日历c?
首先误?Calendar 只是一个抽象类, 也就是说你无法直接获得它的一个实例,换而言之你可以提供一个自己开发的 Calendar 对象?br>
那究竟什么是一?Calendar 呢?中文的翻译就是日历,那我们立d以想到我们生zM有阳(?历、阴(?历之分。它们的区别在哪呢?

比如有:

月䆾的定?- 阳`(??一q?2 个月Q每个月的天数各不同Q阴(?历,每个月固?8?每周的第一?- ??历星期日是第一天;??历,星期一是第一?br>
实际上,在历史上有着许多U纪元的Ҏ。它们的差异实在太大了,比如说一个h的生日是"八月八日" 那么一U可能是??历的八月八日Q但也可以是??历的日期。所以ؓ了计时的l一Q必需指定一个日历的选择。那现在最为普及和通用的日历就?"Gregorian Calendar"。也是我们在讲q年份时常用 "公元几几q?。Calendar 抽象cd义了_的方法,让我们能够表q日历的规则。Java 本n提供了对 "Gregorian Calendar" 规则的实现。我们从 Calendar.getInstance() 中所获得的实例就是一?"GreogrianCalendar" 对象(与您通过 new GregorianCalendar() 获得的结果一??br>
下面的代码可以证明这一点:

   import java.io.*;
    import java.util.*;
 
    public class WhatIsCalendar
    {
        public static void main(String[] args) {
            Calendar calendar = Calendar.getInstance();
            if (calendar instanceof GregorianCalendar)
                System.out.println("It is an instance of GregorianCalendar");
        }
    }
 

 

Calendar ?Java 中是一个抽象类(Abstract Class)QGregorianCalendar 是它的一个具体实现?br>
Calendar ?Date 的{换非常简单:

   Calendar calendar = Calendar.getInstance();
    // 从一?Calendar 对象中获?Date 对象
    Date date = calendar.getTime();
    // ?Date 对象反应C?Calendar 对象中,
    // Calendar/GregorianCalendar 没有构造函数可以接?Date 对象
    // 所以我们必需先获得一个实例,然后讄 Date 对象
    calendar.setTime(date);
 
 

 

Calendar 对象在用时Q有一些值得注意的事:

1. Calendar ?set() Ҏ

set(int field, int value) - 是用来设|?q???时/分钟/U?微秒"{?br>
field 的定义在 Calendar ?br>
set(int year, int month, int day, int hour, int minute, int second) 但没有set(int year, int month, int day, int hour, int minute, int second, int millisecond) 前面 set(int,int,int,int,int,int) Ҏ不会自动?MilliSecond 清ؓ 0?br>
另外Q月份的起始gؓQ而不是1Q所以要讄八月Ӟ我们用7而不??br>
calendar.set(Calendar.MONTH, 7);

我们通常需要在E序逻辑中将它清?0Q否则可能会出现下面的情况:

   import java.io.*;
    import java.util.*;
 
    public class WhatIsCalendarWrite
    {
        public static void main(String[] args) throws Exception{
            ObjectOutputStream out =
                new ObjectOutputStream(
                    new FileOutputStream("calendar.out"));
            Calendar cal1 = Calendar.getInstance();
            cal1.set(2000, 7, 1, 0, 0, 0);
            out.writeObject(cal1);
            Calendar cal2 = Calendar.getInstance();
            cal2.set(2000, 7, 1, 0, 0, 0);
            cal2.set(Calendar.MILLISECOND, 0);
            out.writeObject(cal2);
            out.close();
        }
    }
 

我们?Calendar 保存到文件中

   import java.io.*;
    import java.util.*;
 
    public class WhatIsCalendarRead
    {
        public static void main(String[] args) throws Exception{
            ObjectInputStream in =
                new ObjectInputStream(
                    new FileInputStream("calendar.out"));
            Calendar cal2 = (Calendar)in.readObject();
            Calendar cal1 = Calendar.getInstance();
            cal1.set(2000, 7, 1, 0, 0, 0);
            if (cal1.equals(cal2))
                System.out.println("Equals");
            else
                System.out.println("NotEqual");
            System.out.println("Old calendar "+cal2.getTime().getTime());
            System.out.println("New calendar "+cal1.getTime().getTime());
            cal1.set(Calendar.MILLISECOND, 0);
            cal2 = (Calendar)in.readObject();
            if (cal1.equals(cal2))
                System.out.println("Equals");
            else
                System.out.println("NotEqual");
            System.out.println("Processed Old calendar "+cal2.getTime().getTime());
            System.out.println("Processed New calendar "+cal1.getTime().getTime());
        }
    }
 

然后再另外一个程序中取回来(模拟Ҏ据库的存储)Q但是执行的l果是:

NotEqual
Old calendar 965113200422 <------------ 最后三位的MilliSecond与当前时间有?br>New calendar 965113200059 <-----------/
Equals
Processed Old calendar 965113200000
Processed New calendar 965113200000
 
 

另外我们要注意的一ҎQCalendar Z性能原因?set() Ҏ采取延缓计算的方法。在 JavaDoc 中有下面的例子来说明q个问题Q?br>
Calendar cal1 = Calendar.getInstance();
    cal1.set(2000, 7, 31, 0, 0 , 0); //2000-8-31
    cal1.set(Calendar.MONTH, Calendar.SEPTEMBER); //应该?2000-9-31Q也是 2000-10-1
    cal1.set(Calendar.DAY_OF_MONTH, 30); //如果 Calendar 转化?2000-10-1Q那么现在的l果p?2000-10-30
    System.out.println(cal1.getTime()); //输出的是2000-9-30Q说?Calendar 不是马上刷新其内部的记?br> 

?Calendar 的方法中Qget() ?add() 会让 Calendar 立刻h。Set() 的这个特性会l我们的开发带来一些意想不到的l果。我们后面会看到q个问题?br>
2. Calendar 对象的容错性,Lenient 讄

我们知道特定的月份有不同的日期,当一个用L出错误的日期ӞCalendar 如何处理的呢Q?br>
   import java.io.*;
    import java.util.*;
 
    public class WhatIsCalendar
    {
        public static void main(String[] args) throws Exception{
            Calendar cal1 = Calendar.getInstance();
            cal1.set(2000, 1, 32, 0, 0, 0);
            System.out.println(cal1.getTime());
            cal1.setLenient(false);
            cal1.set(2000, 1, 32, 0, 0, 0);
            System.out.println(cal1.getTime());
        }
    }
 

它的执行l果是:

   Tue Feb 01 00:00:00 PST 2000
    Exception in thread "main" java.lang.IllegalArgumentException
        at java.util.GregorianCalendar.computeTime(GregorianCalendar.java:1368)
        at java.util.Calendar.updateTime(Calendar.java:1508)
        at java.util.Calendar.getTimeInMillis(Calendar.java:890)
        at java.util.Calendar.getTime(Calendar.java:871)
        at WhatIsCalendar.main(WhatIsCalendar.java:12)
 

当我们设|该 Calendar ?Lenient false Ӟ它会依据特定的月份检查出错误的赋倹{?br>
3. 不稳定的 Calendar

我们知道 Calendar 是可以被 serialize 的,但是我们要注意下面的问题

   import java.io.*;
    import java.util.*;
 
    public class UnstableCalendar implements Serializable
    {
 
        public static void main(String[] args) throws Exception{
            Calendar cal1 = Calendar.getInstance();
            cal1.set(2000, 7, 1, 0, 0 , 0);
            cal1.set(Calendar.MILLISECOND, 0);
            ObjectOutputStream out =
                new ObjectOutputStream(
                new FileOutputStream("newCalendar.out"));
            out.writeObject(cal1);
            out.close();
            ObjectInputStream in =
                new ObjectInputStream(
                new FileInputStream("newCalendar.out"));
            Calendar cal2 = (Calendar)in.readObject();
            cal2.set(Calendar.MILLISECOND, 0);
            System.out.println(cal2.getTime());
        }
    }
 

 

q行的结果竟然是: Thu Jan 01 00:00:00 PST 1970

它被复原?EPOC 的v始点Q我们称?Calendar 是处于不E_状态。这个问题的Ҏ原因?Java ?serialize GregorianCalendar 时没有保存所有的信息Q所以当它被恢复到内存中Q又~少_的信息时QCalendar 会被恢复?EPOCH 的v始倹{Calendar 对象׃部分构成Q字D和相对?EPOC 的微U时间差。字D信息是由微U时间差计算出的Q?set() Ҏ不会强制 Calendar 重新计算字段。这样字D值就不对了?br>
下面的代码可以解册个问题:

   import java.io.*;
    import java.util.*;
 
    public class StableCalendar implements Serializable
    {
        public static void main(String[] args) throws Exception{
            Calendar cal1 = Calendar.getInstance();
            cal1.set(2000, 7, 1, 0, 0 , 0);
            cal1.set(Calendar.MILLISECOND, 0);
            ObjectOutputStream out =
                new ObjectOutputStream(
                new FileOutputStream("newCalendar.out"));
            out.writeObject(cal1);
            out.close();
            ObjectInputStream in =
                new ObjectInputStream(
                new FileInputStream("newCalendar.out"));
            Calendar cal2 = (Calendar)in.readObject();
            cal2.get(Calendar.MILLISECOND); //先调?get()Q强?Calendar h
            cal2.set(Calendar.MILLISECOND, 0);  //再设?br>            System.out.println(cal2.getTime());
        }
    }
 

q行的结果是: Tue Aug 01 00:00:00 PDT 2000,q个问题主要会媄响到?EJB ~程中,参数对象中包?Calendar 时。经q?Serialize/Deserialize 后,直接操作 Calendar 会生不E_的情c?br>
4. add() ?roll() 的区?br>
add() 的功能非常强大,add 可以?Calendar 的字D进行计。如果需要减d|那么使用负数值就可以了,?add(field, -value)?br>
add() 有两条规则:

当被修改的字D超出它可以的范围时Q那么比它大的字D会自动修正。如Q?br>
Calendar cal1 = Calendar.getInstance();

cal1.set(2000, 7, 31, 0, 0 , 0); //2000-8-31

cal1.add(Calendar.MONTH, 1); //2000-9-31 => 2000-10-1Q对吗?System.out.println(cal1.getTime()); //l果?2000-9-30
 

另一个规则是Q如果比它小的字D|不可变的Q由 Calendar 的实现类军_Q,那么该小字段会修正到变化最的倹{?br>
以上面的例子Q?-31 ׃变成 9-30Q因为变化最?br>
Roll() 的规则只有一条:当被修改的字D超出它可以的范围时Q那么比它大的字D不会被修正。如Q?br>
Calendar cal1 = Calendar.getInstance();
cal1.set(1999, 5, 6, 0, 0, 0); //1999-6-6, 周日
cal1.roll(Calendar.WEEK_OF_MONTH, -1); //1999-6-1, 周二
cal1.set(1999, 5, 6, 0, 0, 0); //1999-6-6, 周日
cal1.add(Calendar.WEEK_OF_MONTH, -1); //1999-5-30, 周日
WEEK_OF_MONTH ?MONTH 字段,所?roll 不能修正 MONTH 字段?br> 

我们现在已经能够格式化ƈ创徏一个日期对象了, 但是我们如何才能讄和获取日期数据的特定部分? 比如说小? ? 或者分? 我们又如何在日期的这些部分加上或者减d呢? {案是用Calendar c? 如我们前面提到的那? Calendar cM的方法替代了Date cM被hN的方?

假设你想要设|? 获取, 和操U一个日期对象的各个部分, 比方一个月的一天或者是一个星期的一? Z演示q个q程, 我们用具体的子类 java.util.GregorianCalendar. 考虑下面的例? 它计得C面的W十个星期五?3?

import java.util.GregorianCalendar;

import java.util.Date;

import java.text.DateFormat;

public class DateExample5 {

public static void main(String[] args) {

DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL);

// Create our Gregorian Calendar.

GregorianCalendar cal = new GregorianCalendar();

// Set the date and time of our calendar

// to the system&s date and time

cal.setTime(new Date());

System.out.println("System Date: " + dateFormat.format(cal.getTime())); // Set the day of week to FRIDAY

cal.set(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.FRIDAY); System.out.println("After Setting Day of Week to Friday: " + dateFormat.format(cal.getTime()));

int friday13Counter = 0;

while (friday13Counter <= 10) {

// Go to the next Friday by adding 7 days. cal.add(GregorianCalendar.DAY_OF_MONTH, 7);

// If the day of month is 13 we have

// another Friday the 13th.

if (cal.get(GregorianCalendar.DAY_OF_MONTH) == 13) {

friday13Counter++; System.out.println(dateFormat.format(cal.getTime()));

}

}

}

}

在这个例子中我们作了有趣的函数调?

cal.set(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.FRIDAY);

?cal.add(GregorianCalendar.DAY_OF_MONTH, 7);

set Ҏ能够让我们通过单的讄星期中的哪一天这个域来将我们的时间调整ؓ星期? 注意到这里我们用了帔R DAY_OF_WEEK ?FRIDAY来增Z码的可读? add Ҏ让我们能够在日期上加上数? 润年的所有复杂的计算都由q个Ҏ自动处理.

我们q个例子的输出结果是:

System Date: Saturday, September 29, 2001

当我们将它设|成星期五以后就成了: Friday, September 28, 2001

Friday, September 13, 2002

Friday, December 13, 2002

Friday, June 13, 2003

Friday, February 13, 2004

Friday, August 13, 2004

Friday, May 13, 2005

Friday, January 13, 2006

Friday, October 13, 2006

Friday, April 13, 2007

Friday, July 13, 2007

Friday, June 13, 2008

Calendarcȝ基础x变量域的观念。每个类元素都是域,q且q些域在CalendarcM表现为静态变量。这些变量域Q可以通过get/setcL法来获得或者设|域倹{?br>
// 获得默认的Calendar实例Q给它设|时?br>Calendarcal = Calendar.getInstance();
intyear = cal.get(Calendar.YEAR);
cal.set(Calendar.MONTH,Calendar.NOVEMBER);
Calendarcȝadd和rollҎ提供在日期之间{换的能力。每个方法都׃个参数变量和一个参数值来修改Q通过q个可ؓ正数或负数的参数值来修改它。仅仅不同的是,addҎ可以向高阶的变量域溢出。例如,如果从九月三号向后倒退三天Q将得到Q?br>
Calendar cal = Calendar.getInstance();

cal.add(Calendar.DATE,-3);

// gؓ: 星期六八?31 23:43:19 EDT 2002

然而用rollҎ向后回滚三天得出Q?br>
Calendar cal = Calendar.getInstance();

cal.roll(Calendar.DATE,-3);

// gؓ: 星期一九月 30 23:43:47 EDT 2002
q就是ؓ什么通常主要使用addҎ的原因?br>
q有一个隐藏在最通用的Calendar的子cM的功能性方?-isLeapYearQ判断是否ؓ闰年Q方法?br>
Calendar cal = Calendar.getInstance();

booleanleapYear = ( (GregorianCalendar)cal ).isLeapYear(2002);

// q个值是false

管它是一个实例方法,isLeapYearҎ的行现像静态方法,需要提供年份的参数传值给日历?br>
其实求几天几月几q前/后的ҎQ应该用CalendarcL较好的(比DateQ?br>
Calendar cal = Calendar.getInstance();

cal.setTime(date);

cal.add(Calendar.MONTH,1);

cal.add(Calendar.YEAR,2000);

date = cal.getTime();

通过接管日期修改的功能,java.util.Calendarcȝ上去更像是Datacȝ复杂版本。但是它q提供额外的功能Q更不用说它的国际化支持Q得它值得拥有学习的难度曲Uѝ?br>
3.      使用GregorianCalendarc?br>创徏一个代表Q意日期的一个途径使用GregorianCalendarcȝ构造函敎ͼ它包含在java.util包中Q?br>
GregorianCalendar(int year, int month, int date)
注意月䆾的表C,一月是0Q二月是1Q以此类推,?2月是11。因为大多数Z惯于使用单词而不是用数字来表示月䆾Q这L序也许更易读Q父cCalendar使用帔R来表C月份:JANUARY, FEBRUARY,{等。所以,创徏Wilbur ?Orville刉第一架动力飞机的日期QDecember 17, 1903Q,你可以用:

GregorianCalendar firstFlight = new GregorianCalendar(1903, Calendar.DECEMBER, 17);

Z清楚的考虑Q你应该使用前面的Ş式。但是,你也应该学习怎样阅读下面的短格式。下面的例子同样表示December 17,1903Q记住,在短格式中,11表示DecemberQ?br>
       GregorianCalendar firstFlight = new GregorianCalendar(1903, 11, 17);   在上一节中Q你学习了{换Date对象到字W串。这里,你可以做同样的事情;但是首先Q你需要将GregorianCalendar对象转换到Date。要做到q一点,你可以用getTime()ҎQ从它得父类Calendarl承而来。GetTime()Ҏq回GregorianCalendar相应的Date对象。你能够创徏GregorianCalendar对象Q{换到Date对象Q得到和输出相应的字W串q样一个过E。下面是例子Q?

import java.util.*;

import java.text.*;

public class Flight {

   public static void main(String[] args) {

GregorianCalendar firstFlight = new GregorianCalendar(1903, Calendar.DECEMBER, 17);   

Date d = firstFlight.getTime();

DateFormat df = DateFormat.getDateInstance();

String s = df.format(d);

System.out.println("First flight was " + s);

}

有时候创Z个代表当前时ȝGregorianCalendarcȝ实例是很有用的。你可以单的使用没有参数的GregorianCalendar构造函敎ͼ象这P

GregorianCalendar thisday = new GregorianCalendar();
一个输Z天日期的例子E序Q用GregorianCalendar对象Q?br>
import java.util.*;
import java.text.*;
class Today {
   public static void main(String[] args) {
GregorianCalendar thisday = new GregorianCalendar();
Date d = thisday.getTime();
DateFormat df = DateFormat.getDateInstance();
String s = df.format(d);
      System.out.println("Today is " + s);
   }
}
注意刎ͼDate()构造函数和GregorianCalendar()构造函数很cMQ都创徏一个对象,条g单,代表今天?br>GregorianCalendarcL供处理日期的Ҏ。一个有用的Ҏ是add().使用add()ҎQ你能够增加象年Q月敎ͼ天数到日期对象中。要使用add()ҎQ你必须提供要增加的字段Q要增加的数量。一些有用的字段是DATE, MONTH, YEAR, ?WEEK_OF_YEAR。下面的E序使用add()Ҏ计算未来80天的一个日期。在Jules?lt;环球80?gt;是一个重要的数字Q用这个程序可以计Phileas Fogg从出发的那一?872q?0?日后80天的日期Q?br>
import java.util.*;
import java.text.*;
public class World {
   public static void main(String[] args) {
GregorianCalendar worldTour = new GregorianCalendar(1872, Calendar.OCTOBER, 2);
      worldTour.add(GregorianCalendar.DATE, 80);
Date d = worldTour.getTime();
DateFormat df = DateFormat.getDateInstance();
String s = df.format(d);
System.out.println("80 day trip will end " + s);
   }
}
add()一个重要的副作用是它改变了原来的日期。有时候,拥有原始日期和修改后的日期很重要。不q的是,你不能简单的创徏一个GregorianCalendar对象Q设|它和原来的相等QequalQ。原因是两个变量指向同一个Date()对象地址。如果Date对象改变Q两个变量就指向改变后的日期对象。代替这U做法,应该创徏一个新对象。下面的E序C了这U做法:import java.util.*;

import java.text.*;

public class ThreeDates {

   public static void main(String[] args) {

GregorianCalendar gc1 = new GregorianCalendar(2000, Calendar.JANUARY, 1);

GregorianCalendar gc2 = gc1;

GregorianCalendar gc3 = new GregorianCalendar(2000, Calendar.JANUARY, 1);
      //Three dates all equal to January 1, 2000

gc1.add(Calendar.YEAR, 1);

//gc1 and gc2 are changed     

DateFormat df = DateFormat.getDateInstance();

Date d1 = gc1.getTime();

Date d2 = gc2.getTime();

Date d3 = gc3.getTime();

String s1 = df.format(d1);

String s2 = df.format(d2);

String s3 = df.format(d3);

System.out.println("gc1 is " + s1);

System.out.println("gc2 is " + s2);

System.out.println("gc3 is " + s3);

   }

}

         E序q行后,gc1和gc2被变?001q_因ؓ两个对象指向同一个DateQ而Date已经被改变了Q。对象gc3指向一个单独的DateQ它没有被改变?br> package com.minght.sys.util;

/**
 * <p>Title: 开?开?lt;/p>
 * <p>Description: opeansource</p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: ?h</p>
 * @author HaiTang Ming
 * @version 1.0
 */

import java.util.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.text.*;


public class timeUtil {

  /**
   * Datecd日期转化成Stringcd"L"格式
   * java.sql.Date,java.sql.Timestampcd是java.util.Datecd的子c?br>   * @param date Date
   * @param format String
   *               "2003-01-01"格式
   *               "yyyyqM月d?
   *               "yyyy-MM-dd HH:mm:ss"格式
   * @return String
   */
  public static String dateToString(java.util.Date date,String format) {

      if (date==null || format==null) {
          return null;
      }

      SimpleDateFormat sdf = new  SimpleDateFormat(format);
      String str = sdf.format(date);
      return str;
  }

  /**
   * Stringcd日期转化成java.utl.Datecd"2003-01-01"格式
   * @param str String  要格式化的字W串
   * @param format String
   * @return Date
   */
  public static java.util.Date stringToUtilDate(String str,String format) {

      if (str==null||format==null) {
          return null;
      }

      SimpleDateFormat sdf = new  SimpleDateFormat(format);

      java.util.Date date = null;
      try
      {
          date = sdf.parse(str);
      }
      catch(Exception e)
      {
      }
      return date;
  }


  /**
   * Stringcd日期转化成java.sql.Datecd"2003-01-01"格式
   * @param str String
   * @param format String
   * @return Date
   */
  public static java.sql.Date stringToSqlDate(String str,String format) {

      if (str==null||format==null) {
          return null;
      }

      SimpleDateFormat sdf = new  SimpleDateFormat(format);

      java.util.Date date = null;
      try
      {
          date = sdf.parse(str);
      }
      catch(Exception e)
      {
          return null;
      }
      return new java.sql.Date(date.getTime());
  }

  /**
   * Stringcd日期转化成java.sql.Datecd"2003-01-01"格式
   * @param str String
   * @param format String
   * @return Timestamp
   */
  public static java.sql.Timestamp stringToTimestamp(String str,String format) {

      if (str==null||format==null) {
          return null;
      }

      SimpleDateFormat sdf = new  SimpleDateFormat(format);

      java.util.Date date = null;
      try
      {
          date = sdf.parse(str);
      }
      catch(Exception e)
      {
          return null;
      }
      return new java.sql.Timestamp(date.getTime());
  }


  /**
   * java.util.Date日期转化成java.sql.Datecd
   * @param Date
   * @return 格式化后的java.sql.Date
   */
  public static java.sql.Date toSqlDate(Date date) {

      if (date==null) {
          return null;
      }

     return new java.sql.Date(date.getTime());
  }
  /**
   * 字W串转化为时间格?string to string
   * @param str String
   * @param format String
   * @return String
   */
  public static String toDateString(String str,String oldformat,String newformat){

      return dateToString(stringToUtilDate(str,oldformat),newformat);

  }

  /**
   * 日历{化ؓ日期
   * @param calendar Calendar
   * @return Date
   */
  public static java.util.Date converToDate(java.util.Calendar calendar){
    return Calendar.getInstance().getTime();
  }

  /**
   * 日期{化ؓ日历
   * @param date Date
   * @return Calendar
   */
  public static java.util.Calendar converToCalendar(java.util.Date date){
     Calendar calendar = Calendar.getInstance();
     calendar.setTime(date);
     return calendar;
  }

  /**
   * 求得从某天开始,q了几年几月几日几时几分几秒后,日期是多?br>   * 几年几月几日几时几分几秒可以?br>   * @param date Date
   * @param year int
   * @param month int
   * @param day int
   * @param hour int
   * @param min int
   * @param sec int
   * @return Date
   */
  public static java.util.Date modifyDate(java.util.Date date,int year ,int month,int day,int hour,int min,int sec){
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.add(Calendar.YEAR,year);
    cal.add(Calendar.MONTH,month);
    cal.add(Calendar.DATE,day);
    cal.add(Calendar.HOUR,hour);
    cal.add(Calendar.MINUTE,min);
    cal.add(Calendar.SECOND,sec);

    return cal.getTime();

  }


  /**
   * 取得当前日期旉
   * 1:year
   * 2:month
   * 3:day
   */
  public static int getCurTime(int i) {
    if (i == 1) {
      return java.util.Calendar.getInstance().get(Calendar.YEAR);
    }
    else if (i == 2) {
      return java.util.Calendar.getInstance().get(Calendar.MONTH) + 1;
    }
    else if (i == 3) {
      return java.util.Calendar.getInstance().get(Calendar.DATE);
    }
    return 0;

  }

  public static void main(String[] args){
    System.out.println(dateToString(modifyDate(Calendar.getInstance().getTime(),-1,-1,-1,-1,-1,-1),"yyyy-MM-dd HH:mm:ss"));
  }

}


Terry的Blog 2005-12-05 10:15 发表评论
]]>我的最项目管理工具集Q{载)http://m.tkk7.com/terry-zj/archive/2005/11/25/21444.htmlTerry的BlogTerry的BlogFri, 25 Nov 2005 09:28:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/11/25/21444.htmlhttp://m.tkk7.com/terry-zj/comments/21444.htmlhttp://m.tkk7.com/terry-zj/archive/2005/11/25/21444.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/21444.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/21444.html工具从来׃ؕp|但花哨的工具未必适合自己的团队?BR>z净铅华的ȝZ些最必要的,能提供最大辅力加持的工具?BR>参见《死亡中旅?nd Wx?-最工具集.

1.版本理工具和文本比?合ƈ工具
   用的?/FONT>CVS: l毛v?/FONT>?WinMerge.  
   q年_q有谁敢不用版本理工具p人合作开发么Q?有的?BR>   一个好的ProgrammerQ除了要有好的udpate/commit习惯外,会不会善用文本差异比?合ƈ工具是另一层次的观察标准?BR>   另外Q因为重构时有用Q版本管理工兯能和IDEl合?/FONT>

2.目计划QQ务分配,需求变更管理,Bug理工具
    偶然的,
我发现自己把q些都交l了JIRA完成?BR>
    目计划QQ务分配,q度跟踪Q需求变更管理,Bug理几乎是PM的全部工作了?BR>    以前L很多软g分开来管理这些问题,同一问题l常要Copy Paste好几个Y件?BR>    但如果你的团队的目计划是XP plan风格 而不是MS Project
    那恭喜了Q?EM>一个JIRA可以完成所有Q务?

3.支持重构QFlying Error提示QTDD和Debug 的IDE

 Java: IDEA 5.0能满下面的全部要求?nbsp;
 C++: VC7.1+
VAQ就差好多了?BR> Ruby: Eclipse?/FONT>RDT插gQ就弱得一塌糊涂?BR> Groovy:IDEA的插?/FONT>Groovyj
 Php: Zend Stuido

 a.重构Q即使团队用的最多的只是RenameQMoveQExtract Method{有限几个最基本的功能,但J2EEl构里牵一发动全n的事情太多了Q重构会帮你把事情擦q净Q现在已形成依赖?/FONT>

 b.Flying Error提示Q?BR>    Java IDE的标准配|了Q有错马上提C,不要{编译时。可惜其他语a的IDE里这q不是标配?/FONT>

  c.Debug J2EE应用Q?BR>     Web开发者一般用System.out或者log4j来显C试信息,但对于曾l桌面编E的E序员来_直接q入调试模式Q单步跟t程序执行\径,想看哪个变量q哪个变量Q才是天l地义的事情Q只是之前的IDE不能支持而已?BR>    
  d.TDDQTDD不等于Unit Test。TDD是让你不用依赖表现层Q不用手工输入数据,清除数据Q不用重起Tomcat的开发?BR>    我们团队暂时q追求不h试覆盖率QSoQUntTest只是一U开发的手段Q而不是测试的手段?/FONT>

4.团队IM工具和共享文件夹
   
前代是言必称Email的,现在配合
Google Group也很好用Q但我们更喜ƢQQ 的x性?BR>    同时QQ 2005版的"来消息时只显C消息条?的免打扰功能很重要?BR>    对于坐在一L团队Q在文g服务器上Z׃n文g夹就够了?BR>

5.知识库Wiki
   Java?/FONT>JspWiki是最单易装入门wikiQ但php世界里显然有更好的选择?/FONT>Dokuwiki?BR>   我一直希望wiki语法有所见所得的~辑器?BR>

其他工具包括U,W,_大的白板Q随时可用的会议室?BR>
q缺了什么?
一、代码自动生成工具中也没有最手的?BR>二、因为没有够的UnitTest用例Q配好的持箋集成工具没有实际q作?BR>
http://m.tkk7.com/calvin/archive/2005/10/13/15422.html



Terry的Blog 2005-11-25 17:28 发表评论
]]>始终会用上的Common BeanUtils Q{载)http://m.tkk7.com/terry-zj/archive/2005/11/25/21443.htmlTerry的BlogTerry的BlogFri, 25 Nov 2005 09:22:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/11/25/21443.htmlhttp://m.tkk7.com/terry-zj/comments/21443.htmlhttp://m.tkk7.com/terry-zj/archive/2005/11/25/21443.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/21443.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/21443.html

        Beanutils用了术般的反射技术,实现了很多夸张有用的功能Q都是C/C++时代不敢想的。无的项目,始终一天都会用得上它。我是后知后觉了,W一回看到它的时候居焉q?BR>
1.属性的动态getter、setter
       
在这框架满天飞的q代Q不能事事都保证执行getter,setter函数了,有时候属性是要根据名字动态取得的Q就像这P  
BeanUtils.getProperty(myBean,"code");
        而Common BeanUtils的更强功能在于可以直接访问内嵌对象的属性,只要使用点号分隔?BR>BeanUtils.getProperty(orderBean, "address.city");
相比之下其他cd的BeanUtils通常都很单,不能讉K内嵌的对象,所以有时要用Commons BeanUtils来替换它们?BR>
BeanUtilsq支持List和Mapcd的属性,如下面的语法卛_取得Order的顾客列表中W一个顾客的名字
BeanUtils.getProperty(orderBean, "customers[1].name");
其中BeanUtils会用ConvertUtilscL字符串{为Bean属性的真正cdQ方便从HttpServletRequest{对象中提取beanQ或者把bean输出到页面?BR>而PropertyUtils׃原色的保留Bean原来的类型?/FONT>

2.BeanCompartor 动态排?
       
q是通过反射Q动态设定Bean按照哪个属性来排序Q而不再需要在实现bean的Compare接口q行复杂的条件判断?
        List peoples = ...; // Person对象的列?BR>        Collections.sort(peoples, new BeanComparator("age"));
如果要支持多个属性的复合排序Q如"Order By lastName,firstName"

ArrayList sortFields = new ArrayList();
sortFields.add(new BeanComparator("lastName"));
sortFields.add(new BeanComparator("firstName"));
ComparatorChain multiSort = new ComparatorChain(sortFields);
Collections.sort(rows,multiSort);

其中ComparatorChain属于jakata commons-collections包?BR>如果age属性不是普通类型,构造函数需要再传入一个comparator对象为age变量排序?BR>另外, BeanCompartor本n的ComparebleComparator, 遇到属性ؓnull׃抛出异常, 也不能设定升序还是降序。这个时候又要借助commons-collections包的ComparatorUtils.

   Comparator mycmp = ComparableComparator.getInstance();
   mycmp = ComparatorUtils.nullLowComparator(mycmp);  //允许null
   mycmp = ComparatorUtils.reversedComparator(mycmp); //逆序
   Comparator cmp = new BeanComparator(sortColumn, mycmp);
3.Converter 把Request或ResultSet中的字符串绑定到对象的属?
       
l常要从request,resultSet{对象取出值来赋入bean中,如果不用MVC框架的绑定功能的话,下面的代码谁都写M?BR> 
   String a = request.getParameter("a");
   bean.setA(a);
   String b = ....
   bean.setB(b);
   ......
不妨写一个Binder自动l定所有属?
    MyBean bean = ...;
HashMap map = new HashMap();
Enumeration names = request.getParameterNames();
while (names.hasMoreElements())
{
String name = (String) names.nextElement();
map.put(name, request.getParameterValues(name));
}
BeanUtils.populate(bean, map);

    其中BeanUtils的populateҎ或者getProperty,setPropertyҎ其实都会调用convertq行转换?BR>    但Converter只支持一些基本的cdQ甚臌java.util.Datecd也不支持。而且它比较笨的一个地Ҏ当遇C认识的类型时Q居然会抛出异常来?nbsp;对于DatecdQ我参考它的sqldatecd实现了一个ConverterQ而且d了一个设|日期格式的函数?BR>要把q个Converter注册Q需要如下语句:

   ConvertUtilsBean convertUtils = new ConvertUtilsBean();
   DateConverter dateConverter = new DateConverter();
   convertUtils.register(dateConverter,Date.class);



//因ؓ要注册converter,所以不能再使用BeanUtils的静态方法了Q必d建BeanUtilsBean实例
BeanUtilsBean beanUtils = new BeanUtilsBean(convertUtils,new PropertyUtilsBean());
beanUtils.setProperty(bean, name, value);
4 其他功能
4.1 ConstructorUtilsQ动态创建对?BR>        public static Object invokeConstructor(Class klass, Object arg)
4.2 MethodUtilsQ动态调用方?/STRONG> 
        MethodUtils.invokeMethod(bean, methodName, parameter);
4.3 PropertyUtilsQ当属性ؓCollection,Map时的动态读取:
        Collection: 提供index
       
BeanUtils.getIndexedProperty(orderBean,"items",1);
或?BR>        BeanUtils.getIndexedProperty(orderBean,"items[1]");Map: 提供Key Value
       
BeanUtils.getMappedProperty(orderBean, "items","111");//key-value goods_no=111 或?BR>        BeanUtils.getMappedProperty(orderBean, "items(111)")
4.4 PropertyUtilsQ直接获取属性的Classcd
       
public static Class getPropertyType(Object bean, String name)
4.5 动态Bean ?A target=__blank>用DynaBean减除不必要的VO和FormBean 

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=277748



Terry的Blog 2005-11-25 17:22 发表评论
]]>
Hibernate 2 升为Hibernate 3 的注意事?转蝲)http://m.tkk7.com/terry-zj/archive/2005/11/24/21250.htmlTerry的BlogTerry的BlogThu, 24 Nov 2005 03:22:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/11/24/21250.htmlhttp://m.tkk7.com/terry-zj/comments/21250.htmlhttp://m.tkk7.com/terry-zj/archive/2005/11/24/21250.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/21250.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/21250.html目的Q主要是那当前的目l手Q熟悉一下hibernate2和hibernate3的差别,l当前项目一Ҏ展的I间?BR>
1.首先hibernate2.jar替换为hibernate3.jar(hibernate-3.0.5)
  hibernate-tools.jar也替换成新的(从hibernate-tools-3.0.0.alpha4a扑և来的)

2.所有程序中的net.sf.hibernate替换为org.hibernate.
 
3.但是有例?BR>  net.sf.hibernate.expression.Expression换ؓorg.hibernate.criterion.Expression
  如果用eclipse,用ctrl+shift+o快捷键可以加快速度
 
4.在用hql查询时将
  createSQLQuery(hql,"c",EZCampaignDTO.class);改ؓcreateSQLQuery(hql).addEntity("c",EZCampaignDTO.class);
 
5.在批量插入时
  原来的int size = ((SessionFactoryImpl)(session.getSessionFactory())).getJdbcBatchSize()
  改ؓint size = ((SessionFactoryImpl)(session.getSessionFactory())).getSettings().getJdbcBatchSize();
 
6.在计count?BR>  原来的int size = ((Integer) session.iterate(hql).next()).intValue();
  改ؓint size = ((Integer) session.createQuery(hql).iterate().next()).intValue();
其中hql="select count(*) from " + DAOVar.contactClass;
 
7.q有是?hbm中的hibernate-mapping-2.0.dtd替换为hibernate-mapping-3.0.dtd
  Hibernate Mapping DTD 2.0替换为Hibernate Mapping DTD 3.0
 
8.hibernate.cfg.xml?BR>  Hibernate Mapping DTD 2.0替换为Hibernate Mapping DTD 3.0
  <property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
 
9.hibernate.properties中类?BR> 
10.cache-config.xml?BR>   <provider className="net.sf.hibernate.cache.OSCacheProvider"/>替换?BR>   <provider className="org.hibernate.cache.OSCacheProvider"/>
 
11.classeshibernate.properties?BR>   hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
   hibernate.dialect=org.hibernate.dialect.SQLServerDialect
 
12.在自动外部模块部分有一个功能是Ҏ模版自动生成.hbm文g在load,l果出来?hbm中有问题:
   生成?nbsp;<composite-id unsaved-value="any" mapped="false">其中mapped="false" 出错。找了半天才发现在网上的hibernate-mapping-3.0.dtd文g有支持mapped="false"q个属性。而本地的hebernate3.0.5中的hibernate-mapping-3.0.dtd文g没有q个属性。晕Qhibernate也太不负责了吧。解军_法把hibernate-mapping-3.0.dtd copy到jboss\bin目录下然后,在template文g?lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "hibernate-mapping-3.0.dtd">Q然后他会在jboss\bin目录下读取该文g?BR> 
13.重新试,q是咣铛Q发现子c读父类数据时抛出异常:
   "org.hibernate.LazyInitializationException: could not initialize proxy"
   延迟抓取出的错,hb3对many-to-one的默认处理是lazy = "proxy"Q没有搞懂到底怎么回事Q把所有many-to-one,one-to-one都加上lazy="false"Q再试l于大功告成?BR>
文章原作者BlogQ?/FONT>::URL::http://blog.csdn.net/chinaewolf/

Terry的Blog 2005-11-24 11:22 发表评论
]]>
Hibernate的未来发展之路(转蝲Q?/title><link>http://m.tkk7.com/terry-zj/archive/2005/11/24/21248.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Thu, 24 Nov 2005 03:14:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2005/11/24/21248.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/21248.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2005/11/24/21248.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/21248.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/21248.html</trackback:ping><description><![CDATA[<font size="2"><span id="igvmkux" class="postbody">Hibernate的未来发展之?<br><br>最q半q多来,在Java世界QHibernate是最引hx的一个话题。从Gavin King加入EJB3.0 EGQ负责制订EJB3.0的持久层规范Q到Gavin King非正式退出JDO EGQƈ且充满个人情l的dJDO2.0规范Q到《Hibernate in Action》的发行Q再到Hibernate3 Alpha的发布;最后再到最qJBoss 3.0 PR的发?使用Hibernate3实现Entity Bean)。可以说q其中的每一步都引v业界的侧目?<br><br>Hibernate在不?q的旉里,从一个不L的开源Y件发展到今天令业界瞩目的LO/R Mapping框架QGavin King从一个开源Y件的作者成Z界D重的人物Q这多少有些传奇的色彩。毕竟,单纯从技术成p言QHibernate不算是最有成qJava开源框架YӞ到目前ؓ止也不是一个完无~的软gQ从个h技术水q言QGavin King也不绝剙手?<br><br>在当前的Java持久层框架中Q最行的O/R Mapping产品分别是HibernateQJDO和TopLink?<br><br>自从dGavin King加入JBoss之后QHibernate已经׃个民间的开源Y件走上了兼容EJB EntityBean的道路。然而更加oZ目的是,Gavin King在EJB3.0 EG中充当了一个非帔R要的角色Q只要对比一下EJB3.0的EntityBean和Hibernate3Q真相就会大白,虽然API接口不同Q但是EntityBean的设计理念完全来自于Hibernate?<br><br>虽然EJB3.0的EntityBean在相当程度上来源于HibernateQ但是毕竟是不同的API接口Q因此Hibernate和EJB3.0 EntityBeanI竟是怎样的一U关p,是很多h心中的疑问?<br><br>今年四月份JBoss的Ben Wang访华期间Q我曄向BenhHibernate的未来发展,他回{说QHibernate未来仍旧以独立的Y件品存在和发展Q既可以outside EJB container使用Q同时Hibernate也将做ؓJBoss EntityBean ImplementationQ又可以inside EJB container使用。然而如何既insideQ又outsideQ终I缺乏一个感性的认识?<br><br>10?日JBoss发布的EJB3.0 PR揭开了答案。从Sourceforge的CVS服务器上面checkout出来源代码看一下,我们可以发现QGavin King对Hibernate3q行了简单的装Q将EJB 3.0 EntityBean API调用转换为内部Hibernate3自己的APIQ从而实现EJB3.0 EntityBean的兼宏V?<br><br>EJB3.0不承d器调用,如果你想享用EJB3.0Q则必须q行在某个EJB Vendor提供的容器内Q例如你使用JBoss提供的容器,那么你调用的是EntityBean APIQ这些调用请求会被{换ؓHibernate API的调用请求。这意味着Hibernate实际上提供了两套APIQ一套是Hibernate原生APIQ另一套是兼容EJB3.0 EntityBean API。对于那些需要分布式调用支持Q需要EJB容器的开发h员来_他们选择后一套APIQ对于不需要EJB容器的开发h员来_他们选择前一套API。这是Hibernate既定的发展策略?<br><br>今年夏天投票通过的JDO2.0标准从某U程度而言Qƈ不逊色于Hibernate当前的版本,有些功能甚至比Hibernateq要好,例如JDO支持对类属性的lazy loadingQ而Hibernate要到3才支持,当前Hibernate仅仅支持cȝlazy loading。实际上在去q_已l有很多用户不断提出对类属性的lazy loading的需求,然而Gavin King当时一直不认ؓq个需求有d的必要性。再例如被Gavin King形容为“可憎的”JDOQLQ实际上是类SQL查询语言和对象条件查询的混合体。从功能上来_不如HQL强大Q但是远比Hibernate自己的条件查询强很多?<br><br>不知道究竟出于什么原因,Gavin King对JDOg一直怀有由L厌恶Q今q?月,他在Hibernate的blog上面对JDOq行了毫不留情的批判Q列举了JDO的种U缺Ҏ解释Z么EJB3持久层规范没有把JDO考虑q去。然而事实上他的批判充满了对JDO的误解和偏见Q例如Gavin King憎恨JDOQL丝毫没有什么特别的理由Q只因ؓJDOQL不是一个纯_的查询语言Q而是一个؜合体Q这多少让h对Gavin King的风度感到遗憾。在被SolarMetric的Abe White反驳之后Q同h有风度的_“我可没有时间做q种无谓的争论,事实上每个h都认Z自己的技术是最好的……我是错了,JDO那伙Z错了Q每个h都会犯错误……”。(所以说人无完h阿!Q?<br><br>JDO2规范的出C实上构成了对HibernateQ乃臛_于Hibernate理念的EJB3.0 EntityBean的严重威胁。JDO1.0规范在功能上的严重缺失导致了JDO无力面对Hibernate和TopLink的竞争,然而功能基本完备的JDO2挟众多JDO Vendor商业支持的合力,同时JDO规范可以避免产品锁定在某个Vendor的优势,已经竞争的天^拉直?<br><br>然而JDO2和EJB3两大商业L标准的分裂,是大部分人,甚至包括厂商所不希望看到的?于是最lEJB3的Lead Linda DeMichiel和JDO2的Lead Craig Russell联名发表公开信,宣布了一个合qEJB3和JDO2持久层规范的计划Q新的持久层规范以JSR-220(EJB3.0)的持久层规范为基Q融合JDO2的部分特性。新的持久层规范进入J2EE1.5之中Q独立于EJB存在Q既可以inside J2EE容器来用,也可以脱J2EE容器Q独立的q行?<br><br>q个新的持久层框架可以说完全是一个政ȝ产物。EJB VendorsZ自n利益反对JDOQ得JDO没有办法成ؓJ2EE的一部分Q然而标准的分裂也是大部分h更加不希望看到的Q于是最lJDO成了政治斗争的牺牲品。从表面上来看,JDO和EJB3.0 EntityBean都将被新的持久层框架取代Q似乎JDOq没有吃亏,但实际上JDO2标准已经成熟Q部分JDO领导厂商的品已l蓄始待发,而EJB3.0 EntityBeanq处于Early DraftQ等待品诞生至也是一q之后的事情了;另外值得耐hd的是Q新的持久层框架基于当前EJB3.0 EntityBeanQ再l合JDO2的规范,q且处于EJB3.0 EG的控制之下,再加入一些JDO2 EG的成员。因此可以看出来新的持久层框架无疑还是以EJB3.0 EGZD行制定的?<br><br>从长q来看,EJB3和JDO2的政L争对双方都有好处Q长期分裂带来的后果对双方的发展都不利,然而从短期来看QJDO2实是在q场政治斗争中|下阵来。最直接的体现就是,已经有一些JDO的用户对JDO的前景生了动摇和迷茫,不少的JDO爱好者更是直aJDO死?<br><br>不过对JDO来说Q事情未必如此悲观。因为新的持久层框架的最l发布最快也要在2005q夏天,q还是乐观的估计Q比较广泛的使用则是2006q的事情了。ƈ且如果新的持久层框架q是像EJB3 EntityBean那样严重依赖J2SE5.0的annotation的话Q无疑将无法在很多当前运行的pȝ和遗留系l上使用。这些都是JDO2的市场生存空间。有了这D|间的~冲QJDO Vendor可以^~的转变Z个J2EE1.5持久层框架的供应商,面更加qK的企业客L体?<br><br>TopLink是一个老牌的O/R Mapping软g了,自从被Oracle收购之后Q又增加了对Oracle数据库的良好支持Q和对Oracle AS EntityBean的支持。Oracle提供了TopLink的图形设计环境,可以使得设计好的TopLink域模型既可以被单独用在TopLink中,也可以被用在EJB CMP中。因此看来TopLink也走了一条和Hibernate同样{略的\?<br><br>TopLink的问题在于相比Hibernate的开源和免费的优势来_TopLink既不开源,售h又不菲上。本来商业Y件TopLink应该在技术支持和商业宣传{略上拥有够的优势Q然而Oracle公司毕竟是一个以数据库ؓ核心产品的公司,其他的一切品都是ؓ了数据库销售业l而服务的。在Oracle产品U中处于一个从属地位的TopLinkQ由于先天不I只能眼睁睁看着Hibernate的日益壮大而无所作ؓQ因此TopLink更多的被局限在购买了Oracle数据库,q且l定Oracle数据库的用户体中?<br><br>J2EE1.5的新持久层规范将毫无悬念的成为未来持久层框架的主APIQ无论是HibernateQJDOQ还是TopLinkl将兼容q个L商业API。在当前的这三种持久层API当中QHibernate无疑是最有前途的。这是因为: <br><br>1、新的持久层规范基于EJB3.0 EntityBean规范Q这意味着仍将以Hibernate的设计理念ؓ基础 <br>2、JBoss对EJB3.0规范跟随的步伐非常紧密,在规范制定过E中׃断的发布参考实C品,因此可以对对EJB3.0规范产生比较大的影响力?<br>3、根据内部泄漏出来的道消息QBEA公司的WebLogic9产品U的目l理已经在用Hibernate2来实现EJB3.0的持久层框架。WebLogic9 beta1预计q底发布Qbeta2预计明年3月发布,正式产品紧随EJB3.0规范正式版发布之后的明年U季发布?<br><br>lg所qͼ我们有理由对Hibernate的前途抱有强烈的信心?<br><br>最后的一个疑问是Q既然J2EE1.5的新持久层框架可以脱J2EE容器q行Q那么大家不全部都去用Hibernate的后一套兼容APIQ而完全放弃Hibernate的原生API了吗Q那么是否意味着Hibernate做ؓ一个独立品的使命dl结呢? <br><br>对于q个问题我的看法是:J2EE1.5的持久层规范要综合各个EJB VendorQJDO Vendor的意见,要^衡他们之间的利益得失Q那么这样一个瞻前顾后的规范必然无法覆盖所有应用场合的全面需要,q不像Hibernate的原生API可以随时Ҏ开发h员的要求增加功能那么灉|。因此我预计Hibernate的原生API以其更加强大的功能仍然会吸引一大批人直接用原生APIQ而不是兼容J2EE规范的API?<br><br>总而言之,对于我们当前的持久层开发来_最好的办法莫过于坚定的使用DAO层来隔离持久层和业务层逻辑Q那么不未来持久层风云如何变换Q但凡基于POJO的持久层框架都可以被我们拿来L替换?/span><br><br>转蝲来源Q?a ><br>http://www.hibernate.org.cn/viewtopic.php?t=8146&postdays=0&postorder=asc&start=0</a></font><img src ="http://m.tkk7.com/terry-zj/aggbug/21248.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2005-11-24 11:14 <a href="http://m.tkk7.com/terry-zj/archive/2005/11/24/21248.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的三U查询方式(转蝲Q?/title><link>http://m.tkk7.com/terry-zj/archive/2005/11/24/21233.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Thu, 24 Nov 2005 02:27:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2005/11/24/21233.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/21233.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2005/11/24/21233.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/21233.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/21233.html</trackback:ping><description><![CDATA[<span id="onaocmt" class=postdetails><FONT size=2><SPAN style="COLOR: red">Q一QHQL</SPAN> <BR>HQLQHibernate Qusery LanguageQ如果你已经熟悉它,׃发现它跟SQL非常相像。不q?你不要被表面的假象迷惑,HQL是面向对象的QOOQ用生命的眼光看待每一个对象,他们是如?鲜活Q。如果你对JAVA和SQL语句有一定了解的话,那么HQL对你直易如反掌,你完全可以利用在公R上的旉掌握它?<BR><BR>以下从几个方面进行慢慢深入: <BR><BR>1。大些敏感 <BR>大家知道SQL-92 Query是对大小写不敏感的,但是在HQLQ前面提到它是OO的)中对对象cȝ名称和属性确实大写敏感的(W合java~程语法Q?<BR>HQL 子句本n大小写无养I但是其中出现的类名和属性名必须注意大小写区?<BR>如:sElect cat.name from Cat as cat和select cat.name from Cat as cat是一L <BR>但是Q?<BR>sElect cat.name from CAT as cat和select cat.name from Cat as cat实不一L?<BR><BR>2。from语句 <BR>最单的Q?<BR>from eg.Cat <BR>它只是简单的q回所有eg.Cat的实?通常我们此时会ؓeg.Cat其个别名Q因为在query的其余部分可能会用到(参看上边关于大小写敏感时的例子情?Q如Q?<BR>from eg.Cat as cat q里as可以省略?<BR><BR>上边只是单表查询Q多表的情况如下写法Q?<BR>from eg.Cat, eg.Dog <BR>from eg.Cat as cat, eg.Dog as dog <BR><BR>3。join相关 <BR>(inner) join <BR>left (outer) join <BR>right (outer) join <BR>full join <BR>HQL同样对SQL中的q些Ҏ支?<BR>下面插播一个小话题Q关于上边的那些Ҏ,我一直都没怎么用,今天既然说到q里Q就x上边的几个特性的用法说一下,也算对自q一个补充: <BR><BR>假设有两个表Q部门、员工,下面列D一些数据: <BR>员工(Employee)Q?<BR>ID Name DepNo <BR>001 Jplateau 01 <BR>002 Jony 01 <BR>003 Camel 02 <BR>部门(Department)Q?<BR>ID Name <BR>01 研发?<BR>02 营销?<BR><BR>在Hibernate中我们操U늚都是对象Q所以我们操U늚是部门类和员工类 <BR><BR><BR><BR><BR><BR>1).(inner) join <BR>select employee.ID as id1,employee.Name as name1, <BR>department.ID as id2,department.Name as name2 from Employee as employee <BR>join Department as department on employee.DepNo=department.ID (注意到条件语句我用on 没有用where) <BR>那么执行l果是什么呢Q?<BR>id1 name1 id2 name2 <BR>++++++++++++++++++++++++++++++++++++++ <BR>001 Jplateau 01 研发?<BR>002 Jony 01 研发?<BR><BR>2).left (outer) join <BR>select employee.ID as id1,employee.Name as name1,department.ID as id2,department.Name <BR>as name2 from Employee as employee left join Department as department on employee.DepNo= <BR>department.ID <BR>那么执行l果又该是什么呢Q?<BR>id1 name1 id2 name2 <BR>++++++++++++++++++++++++++++++++++++++ <BR>001 Jplateau 01 研发?<BR>002 Jony 01 研发?<BR>003 Camel null null <BR>{是说此时我要已W一个表的记录多ؓ准,W二个表中没有相应纪录的时候填充null} <BR>3). right (outer) join <BR>select employee.ID as id1,employee.Name as name1,department.ID as id2,department.Name <BR>as name2 from Employee as employee right join Department as department on employee.DepNo= <BR>department.ID <BR>那么执行l果又该是什么呢Q?<BR>id1 name1 id2 name2 <BR>++++++++++++++++++++++++++++++++++++++ <BR>001 Jplateau 01 研发?<BR>002 Jony 01 研发?<BR>null null 02 营销?<BR>{是说此时我要已W二个表的记录多ؓ准,W一个表中没有相应纪录的时候填充null} <BR><BR>4。select语句 <BR>是要确定你要从查询中返回哪些对象或者哪些对象的属性。写几个例子吧: <BR>select employee form Employee as employee <BR>select employee form Employee as employee where employee.Name like 'J%' <BR>select employee.Name form Employee as employee where employee.Name like 'J%' <BR>select employee.ID as id1,employee.Name as name1,department.ID as id2,department.Name <BR>as name2 from Employee as employee right join Department as department on employee.DepNo= <BR>department.ID <BR><BR>select elements(employee.Name) from Employee as employee <BR>Q不明白elements到底是做什么用的?望给于说明) <BR>{等 <BR><BR>5。数学函?<BR>JDO目前好像q不支持此类Ҏ?<BR>avg(...), sum(...), min(...), max(...) <BR><BR>count(*) <BR><BR>count(...), count(distinct ...), count(all...) <BR><BR>其用法和SQL基本相同 <BR><BR>select distinct employee.name from Employee as employee <BR>select count(distinct employee.name),count(employee) from Employee as employee <BR><BR>6。polymorphism (暂时不知道如何解释?) <BR>from com.test.Animal as animal <BR>不光得到所有Animal得实例,而且可以得到所有Animal的子c(如果我们定义了一个子cCatQ?<BR>一个比较极端的例子 <BR>from java.lang.Object as o <BR>可以得到所有持久类的实?<BR><BR>7。where语句 <BR>定义查询语句的条Ӟ丑և个例子吧Q?<BR>from Employee as employee where employee.Name='Jplateau' <BR>from Employee as employee where employee.Name like 'J%' <BR>from Employee as employee where employee.Name like '%u' <BR>在where语句中?”不光可以比较对象的属性,也可以比较对象,如: <BR>select animal from com.test.Animal as animal where animal.name=dog <BR><BR>8。表辑ּ <BR><BR>在SQL语句中大部分的表辑ּ在HQL中都可以使用Q?<BR>mathematical operators +, -, *, / <BR><BR>binary comparison operators =, >=, <=, <>, !=, like <BR><BR>logical operations and, or, not <BR><BR>string concatenation || <BR><BR>SQL scalar functions like upper() and lower() <BR><BR>Parentheses ( ) indicate grouping <BR><BR>in, between, is null <BR><BR>JDBC IN parameters ? <BR><BR>named parameters :name, :start_date, <IMG alt=Mad src="http://www.fankai.com/images/smiles/icon_mad.gif" border=0>1 Q这U应该是另一U??"的变通解x法) <BR><BR>SQL literals 'foo', 69, '1970-01-01 10:00:01.0' <BR><BR>Java public static final constants eg.Color.TABBY <BR><BR>其他不必解释了,在这里我只想Ҏ询中的参数问题说明一下: <BR>大家知道在SQL中进行传递参数进行查询的时候,我们通常用PreparedStatementQ在语句中写一大堆的“?”, <BR>在hql中也可以用这U方法,如: <BR>List mates = sess.find( <BR>"select employee.name from Employee as employee " + <BR>"where employee.Name=? ", <BR>name, <BR>Hibernate.STRING <BR>); <BR>(说明Q上面利用Session里的findҎQ在hibernate的api Session中重载了很多findҎQ它可以满你多UŞ式的查询) <BR>上边是一个参数的情ŞQ这U情况下紧接着引入参数和定义参数的cdQ当为多个参敎ͼ调用另一个findҎQ它的后两个 <BR>参数都是数组的Ş式?<BR><BR>q有另外一U方法来解决上边的问题,JDO也有q样的方法,不过和hibernate的表现Ş式上有差别,但他们两个骨子里却是 <BR>一LQ如Q?<BR>Query q = sess.createQuery("select employee.name from Employee as employee where employee.Name=:name"); <BR>q.setString("name", "Jplateau"); <BR>//当有多个参数的时候在此逐一定义 <BR>Iterator employees = q.iterate(); <BR><BR>9。order 语句 <BR>和sql语句没什么差别,如: <BR>select employee.name from Employee as employee where employee.Name like 'J%' order by employee.ID desc (或者asc) <BR><BR>10。group by 语句 <BR>同样和sql语句没什么差别,如: <BR><BR>select employee.name,employee.DepNo from Employee as employee group by employee.DepNo <BR><BR>select foo.id, avg( elements(foo.names) ), max( indices(foo.names) ) from eg.Foo foo group by foo.id <BR>{Note: You may use the elements and indices constructs inside a select clause, even on databases with no subselects.} <BR>谁帮我解释一下上边两句,谢过Q?<BR><BR>11。子查询 <BR>hibernate同样支持子查询,写几个例子: <BR><BR>from eg.Cat as fatcat where fatcat.weight > ( select avg(cat.weight) from eg.DomesticCat cat ) <BR><BR><SPAN style="COLOR: red">Q二Q条件查?/SPAN> <BR>Session osession = ownerSession.getSession(); <BR>Criteria criteria = osession.createCriteria(Owner.class); <BR>criteria.add(Expression.eq("age", new Integer(100))); <BR>criteria.setFirstResult(2); //从返回结果的W二条记录开始的5条记?<BR>criteria.setMaxResults(5); <BR>List lc=criteria.list(); <BR>System.out.println("条g查询"); <BR>System.out.println(lc.size()); <BR><BR><SPAN style="COLOR: red">Q三Q原生sql语句查询 </SPAN><BR>Query query=osession.createSQLQuery("select {owner.*} from Owner as owner", "owner", Owner.class); <BR>query.setMaxResults(4); <BR>List l=query.list(); <BR>System.out.println("原生sql语句查询"); <BR>System.out.println(l.get(0)); </FONT><BR></SPAN><img src ="http://m.tkk7.com/terry-zj/aggbug/21233.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2005-11-24 10:27 <a href="http://m.tkk7.com/terry-zj/archive/2005/11/24/21233.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate3主要的新Ҏ(转蝲Q?/title><link>http://m.tkk7.com/terry-zj/archive/2005/11/24/21232.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Thu, 24 Nov 2005 02:26:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2005/11/24/21232.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/21232.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2005/11/24/21232.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/21232.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/21232.html</trackback:ping><description><![CDATA[Hibernate3主要的新Ҏ包括:<BR><BR>1:实现了EJB3风格的持久化操作。在原有的saveOrUpdate()和saveOrUpdateCopy()两个Ҏ之外Q又提供了EJB3风格的create()和merge()两个操作?BR><BR>2:提供更强的映灵zL。允许将一个类映射到多张表Q允许؜合用“每个承体pM张表”和“每个子cM张表”的映射{略Q等{?BR><BR>3:支持存储q程和手写SQLQƈ且可以用手写SQL替代Hibernate自动生成的SQL语句?BR><BR>4:ZASTQ抽象语法树Q的HQL解析?BR><BR>5:字段U的懒式获取。每个属性都可以在映描q符中声明“lazy=true”,q样声明的属性会到真正用时才从数据库加载。不q,实现q项功能需要首先在~译期对字节码进行增强?BR><BR>具体Ҏ请讉K<A >http://www.hibernate.org/200.html</A><img src ="http://m.tkk7.com/terry-zj/aggbug/21232.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2005-11-24 10:26 <a href="http://m.tkk7.com/terry-zj/archive/2005/11/24/21232.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://m.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://864007.com" target="_blank">youjizz</a>| <a href="http://junyehome.com" target="_blank">av뾫Ʒ</a>| <a href="http://jmzc888.com" target="_blank">91޾Ʒ߹ۿ</a>| <a href="http://www77753.com" target="_blank">ѹվ߹ۿ </a>| <a href="http://avav2021.com" target="_blank">һëƬ޶</a>| <a href="http://my94ok.com" target="_blank">ձĻ</a>| <a href="http://mhysf.com" target="_blank">ձ߿</a>| <a href="http://ebanyou.com" target="_blank">˳ӰԺ߹ۿ</a>| <a href="http://www678678.com" target="_blank">91ѹۿ߹ۿ</a>| <a href="http://by6174.com" target="_blank">þù޹ۿ</a>| <a href="http://qestest.com" target="_blank">51ƷƵѹר</a>| <a href="http://bdykdq.com" target="_blank">Ʒ߲ҳ</a>| <a href="http://www-282555.com" target="_blank">ëƬƵվۿ</a>| <a href="http://qestest.com" target="_blank">޾ƷĻAƬ</a>| <a href="http://wwwaa875.com" target="_blank">ڵƵ</a>| <a href="http://btztjxc.com" target="_blank">ϸëƬ</a>| <a href="http://sd-ll.com" target="_blank">޾Ʒ2345</a>| <a href="http://1408600.com" target="_blank">պƷרѲ</a>| <a href="http://fuhui123.com" target="_blank">ŷ߲</a>| <a href="http://zjfxjy.com" target="_blank">ɫ˿߹ۿ</a>| <a href="http://caoliushequ9.com" target="_blank">ޱ龫Ʒһ</a>| <a href="http://hbtelong.com" target="_blank">޾Ʒ岻</a>| <a href="http://fuhui123.com" target="_blank">޳avѿ</a>| <a href="http://t66p.com" target="_blank">޹Ů޹</a>| <a href="http://www4438xx2.com" target="_blank">ɫɫWWW</a>| <a href="http://ksdhao.com" target="_blank">Ůѹۿվ</a>| <a href="http://cdhxfj.com" target="_blank">޹ƷSSS߹ۿAV</a>| <a href="http://tzfzs.com" target="_blank">þwwƷw˳</a>| <a href="http://www-774220.com" target="_blank">޾ƷĻ</a>| <a href="http://3x79.com" target="_blank">˳wwwþþ</a>| <a href="http://woaianli.com" target="_blank">ÿµavƬ߹ۿ</a>| <a href="http://1992zyzp.com" target="_blank">պƷר</a>| <a href="http://arkinbokis.com" target="_blank">ۺ˾þۺ</a>| <a href="http://88533066.com" target="_blank">2020þþƷ</a>| <a href="http://56v6.com" target="_blank">ŮƵaƵȫվɫ</a>| <a href="http://binz132.com" target="_blank">޵Ӱһ</a>| <a href="http://vv848.com" target="_blank">AƵվ</a>| <a href="http://saohu533.com" target="_blank">aƬѿ</a>| <a href="http://www19977.com" target="_blank">ۺһ뾫Ʒ</a>| <a href="http://vastraje.com" target="_blank">͵v͵v޸</a>| <a href="http://yygcui.com" target="_blank">ѵվ߹ۿ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>