??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲一区二区三区在线网站,亚洲av日韩av不卡在线观看,亚洲综合激情六月婷婷在线观看http://m.tkk7.com/terry-zj/category/4744.html<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"> </script> <script type="text/javascript"> _uacct = "UA-285051-1"; urchinTracker(); </script> zh-cnWed, 28 Feb 2007 01:07:38 GMTWed, 28 Feb 2007 01:07:38 GMT60jsp面上调用Batchhttp://m.tkk7.com/terry-zj/archive/2006/10/10/74308.htmlTerry的BlogTerry的BlogTue, 10 Oct 2006 07:53:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/10/10/74308.htmlhttp://m.tkk7.com/terry-zj/comments/74308.htmlhttp://m.tkk7.com/terry-zj/archive/2006/10/10/74308.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/74308.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/74308.html有这样一个需求,web服务器是sun Soaris5.8 原来有一个java写的Batch打包成jar文g由shell调用 现在要在面上增加一个按钮调用这个shell?br />代码如下Q?br /> struts中的Action

public  ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    
throws  Exception {

    String command 
=   " csh /home/zwfe/shell/zwfecv101.csh " ;
    Process child;
    
try  {
        child 
=  Runtime.getRuntime().exec(command);

        BufferedReader in 
=   new  BufferedReader( new  InputStreamReader(child.getInputStream()));
        String line 
=   "" ;
        
while  ((line  =  in.readLine())  !=   null ) {
            System.out.println(line);
        }
        in.close();

    } 
catch  (IOException e) {
        System.out.println(
" e.getMessage() =  "   +  e.getMessage());
        e.printStackTrace();
    }

    BatchDateDAO dao 
=   new  BatchDateDAO();
    Zwfecw002Form zwfe002form 
=  (Zwfecw002Form) form;
    zwfe002form.setBatchDate(dao.batchDate());

    
return  mapping.findForward( " screen.zwfecw002 " );
}

q里应该注意child = Runtime.getRuntime().exec(command);后需要检查这个Process 是否已经执行完毕Q否则当Action执行完返回后Process 会中断?br />


Terry的Blog 2006-10-10 15:53 发表评论
]]>
学习spring的好?/title><link>http://m.tkk7.com/terry-zj/archive/2006/07/07/57215.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Fri, 07 Jul 2006 15:48:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2006/07/07/57215.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/57215.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2006/07/07/57215.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/57215.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/57215.html</trackback:ping><description><![CDATA[http://www.javaworld.com.tw/confluence/display/opensrc/Spring<img src ="http://m.tkk7.com/terry-zj/aggbug/57215.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2006-07-07 23:48 <a href="http://m.tkk7.com/terry-zj/archive/2006/07/07/57215.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Introducing to Spring FrameworkQ中文修订版Q?转蝲http://m.tkk7.com/terry-zj/archive/2006/06/21/54163.htmlTerry的BlogTerry的BlogWed, 21 Jun 2006 03:42:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/06/21/54163.htmlhttp://m.tkk7.com/terry-zj/comments/54163.htmlhttp://m.tkk7.com/terry-zj/archive/2006/06/21/54163.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/54163.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/54163.html阅读全文

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

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

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

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

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

    public ProxySubject() { }


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

        if( realSubject == null ) {

            realSubject = new RealSubject();
        }

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

        postRequest();
    }


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

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

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

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

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

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

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


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

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

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

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

 

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

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

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

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

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

  public RealSubject(){}

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

}


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

import java.lang.reflect.InvocationHandler;

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

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

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

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

}

 

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

method.invoke(sub,args);

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

客户端:

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

public class Client {

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

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

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

}

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

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

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



Terry的Blog 2006-06-20 11:46 发表评论
]]>
如何用Java得到Excel中Formula的?/title><link>http://m.tkk7.com/terry-zj/archive/2006/05/23/47643.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Tue, 23 May 2006 06:47:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2006/05/23/47643.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/47643.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2006/05/23/47643.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/47643.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/47643.html</trackback:ping><description><![CDATA[工具1QPOI<br />POI是常用的dOffice文g的开源工兗但是在它正式发布的版本中没有提供得到Excel中Formula值的功能?br />q个POIq在开发中的功能。相关信?L<a >http://jakarta.apache.org/poi/hssf/eval.html</a><br /><br />工具2QJExcelAPI<br /><strong>Java Excel API</strong> - A Java API to read, write, and modify Excel spreadsheets<br /><a >http://jexcelapi.sourceforge.net/</a><br />目前的最新版本是2.6 <br /><br /><strong>Some Features</strong><br />* Reads data from Excel 95, 97, 2000, XP, and 2003 workbooks<br />* Reads and writes formulas (Excel 97 and later only)<br />* Generates spreadsheets in Excel 2000 format<br />* Supports font, number and date formatting<br />* Supports shading, bordering, and coloring of cells<br />* Modifies existing worksheets<br />* Is internationalized, enabling processing in almost any locale, country, language, or character encoding (formulas are currently only supported in English, French, * * Spanish, and German, but more can be added if translated)<br />* Supports copying of charts<br />* Supports insertion and copying of images into spreadsheets<br />* Supports logging with Jakarta Commons Logging, log4j, JDK 1.4 Logger, etc<br />...and much more<br /><br /> <br /><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">  1</span> <span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.io.BufferedWriter;<br /></span><span style="COLOR: #008080">  2</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.io.File;<br /></span><span style="COLOR: #008080">  3</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.io.IOException;<br /></span><span style="COLOR: #008080">  4</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.io.OutputStream;<br /></span><span style="COLOR: #008080">  5</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.io.OutputStreamWriter;<br /></span><span style="COLOR: #008080">  6</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.io.UnsupportedEncodingException;<br /></span><span style="COLOR: #008080">  7</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">  8</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.ArrayList;<br /></span><span style="COLOR: #008080">  9</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.Iterator;<br /></span><span style="COLOR: #008080"> 10</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 11</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> jxl.Cell;<br /></span><span style="COLOR: #008080"> 12</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> jxl.CellType;<br /></span><span style="COLOR: #008080"> 13</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> jxl.FormulaCell;<br /></span><span style="COLOR: #008080"> 14</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> jxl.Sheet;<br /></span><span style="COLOR: #008080"> 15</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> jxl.Workbook;<br /></span><span style="COLOR: #008080"> 16</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> jxl.biff.CellReferenceHelper;<br /></span><span style="COLOR: #008080"> 17</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> jxl.biff.formula.FormulaException;<br /></span><span style="COLOR: #008080"> 18</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 19</span> <span style="COLOR: #000000"></span><span style="COLOR: #008000">/**</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #008080"> 20</span> <span style="COLOR: #008000"> * Goes through each cell in the workbook, and if the contents of that cell is a<br /></span><span style="COLOR: #008080"> 21</span> <span style="COLOR: #008000"> * formula, it prints out the last calculated value and the formula string<br /></span><span style="COLOR: #008080"> 22</span> <span style="COLOR: #008000"> </span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 23</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Formulas {<br /></span><span style="COLOR: #008080"> 24</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 25</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> main(String[] args) {<br /></span><span style="COLOR: #008080"> 26</span> <span style="COLOR: #000000">        String file </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">jxlrwtest.xls</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080"> 27</span> <span style="COLOR: #000000">        String encoding </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">UTF8</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080"> 28</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> {<br /></span><span style="COLOR: #008080"> 29</span> <span style="COLOR: #000000">            Workbook w </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> Workbook.getWorkbook(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> File(file));<br /></span><span style="COLOR: #008080"> 30</span> <span style="COLOR: #000000">            Formulas f </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Formulas(w, System.out, encoding);<br /></span><span style="COLOR: #008080"> 31</span> <span style="COLOR: #000000">            w.close();<br /></span><span style="COLOR: #008080"> 32</span> <span style="COLOR: #000000">        } </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (Exception e) {<br /></span><span style="COLOR: #008080"> 33</span> <span style="COLOR: #000000">            e.printStackTrace();<br /></span><span style="COLOR: #008080"> 34</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080"> 35</span> <span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080"> 36</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 37</span> <span style="COLOR: #000000">    </span><span style="COLOR: #008000">/**</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #008080"> 38</span> <span style="COLOR: #008000">     * Constructor<br /></span><span style="COLOR: #008080"> 39</span> <span style="COLOR: #008000">     * <br /></span><span style="COLOR: #008080"> 40</span> <span style="COLOR: #008000">     * </span><span style="COLOR: #808080">@param</span><span style="COLOR: #008000"> w<br /></span><span style="COLOR: #008080"> 41</span> <span style="COLOR: #008000">     *            The workbook to interrogate<br /></span><span style="COLOR: #008080"> 42</span> <span style="COLOR: #008000">     * </span><span style="COLOR: #808080">@param</span><span style="COLOR: #008000"> out<br /></span><span style="COLOR: #008080"> 43</span> <span style="COLOR: #008000">     *            The output stream to which the CSV values are written<br /></span><span style="COLOR: #008080"> 44</span> <span style="COLOR: #008000">     * </span><span style="COLOR: #808080">@param</span><span style="COLOR: #008000"> encoding<br /></span><span style="COLOR: #008080"> 45</span> <span style="COLOR: #008000">     *            The encoding used by the output stream. Null or unrecognized<br /></span><span style="COLOR: #008080"> 46</span> <span style="COLOR: #008000">     *            values cause the encoding to default to UTF8<br /></span><span style="COLOR: #008080"> 47</span> <span style="COLOR: #008000">     * </span><span style="COLOR: #808080">@exception</span><span style="COLOR: #008000"> java.io.IOException<br /></span><span style="COLOR: #008080"> 48</span> <span style="COLOR: #008000">     </span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 49</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Formulas(Workbook w, OutputStream out, String encoding)<br /></span><span style="COLOR: #008080"> 50</span> <span style="COLOR: #000000">            </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> IOException {<br /></span><span style="COLOR: #008080"> 51</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (encoding </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">encoding.equals(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">UnicodeBig</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)) {<br /></span><span style="COLOR: #008080"> 52</span> <span style="COLOR: #000000">            encoding </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">UTF8</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080"> 53</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080"> 54</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 55</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> {<br /></span><span style="COLOR: #008080"> 56</span> <span style="COLOR: #000000">            OutputStreamWriter osw </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> OutputStreamWriter(out, encoding);<br /></span><span style="COLOR: #008080"> 57</span> <span style="COLOR: #000000">            BufferedWriter bw </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> BufferedWriter(osw);<br /></span><span style="COLOR: #008080"> 58</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 59</span> <span style="COLOR: #000000">            ArrayList parseErrors </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> ArrayList();<br /></span><span style="COLOR: #008080"> 60</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 61</span> <span style="COLOR: #000000">            </span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000"> (</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> sheet </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">; sheet </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000"> w.getNumberOfSheets(); sheet</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">) {<br /></span><span style="COLOR: #008080"> 62</span> <span style="COLOR: #000000">                Sheet s </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> w.getSheet(sheet);<br /></span><span style="COLOR: #008080"> 63</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 64</span> <span style="COLOR: #000000">                bw.write(s.getName());<br /></span><span style="COLOR: #008080"> 65</span> <span style="COLOR: #000000">                bw.newLine();<br /></span><span style="COLOR: #008080"> 66</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 67</span> <span style="COLOR: #000000">                Cell[] row </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080"> 68</span> <span style="COLOR: #000000">                Cell c </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br /></span><span style="COLOR: #008080"> 69</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 70</span> <span style="COLOR: #000000">                </span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000"> (</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> i </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">; i </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000"> s.getRows(); i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">) {<br /></span><span style="COLOR: #008080"> 71</span> <span style="COLOR: #000000">                    row </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> s.getRow(i);<br /></span><span style="COLOR: #008080"> 72</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 73</span> <span style="COLOR: #000000">                    </span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000"> (</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> j </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">; j </span><span style="COLOR: #000000"><</span><span style="COLOR: #000000"> row.length; j</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">) {<br /></span><span style="COLOR: #008080"> 74</span> <span style="COLOR: #000000">                        c </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> row[j];<br /></span><span style="COLOR: #008080"> 75</span> <span style="COLOR: #000000">                        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (c.getType() </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> CellType.NUMBER_FORMULA<br /></span><span style="COLOR: #008080"> 76</span> <span style="COLOR: #000000">                                </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> c.getType() </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> CellType.STRING_FORMULA<br /></span><span style="COLOR: #008080"> 77</span> <span style="COLOR: #000000">                                </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> c.getType() </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> CellType.BOOLEAN_FORMULA<br /></span><span style="COLOR: #008080"> 78</span> <span style="COLOR: #000000">                                </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> c.getType() </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> CellType.DATE_FORMULA<br /></span><span style="COLOR: #008080"> 79</span> <span style="COLOR: #000000">                                </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"> c.getType() </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> CellType.FORMULA_ERROR) {<br /></span><span style="COLOR: #008080"> 80</span> <span style="COLOR: #000000">                            FormulaCell nfc </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (FormulaCell) c;<br /></span><span style="COLOR: #008080"> 81</span> <span style="COLOR: #000000">                            StringBuffer sb </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> StringBuffer();<br /></span><span style="COLOR: #008080"> 82</span> <span style="COLOR: #000000">                            CellReferenceHelper.getCellReference(c.getColumn(),<br /></span><span style="COLOR: #008080"> 83</span> <span style="COLOR: #000000">                                    c.getRow(), sb);<br /></span><span style="COLOR: #008080"> 84</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 85</span> <span style="COLOR: #000000">                            </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> {<br /></span><span style="COLOR: #008080"> 86</span> <span style="COLOR: #000000">                                bw.write(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Formula in </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> sb.toString()<br /></span><span style="COLOR: #008080"> 87</span> <span style="COLOR: #000000">                                        </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> value:  </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> c.getContents());<br /></span><span style="COLOR: #008080"> 88</span> <span style="COLOR: #000000">                                bw.flush();<br /></span><span style="COLOR: #008080"> 89</span> <span style="COLOR: #000000">                                bw.write(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> formula: </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> nfc.getFormula());<br /></span><span style="COLOR: #008080"> 90</span> <span style="COLOR: #000000">                                bw.flush();<br /></span><span style="COLOR: #008080"> 91</span> <span style="COLOR: #000000">                                bw.newLine();<br /></span><span style="COLOR: #008080"> 92</span> <span style="COLOR: #000000">                            } </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (FormulaException e) {<br /></span><span style="COLOR: #008080"> 93</span> <span style="COLOR: #000000">                                bw.newLine();<br /></span><span style="COLOR: #008080"> 94</span> <span style="COLOR: #000000">                                parseErrors<br /></span><span style="COLOR: #008080"> 95</span> <span style="COLOR: #000000">                                        .add(s.getName() </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">'</span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">'</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> sb.toString()<br /></span><span style="COLOR: #008080"> 96</span> <span style="COLOR: #000000">                                                </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">: </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> e.getMessage());<br /></span><span style="COLOR: #008080"> 97</span> <span style="COLOR: #000000">                            }<br /></span><span style="COLOR: #008080"> 98</span> <span style="COLOR: #000000">                        }<br /></span><span style="COLOR: #008080"> 99</span> <span style="COLOR: #000000">                    }<br /></span><span style="COLOR: #008080">100</span> <span style="COLOR: #000000">                }<br /></span><span style="COLOR: #008080">101</span> <span style="COLOR: #000000">            }<br /></span><span style="COLOR: #008080">102</span> <span style="COLOR: #000000">            bw.flush();<br /></span><span style="COLOR: #008080">103</span> <span style="COLOR: #000000">            bw.close();<br /></span><span style="COLOR: #008080">104</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">105</span> <span style="COLOR: #000000">            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (parseErrors.size() </span><span style="COLOR: #000000">></span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">) {<br /></span><span style="COLOR: #008080">106</span> <span style="COLOR: #000000">                System.err.println();<br /></span><span style="COLOR: #008080">107</span> <span style="COLOR: #000000">                System.err.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">There were </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> parseErrors.size()<br /></span><span style="COLOR: #008080">108</span> <span style="COLOR: #000000">                        </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> errors</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /></span><span style="COLOR: #008080">109</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">110</span> <span style="COLOR: #000000">                Iterator i </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> parseErrors.iterator();<br /></span><span style="COLOR: #008080">111</span> <span style="COLOR: #000000">                </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000"> (i.hasNext()) {<br /></span><span style="COLOR: #008080">112</span> <span style="COLOR: #000000">                    System.err.println(i.next());<br /></span><span style="COLOR: #008080">113</span> <span style="COLOR: #000000">                }<br /></span><span style="COLOR: #008080">114</span> <span style="COLOR: #000000">            }<br /></span><span style="COLOR: #008080">115</span> <span style="COLOR: #000000">        } </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (UnsupportedEncodingException e) {<br /></span><span style="COLOR: #008080">116</span> <span style="COLOR: #000000">            System.err.println(e.toString());<br /></span><span style="COLOR: #008080">117</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">118</span> <span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080">119</span> <span style="COLOR: #000000">}</span></div><br /><br /><br />两篇中文的介l:<br /><a >http://www.chinaitpower.com/A/2005-03-03/109739.html</a><br /><a >http://www.myfaq.com.cn/A200507/2005-07-24/166992.html</a><a ></a><img src ="http://m.tkk7.com/terry-zj/aggbug/47643.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2006-05-23 14:47 <a href="http://m.tkk7.com/terry-zj/archive/2006/05/23/47643.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>日文~码与Unicode~码转换Q未完)http://m.tkk7.com/terry-zj/archive/2006/04/20/42201.htmlTerry的BlogTerry的BlogThu, 20 Apr 2006 09:45:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/04/20/42201.htmlhttp://m.tkk7.com/terry-zj/comments/42201.htmlhttp://m.tkk7.com/terry-zj/archive/2006/04/20/42201.html#Feedback1http://m.tkk7.com/terry-zj/comments/commentRss/42201.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/42201.html参考网址Q?br />日本語のUnicodeベンダ依存文字?http://www.ingrid.org/java/i18n/unicode.html



Terry的Blog 2006-04-20 17:45 发表评论
]]>
反射机制---Java的动态特性之一http://m.tkk7.com/terry-zj/archive/2006/04/14/41128.htmlTerry的BlogTerry的BlogFri, 14 Apr 2006 09:02:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/04/14/41128.htmlhttp://m.tkk7.com/terry-zj/comments/41128.htmlhttp://m.tkk7.com/terry-zj/archive/2006/04/14/41128.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/41128.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/41128.html阅读全文

Terry的Blog 2006-04-14 17:02 发表评论
]]>
What's Your PurposeQ?/title><link>http://m.tkk7.com/terry-zj/archive/2006/03/31/38430.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Fri, 31 Mar 2006 03:51:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2006/03/31/38430.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/38430.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2006/03/31/38430.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/38430.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/38430.html</trackback:ping><description><![CDATA[ <p>      今天在javaeye上看到BirdGu的一席话Q深有同感?br />      他说Q?strong>重构的目的是什么?是ؓ了满程序员对完程序的不懈q求吗?不是。重构的目的是改善程序的l构QɽE序有更好的可扩展性和灉|性,使得更容易扩充新功能的需要和应对需求变_同时使程序有更好的可L,方便其它E序员的阅读和维护?/strong>q些当然对用h有h值的Q用户ؓq些工作买单也是理所当然的。?br />      有味道的代码是从哪里来的呢? <br />人是不完的Q自然也不可能一开始就写出完美的代码?<br />另一斚wQ代码的好坏有时q无法作出绝对的判断。设计的q程是一个权衡的q程。某U条件组合下是好的,合理的权衡,另一U条件组合下会变成不好的Q不合理的权衡。因此某些条件下是好的代码,条g变化了,可能会变成不好的代码Q会需要重构了?<br />先以最单的方式实现功能Q然后再q行重构。实质就是先提供用户最需要的东西Q实现功能。再提供额外的h|是可扩展性,灉|性和可维护性。这也是从用户需要出发的。?br />      那么在最开始写E序Q甚臛_始开发以前,我们能不能,需不需要做些工作以减少以后的重构呢Q关于这个问题请看今qJolt大奖的获奖作品:Prefactoring。?br /><br />      不管做什么事情都要经常提醒自己最l的目的是什么。重构的目的不是满代码z癖Q设计framework的目的不是练习各UDesign pattern,下蝲电子书的目的不是收藏......</p> <img src ="http://m.tkk7.com/terry-zj/aggbug/38430.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2006-03-31 11:51 <a href="http://m.tkk7.com/terry-zj/archive/2006/03/31/38430.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts1.1中的Lazy ActionFormhttp://m.tkk7.com/terry-zj/archive/2006/03/01/33037.htmlTerry的BlogTerry的BlogWed, 01 Mar 2006 09:27:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/03/01/33037.htmlhttp://m.tkk7.com/terry-zj/comments/33037.htmlhttp://m.tkk7.com/terry-zj/archive/2006/03/01/33037.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/33037.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/33037.html以前我{载过一“介lstruts的新Ҏ?Lazy ActionForm?br />http://m.tkk7.com/terry-zj/archive/2005/12/09/23090.html
q篇文章里面介绍的方法大大较了ActionForm中的~码工作Q但是这个Lazy ActionForm在struts1.1的时候还没有。如果既要用struts1.1又想Lazy一下那Q(实际上struts1.1q是目前使用比较多的版本Q?br />其实量的代码就可以让普通的Form接近Lazy ActionForm的效果?br /> jsp中写Q?br />        <table align="center" border="0" width="300">
                <tr>
                    <td align="right" width="35%">
                        用户ID:
                    </td>
                    <td width="65%">
                        <html:text property="data(username)" size="20" maxlength="20" />
                    </td>
                </tr>
                <tr>
                    <td align="right">
                        密码:
                    </td>
                    <td>
                        <html:text property="data(password)" size="20" maxlength="10" />
                    </td>
                </tr>
                <tr>
                    <td>
                        &nbsp;&nbsp;&nbsp;
                    </td>
                    <td>
                        <html:button property="login" value="认" onclick="submitForm();" />
                        &nbsp;&nbsp;&nbsp;
                        <html:reset value="清空" />
                    </td>
                </tr>
            </table>

LoginAction中写Q?br />public ActionForward doAction(ActionMapping mapping,
                                  RequestContext req) {
        String forward = "menu";
        BaseForm frm = (BaseForm)req.getForm();
        System.out.println(frm.get("username"));
        System.out.println(frm.get("password"));
        // ......        
        return mapping.findForward(forward);
}

BaseForm中写Q?br />public class BaseForm extends ActionForm {
    private HashMap data = new HashMap();

    public HashMap getData() {
         return data;
    }

    public void setData(HashMap data) {
        this.data = data;
    }

    public String get(String key) {
        return (String) data.get(key);
    }

    public void set(String key, Object value) {
        data.put(key, value);
    }
}

struts-config.xml中写Q?br /> <form-beans>
    <form-bean       name="baseform"     type="com.web.system.base.BaseForm"/>
  </form-beans>



Terry的Blog 2006-03-01 17:27 发表评论
]]>
JTA知识(转蝲)http://m.tkk7.com/terry-zj/archive/2006/02/08/29931.htmlTerry的BlogTerry的BlogWed, 08 Feb 2006 07:12:00 GMThttp://m.tkk7.com/terry-zj/archive/2006/02/08/29931.htmlhttp://m.tkk7.com/terry-zj/comments/29931.htmlhttp://m.tkk7.com/terry-zj/archive/2006/02/08/29931.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/29931.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/29931.html最q项目中遇到了JTA的内容,在网上搜索了一番了解了一下基本概c?BR>
JTA知识 http://letgo.bokee.com/351051.html

JTA主要用于分布式的多个数据源的两阶D|交的事务,而JDBC的Connection提供的单个数据源的事? 后者因为只涉及C个数据源,所以其事务可以由数据库自己单独实现, 而JTA事务因ؓ其分布式和多数据源的Ҏ? 不可能由M"一?数据源实C? 因此JTA中的事务是由"事务理?实现?它会在多个数据源之间l筹事务,具体使用的技术就是所谓的"两阶D|?, 一般JTA事务都是用于EJB?因ؓEJB本n也是分布式的), 所以一般的应用服务器都有自q事务理器用来管理JTA事务,注意qƈ不表CEJB容器有管理事务的功能; 事实上也有单独的事务理器比如开源的Tyrex. 如果只用Tomcat做应用服务器的话是不能用JTA事务?

JTA主要用于分布式的多个数据源的两阶D|交的事务,而JDBC的Connection提供的单个数据源的事? 后者因为只涉及C个数据源,所以其事务可以由数据库自己单独实现, 而JTA事务因ؓ其分布式和多数据源的Ҏ? 不可能由M"一?数据源实C? 因此JTA中的事务是由"事务理?实现?它会在多个数据源之间l筹事务,具体使用的技术就是所谓的"两阶D|?, 一般JTA事务都是用于EJB?因ؓEJB本n也是分布式的), 所以一般的应用服务器都有自q事务理器用来管理JTA事务,注意qƈ不表CEJB容器有管理事务的功能; 事实上也有单独的事务理器比如开源的Tyrex. 如果只用Tomcat做应用服务器的话是不能用JTA事务?
使用 JDBC 事务界定Ӟ您可以将多个 SQL 语句l合C个事务中。JDBC 事务的一个缺Ҏ事务的范围局限于一个数据库q接。一?JDBC 事务不能跨越多个数据库。在下面Q我们将看一下如何用 JTA q行事务界定。因?JTA 不像 JDBC 那样有名Q所以我们首先做一个简介?BR>JTA ?BR>Java 事务 API(JTA) 及其同门兄弟 Java 事务服务(Java Transaction Service JTS)?J2EE q_提供了分布式事务服务。一个分布式的事务涉及一个事务管理器和一个或者多个资源管理器。一个资源管理器是Q何类型的持久性的数据存储。事务管理器负责协调所有事务参与者之间的通信?BR>JTA 事务?JDBC 事务功能更强。JDBC 事务局限ؓ一个数据库q接Q?JTA 事务可以有多个参与者。所有下?Java q_lg都可以参?JTA 事务Q?BR>JDBC q接
JDO PersistenceManager 对象
JMS 队列
JMS 主题
企业 JavaBeans
W合 J2EE q接体系l构(J2EE Connector Architecture)规范的资源适配器?BR>



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

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


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


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


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

MyApp

       MyApp.jar

       Jre

              Jre1.5.0目录下的全部内容

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

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

set path=c:\MyApp\jre\bin

然后q行Q?/FONT>

java –verbose –jar MyApp.jar

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

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

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

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

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

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

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

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


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

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

int PASCAL WinMain( HINSTANCE hInstance,

    HINSTANCE hPrevInstance,

    LPSTR lpszCmdLine,

    int nCmdShow )

{

    STARTUPINFO si;

    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );

    si.cb = sizeof(si);

    ZeroMemory( &pi, sizeof(pi) );

    // Start the child process.

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

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

            NULL,             // Process handle not inheritable.

            NULL,             // Thread handle not inheritable.

            FALSE,            // Set handle inheritance to FALSE.

            0,                // No creation flags.

            NULL,             // Use parent’s environment block.

            NULL,             // Use parent’s starting directory.

            &si,              // Pointer to STARTUPINFO structure.

            &pi )             // Pointer to PROCESS_INFORMATION structure.

    )

    {

            ErrorExit( "CreateProcess failed." );

    }

     // Wait until child process exits.

    WaitForSingleObject( pi.hProcess, INFINITE );

     // Close process and thread handles.

    CloseHandle( pi.hProcess );

    CloseHandle( pi.hThread );

}

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



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

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

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

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

下面说说Lazy ActionForm: 

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

CZ代码如下:

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

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

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

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

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

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

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

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

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

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


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

public class FileExtracter{

public static void main(String[] args) {

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

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

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

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

public class PdfExtracter{

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

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

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

}

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


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


Terry的Blog 2005-12-07 14:40 发表评论
]]>
Struts1.0.2中上传文件功能的Bughttp://m.tkk7.com/terry-zj/archive/2005/12/05/22514.htmlTerry的BlogTerry的BlogMon, 05 Dec 2005 02:47:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/05/22514.htmlhttp://m.tkk7.com/terry-zj/comments/22514.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/05/22514.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/22514.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/22514.htmlStruts1.0.2中上传文件功能的Bug(日文文g名有时不能完整表C?
 
struts1.0.2中解?multipart/form-data"型的request时没有根据request.getCharacterEncoding()的结果来解码.
当截取filename时就可能丢失一些字W?比如文g名ؓ"ソウ?xls"

RequestUtil.java 
    public static void populate(Object bean, String prefix, String suffix,
                                HttpServletRequest request)
        throws ServletException {
   
        //initialize a MultipartRequestHandler
        MultipartRequestHandler multipart = null;
        String multipartClass = (String)
        request.getAttribute(Action.MULTIPART_KEY);
        request.removeAttribute(Action.MULTIPART_KEY);
        ......
        //在这里取处理MultipartRequest的类
        multipart = (MultipartRequestHandler) Class.forName(multipartClass).newInstance();
        ......
    }
    
    // 自定义一个DiskMultipartRequestHandlerX

    ActionServlet.java
    /**
     * The MultipartRequestHandler class name used for handling
     * multipart form requests.  This is the global default value,
     * the handler can also be set in individual mapping entries
     */
    protected String multipartClass = "org.apache.struts.upload.DiskMultipartRequestHandler";
   
    public class DefaultActionServlet extends ActionServlet {
   
        protected void process(HttpServletRequest request,
                               HttpServletResponse response) {
            try {
                String contentType = request.getContentType();
                String method = request.getMethod();
               
                //if this is a multipart request, wrap the HttpServletRequest object
                //with a MultipartRequestWrapper to keep the process sub-methods
                //from failing when checking for certain request parameters
                //for command tokens and cancel button detection
                if ((contentType != null) && (contentType.startsWith("multipart/form-data"))
                    && (method.equals("POST"))) {
                    //request.getAttribute(Action.MULTIPART_KEY);
                    // 讄处理MultipartRequest的类Q也可以在struts-config.xml中设|?BR>                    request.setAttribute(Action.MULTIPART_KEY, "com.struts.upload.DiskMultipartRequestHandlerX");
                }
               

                request.setCharacterEncoding("Shift_JIS");
                super.process(request, response);
              
            } catch(Exception e) {
                log.error("encode error: ", e);
            }
        }
    }

q个问题在struts1.1中得C解决.



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

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

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

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

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

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

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

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


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

其他用法cd?/font>

Terry的Blog 2005-12-05 10:31 发表评论
]]>
HttpSessionListener的用?/title><link>http://m.tkk7.com/terry-zj/archive/2005/12/05/22508.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Mon, 05 Dec 2005 02:28:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2005/12/05/22508.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/22508.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2005/12/05/22508.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/22508.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/22508.html</trackback:ping><description><![CDATA[<font size="2">HttpSessionListener的用?<br> <br>参?http://www.javaroad.jp/servletjsp/sj_servlet9.htm<br><br>l承HttpSessionListener接口的类Q来监听Session创徏和销毁的事g<br>package jp.co.sysmex.sps.util;<br><br>import javax.servlet.*;<br>import javax.servlet.http.*;<br>import jp.co.sysmex.sps.app.web.WebAccountBean;<br><br>//①HttpSessionListener 接口的实现?br>public class CheckSessionServlet implements HttpSessionListener {<br>    private static int sesCount = 0;<br><br>    //②session生成时触发sessionCreatedҎ<br>    public void sessionCreated(HttpSessionEvent hse) {<br>        sesCount++;<br>        //ServletContext sc = hse.getSession().getServletContext();<br>        String sessid = hse.getSession().getId();<br>        <br>        System.out.println(" session Created " + sesCount);<br>        System.out.println(" session ++ " + sessid);<br>    }<br><br>    //③session无效时触发sessionDestroyedҎ<br>    //此时session中的内容q可以正常取?br>    public void sessionDestroyed(HttpSessionEvent hse) {<br>        String sessid = hse.getSession().getId();<br>        <br>        System.out.println(" session Destroyed " + sesCount);<br>        System.out.println(" session -- " + sessid);<br>        <br>        WebAccountBean account =  (WebAccountBean)(hse.getSession().getAttribute("ACCOUNT_KEY"));<br>        System.out.println(account.getEnterpriseCode());<br>        System.out.println(account.getEnterpriseFullKanjiName());<br>        <br>        sesCount--;<br>    }<br>}<br><br>web.xml文g中增加配|信?<br> <listener> <br>   <listener-class>jp.co.sysmex.sps.util.CheckSessionServlet</listener-class><br> </listener> <br><br> <br> <br><br></font><img src ="http://m.tkk7.com/terry-zj/aggbug/22508.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2005-12-05 10:28 <a href="http://m.tkk7.com/terry-zj/archive/2005/12/05/22508.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Calendar使用ҎQ{载)http://m.tkk7.com/terry-zj/archive/2005/12/05/22506.htmlTerry的BlogTerry的BlogMon, 05 Dec 2005 02:15:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/05/22506.htmlhttp://m.tkk7.com/terry-zj/comments/22506.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/05/22506.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/22506.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/22506.html明v文集之日期旉1.0

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

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

我们讨Z面的c?

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

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

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

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

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

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

public class DateExample1 {

public static void main(String[] args) {

// Get the system date/time

Date date = new Date();

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

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

}  

}

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

//1q前日期

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

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

   myDate.setTime(myTime*1000);

   String mDate=formatter.format(myDate);

//明天日期

   myDate=new java.util.Date();

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

   myDate.setTime(myTime*1000);

   mDate=formatter.format(myDate);

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

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

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

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

//加半时

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

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

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

date1.setTime(Time*1000);

String mydate1=formatter.format(date1);

//q月周求日期

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

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

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

String mydate2=formatter3.format(date2);

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

SimpleDateFormat formatter4 = new SimpleDateFormat("E");

String mydate3=formatter4.format(mydate);

 
 

 

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

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

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

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

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

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

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

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

System.out.println(date);
 

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

import java.text.SimpleDateFormat;

import java.util.Date;

public class DateExample2 {

public static void main(String[] args) {

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

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

}

}
 

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

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

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

import java.text.SimpleDateFormat;

import java.util.Date;

public class DateExample3 {

public static void main(String[] args) {

// Create a date formatter that can parse dates of

// the form MM-dd-yyyy.

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

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

String dateStringToParse = "9-29-2001";

try {

// Parse the text version of the date.

// We have to perform the parse method in a

// try-catch construct in case dateStringToParse

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

Date date = bartDateFormat.parse(dateStringToParse);

// Now send the parsed date as a long value

// to the system output.

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

}catch (Exception ex) {

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

}

}

}
 

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

import java.text.DateFormat;

import java.util.Date;

public class DateExample4 {

public static void main(String[] args) {

Date date = new Date();

DateFormat shortDateFormat = DateFormat.getDateTimeInstance(

DateFormat.SHORT, DateFormat.SHORT);

DateFormat mediumDateFormat = DateFormat.getDateTimeInstance(

DateFormat.MEDIUM, DateFormat.MEDIUM);

DateFormat longDateFormat = DateFormat.getDateTimeInstance(

DateFormat.LONG, DateFormat.LONG);

DateFormat fullDateFormat = DateFormat.getDateTimeInstance(

DateFormat.FULL, DateFormat.FULL);

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

}

}

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

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

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

比如有:

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

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

 

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

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

 

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

1. Calendar ?set() Ҏ

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

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

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

我们?Calendar 保存到文件中

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

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

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

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

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

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

它的执行l果是:

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

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

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

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

 

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

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

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

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

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

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

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

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

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

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

import java.util.GregorianCalendar;

import java.util.Date;

import java.text.DateFormat;

public class DateExample5 {

public static void main(String[] args) {

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

// Create our Gregorian Calendar.

GregorianCalendar cal = new GregorianCalendar();

// Set the date and time of our calendar

// to the system&s date and time

cal.setTime(new Date());

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

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

int friday13Counter = 0;

while (friday13Counter <= 10) {

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

// If the day of month is 13 we have

// another Friday the 13th.

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

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

}

}

}

}

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

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

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

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

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

System Date: Saturday, September 29, 2001

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

Friday, September 13, 2002

Friday, December 13, 2002

Friday, June 13, 2003

Friday, February 13, 2004

Friday, August 13, 2004

Friday, May 13, 2005

Friday, January 13, 2006

Friday, October 13, 2006

Friday, April 13, 2007

Friday, July 13, 2007

Friday, June 13, 2008

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

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

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

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

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

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

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

// q个值是false

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

cal.setTime(date);

cal.add(Calendar.MONTH,1);

cal.add(Calendar.YEAR,2000);

date = cal.getTime();

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

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

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

import java.util.*;

import java.text.*;

public class Flight {

   public static void main(String[] args) {

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

Date d = firstFlight.getTime();

DateFormat df = DateFormat.getDateInstance();

String s = df.format(d);

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

}

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

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

import java.text.*;

public class ThreeDates {

   public static void main(String[] args) {

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

GregorianCalendar gc2 = gc1;

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

gc1.add(Calendar.YEAR, 1);

//gc1 and gc2 are changed     

DateFormat df = DateFormat.getDateInstance();

Date d1 = gc1.getTime();

Date d2 = gc2.getTime();

Date d3 = gc3.getTime();

String s1 = df.format(d1);

String s2 = df.format(d2);

String s3 = df.format(d3);

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

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

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

   }

}

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

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

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


public class timeUtil {

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

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

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

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

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

      SimpleDateFormat sdf = new  SimpleDateFormat(format);

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


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

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

      SimpleDateFormat sdf = new  SimpleDateFormat(format);

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

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

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

      SimpleDateFormat sdf = new  SimpleDateFormat(format);

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


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

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

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

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

  }

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

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

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

    return cal.getTime();

  }


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

  }

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

}


Terry的Blog 2005-12-05 10:15 发表评论
]]>Hibernate的Encode的问?/title><link>http://m.tkk7.com/terry-zj/archive/2005/12/02/22193.html</link><dc:creator>Terry的Blog</dc:creator><author>Terry的Blog</author><pubDate>Fri, 02 Dec 2005 02:14:00 GMT</pubDate><guid>http://m.tkk7.com/terry-zj/archive/2005/12/02/22193.html</guid><wfw:comment>http://m.tkk7.com/terry-zj/comments/22193.html</wfw:comment><comments>http://m.tkk7.com/terry-zj/archive/2005/12/02/22193.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/terry-zj/comments/commentRss/22193.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/terry-zj/services/trackbacks/22193.html</trackback:ping><description><![CDATA[<font size="2"><span id="iaoukyw" class="postbody">        众所周知Q?span style="color: blue;">com.mysql.jdbc.Connection</span>的构造函?span style="color: blue;">public java.sql.Connection connect(String url, Properties info)</span>会在构造的时候接受一个Properties型的参数Q其中的“useUnicode”和“characterEncoding”决定了它是否在客户端和服务器端传输q程中进行EncodeQ以及如何进行Encode。详l可参见private void <span style="color: blue;">checkServerEncoding()</span>Ҏ? <br> Hibernate使用<span style="color: blue;">net.sf.hibernate.cfg.Environment</span>来存储系l的所有属性,而用<span style="color: blue;">net.sf.hibernate.cfg.Settings</span>来存储Hibernate的设定? <br> 但是<span style="color: blue;">net.sf.hibernate.cfg.Environment</span>里保存的Properties不是直接提供l?span style="color: blue;">com.mysql.jdbc.Connection</span>使用的? <br> <span style="color: blue;">net.sf.hibernate.connection.ConnectionProviderFactory</span>会在public void configure(Properties props)中用用<span style="color: blue;">public static Properties getConnectionProperties(Properties properties)</span>Ҏq行{选? <br> 带有特定前缀<span style="color: blue;">public static final String CONNECTION_PREFIX = "hibernate.connection"</span>q且没有被放?span style="color: blue;">private static final Set SPECIAL_PROPERTIES</span>里的属性才会被留下来? <br> 然后Q它?span style="color: blue;">public Connection getConnection()</span>中徏立连接的时候用的是它自己{选完之后?span style="color: blue;">private Properties connectionProps</span>属性? <br> 所以答案就很明显了? <br> 使用hibernate.cfg.xml的话Q在<session-factory>?lt;/session-factory>之间加入q么一D: <br> </span></font> <table align="center" border="0" cellpadding="3" cellspacing="1" width="90%"> <tbody><tr> <td><font size="2"><span id="cmgwk42" class="genmed"><b>java代码: </b></span></font></td> </tr> <tr> <td class="code"><div style="font-family: 'Courier New',Courier,monospace;"> <font size="2"><br>         <property name="connection.<span style="color: rgb(0, 0, 0);">useUnicode</span>"><span style="color: rgb(153, 0, 102); font-weight: bold;">true</span></property> <br>         <property name="connection.<span style="color: rgb(0, 0, 0);">characterEncoding</span>">UTF-<span style="color: rgb(0, 0, 0);">8</span></property></font></div> <font size="2"><br></font> </td> </tr> </tbody></table> <font size="2"><span id="sswuy44" class="postbody"> <br> 如果是些E序的话Q在创徏完net.sf.hibernate.cfg.Configuration、ƈ使用configure()d完配|文件之后,buildSessionFactory()之前Q执行如下代码: <br> </span></font> <table style="width: 893px; height: 147px;" align="center" border="0" cellpadding="3" cellspacing="1"> <tbody><tr> <td><font size="2"><span id="euiwskg" class="genmed"><b>java代码: </b></span></font></td> </tr> <tr> <td class="code"><div style="font-family: 'Courier New',Courier,monospace;"> <font size="2"><br>             <span style="color: rgb(170, 170, 221);">Properties</span> extraProperties = <span style="color: rgb(153, 0, 102); font-weight: bold;">new</span> <span style="color: rgb(170, 170, 221);">Properties</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">)</span>; <br>             extraProperties.<span style="color: rgb(0, 0, 0);">put</span><span style="color: rgb(0, 0, 0);">(</span>"hibernate.<span style="color: rgb(0, 0, 0);">connection</span>.<span style="color: rgb(0, 0, 0);">useUnicode</span>", "<span style="color: rgb(153, 0, 102); font-weight: bold;">true</span>"<span style="color: rgb(0, 0, 0);">)</span>; <br>             extraProperties.<span style="color: rgb(0, 0, 0);">put</span><span style="color: rgb(0, 0, 0);">(</span>"hibernate.<span style="color: rgb(0, 0, 0);">connection</span>.<span style="color: rgb(0, 0, 0);">characterEncoding</span>", "UTF-<span style="color: rgb(0, 0, 0);">8</span>"<span style="color: rgb(0, 0, 0);">)</span>; <br>             myConfiguration.<span style="color: rgb(0, 0, 0);">addProperties</span><span style="color: rgb(0, 0, 0);">(</span>extraProperties<span style="color: rgb(0, 0, 0);">)</span>;</font></div> <font size="2"><br></font> </td> </tr> </tbody></table> <font size="2"><span id="i220soc" class="postbody">OKQ万事大吉了Q?br><br>*</span><span id="qqgaqek" class="postbody">直接写在connection url后面也可?br></span><span id="m48wmsg" class="postbody">Hibernate配置文g使用xml格式吗?试试看把connection url后面?& W号用xml转义W替代试试看Q或者用<![CDATA[]]>也行?/span><br></font><img src ="http://m.tkk7.com/terry-zj/aggbug/22193.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/terry-zj/" target="_blank">Terry的Blog</a> 2005-12-02 10:14 <a href="http://m.tkk7.com/terry-zj/archive/2005/12/02/22193.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HQL的返回D怎么取得http://m.tkk7.com/terry-zj/archive/2005/12/02/22190.htmlTerry的BlogTerry的BlogFri, 02 Dec 2005 01:41:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/12/02/22190.htmlhttp://m.tkk7.com/terry-zj/comments/22190.htmlhttp://m.tkk7.com/terry-zj/archive/2005/12/02/22190.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/22190.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/22190.html 取单个字D,会返回字DListQ?

java代码: 
Query q = s.createQuery("select c.id from Cat as c");
List l = q.list();
for (i=0; i< l.size(); i++) { 
  Long id = (Long) l.get(i);
  System.out.println(id.longValue());
}

取多个字D,Hibernate把每个id和name做成一?个元素的单维数组QList实际上是一个单l数l的集合?

java代码: 
Query q = s.createQuery("select Cat.id, Cat.name, from Cat ");
List l = q.list();
for (int i=0;  i< l.size(); i++) {
  Object[] row = (Object[]) l.get(i);
  Long id = (Long) row[0];
  String name = (String) row[1]
}

在这U情况下QHQL是不会去构造PO的,q一点很Ҏ验证。JCS是对象CacheQ如果写了这LHQLQJCS里面是空的,说明Hibernate没有构造POQ如果再加上一个对象c本nQJCS里面有数据了,如下Q?

java代码: 
Query q = s.createQuery("select c.id, c.name,c from Cat as c");
List l = q.list();
for (int i=0; i< l.size(); ; i++) {
  Object[] row = (Object[]) l.get(i);
  Long id = (Long) row[0];
  String name = (String) row[1];
  Cat c = (Cat) row[2]
}


Terry的Blog 2005-12-02 09:41 发表评论
]]>Hibernate学习资源介绍http://m.tkk7.com/terry-zj/archive/2005/11/29/21820.htmlTerry的BlogTerry的BlogTue, 29 Nov 2005 05:30:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/11/29/21820.htmlhttp://m.tkk7.com/terry-zj/comments/21820.htmlhttp://m.tkk7.com/terry-zj/archive/2005/11/29/21820.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/21820.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/21820.htmlIBM的developerWorks上的Hibernate文章(重点推荐 入门最xE?
http://www-900.ibm.com/developerWorks/cn/java/l-hibernate1/
http://www-900.ibm.com/developerWorks/cn/java/l-hibernate2/

 Hibernate 3.1.2中文文档发布(重点推荐 中文官方文档)
http://www.redsaga.com/mambo/content/view/42/2/

Hibernate 入門a?日文|站)
http://www.wikiroom.com/koichik

huihoo|站的Hibernate入门文章
http://www.huihoo.com/java/hibernate/
cn-java上的Hibernate的Hello World文章
http://www.cn-java.com/target/news.php?news_id=2738
Hibernate查询语言QHQL
http://www.cn-java.com/target/news.php?news_id=2673
Hibernate对象关系
http://www.erproad.org/article/HibernateObjRela.htm
Hibernate Session和Transaction理
http://chinawebservices.net/dreamland/space/Hibernate+Session%E5%92%8CTransaction%E7%AE%A1%E7%90%86



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

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

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

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

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

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

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

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



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

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



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

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

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

net.sf.hibernate.*

该包的类基本上都是接口类和异常类

net.sf.hibernate.cache.*

JCS的实现类

net.sf.hibernate.cfg.*

配置文gdc?

net.sf.hibernate.collection.*

Hibernate集合接口实现c,例如ListQSetQBag{等QHibernate之所以要自行~写集合接口实现cLZ支持lazy loading

net.sf.hibernate.connection.*

几个数据库连接池的Provider

net.sf.hibernate.dialect.*

支持多种数据库特性,每个Dialect实现cM表一U数据库Q描qC该数据库支持的数据类型和其它特点Q例如是否有AutoIncrementQ是否有SequenceQ是否有分页sql{等

net.sf.hibernate.eg.*

Hibernate文档中用到的例子

net.sf.hibernate.engine.*

q个包的cM用比较散

net.sf.hibernate.expression.*

HQL支持的表辑ּ

net.sf.hibernate.hq.*

HQL实现

net.sf.hibernate.id.*

ID生成?

net.sf.hibernate.impl.*

最核心的包Q一些重要接口的实现c,如果SessionQSessionFactoryQQuery{?

net.sf.hibernate.jca.*

JCA支持Q把Session包装为支持JCA的接口实现类

net.sf.hibernate.jmx.*

我不懂JMXQ只知道JMX是用来编写App Server的管理程序的Q大概是JMX部分接口的实玎ͼ使得App Server可以通过JMX接口理Hibernate

net.sf.hibernate.loader.*

也是很核心的包,主要是生成sql语句?

net.sf.hibernate.lob.*

Blob和Clob支持

net.sf.hibernate.mapping.*

hbm文g的属性实?

net.sf.hibernate.metadata.*

PO的Meta实现

net.sf.hibernate.odmg.*

ODMG是一个ORM标准Q这个包是ODMG标准的实现类

net.sf.hibernate.persister.*

核心包,实现持久对象和表之间的映?

net.sf.hibernate.proxy.*

Proxy和Lazy Loading支持

net.sf.hibernate.ps.*

该包是PreparedStatment Cache

net.sf.hibernate.sql.*

生成JDBC sql语句的包

net.sf.hibernate.test.*

试c,你可以用junit来测试Hibernate

net.sf.hibernate.tool.hbm2ddl.*

用hbm配置文g生成DDL

net.sf.hibernate.transaction.*

Hibernate Transaction实现c?

net.sf.hibernate.type.*

Hibernate中定义的持久对象的属性的数据cd

net.sf.hibernate.util.*

一些工LQ作用比较散

net.sf.hibernate.xml.*

XML数据l定

Hibernate入门 - 基础配置

Hibernate配置文g可以有两U格式,一U是hibernate.propertiesQ另一U是hibernate.cfg.xml。后者稍微方便一些,当增加hbm映射文g的时候,可以直接在hibernate.cfg.xml里面增加Q不必像hibernate.properties必须在初始化代码中加入。但不管怎么_两种的配|项都是一LQ下面详l介l:

在Hibernate的src目录下有一个hibernate.properties模板Q我们不必自׃头写Q修Ҏ板就可以?IMG alt=Smile src="http://www.javaeye.com/images/smiles/icon_smile.gif" border=0>

java代码: 

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



q个配置意思是当你在Hibernate里面输入true的时候,Hibernate会{化ؓ0插入数据库,当你在Hibernate里面输入false的时候,Hibernate会{化ؓ1插入数据库,后面的YQN同理。对于某些数据库Q例如Oracle来说Q没有boolean数据cdQ就是采?代表trueQ?代表falseQ因此用这个配|在Hibernate里面直接用true/false会非常直观?

java代码: 

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



q是一个连接MySQL数据库的例子Q很直观Q不必解释,不同的数据库的连接参数模板中全部l出了?

java代码: 

hibernate.connection.pool_size 1
hibernate.statement_cache.size 25



q是Hibernate自带的连接池的配|参敎ͼ在默认情况下采用。意义很直观Q不多解释。只是提醒一点,Hibernateq个q接池是非常原始非常单的q接池,如果你在目中用Hibernate的话Q徏议你首选App Server的连接池Q次选Hibernate带的DBCPq接池。自带的q接池应该做为末选?

如果你采用DBCPq接池,除了要配|DBCPq接池以外,q需要取消掉下行的注释:

java代码: 

hibernate.connection.provider_class net.sf.hibernate.connection.DBCPConnectionProvider



其它的连接池同理?

如果采用App Server的连接池Q假设App Serverq接池的DataSource的JNDI名称?mypool"的话Q配|应该如下:

java代码: 

hibernate.dialect net.sf.hibernate.dialect.MySQLDialect
hibernate.connection.datasource mypool
hibernate.connection.provider_class net.sf.hibernate.connection.DatasourceConnectionProvider



其它参数׃必写了,因ؓ已经在App Server配置q接池的时候指定好了?

如果你不是在App Server环境中用HibernateQ例如远E客LE序Q但是你又想用App Server的数据库q接池,那么你还需要配|JNDI的参敎ͼ例如Hibernateq接q程Weblogic上的数据库连接池Q?

java代码: 

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



最后,如果你需要在EJB或者JTA中用HibernateQ需要取消下行的注释Q?

java代码: 

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



杂项配置Q?

java代码: 

hibernate.show_sql false



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

java代码: 

#hibernate.connection.isolation 4



指定数据库的隔离U别Q往往不同的数据库有自己定义的隔离U别Q未必是Hibernate的设|所能更改的Q所以也不必ȝ它了?

java代码: 

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



q两个选项非常非常非常重要Q!Q将严重影响Hibernate的CRUD性能!
java代码: 

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



Fetch Size 是设定JDBC的Statementd数据的时候每ơ从数据库中取出的记录条数。例如一ơ查?万条记录Q对于Oracle的JDBC驱动来说Q是不会1ơ性把1万条取出来的Q而只会取出Fetch Size条数Q当U录集遍历完了这些记录以后,再去数据库取Fetch Size条数据。因此大大节省了无谓的内存消耗。当然Fetch Size讄大Q读数据库的ơ数少Q速度快QFetch Size小Q读数据库的ơ数多Q速度慢。这有点像^时我们写E序写硬盘文件一P讄一个BufferQ每ơ写入BufferQ等Buffer满了以后Q一ơ写入硬盘,道理相同?

Oracle数据库的JDBC驱动默认的Fetch Size=10Q是一个非怿守的讑֮Q根据我的测试,当Fetch Size=50的时候,性能会提?倍之多,当Fetch Size=100Q性能q能l箋提升20%QFetch Sizel箋增大Q性能提升的就不显著了。因此我使用Oracle的一定要Fetch Size讑ֈ50?

不过q不是所有的数据库都支持Fetch SizeҎ,例如MySQL׃支持。MySQL像我上面说的那U最坏的情况Q他L一下就?万条记录完全取出来,内存消耗会非常非常惊hQ这个情况就没有什么好办法?Sad

Batch Size是设定对数据库进行批量删除,扚w更新和批量插入的时候的Ҏ大小Q有点相当于讄Buffer~冲区大的意思。Batch Size大Q批量操作的向数据库发送sql的次数越,速度p快。我做的一个测试结果是当Batch Size=0的时候,使用Hibernate对Oracle数据库删?万条记录需?5U,Batch Size = 50的时候,删除仅仅需?U!Q! 可见有多么大的性能提升Q很多h做Hibernate和JDBC的插入性能试会奇怪的发现Hibernate速度臛_是JDBC的两倍,是因ؓHibernate使用了Batch InsertQ而他们写的JDBC没有使用Batch的缘故。以我的l验来看QOracle数据?Batch Size = 30 的时候比较合适,50也不错,性能会l提升,50以上Q性能提升的非常微弱,反而消耗内存更加多Q就没有必要了?


java代码: 

#hibernate.jdbc.use_scrollable_resultset true



讑֮是否可以使用JDBC2.0规范的可滚动l果集,q对Hibernate的分|C有一定的作用Q默认就好了?

java代码: 

#hibernate.cglib.use_reflection_optimizer false

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

不过Q当你在调试E序q程中,特别是和proxyQlazy loading相关的应用中Q代码出错,但是出错提示信息有语焉不详,那么你可以把cglib优化xQ这样Hibernate会输出比较详l的调试信息Q帮助你debug?BR>

Hibernate的灵zL也是一把双刃剑Q用好了q别舒服,用不好,q别头疹{把我原来在jdon一个帖子{q来Q谈Cq个问题Q?

一、Hibernate是JDBC的轻量的对象封装,它是一个独立的对象持久层框Ӟ和App ServerQ和EJB没有什么必然的联系。Hibernate可以用在MJDBC可以使用的场合,例如Java应用E序的数据库讉K代码QDAO接口的实现类Q甚臛_以是BMP里面的访问数据库的代码。从q个意义上来_Hibernate和EB不是一个范畴的东西Q也不存在非此即彼的关系?

二、Hibernate是一个和JDBC密切兌的框Ӟ所以Hibernate的兼Ҏ和JDBC驱动Q和数据库都有一定的关系Q但是和使用它的JavaE序Q和App Server没有M关系Q也不存在兼Ҏ问题?

三、Hibernate不能用来直接和Entity Bean做对比,只有攑֜整个J2EE目的框架中才能比较。ƈ且即使是攑֜软g整体框架中来看,Hibernate也是做ؓJDBC的替代者出现的Q而不是Entity Bean的替代者出现的Q让我再列一ơ我已经列nơ的框架l构Q?

传统的架构:
1) Session Bean <-> Entity Bean <-> DB
Z解决性能障碍的替代架构:
2) Session Bean <-> DAO <-> JDBC <-> DB
使用Hibernate来提高上面架构的开发效率的架构Q?
3) Session Bean <-> DAO <-> Hibernate <-> DB

׃?个架构来分析Q?
1、内存消耗:采用JDBC的架?无疑是最省内存的QHibernate的架?ơ之QEB的架?最差?

2、运行效率:如果JDBC的代码写的非怼化,那么JDBC架构q行效率最高,但是实际目中,q一点几乎做不到Q这需要程序员非常_NJDBCQ运用Batch语句Q调整PreapredStatement的Batch Size和Fetch Size{参敎ͼ以及在必要的情况下采用结果集cache{等。而一般情况下E序员是做不到这一点的。因此Hibernate架构表现出最快的q行效率。EB的架构效率会差的很远?

3、开发效率:在有JBuilder的支持下以及单的目QEB架构开发效率最高,JDBCơ之QHibernate最差。但是在大的目Q特别是持久层关pL很复杂的情况下QHibernate效率高的惊hQJDBCơ之Q而EB架构很可能会p|?

4、分布式Q安全检查,集群Q负载均衡的支持
׃有SB做ؓFacadeQ?个架构没有区别?

四、EB和Hibernate学习隑ֺ在哪里?

EB的难度在哪里Q不在复杂的XML配置文g上,而在于EBq用E微不慎Q就有严重的性能障碍。所以难在你需要学习很多EJB设计模式来避开性能问题Q需要学习App Server和EB的配|来优化EB的运行效率。做EB的开发工作,E序员的大部分精力都被放CEB的性能问题上了Q反而没有更多的_֊x本n׃要投入精力去考虑的对象持久层的设计上来?

Hibernate隑֜哪里Q不在Hibernate本n的复杂,实际上Hibernate非常的简单,隑֜Hibernate太灵zM?

当你用EB来实现持久层的时候,你会发现EB实在是太W拙了,W拙CҎ没有什么可以选择的余圎ͼ所以你Ҏ׃用花费精力去设计ҎQ去qҎ的好坏,去费脑筋考虑选择哪个ҎQ因为只有唯一的方案摆在你面前Q你只能q么做,没得选择?

Hibernate相反Q它太灵zMQ相同的问题Q你臛_可以设计出十几种Ҏ来解冻I所以特别的犯难Q究竟用q个Q还是用那个呢?q些Ҏ之间到底有什么区别呢Q他们的q行原理有什么不同?q行效率哪个比较好?光是主键生成Q就有七八种Ҏ供你选择Q你为难不ؓ难?集合属性可以用SetQ可以用ListQ还可以用BagQ到底哪个效率高Q你为难不ؓ难?查询可以用iteratorQ可以用listQ哪个好Q有什么区别?你ؓ难不为难Q复合主键你可以直接在hbm里面配置Q也可以自定义CustomerTypeQ哪U比较好些?你ؓ难不为难Q对于一个表Q你可以选择单一映射一个对象,也可以映成父子对象Q还可以映射成两?:1的对象,在什么情况下用哪U方案比较好Q你为难不ؓ难?

q个列表可以一直开列下去,直到你不惛_看下Mؓ止。当你面前摆着无数的眼q݋qҎ的时候,你会觉得q福呢?q是悲哀呢?如果你是一个负责的E序员,那么你一定会仔细研究每种Ҏ的区别,每种Ҏ的效率,每种Ҏ的适用场合Q你会觉得你已经陷入q去拔不出来了。如果是用EBQ你W一U种已l做Z军_Q根本没得选择Q比如说集合属性,你只能用CollectionQ如果是HibernateQ你会在BagQList和Set之间来回犹U不决Q甚x不清楚的话,E序都没有办法写?/SPAN>



Terry的Blog 2005-11-21 18:00 发表评论
]]>
一个类在运行的时候可以知道自己所在的目录吗?http://m.tkk7.com/terry-zj/archive/2005/11/17/20286.htmlTerry的BlogTerry的BlogThu, 17 Nov 2005 09:50:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/11/17/20286.htmlhttp://m.tkk7.com/terry-zj/comments/20286.htmlhttp://m.tkk7.com/terry-zj/archive/2005/11/17/20286.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/20286.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/20286.html今天Z个Batchc配|Log4j的时候。遇C个问题:log4j.properties攑֜Batchcȝ相同目录下?BR>怎样在运行时动态的取得q个配置文g?BR>后来解决的办法很单:
Properties prop = ResourceManager.getResourceAsProperties("jp.co.swics.edinaiji.batch.log4j"); 
PropertyConfigurator.configure(prop);
log.debug("[Standard Logger is ready.]");

不过由此惛_了一个问题。一个类在运行的时候可以知道自己所在的目录吗?



Terry的Blog 2005-11-17 17:50 发表评论
]]>
使用java复制Ud文ghttp://m.tkk7.com/terry-zj/archive/2005/11/17/20258.htmlTerry的BlogTerry的BlogThu, 17 Nov 2005 08:03:00 GMThttp://m.tkk7.com/terry-zj/archive/2005/11/17/20258.htmlhttp://m.tkk7.com/terry-zj/comments/20258.htmlhttp://m.tkk7.com/terry-zj/archive/2005/11/17/20258.html#Feedback0http://m.tkk7.com/terry-zj/comments/commentRss/20258.htmlhttp://m.tkk7.com/terry-zj/services/trackbacks/20258.html     * Moving a File to Another Directory
     * @param srcFile  eg: c:\windows\abc.txt
     * @param destPath eg: c:\temp
     * @return success
     */
    public static boolean move(String srcFile, String destPath){
        // File (or directory) to be moved
        File file = new File(srcFile);
       
        // Destination directory
        File dir = new File(destPath);
       
        // Move file to new directory
        boolean success = file.renameTo(new File(dir, file.getName()));
       
        return success;
    }

Terry的Blog 2005-11-17 16:03 发表评论
]]>
վ֩ģ壺 ĻƷþ| avַ| ҹþþþþ| 99Ƶ߿| ޹˾þþƷӰ| Ʒһ| պ߹ۿƵ| þþžȫ| ޹Ʒþþѿ| ޾aa߿| ҹҹƵ| Ůwwwһ| Ʒ| ޾Ʒsuvһ88| ҹˬˬˬWWWƵʮ˽| 91޵ҹ| ѿhƬվ| þۺϾþۺ| ѹ˸Ƶվ| ̱߳ˬƵվ| 99þѾƷɫƬ| ޹þþۺ| 99Ƶ| ۺϾƷһ| ѾƷԲ߹ۿͼƬ | 97seۺ| þþþþþþþѾƷ| ѹۿһëƬ| ۺϾþó69| ҹëƬѹۿƵ| ɫѿ| պƷƵ߹ۿ| ˮĻӰ| ߹ۿİ| 456˳ӰԺ߹| ޲avĻ| ƷƵ׽Ƶ| ޾ƷAAAAƬAPP| þ޾ƷĻ| ѿٸ߳Ƭ| ھƷ99Ѹ|