2008年4月22日

前次,我曾经介绍过可以通过使用JRBeanCollectionDataSource()返回一个JRDataSource,当时javabean 的数据类型都是原始类型,不曾碰到过使用集合类的复合javabean。这次考虑仍然使用javabean 来构造数据源,由于对ireport的datasource的处理机制不是很熟悉,经过很多次尝试后才摸索出一个往子报表插入特定数据源的办法(不是传递父报表的数据源,而是将父报表的一个变量当成数据源传递给子报表!)

DEMO:

准备工作:

一、程序准备:

1、 创建复合javabean :MainVO.java:(getter和setter方法自写)

 

package com.test;

import java.util.List;

public class MainVO {

    private String title;

    private String time;

    private List<SubVO> subList;

}

 

2、 创建子表javabean:SubVO.java(getter和setter方法自写)

 

package com.test;

public class SubVO {

private String name;

 

3、 创建JRAbstractBeanDataSourceProvider:TestSubReport.java

 

package com.test;

public class TestSubReport extends JRAbstractBeanDataSourceProvider {

    public TestSubReport() {

       super(MainVO.class);

    }

    public JRDataSource create(JasperReport arg0) throws JRException {

       /**

       *测试数据,在使用中,不需要继承JRAbstractBeanDataSourceProvider,

       *只需要把集合类封装到JRBeanCollectionDataSource中就可以了

       **/

       List<MainVO> mainList = new ArrayList<MainVO>();

        List<SubVO> list = new ArrayList<SubVO>();

       MainVO vo;

        /**测试数据自写*/

        ……

       return new JRBeanCollectionDataSource(mainList);

    }

 

4、 创建外部测试类:TestMain.java:

 

public static void main(String[] args) {

String filename = "bin/SubReport.jasper";

String outFileName = "bin/Out.html";

/**测试数据mainList自写*/

try {

JasperPrint print = JasperFillManager.fillReport(filename, new HashMap(),new JRBeanCollectionDataSource(mainList));

    JRExporter exporter = new JRHtmlExporter();

     exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME,          outFileName);

    exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);

    exporter.exportReport();

       } catch (JRException e) {

           e.printStackTrace();

       }

    }

 

5、 创建Scriptlet:reportScriptlet.java

注意: 如果你从父报表传给子报表的数据源是个集合类型,且不需要任何的数据处理,这步可以省略,但需要注意我在第二部分的第7步骤的提示。

该类是用来进行类型转换的,要想让jasperreports识别数据源就必须把集合类封装到JRDataSource中。由于父报表把数据源传递给子报表是在afterDetailEval()方法之后,因此只需要重写该方法:

 

package com.test;

public class reportScriptlet extends JRAbstractScriptlet {

    /**其余方法省略*/

    @Override

    public void afterDetailEval() throws JRScriptletException {

       System.out.println("afterDetailEval...");

       List subList = (List)getFieldValue("subList");

       JRDataSource jr = new JRBeanCollectionDataSource(subList);

       /**

       *该值是在父报表中定义的一个变量Variables,

       *类型为net.sf.jasperreports.engine.JRDataSource

         *(需要手动填写Class Type)

       **/

         setVariableValue("other", jr);

    }

}

 

     该Scriptlet供父报表使用

二、报表准备

       由于ireport的汉化很不完整,这里就使用英文的界面做demo(有兴趣汉化的,可以编辑位于ireport.jar包的it.businesslogic.ireport.locale下的Ireport_zh_CN.properties)。

1、 创建父报表:SubReport.jrxml,通过菜单栏:Data -->Connections /Datasources -->new选择JRDataSourceProvider定义如图:

利用复合的javabean构造基于jasperreports的子报表(转) - 涸辙之鱼 - 涸辙之鱼

                       Test 成功后(前提是先在ireport的classpath中设置工程编译文件夹路径)save。

2、 设置另一个数据源(给子报表用)在这里我选择了使用Custom JRDataSource

利用复合的javabean构造基于jasperreports的子报表(转) - 涸辙之鱼 - 涸辙之鱼

                    使用Custom JRDataSource这里我必须在项目中编写一个额外的类用于测试:

         

 

package com.test;

public class CRDSFactory{

    public static JRDataSource createDatasource(){

    List<SubVO> list = new ArrayList<SubVO> ();

    /**测试数据自写*/

        ……

    return new JRBeanCollectionDataSource(list);

    }

}

 

                     Test 成功后 save。

3、 注册字段Fileld

利用菜单中的Data --> Report Query -->DataSource Provider 获取字段,然后全选获取到的字段点击确认注册。

利用复合的javabean构造基于jasperreports的子报表(转) - 涸辙之鱼 - 涸辙之鱼

     

4、 添加变量Variables

该变量用途是作为父报表传递给子报表的数据源,所以类型为JRDataSource

                    如图:

利用复合的javabean构造基于jasperreports的子报表(转) - 涸辙之鱼 - 涸辙之鱼

5、 创建子报表: SubReport_subreport0.jrxml,(名字由系统生成) 点击工具栏中的”SubReport”图标,并确定好子报表的位置,利用系统的wizard一步一步设置,注意在第2步设置”Connection/Datasource ”时最好选择”no connection or datasource”,因为我们的datasource是父报表中的一个变量)

6、 将ireport的Files视窗的其他报表文件关闭(大概需要这样,前几次因为没关闭出了点问题,不清楚什么原因)如果看不到Files视窗,可以通过菜单的View --> Docking panes -->Files 回显。单独选择刚才为该子报表而设置的数据源“custds”,通过刚才的Report Query -->JavaBean Data Source读取子报表相关的javabean属性。选择后点ok将其注册到Fields中。如图:

利用复合的javabean构造基于jasperreports的子报表(转) - 涸辙之鱼 - 涸辙之鱼

7、 打开父报表,在设计窗口的子报表上右键,选择Properties -->SubReport,设置由父报表传递给子报表的数据源:

         

利用复合的javabean构造基于jasperreports的子报表(转) - 涸辙之鱼 - 涸辙之鱼

                  提示:如果你略过了第一部分的第5步,这里的“ $V{other} ”要改成“ new  net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($V{other})”

8、 依次编译(使用动态连接)子报表、父报表(注意数据源的对应关系),如果能通过父报表看到子报表的内容被填充,则说明测试成功了!如果不成功,检查刚才设置是否有遗漏的地方,最好重新创建子报表,有时并不是我们设置问题,ireport目前还不是很稳定,在编译和保存数据时很容易出错,有时连子报表都不认-_-!!

9、

                   效果图:(没有修饰,确实很难看…)

          

利用复合的javabean构造基于jasperreports的子报表(转) - 涸辙之鱼 - 涸辙之鱼

                 注意事项:

?        熟悉jaspereports的以手动编辑代码为主, ireport为辅,使用ireport时有时也必须手动编辑jasperreport,特别是在编译出错的时候。

?       不能把父报表的一个变量同时传递给多个子报表,不然可能只能显示一个或什么都不显示,如果需要这么做,请定义多个变量。

?      子报表的添加不要用旧报表,即使你的旧报表是刚才使用的子报表。

?      如果子报表还要嵌套子报表的话,可以通过为子报表编写一个Scriptlet实现。

                                    不过要清楚的是子报表有可能不执行afterDetailEval()和beforeDetailEval()(比如使用jdbc连 接,这也许跟子报表的数据源选择有关),最好先测试,具体原因希望达人告知!

?     在使用ireport进行开发时,当修改了某个类时,就需要重启ireport才能看到修改的效果,即使是使用ireport的Scriptlet编辑器也一样。

?     不是越高版本越好用,主要是缺少使用文档,连javadoc

posted @ 2009-09-29 09:01 caihaibo 阅读(1412) | 评论 (0)编辑 收藏
查看被锁的表

select   p.spid,a.serial#, c.object_name,b.session_id,b.oracle_username,b.os_user_name   from   v$process   p,v$session   a,   v$locked_object   b,all_objects   c   where   p.addr=a.paddr   and   a.process=b.process   and   c.object_id=b.object_id  




查看连接的进程

SELECT sid, serial#, username, osuser FROM v$session;




杀掉进程

alter   system     kill   session   'sid,serial#';
posted @ 2009-08-18 15:22 caihaibo 阅读(242) | 评论 (0)编辑 收藏
修改bin下的catalina.bat中的java_home
posted @ 2009-08-17 14:26 caihaibo 阅读(203) | 评论 (0)编辑 收藏

 

严重: IOException while loading persisted sessions: java.io.EOFException

java.io.EOFException

at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2281)

at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2750)

at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:780)

at java.io.ObjectInputStream.<init>(ObjectInputStream.java:280)

at org.apache.catalina.util.CustomObjectInputStream.<init>(CustomObjectInputStream.java:58)

at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:362)

at org.apache.catalina.session.StandardManager.load(StandardManager.java:321)

at org.apache.catalina.session.StandardManager.start(StandardManager.java:637)

at org.apache.catalina.core.ContainerBase.setManager(ContainerBase.java:438)

at org.apache.catalina.core.StandardContext.start(StandardContext.java:4271)

at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)

at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)

at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)

at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:926)

at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:889)

at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)

at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)

at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)

at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)

at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)

at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)

at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)

at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)

at org.apache.catalina.core.StandardService.start(StandardService.java:516)

at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)

at org.apache.catalina.startup.Catalina.start(Catalina.java:578)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)

at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)

2008-10-21 15:18:18 org.apache.catalina.session.StandardManager start

严重: Exception loading sessions from persistent storage

java.io.EOFException

at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2281)

at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2750)

at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:780)

at java.io.ObjectInputStream.<init>(ObjectInputStream.java:280)

at org.apache.catalina.util.CustomObjectInputStream.<init>(CustomObjectInputStream.java:58)

at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:362)

at org.apache.catalina.session.StandardManager.load(StandardManager.java:321)

at org.apache.catalina.session.StandardManager.start(StandardManager.java:637)

at org.apache.catalina.core.ContainerBase.setManager(ContainerBase.java:438)

at org.apache.catalina.core.StandardContext.start(StandardContext.java:4271)

at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)

at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)

at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)

at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:926)

at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:889)

at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)

at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)

at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)

at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)

at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)

at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)

at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)

at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)

at org.apache.catalina.core.StandardService.start(StandardService.java:516)

at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)

at org.apache.catalina.startup.Catalina.start(Catalina.java:578)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

at java.lang.reflect.Method.invoke(Method.java:597)

at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)

at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)

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

出现原因:tomcat对保存硬盘的session读取失败

解决方法:打开TOMCAT的安装目录,在WORK文件夹找到当前项目文件夹,把里面的session.ser删除即可。

posted @ 2009-08-03 09:25 caihaibo 阅读(361) | 评论 (0)编辑 收藏
Preferences->General -> Editors -> Text Editors
posted @ 2009-07-31 09:50 caihaibo 阅读(644) | 评论 (0)编辑 收藏
internet选项——常规——设置——Internet·临时文件 (检查网页的较新版本)选中每次访问网页时
posted @ 2009-07-31 09:44 caihaibo 阅读(417) | 评论 (0)编辑 收藏

10g 10.2.1.0 

select * from dba_roles;

CONNECT                                                               创建session角色
RESOURCE                                                            创建资源角色,Create table 等等
DBA                                                                           数据库管理员角色
SELECT_CATALOG_ROLE                                 查看数据字典角色
EXECUTE_CATALOG_ROLE                              执行数据字典中部分函数的角色
DELETE_CATALOG_ROLE                                 删除sys.adu$记录的角色
EXP_FULL_DATABASE                                        全库导出角色
IMP_FULL_DATABASE                                         全库导入角色
RECOVERY_CATALOG_OWNER                      备份目录的拥有者 RMAN使用    
GATHER_SYSTEM_STATISTICS      
LOGSTDBY_ADMINISTRATOR         
AQ_ADMINISTRATOR_ROLE                             高级队列管理员角色
AQ_USER_ROLE                                                  高级队列使用者角色
GLOBAL_AQ_USER_ROLE              
SCHEDULER_ADMIN                                           调度管理者角色
HS_ADMIN_ROLE                                
AUTHENTICATEDUSER                    
OEM_ADVISOR                                    
OEM_MONITOR                                   
WM_ADMIN_ROLE                               
JAVAUSERPRIV                                   
JAVAIDPRIV                    
JAVASYSPRIV                   
JAVADEBUGPRIV                 
EJBCLIENT                     
JAVA_ADMIN                    
JAVA_DEPLOY                   
CTXAPP                        
XDBADMIN                      
XDBWEBSERVICES               
OLAP_DBA                      
OLAP_USER                     
MGMT_USER                     

 

posted @ 2008-12-11 16:12 caihaibo 阅读(1632) | 评论 (0)编辑 收藏

Mysql
************************************
当前列  ClassName    ColumnType  DisplaySize  TypeName
0:
  java.lang.Integer  ColumnType:4  11  INTEGER
1:
  java.lang.Integer  ColumnType:-6  4  TINYINT
2:
  java.lang.String  ColumnType:12  0  UNKNOWN
3:
  java.lang.Boolean  ColumnType:-7  1  TINYINT
4:
  java.lang.Integer  ColumnType:5  6  SMALLINT
5:
  java.lang.Integer  ColumnType:4  9  MEDIUMINT
6:
  java.lang.Integer  ColumnType:4  11  INTEGER
7:
  java.lang.Long    ColumnType:-5  20  BIGINT
8:
  java.lang.Double  ColumnType:8  22  DOUBLE
9:
  java.lang.Double  ColumnType:8  22  DOUBLE
10:
  java.lang.Float    ColumnType:7  12  FLOAT
11:
  java.lang.String  ColumnType:12  11  UNKNOWN
12:
  java.lang.String  ColumnType:12  11  UNKNOWN
13:
  java.lang.String  ColumnType:1  300  CHAR
14:
  java.lang.String  ColumnType:12  300  VARCHAR
15:
  java.sql.Date    ColumnType:91  10  DATE
16:
  java.sql.Time    ColumnType:92  8  TIME
17:
  java.sql.Date    ColumnType:91  4  YEAR
18:
  java.sql.Timestamp  ColumnType:93  19  TIMESTAMP
19:
  java.sql.Timestamp  ColumnType:93  19  DATETIME
20:
  [B      ColumnType:-3  255  TINYBLOB
21:
  [B      ColumnType:-4  65535  BLOB
22:
  [B      ColumnType:-4  16777215  MEDIUMBLOB
23:
  [B      ColumnType:-4  -1  BLOB
24:
  java.lang.String  ColumnType:12  255  TINYBLOB
25:
  java.lang.String  ColumnType:-1  65535  TEXT
26:
  java.lang.String  ColumnType:-1  16777215  MEDIUMBLOB
27:
  java.lang.String  ColumnType:-1  -1  TEXT
28:
  java.lang.String  ColumnType:1  3  CHAR
29:
  java.lang.String  ColumnType:1  3  CHAR

posted @ 2008-12-09 18:57 caihaibo 阅读(365) | 评论 (0)编辑 收藏
mysql安装出现cannot start the service 错误 有可能是因为以前安装的文件夹还存在,删除以前安装的文件夹,再安装ok
posted @ 2008-12-09 18:53 caihaibo 阅读(2031) | 评论 (0)编辑 收藏
你的系统是否最近出现过下图所示的情况呢?


=800) window.open('http://www.91kb.cn/attachment/Mon_0811/7_3836_d3527d6e31ec185.jpg');" src="http://www.91kb.cn/attachment/Mon_0811/7_3836_d3527d6e31ec185.jpg" onload="if(this.width>'800')this.width='800';" border=0>

=800) window.open('http://www.91kb.cn/attachment/Mon_0811/7_3836_b04e7433c85c56a.jpg');" src="http://www.91kb.cn/attachment/Mon_0811/7_3836_b04e7433c85c56a.jpg" onload="if(this.width>'800')this.width='800';" border=0>

杀毒查不出来,系统还原,重装系统均无效,什么原因?原来罪魁祸首是因为系统漏洞所致.
1024日,微软系统爆出2008年最大的安全漏洞(MS08-067),影响包括Windows XP SP3Windows 2000Windows Server 2003Windows Vista等几乎所有主流操作系统。黑客可以利用此漏洞发动大规模远程攻击,实际效果可与“冲击波”、“震荡波”等病毒类似。
本人前两天也深受其害,不能上网,后来打上这个补丁后解决问题.现将解决方法公布如下:
1.去微软下载MS08-067的安全更新,地址:http://www.microsoft.com/downloads/details.aspx?familyid=0D5F9B6E-9265-44B9-A376-2067B73D6A03&displaylang=zh-cn (:盗版软件也可以下,不会受微软黑屏影响,本人电脑就是用此方法解决好的)


  2.利用第三方软件,如瑞星卡卡,360安全卫士,QQ医生等下载系统漏洞补丁.只用下载MS08-067的即可.
posted @ 2008-12-04 21:13 caihaibo 阅读(688) | 评论 (0)编辑 收藏
错误信息:
Exception in thread "main" org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update
原因与解决:
1.因为Hibernate Tools(或者Eclipse本身的Database Explorer)生成*.hbn.xml工具中包含有catalog="***"(*表示数据库名称)这样的属性,将该属性删除就可以了
2.估计是你的列名里面有关键字的原因吧,命名列的时候不要单独使用date,ID...这种关键字 

Hibernate查询时候的问题。
莫名其妙地报如下的错误,
org.hibernate.exception.GenericJDBCException: could not execute query

最后把mysql的驱动程序 从 mysql-connector-java-3.2.0-alpha改成mysql-connector-java-5.0.4就可以了。

posted @ 2008-12-03 22:02 caihaibo 阅读(608) | 评论 (0)编辑 收藏
Hibernate入门 - 基础配置

作者:robbin (MSN:robbin_fan AT hotmail DOT com)

版权声明:本文严禁转载,如有转载请求,请和作者联系

Hibernate配置文件可以有两种格式,一种是 hibernate.properties ,另一种是 hibernate.cfg.xml

后者稍微方便一些,当增加hbm映射文件的时候,可以直接在 hibernate.cfg.xml 里面增加,不必像 hibernate.properties 必须在初始化代码中加入。

但不管怎么说,两种的配置项都是一样的,下面详细介绍:

在Hibernate的src目录下有一个 hibernate.properties 模板,我们不必自己从头写,修改模板就可以了:)


hibernate.query.substitutions true 1, false 0, yes 'Y', no 'N'

这个配置意思是当你在Hibernate里面输入true的时候,Hibernate会转化为1插入数据库,当你在Hibernate里面输入false的时候,Hibernate会转化为0插入数据库,后面的Y,N同理。

对于某些数据库,例如Oracle来说,没有boolean数据类型,就是采用1代表true,0代表false,因此使用这个配置在Hibernate里面直接用true/false会非常直观。


hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class com.mysql.jdbc.Driver
hibernate.connection.url jdbc:mysql:///test
hibernate.connection.username root
hibernate.connection.password

这是一个连接MySQL数据库的例子,很直观,不必解释,不同的数据库的连接参数模板中全部给出了。
对于某些数据库,例如Oracle来说,没有boolean数据类型,就是采用1代表true,0代表false,因此使用这个配置在Hibernate里面直接用true/false会非常直观。


hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class com.mysql.jdbc.Driver
hibernate.connection.url jdbc:mysql:///test
hibernate.connection.username root
hibernate.connection.password

这是一个连接MySQL数据库的例子,很直观,不必解释,不同的数据库的连接参数模板中全部给出了。
如果你不是在App Server环境中使用Hibernate,例如远程客户端程序,但是你又想用App Server的数据库连接池,那么你还需要配置JNDI的参数,例如Hibernate连接远程Weblogic上的数据库连接池:

hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
hibernate.connection.datasource mypool
hibernate.connection.provider_class net.sf.hibernate.connection.DatasourceConnectionProvider
hibernate.jndi.class weblogic.jndi.WLInitialContextFactory
hibernate.jndi.url t3://servername:7001/


最后,如果你需要在EJB或者JTA中使用Hibernate,需要取消下行的注释:

hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory

杂项配置:


hibernate.show_sql false

是否将Hibernate发送给数据库的sql显示出来,这是一个非常非常有用处的功能。当你在调试Hibernate的时候,让Hibernate打印sql语句,可以帮助你迅速解决问题。


#hibernate.connection.isolation 4

指定数据库的隔离级别,往往不同的数据库有自己定义的隔离级别,未必是Hibernate的设置所能更改的,所以也不必去管它了。

hibernate.jdbc.fetch_size 50
hibernate.jdbc.batch_size 25

这两个选项非常非常非常重要!!!将严重影响Hibernate的CRUD性能!

C = create, R = read, U = update, D = delete

Fetch Size 是设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数。

例如一次查询1万条记录,对于Oracle的JDBC驱动来说,是不会1次性把1万条取出来的,而只会取出Fetch Size条数,当纪录集遍历完了这些记录以后,再去数据库取Fetch Size条数据。

因此大大节省了无谓的内存消耗。当然Fetch Size设的越大,读数据库的次数越少,速度越快;Fetch Size越小,读数据库的次数越多,速度越慢。

这有点像平时我们写程序写硬盘文件一样,设立一个Buffer,每次写入Buffer,等Buffer满了以后,一次写入硬盘,道理相同。

Oracle 数据库的JDBC驱动默认的Fetch Size=10,是一个非常保守的设定,根据我的测试,当Fetch Size=50的时候,性能会提升1倍之多,当Fetch Size=100,性能还能继续提升20%,Fetch Size继续增大,性能提升的就不显著了。

因此我建议使用Oracle的一定要将Fetch Size设到50。

不过并不是所有的数据库都支持Fetch Size特性,例如MySQL就不支持。

MySQL就像我上面说的那种最坏的情况,他总是一下就把1万条记录完全取出来,内存消耗会非常非常惊人!这个情况就没有什么好办法了 :(

Batch Size是设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,有点相当于设置Buffer缓冲区大小的意思。

Batch Size越大,批量操作的向数据库发送sql的次数越少,速度就越快。我做的一个测试结果是当Batch Size=0的时候,使用Hibernate对Oracle数据库删除1万条记录需要25秒,Batch Size = 50的时候,删除仅仅需要5秒!!!

可见有多么大的性能提升!很多人做Hibernate和JDBC的插入性能测试会奇怪的发现Hibernate速度至少是JDBC的两倍,就是因为Hibernate使用了Batch Insert,而他们写的JDBC没有使用Batch的缘故。

以我的经验来看,Oracle数据库 Batch Size = 30 的时候比较合适,50也不错,性能会继续提升,50以上,性能提升的非常微弱,反而消耗内存更加多,就没有必要了。


#hibernate.jdbc.use_scrollable_resultset true

设定是否可以使用JDBC2.0规范的可滚动结果集,这对Hibernate的分页显示有一定的作用,默认就好了。


#hibernate.cglib.use_reflection_optimizer false

默认打开,启用cglib反射优化。cglib是用来在Hibernate中动态生成PO字节码的,打开优化可以加快字节码构造的速度。

不过,当你在调试程序过程中,特别是和proxy,lazy loading相关的应用中,代码出错,但是出错提示信息有语焉不详,那么你可以把cglib优化关掉,这样Hibernate会输出比较详细的调试信息,帮助你debug。

Hibernate一共包括了23个jar包,令人眼花缭乱。本文将详细讲解Hibernate每个jar包的作用,便于你在应用中根据自己的需要进行取舍。

下载Hibernate,例如2.0.3稳定版本,解压缩,可以看到一个hibernate2.jar和lib目录下有22个jar包:

hibernate2.jar:
Hibernate的库,没有什么可说的,必须使用的jar包

cglib-asm.jar:
CGLIB库,Hibernate用它来实现PO字节码的动态生成,非常核心的库,必须使用的jar包

dom4j.jar:
dom4j 是一个Java的XML API,类似于jdom,用来读写XML文件的。dom4j是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件,可以在SourceForge上找到它。在IBM developerWorks上面可以找到一篇文章,对主流的Java XML API进行的性能、功能和易用性的评测,dom4j无论在那个方面都是非常出色的。我早在将近两年之前就开始使用dom4j,直到现在。如今你可以看到越来越多的Java软件都在使用dom4j来读写XML,特别值得一提的是连Sun的JAXM也在用dom4j。这是必须使用的jar 包,Hibernate用它来读写配置文件。

odmg.jar:
ODMG是一个ORM的规范,Hibernate实现了ODMG规范,这是一个核心的库,必须使用的jar包。

commons-collections.jar:
Apache Commons包中的一个,包含了一些Apache开发的集合类,功能比java.util.*强大。必须使用的jar包。

commons-beanutils.jar:
Apache Commons包中的一个,包含了一些Bean工具类类。必须使用的jar包。

commons-lang.jar:
Apache Commons包中的一个,包含了一些数据类型工具类,是java.lang.*的扩展。必须使用的jar包。

commons-logging.jar:
Apache Commons包中的一个,包含了日志功能,必须使用的jar包。这个包本身包含了一个Simple Logger,但是功能很弱。在运行的时候它会先在CLASSPATH找log4j,如果有,就使用log4j,如果没有,就找JDK1.4带的 java.util.logging,如果也找不到就用Simple Logger。commons-logging.jar的出现是一个历史的的遗留的遗憾,当初Apache极力游说Sun把log4j加入JDK1.4,然而JDK1.4项目小组已经接近发布JDK1.4产品的时间了,因此拒绝了Apache的要求,使用自己的java.util.logging,这个包的功能比log4j差的很远,性能也一般。后来Apache就开发出来了commons-logging.jar用来兼容两个logger。因此用 commons-logging.jar写的log程序,底层的Logger是可以切换的,你可以选择log4j,java.util.logging或者它自带的Simple Logger。不过我仍然强烈建议使用log4j,因为log4j性能很高,log输出信息时间几乎等于System.out,而处理一条log平均只需要5us。你可以在Hibernate的src目录下找到Hibernate已经为你准备好了的log4j的配置文件,你只需要到Apache 网站去下载log4j就可以了。commons-logging.jar也是必须的jar包。

使用Hibernate必须的jar包就是以上的这几个,剩下的都是可选的。

ant.jar:
Ant编译工具的jar包,用来编译Hibernate源代码的。如果你不准备修改和编译Hibernate源代码,那么就没有什么用,可选的jar包

optional.jar:
Ant的一个辅助包。

c3p0.jar:
C3PO是一个数据库连接池,Hibernate可以配置为使用C3PO连接池。如果你准备用这个连接池,就需要这个jar包。

proxool.jar:
也是一个连接池,同上。

commons-pool.jar, commons-dbcp.jar:
DBCP数据库连接池,Apache的Jakarta组织开发的,Tomcat4的连接池也是DBCP。

实际上Hibernate自己也实现了一个非常非常简单的数据库连接池,加上上面3个,你实际上可以在Hibernate上选择4种不同的数据库连接池,选择哪一个看个人的偏好,不过DBCP可能更通用一些。另外强调一点,如果在EJB中使用Hibernate,一定要用App Server的连接池,不要用以上4种连接池,否则容器管理事务不起作用。

connector.jar:
JCA 规范,如果你在App Server上把Hibernate配置为Connector的话,就需要这个jar。不过实际上一般App Server肯定会带上这个包,所以实际上是多余的包。

jaas.jar:
JAAS是用来进行权限验证的,已经包含在JDK1.4里面了。所以实际上是多余的包。

jcs.jar:
如果你准备在Hibernate中使用JCS的话,那么必须包括它,否则就不用。

jdbc2_0-stdext.jar:
JDBC2.0的扩展包,一般来说数据库连接池会用上它。不过App Server都会带上,所以也是多余的。

jta.jar:
JTA规范,当Hibernate使用JTA的时候需要,不过App Server都会带上,所以也是多余的。

junit.jar:
Junit包,当你运行Hibernate自带的测试代码的时候需要,否则就不用。

xalan.jar, xerces.jar, xml-apis.jar:
Xerces 是XML解析器,Xalan是格式化器,xml-apis实际上是JAXP。一般App Server都会带上,JDK1.4也包含了解析器,不过不是Xerces,是Crimson,效率比较差,不过Hibernate用XML只不过是读取配置文件,性能没什么紧要的,所以也是多余的。

Hibernate 是对JDBC的轻量级对象封装,Hibernate本身是不具备Transaction处理功能的,Hibernate的Transaction实际上是底层的JDBC Transaction的封装,或者是JTA Transaction的封装,下面我们详细的分析:

Hibernate可以配置为JDBCTransaction或者是JTATransaction,这取决于你在hibernate.properties中的配置:

#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory

如果你什么都不配置,默认情况下使用JDBCTransaction,如果你配置为:

hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory

将使用JTATransaction

不管你准备让Hibernate使用JDBCTransaction,还是JTATransaction,我的忠告就是什么都不配,将让它保持默认状态,如下:

#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory

在下面的分析中我会给出原因。

一、JDBC Transaction

看看使用JDBC Transaction的时候我们的代码例子:

Session session = sf.openSession();
Transaction tx = session.beginTransactioin();
...
session.flush();
tx.commit();
session.close();

这是默认的情况,当你在代码中使用Hibernate的Transaction的时候实际上就是JDBCTransaction。那么JDBCTransaction究竟是什么东西呢?来看看源代码就清楚了:

Hibernate2.0.3源代码中的类

net.sf.hibernate.transaction.JDBCTransaction:

public void begin() throws HibernateException {
   
...
        if (toggleAutoCommit) session.connection().setAutoCommit(false);
...
}

这是启动Transaction的方法,看到 connection().setAutoCommit(false) 了吗?是不是很熟悉?

再来看

public void commit() throws HibernateException {  
...
    try {
        if ( session.getFlushMode()!=FlushMode.NEVER ) session.flush();
        try {
            session.connection().commit();
            committed = true;
        }
...
    toggleAutoCommit();
}


这是提交方法,看到connection().commit() 了吗?下面就不用我多说了,这个类代码非常简单易懂,通过阅读使我们明白Hibernate的Transaction都在干了些什么?我现在把用 Hibernate写的例子翻译成JDBC,大家就一目了然了:

Connection conn = ...;         <---   session = sf.openSession();

conn.setAutoCommit(false);     <---   tx = session.beginTransactioin();

...                            <---   ...

conn.commit();                 <---   tx.commit(); (对应左边的两句)
conn.setAutoCommit(true);

conn.close();                  <---   session.close();

看明白了吧,Hibernate的JDBCTransaction根本就是conn.commit而已,根本毫无神秘可言,只不过在Hibernate 中,Session打开的时候,就会自动conn.setAutoCommit(false),不像一般的JDBC,默认都是true,所以你最后不写 commit也没有关系,由于Hibernate已经把AutoCommit给关掉了,所以用Hibernate的时候,你在程序中不写 Transaction的话,数据库根本就没有反应。


JTATransaction

如果你在EJB中使用Hibernate,或者准备用JTA来管理跨Session的长事务,那么就需要使用JTATransaction,先看一个例子:

javax.transaction.UserTransaction tx = new InitialContext().lookup("javax.transaction.UserTransaction");

Session s1 = sf.openSession();
...
s1.flush();
s1.close();

...

Session s2 = sf.openSession();
...
s2.flush();
s2.close();

tx.commit();

这是标准的使用JTA的代码片断,Transaction是跨Session的,它的生命周期比Session要长。如果你在EJB中使用 Hibernate,那么是最简单不过的了,你什么Transaction代码统统都不要写了,直接在EJB的部署描述符上配置某某方法是否使用事务就可以了。

现在我们来分析一下JTATransaction的源代码, net.sf.hibernate.transaction.JTATransaction:

public void begin(InitialContext context, ...
  ...
  ut = (UserTransaction) context.lookup(utName);
  ...

看清楚了吗? 和我上面写的代码 tx = new (Initial Context)().lookup("javax.transaction.UserTransaction"); 是不是完全一样?

public void commit() ...
  ...
  if (newTransaction) ut.commit();
  ...


JTATransaction的控制稍微复杂,不过仍然可以很清楚的看出来Hibernate是如何封装JTA的Transaction代码的。

但是你现在是否看到了什么问题? 仔细想一下,Hibernate Transaction是从Session中获得的,tx = session.beginTransaction(),最后要先提交tx,然后再session.close,这完全符合JDBC的 Transaction的操作顺序,但是这个顺序是和JTA的Transactioin操作顺序彻底矛盾的!!! JTA是先启动Transaction,然后启动Session,关闭Session,最后提交Transaction,因此当你使用JTA的 Transaction的时候,那么就千万不要使用Hibernate的Transaction,而是应该像我上面的JTA的代码片断那样使用才行。
总结:
1、在JDBC上使用Hibernate

必须写上Hibernate Transaction代码,否则数据库没有反应。此时Hibernate的Transaction就是Connection.commit而已

2、在JTA上使用Hibernate

写JTA的Transaction代码,不要写Hibernate的Transaction代码,否则程序会报错

3、在EJB上使用Hibernate

什么Transactioin代码都不要写,在EJB的部署描述符里面配置

|---CMT(Container Managed Transaction)
|
|---BMT(Bean Managed Transaction)
        |
        |----JDBC Transaction
        |
        |----JTA Transaction
 
posted @ 2008-12-03 18:11 caihaibo 阅读(250) | 评论 (0)编辑 收藏
原文出处:http://www.blogjava.net/Andyluo/archive/2006/10/06/73584.html
         在MySQL里创建外键时(Alter table xxx add constraint fk_xxx foreign key),提示错误,但只提示很简单的信息:ERROR 1005 (HY000): Can't create table '.\env_mon\#sql-698_6.frm' (errno: 150)。根本起不到解决问题的作用。

要看错误的详细提示,可以使用命令:(在MySQL Manual里搜索“errno 150”时找到)

SHOW ENGINE INNODB STATUS;     //针对用INNODB存储方式的数据库

在信息中有一组【LATEST FOREIGN KEY ERROR】会有最近错误的详细描述和解决办法。
如:
Cannot find an index in the referenced table where the referenced columns appear as the first columns, or column types in the table and the referenced table do not match for constraint.
(译:不能在“被reference的表”里找到包含“被reference字段”的索引,或者是两个关联字段类型不匹配)

(我犯的错误是没有在主表中设置主键-_-!,即第一种原因)

呵呵,今天建数据库等时出的错误是由第二种原因引起,即两个关联字段类型不匹配,万能的互联网啊。。。。。。
posted @ 2008-12-02 21:25 caihaibo 阅读(150) | 评论 (0)编辑 收藏
 HSQLDB是一个开放源代码的JAVA数据库,具有标准的SQL语法和JAVA接口。HSQLDB可以自由使用和分发,具有内存数据库,独立数据库和客户-服务器三种数据库模式。本文介绍客户-服务器模式的配置。 

    从HSQLDB主页上下载HSQLDB:

    http://hsqldb.org/

  把下载的压缩文件解开,然后在系统环境变量中加入hsqldb.jar,如:

.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;D:\hsqldb\lib\hsqldb.jar

     在硬盘中任意位置建一个目录作为HSQLDB数据库的主目录,然后打开命令行,进入该目录。在里面建一个server.properties文件,这是HSQLDB服务器模式的配置文件。可以在里面设置数据库服务的监听端口、服务名称、数据文件的相对和绝对路径:

#begin of 'server.properties' file

#数据库服务的监听端口
server.port=9001

#定义服务名称,也即数据库名称。数据库链接的URL即为

#jdbc:hsqldb:hsql://localhost:9001/bitan。
server.dbname.0=bitan

# 该服务在硬盘上的相对或绝对路径。file:后面可以跟相#对或绝对路径,如file:bitan表示数据文件为当前目录下的bitan.*文件。服务名和路径之间通过小数点后的数字关联。比如database.0与#dbname.0关联,database.1与dbname.1关联,……, database.n与dbname.n关联。
server.database.0=file:d:/bitan
#mounts a 'file_in_jar' database with alias 'restest'
#database connection url would be 'jdbc:hsqldb:hsql://host:1234/restest'
#server.database.1=res:/mypackage/test
#server.dbname.1=restest
#mounts a 100% in-memory (transient) database with alias 'memtest'
#database connection url would be 'jdbc:hsqldb:hsql://host:1234/memtest'
#server.database.2=mem:test
#server.dbname.2=memtest
#...
#server.database.n=...
#server.dbname.n=...
server.silent=true

#end of 'server.properties' file

 

    进入上面设置的主目录,启动HSQLDB服务器:HSQLDB会在当前目录下寻找server.properties文件,如果没有发现该文件就使用默认设置。

 

D:\work\eclipse\hibe\data>java org.hsqldb.Server
[Server@1034bb5]: [Thread[main,5,main]]: checkRunning(false) entered
[Server@1034bb5]: [Thread[main,5,main]]: checkRunning(false) exited
[Server@1034bb5]: Startup sequence initiated from main() method
[Server@1034bb5]: Loaded properties from [D:\work\eclipse\hibe\data\server.prope
rties]
[Server@1034bb5]: Initiating startup sequence...
[Server@1034bb5]: Server socket opened successfully in 78 ms.
[Server@1034bb5]: Database [index=0, id=0, db=file:bitan, alias=bitan] opened su
cessfully in 1000 ms.
[Server@1034bb5]: Startup sequence completed in 1093 ms.
[Server@1034bb5]: 2005-11-03 11:30:47.046 HSQLDB server 1.8.0 is online
[Server@1034bb5]: To close normally, connect and execute SHUTDOWN SQL
[Server@1034bb5]: From command line, use [Ctrl]+[C] to abort abruptly

 

 

另外开一个命令行窗口,启动HSQLDB的管理工具,这是GUI外观的程序:

 

D:\work\eclipse\hibe\data>java org.hsqldb.util.DatabaseManager

 

首先出现的是登录窗口:

    在“setting name”中填入“bitan”,下次启动管理工具时,该字串就会出现在“recent”下拉框中。点击“clr”按钮可以清除该字串。在“type”中选择HSQL Database Engine Server,然后在“URL”中输入上面server.properties中的设置。

    点“OK” 登录以后,会出现下面的窗口,左边是目录窗口,右边是SQL查询窗口。我们可以在SQL查询窗口中键入任意SQL语句(包括DDL,DML等等),然后点击“Execute”执行该语句。HSQLDB安装文件的doc目录里附带了PDF和HTML格式的文档,介绍了HSQLDB的SQL语法、支持的数据类型、内置函数等等。

可以在SQL窗口里创建新表:

 

create table events

(event_id integer identity not null,

event_date date,

title varchar(500))

(ID的自动插入方式上,HSQLDB支持identity,如sql server;也支持序列+触发器,如Oracle。)

 

可以插入记录:

 

insert into events (event_id, event_date, title)

values (null, curdate(), 'bitan')

 

(curdate()是HSQLDB内置函数,返回当前日期)

 

启动了HSQLDB服务器,我们就可以在java程序中以JDBC方式访问数据库了。hsqldb.jar中内置了JDBC驱动程序。

如下例,这是hibernate中的配置文件Hibernate.cfg.xml:

 

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
   
<hibernate-configuration>
    <session-factory>
        <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
        <property name="connection.url">jdbc:hsqldb:hsql://jim:9001/bitan</property>
        <property name="connection.username">sa</property>
        <property name="connection.password"></property>
       
        <property name="connection.pool_size">1</property>
       
        <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
       
        <property name="show_sql">true</property>
       
        <!-- property name="hbm2ddl.auto">update</property-->
       
        <mapping resource="hbm/Event.hbm.xml"/>
    </session-factory>
</hibernate-configuration>


posted @ 2008-12-02 18:23 caihaibo 阅读(952) | 评论 (0)编辑 收藏

HSQLDB是一个开源的DBMS数据库,以其体积小巧、功能实用、使用方便而越来越受到开发人员的欢迎,特别是在平时的开发、单元测试中。如果你不想安装庞大的ORACLE、SQL Server数据库,同时又想尽快拥有一个可用的数据库,那么HSQLDB绝对是你的首选。

Ant是一个人皆知之的打包发布工具,其简单的语法,丰富的功能,让我们不但可以方便地进行像资源管理、编译、运行、测试的功能,同时也能够快速地管理数据库。

下面就以这两者为例,来介绍一下他们的结合运用。


一、下载Ant和HSQLDB:

Ant的下载地址:http://ant.apache.org/bindownload.cgi
HSQLDB的下载地址:http://sourceforge.net/project/showfiles.php?group_id=23316

二、安装Ant和HSQLDB:

Ant的安装我就不多说了,可以参考其网站的文档。HSQLDB的安装更简单,直接把hsqldb.jar包拷贝到你工程的lib目录下就可以了。

三、配置HSQLDB:

在你的工程目录下创建一个名为data的目录,这是HSQLDB用来存放数据文件的地方。够简单吧,^_^。

四、编写Ant脚本:

我们的Ant脚本很简单,主要的功能有:启动数据库、关闭数据库、显示Swing界面的HSQLDB管理工具。请看下面的XML文件

<?xml version="1.0" encoding="UTF-8"?>

<project name="hibernate-hsql" default="startDb">

  
<!-- Set default database properties -->
  
<property name="hjar" value="lib/hsqldb.jar" />
  
<property name="hclass" value="org.hsqldb.Server" />
  
<property name="hfile" value="-database.0 data/test" />
  
<property name="halias" value="test" />
  
<property name="hport" value="9005" />

  
<!-- Start up HSQLDB instance, use default properties as arguments: database file,database name,port -->
  
<target name="startDb">
  
<java fork="true" classname="${hclass}" 
        classpath
="${hjar}" 
        args
="${hfile} -dbname.0 ${halias} -port ${hport}" />
  
</target>

  
<!-- Start up HSQLDB swing manager UI -->    
  
<target name="hsqldm">
  
<java fork="true" classname="org.hsqldb.util.DatabaseManagerSwing" 
        classpath
="${hjar}"  />
  
</target> 
    
  
<!-- Shut down HSQLDB -->    
  
<target name="shutdownDb">
    
<sql classpath="${hjar}"
           driver
="org.hsqldb.jdbcDriver" 
           url
="jdbc:hsqldb:hsql://localhost:${hport}/${halias}" 
           userid
="sa" password="" 
           print
="yes">
        SHUTDOWN
    
</sql>
  
</target>
    
</project>


首先我们定义了几个属性:

·hjar:HSQLDB的JAR包位置
·hclass:org.hsqldb.Server,代表了HSQLDB。
·hfile:相当于URL,其中database.0代表了第一个数据库,data是存放数据的地方,test是数据库名
·halias:别名
·hport:端口号,默认为9905

接着我们我们看startDb这个Target,它相当于我们在DOS下转到data目录下,执行java -classpath /lib/hsqldb.jar org.hsqldb.Server。启动HSQLDB数据库。执行该Target后我们可以看到如下输出:

startDb:
     [java] The args attribute is deprecated. Please use nested arg elements.
     [java] [Server@a62fc3]: [Thread[main,5,main]]: checkRunning(false) entered
     [java] [Server@a62fc3]: [Thread[main,5,main]]: checkRunning(false) exited
     [java] [Server@a62fc3]: Startup sequence initiated from main() method
     [java] [Server@a62fc3]: Loaded properties from [D:\peng\Java\Pro\framework\hibernate\server.properties]
     [java] [Server@a62fc3]: Initiating startup sequence...
     [java] [Server@a62fc3]: Server socket opened successfully in 32 ms.
     [java] [Server@a62fc3]: Database [index=0, id=0, db=file:data/test, alias=test] opened sucessfully in 968 ms.
     [java] [Server@a62fc3]: Startup sequence completed in 1000 ms.
     [java] [Server@a62fc3]: 2008-02-24 22:56:39.468 HSQLDB server 1.8.0 is online
     [java] [Server@a62fc3]: To close normally, connect and execute SHUTDOWN SQL
     [java] [Server@a62fc3]: From command line, use [Ctrl]+[C] to abort abruptly

hsqldbm这个Target是一个Swing界面的HSQLDB管理工具,可以在上面执行一系列的简单的SQL操作,对于不想看日志的人来说比较方便,但功能不多。值得注意的是:执行这个Target并需要先启动HSQLDB。
启动后我们可以看到如下界面:



最后是HSQLB的关闭了。在Ant中我们可以采用<sql></sql>这个命令来执行SQL操作,首先当然是指定数据库的一系列配置信息,然后在<sql></sql>之间书写SQL语句。这里SHUTDOWN是HSQLDB提供的一个用来关闭数据库的命令。执行该命令后,我们可以看到如下输出:

 [java] [Server@a62fc3]: Initiating shutdown sequence...
 [java] [Server@a62fc3]: Shutdown sequence completed in 16 ms.
 [java] [Server@a62fc3]: 2008-02-24 22:57:27.375 SHUTDOWN : System.exit() is called next

OK,这个简单的脚本就完成了,现在我们可以直接在DOS、Eclipse下启动、关闭、浏览HSQLDB了。

posted @ 2008-12-02 17:43 caihaibo 阅读(148) | 评论 (0)编辑 收藏
,“30岁现象”首先要从程序员自身找原因。一种职业需要的技能越简单,对精力的依赖程度越高,就越容易被淘汰。计算机行业本来是一个需要高度积累的行业,往往要5年以上的时间才能出道。但很多软件开发人员这5年所积累的有效知识十分有限,不是什么高科技含量的东西,所以很容易被年轻人超过。而且目前的社会环境和舆论导向往往使得这些人过分关注操作层面的东西,比如会不会使用一种编程语言。但是,操作层面的知识是无穷无尽的,过分追逐的结果除了疲惫不堪又无法应对之外,真正能称得上核心竞争力的更高层面的知识和技术往往很欠缺,结果当然只能是等待被淘汰。
       “30岁问题”产生的重要原因:企业对程序员发展规划的不重视和程序员对自身发展方向不明确“30岁问题”并不象更年期那样的阶段性心理、生理问题,因此它的产生是多方面原因造成的。首先中国内地的软件大环境不成熟,大多数软件公司都追求短期效益,体现在人才招聘上就是以30岁作为一个界限。而且公司对程序员的发展也很难有规划。有位叫张俊的朋友这么说:“我曾做过的10多家IT企业,没有一家真正关心过员工的职业生涯规划,当然就更没有哪一家曾把企业的发展计划和员工个人的职业生涯规划结合起来了。”包括在德国的一家软件公司工作的朋友也很遗憾地谈到他们公司也没有这方面的指导,大部分公司仅仅是把开发人员教会能够干活就完事了,对于员工的教育培养没有任何长远的打算。在这种情况下,就很难要求程序员将自身的发展紧紧结合在公司的发展上。很多人认为自己公司的管理为零,□不过遵守考勤制度 、每人划分几个模块、按照软件工程的套路开发罢了。没有思想,没有规范,其他的更谈不上。即便是有些人能够做到低层主管的位置, 他们也经常性地被项目进度,客户需求等情况所左右,并不能完全从技术的角度去对待自己负责的工作,经过一段时间,慢慢就会丧失对于先进技术的追求,而后渐渐产生对技术快速发展的恐惧。笔者发现,正因为一些软件公司在这方面的考虑很少,另外也缺乏资深工程师(在国外,资深工程师可以享受副总裁的待遇,以及对产品的很大决策权力)这样的分级别职位,30岁以上的程序员缺乏发展空间。所以程序员的流动性很大,同时也造成了□有通过跳槽才能给自己一个新的职位和高度的看法。 

  “30岁问题”产生的重要原因:很少有人能够有一个明确而踏实的目标,笔者接触过的许多人不是说:“唉,瞎混吧!”就是说:“我要做百万富翁!” 

  从个人方面来说,二十几岁时,刚刚毕业,很少有人能够有一个明确而踏实的目标,笔者接触过的许多人不是说:“唉,瞎混吧!”就是说:“我要做百万富翁!”。就在这种不考虑实际情况的自我催眠中迷失了方向。一旦快到30岁的时候,如果仍然无法确定自己的发展方向,就会发出“30岁以后还能做什么”的感叹。有些人可能比较"幸运",过了一段时间,等到资历或资金够了后,基于"不要给他人打工"的想法,总要自己扯出来单干,于是不断地出现了具有中国特色的小作坊软件公司。当然我们不能简单地把这种现象归结为"浮躁"两个字,除了个人的因素,整个程序员发展的大环境的不成熟也促使这种现象愈演愈烈。 

  解决“30岁问题”的重要方法:在公司内部为程序员提供技术级别分级和程序员按照自身意愿制定职业发展规划分析了问题的原因,找到解决的方法就不难了。我们知道,管理级别是一种金字塔型的结构,越向上的职位,能够做到的人就越少,这样程序员如果□能在管理方面发展的话,那就受到了很多限制。也造成程序员的发展无法保持一种持续性。因为在职位级别的组织结构中, 
人们通常都倾向于升到一个自己所不能胜任的职位,再加上个人利益的盘踞,导致了种种问题。老板有老板的谋略,打工有打工的兵法,题是这些想法的差距太大,双方都很少为对方著想。孙子曰:“上下同欲者胜”。对于企业管理来讲,要达到“上下同欲”是最难的, 不过也是最关键的。因此对程序员的发展来说,首先就是要把组织结构的问题解决。摩托罗拉中国软件中心的总经理陈玲生谈到程序员发展问题时告诉记者,在摩托罗拉并没有“30岁问题”的出现,因为公司为技术人员的发展提供了两条路,一条是技术、一条是管理。而且两方面是同级的。做技术层次也可以做很高,具体到多高,陈玲生说:“从技术角度最高可以做资深副总裁(VP)。”另外友立软件公司也给软件开发人员提供了异曲同工的发展规划——采用技术级别。友立公司的开发人员的发展方向: 

  中国的传统是,如果我做老板,那我的工资比下面的员工要高,技术要比下面的员工好,才能管理下面的员工。但在国外不是这样的。陈 玲生强调说,在摩托罗拉,很多技术人员的技术级别可能要比他的上司还要高,但是他仍然要受自己老板的管理,这是一种文化,国外软件公司普遍接受这种文化。在摩托罗拉,不一定非要做老板,有些人做了一年的小老板,发现自己并不适合管理工作,反而希望能够回过头来在技术领域进行发展。但是在国内,接受这种文化还需要一定的 
时间。 

  在程序员的发展过程中,个人意愿非常重要。陈玲生说:“摩托罗拉公司中技术人员的发展方向不是公司规定的,而是个人的要求。每年摩托罗拉的员工都必须和自己的老板谈4次,主题是个人的表现、发展规划和发展要求。在符合公司整体利益的前提下,公司会提供更多的机会促进个人的成长,包括各种培训和相应的支持。”笔者个人感觉,程序员这个团体在交流和表达方面有所欠缺,所以在这里也要提醒我们的读者,发展是在自己的手中的,一定要提出自己的要求和发展规划。个人的职业发展规划应该是自己的事情,决不是公司的责任,公司□是在符合公司的整体利益的情况帮助你实现个人的职业发展 
规划。 

  那么向什么方向发展呢?实际上,软件的开发包括了很多方面的内容,是一个系统工程,编码□是其中很小的一部分,各个层次的开发者包括底层编码、系统设计等等。打个比方:就象工地一样,一个小工做时间久了之后,他就有可能看懂图纸,然后逐渐的可以设计了,这就是说他的技术层次提高了。另外也象在服装厂,有设计师,有裁剪师,也有最终缝制的女工。对于设计师来说,他也能够缝制衣服,但是他的主要精力在设计上,这就是层次的问题。程序员本身需要对此有充分的理解,这样才能对自己的发展有清醒的认识。 

  陈玲生还说,“在一个比较完善的公司中,应该是公司营造了一个可供发展的环境,个人也充分提出了自己的要求。无论是技术、管理、产品,向哪个方向发展,程序员都需要能够认识到自身存在的缺陷, 要克制浮躁的情绪,不要让一些外界的事物迷失了自己。” 

  最终解决问题的方法:职业化的程序员和程序员的职业化从更深的层次看,所有这些问题的核心集中到一点就是程序员职业化的不成熟。软件公司和开发人员并没有将程序员视为职业(career),而是工作。目前国内程序员考虑的通常是技术能力,而 不是综合的职业素质。这同国内的软件业起步晚、缺乏产业化的环境和条件,身处其中的软件企业本身就在艰难的生存有关。而在这种状况下,程序员的职业化无从谈起,正所谓皮之不存,毛将焉附。但是近年来,软件业的大环境和外部条件发生了很大改观,并且越来越充满希望,软件企业的高速发展和持续发展也成为可能。这样,程序员的职业化就成为来自外部的要求和压力,也成为程序员本身追求自身发展的需求和动力。 

  从程序员发展自身来说,对程序员职业性的要求有哪些呢?摩托罗拉软件中心的陈玲生提到几点:首先,最根本的就是炼好自己的基本功,编写程序少出错误,学习上要扎实,不能浮躁(这个不想做,那个不愿做),在最初的几年将软件工程学习好。第二点就是要不断地学习,在自己希望发展的技术领域中要从初级的了解变为相应的专家,从整体上了解技术领域的发展。第三点就是要学会创新,因为如果你□是在固守在自己的领域而没有创新的话,便有可能被淘汰。对整个软件产业,程序员的职业化也是当务之急,因为□有从产业的高度培养出一批高质量的职业化的程序员,才能够真正带动软件产业的发展。 

  基于此我们认为需要在以下的几个方面加强:一、程序员的职业化教育培训和再教育培训:结合中国软件开发的现状,从实际出发,传递给软件开发人员思想和技术。另外需要结合我们的国情,推广自己取得的经验,比如一个公司对某个工具的使用有了自己的经验,那就应该拿出来,培训其他人了解和使用这些工具,来带动整个产业的积累。二、加强面向程序员的出版业:这也是程序员产业化的必要条件和发展趋势,因为通过报纸、杂志、网络等媒体可以带动业界的交流和思想技术的传播,这样才能更快的满足中国软件产业和适应国际软件产业的飞速发展。三、专业的顾问咨询:不断升级的开发平台和语言让很多的程序员在追随中不知不觉的迷失了方向,DOS平台的开发人员在Windows平台的开发中找不到了自己的位置,而Windows开发高手又无法适应网络开发的技术发展。其实并不是由于这些人不能接受新的技术,而是因为在小公司、小作坊、小团队的局限下,技术人员无法充分地同更多的高手交流,面对新技术时□能通过独自的钻研来缓慢的取得进展。一方面,很多的程序员在摸索中前进,仍然在重复前人的问题,而另一方面,一些专家有了自己的经验和教训却找不到适当的途径去告诉后来者。基于此有必要鼓励专业的顾问咨询,而且顾问咨询产业的兴起也会对程序员的发展提供另一条不错的方向。实际上,看看国外的发展,由于他们有一套系统的咨询机构,当出现新技术时,□要他能够从专家那里领会到新技术的精髓,然后通过强大的交流服务支持,便能够快速地适应新技术的发展。 
  白玲认为,对于一个30岁的程序员而言,更重要的是要具有“能和别人一起干”的团队合作精神,以及在某一领域所积累的经验。她认为,以下五个途径都是不错的“保养之道”:首先是从技术领域转向管理岗位,利用自己所积累的经验管理和带领团队,从而实现顺利转型;二是在技术岗位上不断上升,从一般的程序员向技术专家靠拢;三是寻找行业依托,技术本身的变化虽然日新月异,但行业对技术应用的要求却是相对稳定的,变化周期不是很快,一个既懂技术又对某个行业有所了解的软件人才还是有很大的拓展空间的;四是跨地区发展,北京、上海可能是技术创新的前沿,但一些二线城市的技术应用,相对而言,可能会有一个时间差,跨地区发展可以充分利用原有技术的比较优势;五是凭借多年积累的技术经验和客户资源出去“单干”,做个小业主未尝不是一种好的出路。
  “三十而立”不是不适用于程序员,反而30岁应该成为程序员脱胎换骨的一个分水岭,当然要跨越这样的转变也需要我们有思想、有准备、有目标。伴随著中国软件产业和程序员职业化的成熟,“30岁问题”也就不再称之为一个问题了。

posted @ 2008-12-02 14:03 caihaibo| 编辑 收藏
其實只要下載完後設定環境變數就可以了。


下載後解壓縮到C槽,更名資料夾為ant
接著設定以下環境變數,

ANT_HOME=c:\ant
JAVA_HOME=c:\jdk-1.5.0.05
PATH=%PATH%;%ANT_HOME%\bin


開始 -> 控制台 -> 系統 -> 進階 -> 環境變數 ->
1. 新增 -> 變數名稱: ANT_HOME  變數值: c:\ant -> 確定
2. 找到變數Path -> 編輯 -> 在變數值最後面加上 ;%ANT_HOME%\bin   (注意分號)
確定離開後重新啟動電腦。


重新啟動後,
開始 -> 執行 -> cmd -> 在命令提示字元下輸入 ant 
若出現
Buildfile: build.xml does not exist!
Build failed
表示路徑已完成設定。
posted @ 2008-11-29 23:24 caihaibo| 编辑 收藏
  美国《心身医学》杂志刊登一项最新研究显示,夫妻争执时保持缄默的女性面对死亡的几率是在争执中能自由表达意见女性的4倍,抑郁症和肠胃病在前者人群中较为常见。

  “我常常跟女士说,如果跟你先生吵架了,什么时候把你气哭了再走,别气半截。”北京崔月犁传统医学研究中心研究员樊正伦说。

  “有人为了实验老鼠生气,就掐它尾巴让它生气,制造一个生气的模型,但那与人生气不可能一样,人就是人,是很难模拟的。”樊正伦指出,中医说喜、怒、忧、思、悲、恐、惊是作为一个正常人必须有的情绪,而这些情绪跟你的五脏密切相关。所以情绪的好坏、变化直接影响着你的生命活动。

  怒与肝相关。生气的时候肝气特别旺,一哭,肺气上来了,肺属金,肝属木,金克木,肺气一通肝气就调达了,如果气一半,肝气没下来,回头还得接着吵架不说,还容易得病。“所以,吵架时不能气半截,要吵透。”樊正伦说。

  五脏相互制约,如果可以很好地调整情绪,就可以少生很多病。樊正伦说,临床中发现,女人三四十岁时,甲状腺、卵巢、乳腺都容易出现一系列病变。其原因是35岁到42岁这个阶段,阳明脉衰,自身运化的能力弱了。而且这个年龄,上有老,下有小,在家里和单位都是顶梁柱,郁闷得不到疏散,这类疾病的发病率就非常高。

  他建议,这个年龄段的女性要自觉地调整自己的状态,调整自己的情绪,在特别抑郁的时候大哭一场,或者大骂一顿,能自如地嬉笑怒骂,疾病就会少很多。

  男性以阳气为主,表现得不像女人那么剧烈,不爱哭,什么事都憋着扛着,认为这样才是男子汉。这也是不对的,男人与女人一样,都需要宣泄,以免肝气郁结。

posted @ 2008-11-26 22:43 caihaibo 阅读(206) | 评论 (0)编辑 收藏
我认为生气就是当一个人认为某种事物或现象违背了他内心的准则或信念时产生的一种情绪体验。
我们每个人都有自己的信念系统和价值系统。比如说我认为怎么样才是对的,别人应该怎么样才是对的,我应该怎么样才是对的等等,一旦别人或自己的一些行为违背了这些标准,我们就会不高兴和生气。

这么看来生气是必然的了,确实如此。只不过生气也有轻重之分,也有难易之分。

一个人如果他的标准越宽容他就越难生气,所谓你的胸怀的大小决定于你生气事情的大小。动不动就生气的人,是因为他的信念系统和价值系统认同的范围太窄,所以别人或他自己的一些行为很容易触犯他的准则,使他不高兴,于是生气。其实别人可能根本就没有做错什么。当然别人做没做错也正是根据他的信念系统来评估的,所以别人的对错也没有客观标准,完全在于接受方的评价。
其实还有一点,就是不容易生气的人除了拥有比较宽容的信念系统以外,他还有一条直接避免生气的信念,那就是同理心,即将心比心。虽然他不赞同别人的意见或行为。但他能理解,如果能做到这一点,生气的次数大概要减少80%。

还有一条信念就是,可以将生气压到最低限度。那就是当别人的行为你不能赞同,也不能表示理解,可以说你认定他完全错误,这时候告诫自己,生气就是拿别人的错误来惩罚自己。有了这一条,你想生气都难了。

所以还是那句行话:生气是一种态度,是一种选择,全在乎你愿不愿意,不关别人的事。千万别说是谁惹了你,是谁令你生气,生气完全是你自己要的,自己选的。

建议:每天坚持做长跑也是锻练自控能力的好方法,每天2000米,这样你每天坚持,你的自控能力必然能改善,三天打鱼两天晒网就不可能改善的哦.

我送你12个字:缓一缓 再生气 想一想 再行动!











有句话送给你,不要拿别人的错误来惩罚自己。很多事情,也没必要事事完美,与其改变别人做的更好,不如先改变自己接受一些缺点。或者说把一些你看不惯的东西看成是芝麻绿豆大。
有个故事不知你有没听过,鸭子看东西时,眼睛是放大镜,它看到的人都很大,所以它看到人的时候,总是以为人要来打它,所以它会去咬人,牛看东西的时候,所以的东西在它的眼里都是蚂蚁一样这么小,所以它不会袭击人类。



要生气的时候先问问自己:
我为什么生气?
生气有什么用?
生完气会给别人造成什么伤害?有什么后果?

回答完这几个问题,再从一数到十。


告诉他:怒主肝,生气直接伤肝,肝脏出了问题会影响其他器官,继而身体病就来了。相信他知道了利害关系,会尽快控制自己的情绪。


每次生气都记个数,看看自己每天会生多少次。
然后学习控制自己,慢慢减少次数!!
posted @ 2008-11-26 21:53 caihaibo 阅读(1785) | 评论 (0)编辑 收藏
MyEclipse Update Progress Error现象:
频繁弹出Update Progress(Time of error:……)窗口。
.log文件里

org.eclipse.swt.SWTException: Failed to execute runnable (java.lang.IllegalArgumentException: Argument cannot be null)
at org.eclipse.swt.SWT.error(SWT.java:3563)
at org.eclipse.swt.SWT.error(SWT.java:3481)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:126)
中略
Caused by: java.lang.IllegalArgumentException: Argument cannot be null
at org.eclipse.swt.SWT.error(SWT.java:3547)
at org.eclipse.swt.SWT.error(SWT.java:3481)
at org.eclipse.swt.SWT.error(SWT.java:3452)

 

解决方案
在某英文网站上找到一下答案,试了,没好用。你们可以试下OK不?
a) leave myeclipse
b) point explorer to the .metadata folder
c) right mouse button select "search" giving criteria 'org.eclipse.update*' (without quotes)
d) deleting all the files/folders found
e) restart myeclipse

通过上面的联想到其它UpdateStamp的文件,到MyEclipse的安装目录,之下的“eclipseconfigurationorg.eclipse.update”目录,
发现有一个,last.config.stamp。
a) leave myeclipse
b) delete last.config.stamp
c) restart myeclipse
之后就没有同样的窗口弹出来。
但是,如果在某项目上右键打开项目的属性窗口,点击“Myeclipse”的Update按钮,又会弹出同样的窗口。
这样的话,只要再重复一下上述操作就OK。

posted @ 2008-11-21 14:57 caihaibo 阅读(10520) | 评论 (4)编辑 收藏

本文所用环境:Eclipse 3.2 + MyEclipse 5.0GA + WebLogic 9.2

选择 WebLogic 9.2 的原因

①WebLogic 8 支持的是 J2EE 1.3,也就是 Servlet 2.3 规范。若在 MyEclipse 中建立 Web Project 时选择了 J2EE 1.4[default],在部署的时候就会出现异常,提示部署描述符 web.xml 是畸形的,也就是未通过 DTD 检验。因为 J2EE 1.4 使用的是 Servlet 2.4 规范,这直接体现在 web.xml 部署描述符的头部引用中。这就是有些朋友遇到的,部署在 Tomcat 和 JBoss 中能够运行的 JSP 程序,部署到 WebLogic 8 就无法运行的原因之一。解决这个问题,需要将 WebLogic 升级到 9.2 版本;或者使用 J2EE 1.3。

Servlet 2.3 规范生成的 web.xml 头部:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd"
>
<web-app>
...
</web-app>

Servlet 2.4 规范生成的 web.xml 头部:


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi
=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>
...
</web-app>

②若在上一个问题选择了 J2EE 1.3 进行开发后,在部署时会出现另外的异常,提示“Unsupported major.minor version 49.0”—— 又是版本问题,这次是由于 JDK 版本不支持造成的。WebLogic 8 不支持 JDK 1.5,由 JDK 1.5 编译的程序无法部署到只支持 JDK 1.4 的服务器上运行。解决的办法也有两个:用 JDK 1.4 重新编译;或者换用支持 JDK 1.5 的服务器,也就是升级到 WebLogic 9.2。

配置 WebLogic 9.2

安装 WebLogic 比较容易,在这里就不再累述了,大家可以参阅相关文档。现在着重讲一下 WebLogic 的配置,因为后面在配置 MyEclipse 时将用到这里的配置信息。

①运行开始 -> 程序 -> BEA Products -> Tools -> Configuration Wizard。
②选择 Create a new WebLogic domain,Next。
③在 Select Domain Source 界面保持默认,Next。
④在 User name 处输入 user,两个 password 都输入 12345678(密码要求 8 位),Next。
⑤ 在 Configure Server Start Mode and JDK 界面中保持默认,即 JDK 选择的是“Sun SDK 1.5.0_04 @ C:BEAjdk150_04”,注意这里若选择“Other JDK”配置比 SDK 1.5.0_04 更高的版本,服务器启动时将会出现异常,所以最好保持默认,然后 Next。
⑥在 Customize Environment and Services Settings 界面中默认为 No,Next。
⑦在 Domain name 处输入 mydomain,点击 Create。
⑧完成后点击 Done 关闭 Configuration Wizard 对话框。
⑨ 运行开始 -> 程序 -> BEA Products -> User Projects -> mydomain -> Start Admin Server for Weblogic Server Domain,检查服务器是否启动成功。

配置 MyEclipse 的 WebLogic 9 服务器

启动 Eclipse,选择“Window -> Preferences”菜单,打开首选项对话框。展开 MyEclipse 下的 Application Servers 节点,点击 WebLogic 9,选中右边的 Enable 单选按钮,启用 WebLogic 服务器。配置如下:
①BEA home directory:C:BEA(假定 WebLogic 安装在 C:BEA 目录中)
②WebLogic installation directory:C:BEAWebLogic92
③Admin username:user(来自 WebLogic 中的配置)
④Admin password:12345678(来自 WebLogic 中的配置)
⑤Execution domain root:C:BEAuser_projectsdomainsmydomain
⑥Execution server name:AdminServer
⑦Security policy file:C:BEAWebLogic92serverlibweblogic.policy
⑧JAAS login configuration file:(Null)

接着展开 WebLogic 9 节点,点击 JDK,在右边的 WLS JDK name 处选择 WebLogic 9 的默认 JDK。这里组合框中缺省为单独安装的 JRE。单击 Add 按钮,弹出 WebLogic -> Add JVM 对话框,在 JRE 主目录处选择 WebLogic 安装文件夹中的 JDK 文件夹,我的版本为 C:BEAjdk150_04,程序会自动填充其他选项。单击确定按钮关闭对话框。这时候就可以在 WLS JDK name 组合框中选择 jdk150_04 了。

至此,MyEclipse 中 WebLogic 9 的配置工作就算完成了。下面可以看看在 Eclipse 中能否启动 WebLogic 服务器了?安装了 MyEclipse 之后,Eclipse 工具栏中就会有一个“Run/Stop/Restart MyEclipse Application Servers”下拉按钮。点击该按钮的下拉部分,选择“WebLogic 9 -> Start”菜单,即开始启动 WebLogic 了。通过查看控制台的消息,就可以检查启动是否成功,或发生什么异常。
posted @ 2008-11-19 17:31 caihaibo 阅读(225) | 评论 (0)编辑 收藏
选择 project 或者 file, 点鼠标右键,选 properties 菜单,在弹出窗口,选 Resource, 设置 Text file encoding 为 UTF-8 就 ok 了
posted @ 2008-11-13 18:55 caihaibo 阅读(521) | 评论 (1)编辑 收藏
 MyEclipse是Eclipse的一个插件,所以,你必须先安装Eclipse才可以安装MyEclipse。
MyEclipse是一个编译器,要做JAVA程序,就要配置基本的JDK环境变量
一、安装JDK

首先下载JDK 5.0(JDK 5.0的下载页面为:http://java.sun.com/j2se/1.5.0/download.jsp);然后运行JDK 5.0安装程序jdk-1_5_0_06-windows-i586-p.exe,安装过程中所有选项保持默认;最后配置JDK的环境变量:在“我的电脑”上点右键—>“属性”—>“高级”—> “环境变量(N)”。



新建系统变量JAVA_HOME:C:\Program Files\Java\jdk1.5.0_06;

新建系统变量CLASSPATH:.;%JAVA_HOME%\lib;(注意:点号表示当前目录,不能省略)

在系统变量Path的值的前面加入以下内容:%JAVA_HOME%\bin;(注意:这里的分号不能省略)

到这里,JDK安装完毕。

注意:如果以后要安装诸如Eclipse、Borland JBuilder、JCreator、IntelliJ IDEA等集成开发环境(IDE,Integrated Development Environment),应该在IDE中编译运行一个简单的HelloWorld程序,以保证IDE可以识别出JDK的位置。

二、安装Tomcat

首先下载jakarta-tomcat-5.0.30.zip,之所以下载免安装版的好处是可以使用多个Tomcat(jakarta-tomcat-5.0.30.zip的下载页面为:

http://apache.linuxforum.net/tomcat/tomcat-5/v5.0.30/bin/);

然后将jakarta-tomcat-5.0.30.zip直接解压到D盘根目录:



最后配置Tomcat的环境变量:在“我的电脑”上点右键—>“属性”—>“高级”—> “环境变量(N)”。

新建系统变量CATALINA_HOME:D:\jakarta-tomcat-5.0.30

在系统变量CLASSPATH的值的后面加入:%CATALINA_HOME%\common\lib;

在系统变量Path的值中"%JAVA_HOME%\bin;"的后面加入以下内容:%CATALINA_HOME%\bin;

到这里,Tomcat安装完毕。

进行完一、二两步的设置以后,各系统变量的值如下:

JAVA_HOME:C:\Program Files\Java\jdk1.5.0_06
CATALINA_HOME:D:\jakarta-tomcat-5.0.30
CLASSPATH:.;%JAVA_HOME%\lib;%CATALINA_HOME%\common\lib;
Path:%JAVA_HOME%\bin;%CATALINA_HOME%\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem

三、安装Eclipse

首先下载eclipse-SDK-3.1.2-win32.zip(eclipse-SDK-3.1.2-win32.zip下载地址为:

http://www.eclipse.org/downloads/);

然后将eclipse-SDK-3.1.2-win32.zip直接解压到D盘根目录:



到这里, Eclipse安装完毕。

四、安装MyEclipse

首先下载EnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exe(EnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exe 的下载地址为:
http://www.myeclipseide.com/ContentExpress-display-ceid-10.html);

然后安装EnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exe。注意:安装时候要选择Eclipse的安装路径,其他选项保持默认。



安装完毕之后,将MyEclipse安装目录下的features和plugins这2个目录覆盖到Eclipse的安装目录下。

最后将刚才安装的 MyEclipse 卸载。

解释一下上面这样做的原因:因为MyEclipse是Eclipse的插件,所以只要把features和plugins这2个目录覆盖到Eclipse的安装目录,Eclipse就会自动认出这些插件。

到这里,MyEclipse安装完毕。

五、破解MyEclipse

运行MyEclipse4.1.1注册机MyEclipseKeyGen.exe,选择MyEclipse的版本号,输入注册名,生成序列号。(MyEclipse4.x注册机的下载地址为:

http://esoft.g8.com.cn/UploadFiles/2006-5/520753587.rar

运行eclipse.exe(首次运行要求指定Workspace),依次点击Window ----> Preferences ---->MyEclipse---->Subscription ----> Enter Subscription,输入注册名以及注册机生成的注册码。

到这里,MyEclipse破解完毕。

六、指定Eclipse+MyEclipse的JRE
1.设定Eclipse+MyEclipse的JRE

一般情况下,Eclipse可以自动找到JRE,我们不用进行过多的设置。

到这里,我们的Eclipse+MyEclipse开发环境就搭建完毕了!
参考资料:http://www.webdn.com/web_file/program/jsp/0602080402/MyEclipse是Eclipse的一个插件,所以,你必须先安装Eclipse才可以安装MyEclipse。
MyEclipse是一个编译器,要做JAVA程序,就要配置基本的JDK环境变量
一、安装JDK

首先下载JDK 5.0(JDK 5.0的下载页面为:http://java.sun.com/j2se/1.5.0/download.jsp);然后运行JDK 5.0安装程序jdk-1_5_0_06-windows-i586-p.exe,安装过程中所有选项保持默认;最后配置JDK的环境变量:在“我的电脑”上点右键—>“属性”—>“高级”—> “环境变量(N)”。



新建系统变量JAVA_HOME:C:\Program Files\Java\jdk1.5.0_06;

新建系统变量CLASSPATH:.;%JAVA_HOME%\lib;(注意:点号表示当前目录,不能省略)

在系统变量Path的值的前面加入以下内容:%JAVA_HOME%\bin;(注意:这里的分号不能省略)

到这里,JDK安装完毕。

注意:如果以后要安装诸如Eclipse、Borland JBuilder、JCreator、IntelliJ IDEA等集成开发环境(IDE,Integrated Development Environment),应该在IDE中编译运行一个简单的HelloWorld程序,以保证IDE可以识别出JDK的位置。

二、安装Tomcat

首先下载jakarta-tomcat-5.0.30.zip,之所以下载免安装版的好处是可以使用多个Tomcat(jakarta-tomcat-5.0.30.zip的下载页面为:

http://apache.linuxforum.net/tomcat/tomcat-5/v5.0.30/bin/);

然后将jakarta-tomcat-5.0.30.zip直接解压到D盘根目录:



最后配置Tomcat的环境变量:在“我的电脑”上点右键—>“属性”—>“高级”—> “环境变量(N)”。

新建系统变量CATALINA_HOME:D:\jakarta-tomcat-5.0.30

在系统变量CLASSPATH的值的后面加入:%CATALINA_HOME%\common\lib;

在系统变量Path的值中"%JAVA_HOME%\bin;"的后面加入以下内容:%CATALINA_HOME%\bin;

到这里,Tomcat安装完毕。

进行完一、二两步的设置以后,各系统变量的值如下:

JAVA_HOME:C:\Program Files\Java\jdk1.5.0_06
CATALINA_HOME:D:\jakarta-tomcat-5.0.30
CLASSPATH:.;%JAVA_HOME%\lib;%CATALINA_HOME%\common\lib;
Path:%JAVA_HOME%\bin;%CATALINA_HOME%\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem

三、安装Eclipse

首先下载eclipse-SDK-3.1.2-win32.zip(eclipse-SDK-3.1.2-win32.zip下载地址为:

http://www.eclipse.org/downloads/);

然后将eclipse-SDK-3.1.2-win32.zip直接解压到D盘根目录:



到这里, Eclipse安装完毕。

四、安装MyEclipse

首先下载EnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exe(EnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exe 的下载地址为:
http://www.myeclipseide.com/ContentExpress-display-ceid-10.html);

然后安装EnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exe。注意:安装时候要选择Eclipse的安装路径,其他选项保持默认。



安装完毕之后,将MyEclipse安装目录下的features和plugins这2个目录覆盖到Eclipse的安装目录下。

最后将刚才安装的 MyEclipse 卸载。

解释一下上面这样做的原因:因为MyEclipse是Eclipse的插件,所以只要把features和plugins这2个目录覆盖到Eclipse的安装目录,Eclipse就会自动认出这些插件。

到这里,MyEclipse安装完毕。

五、破解MyEclipse

运行MyEclipse4.1.1注册机MyEclipseKeyGen.exe,选择MyEclipse的版本号,输入注册名,生成序列号。(MyEclipse4.x注册机的下载地址为:

http://esoft.g8.com.cn/UploadFiles/2006-5/520753587.rar

运行eclipse.exe(首次运行要求指定Workspace),依次点击Window ----> Preferences ---->MyEclipse---->Subscription ----> Enter Subscription,输入注册名以及注册机生成的注册码。

到这里,MyEclipse破解完毕。

六、指定Eclipse+MyEclipse的JRE
1.设定Eclipse+MyEclipse的JRE

一般情况下,Eclipse可以自动找到JRE,我们不用进行过多的设置。

到这里,我们的Eclipse+MyEclipse开发环境就搭建完毕了!
参考资料:http://www.webdn.com/web_file/program/jsp/0602080402/MyEclipse是Eclipse的一个插件,所以,你必须先安装Eclipse才可以安装MyEclipse。
MyEclipse是一个编译器,要做JAVA程序,就要配置基本的JDK环境变量
一、安装JDK

首先下载JDK 5.0(JDK 5.0的下载页面为:http://java.sun.com/j2se/1.5.0/download.jsp);然后运行JDK 5.0安装程序jdk-1_5_0_06-windows-i586-p.exe,安装过程中所有选项保持默认;最后配置JDK的环境变量:在“我的电脑”上点右键—>“属性”—>“高级”—> “环境变量(N)”。



新建系统变量JAVA_HOME:C:\Program Files\Java\jdk1.5.0_06;

新建系统变量CLASSPATH:.;%JAVA_HOME%\lib;(注意:点号表示当前目录,不能省略)

在系统变量Path的值的前面加入以下内容:%JAVA_HOME%\bin;(注意:这里的分号不能省略)

到这里,JDK安装完毕。

注意:如果以后要安装诸如Eclipse、Borland JBuilder、JCreator、IntelliJ IDEA等集成开发环境(IDE,Integrated Development Environment),应该在IDE中编译运行一个简单的HelloWorld程序,以保证IDE可以识别出JDK的位置。

二、安装Tomcat

首先下载jakarta-tomcat-5.0.30.zip,之所以下载免安装版的好处是可以使用多个Tomcat(jakarta-tomcat-5.0.30.zip的下载页面为:

http://apache.linuxforum.net/tomcat/tomcat-5/v5.0.30/bin/);

然后将jakarta-tomcat-5.0.30.zip直接解压到D盘根目录:



最后配置Tomcat的环境变量:在“我的电脑”上点右键—>“属性”—>“高级”—> “环境变量(N)”。

新建系统变量CATALINA_HOME:D:\jakarta-tomcat-5.0.30

在系统变量CLASSPATH的值的后面加入:%CATALINA_HOME%\common\lib;

在系统变量Path的值中"%JAVA_HOME%\bin;"的后面加入以下内容:%CATALINA_HOME%\bin;

到这里,Tomcat安装完毕。

进行完一、二两步的设置以后,各系统变量的值如下:

JAVA_HOME:C:\Program Files\Java\jdk1.5.0_06
CATALINA_HOME:D:\jakarta-tomcat-5.0.30
CLASSPATH:.;%JAVA_HOME%\lib;%CATALINA_HOME%\common\lib;
Path:%JAVA_HOME%\bin;%CATALINA_HOME%\bin;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem

三、安装Eclipse

首先下载eclipse-SDK-3.1.2-win32.zip(eclipse-SDK-3.1.2-win32.zip下载地址为:

http://www.eclipse.org/downloads/);

然后将eclipse-SDK-3.1.2-win32.zip直接解压到D盘根目录:



到这里, Eclipse安装完毕。

四、安装MyEclipse

首先下载EnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exe(EnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exe 的下载地址为:
http://www.myeclipseide.com/ContentExpress-display-ceid-10.html);

然后安装EnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exe。注意:安装时候要选择Eclipse的安装路径,其他选项保持默认。



安装完毕之后,将MyEclipse安装目录下的features和plugins这2个目录覆盖到Eclipse的安装目录下。

最后将刚才安装的 MyEclipse 卸载。

解释一下上面这样做的原因:因为MyEclipse是Eclipse的插件,所以只要把features和plugins这2个目录覆盖到Eclipse的安装目录,Eclipse就会自动认出这些插件。

到这里,MyEclipse安装完毕。

五、破解MyEclipse

运行MyEclipse4.1.1注册机MyEclipseKeyGen.exe,选择MyEclipse的版本号,输入注册名,生成序列号。(MyEclipse4.x注册机的下载地址为:

http://esoft.g8.com.cn/UploadFiles/2006-5/520753587.rar

运行eclipse.exe(首次运行要求指定Workspace),依次点击Window ----> Preferences ---->MyEclipse---->Subscription ----> Enter Subscription,输入注册名以及注册机生成的注册码。

到这里,MyEclipse破解完毕。

六、指定Eclipse+MyEclipse的JRE
1.设定Eclipse+MyEclipse的JRE

一般情况下,Eclipse可以自动找到JRE,我们不用进行过多的设置。

到这里,我们的Eclipse+MyEclipse开发环境就搭建完毕了!
参考资料:http://www.webdn.com/web_file/program/jsp/0602080402/
posted @ 2008-11-13 11:43 caihaibo 阅读(519) | 评论 (0)编辑 收藏
 
在Windows Xp系统中,按“Alt+Ctrl+Delete”出现的是任务管理器,不是
安全对话框这样不能锁定计算机,可以打开控制面板,点击“切换到经典视图”
后选择“用户账户”,在选择“更改用户登录或注销方式”,不选“使用欢迎
屏幕”,然后确定。在按Alt+Ctrl+Delete”出现的是Windows安全对话框,点
“锁定计算机”即可OK。
posted @ 2008-11-12 13:33 caihaibo 阅读(207) | 评论 (0)编辑 收藏
今天在导入一个工程时,编译并打包到Tomcat后,发现出现java.lang.UnsupportedClassVersionError: Bad version number in .class file异常,检查了一下我的myEclipse,发现不知道啥时候不小心将编译器改成JDK6.0了,那个工程是从同事的机上拷贝过来的,用的编译器是JDK5.0,试了一下,果然是这个问题引起。
    那次在Linux上部署工程时也出现过因为版本不同引起的问题,那时我们用的IDE的编译器是JDK5.0,而那台Linux装的是JDK6.0,部署后发现很多功能都出错,看来有些东西还是得注意一下啊。
    附,在myEclipse中改变编译器的方法:Project->Properties->Java Compiler->Configure Workspace Setting,在弹出的页面中可以进行设置。
posted @ 2008-11-09 21:59 caihaibo 阅读(275) | 评论 (1)编辑 收藏
手动安装的tomcat没有生成admin跟manager用户,要进入tomcat的admin管理界面必须自己手动添加.

打开tomcat安装目录下的conf/tomcat-users.xml文件,在<tomcat-users>和</tomcat-user>中间添加:

<role rolename="manager"/>
<role rolename="admin"/>

<user username="manager" password="tomcat" roles="manager"/>
<user username="admin" password="tomcat" roles="admin"/>

其中user字段中的username和password就是你的用户名跟密码,添加完成后就可以用这个用户名跟密码登录tomcat的admin以及manager页面了.

http://localhost:8080/admin
http://localhost:8080/manager

懒人方法:

<user username="both" password="tomcat"

                                  roles="manager,tomcat,role1"/>

直接添加到此处,下一次tomcat启动时将自动添加一个manager用户!

posted @ 2008-11-09 21:15 caihaibo 阅读(172) | 评论 (0)编辑 收藏
MyEclipse 6.0官方下载地址:
http://www.myeclipseide.com/module-htmlpages-display-pid-4.html

MyEclipse 6.0注册序列号:
Subscriber:QQ24785490
Subscription Code:DLR8ZC-855551-65657857678050018
posted @ 2008-11-05 18:19 caihaibo 阅读(3953) | 评论 (9)编辑 收藏
 mysql是我以前学习和练习所使用的数据,现在在工作中也在使用,之前公司里用oracle,我在做自己的东西的时候觉得用oracle太不方便,于是就找了mysql(当时也考虑过sqlserver,觉得还是没有mysql小巧),从那时起我就开始接触下面所说的几种mysql客户端工具了。
           我接触的mysql客户端工具一共有4个,mysqlfront, mysqlyog, mysqlbrowser, ems mysql manager,其中mysqlbrowser是我最早使用的一个mysql客户端工具(一年前),当时是在一个自己接的交友网站中使用mysql,于是就找到了这个mysqlbrowser,
mysqlbrowser的优点是简单,及其的简单,安装之后能够立刻上手,马上就能使用的那种,布局也很简陋,功能也很简陋,简单使用没有问题,尤其是刚开始学习mysql的同学,可以尝试一下。

          接下来我使用的是ems,ems到了另外一个极端,强大,非常强大,表和字段的任何属性都能随意修改,那么它强大的同时必然带来了使用的复杂,可以说刚开始 使用的时候很不习惯它的布局。它有一个我比较赞赏的优点,就是快捷键,它有很多快捷键,这一点和mysqlbrowser比有天壤之别。

         我第三个遇到的mysql客户端工具是mysqlfront,它给我的感觉是功能和易用性介于mysqlbrowser和ems之间,它有不少缺点,不如说无法修改表的一些属性,和一些字段的属性等等。

          第四个就是mysqlyog,这个工具给我的感觉是介于mysqlbrowser和mysqlfront之间,总体感觉没有mysqlfront强大。
          通过我的一些认识,我觉得它们的排名是1mysqlbrowser,2mysqlyog,3mysqlfront,4ems。这是根据功能的强大与否来排名的。ems的功能是最强大,所以我现在一直在使用它。我也推荐大家使用ems mysql manager。ems有两个版本,lite版(免费),professional(专业版),我一直使用的lite版,程序员而言,lite版已经完全够用了。
posted @ 2008-11-04 10:43 caihaibo 阅读(168) | 评论 (0)编辑 收藏
模板是指在薄片塑料板上面写字后挖空,再使用毛笔或色笔涂满挖空部分,就能看到纯手工而以不失工整的字样,看到模板上的挖空形状,马上就知道最后会变出什么样子的字,不过实际上所显现出来的字样还是要依所使用的画笔种类而定.拿黑色签字笔当画笔,结果当然就是签字笔的字样;当用铅笔来画,得到的也只会是灰黑色的铅笔字;如果用五颜六色的彩色笔,自然能创出让人眼花的多色字.但是,无论使用哪种文具,制作出来的字样都还是脱不了模板上已经固定的形状。

   下面我们用例子说明模板方法

  程序示例类之间的关系

  1.模板类,相当于我们上面提到的薄片塑料板

Java代码 复制代码
  1. package com.pattern.templateMethod;   
  2.   
  3. /**  
  4.  * 抽象类,充当模板角色  
  5.  * @author administrator  
  6.  *  
  7.  */  
  8. public abstract class AbstractDisplay {   
  9.     //由子类实现的抽象方法   
  10.     public abstract void open();      
  11.     public abstract void print();   
  12.     public abstract void close();   
  13.     //抽象类实现的方法,final可以保证在子类不会被修改   
  14.     public final void display() {   
  15.         open();   //先open...   
  16.         for(int i=0; i < 5; i++) {  //反复输出5次   
  17.             print();     
  18.         }   
  19.         close(); //输出完毕,close   
  20.     }   
  21. }  

 

  2.字符类,输出单个字符

Java代码 复制代码
  1. package com.pattern.templateMethod;   
  2.   
  3. public class CharDisplay extends AbstractDisplay {   
  4.     private char ch;     //应输出的字符   
  5.     public CharDisplay(char ch) {  //把构造函数传递过来的字符ch,存储在字段内   
  6.         this.ch = ch;   
  7.     }   
  8.      
  9.     public void open() {   
  10.         System.out.print("<<");   //输出"<<"作为开始字符串   
  11.     }   
  12.     public void close() {   
  13.         System.out.println(">>");  //输出 ">>"作为结束字符串   
  14.     }   
  15.     public void print() {   
  16.         System.out.print(ch);    //输出存储在字段的字符   
  17.     }   
  18.   
  19. }  

 

   3.字符串类,输出字符串

Java代码 复制代码
  1. package com.pattern.templateMethod;   
  2.   
  3. /**  
  4.  *   
  5.  * @author administrator  
  6.  */  
  7. public class StringDisplay extends AbstractDisplay {   
  8.     private String string;  //应输出的字符串   
  9.     private int width;      //以byte为单位所求出的字符串的"长度"   
  10.        
  11.     public StringDisplay(String string) {   
  12.         this.string =string;   
  13.         width = string.getBytes().length;   
  14.     }   
  15.   
  16.     public void open() {  //打印头装饰字符串   
  17.         printLine();   
  18.     }   
  19.     public void print() { //打印内容   
  20.         System.out.println("|"+string+"|");   
  21.     }   
  22.     public void close() { //打印尾装饰字符串   
  23.         printLine();   
  24.     }   
  25.   
  26.     public void printLine() {   
  27.         System.out.print("+");  //输出"+"号表示边框位置   
  28.         for(int i=0; i < width; ++i) {   
  29.             System.out.print("-");  //当作线段   
  30.         }   
  31.         System.out.println("+");  //输出"+"号表示边框位置   
  32.     }   
  33. }  

  4.测试类

Java代码 复制代码
  1. package com.pattern.templateMethod;   
  2.   
  3. public class Main {   
  4.     public static void main(String[] args) {   
  5.         //建立1个有'A'的CharDisplay的对象   
  6.         AbstractDisplay d1 = new CharDisplay('A');   
  7.         //建立1个有"Hello world"的StringDisplay的对象   
  8.         AbstractDisplay d2 = new StringDisplay("Hello World");   
  9.            
  10.         //d1,d2都是AbstractDisplay的子类对象,可以调用继承到的display()方法   
  11.         d1.display();   
  12.         d2.display();   
  13.     }   
  14. }  

 

 输出:

 

C代码 复制代码
  1.  <<AAAAA>>   
  2. +-----------+   
  3. |Hello World|   
  4. |Hello World|   
  5. |Hello World|   
  6. |Hello World|   
  7. |Hello World|   
  8. +-----------+  

 

 

 

 

 

设计思想:

  作为模板的方法定义在父类(父类为抽象类),而方法定义使用抽象方法,实现抽象方法的是子类,要在子类实现方法,才能决定具体的操作。如果在不同的子类执行不同实现就可以发展出不同的处理内容。不过,无论在哪个子类执行任何一种实现,处理的大致流程都还是要依照父类制定的方式。

posted @ 2008-11-04 10:32 caihaibo 阅读(375) | 评论 (0)编辑 收藏

1. 意图:
为其他对象提供一种代理以控制对这个对象的访问

2. 别名:
surrogate替身

3. 动机
按需创建, 替代对象

4. 适用性
* 远程代理
* 虚代理
* 保护代理
* 智能指引

5. 结构


6. 实例

Java代码 复制代码
  1. package net.yeah.fanyamin.pattern.proxy;   
  2.   
  3. /**  
  4.  * @author walter  
  5.  */  
  6. interface Greet {   
  7.     void sayHello(String name);   
  8.     void goodBye();   
  9. }   
  10.   
  11. class GreetImpl implements Greet {   
  12.     public void sayHello(String name) {   
  13.         System.out.println("Hello " + name);   
  14.     }   
  15.     public void goodBye() {   
  16.         System.out.println("Good bye.");   
  17.     }   
  18. }   
  19.   
  20. public class SimpleProxy implements Greet {   
  21.     private Greet greet = null;   
  22.        
  23.     SimpleProxy(Greet greet) {   
  24.         this.greet = greet;   
  25.     }   
  26.        
  27.     public void sayHello(String name) {   
  28.         System.out.println("--before method sayHello");   
  29.         greet.sayHello(name);   
  30.         System.out.println("--after method sayHello");   
  31.     }   
  32.        
  33.     public void goodBye() {   
  34.         System.out.println("--before method goodBye");   
  35.         greet.goodBye();   
  36.         System.out.println("--after method goodBye");   
  37.     }   
  38.     /**  
  39.      * @param args  
  40.      */  
  41.     public static void main(String[] args) {   
  42.         Greet greet = new SimpleProxy(new GreetImpl());   
  43.         greet.sayHello("walter");   
  44.         greet.goodBye();   
  45.   
  46.     }   
  47.   
  48. }  

 利用JDK中的动态代理

Java代码 复制代码
  1. /**  
  2.  *   
  3.  */  
  4. package net.yeah.fanyamin.pattern.proxy;   
  5.   
  6. import java.lang.reflect.InvocationTargetException;   
  7. import java.lang.reflect.Method;   
  8.   
  9. /**  
  10.  * @author walter  
  11.  */  
  12. public class DebugProxy implements java.lang.reflect.InvocationHandler {   
  13.   
  14.     private Object obj;   
  15.   
  16.     public static Object newInstance(Object obj) {   
  17.         return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),   
  18.                                                         obj.getClass().getInterfaces(), new DebugProxy(obj));   
  19.     }   
  20.   
  21.     private DebugProxy(Object obj) {   
  22.         this.obj = obj;   
  23.     }   
  24.   
  25.     public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {   
  26.         Object result;   
  27.         try {   
  28.             System.out.println("--before method " + m.getName());   
  29.             result = m.invoke(obj, args);   
  30.         } catch (InvocationTargetException e) {   
  31.             throw e.getTargetException();   
  32.         } catch (Exception e) {   
  33.             throw new RuntimeException("unexpected invocation exception: " + e.getMessage());   
  34.         } finally {   
  35.             System.out.println("--after method " + m.getName());   
  36.         }   
  37.         return result;   
  38.     }   
  39.   
  40.     /**  
  41.      * @param args  
  42.      */  
  43.     public static void main(String[] args) {   
  44.         Greet greet = (Greet) DebugProxy.newInstance(new GreetImpl());   
  45.         greet.sayHello("walter");   
  46.         greet.goodBye();   
  47.     }   
  48.   
  49. }  



动态代理确实很有价值,而且java的反射机制其实性能并不慢,只不过被代理的Object需要有个Interface就是了。
实际中,代理多用在访问,权限控制
其实从类的实现表现形式来说,和装饰模式,适配器模式,都比较相似,只不过具体实现意义不一样
posted @ 2008-11-04 10:20 caihaibo 阅读(103) | 评论 (0)编辑 收藏

1. 以一个算术运算为例,传统做法为:

java 代码
  1. package org.common;   
  2.   
  3. public class Calculate {   
  4.        
  5.     public String getResult(float a,float b,char c){   
  6.            
  7.         float add = a+b;   
  8.         float sub = a-b;   
  9.         float mult = a*b;   
  10.         float division = a/b;   
  11.            
  12.         switch(c){   
  13.             case '+':   
  14.                 return "相加结果为:" + add;   
  15.             case '-':   
  16.                 return "相减结果为:" + sub;   
  17.             case '*':   
  18.                 return "相乘结果为:" + mult;   
  19.             case '/':   
  20.                 return "相除结果为:" + division;   
  21.             default:   
  22.                 return "出错";   
  23.         }   
  24.     }   
  25.   
  26. }  

 

java 代码
  1. package org.common;   
  2.   
  3. public class Test {   
  4.        
  5.     public static void main(String[] args){   
  6.         float a = 200;   
  7.         float b = 50;   
  8.         Calculate cal = new Calculate();   
  9.         System.out.println(cal.getResult(a, b, '+'));   
  10.         System.out.println(cal.getResult(a, b, '-'));   
  11.         System.out.println(cal.getResult(a, b, '*'));   
  12.         System.out.println(cal.getResult(a, b, '/'));   
  13.         System.out.println(cal.getResult(a, b, '('));   
  14.     }   
  15.   
  16. }   

 

运行结果为:

 相加结果为:250.0
相减结果为:150.0
相乘结果为:10000.0
相除结果为:4.0
出错

2. 用策略模式来实现:

策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。
策略模式使得算法可以在不影响到客户端的情况下发生变化。使用策略模式可以把行为和环境分割开来。
环境类负责维持和查询行为类,各种算法则在具体策略中提供。由于算法和环境独立开来,算法的修改都不会影响环境和客户端

策略模式:

由三部分组成

A:  抽象策略角色:策略类,通常由一个接口或者抽象类实现
B:  具体策略角色:包装了相关的算法和行为
C:  环境角色:持有一个策略类的引用,最终给客户端调用的。

一个抽象策略角色:

java 代码
  1. package org.strategy;   
  2. /**  
  3.  * 抽象策略角色  
  4.  */  
  5. public abstract class AbstractStrategy {   
  6.   
  7.     public abstract String calculate(float a,float b);   
  8. }   

几个具体策略角色:

java 代码
  1. package org.strategy;   
  2. /**  
  3.  * 具体策略角色  
  4.  */  
  5. public class SubStrategy extends AbstractStrategy{   
  6.   
  7.     public  String calculate(float a,float b){   
  8.         float result = a-b;   
  9.         return "相减结果为:" + result;   
  10.     }   
  11. }  

 

java 代码
  1. package org.strategy;   
  2. /**  
  3.  * 具体策略角色  
  4.  */  
  5. public class AddStrategy extends AbstractStrategy{   
  6.   
  7.     public  String calculate(float a,float b){   
  8.         float result = a+b;   
  9.         return "相加结果为:" + result;   
  10.     }   
  11. }   

 

java 代码
  1. package org.strategy;   
  2. /**  
  3.  * 具体策略角色  
  4.  */  
  5. public class MultStrategy extends AbstractStrategy{   
  6.   
  7.     public  String calculate(float a,float b){   
  8.         float result = a*b;   
  9.         return "相乘结果为:" + result;   
  10.     }   
  11. }  

 

 

java 代码
  1. package org.strategy;   
  2. /**  
  3.  * 具体策略角色  
  4.  */  
  5. public class DivisionStrategy extends AbstractStrategy{   
  6.   
  7.     public  String calculate(float a,float b){   
  8.         float result = a/b;   
  9.         return "相除结果为:" + result;   
  10.     }   
  11. }   

环境角色:

java 代码
  1. package org.strategy;   
  2. /**  
  3.  * 环境角色,最终给客户端调用的  
  4.  */  
  5. public class ContextRole {   
  6.   
  7.     /**  
  8.      * 拥有一个策略类的引用  
  9.      */  
  10.     private AbstractStrategy abstactStrategy;   
  11.        
  12.     public ContextRole(AbstractStrategy abstactStrategy){   
  13.         this.abstactStrategy = abstactStrategy;   
  14.     }   
  15.        
  16.     public String calculate(float a,float b) {   
  17.         String result = abstactStrategy.calculate(a, b);   
  18.         return result;   
  19.     }   
  20. }  

客户端调用:

java 代码
  1. package org.strategy;   
  2. /**  
  3.  * 客户端  
  4.  */  
  5. public class Test {   
  6.        
  7.     public static void main(String[] args){   
  8.         float a = 200;   
  9.         float b = 25;   
  10.            
  11.         ContextRole contextRole1 = new ContextRole(new AddStrategy());   
  12.         System.out.println(contextRole1.calculate(a, b));   
  13.            
  14.         ContextRole contextRole2 = new ContextRole(new SubStrategy());   
  15.         System.out.println(contextRole2.calculate(a, b));   
  16.            
  17.         ContextRole contextRole3 = new ContextRole(new MultStrategy());   
  18.         System.out.println(contextRole3.calculate(a, b));   
  19.            
  20.         ContextRole contextRole4 = new ContextRole(new DivisionStrategy());   
  21.         System.out.println(contextRole4.calculate(a, b));   
  22.            
  23.     }   
  24.   
  25. }   

 

输出结果为:

相加结果为:225.0
相减结果为:175.0
相乘结果为:5000.0
相除结果为:8.0

总结:

策略模式优点:

1.可以很方便的动态改变算法或行为

2.避免使用多重条件转移语句

策略模式缺点:


1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
2.造成很多的策略类。

posted @ 2008-11-04 09:38 caihaibo 阅读(232) | 评论 (0)编辑 收藏

一、首先Java的基础、面向对象的基础和设计模式的基础知识是必不可少的。

关于设计模式我觉得不用学太多,但以下三个模式是学习Spring必不可少的:factory模式(包括简单工厂和抽象工厂), Strategy模式,Template method模式。如果不掌握这些你就根本没法领悟Spring的精髓,只能依样画葫芦地照搬,这是很可怕的事。

我这里强烈建议的书可能让人有点意外,那就是Expert one on one J2EE design and development的第四章,这一章不仅仅是Spring初学者,而是任何搞Java开发的人必读的一章。经典!

二、接下可以看一些Spring的入门书籍

其实我自己没怎么看过这方面的书,我当时只看过Spring的reference,不过现在这方面的书好象多的是,而Spring reference看起来还是有些吃力的。JavaEye上很多人建议夏昕的Spring开发指南,据说入门很容易。另外的入门书应该是Spring live或Spring in action。我大概扫了一下,Spring live是一本只讲怎么做而不讲为什么的书,我不太喜欢(偶尔参考一下倒不错),不过有些人特别喜欢这样的书,看自己的个人爱好吧。

三、研究几个用Spring做的开源项目

理论还是要与实际结合,所以看完书后是要看实际的项目的。很多人喜欢appfuse,我觉得appfuse花的东西太多,真正实质性的内容又太少。我更 喜欢Spring自带的jpetstore,这是一个非常完整的例子,看完后Spring的基本用法应该都能掌握。

四、开始做实际的项目

在上述这些都完备以后,我觉得应该要去实际项目中锻炼了。当然并不是每人都有这样的机会的,这时只能自己做个玩具项目啦。项目的锻炼是非常关键的,其实每个人都清楚,我就不重复了。

五、继续深入学习

经过项目的锤炼,对Spring的用法和原理有了一定的了解的时候,才有可能真正掌握Spring的精髓。这时要读的书才是Rod Johnson的三本经典名著,分别是:

Expert one on one J2ee design and development

Expert one on one J2ee without EJB

Professional Java Development with SpringFramework

前两本书的经典程度我就不说了,只有读了它们,才能真正了解Spring的设计意图,掌握Spring的精髓。

第三本书是我强烈不建议初学者读的书。里面的东西深入而全,但是原理讲解得又不够深,很容易让初学者犯迷糊。但是却是Spring的高级用户必读的一本书(还有一本pro Spring据说也不错,不过我没读过)。我过几天会写一下这本书的书评。

当然这个阶段与第四阶段是交错的,边读书边做项目学到的东西才会更多的。

六、分析源代码,扩展Spring

有人认为没有必要分析Spring的源代码,因为这是很累人又不计好的事。但是要想成为Spring的高级用户,这是必经的阶段。在学习的过 程中,我们学到的不仅是Spring,更重要的是他的设计思想。不管怎样,看牛人的源代码是绝对有好处的。不过这是一个很累人的过程,要有思考准备哦

posted @ 2008-11-03 18:09 caihaibo 阅读(177) | 评论 (0)编辑 收藏
Cookie的目的就是为用户带来方便,为网站带来增值。虽然有着许多误传,事实上Cookie并不会造成严重的安全威胁。Cookie永远不会以任何方 式执行,因此也不会带来病毒或攻击你的系统。另外,由于浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个 Cookie的大小限制为4   KB,因此Cookie不会塞满你的硬盘,更不会被用作“拒绝服务”攻击手段。
posted @ 2008-10-31 16:03 caihaibo 阅读(256) | 评论 (0)编辑 收藏

注:本文转载自 IBM developerworks,作者廖雪峰。版权归原作者所有。

JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与 JavaScript 的交互。本文将快速讲解 JSON 格式,并通过代码示例演示如何分别在客户端和服务器端进行 JSON 格式数据的处理。

尽管有许多宣传关于 XML 如何拥有跨平台,跨语言的优势,然而,除非应用于 Web Services,否则,在普通的 Web 应用中,开发者经常为 XML 的解析伤透了脑筋,无论是服务器端生成或处理 XML,还是客户端用 JavaScript 解析 XML,都常常导致复杂的代码,极低的开发效率。实际上,对于大多数 Web 应用来说,他们根本不需要复杂的 XML 来传输数据,XML 的扩展性很少具有优势,许多 AJAX 应用甚至直接返回 HTML 片段来构建动态 Web 页面。和返回 XML 并解析它相比,返回 HTML 片段大大降低了系统的复杂性,但同时缺少了一定的灵活性。

现在, JSON 为 Web 应用开发者提供了另一种数据交换格式。让我们来看看 JSON 到底是什么,同 XML 或 HTML 片段相比,JSON 提供了更好的简单性和灵活性。

和 XML 一样,JSON 也是基于纯文本的数据格式。由于 JSON 天生是为 JavaScript 准备的,因此,JSON 的数据格式非常简单,您可以用 JSON 传输一个简单的 String,Number,Boolean,也可以传输一个数组,或者一个复杂的 Object 对象。

String,Number 和 Boolean 用 JSON 表示非常简单。例如,用 JSON 表示一个简单的 String “ abc ”,其格式为:

"abc"

除了字符 ""/ 和一些控制符("b"f"n"r"t)需要编码外,其他 Unicode 字符可以直接输出。下图是一个 String 的完整表示结构:

 图 1. String 的完整表示结构  
一个 Number 可以根据整型或浮点数表示如下:

 图 2. Number 的表示结构  
这与绝大多数编程语言的表示方法一致,例如:

12345(整数)
-3.9e10(浮点数)

Boolean 类型表示为 true 或 false 。此外,JavaScript 中的 null 被表示为 null,注意,truefalse 和 null 都没有双引号,否则将被视为一个 String 。

JSON 还可以表示一个数组对象,使用 [] 包含所有元素,每个元素用逗号分隔,元素可以是任意的 Value,例如,以下数组包含了一个 String,Number,Boolean 和一个 null:

["abc",12345,false,null]

Object 对象在 JSON 中是用 {} 包含一系列无序的 Key-Value 键值对表示的,实际上此处的 Object 相当于 Java 中的 Map<String, Object>,而不是 Java 的 Class 。注意 Key 只能用 String 表示。

例如,一个 Address 对象包含如下 Key-Value:

city:Beijing
street:Chaoyang Road
postcode:100025(整数)

用 JSON 表示如下:

{"city":"Beijing","street":" Chaoyang Road ","postcode":100025}

其中 Value 也可以是另一个 Object 或者数组,因此,复杂的 Object 可以嵌套表示,例如,一个 Person 对象包含 name 和 address 对象,可以表示如下:

{"name":"Michael","address":
{"city":"Beijing","street":" Chaoyang Road ","postcode":100025}
}

上面介绍了如何用 JSON 表示数据,接下来,我们还要解决如何在服务器端生成 JSON 格式的数据以便发送到客户端,以及客户端如何使用 JavaScript 处理 JSON 格式的数据。

我们先讨论如何在 Web 页面中用 JavaScript 处理 JSON 数据。我们通过一个简单的 JavaScript 方法就能看到客户端如何将 JSON 数据表示给用户:

function handleJson() {
var j={"name":"Michael","address":
{"city":"Beijing","street":" Chaoyang Road ","postcode":100025}
};
document.write(j.name);
document.write(j.address.city);
}

假定服务器返回的 JSON 数据是上文的:

{"name":"Michael","address":
{"city":"Beijing","street":" Chaoyang Road ","postcode":100025}
}

只需将其赋值给一个 JavaScript 变量,就可以立刻使用该变量并更新页面中的信息了,相比 XML 需要从 DOM 中读取各种节点而言,JSON 的使用非常容易。我们需要做的仅仅是发送一个 Ajax 请求,然后将服务器返回的 JSON 数据赋值给一个变量即可。有许多 Ajax 框架早已包含了处理 JSON 数据的能力,例如 Prototype(一个流行的 JavaScript 库:http://prototypejs.org)提供了 evalJSON()方法,能直接将服务器返回的 JSON 文本变成一个 JavaScript 变量:

new Ajax.Request("http://url", {
method: "get",
onSuccess: function(transport) {
var json = transport.responseText.evalJSON();
// TODO: document.write(json.xxx);
}
});

下面我们讨论如何在服务器端输出 JSON 格式的数据。以 Java 为例,我们将演示将一个 Java 对象编码为 JSON 格式的文本。

将 String 对象编码为 JSON 格式时,只需处理好特殊字符即可。另外,必须用 (") 而非 (') 表示字符串:

 static String string2Json(String s) {
StringBuilder sb = new StringBuilder(s.length()+20);
sb.append('""');
for (int i=0; i<s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '""':
sb.append("""""");
break;
case '""':
sb.append("""""");
break;
case '/':
sb.append("""/");
break;
case '"b':
sb.append("""b");
break;
case '"f':
sb.append("""f");
break;
case '"n':
sb.append("""n");
break;
case '"r':
sb.append("""r");
break;
case '"t':
sb.append("""t");
break;
default:
sb.append(c);
}
}
sb.append('""');
return sb.toString();
}

将 Number 表示为 JSON 就容易得多,利用 Java 的多态,我们可以处理 Integer,Long,Float 等多种 Number 格式:

 static String number2Json(Number number) {
return number.toString();
}

Boolean 类型也可以直接通过 toString() 方法得到 JSON 的表示:

 static String boolean2Json(Boolean bool) {
return bool.toString();
}

要将数组编码为 JSON 格式,可以通过循环将每一个元素编码出来:

 static String array2Json(Object[] array) {
if (array.length==0)
return "[]";
StringBuilder sb = new StringBuilder(array.length << 4);
sb.append('[');
for (Object o : array) {
sb.append(toJson(o));
sb.append(',');
}
// 将最后添加的 ',' 变为 ']':
sb.setCharAt(sb.length()-1, ']');
return sb.toString();
}

最后,我们需要将 Map<String, Object> 编码为 JSON 格式,因为 JavaScript 的 Object 实际上对应的是 Java 的 Map<String, Object> 。该方法如下:

 static String map2Json(Map<String, Object> map) {
if (map.isEmpty())
return "{}";
StringBuilder sb = new StringBuilder(map.size() << 4);
sb.append('{');
Set<String> keys = map.keySet();
for (String key : keys) {
Object value = map.get(key);
sb.append('""');
sb.append(key);
sb.append('""');
sb.append(':');
sb.append(toJson(value));
sb.append(',');
}
// 将最后的 ',' 变为 '}':
sb.setCharAt(sb.length()-1, '}');
return sb.toString();
}

为了统一处理任意的 Java 对象,我们编写一个入口方法 toJson(Object),能够将任意的 Java 对象编码为 JSON 格式:

 public static String toJson(Object o) {
if (o==null)
return "null";
if (o instanceof String)
return string2Json((String)o);
if (o instanceof Boolean)
return boolean2Json((Boolean)o);
if (o instanceof Number)
return number2Json((Number)o);
if (o instanceof Map)
return map2Json((Map<String, Object>)o);
if (o instanceof Object[])
return array2Json((Object[])o);
throw new RuntimeException("Unsupported type: " + o.getClass().getName());
}

我们并未对 Java 对象作严格的检查。不被支持的对象(例如 List)将直接抛出 RuntimeException 。此外,为了保证输出的 JSON 是有效的,Map<String, Object> 对象的 Key 也不能包含特殊字符。细心的读者可能还会发现循环引用的对象会引发无限递归,例如,精心构造一个循环引用的 Map,就可以检测到 StackOverflowException

 @Test(expected=StackOverflowError.class)
public void testRecurrsiveMap2Json() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("key", map);
JsonUtil.map2Json(map);
}

好在服务器处理的 JSON 数据最终都应该转化为简单的 JavaScript 对象,因此,递归引用的可能性很小。

最后,通过 Servlet 或 MVC 框架输出 JSON 时,需要设置正确的 MIME 类型(application/json)和字符编码。假定服务器使用 UTF-8 编码,则可以使用以下代码输出编码后的 JSON 文本:

 response.setContentType("application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter pw = response.getWriter();
pw.write(JsonUtil.toJson(obj));

注:本文转载自 IBM developerworks,作者廖雪峰。版权归原作者所有。

JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与 JavaScript 的交互。本文将快速讲解 JSON 格式,并通过代码示例演示如何分别在客户端和服务器端进行 JSON 格式数据的处理。

尽管有许多宣传关于 XML 如何拥有跨平台,跨语言的优势,然而,除非应用于 Web Services,否则,在普通的 Web 应用中,开发者经常为 XML 的解析伤透了脑筋,无论是服务器端生成或处理 XML,还是客户端用 JavaScript 解析 XML,都常常导致复杂的代码,极低的开发效率。实际上,对于大多数 Web 应用来说,他们根本不需要复杂的 XML 来传输数据,XML 的扩展性很少具有优势,许多 AJAX 应用甚至直接返回 HTML 片段来构建动态 Web 页面。和返回 XML 并解析它相比,返回 HTML 片段大大降低了系统的复杂性,但同时缺少了一定的灵活性。

现在, JSON 为 Web 应用开发者提供了另一种数据交换格式。让我们来看看 JSON 到底是什么,同 XML 或 HTML 片段相比,JSON 提供了更好的简单性和灵活性。

和 XML 一样,JSON 也是基于纯文本的数据格式。由于 JSON 天生是为 JavaScript 准备的,因此,JSON 的数据格式非常简单,您可以用 JSON 传输一个简单的 String,Number,Boolean,也可以传输一个数组,或者一个复杂的 Object 对象。

String,Number 和 Boolean 用 JSON 表示非常简单。例如,用 JSON 表示一个简单的 String “ abc ”,其格式为:

"abc"

除了字符 ""/ 和一些控制符("b"f"n"r"t)需要编码外,其他 Unicode 字符可以直接输出。下图是一个 String 的完整表示结构:

 图 1. String 的完整表示结构  
一个 Number 可以根据整型或浮点数表示如下:

 图 2. Number 的表示结构  
这与绝大多数编程语言的表示方法一致,例如:

12345(整数) -3.9e10(浮点数)

Boolean 类型表示为 true 或 false 。此外,JavaScript 中的 null 被表示为 null,注意,truefalse 和 null 都没有双引号,否则将被视为一个 String 。

JSON 还可以表示一个数组对象,使用 [] 包含所有元素,每个元素用逗号分隔,元素可以是任意的 Value,例如,以下数组包含了一个 String,Number,Boolean 和一个 null:

["abc",12345,false,null]

Object 对象在 JSON 中是用 {} 包含一系列无序的 Key-Value 键值对表示的,实际上此处的 Object 相当于 Java 中的 Map<String, Object>,而不是 Java 的 Class 。注意 Key 只能用 String 表示。

例如,一个 Address 对象包含如下 Key-Value:

city:Beijing street:Chaoyang Road postcode:100025(整数)

用 JSON 表示如下:

{"city":"Beijing","street":" Chaoyang Road ","postcode":100025}

其中 Value 也可以是另一个 Object 或者数组,因此,复杂的 Object 可以嵌套表示,例如,一个 Person 对象包含 name 和 address 对象,可以表示如下:

{"name":"Michael","address": {"city":"Beijing","street":" Chaoyang Road ","postcode":100025} }

上面介绍了如何用 JSON 表示数据,接下来,我们还要解决如何在服务器端生成 JSON 格式的数据以便发送到客户端,以及客户端如何使用 JavaScript 处理 JSON 格式的数据。

我们先讨论如何在 Web 页面中用 JavaScript 处理 JSON 数据。我们通过一个简单的 JavaScript 方法就能看到客户端如何将 JSON 数据表示给用户:

function handleJson() { var j={"name":"Michael","address": {"city":"Beijing","street":" Chaoyang Road ","postcode":100025} }; document.write(j.name); document.write(j.address.city); }

假定服务器返回的 JSON 数据是上文的:

{"name":"Michael","address": {"city":"Beijing","street":" Chaoyang Road ","postcode":100025} }

只需将其赋值给一个 JavaScript 变量,就可以立刻使用该变量并更新页面中的信息了,相比 XML 需要从 DOM 中读取各种节点而言,JSON 的使用非常容易。我们需要做的仅仅是发送一个 Ajax 请求,然后将服务器返回的 JSON 数据赋值给一个变量即可。有许多 Ajax 框架早已包含了处理 JSON 数据的能力,例如 Prototype(一个流行的 JavaScript 库:http://prototypejs.org)提供了 evalJSON()方法,能直接将服务器返回的 JSON 文本变成一个 JavaScript 变量:

new Ajax.Request("http://url", { method: "get", onSuccess: function(transport) { var json = transport.responseText.evalJSON(); // TODO: document.write(json.xxx); } });

下面我们讨论如何在服务器端输出 JSON 格式的数据。以 Java 为例,我们将演示将一个 Java 对象编码为 JSON 格式的文本。

将 String 对象编码为 JSON 格式时,只需处理好特殊字符即可。另外,必须用 (") 而非 (') 表示字符串:

static String string2Json(String s) { StringBuilder sb = new StringBuilder(s.length()+20); sb.append('""'); for (int i=0; i<s.length(); i++) { char c = s.charAt(i); switch (c) { case '""': sb.append(""""""); break; case '""': sb.append(""""""); break; case '/': sb.append("""/"); break; case '"b': sb.append("""b"); break; case '"f': sb.append("""f"); break; case '"n': sb.append("""n"); break; case '"r': sb.append("""r"); break; case '"t': sb.append("""t"); break; default: sb.append(c); } } sb.append('""'); return sb.toString(); }

将 Number 表示为 JSON 就容易得多,利用 Java 的多态,我们可以处理 Integer,Long,Float 等多种 Number 格式:

static String number2Json(Number number) { return number.toString(); }

Boolean 类型也可以直接通过 toString() 方法得到 JSON 的表示:

static String boolean2Json(Boolean bool) { return bool.toString(); }

要将数组编码为 JSON 格式,可以通过循环将每一个元素编码出来:

static String array2Json(Object[] array) { if (array.length==0) return "[]"; StringBuilder sb = new StringBuilder(array.length << 4); sb.append('['); for (Object o : array) { sb.append(toJson(o)); sb.append(','); } // 将最后添加的 ',' 变为 ']': sb.setCharAt(sb.length()-1, ']'); return sb.toString(); }

最后,我们需要将 Map<String, Object> 编码为 JSON 格式,因为 JavaScript 的 Object 实际上对应的是 Java 的 Map<String, Object> 。该方法如下:

static String map2Json(Map<String, Object> map) { if (map.isEmpty()) return "{}"; StringBuilder sb = new StringBuilder(map.size() << 4); sb.append('{'); Set<String> keys = map.keySet(); for (String key : keys) { Object value = map.get(key); sb.append('""'); sb.append(key); sb.append('""'); sb.append(':'); sb.append(toJson(value)); sb.append(','); } // 将最后的 ',' 变为 '}': sb.setCharAt(sb.length()-1, '}'); return sb.toString(); }

为了统一处理任意的 Java 对象,我们编写一个入口方法 toJson(Object),能够将任意的 Java 对象编码为 JSON 格式:

public static String toJson(Object o) { if (o==null) return "null"; if (o instanceof String) return string2Json((String)o); if (o instanceof Boolean) return boolean2Json((Boolean)o); if (o instanceof Number) return number2Json((Number)o); if (o instanceof Map) return map2Json((Map<String, Object>)o); if (o instanceof Object[]) return array2Json((Object[])o); throw new RuntimeException("Unsupported type: " + o.getClass().getName()); }

我们并未对 Java 对象作严格的检查。不被支持的对象(例如 List)将直接抛出 RuntimeException 。此外,为了保证输出的 JSON 是有效的,Map<String, Object> 对象的 Key 也不能包含特殊字符。细心的读者可能还会发现循环引用的对象会引发无限递归,例如,精心构造一个循环引用的 Map,就可以检测到 StackOverflowException

@Test(expected=StackOverflowError.class) public void testRecurrsiveMap2Json() { Map<String, Object> map = new HashMap<String, Object>(); map.put("key", map); JsonUtil.map2Json(map); }

好在服务器处理的 JSON 数据最终都应该转化为简单的 JavaScript 对象,因此,递归引用的可能性很小。

最后,通过 Servlet 或 MVC 框架输出 JSON 时,需要设置正确的 MIME 类型(application/json)和字符编码。假定服务器使用 UTF-8 编码,则可以使用以下代码输出编码后的 JSON 文本:

response.setContentType("application/json;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter pw = response.getWriter(); pw.write(JsonUtil.toJson(obj)); pw.flush();

JSON 已经是 JavaScript 标准的一部分。目前,主流的浏览器对 JSON 支持都非常完善。应用 JSON,我们可以从 XML 的解析中摆脱出来,对那些应用 Ajax 的 Web 2.0 网站来说,JSON 确实是目前最灵活的轻量级方案。

 pw.flush();

JSON 已经是 JavaScript 标准的一部分。目前,主流的浏览器对 JSON 支持都非常完善。应用 JSON,我们可以从 XML 的解析中摆脱出来,对那些应用 Ajax 的 Web 2.0 网站来说,JSON 确实是目前最灵活的轻量级方案。

posted @ 2008-10-31 12:10 caihaibo 阅读(201) | 评论 (0)编辑 收藏
相关的bean如下
TVO.java代码如下
Java代码 复制代码
  1. package demo;  
  2.   
  3. import java.util.*;  
  4.   
  5. import com.easylotto.lottobar.bean.BaseEntity;  
  6. import com.easylotto.lottobar.bean.ReqCommandVO;  
  7.   
  8. public class TVO extends BaseEntity{  
  9.     private String tname;  
  10.     private List<Person> rcvoList;  
  11.     private Map map;  
  12.       
  13.     public List<Person> getRcvoList() {  
  14.         return rcvoList;  
  15.     }  
  16.   
  17.     public void setRcvoList(List<Person> rcvoList) {  
  18.         this.rcvoList = rcvoList;  
  19.     }  
  20.   
  21.     public String getTname() {  
  22.         return tname;  
  23.     }  
  24.   
  25.     public void setTname(String tname) {  
  26.         this.tname = tname;  
  27.     }  
  28.       
  29.   
  30.     public Map getMap() {  
  31.         return map;  
  32.     }  
  33.   
  34.     public void setMap(Map map) {  
  35.         this.map = map;  
  36.     }  
  37.   
  38.     /** 
  39.      * @param args 
  40.      */  
  41.     public static void main(String[] args) {  
  42.         // TODO Auto-generated method stub  
  43.   
  44.     }  
  45.   
  46. }  

Person.java如下
Java代码 复制代码
  1. package demo;  
  2.   
  3. public class Person {  
  4.     private String name;  
  5.     private String age;  
  6.       
  7.     public Person(String name,String age){  
  8.         this.name=name;  
  9.         this.age=age;  
  10.     }  
  11.     public String getAge() {  
  12.         return age;  
  13.     }  
  14.     public void setAge(String age) {  
  15.         this.age = age;  
  16.     }  
  17.     public String getName() {  
  18.         return name;  
  19.     }  
  20.     public void setName(String name) {  
  21.         this.name = name;  
  22.     }  
  23.       
  24. }  


测试类如下:
Java代码 复制代码
  1. package demo;  
  2.   
  3. import net.sf.json.*;  
  4. import java.util.*;  
  5.   
  6. import com.easylotto.lottobar.bean.ReqCommandVO;  
  7. import com.easylotto.lottobar.bean.SocketCommandEntity;  
  8.   
  9. /** 
  10.  * Json使用测试类 
  11.  * @author peidw  
  12.  * 
  13.  */  
  14. public class JsonDemo {  
  15.       
  16.     public String JsonStr2Object(){  
  17.         String str="{'map':{'a2':'A2','a1':'A1'},'rcvoList':[{'age':'20','name':'小裴'},{'age':'58','name':'小庞'}],'tname':'xxname'}";  
  18.         JSONObject jo=JSONObject.fromObject(str);  
  19.         TVO sce=null;  
  20.         if(jo!=null){  
  21.             sce=(TVO)jo.toBean(jo, TVO.class);  
  22.             List alist=sce.getRcvoList();  
  23.             System.out.println(alist.size());  
  24.             Person rcvo=null;  
  25.             for(int i=0;i<alist.size();i++){  
  26.                 rcvo=(Person)alist.get(i);  
  27.                 System.out.print(rcvo.getName()+"-"+rcvo.getAge());  
  28.             }  
  29.         }  
  30.   
  31.   
  32.         return "测试";  
  33.     }  
  34.       
  35.     public void Object2JsonStr(){  
  36.   
  37.         TVO tvo=new TVO();  
  38.         tvo.setTname("xxname");  
  39.         List <Person>a=new ArrayList();  
  40.         a.add(new Person("小裴","20"));  
  41.         a.add(new Person("小庞","58"));  
  42.         tvo.setRcvoList(a);  
  43.         Map map=new HashMap();  
  44.         map.put("a1", "A1");  
  45.         map.put("a2", "A2");  
  46.         tvo.setMap(map);  
  47.         JSONObject jo=JSONObject.fromObject(tvo);  
  48.         System.out.println(jo);  
  49.     }  
  50.       
  51.     public static void main(String[] args){  
  52.         JsonDemo jd=new JsonDemo();  
  53.         jd.JsonStr2Object();  
  54.         //jd.Object2JsonStr();  
  55.     }  
  56. }  


出现的异常如下
2
Exception in thread "main" java.lang.ClassCastException: net.sf.ezmorph.bean.MorphDynaBean
at demo.JsonDemo.JsonStr2Object(JsonDemo.java:26)
at demo.JsonDemo.main(JsonDemo.java:53)
使用的是json-lib-2.2.1-jdk15.jar包,请问这是怎么回事,怎么解决?


这个问题有两个地方值得考虑:
1、一个就是json-lib好像是使用反射实现的,那你的Person类如果没有无参数的构造方法的话,很危险;
2、在你的转化的代码上并没有告诉程序把rcvoList里的数据为何种类型

为此正确的做法是,为Person添加无参数的构造方法,同时修改代码为:

if(jo!=null){ 
             Map<String, Class> m = new HashMap<String, Class>();
             m.put("rcvoList", Person.class);
             sce=(TVO)JSONObject.toBean(jo, TVO.class, m);

这样应该就OK了…………
posted @ 2008-10-31 11:36 caihaibo 阅读(1629) | 评论 (2)编辑 收藏

有人说,创业是孤独的,是寂寞的,你只能独自前行;而我说:朋友,一切都不象你说的那样!有许多与你同路的朋友,何不一起搭个手,做个伴.让我们一起分享创业路上的喜悦和艰难!

    这是我的创业失败总结,我想告戒自己,同时也告诉世人:做多错多,成功只是你看得见的那冰山一角。多少亿万富翁的过去都成为了传奇,我却想留给人们他真实的一面,失败的一面。如果有后来人创业,我有些经验可以共享:

    1、以你现有的经验、能力、资源、资金等,考虑你是要做名商人还是法人,小商人只须自己有能力,法人则要依靠运营系统。如有可能,最好做到在外是商人,在内是法人。

    2、无论你是做商人还是法人,首先要进入相对朝阳的产业。须记住:90%的企业死在了行业选择的决策性失误里,剩余90%的企业,则死在了她一直建不起来的企业系统里。

    3、应考虑你所长,进入你熟悉的领域,不要全力投入你不熟悉的领域。如果实在要做,应做好充足的资金准备,充分的勤奋准备,以及相应的得力人手。否则,及早退出。

    4、进入一个市场,最重要的是要考虑你想解决什么问题,有多大空间,对手怎样,你应在何时用何种方式来解决;如果资金不多,赶紧找盈利的现金点和小模式,不可恋战。

    5、用较长的时间来寻找适合的股东,不可侥幸;所谓成也萧何败也萧何,一个人做的风险远小于与不适合的股东合伙;且做为创业的掌盘者,应宽容、积极、善待你的股东。

    6、公司开始运营,你当身先士卒;有20人时,根据2/8定律,应有4名骨干,你居中协调;有10来名骨干时,帅、将、兵应培养上,同时你自己退后,继续扶持、严管。

    7、管理就是奖和惩,再加企业文化的润滑。管理没有捷径,你投入得越多,你的根基就越深,同时系统枝繁叶茂。领导者要建机制,管理者则首要的是管目标,其次是管人。

    8、领导者是开局者,管理者是服从者。领导者要能听懂人言,善于纳谏,但要一个人拿主意,因为风险都是你的。决策既定,则要说服沟通后贯彻执行,不可朝令夕止。

    9、领导者最重要的四个素质——洞察力:否则难以判断对人和事;全局能力:否则难以平衡人和事;用人能力:否则你累死也做不完;影响力:经常被别人影响就不是领导。

    10、企业家的四要素——梦想:有梦想才有方向和目标;激情——激情是行动力是影响力;冒险——凡事走在前,成功概率越大竞争越激烈;责任——责任使你自律和坚韧。

    11、对于小企业融资,压上游和下游资金是上上策;降价成交、用预期换现、出租房屋是上策;找银行和机构贷款是中策;私人借款、内部集资是下策;信用卡透支、典当是下下策。

posted @ 2008-10-30 17:19 caihaibo| 编辑 收藏

/*
 * 写cookie
*/
Cookie namecookie = new Cookie("name",name);
Cookie passwordcookie = new Cookie("password",password);
Cookie optioncookie = new Cookie("option","1");

//生命周期    
namecookie.setMaxAge(60*60*24*365);
passwordcookie.setMaxAge(60*60*24*365);
optioncookie.setMaxAge(60*60*24*365);
    
response.addCookie(namecookie);
response.addCookie(passwordcookie); 
response.addCookie(optioncookie); 

/*
 * 读cookie
*/
Cookie[] cookies = request.getCookies();
if(cookies!=null)
{
    String name = "";
    String password = "";
    String option = "";
    for (int i = 0; i < cookies.length; i++)
    {
       Cookie c = cookies[i];     
       if(c.getName().equalsIgnoreCase("name"))
       {
          name = c.getValue();
        }
        else if(c.getName().equalsIgnoreCase("password"))
        {
           password = c.getValue();
        }
        else if(c.getName().equalsIgnoreCase("option"))
        {
           option = c.getValue();
        }     
    } 
  }

posted @ 2008-10-30 14:13 caihaibo 阅读(263) | 评论 (0)编辑 收藏
Firefox 中文浏览字体设置(附图)
上传时间:2007-9-21 10:15
相信此问题有不少 FF 中国用户会遇到,包括“软件界面”及“浏览页面”的字体。许多中国网民不接受 FF,和这一因素有莫大关系。很多时候,并非软件的问题,而是使用者自身的操作问题。微软操作系统集成了 IE,在这种情况下,FF 如果没有强大的优势,不可能在短短数年内与 IE 势均力敌,不可能成就目前的佳绩。Netscape 就是最好的反面说明。

以下是我作的字体设置附图。

posted @ 2008-10-29 16:12 caihaibo 阅读(454) | 评论 (0)编辑 收藏

Img240212257.jpg

    很多人尤其是青年学子来问我,你是怎样成功的?

我想说,实际我不像你们想象的那样很成功,尽管你发现我很自信,但实际上我是一个普通人。这就意味着,如果你们觉得你们也是普通人,我身上很多做法是值得借鉴的;如果你们觉得你们是不普通的人,在我身上是借鉴不到什么的。

一年前我出了一本书《道路与梦想》,当时对书名的争议很大,我坚持不同意见。光荣与梦想首先给人什么感觉?一是荣誉感,二是责任感。尽管我们普通人的荣誉和责任仅限于怎么做人,怎么做企业,但我们必须坚持。做人要有底线,坚持下去,成功就不是梦想。

普通人如何才能做到不普通的事?

第一,要有一个可触摸到的目标。就登山来讲,在2001年之前我从来没有想过要登珠峰,我1999年登的第一座山是6000米,第二座雪山是5200 米,登了这两座雪山后我想是不是应该登7000米,登了7000米后按照国家标准训练。2001年登上了慕士塔格峰,这时候想,珠峰咱也可以试一试。目标 不能好高骛远,要可以触及,这是第一点。

第二,锁定目标,一步一个脚印地去实现。对于登山队员来讲是这样,对农民子弟、城市子弟、大学生也是这样。

第三,要有承受失败的心理能力,因为事业当中不会一帆风顺。说句老实话,我也失败过,曾经想自杀,但最后没自杀,因为第二天太阳照常升起,一切都会好的。世界上有很多很糟糕的时候,你要有承受的勇气。

第四,运气。对我而言,努力之后,还不成功我不会后悔,在努力之前你永远不知道你能否成功,努力之后,还是失败,你只能怪你没有这个能力,有这个能力但没这个运气。

第五,对毕业生来讲,少点浮躁。我建议不要太在意找到的第一份工作。我创业是33岁以后的事,之前我当过兵,当过工人,当过工人去上大学,毕业之后搞过 专业工程技术,两年后又跳槽做翻译,这是我到深圳之前的五份工作,到了深圳之后才开始创业。所以不要太在意第一份工作,当然跳槽不能太频繁,太频繁会影响 一个人的心态。

最后,我把成功写成一个公式,供参考:

成功100%=运气90%+理想主义5%+激情2%+坚韧意志2%+控制力2%+自省力2%+平常心2%-浮躁1%-懒惰1%-贪婪1%-依赖1%-没有同情心1%。
posted @ 2008-10-21 19:08 caihaibo| 编辑 收藏

Tutorial:Playing With Ext The Easy Way (玩EXT简单方法)--firebug下调试ext

周五, 12/21/2007 - 02:45 — ppkosd
67
vote

蹒跚学步

第一步 - 入门

想必您已经听说过 Ext、浏览了在线演示,并且尝试阅读API文档。不过,面对复杂的API文档,您却不如何下手?!

第二步 - 起步

通览过API文档,并且找到了所要立刻尝试的功能,面对混杂的网页源代码,如何开始一个简单的测试页面?那么……

不论您的目标是什么,您都可以依照本文快速的开始使用Ext。不,不用搭建服务器,您所需要的仅仅是Firefox浏览器和Firebug调试插件。如果还没有安装,那么现在就是一个好机会。

firebug使用教程

牛刀小试

  • 打开Ext API文档,您已经上路!
  • 单击 F12 打开 Firebug 控制台。
  • 如果您的 firebug 控制台处于单行模式(以 '>>>' 开头),那么请单击右下角的红色上箭头以开启多行编辑模式。
  • 输入以下代码,并敲击 Ctrl-Enter 来运行:
Ext.get(document.body).update('<div id="test"></div>');

上边这行代码的作用是将当前DOM body元素用一个ID为test的div元素替换。刚才那些API文档已经被删除,但 Ext 代码依旧生效,并且随时为您效劳。

现在,我们假设您希望简单的添加一个面板元素(Panel),但对Ext.Panel的API冗繁的说明无能为力。那么试着将这些代码添加到 firebug 的控制台中:

Ext.get(document.body).update('<div id="test"></div>');
new Ext.Panel({ renderTo: 'test',
width: '200px',
title: 'My Title',
html: 'My HTML content' });

再次敲击 Ctrl-Enter 。嗨!您的面板元素已经诞生。

很好,不过如果修改一些选项呢?用下边的代码替换刚才的那些代码:

Ext.get(document.body).update('<div id="test"></div>');
new Ext.Panel({ renderTo: 'test',
width: '200px',
title: 'My Title',
html: 'My HTML content',
collapsible: true });

敲击 Ctrl-Enter 。怎么样,一个可以伸缩的面板就配置好了。(注意面板右上角的小图标)

每次敲击 Ctrl-Enter ,第一行代码都会移除现有的内容,这样您就可以有一个干净的调试环境。这是一个简单的小技巧,十分方便您尝试各种配置选项。

您可以为update()函数添加所需要的 HTML 代码,无论多少。然后编写或多或少的 Javascript 来探索 Ext API。

还等什么?现在就去亲自实践 Ext Api 吧。

posted @ 2008-07-17 15:18 caihaibo 阅读(100) | 评论 (0)编辑 收藏
要使用Oracle还需要做一些前期工作.

使用Oracle用户
# su - oracle

创建表空间 -> 创建新用户 -> 用户授权

一 创建表空间
SQL> CREATE TABLESPACE test01
DATAFILE '/data/oracle/oradata/db/test01.dbf' SIZE 1024M UNIFORM SIZE 128k;

1) DATAFILE: 表空间数据文件存放路径
2) SIZE: 起初设置为1G就可以
3) UNIFORM: 指定区尺寸为128k,如不指定,区尺寸默认为64k
4) 空间名称 test01 与 数据文件名称 test01.dbf 不要求相同,可随意命名.

二 创建新用户
SQL> CREATE USER test IDENTIFIED BY 123456 DEFAULT TABLESPACE test01;

1) 创建用户同时分配表空间

三 用户授权
1)用户角色授权
SQL> CRANT DBA TO test;

a) 我这里将DBA角色赋给新用户test,test将拥有DBA的所有操作权限.

2)直接授权
多用户
SQL> CRANT SELECT,INSERT,UPDATE,DELETE,ON USERS TO test,test1;

下面我们可以使用两种方式登录Oracle db
一 SQLPLUS
1)本地登录
SQL> sqlplus test/123456

2)远程登录
假设db在另一台服务器
SQL> sqlplus test/123456@db

二 PLSQL Developer
上篇中也有讲述,输入账号口令就可以了.


下面说些和上面相关,且工作中会需要用到的.
一 删除用户
SQL> DROP USER test CASCADE;

二 删除表空间
SQL> DROP TABLESPACE test01 INCLUDING CONTENTS AND DATAFILES;

1) 删除表空间内容和数据文件.
2) 一般无效表空间占用磁盘空间,所以这个应该很常用.
posted @ 2008-06-14 15:49 caihaibo 阅读(169) | 评论 (0)编辑 收藏

一、单节点元素操作

  对节点元素的操作是ExtJS的核心内容,大部分的Java操作都需要获取页面上某个节点元素,传统的Java方法,是通过ID来获得DOM节点的,例如我们的页面上有一个id值为content的DIV节点,我们想获得这个节点元素,用以下代码来获得:

var content = getElementById('content');

  而在ExtJS中,类似prototype中的$()方法,ExtJS拥有Ext.get()方法,可以使用

var content = Ext.get('content')

  看起来这并没有太大的优势,但是通过Ext.get返回的节点元素,将自动拥有快捷的、统一的、跨浏览器的接口,直接支持Cache,使多次访问同一节点元素的时候更加高效,并且直接使元素支持一些常用特效,例如:高亮,拖拽等。

  例如以下的HTML代码与js代码:

<body id="content">
hi
</body>
Ext.onReady(() {
Ext.get('content').highlight();
});

  当页面加载完毕之后,他将使整个页面刷下变黄,然后又褪掉了。

二、多节点元素操作

  ExtJS还支持一种使用Ext.select方法的多节点元素的操作,他将返回多个节点元素,与Ext.get方法一样,Ext.select方法返回的节点元素同样拥有那些Ext.get返回的节点元素所拥有的那些特性。

  例如这样的HTML与js代码:

<body id="content">
<p>
段落1
</p>
<div>
字符2
</div>
<p>
段落3
</p>
</body>
Ext.onReady(() {
Ext.select('p').highlight();
});

  当页面加载完毕之后,只有段落1和段落3变黄,然后又褪掉了。

posted @ 2008-06-12 17:55 caihaibo 阅读(709) | 评论 (0)编辑 收藏
在使用ext2.0中使用store加载数据出现this.onMetaChange has no properties错误
                                        var store=Ext.data.SimpleStore(
                                           
{
                                                fields:fields,
                                                data:data                                           
                                            }

           
                            );                                            

这儿是一段使用建造store数据库实例的方法,由于没有加new 构造实例,出现this.onMetaChange的错误
Tag标签: Ext
posted @ 2008-05-28 12:14 caihaibo 阅读(314) | 评论 (0)编辑 收藏
No result defined for action .....
这个问题出现发生的代码如下:

    public String execute() throws Exception {
        
// String path = getText("struts.multipart.saveDir");
        try {
            
int i = getMyDoc().length;

            
for (int j = 0; j < i; j++{
                File save 
= new File("C:/upload/" + getMyDocFileName()[j]);
                FileUtils.copyFile(getMyDoc()[j], save);
            }

        }
 catch (Exception e) {
            
return ActionSupport.ERROR;
        }

        
return ActionSupport.SUCCESS;

    }

这是用Struts2上传多个文件时候的一段代码,错误处理是遇到异常时return 一个ERROR,结果调用这个这个UploadAction报错 No result defined for action .....

应该修改成这样,捕获到异常时return ActionSupport.INPUT ,这样当页面第一次被载入时就不会报错了
posted @ 2008-05-28 09:43 caihaibo 阅读(383) | 评论 (0)编辑 收藏
 在java 企业应用领域,ejb的功能强大同ejb的配置复杂,难于学习一样出名。但在以前我们又有什么办法呢?只有硬着头皮来学ejb。真有点“明知山有虎,偏向虎山行”的精神。现在形式有了乐观的变化,java开源的持续走红,使得开发java企业级应用不再局限于ejb领域。这里我主要介绍一下怎样采用开源的 Spring,Hibernate以及Struts构建一个轻量级的架构。

一、整体架构介绍
    在软件工程领域,为了降低模块耦合度,提高模块的可重用性,分层一直是广为采纳的一个方法。其实分层还可以使开发人员专注于某一层进行开发,使得软件开发的分工变细,提高生产效率(这一点上堪比福特发明的流水线生产汽车的做法,各个工人负责特定部件的生产,最后组装)。
   
一个企业级的java应用,通常分为以下几层:UI层,业务逻辑层,数据持久层,域对象层。下面对这几层分别作简要介绍:
1.     UI层:负责与用户交互,包括:接受用户的请求,把处理结果返回给用户。这里我们采用struts来UI层,虽然比起Tapestry以及JSF这些事件驱动的表现层技术而言,Struts的设计显得有些老土,但它目前仍是表现层事实上的标准,所以我们还是选用它。
2.     业务逻辑层:主要负责具体的业务处理。通过Spring的IOC以及AOP实现各个功能的耦合相连
3.     数据持久层:主要负责与底层的数据库打交道。这里我们采用Spring封装的Hibernate操作来简化实际的编码。主要的操作为CRUD(create ,read,update,delete)
4.     域对象层:具体的实体类,如老师,学生等等这些具体的类(注意:需要与数据库中的某一标对应)。
以上只是简单介绍了各个层的划分以及各层所对应的开源框架,要详细了解各层的具层信息,需要访问 struts,hibernate,spring的官方网站。
二、实例分析
实例说明:一个网站登录的例子,比较简单,但能说明各层是如何协调工作的。
工具:jdk1.5,eclipse3.2,myeclipse5.0GA,mysql5.0,tomcat5.5,至于这几个工具到底该怎么装这里我就不多说了,大家不清楚的可以到网上搜搜。下面是具体操作步骤:
预备工作:用mysql创建一个test数据库,再创建一个user表,再创建两个字段username和password。脚本如下

DROP DATABASE IF EXISTS `test`;
CREATE DATABASE `test`
USE `test`;

CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(30) NOT NULL default '',
`password` varchar(30) default '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312;
打开myeclipse的database explore透视图




右键单击左侧的空白区域 ,点击 new 按钮



单击“configure database driver”来配置数据库的驱动,你必须有mysql的jdbc驱动 ,没有的到mysql的官方网站上下载。



测试数据库配置是否成功。

1.     新建一个myeclipse的web工程




2.     引入Spring包
右键工程名







注意:这里为了省得以后再添加spring的相关包,所以一次性的选中了所有的包。选中
Copy选项,它会把这些包拷贝到/WebRoot/WEB-INF/lib目录下,方便以后的实际部署。

3.添加hibernate包



系统会检测到该工程已经添加了Spring包,选择使用Spring的配置文件



点击 next



点击 next



点击 next



最后点击Finish按钮即可。
4切换到database explore视图,右键 点击 user 表的“Hibrnate Reverse Engineering”



弹出如下窗口



点击 “next”



再单击finish
    在包视图中 可以看到 src下多了一个名为vo的package以及该包下的四个文件



为了更加直观地显示分层,我另建了一个名为dao的package,并把UserDAO.java移到dao中



同时注意在applicationContext.xml中把对UserDAO的引用部分也作相应修改。
5.     建立业务逻辑层代码
新建一个名为service的包,再在里面建立一个Service类,代码如下
package service; import java.util.List; import vo.User; import dao.UserDAO; public class Service { private UserDAO userDao; public UserDAO getUserDao() { return userDao; } public void setUserDao(UserDAO userDao) { this.userDao = userDao; } public boolean isValid(User user) {//判断用户是否合法 List result = userDao.findByExample(user); if (result.size() > 0) return true; else return false; } }


同时在applicationContext.xml中添加如下配置
<bean id="service" class="service.Service" singleton="false">
        <property name="userDao">
              <ref bean="userDao" />
        </property>
    </bean>


6.配置UI层
  添加struts包,方法同添加spring一样



配置struts-config.xml文件,在空白区域右键单击 new 一个 action ,actionForm ,jsp










下一步
对forward作设置,增加succeed转到welcome.jsp,fail转到login.jsp

在WebRoot目录下建立一个welcome.jsp文件,显示用户登录成功后的欢迎信息。



6. 把struts和spring连接起来
6.1修改struts-config.xml注意红色字体部分
<action attribute="loginForm" input="/login.jsp" name="loginForm" path="/login" scope="request" type="org.springframework.web.struts.DelegatingActionProxy"> <forward name="fail" path="/login.jsp" /> <forward name="succeed" path="/welcome.jsp" /> </action>



    再在strut-config.xml中添加如下代码

<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/classes/applicationContext.xml" /> </plug-in>> 6.2修改applicationContext,增加以下内容 <bean name="/login" class="web.action.LoginAction" singleton="false"> <property name="service"> <ref bean="service" /> </property> </bean>

6.3修改LoginAction.java部分代码,增加一个service变量,以及其 get/set方法(主要用于Spring IOC)。代码如下:

/* * Generated by MyEclipse Struts * Template path: templates/java/JavaClass.vtl */ package web.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import web.form.LoginForm; import service.Service; import vo.User; /** * MyEclipse Struts Creation date: 09-27-2006 * * XDoclet definition: * * @struts.action path="/login" name="loginForm" input="/login.jsp" * scope="request" validate="true" * @struts.action-forward name="fail" path="/login.jsp" * @struts.action-forward name="succeed" path="/welcome.jsp" */ public class LoginAction extends Action { /* * Generated Methods */ /** * Method execute * * @param mapping * @param form * @param request * @param response * @return ActionForward */ private Service service; public void setService(Service service) { this.service = service; } public Service getService() { return service; } public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { LoginForm loginForm = (LoginForm) form;// TODO Auto-generated method // stub User user = new User(); user.setPassword(loginForm.getPassword()); user.setUsername(loginForm.getUserName()); if (service.isValid(user)) return mapping.findForward("succeed"); else return mapping.findForward("fail"); } }

  至此一个简单的登录已经做成。剩下的工作就是打包并发布你的应用了。 

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


posted @ 2008-05-26 14:32 caihaibo 阅读(260) | 评论 (0)编辑 收藏
IDE工具:eclipse3.0(插件:hibernate synchronize2.3.1)
框架:hibernate2.1+spring1.2
jar包:cglib-full-2.0.2.jar、commons-collections-2.1.1.jar、commons-dbcp-

1.2.1.jar、commons-lang-1.0.1.jar、commons-logging-1.0.4.jar、commons-

pool-1.2.jar、dom4j-1.4.jar、ehcache-0.9.jar、hibernate2.jar、jta.jar、

odmg-3.0.jar、spring.jar、xalan-2.4.0.jar、xerces-2.4.0.jar、xml-apis.jar

、jconn2.jar(我用的sybase数据库,这个是sybase的驱动)
数据库建表sql(sybase数据库):create table CUSTOMERS (ID int not null,

NAME nvarchar(15) not null, primary key (ID)) ;
create table ORDERS (
ID bigint not null,
ORDER_NUMBER varchar(15),
CUSTOMER_ID bigint,
primary key (ID)
);
alter table ORDERS add constraint FK_CUSTOMER foreign key ( CUSTOMER_ID)

references CUSTOMERS ;
(针对不同的数据有不同的sql语句,请自己修改)
hibernate synchronize插件可以生成hiberante.cfg.xml、Customer.hbm(用这个

插件直接生成的是hbm文件,不是hbm.xml文件)、Order.hbm、Customer.java、

Order.java、以及DAO类(注意:生成的DAO类不适合用spring,所以这里就不提及了

)。
因为这里我们要使用spring,所以直接用spring的配置文件即可(把

hiberante.cfg.xml的内容集成到spring配置文件中)。
以下是所有文件的代码:
1.spring配置文件hibernate_context.xml:
[code:1]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<!-- <bean id="viewResolver"

class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property

name="viewClass"><value>org.springframework.web.servlet.view.JstlView</val

ue></property>
<property name="prefix"><value>/WEB-INF/jsp/</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean> -->

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

<property name="driverClassName">
<value>com.sybase.jdbc2.jdbc.SybDriver</value>
</property>

<property name="url">
<value>jdbc:sybase:Tds:172.16.9.40:5000/quickstart</value>
</property>

<property name="username">
<value>sa</value>
</property>

<property name="password">
<value></value>
</property>
</bean>

<bean id="sessionFactory"

class="org.springframework.orm.hibernate.LocalSessionFactoryBean">

<property name="dataSource">
<ref local="dataSource" />
</property>

<property name="mappingResources">
<list>
<value>com/jacky/hibernate/domainmodel/Customer.hbm</value>
<value>com/jacky/hibernate/domainmodel/Order.hbm</value>
</list>
</property>

<property name="hibernateProperties">
<props>
<prop

key="hibernate.dialect">net.sf.hibernate.dialect.SybaseDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

<bean id="transactionManager"

class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>


<!-- Spring的数据访问异常转换器(Data Access Exception Translator)定义 -

->
<bean id="jdbcExceptionTranslator"

class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator

">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>

<!-- Hibernate Template定义 -->
<bean id="hibernateTemplate"

class="org.springframework.orm.hibernate.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
<property name="jdbcExceptionTranslator">
<ref bean="jdbcExceptionTranslator" />
</property>
</bean>

<!--baseTransactionProxy -->
<bean abstract="true"

class="org.springframework.transaction.interceptor.TransactionProxyFactory

Bean" id="baseTransactionProxy">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="find*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>


<bean id="customerDao"

class="com.jacky.hibernate.domainmodel.dao.CustomerHibernateDao">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>

<bean id="customerManagerTarget"

class="com.jacky.hibernate.service.CustomerManagerImpl">
<property name="customerDao">
<ref local="customerDao" />
</property>
</bean>

<bean id="customerManager"

class="org.springframework.transaction.interceptor.TransactionProxyFactory

Bean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>

<property name="target">
<ref local="customerManagerTarget" />
</property>

<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>

</beans>
[/code:1]

2.Customer.hbm:
[code:1]
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >

<hibernate-mapping package="com.jacky.hibernate.domainmodel">
<class name="Customer" table="CUSTOMERS" lazy="false">
<id column="ID"
name="Id"
type="integer"
>
<generator class="vm" />
</id>
<property
column="NAME"
length="15"
name="Name"
not-null="true"
type="string"
/>
<set inverse="true" name="ORDERSSet" lazy="false" batch-

size="4" outer-join="false">
<key column="CUSTOMER_ID" />
<one-to-many class="Order" />
</set>
</class>
</hibernate-mapping>
[/code:1]

3.Order.hbm:
[code:1]
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >

<hibernate-mapping package="com.jacky.hibernate.domainmodel">
<class name="Order" table="ORDERS" lazy="true">
<id
column="ID"
name="Id"
type="integer"
>
<generator class="vm" />
</id>
<property
column="ORDER_NUMBER"
length="15"
name="OrderNumber"
not-null="true"
type="string"
/>
<many-to-one
class="Customer"
name="Customer"
not-null="true"
outer-join="true"

>
<column name="CUSTOMER_ID" />
</many-to-one>
</class>
</hibernate-mapping>
[/code:1]

4.Customer.java:
[code:1]
package com.jacky.hibernate.domainmodel;

import com.jacky.hibernate.domainmodel.base.BaseCustomers;
//import java.util.Set;
//import java.util.HashSet;
/**
* This is the object class that relates to the CUSTOMERS table.
* Any customizations belong here.
*/
public class Customer extends BaseCustomers {

/*[CONSTRUCTOR MARKER BEGIN]*/
public Customer () {
super();
}

/**
* Constructor for primary key
*/
public Customer (java.lang.Integer _id) {
super(_id);
}

/**
* Constructor for required fields
*/
public Customer (
java.lang.Integer _id,
java.lang.String _name) {

super (
_id,
_name);
}

/*[CONSTRUCTOR MARKER END]*/

}
[/code:1]

5.BaseCustomer.java:
[code:1]
package com.jacky.hibernate.domainmodel.base;

import java.io.Serializable;


/**
* This class has been automatically generated by Hibernate Synchronizer.


* For more information or documentation, visit The Hibernate Synchronizer

page
* at http://www.binamics.com/hibernatesync or contact Joe Hudson at

joe@binamics.com.
*
* This is an object that contains data related to

the CUSTOMERS table.
* Do not modify this class because it will be overwritten if the

configuration file
* related to this class is modified.
*
* @hibernate.class
* table="CUSTOMERS"
*/
public abstract class BaseCustomer implements Serializable {

public static String PROP_NAME = "Name";
public static String PROP_ID = "Id";


private int hashCode = Integer.MIN_VALUE;

// primary key
private java.lang.Integer _id;

// fields
private java.lang.String _name;

// collections
private java.util.Set _oRDERSSet;


// constructors
public BaseCustomer () {
initialize();
}

/**
* Constructor for primary key
*/
public BaseCustomer (java.lang.Integer _id) {
this.setId(_id);
initialize();
}

/**
* Constructor for required fields
*/
public BaseCustomer (
java.lang.Integer _id,
java.lang.String _name) {

this.setId(_id);
this.setName(_name);
initialize();
}

protected void initialize () {}



/**
* Return the unique identifier of this class
* @hibernate.id
* generator-class="vm"
* column="ID"
*/
public java.lang.Integer getId () {
return _id;
}

/**
* Set the unique identifier of this class
* @param _id the new ID
*/
public void setId (java.lang.Integer _id) {
this._id = _id;
this.hashCode = Integer.MIN_VALUE;
}


/**
* Return the value associated with the column: NAME
*/
public java.lang.String getName () {
return _name;
}

/**
* Set the value related to the column: NAME
* @param _name the NAME value
*/
public void setName (java.lang.String _name) {
this._name = _name;
}


/**
* Return the value associated with the column: ORDERSSet


*/
public java.util.Set getORDERSSet () {
return this._oRDERSSet;
}

/**
* Set the value related to the column: ORDERSSet
* @param _oRDERSSet the ORDERSSet value
*/
public void setORDERSSet (java.util.Set _oRDERSSet) {
this._oRDERSSet = _oRDERSSet;
}

public void addToORDERSSet (Object obj) {
if (null == this._oRDERSSet) this._oRDERSSet = new

java.util.HashSet();
this._oRDERSSet.add(obj);
}



public boolean equals (Object obj) {
if (null == obj) return false;
if (!(obj instanceof

com.jacky.hibernate.domainmodel.base.BaseCustomer)) return false;
else {
com.jacky.hibernate.domainmodel.base.BaseCustomer

mObj = (com.jacky.hibernate.domainmodel.base.BaseCustomer) obj;
if (null == this.getId() || null == mObj.getId())

return false;
else return (this.getId().equals(mObj.getId()));
}
}


public int hashCode () {
if (Integer.MIN_VALUE == this.hashCode) {
if (null == this.getId()) return super.hashCode();
else {
String hashStr = this.getClass().getName()

+ ":" + this.getId().hashCode();
this.hashCode = hashStr.hashCode();
}
}
return this.hashCode;
}


public String toString () {
return super.toString();


}

}
[/code:1]

6.Order.java:
[code:1]
package com.jacky.hibernate.domainmodel;

import com.jacky.hibernate.domainmodel.base.BaseOrders;

/**
* This is the object class that relates to the ORDERS table.
* Any customizations belong here.
*/
public class Order extends BaseOrders {
private Customer customers;

/*[CONSTRUCTOR MARKER BEGIN]*/
public Order () {
super();
}

/**
* Constructor for primary key
*/
public Order (java.lang.Integer _id) {
super(_id);
}

/**
* Constructor for required fields
*/
public Order (
java.lang.Integer _id,
com.jacky.hibernate.domainmodel.Customer _customer,
java.lang.String _orderNumber) {

super (
_id,
_customer,
_orderNumber);
}

/*[CONSTRUCTOR MARKER END]*/

}
[/code:1]

7.BaseOrder.java:
[code:1]
package com.jacky.hibernate.domainmodel.base;

import java.io.Serializable;


/**
* This class has been automatically generated by Hibernate Synchronizer.


* For more information or documentation, visit The Hibernate Synchronizer

page
* at http://www.binamics.com/hibernatesync or contact Joe Hudson at

joe@binamics.com.
*
* This is an object that contains data related to

the ORDERS table.
* Do not modify this class because it will be overwritten if the

configuration file
* related to this class is modified.
*
* @hibernate.class
* table="ORDERS"
*/
public abstract class BaseOrder implements Serializable {

public static String PROP_ORDER_NUMBER = "OrderNumber";
public static String PROP_CUSTOMER = "Customer";
public static String PROP_ID = "Id";


private int hashCode = Integer.MIN_VALUE;

// primary key
private java.lang.Integer _id;

// fields
private java.lang.String _orderNumber;

// many to one
private com.jacky.hibernate.domainmodel.Customer _customer;


// constructors
public BaseOrder () {
initialize();
}

/**
* Constructor for primary key
*/
public BaseOrder (java.lang.Integer _id) {
this.setId(_id);
initialize();
}

/**
* Constructor for required fields
*/
public BaseOrder (
java.lang.Integer _id,
com.jacky.hibernate.domainmodel.Customer _customer,
java.lang.String _orderNumber) {

this.setId(_id);
this.setCustomer(_customer);
this.setOrderNumber(_orderNumber);
initialize();
}

protected void initialize () {}



/**
* Return the unique identifier of this class
* @hibernate.id
* generator-class="vm"
* column="ID"
*/
public java.lang.Integer getId () {
return _id;
}

/**
* Set the unique identifier of this class
* @param _id the new ID
*/
public void setId (java.lang.Integer _id) {
this._id = _id;
this.hashCode = Integer.MIN_VALUE;
}


/**
* Return the value associated with the column: ORDER_NUMBER
*/
public java.lang.String getOrderNumber () {
return _orderNumber;
}

/**
* Set the value related to the column: ORDER_NUMBER
* @param _orderNumber the ORDER_NUMBER value
*/
public void setOrderNumber (java.lang.String _orderNumber) {
this._orderNumber = _orderNumber;
}


/**
* @hibernate.property
* column=CUSTOMER_ID
* not-null=true
*/
public com.jacky.hibernate.domainmodel.Customer getCustomer () {
return this._customer;
}

/**
* Set the value related to the column: CUSTOMER_ID
* @param _customer the CUSTOMER_ID value
*/
public void setCustomer (com.jacky.hibernate.domainmodel.Customer

_customer) {
this._customer = _customer;
}


public boolean equals (Object obj) {
if (null == obj) return false;
if (!(obj instanceof

com.jacky.hibernate.domainmodel.base.BaseOrder)) return false;
else {
com.jacky.hibernate.domainmodel.base.BaseOrder

mObj = (com.jacky.hibernate.domainmodel.base.BaseOrder) obj;
if (null == this.getId() || null == mObj.getId())

return false;
else return (this.getId().equals(mObj.getId()));
}
}


public int hashCode () {
if (Integer.MIN_VALUE == this.hashCode) {
if (null == this.getId()) return super.hashCode();
else {
String hashStr = this.getClass().getName()

+ ":" + this.getId().hashCode();
this.hashCode = hashStr.hashCode();
}
}
return this.hashCode;
}


public String toString () {
return super.toString();


}

}
[/code:1]

8.IDAO.java:
[code:1]
/*
* 创建日期:2005-8-19
*
* 作者:<a href="mailto:jacky.jar@gmail.com">贾恺</a>
*/
package com.jacky.hibernate.domainmodel.dao;

/**
* @author 贾恺
*
* TODO 要更改此生成的类型注释的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/
public interface IDAO {

}
[/code:1]

9.ICustomerDao.java:
[code:1]
/*
* 创建日期:2005-8-19
*
* 作者:<a href="mailto:jacky.jar@gmail.com">贾恺</a>
*/
package com.jacky.hibernate.domainmodel.dao;

import java.util.List;

import com.jacky.hibernate.domainmodel.Customer;
/**
* @author 贾恺
*
* TODO 要更改此生成的类型注释的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/
public interface ICustomerDao extends IDAO {
public List getCustomer();
public Customer getCustomer(Integer id);
public List getCustomer(String name);
public void saveCustomer(Customer customer);
public void removeCustomer(String name);


}
[/code:1]

10.CustomerHibernateDao.java:
[code:1]
/*
* 创建日期:2005-8-19
*
* 作者:<a href="mailto:jacky.jar@gmail.com">贾恺</a>
*/
package com.jacky.hibernate.domainmodel.dao;

import java.util.List;

import org.springframework.orm.hibernate.support.HibernateDaoSupport;

import com.jacky.hibernate.domainmodel.Customer;

/**
* @author 贾恺
*
* TODO 要更改此生成的类型注释的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/

//import java.util.List;

import org.springframework.orm.ObjectRetrievalFailureException;
//import org.springframework.orm.hibernate.support.HibernateDaoSupport;

//import com.jacky.hibernate.domainmodel.Customer;
import com.jacky.hibernate.domainmodel.dao.ICustomerDao;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

public class CustomerHibernateDao extends HibernateDaoSupport implements
ICustomerDao {
private Log log = LogFactory.getLog(CustomerHibernateDao.class);

/* (非 Javadoc)
* @see

com.jacky.hibernate.domainmodel.dao.ICustomerDao#getCustomer()
*/
public List getCustomer() {
// TODO 自动生成方法存根
return getHibernateTemplate().find("from Customer");
}

/* (非 Javadoc)
* @see

com.jacky.hibernate.domainmodel.dao.ICustomerDao#getCustomer

(java.lang.String)
*/
public Customer getCustomer(Integer id) {
// TODO 自动生成方法存根
//log.info("***="+name);
Customer Customer = (Customer)getHibernateTemplate().load

(Customer.class,id);
System.out.println(Customer.getId());
if (Customer == null) {
throw new ObjectRetrievalFailureException(Customer.class,

id);
}
return Customer;
}

public List getCustomer(String name){
List list = getHibernateTemplate().find("from Customer

where NAME=?",name);
if (list == null) {
throw new ObjectRetrievalFailureException

(Customer.class, name);
}
return list;
}
/* (非 Javadoc)
* @see com.jacky.hibernate.domainmodel.dao.ICustomerDao#saveUser

(com.jacky.hibernate.domainmodel.Customer)
*/
public void saveCustomer(Customer Customer) {
// TODO 自动生成方法存根
log.info("saveCustomer(Customer Customer)");
getHibernateTemplate().saveOrUpdate(Customer);
if (log.isDebugEnabled()) {

log.debug("Customername set to " +

Customer.getName());

}
}

/* (非 Javadoc)
* @see

com.jacky.hibernate.domainmodel.dao.ICustomerDao#removeUser

(java.lang.String)
*/
public void removeCustomer(String name) {
// TODO 自动生成方法存根
Object Customer = getHibernateTemplate().load

(Customer.class, name);

getHibernateTemplate().delete(Customer);

if (log.isDebugEnabled()) {

log.debug("del Customer " + name);

}

}

}
[/code:1]

11.ICustomerManager.java:
[code:1]
/*
* 创建日期:2005-8-19
*
* 作者:<a href="mailto:jacky.jar@gmail.com">贾恺</a>
*/
package com.jacky.hibernate.service;

/**
* @author 贾恺
*
* TODO 要更改此生成的类型注释的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/

import java.util.List;

import com.jacky.hibernate.domainmodel.Customer;
import com.jacky.hibernate.domainmodel.dao.ICustomerDao;

public interface ICustomerManager {
public void setCustomerDAO(ICustomerDao dao);
public Customer getCustomer(Integer id);
public List getCustomer();
public List getCustomer(String name);
public Customer saveCustomer(Customer customer);
public void removeCustomer(String name);
}
[/code:1]

12.CustomerManagerImpl.java:
[code:1]
/*
* 创建日期:2005-8-19
*
* 作者:<a href="mailto:jacky.jar@gmail.com">贾恺</a>
*/
package com.jacky.hibernate.service;

import java.util.List;

import com.jacky.hibernate.domainmodel.Customer;
import com.jacky.hibernate.domainmodel.dao.ICustomerDao;
//import com.jacky.hibernate.domainmodel.dao.CustomersDAO;
/**
* @author 贾恺
*
* TODO 要更改此生成的类型注释的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/

//import java.util.List;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

public class CustomerManagerImpl implements ICustomerManager {
private static Log log = LogFactory.getLog

(CustomerManagerImpl.class);

public ICustomerDao customerDao;
/* (非 Javadoc)
* @see com.jacky.hibernate.service.ICustomersManager#setUserDAO

(com.jacky.hibernate.domainmodel.dao.ICustomersDao)
*/
public void setCustomerDAO(ICustomerDao dao) {
// TODO 自动生成方法存根
this.customerDao = dao;
}

public ICustomerDao getCustomersDao(){
return customerDao;
}

public void setCustomerDao(ICustomerDao customerDao){
this.customerDao = customerDao;
}
/* (非 Javadoc)
* @see

com.jacky.hibernate.service.ICustomersManager#getCustomers

(java.lang.String)
*/
public Customer getCustomer(Integer id) {
// TODO 自动生成方法存根
return customerDao.getCustomer(id);

}

/* (非 Javadoc)
* @see

com.jacky.hibernate.service.ICustomersManager#getCustomers()
*/
public List getCustomer() {
// TODO 自动生成方法存根
return customerDao.getCustomer();
}

public List getCustomer(String name){
return customerDao.getCustomer(name);
}
/* (非 Javadoc)
* @see com.jacky.hibernate.service.ICustomersManager#saveUser

(com.jacky.hibernate.domainmodel.Customers)
*/
public Customer saveCustomer(Customer customer) {
// TODO 自动生成方法存根
customerDao.saveCustomer(customer);
return customer;
}

/* (非 Javadoc)
* @see com.jacky.hibernate.service.ICustomersManager#removeUser

(java.lang.String)
*/
public void removeCustomer(String name) {
// TODO 自动生成方法存根
customerDao.removeCustomer(name);
}

}
[/code:1]

13.CustomersManagerImplTest.java:
[code:1]
/*
* 创建日期:2005-8-19
*
* 作者:<a href="mailto:jacky.jar@gmail.com">贾恺</a>
*/
package com.jacky.test;

/**
* @author 贾恺
*
* TODO 要更改此生成的类型注释的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.jacky.hibernate.domainmodel.Customer;
import com.jacky.hibernate.domainmodel.Order;
//import com.jacky.hibernate.service.CustomersManagerImpl;
import com.jacky.hibernate.service.ICustomerManager;

public class CustomersManagerImplTest {
private static final Log log = LogFactory.getLog

(CustomersManagerImplTest.class);
private ApplicationContext ac;
private static ICustomerManager cm;
public CustomersManagerImplTest(){
ac = new ClassPathXmlApplicationContext

("hibernate_context.xml");
cm = (ICustomerManager)ac.getBean

("customerManagerTarget");
log.info("welcome!");
}
public static void main(String[] args){
new CustomersManagerImplTest();
test(cm);
}

private static void test(ICustomerManager cm){
//getCustomer(cm);
getCustomer(new Integer(1));
//getCustomer("Tom");
}
private static void getCustomer(ICustomerManager cm){
Iterator it = cm.getCustomer().iterator();
while(it.hasNext()){
log.info("name="+((Customer)it.next()).getName());
}
}
private static void getCustomer(Integer id){
Customer customer = cm.getCustomer(id);
Set set = customer.getORDERSSet();
log.info("name="+customer.getName());
Iterator it = set.iterator();
while(it.hasNext()){
log.info(customer.getName()+":"+((Order)it.next

()).getOrderNumber());
}

}
private static void getCustomer(String name){
Iterator it = cm.getCustomer(name).iterator();
while(it.hasNext())log.info("id="+((Customer)it.next

()).getId());
}
}
[/code:1]

14.build.xml:
[code:1]
<?xml version="1.0"?>
<project name="Learning Hibernate" default="prepare" basedir=".">

<!-- Set up properties containing important project directories -->
<property name="source.root" value="src"/>
<property name="class.root" value="WEB-INF/classes"/>
<property name="lib.dir" value="WEB-INF/lib"/>

<!-- Set up the class path for compilation and execution -->
<path id="project.class.path">
<!-- Include our own classes, of course -->
<pathelement location="${class.root}" />
<!-- Include jars in the project library directory -->
<fileset dir="${lib.dir}">
<include name="*.jar"/>
</fileset>
</path>


<!-- Create our runtime subdirectories and copy resources into them -->
<target name="prepare" description="Sets up build structures">
<delete dir="${class.root}"/>
<mkdir dir="${class.root}"/>


<!-- Copy our property files and O/R mappings for use at runtime -->
<copy todir="${class.root}" >
<fileset dir="${source.root}" >
<include name="**/*.properties"/>
<include name="**/*.hbm.xml"/>
<include name="**/*.xml"/>
<include name="**/*.gif"/>
<include name="**/*.hbm"/>
</fileset>
</copy>

<delete dir="${lib.dir}"/>
<mkdir dir="${lib.dir}"/>
<!-- Copy our property files and O/R mappings for use at runtime

-->
<copy todir="${basedir}/WEB-INF" >
<fileset dir="${basedir}" >
<include name="lib/*.jar"/>
<include name="lib/*.tdt"/>
<include name="lib/*.xml"/>

</fileset>
</copy>
</target>

<!-- Compile the java source of the project -->
<target name="compile" depends="prepare"
description="Compiles all Java classes">
<javac srcdir="${source.root}"
destdir="${class.root}"
debug="on"
optimize="off"
deprecation="on">
<classpath refid="project.class.path"/>
</javac>
</target>

<target name="run" description="Run a Hibernate+spring sample"
depends="compile">
<java classname="com.jacky.test.CustomersManagerImplTest" fork="true">
<arg value="NativeTester" />
<classpath refid="project.class.path"/>
</java>
</target>

</project>
[/code:1]
posted @ 2008-05-21 22:34 caihaibo 阅读(1505) | 评论 (0)编辑 收藏
(1)下载Hibernate,并向项目中导入Hibernate。
     Project->Properies->Java Build Path->Libraries->Add External JARs...,选择Hibernate根目录下的hibernate3.jar,添加到项目中。
    接着,要将Hibernate下的lib文件夹下的所有文件都作为一个User Library添加到项目中,否则,如果仅仅添加hibernate3.jar,编译可以通过,运行却会抛出ClassNotDef的异常,因为hibernate3.jar依赖于Hibernate下的lib文件夹下的文件。

 2)我们的应用的后台数据库使用的是Oracle,所以首先要在例子项目中引入含有Oracle jdbc driver的包,classes12.jar。该jar文件位于oracle安装目录的jdbc\lib目录下。
    在Eclipse中,Project->Properies->Java Build Path->Libraries->Add External JARs...,选择classes12.jar,将其添加到项目中。
    
(3)生成hibernate.cfg.xml文件。
    通常Hibernate的配置文件和.hbm.xml文件都可以自动生成,这种自动生成的工具很多,我使用的是HibernateSynchronizer,它可以作为一个插件添加到Eclipse中。当HibernateSynchronizer插件正确加载后,我们可以向当前项目中添加Hibernate配置文件:File->New->Other->Hibernate->Hibernate Configuration File,出现如下界面:


  注意,Driver Class要选择针对Oracle的oracle.jdbc.driver.OracleDriver,而且Database URL的格式也要正确,如:
jdbc:oracle:thin:@10.8.8.221:1521:ORCL

    最好将hibernate.cfg.xml文件存放于项目的根目录下。

 4)生成.hbm.xml文件。File->New->Other->Hibernate->Hibernate Mapping File,出现如下界面:

     
    在填写完Password后,点击Refresh按钮,就会在Tables中列出所有可以访问的数据库表,然后选中要为其生成.hbm.xml文件的表,点击Finish,即会生成对应的.hbm.xml文件,比如我上面选择的是Mobileuser表,就会生成Mobileuser.hbm.xml文件。

(5)从.hbm.xml文件自动生成实体类。
    在Package Explorer中选中Mobileuser.hbm.xml文件,右键->Hibernate Synchronizer->Synchronize Files ,即可生成对应的实体类和DAO类。如果你仅仅想要实体类,那么可以在Project->Properies->Hibernate Synchronizer->Data Access Objects ,将“I would like to have DAOs created for me”的钩选项去掉即可。

(6)在hibernate.cfg.xml文件中添加对应的mapping resource。
    在Package Explorer中选中Mobileuser.hbm.xml文件,右键->Hibernate Synchronizer->Add Mapping Reference,即会在
hibernate.cfg.xml中自动生成如下配置:

<mapping resource="HibernateTest/Mobileuser.hbm.xml" />

(7)修改自动生成的hibernate.cfg.xml文件。需要在hibernate.cfg.xml文件的首部添加:

<!DOCTYPE hibernate-configuration PUBLIC
        
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

    比较繁琐的是,每次自动修改hibernate.cfg.xml文件后,都要重新添加这个xml片断。

    万事具备,现在可以写个测试来检验一下了:

    //仅仅作为示例,没有进行异常处理
    public static void main(String[] args)
    {
        Configuration cfg 
= new Configuration().configure() ;        
        SessionFactory  sFactory 
= cfg.buildSessionFactory() ;        
        
        Session session 
= sFactory.openSession() ;
        Transaction tx 
= session.beginTransaction();
        Mobileuser user 
= (Mobileuser)session.load(Mobileuser.class , new Integer(2)) ;
        String age 
= user.getMobilenumber() ;
        
        System.
out.println(age) ;
        tx.commit();
        session.close() ;
    }
posted @ 2008-05-19 14:25 caihaibo 阅读(383) | 评论 (0)编辑 收藏

介绍如何利用Hibernate Synchronizer插件在Eclipse 3.0.1中快速的开发Hibernate应用程序,提高我们的工作效率。

  Eclipse是目前非常流行的开发平台,开放扩展的架构让很多程序员找到了自己个性化的工作环境,Hibernate也是目前很流行的O/R Mapping框架,至少在EJB 3.0大行其道之前,它是我们在考虑O/R Mapping时非常好的选择。

  关于Hibernate框架的细节,请参考《Hibernate in Action》一书。

  首先需要安装这个插件,Eclipse 3.0.1为我们提供了更加方便的插件管理方式,选择菜单“帮助—软件更新—查找并安装”,选择“搜索要安装的新功能部件”,操作界面如下:

  选择 New Remote Site ,填写名称 Hibernate PlugIn ,下面的URL中填入:http://www.binamics.com/hibernatesync

如下图:

  然后在“安装”界面中选中我们刚添加的 Hibernate PlugIn ,打开它,选中下一级的Synchronizer,然后Next,以下的安装根据提示进行Next即可了。
  Eclipse就可以自己下载完成安装,然后Eclipse自动重启动一次就完成了。

Spring PlugIn的地址为:
http://springframework.sourceforge.net/spring-ide/eclipse/updatesite/
安装配置类似于Hibernate PlugIn的安装。

Spring的地址为:
http://www.springframework.org/

  下面演示一个最简单的单表操作,让我们熟悉开发过程。我们选择MySQL数据库来做这个应用,首先在MySQL里建立一个新的数据库为HibernateTest,再建立一个数据表,名为Person,包含ID, Name, Sex, Address四个字段,建表语句如下:

# Host: localhost
# Database: hibernatetest
# Table: 'person'
#
CREATE TABLE `person` (
`ID` int(11) NOT NULL auto_increment,
`Name` varchar(20) NOT NULL default '',
`Sex` char(1) default NULL,
`Address` varchar(200) default NULL,
PRIMARY KEY  (`ID`)
) TYPE=MyISAM;

  然后新建一个普通的Java项目:“File -> Project -> New Project ->Java Project

  输入项目名称:HibernateMySQL

  注意加入Hibernate的所有lib文件,包括有Hibernate下面的hibernate2.jar和lib目录下面的所有.jar文件;
还有要加入MySQL的jdbc驱动文件,比如mysql-connector-java-3.0.14-production-bin.jar
驱动程序自己选择加载,版本不同,文件名也不同:)

  下面我们需要在项目中加入一个Hibernate的配置文件,在src目录下选择 New -> Other -> Hibernate -> Hibernate Configuration File,如下图:

  在弹出的界面中,你需要指定要使用的数据库,以及连接数据库所需要的信息,我们对应的选择了数据库为MySQL,并配置了数据库的URL和管理员帐号与密码,如下:

Database Type: QL
Driver Class:  org.git.mm.mysql.Driver
Database URL: jdbc:mysql://localhost:3306/HibernateTest
Username: root
Password:

  点击Browse按钮,在弹出的框中输入Driver,在下面就会出现相应的驱动所在的包
我们选中org.git.mm.mysql.Driver所在的包的文件,确定即可。

  在上图中,我们还可以指定从JNDI数据源中获得连接,可以点击 Datasource 标签进行配置。

  点击 Finish 按钮之后系统会自己生成一个名为 hibernate.cfg.xml 的文件,里面包含了基本的配置信息,如果需要高级配置,可以手动配置,也可以通过其它插件来进行编辑,比如MyEclipse的XML Editor

  下面要生成映射文件,首先新建一个包 New -> Package,输入net.echochina.hibernatetest

  在这个包下选择 New -> Other -> Hibernate -> Hibernate Mapping File ,在弹出的界面中点击 Refresh 按钮,将会列出库中所有的数据表,选中我们要使用的 Person 表,点击 Browse 按钮,选择我们所要生成的POJO文件所在的包:net.echochina.hibernatetest

如下图:

  在上述界面的 Properties 标签中可以配置hbm的其他选项,包括文件扩展名,聚合列名,ID生成规则等。完成后,系统会自动生成一个名为 Person.hbm 的文件,我们可以通过这个文件生成相关的存根类。

  在Person.hbm文件上单击右键,选择 Hibernate Synchronizer -> Synchronize Files

  该操作将生成三个包八个类文件,里面封装了Hibernate的操作细节,让我们可以专心面对业务逻辑的开发,仔细阅读这些文件可以提高你对Hibernate的认识,增长应用技巧。

  然后我们需要在Hibernate的配置文件中添加对Person 的相关信息,在Person.hbm上单击右键,选择Synchronizer -> Add Mapping Reference

  现在我们可以开始编写自己的程序逻辑了,代码可以写在
net.echochina.hibernatetest.dao.PersonDAO类中,这个类的代码不会被插件进行修改的。

  首先在数据库里增加一条新的记录
  在PersonDAO类中增加一个引入import net.echochina.hibernatetest.Person;
  然后加入一个main方法,内容如下:

public static void main(String args[])
{
try
{
_RootDAO.initialize();
PersonDAO persondao = new PersonDAO();
Person person = new Person();
person.setName("YuLimin");
person.setSex("M");
person.setAddress("http://Java.EchoChina.net");
persondao.save(person);
}
catch(Exception e)
{
e.printStackTrace();
}
}

  //测试MySQL的中文问题:更改内容如下,把setName的参数改为中文的内容:

person.setName("俞黎敏");

  这里应当到hibernate.cfg.xml文件的<session-factory/>块中增加上如下两行设置

<property name="connection.useUnicode">true</property>
<property name="connection.characterEncoding">GBK</property>

  这样插入数据与读取数据时才不会有中文的问题,如果仍有中文问题请Google吧:)

  可以看出,插件已经把session操作和事务操作都封装起来了,我们的代码工作得到了极大的简化。而且我们可以利用插件自带的Hibernate Editor来编辑hbm文件,非常方便。
  我们还需要把ID的生成方式改为 identity,右键Person.hbm,Open With -> Hibernate Editor

 

  把ID的生成方式改为 identity

  要让这个程序正常运行,还需要对配置文件hibernate.cfg.xml作一些修改。
  使用Eclipse的 文本编辑器 打开该文件,其中有如下的内容:

<!--
<property name="hibernate.transaction.factory_class">
net.sf.hibernate.transaction.JTATransactionFactory
</property>
<property name="jta.UserTransaction">
java:comp/UserTransaction
</property>
-->

  由于在我们的例子中,并没有使用JTA来控制事务,所以需要将上面的内容注释掉,程序才能正常运行。

  现在可以开始运行了,点击Run

  在出现的配置中选择Java Application,Name中输入PersonDAO

  单击Search 按钮,在弹出地框中选择net.echochina.hibernatetest包中的PersonDAO类

  OK之后,点击Run开始运行,如果以上各步操作正确的话,可以看到数据已经被保存到数据库。

  如果在实际开发工作中,需要重新设计数据表结构,那么只需要在.hbm文件中做相应的修改,然后执行 Synchronize and Overwrite 的操作,插件会重新生成存根文件,我们只需要修改程序逻辑就可以了,非常方便。有了这样的功能插件,我们可以极大的从配置文件的编写、查错中解脱出来,从而提高我们的工作效率。

Hibernate 常用工具

Hibernate Synchronizer 很好的辅助开发工具,是一个Eclipse 的插件,可以生成80%的代码,首选。
MyEclipse 安装的 3.8.3 感觉非常的强大,主要是因为他是付费的,做得比较全面,喜欢他们的struts 组件,开发 Struts 必不可少。
Hibernator Hibernate查询的辅助工具,可以使用 HSQL进行查询,测试HSQL的好工具,是个Eclipse插件。
Hibern8IDE(现更名为:HibernateConsole) 一个单独运行的Hibernate工具,可以运行 Hibernate Query Language (HQL)语句。
MiddleGen 生成持久对象的工具,可以生成

Persistence layer with EJB (CMP 2.0)
Persistence layer with JDO
Persistence layer with Hibernate
Persistence layer with Torque
Database GUI with JSP/Struts

http://spindle.sourceforge.net 开发Tapestry的必备

http://springui.sourceforge.net 写Spring Application Context File的辅助好工具

posted @ 2008-05-19 12:37 caihaibo 阅读(309) | 评论 (0)编辑 收藏

下载并安装Hibernate Synchronizer插件

Hibernate Synchronizer是一个Eclipse插件,可以自动生成*.hbm文件、持久化类和DAO,大大降低开发Hibernate应用的难度。本节介绍如何下载和安装Hibernate Synchronizer插件。

JBoss Eclipse IDE插件中包括Hibernate Tools,按照6.1节介绍的步骤安装JBoss Eclipse IDE插件后就可以完成Hibernate Synchronizer插件的安装,打开如图8-1所示的“关于Eclipse SDK”窗口,其中包含了四个Hibernate插件,说明插件安装成功了。

图8-1关于Eclipse SDK插件窗口

posted @ 2008-05-19 12:32 caihaibo 阅读(1198) | 评论 (2)编辑 收藏
TortoiseSVN是开源界非常流行的一款源代码控制和管理软件,在开源项目里,几乎都用到了SVN。但是安装了SVN后会有一个TSVNCache.exe的进程驻留内存,这个进程会定时地去扫描Subversion管理的文件夹/文件是否被修改了,一旦发现有更新,那本地的这些有更新的文件/文件夹就会被更新,这个动作不仅会占用10-50MB左右的内存,而且也会在执行的瞬间占用超过CPU 50%的负载。对于Minidxer这样使用N年前买的电脑来说,这个进程还是影响到了PC的使用性能,那么应该如何停掉它呢?打开系统的文件夹管理–>右键–>TortoiseSVN–>settings–>look and feel–>Icon Overlays–>Status cache 设为”none”就可以了。
posted @ 2008-05-19 12:17 caihaibo 阅读(1070) | 评论 (1)编辑 收藏

我用的myeclipse 6.0版本,oracle是10g版本,在连接的时候出现了以下问题

 java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1
ORA-12705: Cannot access NLS data files or invalid environment specified

一开始以为是驱动程序的问题,其实不是,只需在eclipse目录下找到eclipse.ini文件,把

Duser.language=en  改成 Duser.language=zh就行了。

有可能大家出现的问题不一样,按我的方法有可能不好使,我写出来仅供大家参考,因为当时为解决这问题,花了不少时间,希望大家少走弯路。

posted @ 2008-05-19 12:15 caihaibo 阅读(924) | 评论 (4)编辑 收藏
在 C:\WINDOWS\system32\drivers\etc 目录下hosts文件设置
posted @ 2008-05-19 09:47 caihaibo 阅读(139) | 评论 (0)编辑 收藏

您可以通过向窗口添加"拆分器",在 Dreamweaver 中设计您自己的框架集。

用Dreamweaver为网页设计框架集

您可以通过向窗口添加"拆分器",在 Dreamweaver 中设计您自己的框架集。

提示在创建框架集或使用框架前,通过选择"查看">"可视化助理">"框架边框",使框架边框在"文档"窗口的"设计"视图中可见。

若要创建框架集,请执行以下操作:

  • 选择"修改">"框架集",然后从子菜单选择拆分项(例如"拆分左框架"或"拆分右框架")。

Dreamweaver 将窗口拆分成几个框架。如果打开一个现有的文档,它将出现在其中一个框架中。

要将一个框架拆分成几个更小的框架,请执行以下操作:

  • 要拆分插入点所在的框架,从"修改">"框架集"子菜单选择拆分项。
  • 要以垂直或水平方式拆分一个框架或一组框架,请将框架边框从"设计"视图的边缘拖入"设计"视图的中间。
  • 要使用不在"设计"视图边缘的框架边框拆分一个框架,请在按住 Alt 键的同时拖动框架边框 (Windows) 或在按住 Option 键的同时拖动框架边框 (Macintosh)。
  • 要将一个框架拆分成四个框架,请将框架边框从"设计"视图一角拖入框架的中间。

提示若要创建三个框架,请首先创建两个框架,然后拆分其中一个框架。不编辑框架集代码是很难合并两个相邻框架的,所以将四个框架转换成三个框架要比将两个框架转换成三个框架更难。

若要删除一个框架,请执行以下操作:

  • 将边框框架拖离页面或拖到父框架的边框上。

如果要删除的框架中的文档有未保存的内容,则 Dreamweaver 将提示您保存该文档。

注意您不能通过拖动边框完全删除一个框架集。要删除一个框架集,请关闭显示它的"文档"窗口。如果该框架集文件已保存,则删除该文件。

若要调整框架的大小,请执行以下操作之一:

  • 若要设置框架的粗略大小,请在"文档"窗口的"设计"视图中拖动框架边框。
  • 若要指定准确大小,并指定当浏览器窗口大小不允许框架以全大小显示时,浏览器分配给框架的行或列的大小,可使用"属性"检查器。
posted @ 2008-05-16 15:42 caihaibo 阅读(192) | 评论 (0)编辑 收藏
Apache下的安装:

我们这次采用的是Apache的一个全新版本Apache2,以前在Apache下安装PHP记得还比较麻烦,现在在Apache2平台下,我们可以方便的以模块化的方式安装PHP,前提是PHP版本必须是4.0以上的。

当然,现在还在用PHP3的已经很少了。所以这次我们只介绍如何以模块化的方式在Apache下安装PHP,如果你想了解在Apache下如何以Cgi的方式加载php,可以参考本站的另一篇文章"PHP+Apache在Win9x下的安装和配置"(http://www.hooday.com/?n=ReadArticle&a=34)。好了,闲话少说,让我们一起来领略模块化安装PHP的风采吧。

1.运行你下载的Apache2安装文件,安装Apache,安装过程中会提示你输入主机名,管理员信箱等信箱,这些信息在你安装完以后是可以修改的,所以可以放心的输入。在选择安装路径时,笔者建议你把安装路径也选成C盘的根目录。在一步步的"Next"后,你会发现Apache很容易就安装好了。

现在再看你的任务栏的右侧,应该有一个类似于这个小图标的图标,这就是Apache2的服务管理器,也是Apache1.X版本所没有的。注意这个图片的状态,如果有一个绿色的小三角,说明你的服务器已经安装成功,如果是红色的,则说明你的Apache没有安装成功,你需要进一步去找一下失败的根源。

一般最常见的错误就是端口有冲突,Apache默认的端口是80,如果你的80端口被另一个程序(如IIS)占用了的话,就会出现无法启动的情况。出现这种情况,你可以按照下面的方法来修改:点击"开始->程序->Apache HTTP Server 2.0.40->Configure Apache Server->Edit the Apache httpd.conf Configuration File"会打开一个Apache的配置文件,你可以用文本编辑器来打开它。

然后在这个文件的第120行左右,你会发现类似于"Listen 80"的字样。现在只要把这个80改成你想要的端口即可,当然在你用浏览器浏览的时候也不要忘了加上端口哦。

到了这里,你的Apache应该已经亮起绿灯了吧,下面我们来测试一下它是否在工作。打开你的浏览器,在地址栏上输入"http://localhost/"(如果你的端口不是80,需要在后面加上":端口号"),不知道你是否看到了Apache的欢迎页,笔者在这一步并没有看到,不知道什么缘故,Apache2版本好像没有默认的引导页面。如果你也没有看到,可以试着在后面加上一个文件名"index.html.en",如果能出现下面类似的页面,则说明Apache已经工作正常了。

2.好了,Apache已经安装OK了,接下来就是看如何跟PHP结合起来了。

最开始的两步和上边介绍的IIS步骤是相同的,也是解压后复制到C盘根目录,然后改名,再把PHP.ini复制到系统文件夹,如果有必要的话,修改一下"extension_dir"和"doc_root"这两项的值。上边已经说得很清楚,不再多说。

接着便是最重要的一步了,也是模块化安装的核心步骤了,可要看仔细了。

打开Apache2的配置文件(http.conf),可以通过点击"开始->程序->Apache HTTP Server 2.0.40->Configure Apache Server->Edit the Apache httpd.conf Configuration File"打开.

或者打开你的Apache安装目录下的Conf目录,你会发现一个名为http.conf的文件,就是它了,你可以用任一个文本编辑器来打开它。在这个文件的第121行左右,你应该能找到"LoadModule"字样,然后后面是一串路径,这就是Apache默认要加载的模块了,同样,咱们也可以在其后加上一句,让他来加载PHP模块。
 
 

其实,就是这么简单,你只要加上这么一句"LoadModule php4_module C:/php/sapi/php4apache2.dll",这里要解释一下"php4_module"是模块的名称,后面跟的路径则随你的PHP安装目录而变,这三个字串之间是用空格符分隔的。

接下来,还有一步工作,也是很多安装失败的朋友所忽略的,刚开始笔者也是无论如何加入上边的那一句后Apache就启动不起来了。后来经过几次试验,才发现,你的PHP安装目录下的"php4ts.dll"必须要复制到windows系统的system32目录下,否则,就不可能启动起来。

现在再试一下,是不是一切都正常了。好了,再来回顾一下我们在Apache下安装的过程。

(1)添加"LoadModule php4_module C:/php/sapi/php4apache2.dll".

(2)复制"php4ts.dll"到system32目录.

是的,就是这么简单,PHP已经运行在你的机器上了。你可以通过双击任务栏的Apache服务器图标来看到这一点。

3.再来测试一下吧。

把下面的代码保存成info.php文件放在你的Apache安装目录下的htdocs目录下。

phpinfo();
            ?>

然后在浏览器中敲入http://localhost/info.php(如果你的端口不是80,请在localhost/后加上":端口号"),是不是看到了类似下面的屏幕所显示的。如果是,恭喜,你已经成功的以模块化方式安装了PHP

以上在Apache部分所讲述的东西对不太熟悉Apache配置的朋友可能有一点不太明白,不过只要你按我上面所说的一步步的来,应该都不会出现什么大的毛病。如果万一不知道自己改的哪一个部分使Apache启动不起来了,你可以切换到Apache安装目录下的Conf文件夹,将http.conf文件删除掉,再将Apache的默认配置文件httpd.default.conf改名成http.conf即可。如果你想进一步的了解Apache的配置。

 


posted @ 2008-05-16 11:52 caihaibo 阅读(766) | 评论 (0)编辑 收藏

前期准备:

Windows XP SP2 (其实系统只要是 98 以上都可以遵循这样的方法我认为)
Apache 2本例中我选用了 2.2.2 for Win32 ……)
http://archive.apache.org/dist/httpd/

PHP 5 (虽然版本数有点不吉利…… 但我还是毅然选择了 5.1.4 for Win32 Zip 版……)
http://www.php.net/downloads.php
 
MySQL 5 (5.1 尚不稳定…… 我们姑且还是选择 MySQL 5.0.22 for Win32 Zip 版……)
http://www.mysql.com/

本方案并不涉及系统文件夹…… 所以我们大可选择其它分区的某个文件夹来方便日后的伺服器维护…… 本为以 X:\Server 为例…… 注意:文件夹名称最好不要包含空格或其它非英文字符…… 否则某些情况下容易造成伺服器崩溃……

========================================
安装 Apache:

运行 apache_2.2.2-win32-x86-no_ssl.msi …… 一路 Next 下来…… 到选择安装方式的时候,选择 “Custom” 自定义方式…… 然后 Next 选择安装路径…… 定位到 X:\Server\Apache (当然,你选择其它路径也可以,甚至选择 Complete 安装都没问题…… 我只是习惯讲所有服伺服器相关软体集中到一起而已)
本来不准备写 IIS 与 Apache 的共存配置…… 想一想还是带一笔吧…… 提示填写 Server Information 时…… 最下方会让你选择端口…… 如果你安装了 IIS 伺服器…… 这里就选择第二项 “only for the current user, on Port 8080, when started manually.”…… 也就是说 Apache 将占用 8080 端口…… 如果你没安装 IIS …… 无视之……
继续 Next …… 弹出几个 CMD 窗口安装 Windows 服务以后…… 安装就完成了…… 右下角将出现 Apache 粉红色的羽毛 Icon,不出意外图标上应该显示绿灯(表示 HTTP 伺服已经正常启动)…… 你可以访问 http://www.quchao.com/ 来试试,如果屏幕出现 “It Works” 就表示安装成功…… (我记得以前的版本不是这样的,而是一个挺花哨的页面…… 所以只要不出现找不到页面的提示…… Apache 伺服就安装成功了)当然了…… 如果亮起红灯…… 配置肯定错误…… 回头查查吧……
Apache 伺服器就安装完毕了……

=======================================
安装 PHP :

解压 PHP-5.1.4-Win32.zip …… 并放置到 X:\Server\PHP 之下……
接下来为 PHP 的安装目录添加环境变量…… 在我的电脑图标上点击滑鼠右键…… 查看‘属性’…… 然后切换到‘高级’选项卡…… 点击‘环境变量’按钮(快捷键:Alt+N)…… 在弹出的‘系统变量’域中找到‘Path’变量…… 双击编辑并在变量值的最后添加 ‘;X:\Server\PHP’ (注意有个分号,用来分隔之前的值)……
重启电脑…… 为啥? 让环境变量生效呗……
至此 PHP 就安装完毕了…… 当然,现在还未与 Apache 关联…… 而且未作任何设置…… 不要急…… 后面我会写……

=======================================
配置 Apache:

尤为重要的一步:如果你跟我一样选择了当前最新的 PHP 稳定版本 5.1.4…… 官方下载来的源码包中的模块化支援 PHP5apache2.dll 是不适用于 Apache 2.2.2 的…… 据查需要重新编译 PHP …… 不过PHP5 研究室提供了解决方法:
下载这个压缩包(http://www.phpv.net/php5apache2.dll-php5.1.x.rar)…… 解压后将 PHP5apache2.dll 扔进 X:\Server\PHP 覆盖原文件…… 将 httpd.exe.manifest 扔进 X:\Server\Apache\Bin 文件夹…… 最后运行 vcredist_x86.exe (如果你安装有 .Net FrameWork 就无需安装此文件)……
当然,如果你选择比较旧的版本则可略过此步。
下面开始修改 Apache 配置文件: X:/Server/Apache/conf/httpd.conf
修改文档发布路径……
搜索:
DocumentRoot “X:/Server/Apache/htdocs”
将值修改成你想要的发布路径,比如:
DocumentRoot “X:/Server/WWW”
然后还有一处也需要修改…… 否则将无权访问……
搜索:
Directory “X:/Server/Apache/htdocs”
修改为:
Directory “X:/Server/WWW”
修改默认脚本:
搜索:
DirectoryIndex index.html
添加你想要的默认脚本名称,用空格分隔,注意前后有优先顺序,比如:
DirectoryIndex index.PHP index.html index.htm
针对 PHP 5 的配置:
在文档的最下方加入以下字符:
# 调用 PHP 5 模块
LoadModule PHP5_module “X:/Server/PHP/PHP5apache2.dll”
# 添加 Mime 类型…… 亦可以修改 mime.types 文件
AddType application/x-httpd-PHP .PHP
AddType application/x-httpd-PHP-source .phps
# 添加默认字符集…… utf8才是王道……
AddDefaultCharset UTF8
# 设置 PHP.ini 目录
PHPIniDir “X:/Server/PHP”
至此,Apache 已经可以支持 PHP 了…… 当然…… 本文仅介绍如何进行基本安装…… 将不涉及详细的配置以及优化…… 各位可以自行参阅手册进行配置……
'www.knowsky.com
=======================================
安装 MySQL:

解压 MySQL-noinstall-5.0.22-win32.zip …… 并放置到 X:\Server\MySQL 之下……
接下来安装 MySQL 服务…… 打开 cmd.exe …… 然后进入 X:\Server\MySQL\bin 目录……(虾米?你不会?那我还是写清楚吧)
开始->运行->cmd->回车……
然后进入 X:\Server\MySQL\bin 目录:
>cd /d X:\Server\MySQL\bin 回车
(如果你的文件夹带有空格,别忘了在路径外添加双引号)
然后运行 MySQL 服务安装脚本:
>mysqld-nt -install
显示 MySQL service installed successfully,表示安装成功……
接下来为 MySQL 的安装目录也添加一个环境变量…… 在我的电脑图标上点击滑鼠右键…… 查看‘属性’…… 然后切换到‘高级’选项卡…… 点击‘环境变量’按钮(快捷键:Alt+N)…… 在弹出的‘系统变量’域中找到‘Path’变量…… 双击编辑并在变量值的最后添加 ‘;X:\Server\MySQL’ (注意有个分号,用来分隔之前的值)……
重启电脑…… 为啥? 还是让环境变量生效……
(我靠…… 安装 PHP 的时候为什么不一起说…… 害我还得重启一遍……)
这个嘛…… 我忘了……
然后配置 MySQL …… 来到 X:\Server\MySQL …… 里头应该有若干个 ini 文件…… 我们根据自己的需要任取一个(大同小异…… 仅仅是默认配置不同…… 你也可以自行修改的)…… 由于我仅仅为了本地的开发调试,所以选择了 my-small.ini …… 将其复制一份…… 命名为 my.ini…… 用文本编辑器打开它:
搜索:
[mysqld]
在下方加入以下字符行:
#MySQL 安装目录
basedir=X:/Server/MySQL
#MySQL 默认数据目录
datadir=X:/Server/MySQL/data
# 默认字符集…… 设置为 UTF8 吧
default-character-set=utf8
# 默认储存引擎…… 还是回到 MyISAM 时代吧…… InnoDB 被甲骨文买了…… 虽然开源…… 但……
default-storage-engine=MyISAM
再在文档最下方加入:
[WinMySQLAdmin]
Server=X:/Server/MySQL/bin/mysqld-nt.exe
MySQL 配置完成…… 下面可以启动试试…… 打开 cmd.exe…… 输入:
net start MySQL
若显示‘MySQL服务已经启动成功’…… 则表示…… 则表示这句话说得没错…… 否则请回头检查……
服务器启动了…… 我们就可以登录试试了……
>cd /d X:\Server\MySQL\bin 回车
接着登陆
>MySQL -u root -p
由于 root 初始状态无密码,提示 Enter Password 时直接回车即可……
然后命令行进入 MySQL Shell 状态即表示‘入侵’成功……
如果你不想别人也用空密码入侵你,最好给 root 设置一个牛叉点儿的密码……
MySQL>set password for ‘root’@’localhost’ = old_password(’Password_for_root‘);
(这是 MySQL 5 的新命令,之前的版本请将 old_password 改成 password)
将其中 Passwor_for_root 更换为你自个儿的密码吧…… 别太简单……
提示 ‘Query Ok’ 表明修改成功。
不信?你可以 exit; 出去再登录试试……
至此…… MySQL 的安装工作完毕…… 详细的优化配置请参阅手册…… 至于 MySQL 与 PHP 的关联下面将提到……

=====================================
'www.knowsky.com
配置 PHP:

进入 X:\Server\PHP …… 将 PHP.ini-recommend 更名为 PHP.ini 并用文本编辑器打开……
修改错误报告级别…… 运行一些书写不规范的程序…… 你会发现满屏的‘错误’……
搜索:
error_reporting = E_ALL
修改为:
error_reporting = error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT
由于是本地调试,我当然希望错误被输出供我调试……
搜索:
display_errors = Off
修改为:
display_errors = On
对于本地开发者,记录错误似乎没有必要……
搜索:
log_errors = On
修改为:
log_errors = Off
设置扩展库的路径是很必要的……
搜索:
extension_dir = “./”
修改为:
extension_dir = “X:/Server/PHP/ext”
PHP 5 默认是不开启对 MySQL 的支持的……
搜索:
;extension=PHP_MySQL.dll
去掉前面的分号:
extension=PHP_MySQL.dll
另外,vBulletin 早已启用了对 Mysqli 的支持…… 所以这里我们引入 MySQL 扩展库……
搜索:
extension=PHP_MySQL.dll
在下方加入:
extension=PHP_mysqli.dll
当然,为了更好的使用 vBulletin 的一些图象相关功能,我们需要启用 GD2 库……
搜索:
;extension=PHP_gd2.dll
去掉前面的分号:
extension=PHP_gd2.dll
我们还希望对一些较常用的库进行调用,比如 PHP_mbstring.dll 、 PHP_curl.dll 、 PHP_sockets.dll 、 PHP_xmlrpc.dll 等等…… 开启方法同上……
(这里仅启用了常用扩展…… 其它的扩展请自行根据需要定夺……)
虽然 vBulletin 使用了其内建 Session 机制,但 PHP 的 Session 机制在很多程序中是必备的……
搜索:
;session.save_path = “/tmp”
修改为一个存在的路径里……
或者到发布目录下建立一个 tmp 目录……
这里我们选用前一种方法…… 先建立这样一个目录 X:\Session ……
然后修改为:
session.save_path = “X:/Session”
到这里基本就设置完毕了…… PHP 也能正常支持 MySQL 了…… 更详细的设置大家还是去翻手册了……

====================================
结语:

最基本的 WAMP 环境就配置完毕了…… 接下来我还配置了 Zend Optimizer 和 Subversion……由于不是标配…… 这里就不做介绍了……
其实 Apache 服务器也可以不用安装…… 可惜我未找到 2.2.2 的 ZIP 版本…… 而用 SRC 文件进行编译又太繁琐…… 所以干脆执行了安装程序…… 等我下一次重装系统时…… Apache 就变成绿色的了…… 让我们一起期待…… (大概两年后?)
呃……………… 想到甚么再补充进来吧……

posted @ 2008-05-16 09:59 caihaibo 阅读(210) | 评论 (0)编辑 收藏
假设:系统盘为 c:/
假设:把所有的东西安装在D盘下的php目录下
假设:安装好后目录状态会是这样子:
apache-------------------------> d:/php/apache
mysql---------------------------> d:/php/mysql
php-----------------------------> d:/php/php
网页文件------------------------> d:/php/www
以上这些是我的喜好,你可以改成你喜欢的

第一步 安装mysql4.1.10a( 本文章的配置适用于mysql4.1 和 mysql5.0版本 )

将下载的的mysql压缩包,直接解压到指定目录(d:phpmysql)就可以了
然后双击 D:phpmysqlbinwinmysqladmin.exe 这个文件,请输入winmysqladmin的初始用户、密码 (注:这不是mysql里的用户、密码)随便填不必在意.确定之后你的右下角任务的启动栏会出现一个红绿灯的图标(绿灯),红灯亮代表服务停止,绿灯亮代表服务正常

(如果不是绿灯,就左击这个图标->winnt->install the service 安装此服务
再左击这个图标->winnt->start the service 启动mysql服务)


修改mysql数据库的root密码
开始->运行,输入cmd 然后cd 到d:mysqlbin 执行以下命令

D:mysqlbin>mysql
 
进入mysql后接着执行:

(将root密码设置为easy)

 
下面一步是让PHP可以连接到mysql4.1以上版本的,一定不可以省略。具体可参考
http://www.phpv.net/article.php/288


密码请根据你需要换成别的


如果你下载的是进制安装包,解压到任意目录后就直接双击setup.exe 文件,按照你安装软件的习惯装好它,记得到路径选择那一步时请写d:phpmysql 装好后打开d:phpmysqlbin文件夹,双击winmysqladmin.exe文件,会弹出一个窗口,要求设置你的mysql服务的管理员用户名密码.自己定吧


两种方法区别一看就明了.

第二步: 安装apache 并配置支持PHP

双击安装文件apache_2.0.53-win32-x86-no_ssl.msi
将apache安装在 D:phpapache 目录下
还会有输入框,提示输入域名呀管理员信箱,随便填就是了.
+-----------------------------------------------------
| 注: 安装完后会自动安装并启动apache的服务,如在此处出现问题:
|“(OS 10048)通常每个套接字地址 (协议/网络地址/端口) 只允许使用一次:
| make_sock: could not bind to address 0.0.0.0:80...” 一般是IIS占用了80端口引起的
| 解决方法: 打开 控制面板->服务 找到 IIS admin 的服务 关闭并禁用
| 然后用CMD进入命令行模式 进入你安装apache的目录 /apache2/bin
| 输入
| apache -k install
| apache -k start
| 如果成功的话,再接着做下面的!
+--------------------------------------------------------------

将php-5.0.3-Win32.zip 里内容解压到 D:phpphp 里

找到 php目录里的 php.ini-dist (似乎这是一个习惯,其实我更喜欢用php.ini-recommended)重命名为 php.ini 并拷到 windows系统目录下(特殊情况:win2k系统目录为winnt)
如我的php.ini是拷到 c:windows目录
再将php目录里的 php5ts.dll,libmysql.dll 拷到 系统目录系统目录如我的是c:windows 里(也可以是c:windowssystem32)
 
最后到D:phpphpext下将php_gd2.dll php_mysql.dll这两个文件复制到system/system32如我的是c:windowssystem里

配置apache里的httpd.conf

打开 D:phpApacheconfhttpd.conf 这个文件

找到 AddDefaultCharset ISO-8859-1 将其改为

AddDefaultCharset GB2312 (让默认语言编码为简体中文)

找到 DocumentRoot "D:/php/Apache2/htdocs" 将其改为你的WEB目录,如我的为

DocumentRoot "D:/php/www"

找到 DirectoryIndex index.html index.html.var 在后面加入 index.htm index.php (默认index.php为首页文件)

--------------模块化安装PHP----------------------------------------
找到 #LoadModule ssl_module modules/mod_ssl.so 这行,在此行后加入一行

LoadModule php5_module d:/php/php/php5apache2.dll

其中d:/php/php/php5apache2.dll 为你php目录中php5apache2.dll所在的位置

再找到 AddType application/x-gzip .gz .tgz 这行,在此行后加入一行

AddType application/x-httpd-php .php

(其实:上面两行红色的,你可以直接加在httpd.conf文件的最后面也可以的)
--------------------------------------------------------------------

此时PHP环境基本已经配置成功
在WEB根目录(如我的D:phpwww)里建一个名为test.php (提示:用记事本的朋友,请避免文件为test.php.txt) ,的文件内容如下
PHP代码:
<? echo phpinfo(); ?>
重新启动apache服务
用浏览器打开 http://localhost/test.php
如果可以看到php配置输出信息就OK了
(如果看到的是下载页面或者<? echo phpinfo(); ?>,请查查你所做的与上面是否有错漏)


三、配置php.ini并测试mysql、GD2(php.ini为 c:windows下的 php.ini)


找到
;extension=php_mysql.dll
将';'去掉改为.

extension=php_mysql.dll
 
找到
;extension=php_gd2.dll 去掉前面的; 以便支持GD库.如
 
extension=php_gd2.dll

找到
;session.save_path = "/tmp"
将';'去掉.设置你保存session的目录,如

session.save_path = "C:WINDOWSTemp";

 
重启apache服务
在Web根目录下(如 D:phpwww)建立testdb.php文件内容如下:
PHP代码:
<?php
$link
=mysql_connect('localhost','root','123456');
//这里的root和123456是MYSQL的用户和密码,请根据你自己的情况改好
if(!$link) echo "fail"
;
else echo
"success"
;
mysql_close
();
?>
用浏览器打开http://localhost/testdb.php 如果输出success就OK了

四、phpmyadmin的安装配置

将phpMyAdmin-2.6.1.zip解压到WEB根目录(d:phpwww中去),重命名文件夹为phpmyadmin或其它
打开phpmyadmin 目录中的 config.inc.php
找到以下这些(以下我已改好):

$cfg['PmaAbsoluteUri'] = 'http://localhost/phpmyadmin';  //假设是有域名的服务器,可改成http://域名/phpmyadmin


$cfg['Servers'][$i]['user'] = 'root';

$cfg['Servers'][$i]['password'] = 'easy; //分别填上你mysql的用户和密码即可

$cfg['Servers'][$i]['auth_type'] = 'http'; // 这里也可以改为cookie



改好了保存,在浏览器打开http://localhost/phpmyadmin 输入你的用户名和密码,便可以管理mysql了


差不多了,如果你想让你的PHP代码执行得更快,就再装个Zend Optimizer.
可到http://down.phpv.net/soft/379.htm下载

方法是:下载后双击,选择路径安装.问PHP.INI路径就填 c:/windows

装好重启apache服务.再看http://localhost/test.php 时应该看到会多一些东西
with Zend Extension Manager v1.0.3, Copyright (c) 2003-2004, by Zend Technologies
with Zend Optimizer v2.5.7, Copyright (c) 1998-2004, by Zend Technologies
posted @ 2008-05-16 09:45 caihaibo 阅读(176) | 评论 (0)编辑 收藏
假设:系统盘为 c:/
假设:把所有的东西安装在D盘下的php目录下
假设:安装好后目录状态会是这样子:
apache-------------------------> d:/php/apache
mysql---------------------------> d:/php/mysql
php-----------------------------> d:/php/php
网页文件------------------------> d:/php/www
以上这些是我的喜好,你可以改成你喜欢的

第一步 安装mysql4.1.10a( 本文章的配置适用于mysql4.1 和 mysql5.0版本 )

将下载的的mysql压缩包,直接解压到指定目录(d:phpmysql)就可以了
然后双击 D:phpmysqlbinwinmysqladmin.exe 这个文件,请输入winmysqladmin的初始用户、密码 (注:这不是mysql里的用户、密码)随便填不必在意.确定之后你的右下角任务的启动栏会出现一个红绿灯的图标(绿灯),红灯亮代表服务停止,绿灯亮代表服务正常

(如果不是绿灯,就左击这个图标->winnt->install the service 安装此服务
再左击这个图标->winnt->start the service 启动mysql服务)


修改mysql数据库的root密码
开始->运行,输入cmd 然后cd 到d:mysqlbin 执行以下命令

D:mysqlbin>mysql
 
进入mysql后接着执行:

(将root密码设置为easy)

 
下面一步是让PHP可以连接到mysql4.1以上版本的,一定不可以省略。具体可参考
http://www.phpv.net/article.php/288


密码请根据你需要换成别的


如果你下载的是进制安装包,解压到任意目录后就直接双击setup.exe 文件,按照你安装软件的习惯装好它,记得到路径选择那一步时请写d:phpmysql 装好后打开d:phpmysqlbin文件夹,双击winmysqladmin.exe文件,会弹出一个窗口,要求设置你的mysql服务的管理员用户名密码.自己定吧


两种方法区别一看就明了.

第二步: 安装apache 并配置支持PHP

双击安装文件apache_2.0.53-win32-x86-no_ssl.msi
将apache安装在 D:phpapache 目录下
还会有输入框,提示输入域名呀管理员信箱,随便填就是了.
+-----------------------------------------------------
| 注: 安装完后会自动安装并启动apache的服务,如在此处出现问题:
|“(OS 10048)通常每个套接字地址 (协议/网络地址/端口) 只允许使用一次:
| make_sock: could not bind to address 0.0.0.0:80...” 一般是IIS占用了80端口引起的
| 解决方法: 打开 控制面板->服务 找到 IIS admin 的服务 关闭并禁用
| 然后用CMD进入命令行模式 进入你安装apache的目录 /apache2/bin
| 输入
| apache -k install
| apache -k start
| 如果成功的话,再接着做下面的!
+--------------------------------------------------------------

将php-5.0.3-Win32.zip 里内容解压到 D:phpphp 里

找到 php目录里的 php.ini-dist (似乎这是一个习惯,其实我更喜欢用php.ini-recommended)重命名为 php.ini 并拷到 windows系统目录下(特殊情况:win2k系统目录为winnt)
如我的php.ini是拷到 c:windows目录
再将php目录里的 php5ts.dll,libmysql.dll 拷到 系统目录系统目录如我的是c:windows 里(也可以是c:windowssystem32)
 
最后到D:phpphpext下将php_gd2.dll php_mysql.dll这两个文件复制到system/system32如我的是c:windowssystem里

配置apache里的httpd.conf

打开 D:phpApacheconfhttpd.conf 这个文件

找到 AddDefaultCharset ISO-8859-1 将其改为

AddDefaultCharset GB2312 (让默认语言编码为简体中文)

找到 DocumentRoot "D:/php/Apache2/htdocs" 将其改为你的WEB目录,如我的为

DocumentRoot "D:/php/www"

找到 DirectoryIndex index.html index.html.var 在后面加入 index.htm index.php (默认index.php为首页文件)

--------------模块化安装PHP----------------------------------------
找到 #LoadModule ssl_module modules/mod_ssl.so 这行,在此行后加入一行

LoadModule php5_module d:/php/php/php5apache2.dll

其中d:/php/php/php5apache2.dll 为你php目录中php5apache2.dll所在的位置

再找到 AddType application/x-gzip .gz .tgz 这行,在此行后加入一行

AddType application/x-httpd-php .php

(其实:上面两行红色的,你可以直接加在httpd.conf文件的最后面也可以的)
--------------------------------------------------------------------

此时PHP环境基本已经配置成功
在WEB根目录(如我的D:phpwww)里建一个名为test.php (提示:用记事本的朋友,请避免文件为test.php.txt) ,的文件内容如下
PHP代码:
<? echo phpinfo(); ?>
重新启动apache服务
用浏览器打开 http://localhost/test.php
如果可以看到php配置输出信息就OK了
(如果看到的是下载页面或者<? echo phpinfo(); ?>,请查查你所做的与上面是否有错漏)


三、配置php.ini并测试mysql、GD2(php.ini为 c:windows下的 php.ini)


找到
;extension=php_mysql.dll
将';'去掉改为.

extension=php_mysql.dll
 
找到
;extension=php_gd2.dll 去掉前面的; 以便支持GD库.如
 
extension=php_gd2.dll

找到
;session.save_path = "/tmp"
将';'去掉.设置你保存session的目录,如

session.save_path = "C:WINDOWSTemp";

 
重启apache服务
在Web根目录下(如 D:phpwww)建立testdb.php文件内容如下:
PHP代码:
<?php
$link
=mysql_connect('localhost','root','123456');
//这里的root和123456是MYSQL的用户和密码,请根据你自己的情况改好
if(!$link) echo "fail"
;
else echo
"success"
;
mysql_close
();
?>
用浏览器打开http://localhost/testdb.php 如果输出success就OK了

四、phpmyadmin的安装配置

将phpMyAdmin-2.6.1.zip解压到WEB根目录(d:phpwww中去),重命名文件夹为phpmyadmin或其它
打开phpmyadmin 目录中的 config.inc.php
找到以下这些(以下我已改好):

$cfg['PmaAbsoluteUri'] = 'http://localhost/phpmyadmin';  //假设是有域名的服务器,可改成http://域名/phpmyadmin


$cfg['Servers'][$i]['user'] = 'root';

$cfg['Servers'][$i]['password'] = 'easy; //分别填上你mysql的用户和密码即可

$cfg['Servers'][$i]['auth_type'] = 'http'; // 这里也可以改为cookie



改好了保存,在浏览器打开http://localhost/phpmyadmin 输入你的用户名和密码,便可以管理mysql了


差不多了,如果你想让你的PHP代码执行得更快,就再装个Zend Optimizer.
可到http://down.phpv.net/soft/379.htm下载

方法是:下载后双击,选择路径安装.问PHP.INI路径就填 c:/windows

装好重启apache服务.再看http://localhost/test.php 时应该看到会多一些东西
with Zend Extension Manager v1.0.3, Copyright (c) 2003-2004, by Zend Technologies
with Zend Optimizer v2.5.7, Copyright (c) 1998-2004, by Zend Technologies
posted @ 2008-05-16 09:45 caihaibo 阅读(113) | 评论 (0)编辑 收藏

/s$/ 匹配以字母"s"结尾的字符串

正则表达式语法通过反斜杠(\)开头的转义序列支持某些非字母的字符如"\n"为直接量换行符
常用的
\o NUL字符
\t 制表符
\n 换行符
\v 垂直制表符
\f 换页符
\r 回车

\xnn 十六进制指定的拉丁字符
\uxxxx
\cX

/[abc]/ 和字母"a","b","c"中的任何一个字母都匹配.
/[^abc]/和除字母"a","b","c"之外的所有字符匹配.
/[a-z]/ 匹配英文小写字母
/[a-zA-Z0-9]/ 匹配拉丁字母集中任何字母数字以及字符.

\w 任何ascii单字字符,等价于[a-zA-Z0-9_]
\W 任何ascii非单字字符,等价于[^a-zA-Z0-9_]
\s 匹配的是空格符(非Unicode空白符)
\S 任何非Unicode空白符,注意\w和\S不同
\d 任何ascii数字,等价于[0-9]
\D 除了ascii数字之外的任何字符,等价于[^0-9]
/[\b]/ 退格符

方框号内也可以用这些字符转义如
/[\s\d] 等同于任意的空白符或数字


/a-/ 匹配一个或多个字符 与aaa都配
/a+?/ 匹配一个或多个必要的字母a.该模式只匹配第一个字母a

 
/ab| cd| ef/ 匹配的是字符串"ab",或者是字符串"cd",又或者是字符串
"ef"
/\d{3}|[a-z]{4}/ 匹配的是三位数字或四个小写字母
注意,选项是从左到右考虑,直到发现了匹配项,如果左边的选择项匹配
,就忽略了右边的匹配项.即使它产生更好的匹配.所以 /a|ab/ 就用到
"ab"上时,它只匹配第一个字符
/java(script)?/ 匹配的是字符串"java",后面既可以有"script",也可以没有
/(ab|cd)+|ef)/ 既可以是字符串"ef",也可以是字符串"ab"或者"cd"的
一次或多次重复

| 选择.匹配的是该符号左边的子表达式或右边的子表达式
(...) 组合.将几个项目组合为一个单元.

例:匹配"JavaScript"可以使用/^JavaScript$/
如想检索"Java" 可以使用 /\sJava\s/ 要求在单字Java之前和之后都有空格
但这样有两个问题:1.如果Java位于开头或结尾时,不匹配
2.当找到与之匹配的字符串时,它返回的匹配字符串的前端和后端都有空格
因则我们可以:/\bJava\b/

 

元字符

+ 元字符规定其前导字符必须在目标.对象中连续出现一次或多次
*  元字符规定其前导字符必须在目标对象中出现零次或连续多次
?   规定其前导对象必须在目标对象中连续出现零次或一次

/fo+/
因为上述正则表达式中包含“+”元字符,表示可以与目标对象中的 “fool”, “fo”, 或者
“football”等在字母f 后面连续出现一个或多个字母o 的字符串相匹配。
/eg*/
因为上述正则表达式中包含“*”元字符,表示可以与目标对象中的 “easy”, “ego”, 或者 “egg”
等在字母e 后面连续出现零个或多个字母g 的字符串相匹配
/Wil?/
因为上述正则表达式中包含“?”元字符,表示可以与目标对象中的 “Win”, 或者 “Wilson”,等在字
母i 后面连续出现零个或一个字母l 的字符串相匹配。

/jim{2,6}/
上述正则表达式规定字符m 可以在匹配对象中连续出现2-6 次,因此,上述正则表达式可以同jimmy 或
jimmmmmy 等字符串相匹配。
“^”定位符规定匹配模式必须出现在目标字符串的开头

“$”定位符规定匹配模式必须出现在目标对象的结尾
,\b 定位符规定匹配模式必须出现在目标字符串的开头或结尾的两个边界之一

“\B”定位符则规定匹配对象必须位于目标字符串的开头和结尾两个边界之内,即匹配对象既不能作为目标字符串的开头,也不能作为目标字符串的结尾


/^hell/
因为上述正则表达式中包含“^”定位符,所以可以与目标对象中以 “hell”, “hello”或
“hellhound”开头的字符串相匹配
/ar$/
因为上述正则表达式中包含“$”定位符,所以可以与目标对象中以 “car”, “bar”或 “ar” 结尾的
字符串相匹配。
/\bbom/
因为上述正则表达式模式以“\b”定位符开头,所以可以与目标对象中以 “bomb”, 或 “bom”开头的
字符串相匹配。
/man\b/
因为上述正则表达式模式以“\b”定位符结尾,所以可以与目标对象中以 “human”, “woman”或
“man”结尾的字符串相匹配。


我们可以使用正则表达式的test 或者search 方法来发现字符中是否符合某个模式。比如:
var ResultFlag = forms[0].UserName.value.search(/[a-z]|[A-Z]/);
if (ResultFlag==-1){alert(表单中的UserName 没有包含任何字符!)};

 

工作中的新用法::
如:密码中不要包含三位重复的字符
if(document.forms[0].cipher1.value.search(/(\S)\1{2}/) != -1)
 {
  alert("密码中请不要包含三位重复的字符");
  bool=false;
  return bool;
 }

后面跟的\1是向后引用,就是引用前面括号内的内容
这个非常实用哦 

 

posted @ 2008-05-15 15:38 caihaibo 阅读(447) | 评论 (0)编辑 收藏

extjs中文解决方案/Eclipse下的js和ext开发
中文化问题,在 ext-all.js 后面,挂上 ext-lang-zh_CN.js :
1. <script type="text/javascript" src="<%=contextPath%>/public/js/ext-base.js"></script>  
2. <script type="text/javascript" src="<%=contextPath%>/public/js/ext-all.js"></script>  
3. <script type="text/javascript" src="<%=contextPath%>/public/js/ext-lang-zh_CN.js"></script>  

注:ext-lang-zh_CN.js文件存放在 ext-2.0-rc1\source\locale 目录下

对中文字体,要对默认的 css 加上修正,例如:

<LINK rel="stylesheet" href="public/css/ext-all.css">
<LINK rel="stylesheet" href="public/css/ext-all-patch.css">

来自:javaEye论坛  http://www.javaeye.com/topic/134418

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

步骤一:建立eclipse环境(基于项目组目前的环境设置)

步骤二:下载并安装jsEclipse  http://www.adobe.com/cfusion/entitlement/index.cfm?e=labs_jseclipse

步骤三:配置文件关联方式: window-preference-general-editors:file association,找到*.js,将jseclipse设为default。

步骤四:打开任意一个js文件(为了出现JSEclipse导航菜单),在JSEclipse菜单下,选择Add Library,导航到ext-all-debug.js(直接输入文件名,默认只能导入XML文件),引入该库,然后在菜单下:refresh code completion library即可,这将会在D:\workspace\.metadata\.plugins\ com.interaktonline.jseclipse\library\YourProject下生成插件xml文档。

如此设置后,在js文件中将会得到智能感知和自动完成的功能了,包括js固有的对象,还有第四步引入的ext库。

来自:JavaEye论坛 http://www.javaeye.com/topic/133392

 

JSEclipse的安装及中文乱码问题和解决办法:

看到一篇写的很详细的JSEclipse的安装与配置教程,还有关于中文乱码问题。

被 Adobe 收购的 Eclipse 下的 JavaScript 编辑工具 最先进的JavaScript编辑器之一。JSEclipse是针对Eclipse开发平台的免费插件。它支持的功能有:代码完成、大纲浏览、错误报告、代码换行,等等。

先到这里:http://labs.adobe.com/technologies/jseclipse/下载最新版本的JSEclipse

    一、jseclipse的安装

        1.打开Eclipse工作区(Workbench)
        2.利用更新管理器安装JSEclipse,在主目录中找到:Help > Software Updates ->Find and Install
        3.在弹出的界面中先择Search for new features to install.
        4.在下一步中选择搜索地址,如果这是第一次从Adobe System安装揷件,则需要新建远程站点(New remote Site),如果不是,则请直接跳至第七步.
        5.要定义新的搜索地址,单击New remote Site按钮.
        6.弹出如下对话框,其中的两处内容都必须填写:
  Name:用于显示的标签,填入"JSEclipse from Adobe Labs"或者其他相似的名称.
  URL:包含插件地址,这里填入"http://www.interaktonline.com/".
  填写完毕后单击确定应用更改,新的选项将出现在Sites to include in search一栏中.
        7.选中新填加的项目:JSEclipse from Adobe Labs.
        8.单击Finish开始搜索新软件,Eclipse会出现如下窗口显示搜索过程.
        9.搜索完成后,过程站点上的可用插件将以列表的形式给出.
        10.选中要安装的插件,单击下一步.
        11.在这一步会出现要安装插件的license agreement,肯定是必须接受的.选中I accept the terms in the license agreement按钮,单击下一步.
        12.下面选择安装路径,一般默认的路径是很合理的,我们直接单击完成开始安装.
        13.如果你的系统要求在安装插件时必须检查数字签名(digital signature),这时还会出现一个警告界面,提示你要安装的插件是没有经过数字签名的,这里直接单击Install或Install All开始安装.
        14.安装完成后系统弹出界面询问是不是要重启Eclipse,虽然不重启新安装的许多功能也能生效,但这里还是建议你重启IDE.选择Yes.
        15.最后一句也是很重要的话:JSEclipse has been installed.

    二、jseclipse的中文问题

        解决方案:  
        打开eclipse的windows-->preference-->genral-->content type,选择text-->javascript ,将对应的ISO8859-1 改为GBK,按update。

    三、注意事项

        JSEclipse需要Java 1.5或更高版本。
怎么样,o(∩_∩)o...哈哈

[JSEclipse的安装及中文乱码问题和解决办法本文版权归 呆森博客www.Dai3.cn 所有]

posted @ 2008-05-15 12:22 caihaibo 阅读(1694) | 评论 (0)编辑 收藏
     摘要: 无论你是Ext库的新手,抑或是想了解Ext的人,本篇文章的内容都适合你。本文将简单地介绍Ext的几个基本概念,和如何快速地做出一个动态的页面并运行起来,假设读者已具备了一些JavaScript经验和初级了解HTML Dom。 目錄 • 1 下载Ext • 2 开始! • 3 Element:Ext的核心 • 4 获取多个DOM的节...  阅读全文
posted @ 2008-05-14 14:43 caihaibo 阅读(1627) | 评论 (0)编辑 收藏

Ext.MasterTemplate是一个功能蛮不错的类,早在今年年头左右的时间就推出了,但使用的人不是很多。

Ext.MasterTemplate的用处在于,能够创建单个模板,在这个模板下带有多个子模板。
这些子模板可将一组对象阵列(arrays of objects )轻松地“填入”到子模板中,自然地也支持循环。定义子模板的地方

你须创建一个'tpl'的标签在模板装饰中(makeup)。

这个例子:
Java代码 复制代码
  1. var iconArray = [{img: 'images/icons/cog_orange.png', desc: 'Active Order'},   
  2.                             {img: 'images/icons/stop.png', desc: 'Cancelled Order'},   
  3.                             {img: 'images/icons/tick.png', desc: 'Completed Order'}];                     
  4.    var iconTpl = new <SPAN class=hilite1><SPAN class=hilite1>Ext</SPAN></SPAN>.MasterTemplate('<fieldset><legend>{title}</legend><tpl><img src="{img}"    
  5.   
  6. width="16" height="16" /> {desc}<br/></tpl></fieldset>');   
  7.    iconTpl.compile();   
  8.    iconTpl.fill(iconArray);   
  9.    iconTpl.append(document.body, {title: 'SAMPLE'});  
现在我们就可以轻松地用几行代码创建icon标签的容器了。fill()的第二个参数(布尔值)指的是是否允许对子模板复位,

像这样:

Java代码 复制代码
  1. iconTpl.fill(iconArray, true);  


如果你不复位子模板,它会一直 增加、追加新数组的值。注意该类所也支持模板变量,当然只适用于MasterTemplate。

本例中,title变量属于这种变量,不包含在tpl标签中。


MasterTemplates亦支持创建表格,配合tpl标签不断循环tr.
这是一个用户登陆表的实例:

Java代码 复制代码
  1. var userArray = [{username: 'aconran', userid: 1, password: '@#jkas(*}'},   
  2.                             {username: 'jarred.nicholls', userid: 2, password: 'pIZh4cKm3'},   
  3.                             {username: 'djliquidice', userid: 3, password: 'sajkfjhasir'}];                     
  4.    var userTpl = new <SPAN class=hilite1><SPAN class=hilite1>Ext</SPAN></SPAN>.MasterTemplate('<table>',   
  5.                                                              '<tr bgcolor="#c0c0c0">',   
  6.                                                                 '<td>UserID</td>',   
  7.                                                                 '<td>UserName</td>',   
  8.                                                                 '<td>Password</td>',   
  9.                                                              '</tr>',   
  10.                                                                 '<tpl>',   
  11.                                                                    '<tr>',   
  12.                                                                       '<td>{userid}</td>',   
  13.                                                                       '<td>{username}</td>',   
  14.                                                                       '<td>{password}</td>',   
  15.                                                                    '</tr>',   
  16.                                                                 '</tpl>',   
  17.                                                              '</table>');   
  18.    userTpl.compile();   
  19.    userTpl.fill(userArray);   
  20.    userTpl.add({username: 'jack.slocum', userid: 4, password: '#Cru$hin'});   
  21.    userTpl.append(document.body);  


子模板可分配名字(name属性),以便在同一个MasterTemplates中处理多个子模板。可在add()/fill()中指定哪个子模

板要去填充。下列代码是从Jack那里来的:(http://extjs.com/forum/showthread.php?t=1618)

Java代码 复制代码
  1. var t = new <SPAN class=hilite1><SPAN class=hilite1>Ext</SPAN></SPAN>.MasterTemplate(   
  2.     '<div id="{id}">',   
  3.     '<div class="right"><tpl name="right"><span>{stuff}</span></tpl></div>',   
  4.     '<div class="left"><tpl name="left"><span>{otherStuff}</span></tpl></div>',   
  5.     '</div>'  
  6.    );   
  7.    t.add('right', {stuff: 'foo'});   
  8.    t.add('left', {otherStuff: 'bar'});      
  9.    t.fill('right', arrayOfStuff);  


Ext.MasterTemplate 构建器可从三个方面创建:
插入多个参数的装饰(makeup);
传入构建器的字符串数组;
单行字符串;
所有格式化功能同样可以应用在MasterTemplates中。您可参阅之前的教程"教程:学习利用模板(Templates)的格式化功能"
http://www.ajaxjs.com/yuicn/article.asp?id=20072919

***********下面的部分专业性过于强,,应用层面可能不多。小弟我就不译了**************
The last thing I'd like to touch on is how to utilize the Member formatting functions within Templates. By adding methods to the instance of your class or by subclassing as we will do here you can create your own custom formatting functions. We will add a column called Revoked to our user table and will be returning a 0 or 1 to represent whether or not this user has been revoked. To make this more user friendly we will create a formatting function called yesNoFormat similar to ColdFusions function which converts 'truthy' values to the word "Yes" and 'falsey' values to the word "No". We simply prepend "this." in front of our new formatting function and use the same syntax that is used for native Ext formatting functions.

Java代码 复制代码
  1. var UserTemplate = function() {    
  2.       var userTableHTML = ['<table>',   
  3.                                         '<tr bgcolor="#c0c0c0">',   
  4.                                            '<td>UserID</td>',   
  5.                                            '<td>UserName</td>',   
  6.                                            '<td>Password</td>',   
  7.                                            '<td>Revoked</td>',   
  8.                                         '</tr>',   
  9.                                            '<tpl>',   
  10.                                               '<tr>',   
  11.                                                  '<td>{userid}</td>',   
  12.                                                  '<td>{username}</td>',   
  13.                                                  '<td>{password}</td>',   
  14.                                                  '<td>{isrevoked:this.yesNoFormat}</td>',   
  15.                                               '</tr>',   
  16.                                            '</tpl>',   
  17.                                         '</table>'];   
  18.       UserTemplate.superclass.constructor.call(this, userTableHTML);   
  19.       this.compile();   
  20.    };   
  21.    <SPAN class=hilite1><SPAN class=hilite1>Ext</SPAN></SPAN>.<SPAN class=hilite1><SPAN class=hilite1>ext</SPAN></SPAN>end(UserTemplate, <SPAN class=hilite1><SPAN class=hilite1>Ext</SPAN></SPAN>.MasterTemplate, {   
  22.       yesNoFormat: function(value) {   
  23.          return value ? 'Yes' : 'No';   
  24.       }          
  25.    });   
  26.       
  27.    <SPAN class=hilite1><SPAN class=hilite1>Ext</SPAN></SPAN>.onReady(function() {   
  28.       var userArray = [{username: 'aconran', userid: 1, password: '@#jkas(*}', isrevoked: 1},   
  29.                                {username: 'jarred.nicholls', userid: 2, password: 'pIZh4cKm3', isrevoked: 0},   
  30.                                {username: 'djliquidice', userid: 3, password: 'sajkfjhasir', isrevoked: 0}];                     
  31.       var userTpl = new UserTemplate();   
  32.       userTpl.fill(userArray);   
  33.       userTpl.add({username: 'jack.slocum', userid: 4, password: '#Cru$hin', isrevoked: 0});   
  34.       userTpl.append(document.body);                           
  35.    });  



Note that this example uses the array format of calling the constructor and that we have seen all 3 ways to instantiate a Template. (single liner, multiple args and an array of strings).

posted @ 2008-05-14 14:41 caihaibo 阅读(202) | 评论 (0)编辑 收藏

入门导向

Ext的新手用户可以通过下列不同的途径获取学习资源:API文档、维基百科全书、日益丰富的教程、论坛、IRC频道等等(参阅Learn ),关于这些各个方面在EXT官网上都有。但最重要的可用资源,可以说是Ext源代码本身。可以这样方便地学习源代码(Ext的项目毕竟是开源的),不仅能助你体验Ext,而且还能让你接触到大量的Javascript高级技巧和最佳实践,进一步提升自身的编码水平。

揭示源代码

Javascript是一门解释型的语言,意味着在运行之前代码是没有经过编译的。按照这种理论,在你网站上所发播的Ext代码是我们看的懂的(human-readible)。我这里说“理论上”,是因为实际情况中,很多源代码是经过某些自动化步骤的处理,生成很小几行的文件最终发布的,通过剔除空白符号和注释,或混淆等的方法,以减小文件大小。

仔细看看EXT标准源码ext-core.js,你会发现这是一段超长的源码。这是刚才提及的自动化步骤生成的结果--对浏览器来说不错!可是对于我们是难以阅读的。

ext-core.js

/*
* Ext JS Library 1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
* licensing@extjs.com
*
* http://www.extjs.com/license
*/
 
Ext.DomHelper=function(){var _1=null;var _2=/^(?:br|frame...
 
Ext.Template=function(_1){if(_1 instanceof Array){_1...
...

接着看下去的是ext-core-debug.js (注意在文件名后面加上-debug的JS文件), 我会发现是全部已格式化好的源代码。这个文件是配合调时器所使用的,像Firebug的工具能够可以让你一步一步地、一行一行地调试代码。你也会发现文件的体积将近大了一倍之多,这便是没有压缩或混淆的缘故。

ext-core-debug.js

/*
* Ext JS Library 1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
* licensing@extjs.com
*
* http://www.extjs.com/license
*/
 
Ext.DomHelper = function(){
var tempTableEl = null;
var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
var tableRe = /^table|tbody|tr|td$/i;
...

该调试版本可以在调试阶段方便地检查EXT库运行到哪一步,但是你还是会错过一个有价值的...代码注释!要完整地看到代码,就要阅读真正的原始代码!

发布Ext源码时的一些细节

你在download得到的压缩文档,包含在这些文件夹之中的,有一source的子目录。在这个文件夹里面,正如所料,是全部的EXT的源文件,遵从Lesser GNU (LGPL) 开源的协议。对于EXT开发者来说应该非常适合。

用你日常使用文本编辑器打开源代码的任意一个文件(推荐有高亮显示的编辑器,或是在这里full-featured IDE看看),便可以开始我们的探险!

我应该从哪里开始?

Ext代码库里面包含了许多各种各样的文件,甚至令人觉得有点望而生畏。好在,Ext是一个通过充分考虑后而设计的JavaScript库,--在底层的代码为各项应用提供稳健的基础如跨浏览器的各种DOM操控,使得在上层的类classes运行于一个较高级的抽象层面(class 一术语与我们已习惯的Java和C++语言稍微有所不同,但一些概念如继承则可是如此类推去理解的--有关面向对象的JavaScript的更多资料,请参见Introduction to object-oriented (OO) JavaScript)。

这意味着,当浏览源码的时候,采取“自顶向下(bottom-up)”还是“自下向顶(top-down)”的方式,都是无关紧要的。你所熟悉API里面的代码已经是属于最高的抽象层面的范畴,你可以根据你的兴趣,顺着这些你熟悉的API逐步深入。但是你若赞同我的看法,并打算深入了解其个中原理,最理想的地方是从底层代码开始。

适配器Adapters

浏览器读取第一个源文件,当中的一个任务就是创建Ext对象本身。 Ext.js

Ext = {};

Ext成型于YahooUI的Javascript库的扩展。在当时,Ext须依赖YUI的底层代码来处理跨浏览器的问题。现在ExtJS已经是独立、免依赖的库了(standalone ),你可将YUI替换为另外你所选择javascript库,如prototype、jQuery、或者是这些之中的最佳选择,-Ext自带的底层库。 负责将这些库(包括Ext自带的底层库)映射为Ext底层库的这部分代码,我们称之为适配器(Adapters)。这部分源码位于source/adapter的子目录。当项目引入Ext的时候便需要选择好你准备使用的适配器。

核心Core

source/core中的文件是构建于适配器API之上的“相对”最底层的源码。有些的源码甚至“底层”到直接为独立库的代码直接使用。这意味着应先了解和学习这整个库,再学习剩余的部分也不迟。要了解Ext的各种“Magic”和核心层面,就应该把重点放在source/core目录下的各个源代码。

 

posted @ 2008-05-14 14:16 caihaibo 阅读(197) | 评论 (0)编辑 收藏
     摘要: Javascript的调试,是开发Web应用尤其是AJAX应用很重要的一环,目前对Javascript进行调试的工具很多,我比较喜欢使用的是Firebug。Firebug是Joe Hewitt开发的一套与Firefox集成在一起的功能强大的web开发工具,可以实时编辑、调试和监测任何页面的CSS、HTML和JavaScript。 本文主要是为初学者介绍一下Firebug的基本功能与如何使用Fir...  阅读全文
posted @ 2008-05-14 13:00 caihaibo 阅读(1221) | 评论 (0)编辑 收藏
最近尝试用extjs来展示树状菜单。着实花了一番功夫。树状菜单的菜单项需要动态加载,而目前版本的extjs中只支持JSON格式的数据。查了一些资料,决定使用struts2的json-plugin。首先按照例子做了一个,但是结果就是不成功,界面上只出来了一个js中生成的root节点,不能加载从后台生成的数据。研究后发现是数据格式有问题。使用json-plugin生成的数据格式如下:
{"cls":"folder","id":10,"leaf":false,"children":[{"cls":"file","id":11,"leaf":true,"children":null,"text":"S600"},{"cls":"file","id":12,"leaf":true,"children":null,"text":"SLK200"}],"text":"Benz"}
而extjs需要的数据格式如下:
[{"cls":"folder","id":10,"leaf":false,"children":[{"cls":"file","id":11,"leaf":true,"children":null,"text":"S600"},{"cls":"file","id":12,"leaf":true,"children":null,"text":"SLK200"}],"text":"Benz"}]
区别很小,就只相差最外面的两个方括号。但是少了这两个方括号,在json中,含义迥然不同,前者表示一个对象,而后者表示一个数组。而extjs中 tree的dataloader需要的数据必须是一个数组。而这样的数据格式是json-plugin自动生成的,无法改变。所以,我最后放弃了json -plugin,转而使用json-lib来解决这个问题。
1. 下载json-lib, http://json-lib.sourceforge.net/
2. lib目录下的jar文件清单:
commons-beanutils-1.7.0.jar
commons-collections-3.2.jar
commons-digester-1.6.jar
commons-lang-2.3.jar
commons-logging-1.1.jar
dom4j-1.6.1.jar
ezmorph-1.0.4.jar
freemarker-2.3.8.jar
json-lib-2.2.1-jdk15.jar
log4j-1.2.13.jar
ognl-2.6.11.jar
struts2-core-2.0.11.jar
xml-apis-1.0.b2.jar
xwork-2.0.4.jar


首先配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>
  
<welcome-file-list>
    
<welcome-file>index.jsp</welcome-file>
  
</welcome-file-list>
  
<filter>
    
<filter-name>struts2</filter-name>
    
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  
</filter>

  
<filter-mapping>
    
<filter-name>struts2</filter-name>
    
<url-pattern>/*</url-pattern>
  
</filter-mapping>
</web-app>

然后是struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd"
>
   
<struts>
    
<constant name="struts.devMode" value="true"/>
    
<constant name="struts.i18n.encoding" value="UTF-8"/>
    
<package name="person" extends="struts-default">
        
<action name="menus" method="execute" class="com.lab.MenuAction">
            
<result>/menu.jsp</result>
        
</action>
    
</package>
</struts>

3. 树的节点模型(省略了getter,setter)
public class Menu {
    
private int id;
    
private String text;
    
private boolean leaf;
    
private String cls;
    
private List<Menu> children;
}

4. action
package com.lab;

import java.util.ArrayList;
import java.util.List;

import net.sf.json.JSONArray;

public class MenuAction {
    
private String menuString;
   
    
private List<Menu> menus;
   
    
public String execute() {

        menus 
= new ArrayList<Menu>();
       
        Menu benz 
= new Menu();
        benz.setText(
"Benz");
        benz.setCls(
"folder");
        benz.setLeaf(
false);
        benz.setId(
10);
        menus.add(benz);
       
        List
<Menu> benzList = new ArrayList<Menu>();
        benz.setChildren(benzList);
       
        Menu menu;
        menu 
= new Menu();
        menu.setText(
"S600");
        menu.setCls(
"file");
        menu.setLeaf(
true);
        menu.setId(
11);
        benzList.add(menu);
        menu 
= new Menu();
        menu.setText(
"SLK200");
        menu.setCls(
"file");
        menu.setLeaf(
true);
        menu.setId(
12);
        benzList.add(menu);
       
        Menu bmw 
= new Menu();
        bmw.setText(
"BMW");
        bmw.setCls(
"folder");
        bmw.setLeaf(
false);
        bmw.setId(
20);
        menus.add(bmw);
       
        List
<Menu> bmwList = new ArrayList<Menu>();
        bmw.setChildren(bmwList);
       
        menu 
= new Menu();
        menu.setText(
"325i");
        menu.setCls(
"file");
        menu.setLeaf(
true);
        menu.setId(
21);
        bmwList.add(menu);
       
        menu 
= new Menu();
        menu.setText(
"X5");
        menu.setCls(
"file");
        menu.setLeaf(
true);
        menu.setId(
22);
        bmwList.add(menu);
       
        JSONArray jsonObject 
= JSONArray.fromObject(menus);
        
try {
            menuString 
= jsonObject.toString();
        } 
catch (Exception e) {
            menuString 
= "ss";
        }

        
return "success";
    }

    
public String getMenuString() {
        
return menuString;
    }

    
public void setMenuString(String menuString) {
        
this.menuString = menuString;
    }
}

5. menu.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>
<s:property value="menuString" escape="false"/>

6. html页面和js
我使用的就是extjs的example中的reorder.html和reorder.js,更改了reorder.js中treeloader的dataurl: menus.action
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Reorder TreePanel</title>
<link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css" />

    
<!-- GC -->
     
<!-- LIBS -->
     
<script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>
     
<!-- ENDLIBS -->
 
    
<script type="text/javascript" src="extjs/ext-all.js"></script>
<script type="text/javascript" src="reorder.js"></script>

<!-- Common Styles for the examples -->
<link rel="stylesheet" type="text/css" href="extjs/resources/css/example.css" />
</head>
<body>
<script type="text/javascript" src="../examples.js"></script><!-- EXAMPLES -->
<h1>Drag and Drop ordering in a TreePanel</h1>
<p>This example shows basic drag and drop node moving in a tree. In this implementation there are no restrictions and 
anything can be dropped anywhere except appending to nodes marked 
&quot;leaf&quot; (the files). <br></p>
<p>Drag along the edge of the tree to trigger auto scrolling while performing a drag and drop.</p>
<p>In order to demonstrate drag and drop insertion points, sorting was <b>not</b> enabled.</p>
<p>The data for this tree is asynchronously loaded with a JSON TreeLoader.</p>
<p>The js is not minified so it is readable. See <href="reorder.js">reorder.js</a>.</p>

<div id="tree-div" style="overflow:auto; height:300px;width:250px;border:1px solid #c3daf9;"></div>

</body>
</html>



js:
/*
 * Ext JS Library 2.0.1
 * Copyright(c) 2006-2008, Ext JS, LLC.
 * licensing@extjs.com
 *
 * http://extjs.com/license
 
*/

Ext.onReady(
function(){
    
// shorthand
    var Tree = Ext.tree;
   
    
var tree = new Tree.TreePanel({
        el:'tree
-div',
        autoScroll:
true,
        animate:
true,
        enableDD:
true,
        containerScroll: 
true,
        loader: 
new Tree.TreeLoader({
            dataUrl:'http:
//localhost:8080/lab/menus.action'
        })
    });

    
// set the root node
    var root = new Tree.AsyncTreeNode({
        text: 'Ext JS',
        draggable:
false,
        id:'source'
    });
    tree.setRootNode(root);

    
// render the tree
    tree.render();
    root.expand();
});
posted @ 2008-05-14 11:17 caihaibo 阅读(879) | 评论 (5)编辑 收藏

Firebug是Firefox下的一款开发类插件,现属于Firefox的 五星级强力推荐插件之一。它集HTML查看和编辑、Javascript控制台、网络状况监视器于一体,是开发JavaScript、CSS、HTML和 Ajax的得力助手。Firebug如同一把精巧的瑞士军刀,从各个不同的角度剖析Web页面内部的细节层面,给Web开发者带来很大的便利。这是一款让 人爱不释手的插件,如果你以前没有接触过它,也许在阅读本文之后,会有一试的欲望。笔者在撰写此文的时候,正逢Firebug发布1.0正式版,这不能不 说是种巧合。

应用

Firebug插件虽然功能强大,但是它已经和Firefox浏览器无缝地结合在一起,使用简单直观。如果你担心它会占用太多的系统资源,也可以方便地启用/关闭这个插件,甚至针对特定的站点开启这个插件。

在安装好插件之后,先用Firefox浏览器打开需要测试的页面,然后点击右下方的绿色按钮或使用快捷键F12唤出Firebug插件,它会将当前页面分成上下两个框架,如图1所示。

图1:Firebug插件展开图示
firebug插件展开图示
从图1中看到,Firebug有6个主要的Tab按钮,下文将主要介绍介绍这几方面的功能。

Console HTML CSS Script Dom Net
控制台 Html查看器 Css查看器 脚本条时期 Dom查看器 网络状况监视

Console 控制台

控制台能够显示当前页面中的javascript错误以及警告,并提示出错的文件和行号,方便调试,这些错误提示比起浏览器本身提供的错误提示更加 详细且具有参考价值。而且在调试Ajax应用的时候也是特别有用,你能够在控制台里看到每一个XMLHttpRequests请求post出去的参数、 URL,http头以及回馈的内容,原本似乎在幕后黑匣子里运作的程序被清清楚楚地展示在你面前。

象C shell或Python shell一样,你还能在控制台中查看变量内容,直接运行javascript语句,就算是大段的javascript程序也能够正确运行并拿到运行期的信息。

控制台还有个重要的作用就是查看脚本的log, 从前你也许习惯了使用alert来打印变量,但是Firebug给我们带来了一个新朋友 —— console.log, 最简单的打印日志的语法是这样的:

CODE:
  1. console.log("hello world")

如果你有一堆参数需要组合在一起输出,可以写成这样:

CODE:
  1. console.log(2,4,6,8,"foo",bar).

Firebug的日志输出有多种可选的格式以及语法,甚至可以定制彩色输出,比起单调的alert,显然更加方便,限于篇幅,这里不做详细说明,但是有志于提高debug效率的读者,可以到Firebug的官方站点(见附录)查看更详细的教程。

图2: 在控制台里调试javascript
在控制台里调试javascript

查看和修改HTML

第一次看到Firebug强大的HTML代码查看器,就觉得它与众不同,相比于Firefox自带的HTML查看器,它的功能强大了许多。 HTML

首先你看到的是已经经过格式化的HTML代码,它有清晰的层次,你能够方便地分辨出每一个标签之间的从属并行关系,标签的折叠功能能够帮助你集中精 力分析代码。源代码上方还标记出了DOM的层次,如图3所示,它清楚地列出了一个hml元素的parent、child以及root元素,配合 Firebug自带的CSS查看器使用,会给div+css页面分析编写带来很大的好处。你还可以在HTML查看器中直接修改HTML源代码,并在浏览器 中第一时间看到修改后的效果,光凭这一点就会让许多页面设计师死心塌地地成为Firebug的粉丝了。

有时候页面中的javascript会根据用户的动作如鼠标的onmouseover来动态改变一些HTML元素的样式表或背景色,HTML查看器会将页面上改变的内容也抓下来,并以黄色高亮标记,让网页的暗箱操作彻底成为历史。

利用Inspect检查功能,我们还可以用鼠标在页面中直接选择一些区块,查看相应的HTML源代码和CSS样式表,真正的做到所见即所得,如果你 使用了外部编辑器修改了当前网页,可以点击Firebug的reload图片重新载入网页,它会继续跟踪你之前用Inspect选中的区块,方便调试。

图3::HTML查看器
HTML查看器

CSS调试

Firebug的CSS调试器是专为网页设计师们量身定做的。

如今的网页设计言必称div+css,如果你是用table套出来的HTML页面,就得按这规矩重构一遍,否则显得你不够时髦!用div做出来的页 面的确能精简HTML代码,HTML标签减肥的结果就是CSS样式表的编写成了页面制作的重头戏。Firebug的CSS查看器不仅自下向上列出每一个 CSS样式表的从属继承关系,还列出了每一个样式在哪个样式文件中定义。你可以在这个查看器中直接添加、修改、删除一些CSS样式表属性,并在当前页面中 直接看到修改后的结果。

一个典型的应用就是页面中的一个区块位置显得有些不太恰当,它需要挪动几个象素。这时候用CSS调试工具可以轻易编辑它的位置——你可以根据需要随意挪动象素。
如图4中正在修改一个区块的背景色。

提示:如果你正在学习CSS样式表的应用,但是总记不住常用的样式表有哪些值,可以尝试在CSS调试器中选中一个样式表属性,然后用上下方向键来改变它的值,它会把可能的值一个个遍历给你看。

图4: CSS查看器,能够直接修改样式表
图4: CSS查看器,能够直接修改样式表

可视化的CSS尺标

我们可以利用Firebug来查看页面中某一区块的CSS样式表,如果进一步展开右侧Layout tab的话,它会以标尺的形式将当前区块占用的面积清楚地标识出来,精确到象素,更让人惊讶的是,你能够在这个可视化的界面中直接修改各象素的值,页面上 区块的位置就会随改动而变化。在页面中某些元素出现错位或者面积超出预料值时,该功能能够提供有效的帮助,你可以籍此分析offset、margin、 padding、size之间的关系,从而找出解决问题的办法。

图5:Firebug中的CSS标尺
图5:Firebug中的CSS标尺

网络状况监视器

也许有一天,你的老板或者客户找到你,抱怨你制作的网页速度奇慢,你该如何应对?你或许会说这可能是网络问题,或者是电脑配置问题,或者是程序太慢,或者直说是他们的人品问题?不管怎么说,最后你可能被要求去解决这个有多种可能的问题。

网络状况监视器能帮你解决这个棘手问题。Firebug的网络监视器同样是功能强大的,它能将页面中的CSS、javascript以及网页中引用 的图片载入所消耗的时间以矩状图呈现出来,也许在这里你能一把揪出拖慢了你的网页的元凶,进而对网页进行调优,最后老板满意客户欢喜,你的饭碗也因此而牢 固。

网络监视器还有一些其它细节功能,比如预览图片,查看每一个外部文件甚至是xmlHttpRequests请求的http头等等。

图6:网络状况监视器
图6:网络状况监视器

Javascript调试器

这是一个很不错的javascript脚本调试器,占用空间不大,但是单步调试、设置断点、变量查看窗口一个不少。正所谓麻雀虽小,五脏俱全。

如果你有一个网站已经建成,然而它的javascript有性能上的问题或者不是太完美,可以通过面板上的Profile来统计每段脚本运行的时间,查看到底是哪些语句执行时间过长,一步步排除问题。

图7:javascript调试器
图7:javascript调试器

DOM查看器

DOM(Document Object Model)里头包含了大量的Object以及函数、事件,在从前,你要想从中查到需要的内容,绝非易事,这好比你去了一个巨大的图书馆,想要找到几本名 字不太确切的小书,众多的选择会让你无所适从。而使用Firebug的DOM查看器却能方便地浏览DOM的内部结构,帮助你快速定位DOM对象。双击一个 DOM对象,就能够编辑它的变量或值,编辑的同时,你可能会发现它还有自动完成功能,当你输入document.get之后,按下tab键就能补齐为 document.getElementById,非常方便。如果你认为补齐得不够理想,按下shift+tab又会恢复原状。用了Firebug的 DOM查看器,你的javascript从此找到了驱使的对象,Web开发也许就成了一件乐事。

图8: Dom查看器
图8: Dom查看器

小结

Firebug插件提供了一整套web开发所必需的工具。从HTML的编写,到CSS样式表的美化调优,以及用javascript脚本开发,亦或 是Ajax应用,Firebug插件都会成为你的得力助手。所谓工欲善其事,必先利其器。在Web2.0的时代,言必称Ajax,动辄就是用户体验提升, 如果把Firebug工具用好,必能让你如虎添翼,将HTML、CSS、javascript整理得服服帖帖,从此成为web开发中的专家级人物。

Firebug的中文含义是萤火虫,作者是Joe Hewitt,官方网页 http://www.getfirebug.com ,Firefox亦即火狐浏览器

点击下面的星星,参与投票评分



平均得分3.50分(共2次打分)
喜欢本文?欢迎订阅且行资源,了解最新资讯 |不了解订阅,请阅读:如何订阅
posted @ 2008-05-12 16:27 caihaibo 阅读(331) | 评论 (0)编辑 收藏
Tomcat 6.0.10 配置指南
作者:佚名    文章来源:不详    点击数:     更新时间:2007-7-8    
    今天在机子上配置了由Apache Software Foundation研发的开源产品Tomcat服务器,以用于jsp开发。
正在装载数据……

    首先,在运行Tomcat之前,我们要确保本机已经安装了JDK(Java developing kit),这是运行Tomcat的首要环境。目前,sun公司已经将jdk升级为JDK 6.0,我们可以直接到下面的网址上去下载http://java.sun.com/javase/downloads/index.jsp。下载完成后按照向导完成安装。然后如下配置环境变量:
    JAVA_HOME:  C:\Program Files\Java\jdk1.6.0(jdk的安装路径)
    CLASSPATH:  .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
    PATH:  %JAVA_HOME%\bin;
    接下来我们就可以到下面的网址去下载Tomcat的最新版本:http://tomcat.apache.org/download-60.cgi,我下载的是Tomcat 6.0.10解压版本。下载完成后直接解压缩就可以用了。
    Tomcat的目录下面有一个bin目录,我们双击里面的startup.bat就可以使Tomcat运行。
    还有一个问题,如果我们注意的话,在运行Tomcat之前,窗口中会打印出如下信息:tomcat6.0The Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path。如果你忽略它并不会影响你的正常使用。这是因为Tomcat 可以用 Apache Portable Runtime 来提供更强性能,提升Web静态页面的处理能力,不再需要专门的Web Server来处理静态页面了。
    但是APR的支持需要安装三个本地组件
    APR support requires three main native components to be installed:
    1、APR library
    2、JNI wrappers for APR used by Tomcat (libtcnative)
    3、OpenSSL libraries
    我们可以点击这里http://tomcat.heanet.ie/native下载编译好的 tcnative-1.dll 文件,然后把它放到bin目录中就OK了。
    相关的文档请参见:http://tomcat.apache.org/tomcat-5.5-doc/apr.html   
posted @ 2008-05-09 11:28 caihaibo 阅读(281) | 评论 (0)编辑 收藏

1) 安装完MyEclipse后,在Eclpise的菜单栏可看到MyEclipse一项,
     下面的工具栏中可看到MyEclipse的Tomcat图标

2) 进行MyEclipse的配置,
      从菜单栏中进入“Windows --> Preferences”

3) 先要进行JDK的配置,
    在左侧栏中选择“Java --> Installed JREs”,
    按“Add”按钮进行添加

4) 在弹出的“Add JRE”画面中,选择JRE的目录,
     就是选择你所在的JDK的目录,
    在JRE名称一栏中,填下想取的名称,我这里叫“JDK”,
    然后“OK”确定

5) 返回到设置框中,将刚刚配置的JRE选中

6) 开始配置MyEclipse,
      左侧MyEclipse节点下“Application Server”中有Tomcat,
      选择自己安装的版本,
      将Tomcat Server设为可用,并设置Tomcat的安装目录

7) 在Tomcat的JDK中选择刚刚配置的JDK

8) 配置完成了,三个地方可以启动它的服务,根据自己的喜好吧~~~ 呵呵~~~

 



Trackback: http://tb.donews.net/TrackBack.aspx?PostId=772830

posted @ 2008-05-08 11:44 caihaibo 阅读(285) | 评论 (0)编辑 收藏
 添加varchar类型的字段时一定要加参数 否则报错1046 错误的符号 可能是解释程序不能编译varchar
   create table test.user(
 id varchar(10) not null,
 name varchar(10) not null,
 password varchar(10)testtesttest not null,
 primary key (id)
  )
posted @ 2008-05-05 11:59 caihaibo 阅读(216) | 评论 (0)编辑 收藏
iis 占用端口 80 ?
posted @ 2008-05-04 10:39 caihaibo 阅读(227) | 评论 (0)编辑 收藏
相信大家都遇见过:在删除一些软件的时候弹出某某文件正在运行或磁盘写保护不能删除这样的报错提示吧(如图1)。而常常删除不掉的都一些后缀为.dll的文件。到底这个dll文件是什么文件,如何才能知道是哪些程序在调用这个dll文件呢?
 
    dll文件英文名称为Dynamic Linking Library,以下简称dll,中文名字"动态链接程序库"文件。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即dll文件,放置于系统中。当我们执行某一个程序时,相应的dll文件就会被调用。一个应用程序可有多个dll文件,一个dll文件也可能被几个应用程序所共用。比如,假设系统中有一dll具备了与远端系统进行网络联接的功能,我们假设其名称为Network.dll,如果有另外一个应用程序想使用该功能,则这个程序只需在执行时与Network.dll进行动态链接(Dynamic Linking),就可以运用Network.dll的网络联接功能来实现远端联接系统。简单地说,dll的特性是:
 
1、dll本身无法自行执行,必须靠其他程序调用。
 
2、dll文件都具有一定的功能。
 
3、在系统刚建立时 (如刚装好Windows时),系统中即存在有一定数量的dll,而某些应用程序亦会将自已所需的dll添至系统中,导致dll的数量随应用程序的增加而增加。
 
    既然知道了dll文件的概念和特性,那么怎么才能解决删除难这个问题呢?虽然解决这个问题的方法有很多种,如用软件unlocker来删除。这里介绍的是手工删除方法dll文件的方法。
 
    因为dll文件的特性注定了它可能被多个软件调用,这也是dll文件为什么删除不掉的原因——正在使用的文件是当然不可能给你删除的。那么到底是哪个程序在调用这个dll文件呢?如何才能删除这个dll文件呢?下面就手动删除dll文件的方法。
 
Step 1.在运行里输入cmd进入命令提示符。
 
step 2.然后输入命令tasklist /m>c:\listdll.txt回车后,在C盘下会出现一个listdll.txt文本文件,这个文件里如图2所示列出了目前运行的各个程序正在调用的dll文件。在用CTRL+F弹出查找框,输入自己要删除的的dll文件,查找出是哪个程序在调用这个dll文件。
step 3.CTRL+ALT+DEL打开Windows资源管理器,结束占用需要删除dll文件的程序或着进程,这时再去删除这个dll文件就很轻松了。
 
step 4.如果查出来的占用dll文件的进程是svhost.exe文件/进程,这个进程一般系统有7、8个至多,到底是哪个svhost.exe进程占用了这个dll文件呢?这是可以在命令提示符下输入tasklist /svc,当然,你也可以把它输出为文本文件tasklist /svc>C:\listsvc.txt。这时listsvc.txt文件里的svhost.exe会跟出如图3所示的各个进程的PID号。这时就可以具体的根据PID号来结束进程,达到删除dll文件的目的。
posted @ 2008-05-04 09:37 caihaibo 阅读(1688) | 评论 (0)编辑 收藏
posted @ 2008-05-03 16:56 caihaibo 阅读(176) | 评论 (0)编辑 收藏

潘石屹的“草根哲学”

——读他的新著《我用一生去寻找:潘石屹的人生哲学》

在生活中,你遇到一个有平民气质的平民不难,遇到一个有贵族气质的贵族也不难,难的是能遇到有贵族气质的平民,和有平民气质的贵族。换句话说,见草是草,见树是树,这不稀奇,但你能见到一根有大树气质的小草,和有小草气质的大树么?这儿就有一个,他叫潘石屹,中国SOHO是他的外形,大树树冠的外形;这本书是他的气质,小草草根的气质。

翻翻这本书,你能闻到一缕缕青草的香气,看到一片片柔软的葱绿,听到一阵阵轻微的窸窣,那不是绸缎和耳鬓斯磨的声音,而是微风吹过草叶的声音。这本书里的每行字,都像是一片片草叶;每片草叶,又都像作者絮语时轻轻卷动的舌头。不同的是,草的话是说给风听的,潘石屹的话是说给我们听的:

“当别人告诉这位智者我整天在网上写博客,我的博客有许多人看时,他提醒我,要有仁慈的舌头,千万不要在人心中播下不和的种子。”

我想,草叶的舌头应该是仁慈的,就像美国大诗人惠特曼的舌头一样。但潘石屹写的并不是《草叶集》,而是沿着草叶深入到根部,写了一本通俗版的人生哲学,我很想将之称为“草根哲学”。这个哲学平易得就像你每天早餐喝的那杯牛奶。

——要有根。这似乎是潘氏“草根哲学”的第一章。什么是人生的“根”? 潘石屹告诉我们,人生的根就是“爱”与“自信”。恨也是一种根,“仇恨入心要发芽”,那还不生根?但从恨的根上会开出恶之花,“以恶对恶,增值的还是恶”,被恶霸占的人生,就像是被毒蛇缠身的兔子,能有什么指望?所以潘石屹说:“我永远相信爱的力量,而相信就是力量。”而有爱的人就有自信,自信的人才会诚实,诚实的人才能成功。所以,在潘石屹看来,爱是人生的第一只桶,自信是人生的第一桶金:

“经常有人问我第一桶金怎么来的,从哪里得到的,有多少。其实每次别人问我这个问题时,我都想说,人的第一桶金是自信。即使你没钱也不要怕,自信就是你的资本。”

我可以为他这段话背书,他当年被海南万通派到北京开发新项目,只带了几万块钱,但肯定在行李箱里放了很多自信进京。如果我没有记错,他最早住的是南兵马司招待所,那地方我也住过,干净,但很简陋。几年后,阜成门的万通广场落成,它当时是万通系最大也是唯一一家发行法人股的地产项目。

——要平凡。平凡,低调,简单……这些词都可以用来定性被你看到,或被你踩在脚底下的小草。不过,当你走进一片丰美的草地时,你就忍不住想躺下来,读几页书,或者无所事事地晒晒太阳,这是说,平凡的东西让人亲近。潘石屹所推崇的平凡,包括必要的“迟钝”,甚至“缓慢”,特别是“简单”:

“从历史的角度来看,一个民族向上的时候,它总是简单和大气为重要的风格;凡是这个民族衰败之时,从建筑、家居、服装、装饰到语言表现出来的都是繁杂和多余。能把简单作为自己的世界观,成为自己做事情的指导思想,是走向成功的一个要素。你会在简单中获得成功。”

潘石屹特别看重谈话和人际交往中的“平凡”。最平凡最受人欢迎的交谈者是“倾听者”:“大多数情况下,当一个好的听众,欣赏别人的表现,就是建立人际关系的第一个好办法。”最糟糕的想法,就是“今天要用语言征服那个人。”结果是针锋相对,面红耳赤。“你看有些人,瞪着眼睛看你说话,你以为他听进去了,他没有,他在找你说话的间歇来插言,来抢话。他是一个全神贯注寻找发言机会的人,就像一个蹲在路边虎视眈眈准备拦路抢劫的强盗一样。”读到这儿,对照一下我自己,只能叹口气,看来,世界上最不平凡的事,就是甘于平凡呵。

——要合群。在潘石屹看来,生命是一个共同体,就像草一样,一根草活不了,草连成片,才成气候。但他这样说,并不是要搞生命共产主义,他不反对“个性”,也不反对“自我”,他反对的是过分的“自我”。他把“自我”比作盐,没有它,没有人生的美味,多了,就破坏了美味。既要自我,又要群体,怎么办?磋商。自我通过磋商达成与别的自我的合作,所以他认为,“人人参与的磋商才具有普世价值”。杜甫有诗云:“繁枝容易纷纷落,嫩蕊商量细细开”。独树一帜的繁枝容易凋落,细细磋商的小草和嫩蕊慢慢茂盛。

——要无为。世界最无为的生命大概就是草了。它不追求什么,也不拒绝什么,不逃避什么,也不挽留什么。起伏随风吹,荣枯顺岁时。作为企业领导人,潘石屹认为,公司做得越大,越要无为而治理。无为而治,其实是顺势而为,“我们好像水上的小舟,依托流水的力量前行。我们要尊重它,感应到它,顺应它。如果你以为你有一点权力,可以无所顾忌,搞乱生活,是一定会受到惩罚的。”禹作敏、牟其中等人如果能早一点悟出这个道理,下场肯定要好得多。

关于潘石屹这本书,当然还有许多话可说,比如要顽强,要敬畏之类,不过,如果一定要我对它提出一点批评意见,我最想说的是,潘石屹的哲学是一个有明确人生目标的人的哲学,不是一个活在当下的人的哲学,后一种人欣赏的不是地上的小草,而是空中的微风和天上的白云。

2008417
——原载
2008-4-28《经济观察报》第48版“商业评论”(提前出版)

posted @ 2008-04-29 17:36 caihaibo 阅读(103) | 评论 (0)编辑 收藏

MyEclipse+struts+Hibernate配置开发

2005-12-18 10:31 作者: CoderGuo 出处: sina博客 责任编辑:方舟

说明:

  这个手册只是为初学者制作的环境配置和快速开发的一些基本方法,为的是广大爱好者能快速上手,少走我走过的弯路,里面没有任何关于java模式和其他相关的说明。本人水平有限,也没有能力去讨论关于模式设计和开发细节的一些内容。

 

 

  建议:

  如果你还不清楚struts和hibernate的一些基本原理,希望能先去了解一下这方面的相关内容。

  推荐:

  Hibernate中文手册》作者认为要学Hibernate看这个就足够了,里面几乎包括了所有的细节,不过可能不太适合快速入门。

  地址:http://www.hibernate.org/hib_docs/v3/reference/zh- cn/html_single/

  关于struts的资料就很多了,这里推荐一个可以下载一些入门教程的网站。

  地址:http://www.wnetw.com/jclub/index.jsp

  强烈建议入门的朋友先了解一下基本的原理!否则本文可能对你没有任何帮助。

  相关工具下载:(注意版本)

  mysql5.0 http://www.mysql.org
  eclipse 3.1.1 http://www.eclipse.org
  myeclipse4.0.3 http://www.myeclipseide.com
  tomcat5.5

  安装:

  关于tomcat和mysql的安装就不多说了,需要注意的是最好保证你的 jdk是1.5的版本,并配置好你的环境变量,不然可能会遇到一些问题。

  把eclipse解开,再去安装刚下载的myeclipse,在安装的时候需要把路径指定到刚才解开的eclipse上,由于myeclipse是个收费软件,所以需要注册。不过一般按照Chinese的习惯,去google一个注册码就可以了:}

  开发环境部署:

  好了,现在保证你的mysql和tomcat服务能够正常启动,myeclipse能够正常打开(如果不能,可以去找一下相关的说明或者给作者留言)。下面我们就要开始真正的开始部署一个传说中的tomcat+struts+hibernate+mysql结构的工程了!(faint!前言就写的我好累)

  首先,在myeclipse里新建一个工程。在左边的Package Exporler面版里点右键选择new->project…

  在跳出菜单里选择MyEclipse->J2EE Projects->Web Project。

  点击next后进入如下画面:


  工程名为:test

  结束后点击Finish。

  好了,如果成功的话你就会在 Package Exporler里看到一个新的test工程!现在我们先配置一下数据库方面的东西。首先在你的mysql 里建立一个数据库webases,再在里面新建一个表admin,里面三个字段分别为id,name,password其中id为自动取值的主键(mysql具体的操作可以自己找资料,不是本文涉及范围)。

  再回到myeclipse ,选中window->Open Perspective->Other…

  可以看到现在跳出一个名为Select Perspective的菜单,在里面选中MyEclipse Databases Exporler,可以看到现在到了下面的页面。

  按以上图示输入相关字段后点击Finish便建立了一个数据库连接,在新出现的JDBC for Mysql上点右键,选择Open connection…,确认用户名和密码正确后点OK,如果一切顺利的话你会看到下面的画面:

  这说明你已经和数据库建立了正确的连接。现在我们再回到window->Open Perspective- >Other…里的MyEclipse,也就是我们刚进来的时候看到的画面。

  右键点击你刚建立的工程 test并选择MyEclipse->Add struts Capabilities…在跳出的菜单里按照如下输入并确定:

  好了,现在你已经为你的工程增加了struts,接下来和上面一样在右键工程后选择MyEclipse- >Add Hibernate Capabilities…一路确定下来为你的工程添加Hibernate。(为方便起见我们在选择路径时把HibernateSessionFactory.java放在了src/com下面,其实最好建立个单独的目录如 src/com/hibernate)

  为了更好的演示我们不建立通常的登陆页面而是建立个注册页面。选择 src目录下的hibernate.cfg.xml文件。照如下填写并保存。这样hibernate就为你建立了数据库的连接池。

  下面我们再选择WebRoot/WEB-INF/struts-config.xml文件,在画面中点击右键选择new- >Form, Action and JSP。如下填写

  再选择JSP选项,如下

  最后选择Finish。

  再新建一个一个success.jsp的页面,

  在刚才struts- config.xml文件里右键选择addAdmin选择Properties,在菜单里选择Forwords,再点add,如下图填写

  最后你的struts-config.xml就是下面这个样子:


  下面我们转到hibernate。换到刚才我们建立数据库的页面,选择你的admin的表点右键选择Create Hibernate Mapping。选择好打包路径后选择Finish。如图:

  在你刚才选择的路径下(我为方便是src/com/yourcompanyname/)下新建立的文件 AdminDAOFactory.java文件并输入以下内容:

package com.yourcompanyname;

import java.util.Iterator;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.hibernate.SessionFactory;

public class AdminDAOFactory {
 Session session;
 Transaction tx;
 public void add(Admin admin) throws HibernateException {
  /**
   * Creation Date: 11-17-2005
   * TODO Add a new admin user.
   * @param An object of Admin
   * @return void
   * @author Coder Guo
   */
  try {
   session = SessionFactory.currentSession();
   tx = session.beginTransaction();
   //Add a new admin
   session.save(admin);
   tx.commit ();
  }catch(HibernateException e){
   throw e;
  }finally{
   if (tx!=null) {
    tx.rollback();
   }
   SessionFactory.closeSession();
  }
 }
}

 再打开com.yourcompany.struts.action下的AddAdminAction.java添加(其中如果有错误选中好按ctrl+shift+o自动添加包)

public class AddAdminAction extends Action {

 // --------------------------------------------------------- Instance Variables

 // --------------------------------------------------------- Methods

 /**
  * Method execute
  * @param mapping
  * @param form
  * @param request
  * @param response
  * @return ActionForward
  * @author Coder Guo
  */
 public ActionForward execute(
  ActionMapping mapping,
  ActionForm form,
  HttpServletRequest request,
  HttpServletResponse response) {
  AddAdminForm addAdminForm = (AddAdminForm) form;
  
  // TODO Add a new admin
  Admin admin = new Admin();
  admin.setName(addAdminForm.getName ());
  admin.setPassword(addAdminForm.getPassword ());
  AdminDAOFactory adminDAO = new AdminDAOFactory ();
  adminDAO.add(admin);
  
  return mapping.findForward("success");
 }

}

 再打开com.yourcompanyname.struts.form下的AddAdminForm.java,修改(如果有错误按照上面说的方法导入包)
 public ActionErrors validate(
  ActionMapping mapping,
  HttpServletRequest request) {

  // TODO Auto-generated method stub
  ActionErrors errors = new ActionErrors();
  
  Session session = SessionFactory.currentSession();
  Transaction tx = session.beginTransaction ();
  Query query = session.createQuery("select admin from Admin as admin where admin.name = '" + this.name + "'");
  Iterator it = query.iterate ();
  if (it.hasNext()){
   errors.add ("addAdmin.err.name",new ActionMessage("form.addAdmin.err.name"));
  }
  tx.commit();
  SessionFactory.closeSession ();
  return errors;
 }

 public void reset(ActionMapping mapping, HttpServletRequest request) {

  // TODO Auto-generated method stub
  this.name=null;
  this.password=null;
 }

  再打开com\yourcompanyname\struts下的ApplicationResource.properties在这里面添加错误信息:

Form.addAdmin.err.name=err

  最后,(汗,好累啊-_-!)打开addAdmin.jsp修改成如下:

<%@ page contentType="text/html; charset=utf-8"%>
<%@ page language="java"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>

<script language = "javascript">
<!--
function check(){
 if (loginForm.userName.value == "" || loginForm.password.value == ""){
  alert("请输入完整的信息!");
  loginForm.userName.focus();
  return false;
 }
}
//-->
</script>
 
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html:html>
  <head>
    <html:base />
   
    <title>login.jsp</title>
    <link href="css/webcss.css" rel="stylesheet" type="text/css">
   
    <meta http-equiv="pragma" content="no- cache">
    <meta http-equiv="cache-control" content="no- cache">
    <meta http-equiv="expires" content="0">   
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http- equiv="description" content="This is my page">
  </head>
 

  <body>
  <center>
   <p>&nbsp;</p>
   <p>&nbsp;</p>
   <table width="300" border="0" cellpadding="0" cellspacing="0">
   <html:form action="/addAdmin" focus="name" method="GET">
     <tr align="center" valign="middle">
       <td colspan="2" class="typt_normal">新增管理员</td>
     </tr>
     <tr>
       <td width="100" align="center" valign="middle" class="typt_normal">名称: </td>
       <td width="200" align="left"><html:text property="name" styleClass="text_s"/><html:errors property="addAdmin.err.name"/></td>
     </tr>
     <tr>
       <td width="100" align="center" valign="middle" class="typt_normal">密码: </td>
       <td width="200" align="left"><html:password property="password" styleClass="text_s"/></td>
     </tr>
     <tr> 
       <td colspan="2" align="center" valign="middle"><html:submit value="提交" onclick="return check ();"/><html:reset value="重置"></html:reset></td>
       </tr>
 </html:form>
   </table>
 </center>
 </body>

</html:html>

  其中可以看到如何在struts的标签中使用javascript的方法。

  配置好myeclipse于tomcat的连接。在window->Preferences做如下设定:

  在项目文件点右键->“myeclipse”->“Add and remove project deployment”,如下图:

  好了,我们的配置工作基本结束了,在myeclipse上开启tomcat服务

  现在打开浏览器,输入

  http://127.0.0.1:8080/test/addAdmin.jsp就可以看到你的jsp页面了!

 

posted @ 2008-04-28 23:17 caihaibo 阅读(165) | 评论 (0)编辑 收藏
SELECT --从数据库表中检索数据行和列
INSERT --向数据库表添加新数据行
DELETE --从数据库表中删除数据行
UPDATE --更新数据库表中的数据
--数据定义
CREATE TABLE --创建一个数据库表
DROP TABLE --从数据库中删除表
ALTER TABLE --修改数据库表结构
CREATE VIEW --创建一个视图
DROP VIEW --从数据库中删除视图
CREATE INDEX --为数据库表创建一个索引
DROP INDEX --从数据库中删除索引
CREATE PROCEDURE --创建一个存储过程
DROP PROCEDURE --从数据库中删除存储过程
CREATE TRIGGER --创建一个触发器
DROP TRIGGER --从数据库中删除触发器
CREATE SCHEMA --向数据库添加一个新模式
DROP SCHEMA --从数据库中删除一个模式
CREATE DOMAIN --创建一个数据值域
ALTER DOMAIN --改变域定义
DROP DOMAIN --从数据库中删除一个域
--数据控制
GRANT --授予用户访问权限
DENY --拒绝用户访问
REVOKE --解除用户访问权限
--事务控制
COMMIT --结束当前事务
ROLLBACK --中止当前事务
SET TRANSACTION --定义当前事务数据访问特征
--程序化SQL
DECLARE --为查询设定游标
EXPLAN --为查询描述数据访问计划
OPEN --检索查询结果打开一个游标
FETCH --检索一行查询结果
CLOSE --关闭游标
PREPARE --为动态执行准备SQL 语句
EXECUTE --动态地执行SQL 语句
DESCRIBE --描述准备好的查询
---局部变量
declare @id char(10)
--set @id = '10010001'
select @id = '10010001'

---全局变量
---必须以@@开头



--IF ELSE
declare @x int @y int @z int
select @x = 1 @y = 2 @z=3
if @x > @y
print 'x > y' --打印字符串'x > y'
else if @y > @z
print 'y > z'
else print 'z > y'



--CASE
use pangu
update employee
set e_wage =
case
when job_level = ’1’ then e_wage*1.08
when job_level = ’2’ then e_wage*1.07
when job_level = ’3’ then e_wage*1.06
else e_wage*1.05
end



--WHILE CONTINUE BREAK
declare @x int @y int @c int
select @x = 1 @y=1
while @x < 3
begin
print @x --打印变量x 的值
while @y < 3
begin
select @c = 100*@x + @y
print @c --打印变量c 的值
select @y = @y + 1
end
select @x = @x + 1
select @y = 1
end



--WAITFOR
--例 等待1 小时2 分零3 秒后才执行SELECT 语句
waitfor delay ’01:02:03’
select * from employee
--例 等到晚上11 点零8 分后才执行SELECT 语句
waitfor time ’23:08:00’
select * from employee




***SELECT***



select *(列名) from table_name(表名) where column_name operator value
ex:(宿主)
select * from stock_information where stockid = str(nid)
stockname = 'str_name'
stockname like '% find this %'
stockname like '[a-zA-Z]%' --------- ([]指定值的范围)
stockname like '[^F-M]%' --------- (^排除指定范围)
--------- 只能在使用like关键字的where子句中使用通配符)
or stockpath = 'stock_path'
or stocknumber < 1000
and stockindex = 24
not stock*** = 'man'
stocknumber between 20 and 100
stocknumber in(10,20,30)
order by stockid desc(asc) --------- 排序,desc-降序,asc-升序
order by 1,2 --------- by列号
stockname = (select stockname from stock_information where stockid = 4)
--------- 子查询
--------- 除非能确保内层select只返回一个行的值,
--------- 否则应在外层where子句中用一个in限定符
select distinct column_name form table_name --------- distinct指定检索独有的列值,不重复
select stocknumber ,"stocknumber + 10" = stocknumber + 10 from table_name
select stockname , "stocknumber" = count(*) from table_name group by stockname
--------- group by 将表按行分组,指定列中有相同的值
having count(*) = 2 --------- having选定指定的组



select *
from table1, table2
where table1.id *= table2.id -------- 左外部连接,table1中有的而table2中没有得以null表示
table1.id =* table2.id -------- 右外部连接



select stockname from table1
union [all] ----- union合并查询结果集,all-保留重复行
select stockname from table2



***insert***



insert into table_name (Stock_name,Stock_number) value ("xxx","xxxx")
value (select Stockname , Stocknumber from Stock_table2)---value为select语句



***update***



update table_name set Stockname = "xxx" [where Stockid = 3]
Stockname = default
Stockname = null
Stocknumber = Stockname + 4



***delete***



delete from table_name where Stockid = 3
truncate table_name ----------- 删除表中所有行,仍保持表的完整性
drop table table_name --------------- 完全删除表



***alter table*** --- 修改数据库表结构



alter table database.owner.table_name add column_name char(2) null .....
sp_help table_name ---- 显示表已有特征
create table table_name (name char(20), age smallint, lname varchar(30))
insert into table_name select ......... ----- 实现删除列的方法(创建新表)
alter table table_name drop constraint Stockname_default ---- 删除Stockname的default约束



***function(/*常用函数*/)***



----统计函数----
AVG --求平均值
COUNT --统计数目
MAX --求最大值
MIN --求最小值
SUM --求和



--AVG
use pangu
select avg(e_wage) as dept_avgWage
from employee
group by dept_id



--MAX
--求工资最高的员工姓名
use pangu
select e_name
from employee
where e_wage =
(select max(e_wage)
from employee)



--STDEV()
--STDEV()函数返回表达式中所有数据的标准差



--STDEVP()
--STDEVP()函数返回总体标准差



--VAR()
--VAR()函数返回表达式中所有值的统计变异数



--VARP()
--VARP()函数返回总体变异数



----算术函数----



/***三角函数***/
SIN(float_expression) --返回以弧度表示的角的正弦
COS(float_expression) --返回以弧度表示的角的余弦
TAN(float_expression) --返回以弧度表示的角的正切
COT(float_expression) --返回以弧度表示的角的余切
/***反三角函数***/
ASIN(float_expression) --返回正弦是FLOAT 值的以弧度表示的角
ACOS(float_expression) --返回余弦是FLOAT 值的以弧度表示的角
ATAN(float_expression) --返回正切是FLOAT 值的以弧度表示的角
ATAN2(float_expression1,float_expression2)
--返回正切是float_expression1 /float_expres-sion2的以弧度表示的角
DEGREES(numeric_expression)
--把弧度转换为角度返回与表达式相同的数据类型可为
--INTEGER/MONEY/REAL/FLOAT 类型
RADIANS(numeric_expression) --把角度转换为弧度返回与表达式相同的数据类型可为
--INTEGER/MONEY/REAL/FLOAT 类型
EXP(float_expression) --返回表达式的指数值
LOG(float_expression) --返回表达式的自然对数值
LOG10(float_expression)--返回表达式的以10 为底的对数值
SQRT(float_expression) --返回表达式的平方根
/***取近似值函数***/
CEILING(numeric_expression) --返回>=表达式的最小整数返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT 类型
FLOOR(numeric_expression) --返回<=表达式的最小整数返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT 类型
ROUND(numeric_expression) --返回以integer_expression 为精度的四舍五入值返回的数据
--类型与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型
ABS(numeric_expression) --返回表达式的绝对值返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT 类型
SIGN(numeric_expression) --测试参数的正负号返回0 零值1 正数或-1 负数返回的数据类型
--与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型
PI() --返回值为π 即3.1415926535897936
RAND([integer_expression]) --用任选的[integer_expression]做种子值得出0-1 间的随机浮点数




----字符串函数----
ASCII() --函数返回字符表达式最左端字符的ASCII 码值
CHAR() --函数用于将ASCII 码转换为字符
--如果没有输入0 ~ 255 之间的ASCII 码值CHAR 函数会返回一个NULL 值
LOWER() --函数把字符串全部转换为小写
UPPER() --函数把字符串全部转换为大写
STR() --函数把数值型数据转换为字符型数据
LTRIM() --函数把字符串头部的空格去掉
RTRIM() --函数把字符串尾部的空格去掉
LEFT(),RIGHT(),SUBSTRING() --函数返回部分字符串
CHARINDEX(),PATINDEX() --函数返回字符串中某个指定的子串出现的开始位置
SOUNDEX() --函数返回一个四位字符码
--SOUNDEX函数可用来查找声音相似的字符串但SOUNDEX函数对数字和汉字均只返回0 值
DIFFERENCE() --函数返回由SOUNDEX 函数返回的两个字符表达式的值的差异
--0 两个SOUNDEX 函数返回值的第一个字符不同
--1 两个SOUNDEX 函数返回值的第一个字符相同
--2 两个SOUNDEX 函数返回值的第一二个字符相同
--3 两个SOUNDEX 函数返回值的第一二三个字符相同
--4 两个SOUNDEX 函数返回值完全相同




QUOTENAME() --函数返回被特定字符括起来的字符串
/*select quotename('abc', '{') quotename('abc')
运行结果如下
----------------------------------{
{abc} [abc]*/



REPLICATE() --函数返回一个重复character_expression 指定次数的字符串
/*select replicate('abc', 3) replicate( 'abc', -2)
运行结果如下
----------- -----------
abcabcabc NULL*/



REVERSE() --函数将指定的字符串的字符排列顺序颠倒
REPLACE() --函数返回被替换了指定子串的字符串
/*select replace('abc123g', '123', 'def')
运行结果如下
----------- -----------
abcdefg*/



SPACE() --函数返回一个有指定长度的空白字符串
STUFF() --函数用另一子串替换字符串指定位置长度的子串




----数据类型转换函数----
CAST() 函数语法如下
CAST() (<expression> AS <data_ type>[ length ])
CONVERT() 函数语法如下
CONVERT() (<data_ type>[ length ], <expression> [, style])



select cast(100+99 as char) convert(varchar(12), getdate())
运行结果如下
------------------------------ ------------
199 Jan 15 2000



----日期函数----
DAY() --函数返回date_expression 中的日期值
MONTH() --函数返回date_expression 中的月份值
YEAR() --函数返回date_expression 中的年份值
DATEADD(<datepart> ,<number> ,<date>)
--函数返回指定日期date 加上指定的额外日期间隔number 产生的新日期
DATEDIFF(<datepart> ,<number> ,<date>)
--函数返回两个指定日期在datepart 方面的不同之处
DATENAME(<datepart> , <date>) --函数以字符串的形式返回日期的指定部分
DATEPART(<datepart> , <date>) --函数以整数值的形式返回日期的指定部分
GETDATE() --函数以DATETIME 的缺省格式返回系统当前的日期和时间



----系统函数----
APP_NAME() --函数返回当前执行的应用程序的名称
COALESCE() --函数返回众多表达式中第一个非NULL 表达式的值
COL_LENGTH(<'table_name'>, <'column_name'>) --函数返回表中指定字段的长度值
COL_NAME(<table_id>, <column_id>) --函数返回表中指定字段的名称即列名
DATALENGTH() --函数返回数据表达式的数据的实际长度
DB_ID(['database_name']) --函数返回数据库的编号
DB_NAME(database_id) --函数返回数据库的名称
HOST_ID() --函数返回服务器端计算机的名称
HOST_NAME() --函数返回服务器端计算机的名称
IDENTITY(<data_type>[, seed increment]) [AS column_name])
--IDENTITY() 函数只在SELECT INTO 语句中使用用于插入一个identity column列到新表中
/*select identity(int, 1, 1) as column_name
into newtable
from oldtable*/
ISDATE() --函数判断所给定的表达式是否为合理日期
ISNULL(<check_expression>, <replacement_value>) --函数将表达式中的NULL 值用指定值替换
ISNUMERIC() --函数判断所给定的表达式是否为合理的数值
NEWID() --函数返回一个UNIQUEIDENTIFIER 类型的数值
NULLIF(<expression1>, <expression2>)
--NULLIF 函数在expression1 与expression2 相等时返回NULL 值若不相等时则返回expression1 的值







sql中的保留字



action add aggregate all
alter after and as
asc avg avg_row_length auto_increment
between bigint bit binary
blob bool both by
cascade case char character
change check checksum column
columns comment constraint create
cross current_date current_time current_timestamp
data database databases date
datetime day day_hour day_minute
day_second dayofmonth dayofweek dayofyear
dec decimal default delayed
delay_key_write delete desc describe


>distinct distinctrow double drop
end else escape escaped
enclosed enum explain exists
fields file first float
float4 float8 flush foreign
from for full function
global grant grants group
having heap high_priority hour
hour_minute hour_second hosts identified
ignore in index infile
inner insert insert_id int
integer interval int1 int2
int3 int4 int8 into
if is isam join
key keys kill last_insert_id
leading left length like
lines limit load local
lock logs long longblob
longtext low_priority max max_rows
match mediumblob mediumtext mediumint
middleint min_rows minute minute_second
modify month monthname myisam
natural numeric no not
null on optimize option
optionally or order outer
outfile pack_keys partial password
precision primary procedure process
processlist privileges read real
references reload regexp rename
replace restrict returns revoke
rlike row rows second
select set show shutdown
smallint soname sql_big_tables sql_big_selects
sql_low_priority_updates sql_log_off sql_log_update sql_select_limit
sql_small_result sql_big_result sql_warnings straight_join
starting status string table
tables temporary terminated text
then time timestamp tinyblob
tinytext tinyint trailing to
type use using unique
unlock unsigned update usage
values varchar variables varying
varbinary with write when
where year year_month zerofill
posted @ 2008-04-28 22:38 caihaibo 阅读(120) | 评论 (0)编辑 收藏
myeclipse6.0注册码大放送

Subscriber: yeming
Subscription Code: lLR7ZL-655444-54516456213945437
找了半天才找了个网上不太那么显眼的,我用过可是使用,不过注意注册时千万别上网否则你就重装吧!

正常:

Subscriber:Administrator
Subscription Code:NLR8ZC-855550-6552685393219112

可以用,我试过了. 

6.0的:
Subscriber: www.1cn.biz
Subscriber Code: jLR8ZC-655355-5450765457039125
或者
Subscriber: www.1cn.biz
Subscriber Code: jLR7ZL-655355-5450755330522962 

MyEclipse 6.0.1 注册码

Subscriber: administrator
Subscription Code: nLR7ZL-655342-54657656405281154注册后:

Subscriber: administrator
Product ID: E2MY (MyEclipse Standard Subscription)
License version: 1.0
Full Maintenance Included
Subscription expiration date (YYYYMMDD): 20091021
Number of licenses: 897

posted @ 2008-04-28 21:54 caihaibo 阅读(217) | 评论 (0)编辑 收藏
DynaBean是BeanUtils里的宝贝之一。有了动态Bean,就不用写那么多VO出来了,特别那些只是为了和View交互而存在的bean,i hate Form Bean。
     DynaBean的用法很简单,特别是有了LazyBynaBean之后.
         DynaBean car = new LazyDynaBean();
         car.set("carNo",1);
         car.set("owner","张三");

         out.print(car.get("carNo"));

 

         看着像一个map,只不过多了反射的功能,所以支持那些使用反射来获取属性的场合。

         但是因为他没有car.getCarNo()这样的函数,只能用car.get("carNo"),所以也就不支持JSTL里面<c: out value="{car.carNo}">这样的语法,因为JSTL是默认转回car.getCarNo()的。
而且几经讨论,JSTL不支持 car.userFunction(),理由是不希望代码里有java代码:(

         因此,还是写<%=car.get("carNo")>好了,如果是陷在JSTL的一个循环结构里,就要用从pageContext里面把bean拿出来,
        又或者自己写的tag,幸亏也很简单,用BeanUtils.getProperty(bean,property)函数就可以了,
        又或者,用Velocity和Freemarker。

       最后,如果car.set("carNo",null),会得到一个莫名其妙的Object对象,如果要使它为Null,需要先定义他的类型。
       因此,对于可能为Null的列,需要用LazyClass定义类型,幸亏也很Lazy, 不可能为Null的值可以不管。

      LazyDynaClass lc = new LazyDynaClass();
      lc.add("owner",String.class); // 指定null converter String
      DynaBean car = new LazyDynaBean(lc);
      car.set("carNo",1);
      car.set("owner",null);


posted @ 2008-04-24 13:15 caihaibo 阅读(169) | 评论 (0)编辑 收藏
PO是持久化对象,它只是将物理数据实体的一种对象表示,为什么需要它?因为它可以简化我们对于物理实体的了解和耦合,简单地讲,可以简化对象的数据转换为物理数据的编程。VO是什么?它是值对象,准确地讲,它是业务对象,是生活在业务层的,是业务逻辑需要了解,需要使用的,再简单地讲,它是概念模型转换得到的。FormBean又是什么?它只是HTML表单的封装,是为了在控制层弱化request中存储数据的作用,将request的get方法转变为对象的存取值。
理清了上述概念,好,我们就开始讨论,为什么需要它们,为什么不需要它们。首先说PO和VO吧,它们的关系应该是相互独立的,一个VO可以只是PO的部分,也可以是多个PO构成,同样也可以等同于一个PO(当然我是指他们的属性)。正因为这样,PO独立出来,数据持久层也就独立出来了,它不会受到任何业务的干涉。又正因为这样,业务逻辑层也独立开来,它不会受到数据持久层的影响,业务层关心的只是业务逻辑的处理,至于怎么存怎么读交给别人吧!不过,另外一点,如果我们没有使用数据持久层,或者说没有使用hibernate,那么PO和VO也可以是同一个东西,虽然这并不好。其次,让我们看看FormBean和VO,如果简单地讲,我们是可以不需要FormBean的,它只是struts带来的一部分,而VO是无论如何不能舍弃的。如果让FormBean直接到业务层(它本来应该生活在控制层),那么会带来什么?View和Model就出现了强耦合,如果想改一下view的表示,整个业务逻辑都得改,恐怖的事情啊!
这些对象概念的出现其实就是体现了一种层的思维,也是体现了一种框架的思维,在层与层之间我们需要什么?我们应该怎么通信,其实大家认真地用笔画上几个图就可以知道了。做web应用尤其是企业应用,切忌像楼上某些朋友说的,一个东东从头到尾,那是非常低劣和错误的设计。我们不要单纯地就为了某些对象去争论什么,它们更多的只是思维。这样的思维给我们带来了哪些好处,不言自明,当然,我们也不得不否认,我们因此失去了某些东西,比如局部的性能或者繁琐的代码和调用过程,只是自己衡量一下,它是否值得。
posted @ 2008-04-24 12:50 caihaibo 阅读(131) | 评论 (0)编辑 收藏
我在action中使用PropertyUtils.copyProperties方法将一个formbean复制给一个vo,但是formbean中的value值的类型是String,所以我的vo的value的类型也必须是String,但是我的po和数据库对应的字段不一定的String,我怎么从一个formbean将值复制给一个vo(po),并和相应的hbm.xml配合和数据库建立映射关系。比如我的数据库的某各字段weight是float类型,我如何写我的formbean,vo,po,hbm.htm,谢谢!
推荐链接
    时间:2004-07-04
    不好意思,我用的是hibernet.
    请登录后投票
    时间:2004-07-04
    PropertyUtils.copyProperties并不要求属性的类型必须一致,它会自动进行转换,当然转换不了的情况下会抛错。
    请登录后投票
    时间:2004-07-04
    posted @ 2008-04-24 12:07 caihaibo 阅读(191) | 评论 (0)编辑 收藏
         摘要: PO即 Persistence Object   VO即 Value Object  VO和PO的主要区别在于:   VO是独立的Java Object。   PO是由Hibernate纳入其实体容器(Entity Map)的对象,它代表了与数据库中某条记录对应的Hibernate实体,PO的变化在事务提交时将反应到实际数据库中。  实际上,这个VO被用作Data Transfer Ob...  阅读全文
    posted @ 2008-04-24 12:04 caihaibo 阅读(2990) | 评论 (0)编辑 收藏
         摘要: ajax巨好用,4级级联菜单的解决 为解决省、市、区、区域4级级联菜单,在网上搜索了大量的级联菜单解决方案,也请教过不少朋友,要么过于复杂,要么过于占内存,未果。 在建议下,悉心读《ajax基础教程》4余遍,方有与ajax相识恨晚之感,唯一的感慨就是好用好用绝对好用。 现在把已经可以正常运行的例子的核心代码分享: 客户端ajax代码如下: Code highlighting ...  阅读全文
    posted @ 2008-04-23 20:25 caihaibo 阅读(212) | 评论 (0)编辑 收藏
    Javascript & DHTML 实例编程(教程),基础篇(二)DOM基础和基本API

    一、什么是DOM?
    什么叫DOM,DOM是文档对象模型(Document Object Model,是基于浏览器编程(在本教程中,可以说就是DHTML编程)的一套API接口,W3C出台的推荐标准,每个浏览器都有一些细微的差别,其中以Mozilla的浏览器最与标准接近。单纯的Javascript要结合DOM才能做DHTML编程,才能做出漂亮的效果、应用于WEB。这点几乎与其它的语言无异,正如C/C++需要库支持是一样的道理。否则就是单纯的在语法上做研究了。因此,必须要对DOM有一定的认识,才能把Javascript应用于WEB,或你的RIA应用当中,因为DHTML本质上就是操作DOM树。
    以后的编程当中,希望你能够把DHTML.chm这本手册也拿上,如果你需要兼容gecko,把gecko的DOM手册也带上。因为API太多,想不起来的接口还可以查这本手册。

    如果你要测试浏览器是否是支持DOM的,简单的一句就可以判断
    <script>
    var isSupportDOM = !!document.getElementById; //两个取反,这已经在上节中说过了,意思是强制转型
    alert("你的浏览器 " +(isSupportDOM?"":"不")+ "支持 DOM!");
    </script>

    二、DOM树
    要注意:DOM树的根统一为文档根—document,DOM既然是树状结构,那么他们自然有如下的几种关系:

    根结点(document)
      |
      父结点(parentNode)
        |
        子结点(childNodes)
            |          |
          兄弟结点  兄弟结点
          (sibling)  (sibling)

    例子:

    假设网页的HTML如下
    <html>
      <head>
        <title>never-online's website</title>
      </head>
      <body>
        <div>tutorial of DHTML and javascript programming</div>
      </body>
    </html>
    我们参照树的概念,画出该HTML文档结构的DOM树:

               html
              |      |
          body       head
          |            |
        div          title
        |                |
      文本              文本

    从上面的图示可以看出
    html有两个子结点,而html就是这两个子节点的父结点

    head有节点title,title下有一个文本节点

    doby下有节点div,div下有一个文本节点

    三、操作DOM树
    开篇已经说过,DHTML本质就是操作DOM树。如何操作它呢?
    假设我要改变上面HTML文档中div结点的文本,如何做?[code]<html>
      <head>
        <title>never-online's website</title>
        <script>
        function changedivText (strText) {
          var nodeRoot = document; //这个是根结点
          var nodeHTML = nodeRoot.childNodes[0]; //这个是html结点
          var nodeBody = nodeHTML.childNodes[1]; //body结点
          var nodeDiv = nodeBody.childNodes[0]; //DIV结点
          var nodeText = nodeDiv.childNodes[0];//文本结点'
          nodeText.data = strText; //文本节点有data这个属性,因此我们可以改变这个属性,也就成功的操作了DOM树中的一个结点了
        }
        </script>
      </head>
      <body>
        <div>tutorial of DHTML and javascript programming</div>
        <input onclick="changedivText('change?')" type="button" value="change"/>
      </body>
    </html>

    从上面的示例可以看出,我们可以用上面的这种方法操作DOM树上的任一节点。(注:1. 跨域除外,跨域通常是在操作frame上,简单的说,就是两个frame不属于同一域名。2.上面的操作为了演示,采用的方法是从根结点一直到文本结点的遍历,在DOM方法上,有更简洁的方法,这些以后会有更多示例加以说明,下文中也会有介绍)

    三、DOM节点。
    细心些的朋友也许发现了,在上面写的HTML代码时用<>与</>包函起来的就是一个结点,事实上是这样的吗?答案是否定的。下面就是说说节点类型,否则在有的时候是会犯错误的。比如,你把上面的代码放到Mozilla firefox的浏览器里运行一下,就会知道了。
    DOM中的结点类型比较多,这里写一些在HTML文档中(注:XML也是DOM树结构)常见的几种结点类型。

    1、DOCUMENT_NODE
    (document)文档根结点类型,该枚举型的值是9.

    2、ELEMENT_NODE
    (element)元素结点类型,该枚举型的值是1。上文中的html, body, div这些结点都是属于该类型。

    3、TEXT_NODE
    (text)文本结点类型,该枚举型的值是3。上文中的文本,如:tutorial of DHTML and javascript programming就是属于该类型。
    (注:一个空格也就可能是一个文本结点)

    通常更需要注意的是文本结点,有可能一个回车,一个空格都是文本结点。这一点以后会碰到,当然,我们也有办法处理,这里先不要急,以后也会说到的。

    四、DOM常用的API

    这些常用的API是要记下来的,当然在非IE的浏览器里也会有效,是符合w3c的。这些API在以后的编程中会常常用到。正如每个编程平台所提供的API一样,常用必须记下来,节省时间从而提高编程效率。只写几个最常用的,其它的API会在以后的示例中写出。由浅而深,从易到难嘛。

    1、获取ELEMENT_NODE,元素节点
      1)、方法:document.getElementById(元素的Id),返回值为元素的节点引用。可以假想一下这个API的原理:象我们上面所做的是遍历每个节点(从根到我们所需结点),这个API,也可以想成是从根遍历,查询每个结点(空白结点和空结点除外),并获取该结点的id是否为指定的ID,如果是的话,就返回这个结点(注:在JS中,数组和对象是引用类型),如果没有就返回空。我们可以写写这个代码,帮助我们理解document.getElementById。下面是一个简单遍历BODY中元素的示例。
    <html>
      <head>
        <title>never-online's website</title>
        <script>
        function myGetElementById (id) {
          var nodeRoot = document; //这个是根结点
          var nodeHTML = nodeRoot.childNodes[0]; //这个是html结点
          var nodeBody = nodeHTML.childNodes[1]; //body结点
          var bodyChild = nodeBody.childNodes; //body的孩子
          for (var i=0; i<bodyChild.length; i++) { //简单的遍历(指body的孩子下的深度为1)
            if (bodyChild[i].id==id) return bodyChild[i];
          };
          return null;
        }
        function TestGetElementById (id) {
          var node = myGetElementById(id);
          if (node!=null) {
            alert("找到结点 "+id+"!");
            alert(node.childNodes[0].data);
          } else {
            alert("没有找到结点 "+id+".");
          }
        }
        </script>
      </head>
      <body>
        <div id="aTestNode"></div>
        <div id="textNode">tutorial of DHTML and javascript programming</div>
        <input onclick="TestGetElementById('textNode')" type="button" value="change"/>
      </body>
    </html>

      2)、属性:object.innerHTML,返回值:一个节点内的HTML值。该属性为可写属性。它虽然不是获取结点,但经常与获取结点相结合,所以我把它放在获取结点这一类,它的属性就类似于是纯文本节点属性中的data。以document.getElementById和object.innerHTML这两个API为例,我们就可以把上面所写的代码简化一下了,示例如下:
    <html>
      <head>
        <title>never-online's website</title>
        <script>
        function changedivText (strText) {
          var node = document.getElementById("textNode");
          node.innerHTML = strText;
        }
        </script>
      </head>
      <body>
        <div id="textNode">tutorial of DHTML and javascript programming</div>
        <input onclick="changedivText('change?')" type="button" value="change"/>
      </body>
    </html>

      3)、方法:object.getElementsByTagName(标签的名字),返回一个集合,该集合的把有元素都是有指定标签的元素。访问集合里的元素,可以用下标来访问。语法里的object,是指document(根)或者是一个ELEMENT_NODE。这个的原理示例我就不写了,可以作为一个作业,大家可以写写。这里写一些具体应用。如上例,我们还可以这样写。
    <html>
      <head>
        <title>never-online's website</title>
        <script>
        function changedivText (strText) {
          var node = document.getElementsByTagName("DIV");
          node[0].innerHTML = strText;
        }
        </script>
      </head>
      <body>
        <div>tutorial of DHTML and javascript programming</div>
        <input onclick="changedivText('change?')" type="button" value="change"/>
      </body>
    </html>
    再取一个例子,注意,BODY下的结点深度为2。
    <html>
      <head>
        <title>never-online's website</title>
        <script>
        function changedivText (strText) {
          var node = document.getElementById("nodeTest");
          var myNode = node.getElementsByTagName("DIV");
          myNode[0].innerHTML = strText;
        }
        </script>
      </head>
      <body>
        <div id="nodeTest">
          <div>tutorial of DHTML and javascript programming</div>
          <input onclick="changedivText('change?')" type="button" value="change"/>
        </div>
      </body>
    </html>

    二、动态创建与插入结点

      1)、创建结点对象。document.createElement(tagname),tagname指的是一个标签,比如一个DIV,就是document.createElement("DIV"),它返回的是这个结点的引用。

      2)、在body的尾部插入结点用document.body.appendChild(object),为了容易理解,下面这个示例,我用了IE专有的属性object.outerHTML,得到一个该元素的HTML标签内容(包括自身),这样会更容易看到效果。
    <html>
      <head>
        <title>never-online's website</title>
        <script>
        function insertNode (strText) {
          alert("插入元素前的body HTML:\n" +document.body.outerHTML);
          var node = document.createElement("DIV");
          node.innerHTML = strText;
          document.body.appendChild(node);
          alert("插入元素后的body HTML:\n" +document.body.outerHTML);
        }
        </script>
      </head>
      <body>
        <div>tutorial of DHTML and javascript programming</div>
        <input onclick="insertNode('change?')" type="button" value="change"/>
      </body>
    </html>

      3)、在元素处插入结点。object.insertBefore(oNewNode [, oChildNode]),oNewNode为一个我们创建的结点,oChildNode是可选的,为object下的一个子节点。同样的,为了看到效果,我也用了outerHTML。示例
    <html>
      <head>
        <title>never-online's website</title>
        <script>
        function insertNode (strText) {
          alert("插入元素前的body HTML:\n" +document.body.outerHTML);
          var node = document.createElement("DIV");
          var myNode = document.getElementById("textNode");
          node.innerHTML = strText;
          document.body.insertBefore(node,myNode);
          alert("插入元素后的body HTML:\n" +document.body.outerHTML);
        }
        </script>
      </head>
      <body>
        <div id="textNode">tutorial of DHTML and javascript programming</div>
        <input onclick="insertNode('change?')" type="button" value="change"/>
      </body>
    </html>

    三、移除结点。
      1) object.parentNode.removeChild(oChildNode),这个就是语法,下面看示例。
    <html>
      <head>
        <title>never-online's website</title>
        <script>
        function insertNode (strText) {
          alert("插入元素前的body HTML:\n" +document.body.outerHTML);
          var node = document.createElement("DIV");
          var myNode = document.getElementById("textNode");
          node.innerHTML = strText;
          document.body.insertBefore(node,myNode);
          alert("插入元素后的body HTML:\n" +document.body.outerHTML);
        }
        function removeCreateNode() {
          alert("移除元素前的body HTML:\n" +document.body.outerHTML);
          var node = document.getElementById("textNode");
          node.parentNode.removeChild(node);
          alert("移除元素前的body HTML:\n" +document.body.outerHTML);
        }
        </script>
      </head>
      <body>
        <div id="textNode">tutorial of DHTML and javascript programming</div>
        <input onclick="insertNode('change?')" type="button" value="insert"/>
        <input onclick="removeCreateNode()" type="button" value="remove"/>
      </body>
    </html>
    这一节就先写到这里,下一节我们就可以用这几个简单的API做许多事情了,几个API就可以写出很多效果。:D
    posted @ 2008-04-23 20:18 caihaibo 阅读(289) | 评论 (1)编辑 收藏

    文件名和路径约定
       在unix及其上运行时,ant将路径dir;dir\\subdir(注意转义符"\")正确的解释为dir:dir/subdir
       在同一个值类型中,分隔符的使用必须保持一致  ;属于windows路径分隔符, \\属于unix的目录分隔符。
       ant并不关心你所使用的平台。
       ant不处理跨平台的驱动器盘符,在ant路径元素中使用驱动器盘符将限制构建文件在windows环境下的使用。

    xml注意事项
              第一行为xml声明。如果有,必须出现在xml文件的第一行;在其之前不允许出现空行。实际上,即便在<?xml之前只有一个空格
        也会导致xml解析程序失败。  
              xml对于大小写、引号以及正确的标签语法很挑剔。如果其中任何一项不正确,ant就会失败,这是因为其底层的xml解析程序会失败。

    构建文件描述
        <project>元素为这个工程建立工作目录“.”。这就是包含此构建文件的目录。
        特性定义允许我们避免在构建文件中将目录名硬编码。这些路径是相对于<project>元素所指定的基目录。
        在目标中存在任务,这些任务完成构建中的具体工作。ant1.4.1内置有100多个核心的和可选的任务。
        包含有discription属性的为主目标,不包含的为子目标。

    软件下载
       .tar.gz文件(面向Unix用户) .zip文件(面向windows用户)

    posted @ 2008-04-22 16:18 caihaibo 阅读(376) | 评论 (0)编辑 收藏