??xml version="1.0" encoding="utf-8" standalone="yes"?>国产成人精品日本亚洲直接,久久久久亚洲精品男人的天堂 ,亚洲一卡二卡三卡http://www.tkk7.com/liulu/Open & Open <a title="Free Web Counter"><font color="red"><script src="http://fastwebcounter.com/secure.php?s=www.tkk7.com/liulu"></script>hits</font></a>zh-cnSat, 10 May 2025 15:54:39 GMTSat, 10 May 2025 15:54:39 GMT60HSQL 学习(fn)W记1(zz)http://www.tkk7.com/liulu/archive/2007/03/26/106463.html刘璐刘璐Mon, 26 Mar 2007 09:18:00 GMThttp://www.tkk7.com/liulu/archive/2007/03/26/106463.htmlhttp://www.tkk7.com/liulu/comments/106463.htmlhttp://www.tkk7.com/liulu/archive/2007/03/26/106463.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/106463.htmlhttp://www.tkk7.com/liulu/services/trackbacks/106463.html http://hi.baidu.com/wannachan/blog/item/8e82bf86fc5d663f67096ef1.html

HSQL 学习(fn)W记

1.     hsql 学习(fn)
1.1.     学习(fn)目的
本文档是针对hSQL 数据库方面的基础学习(fn)Qؓ(f)?jin)ə目l成员能够达C用hSQL 数据库的目的?br />1.2.     培训对象
开发h?br />1.3.     常用词及(qing)W号说明
常用词:(x)
hsqlQ一U免费的跨^台的数据库系l?br />E:\hsqldbQ表C是在dos 命o(h)H口下面
1.4.     参考信?br />doc\guide\guide.pdf

2.     HSQL
2.1.     HSQL q行工具
java -cp ../lib/hsqldb.jar org.hsqldb.util.DatabaseManager
注意hsqldb.jar 文g的文件\?最好能攑ֈclasspath 里面,或者放到当前\径下.
java -cp hsqldb.jar org.hsqldb.util.DatabaseManager

2.2.     q行数据?br />启动方式: Server Modes and
In-Process Mode (also called Standalone Mode).

一个test 数据库会(x)包含如下文g:
?test.properties
?test.script
?test.log
?test.data
?test.backup
test.properties 文g包含关于数据库的一般设|?
test.script   文g包含表和其它数据?插入没有~存表的数据.
test.log 文g包含当前数据库的变更.
test.data 文g包含~存表的数据
test.backup 文g是最q持久化状态的表的数据文g的压~备份文?br />所有以上这个文仉是必要的,不能被删?如果数据库没有缓存表,test.data 和test.backup 文g不?x)存?另外,除了(jin)以上文gHSQLDB 数据库可以链接到M文本文g,比如cvs 文g.

当操作test 数据库的时? test.log 用于保存数据的变? 当正常SHUTDOWN,q个文g被删除. 否则(不是正常shutdown),q个文g用于再ơ启动的时?重做q些变更.test.lck 文g也用于记录打开的数据库的事? 正常SHUTDOWN,文g也被删除.在一些情况下,test.data.old 文g?x)被创?q删除以前的.






2.3.     Server Mode
java -cp ../lib/hsqldb.jar org.hsqldb.Server -database.0 file:mydb -dbname.0 xdb

命o(h)行方?


启动数据,数据库文件mydb,数据库名Uxdb

也可以在 server.properties 文g中定义启动的数据?最?0?br />例如: server.properties:
server.database.0=file:E:/hsqldb/data/mydb
server.dbname.0=xdb

server.database.1=file:E:/hsqldb/data/testdb
server.dbname.1=testdb

server.database.2=mem:adatabase
server.dbname.2=quickdb
启动命o(h): java -cp ../lib/hsqldb.jar org.hsqldb.Server
q行l果如下



java 试E序:
package test;
import junit.framework.TestCase;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestConnect extends TestCase {
     Connection connection;
     protected void setUp()
     {        
         try {
             Class.forName("org.hsqldb.jdbcDriver" );
             connection = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/xdb","sa","");
            
            
         } catch (Exception e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
     }
     public void testselect()
     {
         Statement stmt=null;
         ResultSet rs=null;
         try {
             stmt = connection.createStatement();
             String sql ="select * from test";
             rs=stmt.executeQuery( sql);
             while(rs.next() )
             {
                 System.out.println("id="+rs.getString("id"));
                 System.out.println("name="+rs.getString("name"));
             }
            
         } catch (SQLException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
         finally
         {
             try {
                 rs.close() ;
                 stmt.close();
             } catch (SQLException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }            
         }    
        
     }
     protected void tearDown()
     {
         try {
             connection.close();
         } catch (Exception e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
     }

}
以上在eclipse 中测试通过.

2.4.     In-Process (Standalone) Mode
不需要启动server
connection = DriverManager.getConnection("jdbc:hsqldb:file:E:/hsqldb/data/mydb","sa","");
q样可以连接数据库?br />只能在一个jvm 中用,不能在多个jvm 中用?br />q种模式是在相同的jvm 下作Z的应用程序的一部分Q运行数据库引擎。对大多数应用程序,q种模式q行?x)相当快Q作为数据,不需要{换和|络传输?br />
主要的缺点就是不可能从外面的应用E序讉K到默认数据库Q因此当你的应用q行时候,你不能通过别的工具(g)查数据库内容。在1.8.0 版本?你可以在相同jvm 中的U程中运行数据库初始化,q提供外面访问你的进E内数据库?br />     推荐在开发应用中使用q种方式?br />q接Ԍ(x)
Windows: DriverManager.getConnection("jdbc:hsqldb:file:E:/hsqldb/data/mydb","sa","");
Unix: DriverManager.getConnection("jdbc:hsqldb:file:/opt/db/testdb","sa","");

2.5.     Memory-Only Databases
当随卌问内存,数据库不固定Ӟ可以采用内存的方式运行数据库Q由于没有数据写到硬盘上Q这U方式用在应用数据和applets 和特D应用的内部q程中用,URLQ?br />
Connection c = DriverManager.getConnection("jdbc:hsqldb:mem:aname", "sa", "");
2.6.     Using Multiple Databases in One JVM
2.7.     Different Types of Tables
HSQLDB 支持 TEMP 表和三种cd的持久表QMEMORY ? CACHED 表,TEXT表)(j)

当?CREATE TABLE   命o(h)ӞMemory 表时默认cdQ它们的数据整体保存在内存当中,但是M改变它们的结构或者内容,它们?x)被写?lt;dbname>.script 文g中。这个脚本文件在数据库下一ơ打开的时候被对出Q内存表重新被创建内容,根temp 表不同,内存表时持久化的?br />
CACHED 表通过CREATE CACHED TABLE 命o(h)建立. 只有部分的它们的数据或者烦(ch)引被保存在内存中Q允许大表占用几癑օ的内存空间。例外一个优点,在数据库引擎中,启动大量数据的缓存表需要花费少量的旉Q缺Ҏ(gu)减慢?jin)运行和使用Hsqldb 的速度。表相对的时候,不要使用cache 表,在小表中使用内存数据库?br />
从版?1.7.0 以后Q支持text 表,使用 CSV (Comma Separated Value)   或者其它分隔符文本文g作ؓ(f)它们的数据源。你可以Ҏ(gu)指定一个存在的CSV 文gQ例如从其它的数据或者程序中导出文gQ作为TXT 表的数据源?同时,你可以指定一个空文gQ通过数据库引擎填充数据。TEXT 表将比cache 表更加效率高。Text 表可以指向不同的数据文g?br />
* memory-only databases 数据库只支持memory 表和cache 表,不支持text 表?br />2.8.     U束和烦(ch)?br />HSQLDB 支持 PRIMARY KEY, NOT NULL, UNIQUE, CHECK and FOREIGN KEY U束.





3.     sql 命o(h)
3.1.     sql 支持
select top 1 * from test;
select limit 0 2 * from test;
DROP TABLE test IF EXISTS;
3.2.     Constraints and Indexes
dU束QPRIMARY KEY
唯一U束Q?br />唯一索引Q?br />外健Q?br />CREATE TABLE child(c1 INTEGER, c2 VARCHAR, FOREIGN KEY (c1, c2) REFERENCES parent(p1, p2));

3.3.     索引和查询速度
索引提高查询速度Q比提高排序速度?br />d和唯一所列自动创建烦(ch)引,否则需要自己创建CREATE INDEX command?br />索引Q?唯一索引和非唯一索引
多列的烦(ch)引,如果只是使用后面的,不用第一个,不?x)条查询速度?br />
(TB is a very large table with only a few rows where TB.COL3 = 4)
SELECT * FROM TA JOIN TB ON TA.COL1 = TB.COL2 AND TB.COL3 = 4;
SELECT * FROM TB JOIN TA ON TA.COL1 = TB.COL2 AND TB.COL3 = 4;(faster)

原因?TB.COL3 可以被快速的估计,如果TB 表放到前?index on TB.COL3):
一般规则是把羃?yu)条件的列的表放在前?br />
3.4.     使用where q是join
使用 WHERE   条g链接表可能会(x)降低q行速度.
下面的例子将?x)比较?即使用?jin)?ch)?
     SELECT ... FROM TA, TB, TC WHERE TC.COL3 = TA.COL1 AND TC.COL3=TB.COL2 AND TC.COL4 = 1
q个查询隐含TA.COL1 = TB.COL2 ,但是没有直接讑֮q个条g.如果 TA ?TB 每个表都包含100 条记?10000 l合和 TC 兌,用于TCq个列的条g,管有烦(ch)引在q个列上.使用JOIN 关键? 在组合TC 之前,TA.COL1 = TB.COL2 条g直接q羃?yu)组?TA ?TB 的行? 在运行大数据量的表的l果?会(x)很快:
     SELECT ... FROM TA JOIN TB ON TA.COL1 = TB.COL2 JOIN TC ON TB.COL2 = TC.COL3 WHERE TC.COL4 = 1
q个查询可以提高一大步,如果改变表的序, 所?TC.COL1 = 1 最先?q样更小的集合将l合在一?
     SELECT ... FROM TC JOIN TB ON TC.COL3 = TB.COL2 JOIN TA ON TC.COL3 = TA.COL1 WHERE TC.COL4 = 1
以上例子,数据引擎自动应用于TC.COL4 = 1 l合的集合于其它表兌. Indexes TC.COL4, TB.COL2   TA.COL1 都将使用索引,提高查询速度.
3.5.     Subqueries and Joins
使用join 和调整表的顺序提高效?
例如:, W二个查询的速度更快一?TA.COL1 和TB.COL3都有索引):
Example 2.2. Query comparison
     SELECT ... FROM TA WHERE TA.COL1 = (SELECT MAX(TB.COL2) FROM TB WHERE TB.COL3 = 4)

     SELECT ... FROM (SELECT MAX(TB.COL2) C1 FROM TB WHERE TB.COL3 = 4) T2 JOIN TA ON TA.COL1 = T2.C1
W二个查询将 MAX(TB.COL2) 与一个单记录表相兌. q用TA.COL1索引,q将变得非常? W一个查询是?TA 表中的每一条记录不断地与MAX(TB.COL2)匚w.
3.6.     数据cd
TINYINT, SMALLINT, INTEGER, BIGINT, NUMERIC and DECIMAL (without a decimal point) are supported integral types and map to byte, short, int, long and BigDecimal in Java.

Integral Types:
TINYINT, SMALLINT, INTEGER, BIGINT, NUMERIC and DECIMAL
Other Numeric Types:
REAL, FLOAT or DOUBLE
Bit and Boolean Types:
     BOOLEAN: UNDEFINED,TRUE,FALSE  
NULL values are treated as undefined.
Storage and Handling of Java Objects
Sequences and Identity

Identity Auto-Increment Columns:
The next IDENTITY value to be used can be set with the
ALTER TABLE ALTER COLUMN <column name> RESTART WITH <new value>;
Sequences:
SELECT NEXT VALUE FOR mysequence, col1, col2 FROM mytable WHERE ...
    
3.7.     事务问题:
SET PROPERTY "sql.tx_no_multi_rewrite" TRUE

4.     Connections
通用驱动jdbc:hsqldb:   下列协议标识(mem: file: res: hsql: http: hsqls: https:)
Table 4.1. Hsqldb URL Components
Driver and Protocol     Host and Port     Database
jdbc:hsqldb:mem:
     not available     accounts

jdbc:hsqldb:mem:.
jdbc:hsqldb:file:
     not available     mydb
/opt/db/accounts
C:/data/mydb

数据库\?
jdbc:hsqldb:res:
     not available     /adirectory/dbname

jars files are accessed in Java programs. The /adirectory above stands for a directory in one of the jars.
jdbc:hsqldb:hsql:
jdbc:hsqldb:hsqls:
jdbc:hsqldb:http:
jdbc:hsqldb:https:
     //localhost
//192.0.0.10:9500
//dbserver.somedomain.com
     /an_alias
/enrollments
/quickdb

别名在server.properties or webserver.properties文g中指?br />     database.0=file:/opt/db/accounts
     dbname.0=an_alias

     database.1=file:/opt/db/mydb
     dbname.1=enrollments

     database.2=mem:adatabase
     dbname.2=quickdb
In the example below, the database files lists.* in the /home/dbmaster/ directory are associated with the empty alias:
     database.3=/home/dbmaster/lists
     dbname.3=
4.1.     Connection properties
Connection properties are specified either by establishing the connection via the:
     DriverManager.getConnection (String url, Properties info);
method call, or the property can be appended to the full Connection URL.
Table 4.2. Connection Properties
get_column_name     true     column name in ResultSet
This property is used for compatibility with other JDBC driver implementations. When true (the default), ResultSet.getColumnName(int c) returns the underlying column name
When false, the above method returns the same value as ResultSet.getColumnLabel(int column) Example below:
     jdbc:hsqldb:hsql://localhost/enrollments;get_column_name=false
                    
When a ResultSet is used inside a user-defined stored procedure, the default, true, is always used for this property.
ifexists     false     connect only if database already exists
Has an effect only with mem: and file: database. When true, will not create a new database if one does not already exist for the URL.
When false (the default), a new mem: or file: database will be created if it does not exist.
Setting the property to true is useful when troubleshooting as no database is created if the URL is malformed. Example below:
     jdbc:hsqldb:file:enrollments;ifexists=true
shutdown     false     shut down the database when the last connection is closed
This mimics the behaviour of 1.7.1 and older versions. When the last connection to a database is closed, the database is automatically shut down. The property takes effect only when the first connection is made to the database. This means the connection that opens the database. It has no effect if used with subsequent, simultaneous connections.
This command has two uses. One is for test suites, where connections to the database are made from one JVM context, immediately followed by another context. The other use is for applications where it is not easy to configure the environment to shutdown the database. Examples reported by users include web application servers, where the closing of the last connection conisides with the web app being shut down.


4.2.     Properties Files
大小写敏?(e.g. server.silent=FALSE will have no effect, but server.silent=false will work).
属性文件和讑֮存储如下 :
Table 4.3. Hsqldb Server Properties Files
File Name     Location     Function
server.properties     the directory where the command to run the Server class is issued     settings for running HSQLDB as a database server communicating with the HSQL protocol
webserver.properties     the directory where the command to run the WebServer class is issued     settings for running HSQLDB as a database server communicating with the HTTP protocol
<dbname>.properties     the directory where all the files for a database are located     settings for each particular database
Properties files for running the servers are not created automatically. You should create your own files that contain server.property=value pairs for each property.
4.2.1.     Server and Web Server Properties
server.properties and webserver.properties 文g支持如下讑֮:
Table 4.4. Property File Properties
Value     Default     Description
server.database.0     test     the path and file name of the first database file to use
server.dbname.0     ""     lowercase server alias for the first database file
server.urlid.0     NONE     SqlTool urlid used by UNIX init script. (This property is not used if your are running Server/Webserver on a platform other than UNIX, or of you are not using our UNIX init script).
server.silent     true     no extensive messages displayed on console
server.trace     false     JDBC trace messages displayed on console
In 1.8.0, 每个服务器支持同时启?0个不同的数据? The server.database.0 property defines the filename / path whereas the server.dbname.0 defines the lowercase alias used by clients to connect to that database. The digit 0 is incremented for the second database and so on. Values for the server.database.{0-9} property can use the mem:, file: or res: prefixes and properties as discussed above under CONNECTIONS. For example,
     database.0=mem:temp;sql.enforce_strict_size=true;
Values specific to server.properties are:
Table 4.5. Server Property File Properties
Value     Default     Description
server.port     9001     TCP/IP port used for talking to clients. All databases are served on the same port.
server.no_system_exit     true     no System.exit() call when the database is closed
Values specific to webserver.properties are:
Table 4.6. WebServer Property File Properties
Value     Default     Description
server.port     80     TCP/IP port used for talking to clients
server.default_page     index.html     the default web page for server
server.root     ./     the location of served pages
.<extension>     ?     multiple entries such as .html=text/html define the mime types of the static files served by the web server. See the source for WebServer.java for a list.
All the above values can be specified on the command line to start the server by omitting the server. prefix.
5.     SqlTool
Mem 数据?
E:\hsqldb>java -jar ./lib/hsqldb.jar mem
Hsql Server:
(前提是xdb server 已经启动):
(java -cp ../lib/hsqldb.jar org.hsqldb.Server -database.0 file:mydb -dbname.0 xdb)
java -jar ./hsqldb.jar xdb


刘璐 2007-03-26 17:18 发表评论
]]>
(?用DbUnitq行SqlMap单元试- -http://www.tkk7.com/liulu/archive/2007/03/26/106460.html刘璐刘璐Mon, 26 Mar 2007 09:16:00 GMThttp://www.tkk7.com/liulu/archive/2007/03/26/106460.htmlhttp://www.tkk7.com/liulu/comments/106460.htmlhttp://www.tkk7.com/liulu/archive/2007/03/26/106460.html#Feedback0http://www.tkk7.com/liulu/comments/commentRss/106460.htmlhttp://www.tkk7.com/liulu/services/trackbacks/106460.html http://starrynight.blogdriver.com/starrynight/621943.html
DbUnit?/strong>

Z赖于其他外部pȝQ如数据库或其他接口Q的代码~写单元试是一件很困难的工作。在q种情况下,有效的单元必隔L试对象和外部依赖Q以便管理测试对象的状态和行ؓ(f)?/p>

使用mock object对象Q是隔离外部依赖的一个有效方法。如果我们的试对象是依赖于DAO的代码,mock object技术很方便。但如果试对象变成?jin)DAO本nQ又如何q行单元试呢?

开源的DbUnit目Qؓ(f)以上的问题提供了(jin)一个相当优雅的解决Ҏ(gu)。用DbUnitQ开发h员可以控制测试数据库的状态。进行一个DAO单元试之前QDbUnit为数据库准备好初始化数据Q而在试l束ӞDbUnit?x)把数据库状态恢复到试前的状态?/p>

下面的例子用DbUnit为iBATIS SqlMap的DAO~写单元试?/p>

准备试数据
首先Q要为单元测试准备数据。用DbUnitQ我们可以用XML文g来准备测试数据集。下面的XML文gUCؓ(f)目标数据库的Seed FileQ代表目标数据库的表名和数据Q它为测试准备了(jin)两个Employee的数据。employee对应数据库的表名Qemployee_uid、start_date、first_name和last_name都是表employee的列名?/span>

<?xml version="1.0" encoding="GB2312"?>
<dataset>
    <employee employee_uid="0001"
        start_date="2001-01-01"
        first_name="liutao"
        last_name="liutao" />
   
    <employee employee_uid="0002"
        start_date="2001-04-01"
        first_name="wangchuang"
        last_name="wangchuang" />
</dataset>

~省情况下,DbUnit在单元测试开始之前删除Seed File中所有表的数据,然后导入Seed File的测试数据。在Seed File中不存在的表QDbUnit则不处理?br />Seed File可以手工~写Q也可以用程序导出现有的数据库数据ƈ生成?br />

SqlMap代码
我们要测试的SqlMap映射文g如下所C:(x)
<select id="queryEmployeeById" parameterClass="java.lang.String"
    resultClass="domain.Employee">
    select employee_uid as userId,
        start_date as startDate,
        first_name as firstName,
        last_name as lastName
    from EMPLOYEE where employee_uid=#value#
</select>
<delete id="removeEmployeeById" parameterClass="java.lang.String">
    delete from EMPLOYEE where employee_uid=#value#
</delete>
<update id="updateEmpoyee" parameterClass="domain.Employee">
    update EMPLOYEE
    set start_date=#startDate#,
    first_name=#firstName#,
    last_name=#lastName#
    where employee_uid=#userId#
</update>
<insert id="insertEmployee" parameterClass="domain.Employee">
    insert into employee (employee_uid,
        start_date, first_name, last_name)
        values (#userId#, #startDate#, #firstName#, #lastName#)
</insert>

~写DbUnit TestCase
Z(jin)方便试Q首先ؓ(f)SqlMap的单元测试编写一个抽象的试基类Q代码如下?/span>

public abstract class BaseSqlMapTest extends DatabaseTestCase {
    protected static SqlMapClient sqlMap;

    protected IDatabaseConnection getConnection() throws Exception {
        return new DatabaseConnection(getJdbcConnection());
    }
    protected void setUp() throws Exception {
        super.setUp();
        init();
    }
    protected void tearDown() throws Exception {
        super.tearDown();
        getConnection().close();
        if (sqlMap != null) {
            DataSource ds = sqlMap.getDataSource();
            Connection conn = ds.getConnection();
            conn.close();
        }
    }
    protected void init() throws Exception {
        initSqlMap("sqlmap/SqlMapConfig.xml", null);
    }
    protected SqlMapClient getSqlMapClient() {
        return sqlMap;
    }
    protected void initSqlMap(String configFile, Properties props)
            throws Exception {
        Reader reader = Resources.getResourceAsReader(configFile);
        sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader, props);
        reader.close();
    }
    protected void initScript(String script) throws Exception {
        DataSource ds = sqlMap.getDataSource();
        Connection conn = ds.getConnection();
       
        Reader reader = Resources.getResourceAsReader(script);
        ScriptRunner runner = new ScriptRunner();
        runner.setStopOnError(false);
        runner.setLogWriter(null);
        runner.setErrorLogWriter(null);

        runner.runScript(conn, reader);
        conn.commit();
        conn.close();
        reader.close();
    }
    private Connection getJdbcConnection() throws Exception {
        Properties props = new Properties();
        props.load(Resources.getResourceAsStream("sqlmap/SqlMapConfig.properties"));
        Class driver = Class.forName(props.getProperty("driver"));
        Connection conn = DriverManager.getConnection(props.getProperty("url"),
                props.getProperty("username"), props.getProperty("password"));
        return conn;
    }
}

然后为每个SqlMap映射文g~写一个测试用例,extends上面的抽象类。如~写Employ.xml的测试用例如下,它覆盖了(jin)DbUnit的DatabaseTestCasecȝgetDataSetҎ(gu)?br />

public class EmployeeDaoTest extends BaseSqlMapTest {
   
    protected IDataSet getDataSet() throws Exception {
        Reader reader = Resources.getResourceAsReader("config/employee_seed.xml");
        return new FlatXmlDataSet(reader);
    }
    public void testQueryEmpoyeeById() throws Exception {
        String id = "0001";
        Employee emp = (Employee)sqlMap.queryForObject("queryEmployeeById", id);
        assertNotNull(emp);
        assertEquals("0001", emp.getUserId());
        assertEquals("liutao", emp.getFirstName());
    }
    public void testRemoveEmployeeById() throws Exception {
        String id = "0001";
        int num = sqlMap.delete("removeEmployeeById", id);
        assertEquals(1, num);
       
        // 注意q里, 认删除不能使用SqlMap的查? 很奇怪!
        ITable table = getConnection().createQueryTable("removed",
                "select * from employee where employee_uid='0001'");
        assertEquals(0, table.getRowCount());
    }
    public void testUpdateEmployee() throws Exception {
        String id = "0002";
        Employee emp = (Employee)sqlMap.queryForObject("queryEmployeeById", id);
        emp.setLastName("wch");
        sqlMap.update("updateEmpoyee", emp);
       
        Employee emp1 = (Employee)sqlMap.queryForObject("queryEmployeeById", id);
        assertEquals("wch", emp1.getLastName());
    }
    public void testInsertEmployee() throws Exception {
        Employee emp = new Employee();
        emp.setUserId("0005");
        emp.setStartDate("2003-09-09");
        emp.setFirstName("macy");
        emp.setLastName("macy");
        sqlMap.insert("insertEmployee", emp);
       
        Employee emp1 = (Employee)sqlMap.queryForObject("queryEmployeeById", "0005");
        assertEquals(emp.getFirstName(), emp1.getFirstName());
        assertEquals(emp.getStartDate(), emp1.getStartDate());
    }
}

以上例子中的l色代码部分使用ITable接口来查询已删除的数据。因Z用SqlMapClient.queryForObjectҎ(gu)查询Q已删除的数据还存在Q真奇怪(有时间再研究Q?br />
DbUnit的断a
我们可以使用DbUnit的AssertioncȝҎ(gu)来比较数据是否相同?br />

public class Assertion {
    public static void assertEquals(ITable expected, ITable actual)
    public static void assertEquals(IDataSet expected, IDataSet actual)
}

DatabaseTestCase的getSetUpOperation和getTearDownOperationҎ(gu)
~省情况下,DbUnit执行每个试前,都会(x)执行CLEAN_INSERT操作Q删除Seed File中所有表的数据,q插入文件的试数据。你可以通过覆盖getSetUpOperation和getTearDownOperationҎ(gu)改变setUp和tearDown的行为?br />

protected DatabaseOperation getSetUpOperation() throws Exception {
    return DatabaseOperation.REFRESH;
}
protected DatabaseOperation getTearDownOperation() throws Exception {
   
return DatabaseOperation.NONE;
}

REFRESH操作执行试前ƈ不执行CLEAN操作Q只是导入文件中的数据,如果目标数据库数据已存在QDbUnit使用文g的数据来更新数据库?/span>

使用Ant
上面的方法通过extends DbUnit的DatabaseTestCase来控制数据库的状态。?/span>
使用DbUnit的Ant TaskQ完全可以通过Ant脚本的方式来实现?/span>

<taskdef name="dbunit" classname="org.dbunit.ant.DbUnitTask"/>
<!-- 执行set up 操作 -->
<dbunit driver="org.hsqldb.jdbcDriver"
        url="jdbc:hsqldb:hsql://localhost/xdb"
        userid="sa" password="">
    <operation type="INSERT" src="employee_seed.xml"/>
</dbunit>
<!-- run all tests in the source tree -->
<junit printsummary="yes" haltonfailure="yes">
  <formatter type="xml"/>
  <batchtest fork="yes" todir="${reports.tests}">
    <fileset dir="${src.tests}">
      <include name="**/*Test*.java"/>
    </fileset>
  </batchtest>
</junit>
<!-- 执行tear down 操作 -->
<dbunit driver="org.hsqldb.jdbcDriver"
        url="jdbc:hsqldb:hsql://localhost/xdb"
        userid="sa" password="">
    <operation type="DELETE" src="employee_seed.xml"/>
</dbunit>

以上的Ant脚本把junit task攑֜DbUnit的Task中间Q可以达到控制数据库状态的目标?br />

由此可知QDbUnit可以灉|控制目标数据库的试状态,从而ɾ~写SqlMap单元试变得更加L?br />

本文抄袭?jin)资源列表的“Effective Unit Test with DbUnit”,但重新编写了(jin)代码CZ?br />

|上资源

1?a >DbUnit Framework

2?a >Effective Unit Testing with DbUnit

3?a >Control your test-environement with DbUnit and Anthill



刘璐 2007-03-26 17:16 发表评论
]]>
抽象cd接口的区?/title><link>http://www.tkk7.com/liulu/archive/2007/03/08/102584.html</link><dc:creator>刘璐</dc:creator><author>刘璐</author><pubDate>Thu, 08 Mar 2007 05:27:00 GMT</pubDate><guid>http://www.tkk7.com/liulu/archive/2007/03/08/102584.html</guid><wfw:comment>http://www.tkk7.com/liulu/comments/102584.html</wfw:comment><comments>http://www.tkk7.com/liulu/archive/2007/03/08/102584.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/liulu/comments/commentRss/102584.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/liulu/services/trackbacks/102584.html</trackback:ping><description><![CDATA[ <span style="FONT-WEIGHT: 400"> <span id="bkdcary" class="unnamed4"> <font style="FONT-SIZE: 9pt">abstract class和interface是Java语言中对于抽象类定义q行支持的两U机Ӟ正是׃q两U机制的存在Q才赋予?jin)Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的怼性,甚至可以怺替换Q因此很多开发者在q行抽象cd义时对于abstract class和interface的选择昑־比较随意。其实,两者之间还是有很大的区别的Q对于它们的选择甚至反映出对于问题领域本质的理解、对于设计意囄理解是否正确、合理。本文将对它们之间的区别q行一番剖析,试图l开发者提供一个在二者之间进行选择的依据。 ?br /><br />理解抽象c ?br /><br />abstract class和interface在Java语言中都是用来进行抽象类Q本文中的抽象类q从abstract class译而来Q它表示的是一个抽象体Q而abstract class为Java语言中用于定义抽象类的一U方法,误者注意区分)(j)定义的,那么什么是抽象c,使用抽象c能为我们带来什么好处呢Q ?br /><br />在面向对象的概念中,我们知道所有的对象都是通过cL描绘的,但是反过来却不是q样。ƈ不是所有的c都是用来描l对象的Q如果一个类中没有包含够的信息来描l一个具体的对象Q这L(fng)cd是抽象类。抽象类往往用来表征我们在对问题领域q行分析、设计中得出的抽象概念,是对一pd看上M同,但是本质上相同的具体概念的抽象。比如:(x)如果我们q行一个图形编辑Y件的开发,׃(x)发现问题领域存在着圆、三角Şq样一些具体概念,它们是不同的Q但是它们又都属于Ş状这样一个概念,形状q个概念在问题领域是不存在的Q它?yu)是一个抽象概c(din)正是因为抽象的概念在问题领域没有对应的具体概念Q所以用以表征抽象概늚抽象cL不能够实例化的。 ?br /><br />在面向对象领域,抽象cM要用来进行类型隐藏。我们可以构造出一个固定的一l行为的抽象描述Q但是这l行为却能够有Q意个可能的具体实现方式。这个抽象描q就是抽象类Q而这一lQ意个可能的具体实现则表现为所有可能的zcR模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允怿改的Q同Ӟ通过从这个抽象体zQ也可扩展此模块的行为功能。熟(zhn)OCP的读者一定知道,Z(jin)能够实现面向对象设计的一个最核心(j)的原则OCP(Open-Closed Principle)Q抽象类是其中的关键所在。 ?br /><br /><br />从语法定义层面看abstract class和interface  <br /><br />在语法层面,Java语言对于abstract class和interfacel出?jin)不同的定义方式Q下面以定义一个名为Demo的抽象类Z来说明这U不同。 ?br /><br />使用abstract class的方式定义Demo抽象cȝ方式如下Q ?br /><br />abstract class Demo ?jng) ?br /> abstract void method1();  <br /> abstract void method2();  <br /> … ?br />} ?br /><br />使用interface的方式定义Demo抽象cȝ方式如下Q ?br /><br />interface Demo {  <br /> void method1();  <br /> void method2();  <br /> … ?br />}  <br /><br />在abstract class方式中,Demo可以有自q数据成员Q也可以有非abstarct的成员方法,而在interface方式的实CQDemo只能够有?rn)态的不能被修改的数据成员Q也是必须是static final的,不过在interface中一般不定义数据成员Q,所有的成员Ҏ(gu)都是abstract的。从某种意义上说Qinterface是一U特DŞ式的abstract class。 ?br /><br />      从编E的角度来看Qabstract class和interface都可以用来实?design by contract"的思想。但是在具体的用上面还是有一些区别的。 ?br /><br />首先Qabstract class在Java语言中表C的是一U承关p,一个类只能使用一ơ承关pR但是,一个类却可以实现多个interface。也许,q是Java语言的设计者在考虑Java对于多重l承的支持方面的一U折中考虑吧。 ?br /><br />其次Q在abstract class的定义中Q我们可以赋予方法的默认行ؓ(f)。但是在interface的定义中Q方法却不能拥有默认行ؓ(f)Qؓ(f)?jin)绕q这个限Ӟ必须使用委托Q但是这?x) 增加一些复杂性,有时?x)造成很大的麻?ch)。 ?br /><br />在抽象类中不能定义默认行存在另一个比较严重的问题Q那是可能?x)造成l护上的ȝ(ch)。因为如果后来想修改cȝ界面Q一般通过abstract class或者interface来表C)(j)以适应新的情况Q比如,d新的Ҏ(gu)或者给已用的方法中d新的参数Q时Q就?x)非常的ȝ?ch)Q可能要p很多的时_(d)对于zcd多的情况Q尤为如此)(j)。但是如果界面是通过abstract class来实现的Q那么可能就只需要修改定义在abstract class中的默认行ؓ(f)可以了(jin)。 ?br /><br />同样Q如果不能在抽象cM定义默认行ؓ(f)Q就?x)导致同L(fng)Ҏ(gu)实现出现在该抽象cȝ每一个派生类中,q反?one ruleQone place"原则Q造成代码重复Q同样不利于以后的维护。因此,在abstract class和interface间进行选择时要非常的小?j)。 ?br /><br /><br />从设计理念层面看abstract class和interface  <br /><br />上面主要从语法定义和~程的角度论qC(jin)abstract class和interface的区别,q些层面的区别是比较低层ơ的、非本质的。本节从另一个层面:(x)abstract class和interface所反映出的设计理念Q来分析一下二者的区别。作者认为,从这个层面进行分析才能理解二者概늚本质所在。 ?br /><br />前面已经提到q,abstarct class在Java语言中体C(jin)一U承关p,要想使得l承关系合理Q父cdzcM间必d?is a"关系Q即父类和派生类在概忉|质上应该是相同的Q参考文献?〕中有关?is a"关系的大幅深入的论qͼ有兴的读者可以参考)(j)。对于interface 来说则不?dng)q不要求interface的实现者和interface定义在概忉|质上是一致的Q仅仅是实现?jin)interface定义的契U而已。ؓ(f)?jin)便于理解Q下面将通过一个简单的实例q行说明。 ?br /><br />考虑q样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Doorh执行两个动作open和closeQ此时我们可以通过abstract class或者interface来定义一个表C抽象概念的类型,定义方式分别如下所C:(x)  <br /><br />使用abstract class方式定义DoorQ ?br /><br />abstract class Door {  <br /> abstract void open();  <br /> abstract void close()Q ?br />}  <br /><br />   <br />使用interface方式定义DoorQ ?br /><br /><br />interface Door {  <br /> void open();  <br /> void close();  <br />}  <br /><br />   <br />其他具体的Doorcd可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看h好像使用abstract class和interface没有大的区别。 ?br /><br />如果现在要求Doorq要h报警的功能。我们该如何设计针对该例子的cȝ构呢Q在本例中,主要是ؓ(f)?jin)展Cabstract class和interface反映在设计理念上的区别,其他斚w无关的问题都做了(jin)化或者忽略)(j)Q下面将|列出可能的解决Ҏ(gu)Qƈ从设计理念层面对q些不同的方案进行分析。 ?br /><br />解决Ҏ(gu)一Q ?br /><br />单的在Door的定义中增加一个alarmҎ(gu)Q如下:(x)  <br /><br />abstract class Door {  <br /> abstract void open();  <br /> abstract void close()Q ?br /> abstract void alarm();  <br />}  <br /><br />   <br />或者 ?br /><br />interface Door {  <br /> void open();  <br /> void close();  <br /> void alarm();  <br />}  <br /><br />   <br />那么h报警功能的AlarmDoor的定义方式如下:(x)  <br /><br />class AlarmDoor extends Door {  <br /> void open() { … }  <br /> void close() { … }  <br /> void alarm() { … }  <br />}  <br /><br />   <br />或者 ?br /><br />class AlarmDoor implements Door ?jng) ?br /> void open() { … }  <br /> void close() { … }  <br /> void alarm() { … }  <br />} ?br /><br />q种Ҏ(gu)q反?jin)面向对象设计中的一个核?j)原则ISPQInterface Segregation PricipleQ,在Door的定义中把Door概念本n固有的行为方法和另外一个概?报警?的行为方法؜在了(jin)一赗这样引L(fng)一个问题是那些仅仅依赖于Doorq个概念的模块会(x)因ؓ(f)"报警?q个概念的改变(比如Q修改alarmҎ(gu)的参敎ͼ(j)而改变,反之依然。 ?br /><br />解决Ҏ(gu)二:(x)  <br /><br />既然open、close和alarm属于两个不同的概念,Ҏ(gu)ISP原则应该把它们分别定义在代表q两个概늚抽象cM。定义方式有Q这两个概念都用abstract class方式定义Q两个概念都使用interface方式定义Q一个概念用abstract class方式定义Q另一个概念用interface方式定义。 ?br /><br />昄Q由于Java语言不支持多重承,所以两个概念都使用abstract class方式定义是不可行的。后面两U方式都是可行的Q但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意囄反映是否正确、合理。我们一一来分析、说明。 ?br /><br />如果两个概念都用interface方式来定义,那么反映出两个问题Q?、我们可能没有理解清楚问题领域,AlarmDoor在概忉|质上到底是Doorq是报警器?2、如果我们对于问题领域的理解没有问题Q比如:(x)我们通过对于问题领域的分析发现AlarmDoor在概忉|质上和Door是一致的Q那么我们在实现时就没有能够正确的揭C我们的设计意图Q因为在q两个概늚定义上(均用interface方式定义Q反映不Zq含义。 ?br /><br />如果我们对于问题领域的理解是QAlarmDoor在概忉|质上是DoorQ同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢Q前面已l说q,abstract class在Java语言中表CZU承关p,而承关pd本质上是"is a"关系。所以对于Doorq个概念Q我们应该用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行ؓ(f)Q所以报警概念可以通过interface方式定义。如下所C:(x)  <br /><br />abstract class Door {  <br /> abstract void open();  <br /> abstract void close()Q ?br />}  <br />interface Alarm {  <br /> void alarm();  <br />}  <br />class AlarmDoor extends Door implements Alarm {  <br /> void open() { … }  <br /> void close() { … }  <br />    void alarm() { … }  <br />}  <br /><br />   <br />q种实现方式基本上能够明的反映出我们对于问题领域的理解Q正的揭示我们的设计意图。其实abstract class表示的是"is a"关系Qinterface表示的是"like a"关系Q大家在选择时可以作Z个依据,当然q是建立在对问题领域的理解上的,比如Q如果我们认为AlarmDoor在概忉|质上是报警器Q同时又hDoor的功能,那么上述的定义方式就要反q来?jin)?/font> </span> </span> <img src ="http://www.tkk7.com/liulu/aggbug/102584.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/liulu/" target="_blank">刘璐</a> 2007-03-08 13:27 <a href="http://www.tkk7.com/liulu/archive/2007/03/08/102584.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于session的详l解?/title><link>http://www.tkk7.com/liulu/archive/2007/03/07/102334.html</link><dc:creator>刘璐</dc:creator><author>刘璐</author><pubDate>Wed, 07 Mar 2007 02:50:00 GMT</pubDate><guid>http://www.tkk7.com/liulu/archive/2007/03/07/102334.html</guid><wfw:comment>http://www.tkk7.com/liulu/comments/102334.html</wfw:comment><comments>http://www.tkk7.com/liulu/archive/2007/03/07/102334.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/liulu/comments/commentRss/102334.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/liulu/services/trackbacks/102334.html</trackback:ping><description><![CDATA[ <p style="TEXT-INDENT: 2em"> <span id="ArticleContent1_ArticleContent1_lblContent">一、术语session <p>  在我的经验里Qsessionq个词被滥用的程度大概仅ơ于transactionQ更加有的是transaction与session在某些语境下的含义是相同的?/p><p>  sessionQ中文经常翻译ؓ(f)?x)话Q其本来的含义是指有始有l的一pd动作/消息Q比如打?sh)话时从拿v?sh)话拨号到挂断?sh)话这中间的一pdq程可以UCZ个session。有时候我们可以看到这L(fng)话“在一个浏览器?x)话期间Q?..”,q里的会(x)话一词用的就是其本义Q是指从一个浏览器H口打开到关闭这个期间①。最混ؕ的是“用P客户端)(j)在一ơ会(x)话期间”这样一句话Q它可能指用L(fng)一pd动作Q一般情况下是同某个具体目的相关的一pd动作Q比如从d到选购商品到结账登?gu)样一个网上购物的q程Q有时候也被称Z个transactionQ,然而有时候也可能仅仅是指一ơ连接,也有可能是指含义①,其中的差别只能靠上下文来推断②?/p><p>  然而当session一词与|络协议相关联时Q它又往往隐含?jin)“面向连接”和/或“保持状态”这样两个含义,“面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道,比如打电(sh)话,直到Ҏ(gu)接了(jin)?sh)话通信才能开始,与此相对的是写信Q在你把信发出去的时候你q不能确认对方的地址是否正确Q通信渠道不一定能建立Q但对发信h来说Q通信已经开始了(jin)。“保持状态”则是指通信的一方能够把一pd的消息关联v来,使得消息之间可以互相依赖Q比如一个服务员能够认出再次光(f)的老顾客ƈ且记得上ơ这个顾客还?gu)Ơ店里一块钱。这一cȝ例子有“一个TCP session”或者“一个POP3 session”③?/p><p>  而到?jin)web服务器蓬勃发展的时代Qsession在web开发语境下的语义又有了(jin)新的扩展Q它的含义是指一cȝ来在客户端与服务器之间保持状态的解决Ҏ(gu)④。有时候session也用来指q种解决Ҏ(gu)的存储结构,如“把xxx保存在session里”⑤。由于各U用于web开发的语言在一定程度上都提供了(jin)对这U解x案的支持Q所以在某种特定语言的语境下Qsession也被用来指代该语a的解x案,比如l常把Java里提供的javax.servlet.http.HttpSessionUCؓ(f)session⑥?/p><p>  鉴于q种混ؕ已不可改变,本文中session一词的q用也会(x)Ҏ(gu)上下文有不同的含义,请大家注意分辨?/p><p>  在本文中Q用中文“浏览器?x)话期间”来表达含义①,使用“session机制”来表达含义④,使用“session”表辑֐义⑤Q用具体的“HttpSession”来表达含义?/p><p>  二、HTTP协议与状态保?/p><p>  HTTP协议本n是无状态的Q这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器h下蝲某些文gQ无论是客户端还是服务器都没有必要纪录彼此过ȝ行ؓ(f)Q每一ơ请求之间都是独立的Q好比一个顾客和一个自动售货机或者一个普通的Q非?x)员Ӟ?j)大卖Z间的关系一栗?/p><p>  然而聪明(或者贪?j)?Q的Z很快发现如果能够提供一些按需生成的动态信息会(x)使web变得更加有用Q就像给有线?sh)视加上?gu)功能一栗这U需求一斚wqHTML逐步d?jin)表单、脚本、DOM{客L(fng)行ؓ(f)Q另一斚w在服务器端则出现?jin)CGI规范以响应客L(fng)的动态请求,作ؓ(f)传输载体的HTTP协议也添加了(jin)文g上蝲、cookieq些Ҏ(gu)。其中cookie的作用就是ؓ(f)?jin)解决HTTP协议无状态的~陷所作出的努力。至于后来出现的session机制则是又一U在客户端与服务器之间保持状态的解决Ҏ(gu)?/p><p>  让我们用几个例子来描qC下cookie和session机制之间的区别与联系。笔者曾l常ȝ一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠Q然而一ơ性消?杯咖啡的Z(x)微乎其微Q这时就需要某U方式来U录某位֮的消Ҏ(gu)量。想象一下其实也无外乎下面的几种Ҏ(gu)Q?/p><p>  1、该店的店员很厉宻I能记住每位顾客的消费数量Q只要顾客一走进咖啡店,店员q道该怎么对待?jin)。这U做法就是协议本w支持状态?/p><p>  2、发l顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每ơ消Ҏ(gu)Q如果顾客出C张卡片,则此ơ消费就?x)与以前或以后的消费相联pv来。这U做法就是在客户端保持状态?/p><p>  3、发l顾客一张会(x)员卡Q除?jin)卡号之外什么信息也不纪录,每次消费Ӟ如果֮出示该卡片,则店员在店里的纪录本上找到这个卡号对应的U录d一些消费信息。这U做法就是在服务器端保持状态?/p><p>  ׃HTTP协议是无状态的Q而出于种U考虑也不希望使之成ؓ(f)有状态的Q因此,后面两种Ҏ(gu)成为现实的选择。具体来说cookie机制采用的是在客L(fng)保持状态的Ҏ(gu)Q而session机制采用的是在服务器端保持状态的Ҏ(gu)。同时我们也看到Q由于采用服务器端保持状态的Ҏ(gu)在客L(fng)也需要保存一个标识,所以session机制可能需要借助于cookie机制来达C存标识的目的Q但实际上它q有其他选择?/p><p>  三、理解cookie机制 </p><p>  cookie机制的基本原理就如上面的例子一L(fng)单,但是q有几个问题需要解冻I(x)“会(x)员卡”如何分发;“会(x)员卡”的内容Q以?qing)客户如何用“会(x)员卡”?/p><p>  正统的cookie分发是通过扩展HTTP协议来实现的Q服务器通过在HTTP的响应头中加上一行特D的指示以提C浏览器按照指示生成相应的cookie。然而纯_的客户端脚本如JavaScript或者VBScript也可以生成cookie?/p><p>  而cookie的用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器(g)查所有存储的cookieQ如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置Q则把该cookie附在h资源的HTTPh头上发送给服务器。意思是麦当劳的?x)员卡只能在麦当劳的店里出示Q如果某家分店还发行?jin)自q?x)员卡,那么q这家店的时候除?jin)要出示麦当劳的会(x)员卡,q要出示q家店的?x)员卡?/p><p>  cookie的内容主要包括:(x)名字Q|q期旉Q\径和域?/p><p>  其中域可以指定某一个域比如.google.comQ相当于d招牌Q比如宝z公司,也可以指定一个域下的具体某台机器比如www.google.com或者f(xi)roogle.google.comQ可以用飘柔来做比?/p><p>  路径是跟在域名后面的URL路径Q比?或?foo{等Q可以用某飘柔专柜做比?/p><p>  路径与域合在一起就构成?jin)cookie的作用范围?/p><p>  如果不设|过期时_(d)则表C个cookie的生命期为浏览器?x)话期间Q只要关闭浏览器H口Qcookie消׃(jin)。这U生命期为浏览器?x)话期的cookie被称Z(x)话cookie。会(x)话cookie一般不存储在硬盘上而是保存在内存里Q当然这U行为ƈ不是规范规定的。如果设|了(jin)q期旉Q浏览器׃(x)把cookie保存到硬盘上Q关闭后再次打开览器,q些cookie仍然有效直到过讑֮的过期时间?/p><p>  存储在硬盘上的cookie可以在不同的览器进E间׃nQ比如两个IEH口。而对于保存在内存里的cookieQ不同的览器有不同的处理方式。对于IEQ在一个打开的窗口上按Ctrl-NQ或者从文g菜单Q打开的窗口可以与原窗口共享,而用其他方式新开的IEq程则不能共享已l打开的窗口的内存cookieQ对于Mozilla Firefox0.8Q所有的q程和标{N都可以共享同L(fng)cookie。一般来说是用javascript的window.open打开的窗口会(x)与原H口׃n内存cookie。浏览器对于?x)话cookie的这U只认cookie不认人的处理方式l常l采用session机制的web应用E序开发者造成很大的困扰?/p><p>  下面是一个goolge讄cookie的响应头的例?/p><p>HTTP/1.1 302 Found<br />Location: http://www.google.com/intl/zh-CN/<br />Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com<br />Content-Type: text/html</p><p align="center"></p><p>  q是使用HTTPLookq个HTTP Sniffer软g来俘L(fng)HTTP通讯U录的一部分</p><p align="center"></p><p><br />  览器在再次讉Kgoolge的资源时自动向外发送cookie</p><p align="center"></p><p>  使用Firefox可以很容易的观察现有的cookie的?/p><p>  使用HTTPLook配合F(tun)irefox可以很容易的理解cookie的工作原理?/p><p align="center"></p><p><br />  IE也可以设|在接受cookie前询?/p><p align="center"></p><p>  q是一个询问接受cookie的对话框?/p><p>  四、理解session机制</p><p> session机制是一U服务器端的机制Q服务器使用一U类g散列表的l构Q也可能是使用散列表)(j)来保存信息?/p><p>  当程序需要ؓ(f)某个客户端的h创徏一个session的时候,服务器首先检查这个客L(fng)的请求里是否已包含了(jin)一个session标识 - UCؓ(f)session idQ如果已包含一个session id则说明以前已lؓ(f)此客L(fng)创徏qsessionQ服务器按照session id把这个session(g)索出来用(如果(g)索不刎ͼ可能?x)新Z个)(j)Q如果客L(fng)h不包含session idQ则为此客户端创Z个sessionq且生成一个与此session相关联的session idQsession id的值应该是一个既不会(x)重复Q又不容易被扑ֈ规律以仿造的字符Ԍq个session id被在本ơ响应中q回l客L(fng)保存?/p><p>  保存q个session id的方式可以采用cookieQ这样在交互q程中浏览器可以自动的按照规则把q个标识发挥l服务器。一般这个cookie的名字都是类gSEEESIONIDQ而。比如weblogic对于web应用E序生成的cookieQJSESSIONID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764Q它的名字就是JSESSIONID?/p><p>  ׃cookie可以被h为的止Q必L其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一U技术叫做URL重写Q就是把session id直接附加在URL路径的后面,附加方式也有两种Q一U是作ؓ(f)URL路径的附加信息,表现形式为http://...../xxx;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764另一U是作ؓ(f)查询字符串附加在URL后面Q表现Ş式ؓ(f)http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764<br />q两U方式对于用h说是没有区别的,只是服务器在解析的时候处理的方式不同Q采用第一U方式也有利于把session id的信息和正常E序参数区分开来?/p><p>  Z(jin)在整个交互过E中始终保持状态,必d每个客户端可能请求的路径后面都包含这个session id?/p><p>  另一U技术叫做表单隐藏字Dc(din)就是服务器?x)自动修改表单,d一个隐藏字D,以便在表单提交时能够把session id传递回服务器。比如下面的表单</p><p></p><form name="testform" action="/xxx"><br /><input /><br /></form></span> </p> <p>  在被传递给客户端之前将被改写成</p> <p> </p> <form name="testform" action="/xxx"> <br /> <input type="hidden" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764" name="jsessionid" /> <br /> <input /> <br /> </form> <p>  q种技术现在已较少应用Q笔者接触过的很古老的iPlanet6(SunONE应用服务器的前n)׃用了(jin)q种技术。实际上q种技术可以简单的用对action应用URL重写来代ѝ?/p> <p>  在谈论session机制的时候,常常听到q样一U误解“只要关闭浏览器Qsession消׃(jin)”。其实可以想象一下会(x)员卡的例子,除非֮d对店家提出销卡,否则店家l对不会(x)L删除֮的资料。对session来说也是一L(fng)Q除非程序通知服务器删除一个sessionQ否则服务器?x)一直保留,E序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会(x)d在关闭之前通知服务器它?yu)要关闭Q因此服务器Ҏ(gu)不会(x)有机?x)知道浏览器已经关闭Q之所以会(x)有这U错觉,是大部分session机制都用会(x)话cookie来保存session idQ而关闭浏览器后这个session id消׃(jin)Q再ơ连接服务器时也无法找到原来的session。如果服务器讄的cookie被保存到盘上,或者用某U手D|写浏览器发出的HTTPh_(d)把原来的session id发送给服务器,则再ơ打开览器仍然能够找到原来的session?/p> <p>  恰恰是由于关闭浏览器不会(x)Dsession被删除,q服务器ؓ(f)seesion讄?jin)一个失效时_(d)当距dL(fng)上一ơ用session的时间超q这个失效时间时Q服务器可以认为客L(fng)已经停止?jin)活动,才?x)把session删除以节省存储空间?/p> <p>  五、理解javax.servlet.http.HttpSession</p> <p>  HttpSession是Javaq_对session机制的实现规范,因ؓ(f)它仅仅是个接口,具体到每个web应用服务器的提供商,除了(jin)对规范支持之外,仍然?x)有一些规范里没有规定的细微差异。这里我们以BEA的Weblogic Server8.1作ؓ(f)例子来演C?/p> <p>  首先QW(xu)eblogic Server提供?jin)一pd的参数来控制它的HttpSession的实玎ͼ包括使用cookie的开关选项Q用URL重写的开关选项Qsession持久化的讄Qsession失效旉的设|,以及(qing)针对cookie的各U设|,比如讄cookie的名字、\径、域Qcookie的生存时间等?/p> <p>  一般情况下Qsession都是存储在内存里Q当服务器进E被停止或者重启的时候,内存里的session也会(x)被清I,如果讄?jin)session的持久化Ҏ(gu),服务器就?x)把session保存到硬盘上Q当服务器进E重新启动或q些信息能够被再次使用QW(xu)eblogic Server支持的持久性方式包括文件、数据库、客L(fng)cookie保存和复制?/p> <p>  复制严格说来不算持久化保存,因ؓ(f)session实际上还是保存在内存里,不过同样的信息被复制到各个cluster内的服务器进E中Q这样即使某个服务器q程停止工作也仍然可以从其他q程中取得session?/p> <p>  cookie生存旉的设|则?x)?jing)响浏览器生成的cookie是否是一个会(x)话cookie。默认是使用?x)话cookie。有兴趣的可以用它来试验我们在第四节里提到的那个误解?/p> <p>  cookie的\径对于web应用E序来说是一个非帔R要的选项QW(xu)eblogic Server对这个选项的默认处理方式得它与其他服务器有明昄区别。后面我们会(x)专题讨论?/p> <p>  关于session的设|参考[5] <a >http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869</a></p> <p>  六、HttpSession常见问题</p> <p>  Q在本小节中session的含义ؓ(f)⑤和⑥的混合Q?/p> <p>  1、session在何时被创徏</p> <p>  一个常见的误解是以为session在有客户端访问时p创徏Q然而事实是直到某server端程序调用HttpServletRequest.getSession(true)q样的语句时才被创徏Q注意如果JSP没有昄的?<%@page session="false"%>关闭sessionQ则JSP文g在编译成Servlet时将?x)自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);q也是JSP中隐含的session对象的来历?/p> <p>  ׃session?x)消耗内存资源,因此Q如果不打算使用sessionQ应该在所有的JSP中关闭它?/p> <p>  2、session何时被删?/p> <p>  l合前面的讨论,session在下列情况下被删除a.E序调用HttpSession.invalidate();或b.距离上一ơ收到客L(fng)发送的session id旉间隔过?jin)session的超时设|?或c.服务器进E被停止Q非持久sessionQ?/p> <p>  3、如何做到在览器关闭时删除session</p> <p>  严格的讲Q做不到q一炏V可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进E这些非常规手段仍然无能为力?/p> <p>  4、有个HttpSessionListener是怎么回事</p> <p>  你可以创L(fng)listenerȝ控session的创建和销毁事Ӟ使得在发生这L(fng)事g时你可以做一些相应的工作。注意是session的创建和销毁动作触发listenerQ而不是相反。类似的与HttpSession有关的listenerq有HttpSessionBindingListenerQHttpSessionActivationListener和HttpSessionAttributeListener?br /><br />        5、存攑֜session中的对象必须是可序列化的?/p> <p>  不是必需的。要求对象可序列化只是ؓ(f)?jin)session能够在集中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内存。在Weblogic Server的session中放|一个不可序列化的对象在控制C?x)收C个警告。我所用过的某个iPlanet版本如果session中有不可序列化的对象Q在session销毁时?x)有一个ExceptionQ很奇怪?/p> <p>  6、如何才能正的应付客户端禁止cookie的可能?/p> <p>  Ҏ(gu)有的URL使用URL重写Q包括超链接Qform的actionQ和重定向的URLQ具体做法参见[6]<br /><a >http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770</a></p> <p>  7、开两个览器窗口访问应用程序会(x)使用同一个sessionq是不同的session</p> <p>  参见W三节对cookie的讨论,对session来说是只认id不认人,因此不同的浏览器Q不同的H口打开方式以及(qing)不同的cookie存储方式都会(x)对这个问题的{案有媄(jing)响?/p> <p>  8、如何防止用h开两个览器窗口操作导致的session混ؕ</p> <p>  q个问题与防止表单多ơ提交是cM的,可以通过讄客户端的令牌来解冟뀂就是在服务器每ơ生成一个不同的idq回l客L(fng)Q同时保存在session里,客户端提交表单时必须把这个id也返回服务器Q程序首先比较返回的id与保存在session里的值是否一_(d)如果不一致则说明本次操作已经被提交过?jin)。可以参看《J2EE核心(j)模式》关于表C层模式的部分。需要注意的是对于用javascript window.open打开的窗口,一般不讄q个idQ或者用单独的idQ以防主H口无法操作Q徏议不要再window.open打开的窗口里做修Ҏ(gu)作,q样可以不用设|?/p> <p>  9、ؓ(f)什么在Weblogic Server中改变session的值后要重新调用一ơsession.setValue<br />做这个动作主要是Z(jin)在集环境中提示Weblogic Server session中的值发生了(jin)改变Q需要向其他服务器进E复制新的session倹{?/p> <p>  10、ؓ(f)什么session不见?/p> <p>  排除session正常失效的因素之外,服务器本w的可能性应该是微乎其微的,虽然W者在iPlanet6SP1加若q补丁的Solaris版本上倒也遇到q;览器插件的可能性次之,W者也遇到q?721插g造成的问题;理论上防火墙或者代理服务器在cookie处理上也有可能会(x)出现问题?/p> <p>  出现q一问题的大部分原因都是E序的错误,最常见的就是在一个应用程序中去访问另外一个应用程序。我们在下一节讨个问题?/p> <p id="#7">  七、跨应用E序的session׃n<br /><br />  常常有这L(fng)情况Q一个大目被分割成若干项目开发,Z(jin)能够互不q扰Q要求每个小目作ؓ(f)一个单独的web应用E序开发,可是C(jin)最后突然发现某几个项目之间需要共享一些信息,或者想使用session来实现SSO(single sign on)Q在session中保存login的用户信息,最自然的要求是应用E序间能够访问彼此的session?/p> <p>  然而按照Servlet规范Qsession的作用范围应该仅仅限于当前应用程序下Q不同的应用E序之间是不能够互相讉KҎ(gu)的session的。各个应用服务器从实际效果上都遵守了(jin)q一规范Q但是实现的l节却可能各有不同,因此解决跨应用程序session׃n的方法也各不相同?/p> <p>  首先来看一下Tomcat是如何实现web应用E序之间session的隔ȝQ从Tomcat讄的cookie路径来看Q它对不同的应用E序讄的cookie路径是不同的Q这样不同的应用E序所用的session id是不同的Q因此即使在同一个浏览器H口里访问不同的应用E序Q发送给服务器的session id也可以是不同的?br /></p> <p align="center"> </p> <p>  Ҏ(gu)q个Ҏ(gu),我们可以推测Tomcat中session的内存结构大致如下?br /></p> <p align="center"> </p> <p>  W者以前用q的iPlanet也采用的是同L(fng)方式Q估计SunONE与iPlanet之间不会(x)有太大的差别。对于这U方式的服务器,解决的思\很简单,实际实行h也不难。要么让所有的应用E序׃n一个session idQ要么让应用E序能够获得其他应用E序的session id?/p> <p>  iPlanet中有一U很单的Ҏ(gu)来实现共享一个session idQ那是把各个应用程序的cookie路径都设?Q实际上应该?NASAppQ对于应用程序来讲它的作用相当于根)(j)?/p> <p> <session-info> <path>/NASApp</path> <br /> </session-info> </p> <p>  需要注意的是,操作׃n的session应该遵@一些编E约定,比如在session attribute名字的前面加上应用程序的前缀Q得setAttribute("name", "neo")变成setAttribute("app1.name", "neo")Q以防止命名I间冲突Q导致互相覆盖?/p> <p> <br />  在Tomcat中则没有q么方便的选择。在Tomcat版本3上,我们q可以有一些手D|׃nsession。对于版?以上的TomcatQ目前笔者尚未发现简单的办法。只能借助于第三方的力量,比如使用文g、数据库、JMS或者客L(fng)cookieQURL参数或者隐藏字D늭手段?/p> <p>  我们再看一下Weblogic Server是如何处理session的?br /></p> <p align="center"> </p> <p align="center"> </p> <p>  从截屏画面上可以看到Weblogic ServerҎ(gu)有的应用E序讄的cookie的\径都?Q这是不是意味着在Weblogic Server中默认的可以共享session?jin)呢Q然而一个小实验卛_证明即不同的应用程序用的是同一个sessionQ各个应用程序仍然只能访问自己所讄的那些属性。这说明Weblogic Server中的session的内存结构可能如?br /></p> <p align="center"> </p> <p>  对于q样一U结构,在session机制本n上来解决session׃n的问题应该是不可能的?jin)。除?jin)借助于第三方的力量,比如使用文g、数据库、JMS或者客L(fng)cookieQURL参数或者隐藏字D늭手段Q还有一U较为方便的做法Q就是把一个应用程序的session攑ֈServletContext中,q样另外一个应用程序就可以从ServletContext中取得前一个应用程序的引用。示例代码如下,</p> <p>  应用E序A</p> <p>context.setAttribute("appA", session); </p> <p>  应用E序B</p> <p>contextA = context.getContext("/appA");<br />HttpSession sessionA = (HttpSession)contextA.getAttribute("appA"); </p> <p>  值得注意的是q种用法不可ULQ因为根据ServletContext的JavaDocQ应用服务器可以处于安全的原因对于context.getContext("/appA");q回I|以上做法在Weblogic Server 8.1中通过?/p> <p>  那么Weblogic ServerZ么要把所有的应用E序的cookie路径都设?呢?原来是ؓ(f)?jin)SSOQ凡是共享这个session的应用程序都可以׃n认证的信息。一个简单的实验可以证明这一点,修改首先d的那个应用程序的描述Wweblogic.xmlQ把cookie路径修改?appA讉K另外一个应用程序会(x)重新要求dQ即使是反过来,先访问cookie路径?的应用程序,再访问修改过路径的这个,虽然不再提示dQ但是登录的用户信息也会(x)丢失。注意做q个实验时认证方式应该用FORMQ因为浏览器和web服务器对basic认证方式有其他的处理方式Q第二次h的认证不是通过session来实现的。具体请参看[7] secion 14.8 AuthorizationQ你可以修改所附的CZE序来做q些试验?/p> <p>  八、ȝ</p> <p>  session机制本nq不复杂Q然而其实现和配|上的灵zL却使得具体情况复杂多变。这也要求我们不能把仅仅某一ơ的l验或者某一个浏览器Q服务器的经验当作普遍适用的经验,而是始终需要具体情况具体分析?/p> <img src ="http://www.tkk7.com/liulu/aggbug/102334.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/liulu/" target="_blank">刘璐</a> 2007-03-07 10:50 <a href="http://www.tkk7.com/liulu/archive/2007/03/07/102334.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>?J2EE开发之常用开源项目介l?/title><link>http://www.tkk7.com/liulu/archive/2006/12/28/90547.html</link><dc:creator>刘璐</dc:creator><author>刘璐</author><pubDate>Thu, 28 Dec 2006 09:36:00 GMT</pubDate><guid>http://www.tkk7.com/liulu/archive/2006/12/28/90547.html</guid><wfw:comment>http://www.tkk7.com/liulu/comments/90547.html</wfw:comment><comments>http://www.tkk7.com/liulu/archive/2006/12/28/90547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/liulu/comments/commentRss/90547.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/liulu/services/trackbacks/90547.html</trackback:ping><description><![CDATA[ <div twffan="done">主要我所?jin)解的J2EE开发的框架或开源项目做个介l?可以Ҏ(gu)需求选用适当的开源组件进行开?主要q是以Spring为核?也ȝ?jin)一些以前web开发常用的开源工具和开源类?/div> <div twffan="done"> </div> <div twffan="done">1持久?</div> <div style="TEXT-INDENT: 21pt" twffan="done">1)Hibernate</div> <div style="TEXT-INDENT: 21pt" twffan="done">q个不用介绍?用的很频J?用的比较多的是映?包括l承映射和父子表映射</div> <div style="TEXT-INDENT: 21pt" twffan="done">对于DAO在这里介l个在它基础上开发的包bba96,目前最新版本是bba96 2.0它对Hibernateq行?jin)封? 查询功能包括执行hsql或者sql查询/更新的方法,如果你要多层ơ逻辑的条件查询可以自q装QueryObject.可以参考它做HibernateDAO.也可以直接利用它</div> <div style="TEXT-INDENT: 21pt" twffan="done">2) iBATIS</div> <div style="TEXT-INDENT: 21pt" twffan="done">另一个ORM工具,Apache?没有Hibernate那么集成,自由度比较大</div> <div twffan="done">2:SpringMVC</div> <div twffan="done"> <span twffan="done">       </span>原理说明和快速入?</div> <div twffan="done"> <span twffan="done">       </span>配置文g?</div> <div style="TEXT-INDENT: 21pt" twffan="done">Spring的配|文仉认ؓ(f)WEB-INF/xxxx-servelet.xm其中xxx为web.xml中org.springframework.web.servlet.DispatcherServlet的servlet-name?/div> <div twffan="done"> <span twffan="done">       Action</span>分发:</div> <div style="TEXT-INDENT: 21pt" twffan="done">Spring按照配|文件定义的URLQMapping到具体Controllerc,再根据URL里的action= xxx或其他参敎ͼ利用反射调用Controller里对应的ActionҎ(gu)?/div> <div style="TEXT-INDENT: 21pt" twffan="done">输入数据l定:</div> <div style="TEXT-INDENT: 21pt" twffan="done">Spring提供Binder 通过名字的一一对应反射l定PojoQ也可以直接从request.getParameter()取数据?/div> <div style="TEXT-INDENT: 21pt" twffan="done">输入数据验证</div> <div style="TEXT-INDENT: 21pt" twffan="done">Sping 提供?jin)Validator接口当然q可以用开源的Commons-Validaor支持最?/div> <div style="TEXT-INDENT: 21pt" twffan="done">Interceptor(拦截?</div> <div style="TEXT-INDENT: 21pt" twffan="done">Spring的拦截器提供接口需要自q?在这点不如WebWork做的?全面 </div> <div twffan="done"> <span twffan="done">       (</span>q里提一下WebWork和Struts的区别最主要的区别在于WebWork在徏立一个Action时是新New一个对象而Struts是SingleMoule所有的都承它的一个Action,所以根据项目需要合适的选择.)</div> <div twffan="done">3:View?/div> <div style="TEXT-INDENT: 21pt" twffan="done">1) 标签?JSP2.0/JSTL</div> <div style="TEXT-INDENT: 21pt" twffan="done">׃Webwork或Spring的标{实很有限,一般view层用JSTL标签,而且据说JSTL设计很好速度是所有标{中最快的使用h也很?/div> <div style="TEXT-INDENT: 21pt" twffan="done"> </div> <div style="TEXT-INDENT: 21pt" twffan="done">2) 富客L(fng):DOJO Widgets, YUI(YahooUI),FCKEditor, Coolest日历控g</div> <div style="TEXT-INDENT: 21pt" twffan="done">Dojo主要提供Tree, Tab{富客户端控?可以用其q行辅助客户端开?/div> <div style="TEXT-INDENT: 21pt" twffan="done">YahooUI和DOJO一样它有自q一套javascript调试控制?主要支持ajax开发也有很多Tree,Table,Menu{富客户端控?/div> <div style="TEXT-INDENT: 21pt" twffan="done">FCKEditor 最行的文本编辑器</div> <div style="TEXT-INDENT: 21pt" twffan="done">Coolest日历控g 目前很多日历控g可用,集成在项目中也比较简?q个只是其中的一?界面不错的说..</div> <div style="TEXT-INDENT: 21pt" twffan="done"> </div> <div style="TEXT-INDENT: 21pt" twffan="done">3) JavaScript:Prototype.js</div> <div style="TEXT-INDENT: 21pt" twffan="done">Prototype.js作ؓ(f)javascript的成功的开源框Ӟ装?jin)很多好用的功?通过它很Ҏ(gu)~写AJAX应用,现在AJAX技术逐渐成熟,框架资源比较丰富,比如YUI,DWR{等,也是因ؓ(f)JavaScript没有合适的调试工具,所以没有必要从零开始编写AJAX应用,个h认ؓ(f)多用一些成熟的Ajax框架实现无刷新更新页面是不错的选择.</div> <div style="TEXT-INDENT: 21pt" twffan="done"> </div> <div style="TEXT-INDENT: 21pt" twffan="done">4)表格控g:Display Tag ,Extreme Table</div> <div style="TEXT-INDENT: 21pt" twffan="done">q两个的功能差不?都是View层表格的生成,界面也比较相?可以导出Excel,Pdf,对Spring支持很容?</div> <div style="TEXT-INDENT: 21pt" twffan="done">相比较而言比较推荐ExtremeTable,它的设计很好功能上比DisplayTag多一?支持Ajax,装?jin)一些拦截器,而且最斚w的是在主wiki中有详细的中文用文?</div> <div style="TEXT-INDENT: 21pt" twffan="done"> </div> <div style="TEXT-INDENT: 21pt" twffan="done">5):OSCache</div> <div style="TEXT-INDENT: 21pt" twffan="done">OSCache是OpenSymphonyl织提供的一个J2EE架构中Web应用层的~存技术实现组?Cache是一U用于提高系l响应速度、改善系l运行性能的技术。尤其是在Web应用中,通过~存面的输出结果,可以很显著的改善pȝ的稳定性和q行性能?/div> <div style="TEXT-INDENT: 21pt" twffan="done">它主要用在处理短旉或一定时间内一些数据或面不会(x)发生变化,或将一些不变的l计报表,~冲在内?可以充分的减L务器的压?防治负蝲q,快速重启服务器(通过盘~存).</div> <div style="TEXT-INDENT: 21pt" twffan="done"> </div> <div style="TEXT-INDENT: 21pt" twffan="done">6)SiteMesh</div> <div style="TEXT-INDENT: 21pt" twffan="done">sitemesh应用Decorator模式主要用于提高面的可l护性和复用性,其原理是用Filter截取request和response,把页面组件head,content,bannerl合Z个完整的视图。通常我们都是用include标签在每个jsp面中来不断的包含各Uheader, stylesheet, scripts and footerQ现在,在sitemesh的帮助下Q我们删掉他们轻松达到复合视图模?</div> <div style="TEXT-INDENT: 21pt" twffan="done">Sitemesh也是<span twffan="done"> OpenSymphony</span>的一个项目现在最q的版本?.2,目前OpenSymphony自从04q就没有更新的版本了(jin)..感觉它还是比较有创新的一U页面组装方? OpenSymphony开源组l的代码一般写的比较漂?可以改其源代码对自己的项目进行适配.</div> <div style="TEXT-INDENT: 21pt" twffan="done">试发现Sitemeshq存在一些问?比如中文问题,它的默认~码是iso-8859-1在用时候需要做一些改?</div> <div style="TEXT-INDENT: 21pt" twffan="done"> </div> <div style="TEXT-INDENT: 21pt" twffan="done">7)CSS,XHTML</div> <div style="TEXT-INDENT: 21pt" twffan="done">q个不用说了(jin),遵@W3C标准的web面开?</div> <div style="TEXT-INDENT: 21pt" twffan="done"> </div> <div style="TEXT-INDENT: 21pt" twffan="done">8)分页标签: pager-tagliblg</div> <div style="TEXT-INDENT: 21pt" twffan="done">Pager-taglib 是一套分|{ֺQ可以灵zd实现多种不同风格的分导航页面,q且可以很好的与服务器分逻辑分离.使用h也比较简?</div> <div style="TEXT-INDENT: 21pt" twffan="done"> </div> <div style="TEXT-INDENT: 21pt" twffan="done">9)Form: Jodd Form taglib</div> <div style="TEXT-INDENT: 21pt" twffan="done">Jodd Form taglib使用比较?只要?lt;form>的头以<jodd:form bean= "mybean">包住</div> <div twffan="done">׃(x)自动l定mybean, 自动l定mybean的所有同名属性到普通html标记input, selectbox, checkbox,radiobox.....在这些input框里不用再写M代码?/div> <div twffan="done"> <span twffan="done">       </span> </div> <div style="TEXT-INDENT: 21pt" twffan="done">10)Ajax:DWR</div> <div twffan="done"> <span twffan="done">       J2EE</span>应用最常用的ajax框架</div> <div twffan="done"> <span twffan="done">       </span> </div> <div twffan="done"> <span twffan="done">       11)</span>报表 图表</div> <div style="MARGIN-LEFT: 21pt" twffan="done">Eclipse BIRT功能比较强大,也很庞大..好几?span twffan="done">M,一般没有特别需求或别的图表设计软g可以解决的不用它</span></div> <div style="TEXT-INDENT: 21pt" twffan="done">JasperReports+ iReport是一个基于Java的开源报表工P它可以在Java环境下像其它IDE报表工具一h制作报表。JasperReports支持PDF、HTML、XLS、CSV和XML文g输出格式。JasperReports是当前Java开发者最常用的报表工兗?/div> <div style="TEXT-INDENT: 21pt" twffan="done">JFreeChart主要是用来制作各U各L(fng)图表Q这些图表包括:(x)饼图、柱状图(普通柱状图以及(qing)堆栈q?、线图、区域图、分布图、؜合图、甘特图以及(qing)一些A表盘{等?/div> <div twffan="done"> <span twffan="done">      琴棋报表,国?.重点推荐,适合中国的情?开放源代码Q用完全免贏V纯JAVA开发,适用多种pȝq_。特别适合B/Sl构的系l。官方网站有其优点介l?看来用它q是不错的选择,最重要的是支持国呵呵</span> </div> <div twffan="done"> </div> <div twffan="done">4:权限控制: Acegi</div> <div style="TEXT-INDENT: 21pt" twffan="done">Acegi是Spring Framework 下最成熟的安全系l,它提供了(jin)强大灉|的企业安全服务Q如完善的认证和授权机制QHttp资源讉K控制QMethod 调用讉K控制{等,支持CAS</div> <div twffan="done">(耉大学的单点登陆技?q个单点登陆Ҏ(gu)比较出名.我也q行q配|?可以Ҏ(gu)目需?如果用户分布在不同的地方不同的系l通用一套登陆口令可以用它进行解?一般注册机登陆机就是这栯决的)</div> <div twffan="done"> <span twffan="done">       Acegi</span>只是于Springl合最好的安全框架,功能比较强大,当然q有一些其他的安全框架,q里列D一些比较流行的是我从网上找到的,使用Ҏ(gu)看其官方文档把?/div> <div style="TEXT-INDENT: 21pt" twffan="done">JAAS, Seraph, jSai - Servlet Security, Gabriel, JOSSO, Kasai, jPAM, OpenSAML都是些安全控制的框架..真够多的呵呵</div> <div twffan="done"> </div> <div twffan="done">5:全文(g)?/div> <div twffan="done"> <span twffan="done">       1) Lucene</span> </div> <div twffan="done"> <span twffan="done">       Lucene</span>是一套全文烦(ch)引接?可以通过它将数据q行倒排文g处理加入索引文g,它的索引速度和查询速度是相当快?查询百万U数据毫U出结?现在最火的Apache开源项?版本更新速度很快现在已经C(jin)2.0,每个版本更新的都比较?目前用的最多的版本应该?.4.3,但它有个不太斚w的地方单个烦(ch)引文件有2G文g限制,现在2.0版本没有q个限制,我研I的比较?它的扩展性比较好,可以很方面的扩充其分词接口和查询接口.</div> <div twffan="done"> <span twffan="done">       </span>Z它的开发的pȝ很多,比如最常用的Eclipse的搜索功?q有一些开源的软g比如Compass,Nutch,Lius,q有我最q做的InSearch(企业UFTP文g|页搜烦(ch))</div> <div twffan="done">6:公共Utilc?/div> <div twffan="done"> <span twffan="done">       </span>主要是Jakarta-Commonscd,其中最常用得是以下几个cd</div> <div style="TEXT-INDENT: 21pt" twffan="done">1) Jakarta-Commons-Language</div> <div style="TEXT-INDENT: 21pt" twffan="done"> <span twffan="done">       </span>最常用得类是StringUtilsc?提供?jin)用的字符串处理的常用?gu)效率比较?/div> <div style="TEXT-INDENT: 21pt" twffan="done">2) Jakarta-Commons-Beantuils</div> <div style="TEXT-INDENT: 21pt" twffan="done"> <span twffan="done">       </span>主要用Beantuils能够获得反射函数装?qing)对嵌套属性,map,array型属性的d?/div> <div style="TEXT-INDENT: 21pt" twffan="done">3) Jakarta-Commons-Collections</div> <div style="TEXT-INDENT: 21pt" twffan="done"> <span twffan="done">       </span>里面有很多UtilsҎ(gu)</div> <div style="TEXT-INDENT: 21pt" twffan="done"> </div> <div twffan="done">7 日志理</div> <div twffan="done"> <span twffan="done">       Log4J</span> </div> <div twffan="done"> <span twffan="done">       </span>d是日志记?分ؓ(f)Info,Warn,error几个层次可以更好的调试程?/div> <div twffan="done"> </div> <div twffan="done">8 开源的J2EE框架</div> <div twffan="done"> <span twffan="done">       1) Appfuse</span> </div> <div twffan="done"> <span twffan="done">              Appfuse</span>是Matt Raible 开发的一个指导性的入门UJ2EE框架, 它对如何集成行的Spring、Hibernate、iBatis、Struts、Xdcolet、JUnit{基框架l出?jin)示? 在持久层QAppFuse采用?jin)Hibernate O/R映射工具Q在容器斚wQ它采用?jin)Spring,用户可以自由选择Struts、Spring/MVCQW(xu)ebworkQJSFq几个Web框架?/div> <div twffan="done"> <span twffan="done">       </span> </div> <div twffan="done"> <span twffan="done">       2) SpringSide</span> </div> <div twffan="done"> <span twffan="done">       .SpringSide</span>较完整的演示?jin)企业应用的各个斚w,是一个电(sh)子商务网站的应用 SpringSide也大量参考了(jin)Appfuse中的优秀l验。最重要的是它是国内的一个开源项?可以?jin)解到国内现在的一些实际技术动态和方向很有指导意义?/div> <div twffan="done"> </div> <div twffan="done">9:模版 Template </div> <div style="TEXT-INDENT: 21pt" twffan="done">主要有Veloctiy和Freemarker</div> <div style="TEXT-INDENT: 21pt" twffan="done">模板用Servlet提供的数据动态地生成 HTML。编译器速度快,输出接近?rn)态HTML<span twffan="done">             </span>面的速度?/div> <div style="TEXT-INDENT: 21pt" twffan="done"> </div> <div twffan="done">10:工作?/div> <div twffan="done"> <span twffan="done">       </span>我所知道比较出名的主要有JBpm Shark Osworkflow,׃对它没有q多的研I所以还不是很清楚之间有什么区?</div> <div twffan="done"> </div> <div twffan="done">目理软g</div> <div style="TEXT-INDENT: 21pt" twffan="done">dotProject:是一个基于LAMP的开源项目管理Y件。最出名的项目管理Y?/div> <div style="TEXT-INDENT: 21pt" twffan="done">JIRA: 目计划QQ务安排,错误理</div> <div style="TEXT-INDENT: 21pt" twffan="done">Bugzilla:提交和管理bug,和eclipse集成,可以通过安装MyEclipse配置一下即可?/div> <div style="MARGIN-LEFT: 52.5pt; TEXT-INDENT: -31.5pt" twffan="done">BugFree借鉴微Y公司软g研发理念、免费开放源代码、基于Web的精版Bug理</div> <div style="TEXT-INDENT: 21pt" twffan="done">CVS:q个׃介绍?jin)都在?</div> <div style="MARGIN-LEFT: 47.25pt; TEXT-INDENT: -26.25pt" twffan="done">SVN: SubVersion已逐渐越CVSQ更适应于JavaEE的项目。Apache用了(jin)它很久后QSourceforge刚刚推出SVN的支持?/div> <div style="MARGIN-LEFT: 47.25pt; TEXT-INDENT: -26.25pt" twffan="done">试用例:主要JUnit单元试,~写TestCase,Spring也对Junit做了(jin)很好的支?/div> <div twffan="done"> </div> <div twffan="done">后记:</div> <div twffan="done"> <span twffan="done">       </span>以SpringZ的应用开发可选用的组件中间g真是D~ؕ,所以针对不同的目需求可以利用不同的开源品解?比如用Spring+Hibernate/ iBATIS或Spring+WebWork+Hibernate/ iBATIS或Spring+Struts+Hibernate/ iBATIS,合理的框架设计和代码复用设计寚w目开发效率和E序性能有很大的提高,也有利于后期的维?</div> <img src ="http://www.tkk7.com/liulu/aggbug/90547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/liulu/" target="_blank">刘璐</a> 2006-12-28 17:36 <a href="http://www.tkk7.com/liulu/archive/2006/12/28/90547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://888-28.com" target="_blank">AVպۺһ</a>| <a href="http://http99.com" target="_blank">òƵ</a>| <a href="http://shrongshan.com" target="_blank">þþƷ</a>| <a href="http://wwwaa875.com" target="_blank">91Ѳˬ˿</a>| <a href="http://0769wwt.com" target="_blank">ҹƵ</a>| <a href="http://sztsa.com" target="_blank">պƷһ</a>| <a href="http://www-533999.com" target="_blank">þþƷަvDz </a>| <a href="http://nzzys.com" target="_blank">ƷŮٸaѾþ</a>| <a href="http://4001120002.com" target="_blank">˳ëƬ߲</a>| <a href="http://hidiaoyan.com" target="_blank">޻ɫƬѿ</a>| <a href="http://badabg.com" target="_blank">AVպƷþþþþ</a>| <a href="http://440878.com" target="_blank">߹ۿѲavƬ</a>| <a href="http://wwwby1378.com" target="_blank">߹ۿձһ</a>| <a href="http://xjkakatong.com" target="_blank">aƬѹۿ</a>| <a href="http://hwafarda.com" target="_blank">һ</a>| <a href="http://liuxilife.com" target="_blank">޹Ʒۺɫ</a>| <a href="http://youkabaitiao.com" target="_blank">aëƬav</a>| <a href="http://wdjiuye.com" target="_blank">ĻĻmv </a>| <a href="http://qqc46.com" target="_blank">Ƶ</a>| <a href="http://quxx10.com" target="_blank">Ļ߹ۿձ</a>| <a href="http://528676.com" target="_blank">ҹƷ߹ۿ</a>| <a href="http://simupiao.com" target="_blank">AVһַ</a>| <a href="http://youweidianqi.com" target="_blank">av޹av</a>| <a href="http://44g8.com" target="_blank">ձҹѸƵ</a>| <a href="http://653349.com" target="_blank">ɫƨƨwwwӰԺѹۿƵ</a>| <a href="http://rbthy.com" target="_blank">žƷƵ</a>| <a href="http://26cgw.com" target="_blank">վ߹ۿ</a>| <a href="http://wwwseselu.com" target="_blank">޻ɫ߹ۿ</a>| <a href="http://clzqb2b.com" target="_blank">˾ƷԻ79ren</a>| <a href="http://xy996688.com" target="_blank">߹ۿѳ</a>| <a href="http://138site.com" target="_blank">91߹ۿ</a>| <a href="http://kyqp0033.com" target="_blank">һëƬȫѲ</a>| <a href="http://horticartf.com" target="_blank">ɫ18վWWW߲</a>| <a href="http://czhos.com" target="_blank">޳aƬ߹ۿĶ</a>| <a href="http://cytanhuang.com" target="_blank">ŮaƵ</a>| <a href="http://rp71.com" target="_blank">ձ</a>| <a href="http://6969aaa.com" target="_blank">ƷרWEB</a>| <a href="http://hwafarda.com" target="_blank">޾ƷƷ벻</a>| <a href="http://xiaomaomi8.com" target="_blank">Ƶ</a>| <a href="http://bogygames.com" target="_blank">ŮҺƵ</a>| <a href="http://hwjyrck.com" target="_blank">Ʒ߲ҳ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>