马上行动 - Action Now
===========================================================
I Care About Software
===========================================================

I Care About Software

I believe that the software I help to create defines me as a professional, and speaks volumes about my commitment to software development.

· I care that the software I help to create is useful and usable

· I care that the software I help to create is simple and elegant

· I care that the software I help to create is reliable and robust

· I care that the software I help to create is responsive and scalable

· I care that the software I help to create can be extended and maintained

· I care that the software I help to create can be safely reused

· I care that the software I help to create is economical

· I care that the software I help to create is ready when it's needed

· I care that the people I work with also care about software as passionately as I do

As someone who cares passionately about software, I will:

· Look for ways to achieve higher value with greater economy in my work

· Champion those practices which lead to higher value with greater economy in the wider software development community

· Enthusiastically contribute to software development research, knowledge-sharing and debate with others who care as passionately as I do

· Defend against demonstrably poor practices, be they born out of ignorance or the special interests of people and organisations who evidently do not care about software as passionately as I do

· Offer moral and practical support to those who care as much as I do to help them do the right thing.

htthttp://www.icareaboutsoftware.org/


nmtcolin 发表于:2008.05.23 09:06 ::分类: ( IT ) ::阅读:(27次) :: 评论 (0)
===========================================================
Oracle - Tables/Indexes
===========================================================

Here are some scripts related to Tables/Indexes .

Tabs w/ Questionable Inds

TABLES WITH QUESTIONABLE INDEX(ES) NOTES:

  • Owner - Owner of the table
  • Table Name - Name of the table
  • Column - Name of the column in question

  • The above query shows all tables that have more than one index with the same leading column. These indexes can cause queries to use an inappropriate indexes; in other words, Oracle will use the index that was created most recently if two indexes are of equal ranking. This can cause different indexes to be used from one environment to the next (e.g., from DEV to TEST to PROD).
  • The information does not automatically indicate that an index is incorrect; however, you may need to justify the existence of each of the indexes above.

    select 	TABLE_OWNER,
    	TABLE_NAME,
    	COLUMN_NAME
    from  	dba_ind_columns 
    where  	COLUMN_POSITION=1
    and  	TABLE_OWNER not in ('SYS','SYSTEM')
    group  	by TABLE_OWNER, TABLE_NAME, COLUMN_NAME
    having  count(*) > 1 
    
    

    Tabs With More Than 5 Inds

    TABLES WITH MORE THAN 5 INDEXES NOTES:

  • Owner - Owner of the table
  • Table Name - Name of the table
  • Index Count - Number of indexes

    select 	OWNER,
    	TABLE_NAME,
    	COUNT(*) index_count
    from  	dba_indexes 
    where  	OWNER not in ('SYS','SYSTEM')
    group  	by OWNER, TABLE_NAME 
    having  COUNT(*) > 5 
    order 	by COUNT(*) desc, OWNER, TABLE_NAME
    
    

    Tables With No Indexes

    TABLES WITHOUT INDEXES NOTES:

  • Owner - Owner of the table
  • Table Name - Name of the table

    select 	OWNER,
    	TABLE_NAME
    from 
    (
    select 	OWNER, 
    	TABLE_NAME 
    from 	dba_tables
    minus
    select 	TABLE_OWNER, 
    	TABLE_NAME 
    from 	dba_indexes
    )
    orasnap_noindex
    where	OWNER not in ('SYS','SYSTEM')
    order 	by OWNER,TABLE_NAME
    
    

    Tables With No PK

    NO PRIMARY KEY NOTES:

  • Table Owner - Owner of the table
  • Table Name - Name of the table

    select  OWNER,
    	TABLE_NAME
    from    dba_tables dt
    where   not exists (
            select  'TRUE'
            from    dba_constraints dc
            where   dc.TABLE_NAME = dt.TABLE_NAME
            and     dc.CONSTRAINT_TYPE='P')
    and 	OWNER not in ('SYS','SYSTEM')
    order	by OWNER, TABLE_NAME
    
    

    Disabled Constraints

    DISABLED CONSTRAINT NOTES:

  • Owner - Owner of the table
  • Table Name - Name of the table
  • Constraint Name - Name of the constraint
  • Constraint Type - Type of constraint
  • Status - Current status of the constraint

    select  OWNER,
            TABLE_NAME,
            CONSTRAINT_NAME,
            decode(CONSTRAINT_TYPE, 'C','Check',
                                    'P','Primary Key',
                                    'U','Unique',
                                    'R','Foreign Key',
                                    'V','With Check Option') type,
            STATUS 
    from 	dba_constraints
    where 	STATUS = 'DISABLED'
    order 	by OWNER, TABLE_NAME, CONSTRAINT_NAME
    
    

    FK Constraints

    FOREIGN KEY CONSTRAINTS NOTES:

  • Table Owner - Owner of the table
  • Table Name - Name of the table
  • Constraint Name - Name of the constraint
  • Column Name - Name of the column
  • Referenced Table - Name of the referenced table
  • Reference Column - Name of the referenced column
  • Position - Position of the column

    select 	c.OWNER,
    	c.TABLE_NAME,
    	c.CONSTRAINT_NAME,
    	cc.COLUMN_NAME,
    	r.TABLE_NAME,
    	rc.COLUMN_NAME,
    	cc.POSITION
    from 	dba_constraints c, 
    	dba_constraints r, 
    	dba_cons_columns cc, 
    	dba_cons_columns rc
    where 	c.CONSTRAINT_TYPE = 'R'
    and 	c.OWNER not in ('SYS','SYSTEM')
    and 	c.R_OWNER = r.OWNER
    and 	c.R_CONSTRAINT_NAME = r.CONSTRAINT_NAME
    and 	c.CONSTRAINT_NAME = cc.CONSTRAINT_NAME
    and 	c.OWNER = cc.OWNER
    and 	r.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
    and 	r.OWNER = rc.OWNER
    and 	cc.POSITION = rc.POSITION
    order 	by c.OWNER, c.TABLE_NAME, c.CONSTRAINT_NAME, cc.POSITION
    
    

    FK Index Problems

    FK CONSTRAINTS WITHOUT INDEX ON CHILD TABLE NOTES:

  • Owner - Owner of the table
  • Constraint Name - Name of the constraint
  • Column Name - Name of the column
  • Position - Position of the index
  • Problem - Nature of the problem

  • It is highly recommended that an index be created if the Foreign Key column is used in joining, or often used in a WHERE clause. Otherwise a table level lock will be placed on the parent table.

    select 	acc.OWNER,
    	acc.CONSTRAINT_NAME,
    	acc.COLUMN_NAME,
    	acc.POSITION,
    	'No Index' Problem
    from   	dba_cons_columns acc, 
    	dba_constraints ac
    where  	ac.CONSTRAINT_NAME = acc.CONSTRAINT_NAME
    and   	ac.CONSTRAINT_TYPE = 'R'
    and     acc.OWNER not in ('SYS','SYSTEM')
    and     not exists (
            select  'TRUE' 
            from    dba_ind_columns b
            where   b.TABLE_OWNER = acc.OWNER
            and     b.TABLE_NAME = acc.TABLE_NAME
            and     b.COLUMN_NAME = acc.COLUMN_NAME
            and     b.COLUMN_POSITION = acc.POSITION)
    order   by acc.OWNER, acc.CONSTRAINT_NAME, acc.COLUMN_NAME, acc.POSITION
    
    

    Inconsistent Column Names

    INCONSISTENT COLUMN DATATYPE NOTES:

  • Owner - Owner of the table
  • Column - Name of the column
  • Table Name - Name of the table
  • Datatype - Datatype of the column

    select 	OWNER,
    	COLUMN_NAME,
    	TABLE_NAME,
    	decode(DATA_TYPE, 'NUMBER', DATA_PRECISION, DATA_LENGTH) datatype
    from 	dba_tab_columns 
    where  	(COLUMN_NAME, OWNER) in
    		(select	COLUMN_NAME, 
    			OWNER
    	 	 from 	dba_tab_columns
    	 	 group	by COLUMN_NAME, OWNER
    	  	 having	min(decode(DATA_TYPE, 'NUMBER', DATA_PRECISION, DATA_LENGTH)) <
    		 	max(decode(DATA_TYPE, 'NUMBER', DATA_PRECISION, DATA_LENGTH)) )
    and 	OWNER not in ('SYS', 'SYSTEM')
    order	by COLUMN_NAME,DATA_TYPE 
    
    

    Object Extent Warning

    TABLES THAT CANNOT EXTEND NOTES:

  • Owner - Owner of the object
  • Object Name - Name of the object
  • Object Type - Type of object
  • Tablespace - Name of the tablespace
  • Next Extent - Size of next extent (bytes)

    select 	OWNER,
    	SEGMENT_NAME,
    	SEGMENT_TYPE,
    	TABLESPACE_NAME,
    	NEXT_EXTENT
    from (
    	select 	seg.OWNER, 
    		seg.SEGMENT_NAME,
    			seg.SEGMENT_TYPE, 
    		seg.TABLESPACE_NAME,
    			t.NEXT_EXTENT
    	from 	dba_segments seg,
    			dba_tables t
    	where 	(seg.SEGMENT_TYPE = 'TABLE'
    	and  	 seg.SEGMENT_NAME = t.TABLE_NAME
    	and  	 seg.owner = t.OWNER
    	and    NOT EXISTS (
    			select 	TABLESPACE_NAME
    				from 	dba_free_space free
    				where 	free.TABLESPACE_NAME = t.TABLESPACE_NAME
    				and 	BYTES >= t.NEXT_EXTENT))
    	union
    	select 	seg.OWNER, 
    		seg.SEGMENT_NAME,
    			seg.SEGMENT_TYPE, 
    		seg.TABLESPACE_NAME,
    			c.NEXT_EXTENT
    	from 	dba_segments seg,
    			dba_clusters c 
    	where  	(seg.SEGMENT_TYPE = 'CLUSTER'
    	and    	 seg.SEGMENT_NAME = c.CLUSTER_NAME
    	and    	 seg.OWNER = c.OWNER
    	and    	NOT EXISTS (
    			select 	TABLESPACE_NAME
    			from 	dba_free_space free
    			where 	free.TABLESPACE_NAME = c.TABLESPACE_NAME
    			and 	BYTES >= c.NEXT_EXTENT))
    	union
    	select 	seg.OWNER, 
    		seg.SEGMENT_NAME,
    			seg.SEGMENT_TYPE, 
    		seg.TABLESPACE_NAME,
    			i.NEXT_EXTENT
    	from 	dba_segments seg,
    			dba_indexes  i
    	where  	(seg.SEGMENT_TYPE = 'INDEX'
    	and    	 seg.SEGMENT_NAME = i.INDEX_NAME
    	and    	 seg.OWNER        = i.OWNER
    	and    	 NOT EXISTS (
    			select 	TABLESPACE_NAME
    					from 	dba_free_space free
    					where 	free.TABLESPACE_NAME = i.TABLESPACE_NAME
    			and 	BYTES >= i.NEXT_EXTENT))
    	union
    	select 	seg.OWNER, 
    		seg.SEGMENT_NAME,
    			seg.SEGMENT_TYPE, 
    		seg.TABLESPACE_NAME,
    			r.NEXT_EXTENT
    	from 	dba_segments seg,
    			dba_rollback_segs r
    	where  	(seg.SEGMENT_TYPE = 'ROLLBACK'
    	and    	 seg.SEGMENT_NAME = r.SEGMENT_NAME
    	and    	 seg.OWNER        = r.OWNER
    	and    	 NOT EXISTS (
    			select	TABLESPACE_NAME
    					from 	dba_free_space free
    					where 	free.TABLESPACE_NAME = r.TABLESPACE_NAME
                    and 	BYTES >= r.NEXT_EXTENT))
    )
    orasnap_objext_warn
    order 	by OWNER,SEGMENT_NAME
    
    

    Segment Fragmentation

    OBJECTS WITH MORE THAN 50% OF MAXEXTENTS NOTES:

  • Owner - Owner of the object
  • Tablespace Name - Name of the tablespace
  • Segment Name - Name of the segment
  • Segment Type - Type of segment
  • Size - Size of the object (bytes)
  • Extents - Current number of extents
  • Max Extents - Maximum extents for the segment
  • Percentage - Percentage of extents in use

  • As of v7.3.4, you can set MAXEXTENTS=UNLIMITED to avoid ORA-01631: max # extents (%s) reached in table $s.%s.
  • To calculate the MAXEXTENTS value on versions < 7.3.4 use the following equation: DBBLOCKSIZE / 16 - 7
  • Here are the MAXEXTENTS for common blocksizes: 1K=57, 2K=121, 4K=249, 8K=505, and 16K=1017
  • Multiple extents in and of themselves aren't bad. However, if you also have chained rows, this can hurt performance.

    select 	OWNER,
    	TABLESPACE_NAME,
    	SEGMENT_NAME,
    	SEGMENT_TYPE,
    	BYTES,
    	EXTENTS,
    	MAX_EXTENTS,
    	(EXTENTS/MAX_EXTENTS)*100 percentage
    from 	dba_segments
    where 	SEGMENT_TYPE in ('TABLE','INDEX')
    and 	EXTENTS > MAX_EXTENTS/2
    order 	by (EXTENTS/MAX_EXTENTS) desc
    
    

    Extents reaching maximum

    TABLES AND EXTENTS WITHIN 3 EXTENTS OF MAXIMUM :

  • Owner - Owner of the segment
  • Segment Name - Name of the segment

    select owner "Owner",
           segment_name "Segment Name",
           segment_type "Type",
           tablespace_name "Tablespace",
           extents "Ext",
           max_extents "Max"
    from dba_segments
    where ((max_extents - extents) <= 3) 
    and owner not in ('SYS','SYSTEM')
    order by owner, segment_name
    
    

    Analyzed Tables

    ANALYZED TABLE NOTES:

  • Owner - Owner of the table
  • Analyzed - Number of analyzed tables
  • Not Analyzed - Number of tables that have not be analyzed
  • Total - Total number of tables owned by user

  • The ANALYZE statement allows you to validate and compute statistics for an index, table, or cluster. These statistics are used by the cost-based optimizer when it calculates the most efficient plan for retrieval. In addition to its role in statement optimization, ANALYZE also helps in validating object structures and in managing space in your system. You can choose the following operations: COMPUTER, ESTIMATE, and DELETE. Early version of Oracle7 produced unpredicatable results when the ESTIMATE operation was used. It is best to compute your statistics.
  • A COMPUTE will cause a table-level lock to be placed on the table during the operation.

    select	OWNER,
    	sum(decode(nvl(NUM_ROWS,9999), 9999,0,1)) analyzed,
    	sum(decode(nvl(NUM_ROWS,9999), 9999,1,0)) not_analyzed,
    	count(TABLE_NAME) total
    from 	dba_tables
    where 	OWNER not in ('SYS', 'SYSTEM')
    group 	by OWNER
    
    

    Recently Analyzed Tables

    LAST ANALYZED TABLE NOTES:

  • Owner - Owner of the table
  • Table Name - Name of the table
  • Last Analyzed - Last analyzed date/time

    select 	OWNER,
    	TABLE_NAME,
    	to_char(LAST_ANALYZED,'MM/DD/YYYY HH24:MI:SS') last_analyzed
    from 	dba_tab_columns
    where 	OWNER not in ('SYS','SYSTEM')
    and 	LAST_ANALYZED is not null
    and	COLUMN_ID=1
    and 	(SYSDATE-LAST_ANALYZED) < 30
    order	by (SYSDATE-LAST_ANALYZED)
    
    

    Cached Tables

    CACHED TABLE NOTES:

  • Owner - Owner of the table
  • Table Name - Name of the table
  • Cache - Cached?

  • Oracle 7.1+ provides a mechanism for caching table in the buffer cache. Caching tables will speed up data access and improve performance by finding the data in memory and avoiding disk reads.

    select 	OWNER,
    	TABLE_NAME,
    	CACHE
    from dba_tables
    where OWNER not in ('SYS','SYSTEM')
    and CACHE like '%Y'
    order by OWNER,TABLE_NAME
    
    

  • nmtcolin 发表于:2008.05.06 15:35 ::分类: ( IT ) ::阅读:(58次) :: 评论 (1)
    ===========================================================
    Weblogic 只允许能连接5个IP的解决办法
    ===========================================================

    Weblogic 只允许能连接5个IP的解决办法

    0. Weblogic试用版只允许连接5个不同IP, 尽管可重新启动weblogic server可以重新获取5个IP,
    对于开发测试环境来说, 对于开发测试来说很不方便, 也不可能购买Weblogic的licences.


    1. shell scripts & Java command
    local_port: 12345
    host: ydc062
    remote_port: 8080

    java -classpath ./Relay.jar Relay 12345 ydc062 8080

    2. 使用方法
    http://ydc062:8080(limit 5 ip)

    http://ydc062:12345(not limit forward to above access)


    3. Java source code

    /**
    * DataRelay.java
    */
    import java.io.InputStream;
    import java.io.OutputStream;

    public class DataRelay implements Runnable {
    private InputStream in;

    private OutputStream out;

    public void run() {
    byte abyte0[] = new byte[4096];
    try {
    do {
    int i = in.read(abyte0);
    if (i == 0)
    break;
    out.write(abyte0, 0, i);
    } while (true);
    try {
    in.close();
    } catch (Exception exception) {
    }
    try {
    out.close();
    } catch (Exception exception1) {
    }
    } catch (Exception exception2) {
    try {
    in.close();
    } catch (Exception exception3) {
    }
    try {
    out.close();
    } catch (Exception exception4) {
    }
    }
    }

    public DataRelay(InputStream inputstream, OutputStream outputstream) {
    in = inputstream;
    out = outputstream;
    }
    }


    /**
    * Relay.java
    */
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;

    public class Relay implements Runnable {

    public int listenPort;

    public String relayHost;

    public int relayPort;

    public Relay() {
    }

    public Relay(int i, String s, int j) {
    listenPort = i;
    relayHost = s;
    relayPort = j;
    }

    public void run() {
    try {
    ServerSocket serversocket = new ServerSocket(listenPort);
    do {
    Socket socket = serversocket.accept();
    try {
    Socket socket1 = new Socket(relayHost, relayPort);
    startRelay(socket.getInputStream(), socket1
    .getOutputStream());
    startRelay(socket1.getInputStream(), socket
    .getOutputStream());
    } catch (Exception exception1) {
    exception1.printStackTrace();
    socket.close();
    }
    } while (true);
    } catch (Exception exception) {
    exception.printStackTrace();
    }
    }

    public void startRelay(InputStream inputstream, OutputStream outputstream)
    throws IOException {
    DataRelay datarelay = new DataRelay(inputstream, outputstream);
    Thread thread = new Thread(datarelay);
    thread.start();
    }

    public static void main(String args[]) {
    if (args.length < 3) {
    System.out.println("-------------------------------------------");
    System.out.println("Usage: ./Relay local_port host remote_port");
    System.out.println("-------------------------------------------");
    System.exit(0);
    }
    int i = 0;
    try {
    i = Integer.parseInt(args[0]);
    } catch (Exception exception) {
    System.out.println("Invalid local port: " + args[0]);
    System.exit(0);
    }
    int j = 0;
    try {
    j = Integer.parseInt(args[2]);
    } catch (Exception exception1) {
    System.out.println("Invalid remote port: " + args[2]);
    System.exit(0);
    }
    Relay relay = new Relay(i, args[1], j);
    relay.run();
    }

    }


    nmtcolin 发表于:2008.04.28 15:52 ::分类: ( IT ) ::阅读:(165次) :: 评论 (0)
    ===========================================================
    关于中文简体繁体的相互转换!
    ===========================================================

    1. 利用 ResourceBundle Editor (http://eclipse-rbe.sourceforge.net)可以解决资源文件同步编辑.如下列英文,简体和繁体同时编辑.

    icsis_en.properties
    icsis_zh_CN.properties
    icsis_zh_TW.properties

    2. 有了简体资源文件可以用下列产生繁体资源文件.

    java -classpath .;libzhcode.jar zhcode -gb configpropssltnt_GB2312.xml configpropssltnt_Big5.xml


    native2ascii -encoding Big5 configpropssltnt_Big5.xml configpropssltnt_zh_HK.xml
    zhcode.jar download from the following link.http://www.mandarintools.com/download/zhcode.zip

    3. Big5、GB2312、Unicode、UTF8 等多种中文编码之间转换。

    官方网页为:
    http://www.mandarintools.com/javaconverter.html

    编码与解码工具:

    http://web.hku.hk/~jwilam/it/codewares.htm


    nmtcolin 发表于:2008.04.23 13:50 ::分类: ( IT ) ::阅读:(61次) :: 评论 (0)
    ===========================================================
    The value for the useBean class attribute SecurityOrgPages is invalid. in tomcat 5.5
    ===========================================================

    Aproject work fine in tomcat 4.1, but upgrade apache-tomcat-4.1.34/jdk 1.4 to apache-tomcat-5.5.25, jdk 1.5, ecounter the following error.

    type Exception report

    message

    description The server encountered an internal error () that prevented it from fulfilling this request.

    exception

    org.apache.jasper.JasperException: /jsp/security/securityOrgPages.jsp(4,0) The value for the useBean class attribute SecurityOrgPages is invalid.
    org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:40)
    org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:407)
    org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:148)
    org.apache.jasper.compiler.Generator$GenerateVisitor.visit(Generator.java:1175)
    org.apache.jasper.compiler.Node$UseBean.accept(Node.java:1117)
    org.apache.jasper.compiler.Node$Nodes.visit(Node.java:2166)
    org.apache.jasper.compiler.Node$Visitor.visitBody(Node.java:2216)
    org.apache.jasper.compiler.Node$Visitor.visit(Node.java:2222)
    org.apache.jasper.compiler.Node$Root.accept(Node.java:457)
    org.apache.jasper.compiler.Node$Nodes.visit(Node.java:2166)
    org.apache.jasper.compiler.Generator.generate(Generator.java:3322)
    org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:199)
    org.apache.jasper.compiler.Compiler.compile(Compiler.java:296)
    org.apache.jasper.compiler.Compiler.compile(Compiler.java:277)
    org.apache.jasper.compiler.Compiler.compile(Compiler.java:265)
    org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:564)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:302)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:329)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    com.newmodern.etm.security.servlet.SecurityOrgServlet.service(SecurityOrgServlet.java:367)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:803)


    note The full stack trace of the root cause is available in the Apache Tomcat/5.5.25 logs.

    in jsp /jsp/security/securityOrgPages.jsp change below bean classs as absolute path ok, why??? but it work fine in tomcat 4.1.

    <%@ page import="com.xxxxxx.xxx.security.entity.*" %>
    <jsp:useBean id="etmSecurityOrgPages" class="SecurityOrgPages" scope="request"/>

    Solution:
    <jsp:useBean id="etmSecurityOrgPages" class="com.xxxxxx.xxx.security.entity.SecurityOrgPages" scope="request"/>


    nmtcolin 发表于:2008.04.16 17:02 ::分类: ( IT ) ::阅读:(131次) :: 评论 (0)
    ===========================================================
    Coding your second Jakarta Struts Application
    ===========================================================

    Coding your second Jakarta Struts Application

    http://javaboutique.internet.com/tutorials/Struts2/

    Introduction

    Did the title of the article make you curious? If this is the second application then what was the first one? The answer is, the first application was presented in my previous article about Jakarta Struts, "Stepping through Jakarta Struts". Here I showed you:

    • how to download and install Struts
    • the directory structure of a Struts application
    • how to create the first pieces of a new application
    • the contents and purpose of the configuration files
    • how to build a simple Struts HTML page using taglibs
    • how to code an ActionForm class
    • how to code an Action class
    • and finally how to test your application

    The "application" that I used as the example was a simple HTML page containing a form with the common controls--text and textarea fields, radio buttons, a checkbox, a selection list (drop down), and a submit button. The submit button would simply submit the form to the page again, and despite the simplicity of the application, all of the main pieces of the Struts framework were being used.

    In this article I'll show you how to take one more step up the Struts ladder. This time we'll build a classic list-detail application with the well-known CRUD-actions: Create, Read, Update, and Delete.

    The DVD library application

    Reuse is a good thing, so I decided to take the specs for our second application from a previous article of mine, "Java and JDOM: the perfect couple". Here, a small web application that could manage a collection of DVDs was built. The DVD information is held in an XML file. The application consists of two pages, a DVD List page and a DVD Detail page. Here's the List page first:

    When you click on one of "Id"-hyperlinks you'll go to the Detail page:

    As you can see there are 7 functions in total to implement: list, detail, save, update, create, delete and cancel. The flow of the application is as follows:

    In the JDOM article, I used a very simple MVC-architecture using only jsp-pages (even for the controllers) and JavaBeans. The beans can be re-used in the Struts application, and also the html layout. To finish the Struts application we'll have to:

    • write the proper configuration files (struts-config.xml and ApplicationRessources.properties)
    • code ActionForm and Action classes for the 7 functions
    • write the two jsp-pages using Struts tags

    nmtcolin 发表于:2008.04.11 23:14 ::分类: ( IT ) ::阅读:(39次) :: 评论 (0)
    ===========================================================
    The Power of Three - Eclipse, Tomcat, and Struts
    ===========================================================

    Java(TM) Boutique - The Power of Three - Eclipse, Tomcat, and Struts

    Introduction

    As a programmer it's important to be productive, and as any other craftsman you need good tools to be productive. In this article I'll present a set of tools, which can really help you get your job done. What's more, they're all free, open source, and well documented. I've been using these tools in several real-life projects and have found that they often outdo expensive development tools. This is because they're simple to install, simple to use, reliable and have good performance.

    The names of the tools are Eclipse, Tomcat, and Struts.

    You've probably heard about all of them, and maybe you have used them in your work, but anyway: here's a short description of each:

    • Eclipse is an IDE from eclipse.org, which can be used for programming in Java and many other programming languages.
    • Tomcat is a J2EE web server from the Apache Jakarta project
    • Struts is a framework--also from Apache Jakarta--for building MVC-type servlet applications

    So, these tools are made for making web applications based on the servlet specification. They don't cover EJB's, since Tomcat is not an EJB-server, and standard Eclipse does not cover EJB's.

    Eclipse has a project type for Java development, but strangely enough not for Java web application development. A Java web application is characterized by a special directory structure (war-file structure), and a set of specialized files: jsp-files, XML configuration files, servlets, etc. To fill this gap, a very nice Eclipse plug-in from sysdeo.com is at hand. It not only gives us the web application project but also a way of managing the Tomcat server from within Eclipse. Below we'll see how to install and use this plug-in.

    Struts gives you a way of building modular, de-coupled web applications. How Struts is included in Eclipse is another topic that'll be covered later in this article.

    How to debug Jsp, servlet etc.

    http://javaboutique.internet.com/tutorials/three/index.html

     查看全文
    nmtcolin 发表于:2008.04.11 23:01 ::分类: ( IT ) ::阅读:(49次) :: 评论 (0)
    ===========================================================
    项目自动化之道--如何构建、部署、监控Java应用
    ===========================================================

    Pragmatic Project Automation

    项目自动化之道--如何构建、部署、监控Java应用

    英文版下载地址:

    http://www.net130.com/CMS/Pub/book/book_program/book_program_zh/2005_08_12_42744.htm

    http://www.china-pub.com/25643

    【内容简介】
    您想可靠准确地建构、测试和部署您的软件吗?您想少花时间到简单劳动,而腾出大部分功力精雕细镂

    您的软件、锻炼您的技巧吗?本书正好符合您的需要。
    让计算机为您干活,让它去做所有必需的枯燥的重复性工作和杂事——以规律间隔建构和测试代码,产生

    恒定的发布,部署和安装应用,以及监控所运行的程序。您将会有更多时间和精力去享受编写高质量代

    码的乐趣。
    本书由程序员所写,也是为程序员所用。这里的自动化并非与处理工资表有关,它是对那些日复一日、

    周复一周编写应用软件的人而言的。为了跟上开发周期的脚步,我们需要更巧妙地工作,而不是更卖力

    地工作。
    只要是手工过程,问题就会迅速积小成大,自动化正是其解决之道。
    阅读本书,您将:
    ·学习怎样使用Ant和CruiseControl对建构和测试过程自动化;
    ·通过运行简单的脚本,就能根据需要生成经过测试的发布;
    ·使用电子邮件、短信、RSS和可视装置让团队中的每个人知道项目的当前健康状况;
    ·创建安装/卸载程序,或者使用Java Web Start部署到远端机器上;
    ·分发诊断测试代码,从而节约故障排错时间;
    ·探讨使程序自我监控和报告问题的技巧。
    你还会学到实现自动化工作的很多诀窍花招,它们都是很有趣的。
    本书所讲述的内容都是有关Java领域的软件开发工具。
    Mike Clark先生是一位咨询师、作家和演说家。更重要的是,他还是一名程序员。在他的Clarkware咨

    询公司,他已经在让自己的团队更好更快地开发软件了。(您还等什么呢?)

    【目录信息】

    关于程序员修炼三部曲 1
    前言 iii
    第1章 序言 1
    1.1 瞧,不用手就能搞定 1
    1.2 自动化的类型 4
    1.3 关于自动化的问题 6
    1.4 路线图 9
    第2章 单步建构 11
    2.1 建构软件很像做香肠 11
    2.2 选择项目目录结构 16
    2.3 生成你的首个建构 17
    2.4 用Ant建构 20
    2.5 对建构进行“口味测试” 30
    2.6 打扫战场 35
    2.7 脚本化建构 36
    2.8 提早开始 40
    2.9 小结 41
    第3章 定时建构 43
    3.1 定时首个建构 44
    ......


    nmtcolin 发表于:2008.01.25 09:41 ::分类: ( IT ) ::阅读:(75次) :: 评论 (0)
    ===========================================================
    Google大事记
    ===========================================================
    Google大事记

    ·1995年3月 谢尔盖-布林和拉里-佩奇在斯坦福大学计算机博士候选人的春季聚会上首次见面。

    ·1998年9月7日 组建Google公司,位于加州一个车库,有四名员工。

    ·1999年2-6月 得到Sequoia Capital和Kleiner Perkins Caufield & Byers两家风险投资基金的2500万美元注资。

    ·2000年5-6月 每天进行1800万次查询,成为最大的互联网搜索引擎,雅虎选择Google作为默认的搜索结果供应商。

    ·2002年3-4月 推出了Google新闻的测试版。

    ·2002年9-10月 在全球推出了关键词广告,在英国、德国、法国和日本都能提供关键词广告服务。

    ·2003年1-6月 收购了Pyra实验室,这是网络出版工具Blogger的创建者。

    ·2003年5-6月 推出AdSense,这一广告计划能按照网站内容做广告。

    ·2004年2月 雅虎开始推出自己的搜索技术,淡出Google搜索技术。

    ·2004年3月31日 宣布了免费电子邮件服务Gmail。

    ·2004年4月29日 向美国证券交易委员会提交IPO申请文件。

    ·2004年8月19日 以100.01美元开盘,比IPO价格上涨18%。

    ·2005年5月,Google宣布李开复加盟,任中国区总裁,Google中国公司开始启动.

    ·2006年4月,Google中文改名"谷歌".

     查看全文
    nmtcolin 发表于:2008.01.11 14:45 ::分类: ( IT ) ::阅读:(71次) :: 评论 (0)
    ===========================================================
    微软支持Android的原因:打击Sun
    ===========================================================

    微软支持Android的原因:打击Sunhttp://tech.it168.com/o/2008-01-07/200801071645655.shtml

    【IT168 分析评论】最近谷歌公司推出了其移动开发平台Android,并一手促成了开放手机联盟的建立。对于微软来说,这是一件值得庆祝的事情。据专家分析,对于微软来说,Android推出的意义堪与微软在上世纪90年代赢得浏览器之争相比。

    微软在开发领域最大对手:Sun的Java平台

    在软件开发行业,在过去12年中,微软最大的竞争对手非Sun公司的Java平台莫属。从上世纪90年代中后期开始,Sun就开始在各个开发领域让原属于微软阵营的开发者纷纷转投Java平台。据Sun公司统计数据表示,现在有超过600万在使用Java进行开发,很明显,Java平台在软件开发行业占据了统治地位。

    事实上,为了应对Java平台的挑战,在2000年微软就已经不得不全面修改其软件开发平台,即推出全新.NET平台对抗Java。尽管微软的.NET平台在一定程度上从Java手中收复了一部分失地,但是,Java依然是程序员们进行企业应用开发的首选平台,甚至可以说有史以来最成功的软件开发平台。微软当然不会太喜欢这个Java平台。因为Java是微软最大的竞争对手,是其要全力打击的目标。

    然而,Java平台和它的标准化过程也并非完美无缺。Sun公司和Java标准制定组织(Java Community Process,JCP)在决策上的一系列失误,让微软的.NET平台趁机取得了一定成功。定义Java标准的机构JCP已经使其企业开发平台Java EE变得过于复杂,同时Sun已经为它的移动开发创建了一个平台——Java ME,尽管它具有很大的突破,但是却四分五裂。但是,Java SE依然是一个非常强大的竞争对手,微软并没有从它身上赚多少便宜,不过,随着Google的Android移动开发平台的推出,这种情况将会发生改变。

    Android分裂Java阵营 微软.NET平台受益坦率的说,正如Android现在的定义所指出的,它是一个Java ME平台的分支。Android与Java ME非常相似,但是它是一个非一致性的实现。它既与Java ME不兼容,也与Java SE不兼容。事实上,它不是一个真正的Java实现。尽管它使用了Java编程语言,但是它的核心应用程序编程接口(API)和虚拟机是与Java ME或SE平台不兼容的,它是一个分支。这一点已经被Apache实验室的开发人员Stefano Mazzocchi在其博客中指出。

    那么Android对Java的这种分支作用和微软有什么关系?实际上它间接的减轻了Java平台对微软的压力,对微软来说是一个好消息,理由如下。

    首先,从市场的观点来说,Java平台最强大的地方在于其标准化和多厂商支持(例如IBM、甲骨文、SAP等等)的特点。相比之下,微软的.NET平台则通常被描述成一个专有平台,将厂商锁定在微软平台之上。这也是Java支持者十几年以来用于宣传Java的口号。

    但是,现在随着Android平台的引入,围绕在Java平台周围的这种团结性将面临挑战。对此,Sun也已经表达了它的担忧:Google的Android项目会造成数种互不兼容的Java版本。如果现在的Android平台取得成功的话,对于Java的兼容性实现是一个挑战。

    微软提供了它自己的一个优秀的移动平台——Windows Mobile和微软的.NET精简框架。的确,它是一个专有性平台,但是正因如此它也有自己的优点:具有很好的兼容性;而且对于开发富移动应用程序(RMA)来说是一个非常强大的平台。相比之下,Java ME是一个具有非常丰富功能的标准,而且也被很多厂商所支持,但是它在跨移动设备上的非兼容实现使得开发“一次编写,随处运行”的应用程序变得非常困难。如果Android移动平台成功的话,那么在移动设备上的Java对市场的掌控力将减弱。Android可能会成功,但是Java ME却会影响力变弱。如果我在WindowsMobile和.NETCF框架销售部门的话,我也会对Android的发布表示欢迎。这对微软的移动开发平台来说是一件好事情。

    Android对Java SE的影响

    如上所叙述,Android平台的推出将使Sun的Java移动平台受到影响。那么它是否会影响Java SE?有什么影响呢?或许有的人会说,毕竟Java SE被用于桌面和服务器端应用开发,它怎么会被一个移动平台所威胁?但是Android的确对Java SE有影响,这要从Sun公司对Java SE的未来定位说起。

    最近,Sun一直在致力于统一Java ME和Java SE平台。这一点从Java之父James Gosling的一段话中可以看出些许端倪:

    “我们正在尽力把所有事情汇聚到Java SE规范上。移动电话和机顶盒的应用正在增长,这种汇总可能需要花费数年的时间。”

    不要认为James Gosling的这句话仅仅是在谈论Sun去年初刚刚推出的JavaFX Mobile,它是针对整个Java SE平台的,而不是Java ME。简而言之,Sun公司没有把Java ME做大做强的打算,它们的宝押在了Java SE上。毕竟,Java ME是针对那些具有低内存和有限处理能力的“受限设备”而设计的。但是,随着技术的发展,这种情况将不再适用于移动设备。智能电话正在变得越来越强大,它开始具有更强大的处理能力和更大容量的内存。移动电话仅仅是一个简单设备的时代已经结束,移动电话正在朝着一个完整的计算平台发展。

    对于Sun公司来说,Java ME的逐步被淘汰和将Java SE扩展到移动平台的战略非常重要。因为这符合其对Java的最初定位。它将为所有计算设备创建一个单一平台。这对于实现跨计算平台的兼容性Java实现来说具有重大的意义。但是,不幸的是,Android的推出将使移动Java社区分裂成Java ME和Android两个不同的阵营。

    随着Java ME作为一个移动开发的标准平台的逐渐推出,Java SE将取代它的位置,一个支持所有计算设备的兼容性平台将变得更加重要。Java SE将成为一个支持移动开发、桌面开发和服务器端开发的标准。企业开发人员在桌面和服务器端编程中的经验将直接可以应用到移动平台中。

    不幸的是,Android的推出正在阻碍这一美好前景的发生。它告诉业界,Java不支持兼容跨计算平台。

    Java今天最强大的地方在于其一致性和普及性。如果没有了一致性,你将面临多种不同的Java版本,因此也就没有了真正的普及性。没有了普及性,就几乎很少有什么突出的特点让人们选择它而不选择.NET平台。实际上,微软.NET开始更具有吸引力,因为它可以被始终如一的实现。Java今天所具有的最大的市场财产——“一次编写,处处运行”的标准化——也将丧失殆尽,而这对微软来说当然值得庆祝的事情。


    nmtcolin 发表于:2008.01.11 14:07 ::分类: ( IT ) ::阅读:(53次) :: 评论 (0)
    ===========================================================
    Java Puzzlers & Effective Java - Book Sharing
    ===========================================================

    引言:你认为你到底有多了解Java?你是一个代码神探吗?你是否曾经花费过数天时间去追踪一个由Java或其类库的陷阱和缺陷而导致的bug?你喜欢智力测验吗?那么这本书正好适合你!

    Joshua Bloch :Google的首席工程师。凭借Effective Java 获得过Jolt大奖.之前是SUN的杰出工程师。他曾经是Java语言开发团队的核心。领导了大量的Java平台特性的设计和实现工作。同时他也是JDK1.5的项目经理。个人很欣赏他对JDK集合框架做出的贡献[在学校的时候数据结构学得不好!呵呵·]
    Neal Gafter是Google的软件工程师和Java的传道者。他之前是Sun Microsystems的资深员工工程师,在那里他领导了Java编译器的开发工作,并且通过5.0版实现了1.4版中的Java语言特性。Neal曾经是C++标准委员会的成员,他在Sun Microsystems、Microtec Research和Texas Instruments时领导了C和C++编译器的开发工作。他拥有罗彻斯特大学计算机科学的博士学位。
    网络上断断续续的看了一些人在讨论Java 解惑部分迷题。在现在有IDE的时代,很多问题其实已经不成为问题。权当闲暇时自娱的小游戏吧!~~

    如果能找到一个免费完整的版本阅读就可以省¥39了阅读地址:Java Puzzlers 送给:还没有找到免费版的朋友

    http://www.ithome.com.tw/itadm/article.php?c=39042&s=3

    Java Puzzlers(中文)

    http://www.java3z.com/cwbwebhome/article/article3/3259.jsp?id=883

    Effective Java(英文)

    http://java.sun.com/docs/books/effective/index.html


    nmtcolin 发表于:2007.11.30 15:40 ::分类: ( IT ) ::阅读:(74次) :: 评论 (0)
    ===========================================================
    开源面向对象数据库 db4o 之旅
    ===========================================================

    开源面向对象数据库 db4o 之旅

    第 1 部分: 初识 db4o
    http://www.ibm.com/developerworks/cn/java/j-lo-db4o1/

    第 2 部分: db4o 查询方式
    http://www.ibm.com/developerworks/cn/java/j-lo-db4o2/index.html

    第 3 部分: 深入db4o
    http://www.ibm.com/developerworks/cn/java/j-lo-db4o3/index.html


    nmtcolin 发表于:2007.11.27 09:39 ::分类: ( IT ) ::阅读:(53次) :: 评论 (0)
    ===========================================================
    下一道彩虹 - AppFuse 开源大杂会
    ===========================================================

    下一道彩虹 - AppFuse

    使用AppFuse 快速构建J2EE 应用

    使用AppFuse 的七个理由

    Raible's Wiki: AppFuse

    Nabble - AppFuse forum

    The CRUD framework has a controller that is framework neutral as well. Currently there is an example the uses JSF to quickly create CRUD listings and master detail forms as follows: http://code.google.com/p/krank/

    Facelets 非常适合 JSF

    http://www.ibm.com/developerworks/cn/java/j-facelets

    开源框架之集大成 AppFuse

    http://www.appfusechina.cn/html/11/t-11.html


    nmtcolin 发表于:2007.11.13 09:40 ::分类: ( IT ) ::阅读:(94次) :: 评论 (0)
    ===========================================================
    WebLogic Server-避免不必要的JSP重新编译
    ===========================================================
    摘要
      关于JavaServer页面(JSP)新闻组的最常见的一个问题与重新编译有关。不想重新编译JSP,却又不得不这样做,这是许多开发人员所面对的烦恼。本文将描述造成重新编译的场景,并从解释WebLogic JSP容器的内部操作开始,介绍每个显然“不受欢迎的”场景,并应用容器的过期检查算法(Stale Checking Algorithm)。此外,本文还将讨论控制JSP和servlet类重载的参数。对以生产模式下运行的服务器,极力推荐这么做。

    JSP容器的过期检查机制
      在WebLogic中,JSP被编译成.class文件。我们使用的术语过期检查机制(Stale Checking Mechanism)指的是用来判断某一特殊JSP .class文件是否比当前JSP文件更旧(“过期”)的逻辑。WebLogic JSP容器确保任何JSP及其相关文件只在修改后才能被重新编译。查看生成的Java代码是了解JSP容器内部操作的一个好方法。我们将采用一个JSP作为例子,使用命令行JSP编译器编译它,并查看生成的源代码。JSP编译器(WebLogic.jspc)是随标准WebLogic 服务器安装工具箱一起提供的。

    考虑一个称为foo.jsp的简单JSP页面:

    A simple JSP page

      现在使用命令行JSP编译器来编译这个JSP,指定一个称为keepgenerated的选项,顾名思义,该选项为JSP页面生成相应的Java代码,并将代码保存在磁盘上。

    java weblogic.jspc -keepgenerated -d .WEB-INFclasses foo.jsp
    
    [jspc]warning: expected file /WEB-INF/web.xml not found, 
       tag libraries cannot be resolved.
       <Jul 11, 2004 7:29:26 PM PDT> <Warning> <HTTP> 
       <BEA-101181> <Could not find web.
       xml under WEB-INF in the doc root: ..>

      编译器在作为上述选项指定的输出目录(-d)中生成.java文件及其对应的.class文件。它将生成的类文件放在称为jsp_servlet的包中,这恰巧是默认的JSP包前缀(除非在weblogic.xml中覆盖),因此,生成的Java文件可在.WEB-INFclassesjsp_servlet中找到,并且称为__foo.java。
      请注意,我们可忽略编译器发出的关于未找到web.xml文件的警告,因为此时我们并没有真正使用标签库。
      在生成代码(__foo.java)中,与我们的讨论最相关的部份就是staticIsStale()方法,如下所示。

    清单1. staticIsStale()方法

    public static boolean _staticIsStale(weblogic.servlet.jsp.StaleChecker sci) {
       if (sci.isResourceStale("/foo.jsp", 1089594167518L, "8.1.2.0", 
                                                "America/Los_Angeles")) 
         return true;
       return false;
    }
      从上面一小段代码中显然可以看出,调用weblogic.servlet.jsp.StaleChecker接口上的isResourceStale()方法是为了确定JSP是否已修改过。isResourceStale()方法的参数如下所示,这些参数是按以下顺序出现的:

    1、 要检查的资源,比如,/foo.jsp。
    2、 JSP页面的时间戳(长整型)。
    3、 WebLogic Release Build版。
    4、 当前机器的默认时区。

      JSP容器通过实现StaleChecker接口调用_staticIsStale()方法。该实现接收一个带有清单1中所示参数的回调(isResourceStale())。有了这些参数,该实现可以仅接收所有必需的信息,以推断给定资源是否过期。当资源(参数1)/foo.jsp的时间戳(参数2)比存储在已编译类文件中的时间戳还要新(参数更大)时,或者当发行版本不同时,JSP容器认为JSP.class文件“过期”。

      让我们看它的一些重要结论:

    • 因为JSP页面的时间戳保存在类文件内部,并且是在编译时计算的,所以修改类文件的时间戳不会对过期检查过程产生影响。(这是一种很常见的荒谬说法,但愿上面的例子清楚地驳斥了它。)
    • 第4个参数,也就是时区,只在以存档格式(.war)进行部署时使用。
    • WebLogic发行版本随每个服务包改变,因此需要为每个服务包重新编译所有JSP。提出这个要求是为了确保JSP类可以利用较新服务包或发行版本中的所有编译器缺陷修复或所有JSP运行时更改。

    静态包含怎样?
      人们会问的下一个合乎逻辑的问题是:即使只修改了特定JSP页面的一个静态包含文件,JSP也会重新编译这个页面吗?回答是肯定的。即使是修改了像静态包含这样的相关文件,也要重新编译整个页面(称为“编译单元”更合适)。要了解容器如何处理这种依赖性,请考虑以下包含名为baz.inc的静态包含文件的JSP。

    清单2. foo.jsp

    A simple jsp page.
    <%@ include file="baz.inc"%>

    清单3. baz.inc

    --
    Simple Static Include
    --
      为JSP编译器对foo.jsp重运行上述命令行,现在会产生一个Java文件,它包含如下所示的一小段有趣代码。如您所见,每个从属物都是用_staticIsStale()方法处理的,这样,即使修改了一个从属物(这里是baz.inc),也要重新编译整个JSP或“编译单元”。JSP容器期望根JSP页面(foo.jsp)返回一个指示它是否过期的布尔值。因此,每个生成的类文件都会生成检验其所有相关文件的代码。
    public static boolean _staticIsStale(weblogic.servlet.jsp.StaleChecker sci) {
      if (sci.isResourceStale("/foo.jsp", 1089616972487L, "8.1.2.0", "America/Los_Angeles")) 
        return true;
      if (sci.isResourceStale("/baz.inc", 1089616984268L, "8.1.2.0", "America/Los_Angeles")) 
        return true;
      return false;
    }

      总之,WebLogic JSP容器让每个JSP .class维护自己的从属物列表,并根据这个列表来存储原始JSP(及其从属物)的状态(时间戳)。容器对JSP .class调用_staticIsStale()方法,然后JSP .class回调JSP容器,并通过weblogic.servlet.jsp.StaleChecker.isResourceStale()返回判断单个资源是否过期所需的所有信息。这大大简化了过期检查任务,而且消除了在单独某个位置上为每个JSP维护时间戳的需要。

    导致重新编译JSP的场景
      我们已经分析了JSP容器执行过期检查时要考虑的一些因素。现在,让我们来看看重新编译JSP的一些常见场景:

    1. 使用构建脚本的文件副本可修改JSP的时间戳。这可导致重新编译所有JSP。
      考虑一下所有JSP都位于名为src的目录中的场景。假定某一构建脚本复制了所有JSP,并将servlet Java文件编译到构建目录中。然后该脚本在src目录之上运行weblogic.jspc,并将所有已编译的JSP放入构建目录中。在这里,将JSP复制到构建目录中很可能改变了JSP的时间戳(除非构建脚本使用cp –p/-m保留文件时间戳)。当该Web应用程序从构建目录部署到服务器上时,要重新编译所有JSP,因为JSP类是用比已部署的JSP更旧的JSP(也就是这里复制到构建目录下的JSP)来编译的。这是最常见的重新编译的情况之一,它可通过确保执行复制操作时保留了文件时间戳来避免。

    2. 修改weblogic.xml的packagePrefix参数将导致重新编译。过期检查机制负责查找特殊Web应用程序weblogic.xml文件中的packagePrefix,并为/foo.jsp搜索名为<packagePrefix>.__foo.class的类。假定我们使用weblogic.jspc 预构建所有JSP,将它们放在Web应用程序的WEB-INF/classes目录中,然后我们将该Web应用程序归档(WAR)部署到服务器上。假定我们在这个Web应用程序中有一个名为foo.jsp的JSP。在weblogic.xml中缺乏“packagePrefix”的情况下,过期检查机制将查找jsp_servlet.__foo.class类。现在假定我们修改weblogic.xml并添加一个包前缀,比如说com.bar,然后将同一WAR重新部署到服务器。此时访问foo.jsp将导致重新编译JSP,因为过期检查机制将查找名为“com.foo.__foo.class”的类。通过确保调用weblogic.jspc命令时使用了-package参数并使用了相同的包名称,可避免这个问题。

    3. 修改weblogic.xml的workingDir参数也会导致重新编译。在这种情况下,除了通常的Web应用程序类路径之外,JSP容器还将在新的“workingDir”中查找JSP类。因为在部署新版本之前,原先使用的目录中有JSP类,但JSP容器无法找到它们,因此将重新编译请求的JSP。
      注意:场景2和场景3清楚地解释了即使在修改weblogic.xml时,也需要重构建或预编译Web应用程序。在完成所有修改后部署预编译的WAR,确保不用重新编译JSP。

    4. 将预构建的WAR部属到一个更新版本的WebLogic服务器会导致重新编译所有JSP。正如描述过期检查机制那一节所解释的,在将JSP部署到不同版本的服务器时,JSP容器会重新编译所有JSP。这么做是为了确保特定版本或服务包中的所有JSP编译器/运行时增强或缺陷修复在生成的代码中可用(没有这一限制,可能会以一些类在JSP运行时引用不存在的方法而结束操作)。在理想情况下,预编译JSP 的构建脚本必须使用与正在部署的服务器使用同一版本的weblogic.jar。建议将服务器使用的所有补丁和周期性修复添加到构建脚本使用的类路径下。总之,构建和部署环境必须完全一致。这可以避免部署后遇到任何不必要重新编译的问题。

    进一步控制过期检查
      在容器执行过期检查时进行控制可以让我们调优容器,使它运行得更好,因此为JSP和servlet提供了更好的响应时间。每次过期检查都要求JSP容器转到磁盘并为那个特定的JSP重新读取最后修改时间。当调用太频繁时,该过程可导致性能下降,因为它影响JSP的响应时间。在理想情况下,需要过期检查开发期间表现得非常活跃,特别是在应用程序经常改变时。通过单击浏览器上的刷新/重载,并让JSP容器重新编译和重载新页面,可很好地测试出对特殊JSP所做的修改。但在生产模式下,同样的做法可能导致性能降低。
      以下参数的默认值最适合开发模式。建议你们在生产环境下进行部署时相应地修改这些值。

    PageCheckSeconds
      对已经编译好的JSP的每个新请求,容器都会从其配置文件(这里是weblogic.xm)检查pageCheckSeconds的值,如果上次过期检查与当前时间之间的间隔大于pageCheckSeconds,那么还要执行过期检查操作。例如,假设pageCheckSeconds的值设为10秒。对于针对foo.jsp的请求,容器执行检查操作,以了解当前时间与最后过期检查之间的间隔是否大于pageCheckSeconds。这里假定页面在10秒以前被重新编译和访问过;容器将检查该类是否过期。在此间隔中,不会对foo.jsp的任何请求进行过期检查。
      如果不是处于开发模式下,而且无需要每隔1秒(默认值)就检查一次JSP页面,那么强烈推荐您将参数值更改为-1(永远不进行过期检查)或者更改为像60秒这样的值。这避免了每次访问JSP时都调用File.lastModified()、重载JSP类和检查时间戳。

    清单4. 来自weblogic.xml的代码片段,展示了可如何设置该这个参数

    <!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 8.1//EN"
     "http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">
    <weblogic-web-app>
      <jsp-descriptor>
       <jsp-param>
         <param-name>pageCheckSeconds</param-name>
         <param-value>10</param-value>
       </jsp-param>
      </jsp-descriptor>
    </weblogic-web-app>
      请注意,对于Web应用程序中的JSP从不个别改变的生产环境,最好配置容器永不对servlets和JSP执行过期检查。

    servlet-reload-check-secs
      在开发模式中,当servlet被修改和重新编译到,比方说,迅速增长的WAR的WEB-INF/classes目录中时,我们期望从浏览器执行请求时,容器调用它的最新版本的servlet。为了处理该问题,WebLogic 的Web容器每隔servlet-reload-check-secs间隔就会检查WEB-INF/classes中是否有文件被修改过。这个参数的默认值是1秒。对于希望看到对servlet类的最新修改但又不必重新部署应用程序的开发模式而言,这是一个很好的默认值。但在进入生产之前,必须将这个值更改为-1(永不重载servlet文件)。在生产模式下,个别类不会改变,将servlet-reload-check-secs的值设为-1总是最好的选择。

    清单5. servlet-reload-check-secs值设为-1的weblogic.xml示例

    <!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 8.1//EN"
     "http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">
    
    <weblogic-web-app>
      <container-descriptor>
        <servlet-reload-check-secs>-1</servlet-reload-check-secs>
      </container-descriptor>
    </weblogic-web-app>

    JSP类加载器
      我们将通过查看WebLogic服务器如何加载JSP类来结束我们的讨论。每个JSP都是在自己的类加载器(通常称为一次性类加载器)中加载的。该类加载器是Web应用程序类加载器的子加载器,负责加载有关的JSP类及其内部类(如果有的话)。好奇的读者可能会觉得奇怪,为什么WebLogic在每个JSP自己的类加载器中加载JSP。真的需要这么复杂吗?WebLogic不能只用应用程序类加载器而使得生活更轻松吗?所有这些问题都是有根据的,而且每个寻求WebLogic类加载器天堂的人都应该问自己这些问题。为了解决这些问题,让我们设想我们的Web应用程序有几个JSP、少数servlet、一个过滤器以及几百个还包含标签处理器类的实用类。现在,假设所有这些类都被加载到单个类加载器中。如果修改单个JSP,然后单击浏览器上的重载,那么下面的事情将不得不发生:

    • JSP容器将不得不重新编译页面。
    • 将不得不丢弃用来加载较早类版本的整个Web应用程序类加载器。
    • 不得不创建一个新的Web应用程序类加载器,而且要重载和重新初始化所有servlet和JSP(包括刚才修改的那个)。

      Java不允许重用类加载器来重载类的新版本。相反,您不得不放弃类加载器并创建一个新的。基于这个原因,上面的场景非常不合时宜;即使只更改了一个类,应用服务器也不得不重载大量的类。
      现在,让我们看看WebLogic是如何实现其类加载器方案的。考虑一下前面提及的那个场景。如果我们修改JSP,并碰巧在浏览器上进行重载,那么服务器将执行以下任务:

    • JSP容器重新编译页面。
    • 它丢弃用来加载这个JSP类的旧版本的那个JSP类加载器。
    • 它创建一个将Web应用程序类加载器作为父加载器的新JSP类加载器,并为该页面提供服务。

      如您所见,只有一个JSP类必须重载,整个Web应用程序类加载器保持不动,并且不受我们对JSP所做小小改动的影响。因此,在修改单个JSP时,容器会丢弃旧的类加载器、重新编译并只重载为这个JSP生成的类。这避免了重载或抛弃整个Web应用程序类加载器。当只有某一特殊Web应用程序中的某些JSP经常改变时,这是一个很大的胜利。

    结束语
      
    有了这些关于JSP容器内部组织的知识,不但可以避免遭遇令人不快的、不必要的JSP重新编译的状况,而且还可以通过使用pageCheckSeconds和servlet-reload-checks-secs参数改进页面响应时间自身。
      Nagesh Susarla是BEA Systems的WebLogic服务器开发小组的一名高级软件工程师。他致力于为WebLogic服务器设计和实现Servlet/JSP容器,而且还是ANTLR (分析器/生成器)的超级爱好者。

    原文出处:
    http://dev2dev.bea.com/pub/a/2005/01/jsp_reloaded.html


    nmtcolin 发表于:2005.05.22 20:34 ::分类: ( IT ) ::阅读:(699次) :: 评论 (0)
    ===========================================================
    物流名词中英对照
    ===========================================================
    物流名词中英对照
    alternate tiers row pattern 交错码放 

    AGV 无人搬运车 

    anchoring 膨胀螺丝 

    AS/RS (Automatic Storage Retrieval System)自动存取机/系统自动存取仓储系统自动仓库系统assembly packaging集合包装 

    average inventory平均存货 

    battery电瓶beam橫撑,横梁 

    belt conveyor皮带式输送机(带) 

    block pattern row pattern整齐码放 

    bonded warehouse国际物流中心保税仓库 

    brick pattern砌砖式码放 

    buffer stock缓冲储备 

    cantilever shalving悬臂架 

    cargo freight货物 

    carrying搬运 

    chain conveyor链条式输送机(带) 

    charger充电机 

    cold chain system冷冻链系统 

    common carrier公共承运人 

    consolidation装运整合 

    container terminal集装箱中转站 

    contract carrier契约承运人 

    contract logistics契约物流 

    counterbalance truck平衡式电动(柴油、电动、瓦斯)堆高机 

    cycle inventory周期存货 

    delivery配送 

    depalletizer托盘拆垛机 

    devanning拆箱 

    diagonal bracing斜撑 

    dock leveller月台调整板 

    dock shelter月台门封(充气式,非充气式) 

    double-deep pallet racking双层深式重型物料钢架 

    drive-in pallet racking直入式重型物料钢架 

    dry cargo干货dunnage填充 

    electronic data interchange电子资料交换 

    EDIexport processing zone加工出口区 

    fill rate供应比率 

    floor utilization percentage地面面积利用率 

    flow(dynamic) racking重型流力架 

    flow(dynamic) rack shelving轻型(料盒、纸箱)流力架 

    forklift truck叉车four-way reach truck四向式电动堆高机 

    frame支柱组frame feet脚底板 

    frame joint柱连杆 

    freight container货物集装箱 

    general cargo一般货物 

    hand pallet truck油压拖板车 

    horizontal bracing橫撑 

    industrial door工业门 

    industrial vehicle工业车辆 

    intermodal transportation复合一贯运输 

    lashing捆扎加固 

    levelling plate垫片 

    LGV激光引导无人搬运车 

    load efficient装载效率 

    loading and unloading装卸 

    logistical utilities物流效用 

    logistics物流 

    materials handling物料搬运 

    mezzanines floor积层架 

    mini-load AS/RS料盒式自动仓库系統 

    mobile dock leveller月台桥板 

    mobile shelving移动柜 

    net unit load size净单元货载尺寸 

    operation area理货区 

    order picking truck电动拣料车 

    order picking指令拣选 

    order shipped complete订货完成率 

    packaged cargo包装货物 

    packaging包装pallet托盘,(木质)栈板 

    pallet container栈板笼架 

    pallet pool system通用托盘系统 

    pallet racking传统式重型物料钢架 

    palletization托盘化 

    palletizer托盘堆垛机 

    palletizing pattern托盘装载方式 

    pick up货物聚集picking拣货,拣选作业 

    pictorial marking for handling货运标识 

    pinwheel pattern针轮式码放 

    plan view size平面尺寸 

    plastic bin物料盒 

    plastic pallet塑胶栈板 

    platform物流容器,站台,月台 

    physical distribution model物流标准 

    powered pallet truck电动拖板车 

    powered stacker自走式电动堆高机 

    push-back pallet racking后推式重型物料钢架 

    rack货架rack notice标示牌 

    reach truck前伸式电动堆高机 

    returnable container通用容器 

    roll container笼车 

    roller conveyor滚筒式输送机(带) 

    safety pin插销 

    safety stock安全储备 

    scrubber洗地机 

    shed临时周转仓库 

    shelving轻量型物料钢架 

    shuttle car梭车 

    slat conveyor条板式输送机(带) 

    slotted-angle shelving角钢架 

    sorting分类 

    special cargo特殊货物 

    spot stock现场储备 

    stacker crane自动存取机高架吊车 

    stacking堆垛 

    stockout frequency缺货频率 

    storage存储 

    support bar跨梁 

    surface utilization percentage表面利用率 

    sweeper扫地机 

    table trolley物流台车 

    third part logistics第三方物流 

    third party logistics service provider第三方物流服务商 

    transit inventory中转存货 

    transportation运输 

    transportation package size by modular coordination运输包装系列尺寸 

    tray conveyor盘式输送机(带) 

    truck terminal卡车货运站 

    turntable转盘(变更输送方向) 

    unit load单元货载 

    unit load system单元货载系统 

    upright支柱 

    upright protctors护脚 

    value added network—VAN加值网络 

    vanning装箱 

    vertical conveyor垂直输送机 

    very narrow aisle truck窄巷道电动堆高机 

    warehouse仓库WCS (Warehouse Control System)仓储控制系统 

    WMS (Warehouse Management System)仓储管理系统  

    nmtcolin 发表于:2005.05.21 23:18 ::分类: ( IT ) ::阅读:(345次) :: 评论 (0)
    ===========================================================
    使用JMeter进行性能测试
    ===========================================================

    JMeter是Apache组织的开放源代码项目,它是功能和性能测试的工具,100%的用java实现,最新的版本是1.9.1,大家可以到http://jakarta.apache.org/jmeter/index.html下载源代码和查看相关文档。

    1 JMeter作用领域

    JMeter可以用于测试静态或者动态资源的性能(文件、Servlets、Perl脚本、java对象、数据库和查询、ftp服务器或者其他的资源)。JMeter用于模拟在服务器、网络或者其他对象上附加高负载以测试他们提供服务的受压能力,或者分析他们提供的服务在不同负载条件下的总性能情况。你可以用JMeter提供的图形化界面分析性能指标或者在高负载情况下测试服务器/脚本/对象的行为。

    http://industry.ccidnet.com/pub/article/c322_a92693_p1.html


    nmtcolin 发表于:2005.05.21 21:51 ::分类: ( IT ) ::阅读:(2345次) :: 评论 (67)
    ===========================================================
    掌握JDK1.5枚举类型
    ===========================================================
      Enum作为Sun全新引进的一个关键字,看起来很象是特殊的class, 它也可以有自己的变量,可以定义自己的方法,可以实现一个或者多个接口。 当我们在声明一个enum类型时,我们应该注意到enum类型有如下的一些特征。

      1.它不能有public的构造函数,这样做可以保证客户代码没有办法新建一个enum的实例。

      2.所有枚举值都是public , static , final的。注意这一点只是针对于枚举值,我们可以和在普通类里面定义 变量一样定义其它任何类型的非枚举变量,这些变量可以用任何你想用的修饰符。

      3.Enum默认实现了java.lang.Comparable接口。

      4.Enum覆载了了toString方法,因此我们如果调用Color.Blue.toString()默认返回字符串”Blue”.

      5.Enum提供了一个valueOf方法,这个方法和toString方法是相对应的。调用valueOf(“Blue”)将返回Color.Blue.因此我们在自己重写toString方法的时候就要注意到这一点,一把来说应该相对应地重写valueOf方法。

      6.Enum还提供了values方法,这个方法使你能够方便的遍历所有的枚举值。

      7.Enum还有一个oridinal的方法,这个方法返回枚举值在枚举类种的顺序,这个顺序根据枚举值声明的顺序而定,这里Color.Red.ordinal()返回0。

      了解了这些基本特性,我们来看看如何使用它们。

      1.遍历所有有枚举值. 知道了有values方法,我们可以轻车熟路地用ForEach循环来遍历了枚举值了。

      for (Color c: Color.values())
      System.out.println(“find value:” + c);

      2.在enum中定义方法和变量,比如我们可以为Color增加一个方法随机返回一个颜色。

      public enum Color {
      Red,
      Green,
      Blue;

      /*
      *定义一个变量表示枚举值的数目。
      *(我有点奇怪为什么sun没有给enum直接提供一个size方法).
      */
      private static int number = Color.values().length ;

      /**
      * 随机返回一个枚举值
      @return a random enum value.
      */
      public static Color getRandomColor(){
      long random = System.currentTimeMillis() % number;
      switch ((int) random){
       case 0:
        return Color.Red;
       case 1:
        return Color.Green;
       case 2:
        return Color.Blue;
       default : return Color.Red;
      }
      }
      }

      可以看出这在枚举类型里定义变量和方法和在普通类里面定义方法和变量没有什么区别。唯一要注意的只是变量和方法定义必须放在所有枚举值定义的后面,否则编译器会给出一个错误。

      3.覆载(Override)toString, valueOf方法

      前面我们已经知道enum提供了toString,valueOf等方法,很多时候我们都需要覆载默认的toString方法,那么对于enum我们怎么做呢。其实这和覆载一个普通class的toString方法没有什么区别。

      ….
      public String toString(){
      switch (this){
      case Red:
       return "Color.Red";
      case Green:
       return "Color.Green";
      case Blue:
       return "Color.Blue";
      default:
       return "Unknow Color";
      }
      }
      ….

      这时我们可以看到,此时再用前面的遍历代码打印出来的是

      Color.Red
      Color.Green
      Color.Blue

      而不是

      Red
      Green
      Blue.

      可以看到toString确实是被覆载了。一般来说在覆载toString的时候我们同时也应该覆载valueOf方法,以保持它们相互的一致性。

      4.使用构造函数

      虽然enum不可以有public的构造函数,但是我们还是可以定义private的构造函数,在enum内部使用。还是用Color这个例子。

      public enum Color {
      Red("This is Red"),
      Green("This is Green"),
      Blue("This is Blue");

      private String desc;

      Color(String desc){
      this.desc = desc;
      }

      public String getDesc(){
      return this.desc;
      }

      }

      这里我们为每一个颜色提供了一个说明信息, 然后定义了一个构造函数接受这个说明信息。

      要注意这里构造函数不能为public或者protected, 从而保证构造函数只能在内部使用,客户代码不能new一个枚举值的实例出来。这也是完全符合情理的,因为我们知道枚举值是public static final的常量而已。

      5.实现特定的接口

      我们已经知道enum可以定义变量和方法,它要实现一个接口也和普通class实现一个接口一样,这里就不作示例了。

      6.定义枚举值自己的方法。

      前面我们看到可以为enum定义一些方法,其实我们甚至可以为每一个枚举值定义方法。这样,我们前面覆载 toString的例子可以被改写成这样。

      public enum Color {
      Red {
      public String toString(){
       return "Color.Red";
      }
      },
      Green {
      public String toString(){
       return "Color.Green";
      }
      },
      Blue{
      public String toString(){
       return "Color.Blue";
      }
      };
      }

      从逻辑上来说这样比原先提供一个“全局“的toString方法要清晰一些。

      总的来说,enum作为一个全新定义的类型,是希望能够帮助程序员写出的代码更加简单易懂,个人觉得一般也不需要过多的使用enum的一些高级特性,否则就和简单易懂的初衷想违背了。

    nmtcolin 发表于:2005.05.17 22:47 ::分类: ( IT ) ::阅读:(252次) :: 评论 (0)
    ===========================================================
    JDK1.5新特性
    ===========================================================
    [JAVA漫谈]JDK1.5新特性
    JDK1.5新特性
     “JDK1.5”(开发代号猛虎)的一个重要主题就是通过新增一些特性来简化开发,这些特性包括泛型,for-each 循环,自动装包/拆包,枚举,可变参数, 静态导入 。使用这些特性有助于我们编写更加清晰,精悍,安全的代码。

    下面我们简单介绍一下这些新特性。
    1.泛型(Generic)
    C+ +通过模板技术可以指定集合的元素类型,而Java在1.5之前一直没有相对应的功能。一个集合可以放任何类型的对象,相应地从集合里面拿对象的时候我们也不得不对他们进行强制得类型转换。猛虎引入了泛型,它允许指定集合里元素的类型,这样你可以得到强类型在编译时刻进行类型检查的好处。
    Collection<String> c = new ArrayList();
    c.add(new Date());
    编译器会给出一个错误,
    add(java.lang.String) in java.util.Collection<java.lang.String> cannot be applied to (java.util.Date)


    2.For-Each循环
    For-Each循环得加入简化了集合的遍历。假设我们要遍历一个集合对其中的元素进行一些处理。典型的代码为:
    void processAll(Collection c){
        for(Iterator i=c.iterator(); i.hasNext();){
            MyClass myObject = (MyClass)i.next();
            myObject.process();
        }
    }
    使用For-Each循环,我们可以把代码改写成,
    void processAll(Collection<MyClass> c){
        for (MyClass  myObject :c)
            myObject.process();
    }
    这段代码要比上面清晰许多,并且避免了强制类型转换。


    3.自动装包/拆包(Autoboxing/unboxing)
    自动装包/拆包大大方便了基本类型数据和它们包装类地使用。
    自动装包:基本类型自动转为包装类.(int >> Integer)
    自动拆包:包装类自动转为基本类型.(Integer >> int)
    在JDK1.5之前,我们总是对集合不能存放基本类型而耿耿于怀,现在自动转换机制解决了我们的问题。
    int a = 3;
    Collection c = new ArrayList();
    c.add(a);//自动转换成Integer.

    Integer b = new Integer(2);
    c.add(b + 2);
    这里Integer先自动转换为int进行加法运算,然后int再次转换为Integer.


    4.枚举(Enums)
    JDK1.5加入了一个全新类型的“类”-枚举类型。为此JDK1.5引入了一个新关键字enmu. 我们可以这样来定义一个枚举类型。
     
    public enum Color
    {
       Red,
       White,
       Blue
    }
    然后可以这样来使用Color myColor = Color.Red.
    枚举类型还提供了两个有用的静态方法values()和valueOf(). 我们可以很方便地使用它们,例如
    for (Color c : Color.values())
                System.out.println(c);

    5.可变参数(Varargs)
    可变参数使程序员可以声明一个接受可变数目参数的方法。注意,可变参数必须是函数声明中的最后一个参数。假设我们要写一个简单的方法打印一些对象,
    util.write(obj1);
    util.write(obj1,obj2);
    util.write(obj1,obj2,obj3);

    在JDK1.5之前,我们可以用重载来实现,但是这样就需要写很多的重载函数,显得不是很有效。如果使用可变参数的话我们只需要一个函数就行了
    public void write(Object... objs) {
       for (Object obj: objs)
          System.out.println(obj);
    }
    在引入可变参数以后,Java的反射包也更加方便使用了。对于c.getMethod("test", new Object[0]).invoke(c.newInstance(), new Object[0])),
    现在我们可以这样写了c.getMethod("test").invoke(c.newInstance()),这样的代码比原来清楚了很多。 


    6.静态导入(Static Imports)
    要使用用静态成员(方法和变量)我们必须给出提供这个方法的类。使用静态导入可以使被导入类的所有静态变量和静态方法在当前类直接可见,使用这些静态成员无需再给出他们的类名。
    import static java.lang.Math.*;
    …….
    r = sin(PI * 2); //无需再写r = Math.sin(Math.PI);
    不过,过度使用这个特性也会一定程度上降低代码地可读性。

    nmtcolin 发表于:2005.05.17 22:46 ::分类: ( IT ) ::阅读:(288次) :: 评论 (0)
    ===========================================================
    Java Excel API简介
    ===========================================================

     Java Excel API简介

      Java Excel是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容、创建新的Excel文件、更新已经存在的Excel文件。使用该API非Windows操作系统也可以通过纯Java应用来处理Excel数据表。因为是使用Java编写的,所以我们在Web应用中可以通过JSP、Servlet来调用API实现对Excel数据表的访问。

      现在发布的稳定版本是V2.0,提供以下功能:

       从Excel 95、97、2000等格式的文件中读取数据;
       读取Excel公式(可以读取Excel 97以后的公式);
       生成Excel数据表(格式为Excel 97);
       支持字体、数字、日期的格式化;
       支持单元格的阴影操作,以及颜色操作;
       修改已经存在的数据表;

      现在还不支持以下功能,但不久就会提供了:

       不能够读取图表信息;
       可以读,但是不能生成公式,任何类型公式最后的计算值都可以读出;

    1、从Excel文件读取数据表

      Java Excel API既可以从本地文件系统的一个文件(.xls),也可以从输入流中读取Excel数据表。读取Excel数据表的第一步是创建Workbook(术语:工作薄),下面的代码片段举例说明了应该如何操作:(完整代码见ExcelReading.java)

    import java.io.*;
    import jxl.*;
    … … … …
    try
    {
    //构建Workbook对象, 只读Workbook对象
    //直接从本地文件创建Workbook
    //从输入流创建Workbook
    InputStream is = new FileInputStream(sourcefile);
    jxl.Workbook rwb = Workbook.getWorkbook(is);
    }
    catch (Exception e)
    {
    e.printStackTrace();
    }

      一旦创建了Workbook,我们就可以通过它来访问Excel Sheet(术语:工作表)。参考下面的代码片段:

    //获取第一张Sheet表
    Sheet rs = rwb.getSheet(0);

      我们既可能通过Sheet的名称来访问它,也可以通过下标来访问它。如果通过下标来访问的话,要注意的一点是下标从0开始,就像数组一样。

      一旦得到了Sheet,我们就可以通过它来访问Excel Cell(术语:单元格)。参考下面的代码片段:

    //获取第一行,第一列的值
    Cell c00 = rs.getCell(0, 0);
    String strc00 = c00.getContents();

    //获取第一行,第二列的值
    Cell c10 = rs.getCell(1, 0);
    String strc10 = c10.getContents();

    //获取第二行,第二列的值
    Cell c11 = rs.getCell(1, 1);
    String strc11 = c11.getContents();

    System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " + c00.getType());
    System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " + c10.getType());
    System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " + c11.getType());

      如果仅仅是取得Cell的值,我们可以方便地通过getContents()方法,它可以将任何类型的Cell值都作为一个字符串返回。示例代码中Cell(0, 0)是文本型,Cell(1, 0)是数字型,Cell(1,1)是日期型,通过getContents(),三种类型的返回值都是字符型。

      如果有需要知道Cell内容的确切类型,API也提供了一系列的方法。参考下面的代码片段:

    String strc00 = null;
    double strc10 = 0.00;
    Date strc11 = null;

    Cell c00 = rs.getCell(0, 0);
    Cell c10 = rs.getCell(1, 0);
    Cell c11 = rs.getCell(1, 1);

    if(c00.getType() == CellType.LABEL)
    {
    LabelCell labelc00 = (LabelCell)c00;
    strc00 = labelc00.getString();
    }
    if(c10.getType() == CellType.NUMBER)
    {
    NmberCell numc10 = (NumberCell)c10;
    strc10 = numc10.getvalue();
    }
    if(c11.getType() == CellType.DATE)
    {
    DateCell datec11 = (DateCell)c11;
    strc11 = datec11.getDate();
    }

    System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " + c00.getType());
    System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " + c10.getType());
    System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " + c11.getType());

      在得到Cell对象后,通过getType()方法可以获得该单元格的类型,然后与API提供的基本类型相匹配,强制转换成相应的类型,最后调用相应的取值方法getXXX(),就可以得到确定类型的值。API提供了以下基本类型,与Excel的数据格式相对应,如下图所示:

      每种类型的具体意义,请参见Java Excel API document.

      当你完成对Excel电子表格数据的处理后,一定要使用close()方法来关闭先前创建的对象,以释放读取数据表的过程中所占用的内存空间,在读取大量数据时显得尤为重要。参考如下代码片段:

    //操作完成时,关闭对象,释放占用的内存空间
    rwb.close();

      Java Excel API提供了许多访问Excel数据表的方法,在这里我只简要地介绍几个常用的方法,其它的方法请参考附录中的Java Excel API document.

    Workbook类提供的方法

      1. int getNumberOfSheets()

      获得工作薄(Workbook)中工作表(Sheet)的个数,示例:

    jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
    int sheets = rwb.getNumberOfSheets();

      2. Sheet[] getSheets()

      返回工作薄(Workbook)中工作表(Sheet)对象数组,示例:

    jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
    Sheet[] sheets = rwb.getSheets();

      3. String getVersion()

      返回正在使用的API的版本号,好像是没什么太大的作用。

    jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
    String apiVersion = rwb.getVersion();

      Sheet接口提供的方法

      1) String getName()

      获取Sheet的名称,示例:

    jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
    jxl.Sheet rs = rwb.getSheet(0);
    String sheetName = rs.getName();

      2) int getColumns()

      获取Sheet表中所包含的总列数,示例:

    jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
    jxl.Sheet rs = rwb.getSheet(0);
    int rsColumns = rs.getColumns();

      3) Cell[] getColumn(int column)

      获取某一列的所有单元格,返回的是单元格对象数组,示例:

    jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
    jxl.Sheet rs = rwb.getSheet(0);
    Cell[] cell = rs.getColumn(0);

      4) int getRows()

      获取Sheet表中所包含的总行数,示例:

    jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
    jxl.Sheet rs = rwb.getSheet(0);
    int rsRows = rs.getRows();

      5) Cell[] getRow(int row)

      获取某一行的所有单元格,返回的是单元格对象数组,示例子:

    jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
    jxl.Sheet rs = rwb.getSheet(0);
    Cell[] cell = rs.getRow(0);

      6) Cell getCell(int column, int row)

      获取指定单元格的对象引用,需要注意的是它的两个参数,第一个是列数,第二个是行数,这与通常的行、列组合有些不同。

    jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
    jxl.Sheet rs = rwb.getSheet(0);
    Cell cell = rs.getCell(0, 0);

     查看全文
    nmtcolin 发表于:2005.04.14 22:13 ::分类: ( IT ) ::阅读:(841次) :: 评论 (1)
    自我介绍
    切换风格
    新闻聚合
    博客日历
    文章归档...
    最新发表...
    博客统计...
    Blog信息
    网站链接...