2008年1月8日

MyEclipse使用技巧

程序代码自动排版:Ctrl+Shift+F,会自动把代码进行格式化的排版,非常方便
快速执行程序:Ctrl + F11第一次执行时,它会询问您执行模式,设置好后,以后只要按这个热键,它就会快速执行。

Ctrl+Shift+/ 加上段注释/**/

Ctrl+Shift+\ 取消段注释/**/

Ctrl+/ 加上行注释或取消行注释

自动汇入所需要的类别:Ctrl+Shift+O

取消自动validation:
取消方法: windows-->perferences-->myeclipse-->validation 
除开Manual下面的复选框全部选中之外,其他全部不选 
手工验证方法: 
在要验证的文件上,单击鼠标右键-->myeclipse-->run validation 

按new Remote Site,Name填 svn , URL填http://subclipse.tigris.org/update,一直next到finished为止

posted @ 2008-02-18 21:09 灵! 阅读(780) | 评论 (0)编辑 收藏

几个提高代码质量,检查代码规范的工具

1.FindBugs:查错
 目前版本0.9.1,有for eclipse的插件. 网址是http://findbugs.sourceforge.net.
 
 工作原理:检查程序生成的class的工具.
 
 界面:独立运行的提供图形界面,很友好,有bug报告.
 
 可用性:大多数提示有用,值得改
 
 插件:
  可以设置基本和检查的错误类别.
  插件保存设置有问题,我是关闭项目后台修改了配置文件,在装入才成功改了配置的.
  bug临时解决: 使用独立的findbugs设置规则,然后到C:\Documents and Settings\XXX\下找.Findbugs_prefs,然后改名覆盖eclipse project下的.fbprefs (先关闭你的project)
 
 配置没有查找功能,不过缩写能让我们很快找到某个规则
 
2.PMD:主要是查错
 目前版本3.2,有for eclipse以及其他ide的插件.网址是http://pmd.sourceforge.net
 工作原理:检查源码
 可用性:一部分值得修改,有些过于严格
 界面:独立运行的是命令行界面,命令比较简单.
 插件:可以配置规则,有一个独立的窗口显示提示,分5级提示,很友好
 
 使用:建立自己的规范,然后用于实际使用中.
 
3.CheckStyle:主要查代码规范
 目前版本4.0 beta 5,有for eclipse的插件.网址是http://checkstyle.sourceforge.net.
 工作原理:检查源码,对javadoc,书写格式等进行检查.
 规则定义:默认的规则是sun的编码规范.不过按照sun的规则则过于严格,而且每个公司也有自己的规范,和sun的不同,所以需要自定义规范. 

4.JTest 重量级的商业工具
 目前版本7.0.7,有for eclipse的插件.网址是http://www.parasoft.com/
 
 不推荐使用,不过功能强大,可以进行代码检查,可以自动生成单元测试和进行单元测试.(不过就是太慢了,而且生成的单元测试没太大用途)
 
 
 

使用感觉:

 安装上插件后,对自己的项目进行检查,发现警告太多了,有点发蒙的感觉.不过把警告看一遍,觉得都很有道理,有些也确实是一些错误.
 当然PMD和CheckStyle的规范太严格,最后还是配置了一下.
 
 通过改正警告,感觉还是不错,至少可以说自己的代码可以通过工具的检测了.
 
 当然基础代码和项目代码还是不一样的,基础代码往往比较复杂,所以和普通项目代码的规范应该有所不同.有些规则只能用在普通代码上,用在基础类代码上往往没法处理.
 
其他

代码查错推荐使用Findbugs和PMD,代码书写规范推荐使用CheckStyle进行检查.这样不仅能查出一些基本的错误,也能提高项目的代码质量.对提高自己的代码水平也是非常好.

推荐项目组建立统一的规则,代码复查的时候就使用这些工具,省时省力.

实乃居家旅行,杀人越货必备之工具也.(因为肯定有人要骂你,呵呵,也是你找"差"的工具)

posted @ 2008-01-11 09:48 灵! 阅读(800) | 评论 (0)编辑 收藏

使用Lucene进行全文检索(一)---处理索引

 Lucene是一个全文检索的引擎,目前有Java和.Net 等几个版本.Java版本的网址是http://lucene.apache.org.相关的一个项目是车东的WebLucene: http://sourceforge.net/projects/weblucene.

 首先,基于一个简单的新闻系统,要想做全文检索.新闻系统的管理等在这里不在具体提出,下面列出新闻对象的类:
 
 注:程序用会到一些工具类,不在此列出,用户可以自己实现.
 
 

  package com.jscud.website.newsinfo.bean;
  
  
  import java.sql.Timestamp;
  
  import com.jscud.util.DateTime;
  import com.jscud.util.StringFunc;
  import com.jscud.website.newsinfo.NewsConst;
  
  
  /**
   * 一个新闻.
   *
   * @author scud(飞云小侠) http://www.jscud.com
   * 
   */
  public class NewsItem
  {
  
      private int nid; //新闻编号
  
      private int cid; //类别编号
  
      private String title;//标题
  
      private int showtype; //内容类型:目前支持url和html
  
      private String content;//内容
  
      private String url;//对应网址,如果内容类型是url的话
  
      private Timestamp addtime; //增加时间
  
      private int click; //点击数
     
      //对应的get,set函数,较多不在列出,可以使用工具生成
      //......
  
     
      /**
       * 按照类型格式化
       */
      public String getShowContent()
      {
          String sRes = content;
          if(showtype == NewsConst.ShowType_HTML)
          {
          }  
          return sRes;
      }
     
      public String getTarget()
      {
          if(showtype == NewsConst.ShowType_URL)
          {
              return "_blank";
          }
          else
              return "";       
      }
     
      /**
       * 静态Html文件的路径及其名字
       */
      public String getHtmlFileName()
      {
          int nYear = DateTime.getYear_Date(getAddtime());
          int nMonth =  DateTime.getMonth_Date(getAddtime());
             
          String sGeneFileName =
             "/news/" + getCid() + "/" + nYear + "/" + nMonth +"/" + getNid() + ".htm";
         
          return sGeneFileName;
      }
     
      /**
       * 静态Html文件的路径
       */
      public String getHtmlFilePath()
      {
          int nYear = DateTime.getYear_Date(getAddtime());
          int nMonth =  DateTime.getMonth_Date(getAddtime());
             
          String sGeneFilePath =
             getCid() + "_" + nYear + "_" + nMonth;
         
          return sGeneFilePath;
      }     
  } 


 
 可以看到,我们需要对标题和内容进行检索,为了这个目的,我们首先需要来研究一下lucene.
 
 在Lucene中,如果要进行全文检索,必须要先建立索引然后才能进行检索,当然实际工作中还会有删除索引和更新索引的工作.
 
 在此之前,介绍一个最基本的类(摘抄自http://www.blogjava.net/cap/archive/2005/07/17/7849.html):
 
 Analyzer 文件的分析器(听起来别扭,还是叫Analyzer好了)的抽象,这个类用来处理分词(对中文尤其重要,转换大小写(Computer->computer,实现查询大小写无关),转换词根(computers->computer),消除stop words等,还负责把其他格式文档转换为纯文本等.
 
 在lucene中,一般会使用StandardAnalyzer来分析内容,它支持中文等多字节语言,当然可以自己实现特殊的解析器.StandardAnalyzer目前对中文的处理是按照单字来处理的,这是最简单的办法,但是也有缺点,会组合出一些没有意义的结果来. 
 
 
 首先我们来了解建立索引,建立索引包含2种情况,一种是给一条新闻建立索引,另外的情况是在开始或者一定的时间给批量的新闻建立索引,所以为了通用,我们写一个通用的建立索引的函数:
 
 (一般一类的索引都放在一个目录下,这个配置可以在函数中定义,也可以写在配置文件中,通过参数传递给函数.)

    /**
     * 生成索引.
     *
     * @param doc 目标文档
     * @param indexDir 索引目录
     */
    public static void makeIndex(Document doc, String indexDir)
    {
        List aList = new ArrayList();
        aList.add(doc);
        makeIndex(aList, indexDir);
    }
 
    /**
     * 生成索引.
     *
     * @param doc 生成的document.
     * @param indexDir 索引目录
     */
    public static void makeIndex(List docs, String indexDir)
    {
        if (null == docs)
        {
            return;
        }       
        boolean indexExist = indexExist(indexDir);

        IndexWriter writer = null;
        try
        {
            StandardAnalyzer analyzer = new StandardAnalyzer();
           
            //如果索引存在,就追加.如果不存在,就建立新的索引.lucene要是自动判决就好了.
            if(indexExist)
            {
                writer = new IndexWriter(indexDir, analyzer, false);
            }
            else
            {
                writer = new IndexWriter(indexDir, analyzer, true);
            }

            //添加一条文档
            for (int i = 0; i < docs.size(); i++)
            {
                Document doc = (Document) docs.get(i);
                if (null != doc)
                {
                    writer.addDocument(doc);
                }
            }

            //索引完成后的处理
            writer.optimize();
        }
        catch (IOException e)
        {
            LogMan.warn("Error in Make Index", e);
        }
        finally
        {
            try
            {
                if (null != writer)
                {
                    writer.close();
                }
            }
            catch (IOException e)
            {
                LogMan.warn("Close writer Error");
            }
        }
    }



 可以看到,建立索引用到类是IndexWrite,它可以新建索引或者追加索引,但是需要自己判断.判断是通过IndexReader这个类来实现的,函数如下:

 

  /**
     * 检查索引是否存在.
     * @param indexDir
     * @return
     */
    public static boolean indexExist(String indexDir)
    {
        return IndexReader.indexExists(indexDir);
    }
 


 如果每次都是新建索引的话,会把原来的记录删除,我在使用的时候一开始就没有注意到,后来观察了一下索引文件,才发现这个问题.
 
 
 还可以看到,建立索引是给用户的Document对象建立索引,Document表示索引中的一条文档记录.那么我们如何建立一个文档那?以新闻系统为例,代码如下:
 

     /**
      * 生成新闻的Document.
      *
      * @param aNews 一条新闻.
      *
      * @return lucene的文档对象
      */
     public static Document makeNewsSearchDocument(NewsItem aNews)
     {
         Document doc = new Document();
 
         doc.add(Field.Keyword("nid", String.valueOf(aNews.getNid())));
 
         doc.add(Field.Text("title", aNews.getTitle()));
        
         //对Html进行解析,如果不是html,则不需要解析.或者根据格式调用自己的解析方法
         String content = parseHtmlContent(aNews.getContent());
 
         doc.add(Field.UnStored("content", content));
 
         doc.add(Field.Keyword("addtime", aNews.getAddtime()));
 
         //可以加入其他的内容:例如新闻的评论等
         doc.add(Field.UnStored("other", ""));
 
         //访问url
         String newsUrl = "/srun/news/viewhtml/" + aNews.getHtmlFilePath() + "/" + aNews.getNid()
                         + ".htm";
 
         doc.add(Field.UnIndexed("visiturl", newsUrl));
 
         return doc;
     }


 
 通过上面的代码,我们把一条新闻转换为lucene的Document对象,从而进行索引工作.在上面的代码中,我们又引入了lucene中的Field(字段)类.Document文档就像数据库中的一条记录,它有很多字段,每个字段是一个Field对象.
 
 从别的文章摘抄一段关于Field的说明(摘抄自http://www.blogjava.net/cap/archive/2005/07/17/7849.html):
 [quote]
    类型                               Analyzed Indexed Stored 说明
    Field.Keyword(String,String/Date)  N Y Y                    这个Field用来储存会直接用来检索的比如(编号,姓名,日期等)
    Field.UnIndexed(String,String)     N N Y                    不会用来检索的信息,但是检索后需要显示的,比如,硬件序列号,文档的url地址
    Field.UnStored(String,String)      Y Y N                    大段文本内容,会用来检索,但是检索后不需要从index中取内容,可以根据url去load真实的内容
    Field.Text(String,String)          Y Y Y                    检索,获取都需要的内容,直接放index中,不过这样会增大index
    Field.Text(String,Reader)          Y Y N                    如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略.
 [/quote]
 
 我们可以看到新闻的编号是直接用来检索的,所以是Keyword类型的字段,新闻的标题是需要检索和显示用的,所以是Text类型,而新闻的内容因为是Html格式的,所以在经过解析器的处理用,使用的UnStored的格式,而新闻的时间是直接用来检索的,所以是KeyWord类型.为了在新闻索引后用户可以访问到完整的新闻页面,还设置了一个UnIndexed类型的访问地址字段.
 
 (对Html进行解析的处理稍后在进行讲解)
 
 为一条新闻建立索引需要两个步骤:获取Document,传给makeIndex函数,代码如下:

    public static void makeNewsInfoIndex(NewsItem aNews)
    {
        if (null == aNews)
        {
            return;
        }
        makeIndex(makeNewsSearchDocument(aNews),indexDir);
    }  


 

 
 
 建立索引的工作就进行完了,只要在增加新闻后调用 makeNewsInfoIndex(newsitem); 就可以建立索引了.
 
 如果需要删除新闻,那么也要删除对应的索引,删除索引是通过IndexReader类来完成的:
 


    /**
     * 删除索引.
     * @param aTerm 索引删除条件
     * @param indexDir 索引目录
     */
    public static void deleteIndex(Term aTerm, String indexDir)
    {
        List aList = new ArrayList();
        aList.add(aTerm);
        deleteIndex(aList, indexDir);
    }

    /**
     * 删除索引.
     *
     * @param aTerm 索引删除条件.
     * @param indexDir 索引目录
     * 
     */
    public static void deleteIndex(List terms, String indexDir)
    {
        if (null == terms)
        {
            return;
        }
       
        if(!indexExist(indexDir)) { return; }

        IndexReader reader = null;
        try
        {
            reader = IndexReader.open(indexDir);
            for (int i = 0; i < terms.size(); i++)
            {
                Term aTerm = (Term) terms.get(i);
                if (null != aTerm)
                {
                    reader.delete(aTerm);
                }
            }
        }
        catch (IOException e)
        {
            LogMan.warn("Error in Delete Index", e);
        }
        finally
        {
            try
            {
                if (null != reader)
                {
                    reader.close();
                }
            }
            catch (IOException e)
            {
                LogMan.warn("Close reader Error");
            }
        }
    } 


 
 删除索引需要一个条件,类似数据库中的字段条件,例如删除一条新闻的代码如下:
 

     public static void deleteNewsInfoIndex(int nid)
     {
         Term aTerm = new Term("nid", String.valueOf(nid));
         deleteIndex(aTerm,indexDir);
     }   




 通过新闻的ID,就可以删除一条新闻.
 
 如果需要更新新闻,如何更新索引哪? 更新索引需要先删除索引然后新建索引2个步骤,其实就是把上面的代码组合起来,例如更新一条新闻:

     public static void updateNewsInfoIndex(NewsItem aNews)
     {
         if (null == aNews)
         {
             return;
         }
         deleteNewsInfoIndex(aNews.getNid());
         makeNewsInfoIndex(aNews);
     } 
 



 
 至此,索引的建立更新和删除就告一段落了.其中批量更新新闻的代码如下:
 (批量更新应该在访问人数少或者后台程序在夜间执行)

    public static void makeAllNewsInfoIndex(List newsList)
    {
        List terms = new ArrayList();
        List docs = new ArrayList();

        for (int i = 0; i < newsList.size(); i++)
        {
            NewsItem aitem = (NewsItem) newsList.get(i);
            if (null != aitem)
            {
                terms.add(new Term("nid", String.valueOf(aitem.getNid())));
                docs.add(makeNewsSearchDocument(aitem));
            }
        }

        deleteIndex(terms,indexDir);
        makeIndex(docs,indexDir);
    } 

posted @ 2008-01-11 09:47 灵! 阅读(288) | 评论 (0)编辑 收藏

分析/解析Html页面:HTML Parser的试用

最近在研究lucene的全文检索,在很多地方需要解析或者说分析Html内容或者Html页面,Lucene本身的演示程序中也提供了一个Html Parser,但是不是纯Java的解决方案.于是到处搜索,在网上找到了一个"HTMLParser".

网址是: http://htmlparser.sourceforge.net ,当前版本为1.5.

下载下来,试用一番,感觉不错,完全能满足lucene解析Html的需求.

过几天贴出lucene进行全文检索的代码.(检索本站的文章等).

试用代码如下,供大家参考:

package com.jscud.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;

import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.filters.OrFilter;
import org.htmlparser.nodes.TextNode;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.HtmlPage;
import org.htmlparser.visitors.TextExtractingVisitor;

import com.jscud.util.LogMan; //一个日志记录类

/**
 * 演示了Html Parse的应用.
 *
 * @author scud http://www.jscud.com
 */

public class ParseHtmlTest
{

    public static void main(String[] args) throws Exception
    {
        String aFile = "e:/jscud/temp/test.htm";

        String content = readTextFile(aFile, "GBK");

        test1(content);
        System.out.println("====================================");

        test2(content);
        System.out.println("====================================");

        test3(content);
        System.out.println("====================================");

        test4(content);
        System.out.println("====================================");

        test5(aFile);
        System.out.println("====================================");

        //访问外部资源,相对慢
        test5("http://www.jscud.com");
        System.out.println("====================================");

    }

    /**
     * 读取文件的方式来分析内容.
     * filePath也可以是一个Url.
     *
     * @param resource 文件/Url
     */
    public static void test5(String resource) throws Exception
    {
        Parser myParser = new Parser(resource);

        //设置编码
        myParser.setEncoding("GBK");

        HtmlPage visitor = new HtmlPage(myParser);

        myParser.visitAllNodesWith(visitor);

        String textInPage = visitor.getTitle();

        System.out.println(textInPage);
    }

    /**
     * 按页面方式处理.对一个标准的Html页面,推荐使用此种方式.
     */
    public static void test4(String content) throws Exception
    {
        Parser myParser;
        myParser = Parser.createParser(content, "GBK");

        HtmlPage visitor = new HtmlPage(myParser);

        myParser.visitAllNodesWith(visitor);

        String textInPage = visitor.getTitle();

        System.out.println(textInPage);
    }

    /**
     * 利用Visitor模式解析html页面.
     *
     * 小优点:翻译了<>等符号
     * 缺点:好多空格,无法提取link
     *  
     */
    public static void test3(String content) throws Exception
    {
        Parser myParser;
        myParser = Parser.createParser(content, "GBK");

        TextExtractingVisitor visitor = new TextExtractingVisitor();

        myParser.visitAllNodesWith(visitor);

        String textInPage = visitor.getExtractedText();

        System.out.println(textInPage);
    }

    /**
     * 得到普通文本和链接的内容.
     *
     * 使用了过滤条件.
     */
    public static void test2(String content) throws ParserException
    {
        Parser myParser;
        NodeList nodeList = null;

        myParser = Parser.createParser(content, "GBK");

        NodeFilter textFilter = new NodeClassFilter(TextNode.class);
        NodeFilter linkFilter = new NodeClassFilter(LinkTag.class);

        //暂时不处理 meta
        //NodeFilter metaFilter = new NodeClassFilter(MetaTag.class);

        OrFilter lastFilter = new OrFilter();
        lastFilter.setPredicates(new NodeFilter[] { textFilter, linkFilter });

        nodeList = myParser.parse(lastFilter);

        Node[] nodes = nodeList.toNodeArray();

        for (int i = 0; i < nodes.length; i++)
        {
            Node anode = (Node) nodes[i];

            String line = "";
            if (anode instanceof TextNode)
            {
                TextNode textnode = (TextNode) anode;
                //line = textnode.toPlainTextString().trim();
                line = textnode.getText();
            }
            else if (anode instanceof LinkTag)
            {
                LinkTag linknode = (LinkTag) anode;

                line = linknode.getLink();
                //@todo 过滤jsp标签:可以自己实现这个函数
                //line = StringFunc.replace(line, "<%.*%>", "");
            }

            if (isTrimEmpty(line))
                continue;

            System.out.println(line);
        }
    }

    /**
     * 解析普通文本节点.
     *
     * @param content
     * @throws ParserException
     */
    public static void test1(String content) throws ParserException
    {
        Parser myParser;
        Node[] nodes = null;

        myParser = Parser.createParser(content, null);

        nodes = myParser.extractAllNodesThatAre(TextNode.class); //exception could be thrown here

        for (int i = 0; i < nodes.length; i++)
        {
            TextNode textnode = (TextNode) nodes[i];
            String line = textnode.toPlainTextString().trim();
            if (line.equals(""))
                continue;
            System.out.println(line);
        }

    }

    /**
     * 读取一个文件到字符串里.
     *
     * @param sFileName  文件名
     * @param sEncode   String
     * @return 文件内容
     */
    public static String readTextFile(String sFileName, String sEncode)
    {
        StringBuffer sbStr = new StringBuffer();

        try
        {
            File ff = new File(sFileName);
            InputStreamReader read = new InputStreamReader(new FileInputStream(ff),
                    sEncode);
            BufferedReader ins = new BufferedReader(read);

            String dataLine = "";
            while (null != (dataLine = ins.readLine()))
            {
                sbStr.append(dataLine);
                sbStr.append("\r\n");
            }

            ins.close();
        }
        catch (Exception e)
        {
            LogMan.error("read Text File Error", e);
        }

        return sbStr.toString();
    }

    /**
     * 去掉左右空格后字符串是否为空
     * @param astr String
     * @return boolean
     */
    public static boolean isTrimEmpty(String astr)
    {
        if ((null == astr) || (astr.length() == 0))
        {
            return true;
        }
        if (isBlank(astr.trim()))
        {
            return true;
        }
        return false;
    }

    /**
     * 字符串是否为空:null或者长度为0.
     * @param astr 源字符串.
     * @return boolean
     */
    public static boolean isBlank(String astr)
    {
        if ((null == astr) || (astr.length() == 0))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

}

 


posted @ 2008-01-11 09:45 灵! 阅读(274) | 评论 (0)编辑 收藏

JavaEE事务扫盲笔记之一扫扫到尾

1.资料

2.本地事务与分布式事务

  • 本地事务
    完全依赖于DB、JMS自身,,如直接调用jdbc中的conn.commit();这里没应用服务器什么事,所以也不支持多数据源的全局事务。
  • 分布式事务
    在JavaEE世界的事务在JTA、JTS规范和XA Sources之上实现。
    JTA是用户编程接口,JTS是服务器底层服务,两者一般由应用服务器自带实现,而atomikos 、JOTM 和JBoss Transaction 是专门搞局抢生意的。
    XA Sources其实先于JavaEE而存在,JDBC driver必须有javax.sql.XADataSource接口的实现类,否则所谓二阶段提交就是个伪能力。
    JavaEE除了支持JDBC和JMS外,还引入了JCA模型。JCA可以说是目前唯一可移植的插入JavaEE事务的资源模型,因此像JDO这类框架/Server就是靠乖乖出自己的JCA连接器来参与JavaEE事务的。

3.编程式模型

    手工调用jdbc的connection事务方法和使用JTA接口都属于编程式开发,在EJB中叫BMT(Bean管理事务)。
    JTA最重要的接口就是UserTransaction和它的六个方法-begin,commit,rollback,getStatus,setRollbackonly,setTransactionTimeout。
    程序需要UserTransaction时可以从JNDI领取,不过JNDI名随应用服务器不同而不同。EJB3里可以直接用个@Resource注入。

4.宣告式模型

    前面都是铺垫,这个才是主打的事务模型,如EJB的CMT(容器管理事务)和Sprin。

    其中EJB2.0,Spring1.0在部署描述符和applicationContext.xml中定义,而EJB3.0和Spring2.0则采用annotation。

4.1 事务类型

     这里JavaEE与Spring的定义基本相同:

  • Required:如果Context中有事务就加入,没有就自己创建一个。(最常用设置)
  • Mandatory:永远加入一个事务。如果当前Context没有事务,抛出异常。(那些不打算自己负责rollback事务的方法,必须加入到别人的事务,由别人来控制rollback)
  • RequiresNew:永远新建一个事务。(那些不管别人如何,自己必须提交事务的方法,比如审计信息是一定要写的)
  • Supports:如果有事务就加入,如果没有就算了。永远不会创建新事务。(一般用于只读方法,不会主动创建事务,但如果当前有事务就加入,以读到事务中未提交的数据)
  • NotSupported:永远不使用事务,如果当前有事务,挂起事务。(那些有可能抛异常但异常并不影响全局的方法)
  • Never:不能在有当前事务的情况下调用本方法。(生人勿近?)

      可见,Required是默认的设置,Supports是只读方法的最佳选择。

4.2 事务隔离级别

  • ReadUncommited:本事务可以看到另一事务未提交的数据。脏读。
  • ReadCommited:本事务只可以看到另一事务已提交的数据。不可重复读。
  • RepeatableRead:可重复读。在一个事务内,第一次读到的数据,在本事务没有提交前,无论另一个事务如何提交数据,本事务读到的数据都是不变的。
  • Serializable:串行化,同时只有一个事务能读相同的数据。

    级别越低越安全效率也越低。隔离级别需要相关资源支持,如重复读在Oracle里会降级为ReadCommited。Spring里默认的Default级别完全看数据源的脸色行事。

4.3 关于Rollback

    EJB里,想rollback只能sessionContext.setRollbackOnly(),或者抛出EJBException。(EJB3还可以annotation设置某些自定义Exception可以触发rollback)

    在Spring里,同样只会rollback unchecked exception(RuntimeExcption及子类),而checked exception(Exception及子类)是不会rollback的,除非你特别声明。

   @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW,rollbackFor = {MyException1.class,MyException2.class})

    因此所有在service层方法中用throws定义的Exception,都必须在事务定义中进行rollback设定。(请勿善忘)

    所有在service层方法中c被atch处理了的异常,又希望容器辅助rollback的话,必须重抛一个预定义的RuntimeException的子类。(请勿回望)

4.4 关于Spring

    Spring不希望编程式事务管理。
    Spring也不希望使用EJB CMT--CMT依赖于EJB而无法用于POJO,依赖于JTA全局事务对单数据源场景造成了浪费,而且rollback机制比较麻烦(必须为EJBException或手工setRollbackOnly())。
    因此Spring通过AOP实现了对POJO的整套宣告式事务体系;对jdbc,hibernate,jpa,jms等local数据源和JTA实现了统一的事务管理机制,而且支持本地资源与JTA在配置文件级的切换,而且改进了rollback机制。

   1)一个本地事务管理器:

<bean id="transactionManager"  class="org.springframework.orm.jpa.JpaTransactionManager">  <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean>

   2)Spring就会把请求都转发到应用服务器的JTA对象上(注意此时数据源也需要改为用JNDI从应用服务器获取)。

<bean id="myTxManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

   3)应用服务器专有的类型的JTA事务管理器:

<bean id="myTxManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager"/>

posted @ 2008-01-11 09:44 灵! 阅读(276) | 评论 (0)编辑 收藏

包装你的Session,使Session对象化

 在Web开发中,经常需要使用Session来保存特定用户的信息,在我们的程序中很多地方散落着类似下面的语句:
 int userAge = (int)this.Session["UserAge"];
    
    我们知道,Session中存放的是键值对,键是string类型的,如果我们一不小心把上面的语句写成这样:
  int userAge = (int)this.Session["UseAge"];
    编译期不会发现这个错误,但运行时一定会抛出异常,这是在程序中直接操作Session可能引发的问题之一。另外,每次获取userAge的时候都要写代码进行强制转换,感觉很繁琐。我们需要一个解决方案来解决这些问题。我的做法是引入一个Session的包装,使之对象化、强类型化。就像接下来的例子一样:
public class SessionHelper
{
    
private HttpSessionState curSession;

    
public SessionHelper(HttpSessionState session)
    {
        
this.curSession = session;
    }

    
public static SessionHelper CreateInstance(HttpSessionState session)
    {        
        
return new SessionHelper(session);
    }


    
public string UserID
    {
        
get
        {
            
return this.curSession["UserID"].ToString();
        }
        
set
        {
            
this.curSession["UserID"= value ;
        }
    }

    
public int UserAge
    {
        
get
        {
            
return (int)this.curSession["UserAge"];
        }
        
set
        {
            
this.curSession["UserAge"= value ;
        }
    }

    
//某用户上传的所有图片
    public ArrayList PicList
    {
        
get
        {
            
if (this.curSession["PicList"== null)
            {
                
this.curSession["PicList"= new ArrayList();
            }

            
return (ArraayList)this.curSession["PicList"];
        }       
    }

    
//清空图片列表
    public void ClearAllPics()
    {
        
this.PicList.Clear();
    }  
}

    这样,我们用起来就非常方便了:
       SessionHelper sessionHelper = SessionHelper.CreateInstance(this.Session);
        ArrayList picList 
= sessionHelper.PicList;
        
//    处理picList中的图片
        sessionHelper.ClearAllPics();  

    引入这一层包装,可以使我们的程序的可读性、可维护性更好,而且将原来的一些运行期的错误提前到了编译期,这也是强类型带来的好处。

posted @ 2008-01-11 09:36 灵! 阅读(193) | 评论 (0)编辑 收藏

Java -- 在Eclipse上使用Hibernate

  最近一个项目要用Java做,一点都不熟啊。没办法,只好硬着头皮啃了,花了大半天的时间,终于在Eclipse上完成了第一个Hibernate例子。下面记录关键的步骤,权作笔记,以备日后查看。

 (1)下载Hibernate,并向项目中导入Hibernate。
     Project->Properies->Java Build Path->Libraries->Add External JARs...,选择Hibernate根目录下的hibernate3.jar,添加到项目中。
    接着,要将Hibernate下的lib文件夹下的所有文件都作为一个User Library添加到项目中,否则,如果仅仅添加hibernate3.jar,编译可以通过,运行却会抛出ClassNotDef的异常,因为hibernate3.jar依赖于Hibernate下的lib文件夹下的文件。

 2)我们的应用的后台数据库使用的是Oracle,所以首先要在例子项目中引入含有Oracle jdbc driver的包,classes12.jar。该jar文件位于oracle安装目录的jdbc\lib目录下。
    在Eclipse中,Project->Properies->Java Build Path->Libraries->Add External JARs...,选择classes12.jar,将其添加到项目中。
    
(3)生成hibernate.cfg.xml文件。
    通常Hibernate的配置文件和.hbm.xml文件都可以自动生成,这种自动生成的工具很多,我使用的是HibernateSynchronizer,它可以作为一个插件添加到Eclipse中。当HibernateSynchronizer插件正确加载后,我们可以向当前项目中添加Hibernate配置文件:File->New->Other->Hibernate->Hibernate Configuration File,出现如下界面:


  注意,Driver Class要选择针对Oracle的oracle.jdbc.driver.OracleDriver,而且Database URL的格式也要正确,如:
jdbc:oracle:thin:@10.8.8.221:1521:ORCL

    最好将hibernate.cfg.xml文件存放于项目的根目录下。

 4)生成.hbm.xml文件。File->New->Other->Hibernate->Hibernate Mapping File,出现如下界面:

     
    在填写完Password后,点击Refresh按钮,就会在Tables中列出所有可以访问的数据库表,然后选中要为其生成.hbm.xml文件的表,点击Finish,即会生成对应的.hbm.xml文件,比如我上面选择的是Mobileuser表,就会生成Mobileuser.hbm.xml文件。

(5)从.hbm.xml文件自动生成实体类。
    在Package Explorer中选中Mobileuser.hbm.xml文件,右键->Hibernate Synchronizer->Synchronize Files ,即可生成对应的实体类和DAO类。如果你仅仅想要实体类,那么可以在Project->Properies->Hibernate Synchronizer->Data Access Objects ,将“I would like to have DAOs created for me”的钩选项去掉即可。

(6)在hibernate.cfg.xml文件中添加对应的mapping resource。
    在Package Explorer中选中Mobileuser.hbm.xml文件,右键->Hibernate Synchronizer->Add Mapping Reference,即会在
hibernate.cfg.xml中自动生成如下配置:

<mapping resource="HibernateTest/Mobileuser.hbm.xml" />

(7)修改自动生成的hibernate.cfg.xml文件。需要在hibernate.cfg.xml文件的首部添加:

<!DOCTYPE hibernate-configuration PUBLIC
        
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

    比较繁琐的是,每次自动修改hibernate.cfg.xml文件后,都要重新添加这个xml片断。

    万事具备,现在可以写个测试来检验一下了:

    //仅仅作为示例,没有进行异常处理
    public static void main(String[] args)
    {
        Configuration cfg 
= new Configuration().configure() ;        
        SessionFactory  sFactory 
= cfg.buildSessionFactory() ;        
        
        Session session 
= sFactory.openSession() ;
        Transaction tx 
= session.beginTransaction();
        Mobileuser user 
= (Mobileuser)session.load(Mobileuser.class , new Integer(2)) ;
        String age 
= user.getMobilenumber() ;
        
        System.
out.println(age) ;
        tx.commit();
        session.close() ;
    }

posted @ 2008-01-11 09:34 灵! 阅读(536) | 评论 (0)编辑 收藏

Java -- 在Eclipse上使用Spring

   在.NET上用的VS.NET+Spring.net+Nhibernate,到了Java平台上,自然对应着Eclipse+Spring+Hibernate。上一篇文章介绍了如何在Eclipse上使用Hibernate的入门,本文就简单介绍一下如何在Eclipse使用Spring。

    (1)首先,是下载Spring,可以从sourceforge上下载,http://sourceforge.net/projects/springframework。目前的最新的可以下载 spring-framework-1.2.8-with-dependencies.zip 。

    (2)然后,可以将Spring引入到你的项目中。
    先将spring-framework-1.2.8-with-dependencies.zip解压,将其中的spring.jar(dist目录中)、commons-logging.jar(lib\jakarta-commons目录)、log4j-1.2.13.jar(lib\log4j目录)这三个文件复制到的”D:\java\Spring\lib" 目录中,然后在Eclipse中建立一个“Spring”库,将那三个文件添加进“Spring”库中。

    (3)测试一下:
    新建两个类,Student和Book。
public class Book 
{
    
private int id = 0 ;
    
private String bookName ;
    
public String getBookName() {
        
return bookName;
    }
    
public void setBookName(String bookName) {
        
this.bookName = bookName;
    }
    
public int getId() {
        
return id;
    }
    
public void setId(int id) {
        
this.id = id;
    }
}

public class Student 
{
    
private int age = 0;    
    
private String name ;
    
private Book book ;

    
public int getAge() {
        
return age;
    }

    
public void setAge(int age) {
        
this.age = age;
    }
    
    
public String getName() {
        
return name;
    }

    
public void setName(String name) {
        
this.name = name;
    }

    
public Book getBook() {
        
return book;
    }

    
public void setBook(Book book) {
        
this.book = book;
    }
    
    
public String GetBookName()
    {
        
return this.book.getBookName() ;
    }    
}

    然后添加Spring配置文件bean.xml(bean.xml必须在CLASSPATH可以存取到的目录中):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" 
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    
<bean id="student" class="com.springTest.Student">
        
<property name="age">
            
<value>22</value>
        
</property>
        
<property name="name">
            
<value>Sky</value>
        
</property>
        
<property name="book" ref="book">            
        
</property>
    
</bean>
    
    
<bean id="book" class="com.springTest.Book">
         
<property name="id">
            
<value>1000</value>
        
</property>
        
<property name="bookName">
            
<value>战争与和平</value>
        
</property>
    
</bean>
</beans>

    最后的主程序:
    public static void main(String[] args) 
    {
        Resource res 
= new ClassPathResource("bean.xml");
        BeanFactory factory 
= new XmlBeanFactory(res);

        Student stu 
= (Student) factory.getBean("student");
        System.
out.println(stu.GetBookName());
    }
    运行后可以看到控制台输出--“战争与和平”。

    与Spring.net的使用基本完全一致(包括配置文件、BeanFactory的获取等),所以熟悉Spring.net的你过渡到Spring是非常平滑的。
    最后,Java中的属性实在是没有C#中的简洁,呵呵。

posted @ 2008-01-11 09:33 灵! 阅读(261) | 评论 (0)编辑 收藏

Java -- 在Eclipse上使用XFire开发WebService

   终于,使用Java完成了一个WebService的例子,其中的一个非常小的问题,折腾了我将近一天的时间。下面给出步骤,说明在Java平台上如何开发WebService。

    采用的工具:Eclipse3.1.2 + Tomcat5.5 + XFire1.1 。使用XFire开发WebService应该说非常的容易,只需要按照下面例子的步骤来做:

(1)在Eclipse中新建一个dynamic Web Project ,假设名为XFireZhuweiTest。

(2)导入XFire用户库。该库中应包含xfire-1.1目录下的xfire-all-1.1.jar文件,以及xfire-1.1\lib目录下的所有文件。

(3)将上述的XFire用户库中的所有文件拷贝到XFireZhuweiTest项目的WebContent\WEB-INF\lib目录下。

(4)修改WebContent\WEB-INF\web.xml配置文件的内容,下面是修改后web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>
    XFireZhuweiTest</display-name>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
    
    <servlet>
         <servlet-name>XFireServlet</servlet-name>
         <servlet-class>
                 org.codehaus.xfire.transport.http.XFireConfigurableServlet
         </servlet-class>
     </servlet>
     
     <servlet-mapping>
         <servlet-name>XFireServlet</servlet-name>
         <url-pattern>/servlet/XFireServlet/*</url-pattern>
     </servlet-mapping>
 
     <servlet-mapping>
         <servlet-name>XFireServlet</servlet-name>
          <url-pattern>/services/*</url-pattern>
     </servlet-mapping>
    
</web-app>

    web.xml中添加的servlet映射表明,所有匹配“/services/*”的url请求全部交给org.codehaus.xfire.transport.http.XFireConfigurableServlet来处理。

(5)编写需要发布为WebService的Java类,这个例子中是一个非常简单的MathService.java。

package com.zhuweisky.xfireDemo;
public class MathService 
{
    
public int Add(int a ,int b)
    {
        
return a+b ;
    }
}

(6)在WebContent\META-INF目录下新建xfire文件夹,然后在xfire目录下添加一个XFire使用的配置文件services.xml,该配置文件中的内容反映了要将哪些java类发布为web服务。本例中的services.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xfire.codehaus.org/config/1.0">
    
<service>
      
<name>MathService</name>
      
<namespace>http://com.zhuweisky.xfireDemo/MathService</namespace>
      <serviceClass>com.zhuweisky.xfireDemo.MathService</serviceClass>
    
</service>
</beans>

    XFire会借助Spring来解析services.xml,从中提取需要发布为WebService的配置信息。

    很多文章介绍到这里就完了,然而当我按照他们所说的启动WebService ,然后通过http://localhost:8080/XFireZhuweiTest/services/MathService?wsdl 来访问服务描述时,却抛出了异常,说services.xml文件不存在--
“org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [META-INF/xfire/services.xml]; nested exception is java.io.FileNotFoundException: class path resource [META-INF/xfire/services.xml] cannot be opened because it does not exist”。  

(7)非常关键的一点,就是这个小难题花费了我将近一天的时间。
    在WebContent\WEB-INF目录下新建classes文件夹,然后需要将WebContent下的整个META-INF文件夹剪切到新建的classes文件夹下。
    到这里,项目的完整目录结构如下:



(8)在Package Explorer中选中XFireZhuweiTest项目,右键->Run As ->Run On Server,关联到你机器上的TomCat,然后会启动Tomcat,以启动web服务。(注意,在进行此步骤之前,请先停止TomCat) 

(9)在IE中输入 http://localhost:8080/XFireZhuweiTest/services/MathService?wsdl 会得到正确的web服务描述文档。

(10)测试刚发布的webService。我使用C#动态调用Web服务:

                //C#
                string url = "http://localhost:8080/XFireZhuweiTest/services/MathService" ;
                
object[] args ={1,2} ;
                
object result = ESFramework.WebService.WebServiceHelper.InvokeWebService(url ,"Add" ,args) ;
                MessageBox.Show(result.ToString());

    (关于C#动态调用Web服务,请参见这里

    执行后,弹出对话框,显示结果是3。

posted @ 2008-01-11 09:31 灵! 阅读(1703) | 评论 (0)编辑 收藏

通用分页存储过程(原创)

 这是我项目中使用的一个分页存储过程,具有很强的通用性。配合前台ASP.NET使用50万条数据基本感不到延迟。数据库为SQLServer2000。

1.分页存储过程

CREATE   procedure pagination

 @str_sql           varchar(1000) = '*',     -- 执行的SQL 不含Order by 内容  
 @str_orderfield    varchar(255)='''',       -- 排序的字段名 
 @page_size         int = 10,                     -- 页大小 
 @page_index        int = 0,                      -- 页码
 @order_type        int,                           -- 设置排序类型, 非 -1 值则降序 
 @total_count       int   output                 -- 返回记录总数, 非 0 值则返回 
as

---------------------
-- 获取指定页的数据--
---------------------

declare @strsql   varchar(5000)              -- 主语句
declare @strtmp   varchar(5000)             -- 临时变量
declare @strorder varchar(400)              -- 排序字串
declare @cruRow   int                            -- 当前行号
 

--执行总数统计
exec getRowCount @str_sql,@total_count output

set @strtmp =  ' select * from ' +
        '      (select top ' + convert(varchar(10),@page_size) + ' * from ' +
        '         (select top ' + convert(varchar(10),(@page_index + 1) * @page_size)  +' * from '+        -- N+1页
        '            ('+ @str_sql +') Src '

--排序方向
if @order_type !=0
 begin
 set @strsql= @strtmp +
       '          order by @str_orderfield asc) a ' +
       '       order by @str_orderfield desc)b' +
              ' order by @str_orderfield asc'
 end
else
 begin
 set @strsql= @strtmp +
       '          order by @str_orderfield desc) a ' +
       '       order by  @str_orderfieldasc)b' +
              ' order by  @str_orderfield desc'
 end

exec (@strsql)

GO

----------------------------------------------------------------------------

2.分页存储过程执行中用到的行数统计

create  procedure getRowCount
       @sql    nvarchar(2000),
       @count  int output
as
begin

--------------------
-- 获取数据总行数 --
--------------------

  declare @tmpsql nvarchar(2000)
  set @tmpsql='select @count=count(*)  from ('+ @sql +') a'

  execute sp_executesql @tmpsql,N'@count int output',@count output
 
end

GO

posted @ 2008-01-10 17:08 灵! 阅读(434) | 评论 (0)编辑 收藏

JAVA面试题汇总 四

31 构造器Constructor是否可被override?

  构造器Constructor不能被继承,因此不能重写Overriding,但可以被重载Overloading。

32 是否可以继承String类?

  String类是final类故不可以继承。

33 当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?

  不能,一个对象的一个synchronized方法只能由一个线程访问。

33  try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不

会被执行,什么时候被执行,在return前还是后? 
  会执行,在return前执行。

34 编程题: 用最有效率的方法算出2乘以8等於几? 

  2 << 3 

35 两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?

  不对,有相同的hash code。

36  当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

  是值传递。Java编程语言只由值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。

37  swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?

  switch(expr1)中,expr1是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。 
38 Hashtable和HashMap

  Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现 
  HashMap允许将null作为一个entry的key或者value,而Hashtable不允许
还有就是,HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
  最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在
多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap就必须为之提供外同步。 
Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。

posted @ 2008-01-10 17:04 灵! 阅读(150) | 评论 (0)编辑 收藏

JAVA面试题汇总 三

21 数组有没有length()这个方法? String有没有length()这个方法?

  数组没有length()这个方法,有length的属性。 
  String有有length()这个方法。

22 Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?

  方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写(Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。 
Overloaded的方法是可以改变返回值的类型。

23 Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?

  Set里的元素是不能重复的,那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等。 equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。 

24最常见到的runtime exception。

ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException,EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException,ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFORMatException, Secur 
ityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException 

25 error和exception有什么区别?

  error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。 
  exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。

26 List, Set, Map是否继承自Collection接口?

     List,Set是 
     Map不是
    
27 abstract class和interface有什么区别?

  声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。 
  接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口。 

28 abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?

  都不能

29 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?

  接口可以继承接口。抽象类可以实现(implements)接口,抽象类可继承实体类,但前提是实体类必须有明确的构造函数。

30 启动一个线程是用run()还是start()?

  启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。

posted @ 2008-01-10 17:03 灵! 阅读(107) | 评论 (0)编辑 收藏

JAVA面试题汇总 二

11   &和&&的区别。 
  &是位运算符。&&是布尔逻辑运算符。 

12  HashMap和Hashtable的区别。

  都属于Map接口的类,实现了将惟一键映射到特定的值上。 
  HashMap 类没有分类或者排序。它允许一个 null 键和多个 null 值。 


  Hashtable 类似于 HashMap,但是不允许 null 键和 null 值。它也比 HashMap 慢,因为它是同步的。

13 Collection 和 Collections的区别。

    Collection是个java.util下的接口,它是各种集合结构的父接口。
  Collections是个java.util下的类,它包含有各种有关集合操作的静态方法。

14 什么时候用assert。

  断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为 true。 
如果表达式计算为 false,那么系统会报告一个 Assertionerror。它用于调试目的: 
assert(a > 0); // throws an Assertionerror if a <= 0 
断言可以有两种形式: 
assert Expression1 ; 
assert Expression1 : Expression2 ; 
  Expression1 应该总是产生一个布尔值。 
  Expression2 可以是得出一个值的任意表达式。这个值用于生成显示更多调试 
信息的 String 消息。 
  断言在默认情况下是禁用的。要在编译时启用断言,需要使用 source 1.4 标记:
  javac -source 1.4 Test.java 
  要在运行时启用断言,可使用 -enableassertions 或者 -ea 标记。 
  要在运行时选择禁用断言,可使用 -da 或者 -disableassertions 标记。 
  要系统类中启用断言,可使用 -esa 或者 -dsa 标记。还可以在包的基础上启用或者禁用断言。 
  可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既可以在公有方法中,也可以在非公有方法中利用断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。 

15 GC是什么? 为什么要有GC? (基础)。

  GC是垃圾收集器。Java 程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:
  System.gc() 
  Runtime.getRuntime().gc()

16 String s = new String("xyz");创建了几个String Object?

  两个对象,一个是“xyz”,一个是指向“xyz”的引用对象s。

17 Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

  Math.round(11.5)返回(long)12,Math.round(-11.5)返回(long)-11;

18 short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?

  short s1 = 1; s1 = s1 + 1;有错,s1是short型,s1+1是int型,不能显式转化为short型。可修改为s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正确。

19 sleep() 和 wait() 有什么区别? 搞线程的最爱

  sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非(a)“醒来”的线程具有更高的优先级 (b)正在运行的线程因为其它原因而阻塞。 
  wait()是线程交互时,如果线程对一个同步对象x 发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。 

20 Java有没有goto? 
  Goto—java中的保留字,现在没有在java中使用。

posted @ 2008-01-10 17:02 灵! 阅读(135) | 评论 (0)编辑 收藏

JAVA面试题汇总 一

1. Java中的异常处理机制的简单原理和应用。 

当Java程序违反了Java的语义规则时,Java虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是Java类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种情况就是Java允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用throw关键字引发异常。所有的异常都是java.lang.Thowable的子类。 

2. Java的接口和C++的虚类的相同和不同处。 

由于Java不支持多继承,而有可能某个类或对象要使用分别在几个类或对象里面的方法或属性,现有的单继承机制就不能满足要求。与继承相比,接口有更高的灵活性,因为接口中没有任何实现代码。当一个类实现了接口以后,该类要实现接口里面所有的方法和属性,并且接口里面的属性在默认状态下面都是public static,所有方法默认情况下是public.一个类可以实现多个接口。 

3. 垃圾回收的优点和原理。并考虑2种回收机制。 

Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有“作用域”的概念,只有对象的引用才有“作用域”。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。 

4.线程同步的方法。 

wait():使一个线程处于等待状态,并且释放所持有的对象的lock。 

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。 

notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切地唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。 

Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。 

5. Error与Exception有什么区别? 

Error表示系统级的错误和程序不必处理的异常, 

Exception表示需要捕捉或者需要程序进行处理的异常。 

6. 在java中一个类被声明为final类型,表示了什么意思? 

   表示该类不能被继承,是顶级类。
  
7 heap和stack有什么区别。

   栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。堆是栈的一个组成元素。

8谈谈final, finally, finalize的区别。

  final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。 
  finally—异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。 
  finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。

9  Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?

  匿名的内部类是没有名字的内部类。不能extends(继承) 其它类,但一个内部类可以作为一个接口,由另一个内部类实现。

10  Static Nested Class 和 Inner Class的不同
Nested Class (一般是C++的说法),Inner Class (一般是JAVA的说法)。Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。
  注: 静态内部类(Inner Class)意味着1创建一个static内部类的对象,不需要一个外部类对象,2不能从一个static内部类的一个对象访问一个外部类对象  .

posted @ 2008-01-10 17:02 灵! 阅读(157) | 评论 (0)编辑 收藏

汉字编码转换

汉字编码转换

相关:

UNICODE 是为了处理包括中文,日文等字符而提出的一种通用的字符集。最初的UNICODE为双字节字符集,即16位编码,能够包括65,536个字符。但这样的容量并不能满足所有需要,因此,现在的UNICODE已经扩展到4个字节,能够容纳1,112,064 个字符,而这些在16位之后的扩展背称为增补字符。

UTF-32 UTF-16 UTF-8 Unicode 标准的编码字符集的字符编码方案。

UTF-8 使用一至四个字节的序列对编码 Unicode 代码点进行编码

UTF-8 使用一至四个字节的序列对编码 Unicode 代码点进行编码。U+0000 至 U+007F 使用一个字节编码,U+0080 至 U+07FF 使用两个字节,U+0800 至 U+FFFF 使用三个字节,而 U+10000 至 U+10FFFF 使用四个字节。UTF-8 设计原理为:字节值 0x00 至 0x7F 始终表示代码点 U+0000 至 U+007F(Basic Latin 字符子集,它对应 ASCII 字符集)。这些字节值永远不会表示其他代码点,这一特性使 UTF-8 可以很方便地在软件中将特殊的含义赋予某些 ASCII 字符。

  GB2312(1980 ) 一共收录了 7445 个字符,包括 6763 个汉字和 682 个其它符号。汉字区的内码范围高字节从 B0-F7 ,低字节从 A1-FE ,占用的码位是 72*94=6768 。其中有 5 个空位是 D7FA-D7FE 。当然也可以表示数字和字符(一个字节,与 ASCII 表示相同)。

要读取一个以 GB2312 编码的包含汉字、数字、字母的二进制文件。

String strName =Encoding.GetEncoding("gb2312").GetString(name,0,i) ;

// name 是读取的二进制数组。

这样就能将二进制数组转换为 汉字、数字或字母

同样:也可以将包含汉字、数字、字母的字符串转换为 二进制数组保存到 二进制文件。

String unicodeString =   " 备用43E";

Byte[] encodedBytes = Encoding.GetEncoding("gb2312").GetBytes(unicodeString);

当然也可以进行二进制数组与UNICODE,UTF-8等编码方式的转换

Byte[] encodedBytes = utf8.GetBytes(unicodeString);

String decodedString = utf8.GetString(encodedBytes);

UnicodeEncoding unicode = new UnicodeEncoding();

Byte[] encodedBytes = unicode.GetBytes(unicodeString);

String decodedString = unicode.GetString(encodedBytes);

posted @ 2008-01-10 11:46 灵! 阅读(486) | 评论 (0)编辑 收藏

JBuilderX快捷键

F1 Help
F3 查找下一个

shift + F3 反向查找下一个

ctrl + F 查找

ctrl + p 路径查找

ctrl + F4 运行到当前位置
ctrl+F6在jbuilder中,切换不同的文件
Ctrl+F4关闭正在编辑的文件,
Ctrl + F5切换工程


F5 设置断点

F7 跟入

F8 单步

F9 运行

ctrl + F9 编译工程

shift + F9 调试模式运行

ctrl + shift + F9 编译当前类

ctrl + H 显示本类成员

ctrl + J 显示模板
ctrl + shift + J 模板编辑

ctrl + shift + c 自动完成错误捕捉代码

ctrl + Enter /mouseClick 当前关键字追踪

ctrl + shit + 数字(0-9) 设置/去除标签

ctrl + 数字(0-9) 返回标签位置

ctrl + alt + -> / <- 返回最近访问点

ctrl + -> / <- 光标跳过当前单位词

ctrl + shift + -> / <- 选择单位词

ctrl + 上下方向键 滚动屏幕

ctrl + home/end/pageup/pagedown

shift +盘方向键/home/end/pageup/pagedown 选择

ctrl + e 增量式查找

ctrl + w 捕捉离光标最近的单词

ctrl + shift + h 参数查找

ctrl + alt + space class insight

ctrl + F4 关闭当前类

ctrl + shift + F4 关闭(显示选择)

ctrl + B 切换窗体

ctrl + F6 切换窗体

ctrl + alt + p/c/m/z/s 视图开关

ctrl + o/n/c/v/x/p/a

ctrl + g 到指定行

Tab 格式化宿进

ctrl + / 注释/去除注释选择行

ctrl + shift + I 宿进

ctrl + shift + U 反向宿进

posted @ 2008-01-10 11:45 灵! 阅读(132) | 评论 (0)编辑 收藏

常用到的Eclipse快捷键

常用到的Eclipse快捷键

Ctrl+s                 存盘

Ctrl+/                  注释(取消)代码

Ctrl+shift+/       注释代码块

Ctrl+shift+\       取消代码块

Alt+/                  代码辅助/调出IF语句等程序模板:使用方法:打出if,按ALT+/

Ctrl+D             删除一行 

Ctrl+Shift+D   debug 模式里显示变量值

Ctrl+1               快速修复  

Ctrl+Shift+f     代码格式化

Ctrl+Shift+o    整理导入  

Ctrl+f6             切换窗口  

ctrl+shift+M   导入未引用的包

ctrl+w             关闭单个窗口

F3                      跳转到类、变量的声明

F11                   运行上次程序

Ctrl + F11        调试上次程序

Alt +                 回下一个编辑点

ctrl+shift+T   查找工程中的类

Alt-left arrow :    在导航历史记录(Navigation History)中后退。就像Web浏览器的后退按钮一样,在利用F3跳转之后,特别有用。(用来返回原先编译的地方)

Alt+right arrow :   导航历史记录中向前。

Control+Q :         回到最后依次编辑的地方。这个快捷键也是当你在代码中跳转后用的。特别是当你钻的过深,忘记你最初在做什么的时候。

ctrl+Alt+down     复制鼠标所在行到下一行

Alt+down arrow :    将一行或多行向下移动。

Alt+up arrow      将一行或多行 向上移动。

posted @ 2008-01-10 11:44 灵! 阅读(174) | 评论 (0)编辑 收藏

迭代器

迭代这个名词对于熟悉Java的人来说绝对不陌生。我们常常使用JDK提供的迭代接口进行java collection的遍历:

Iterator it = list.iterator();
while(it.hasNext()){
 //using “it.next();”do some businesss logic
}

  而这就是关于迭代器模式应用很好的例子。

  二、 定义与结构

  迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。

  从定义可见,迭代器模式是为容器而生。很明显,对容器对象的访问必然涉及到遍历算法。你可以一股脑的将遍历方法塞到容器对象中去;或者根本不去提供什么遍历算法,让使用容器的人自己去实现去吧。这两种情况好像都能够解决问题。

  然而在前一种情况,容器承受了过多的功能,它不仅要负责自己“容器”内的元素维护(添加、删除等等),而且还要提供遍历自身的接口;而且由于遍历状态保存的问题,不能对同一个容器对象同时进行多个遍历。第二种方式倒是省事,却又将容器的内部细节暴露无遗。

  而迭代器模式的出现,很好的解决了上面两种情况的弊端。先来看下迭代器模式的真面目吧。

  迭代器模式由以下角色组成:

  1) 迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的接口。

  2) 具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。

  3) 容器角色(Container):容器角色负责提供创建具体迭代器角色的接口。

  4) 具体容器角色(Concrete Container):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。

  迭代器模式的类图如下:


  从结构上可以看出,迭代器模式在客户与容器之间加入了迭代器角色。迭代器角色的加入,就可以很好的避免容器内部细节的暴露,而且也使得设计符号“单一职责原则”。

  注意,在迭代器模式中,具体迭代器角色和具体容器角色是耦合在一起的——遍历算法是与容器的内部细节紧密相关的。为了使客户程序从与具体迭代器角色耦合的困境中脱离出来,避免具体迭代器角色的更换给客户程序带来的修改,迭代器模式抽象了具体迭代器角色,使得客户程序更具一般性和重用性。这被称为多态迭代。

  三、 举例

  由于迭代器模式本身的规定比较松散,所以具体实现也就五花八门。我们在此仅举一例,根本不能将实现方式一一呈现。因此在举例前,我们先来列举下迭代器模式的实现方式。

  1.迭代器角色定义了遍历的接口,但是没有规定由谁来控制迭代。在Java collection的应用中,是由客户程序来控制遍历的进程,被称为外部迭代器;还有一种实现方式便是由迭代器自身来控制迭代,被称为内部迭代器。外部迭代器要比内部迭代器灵活、强大,而且内部迭代器在java语言环境中,可用性很弱。

  2.在迭代器模式中没有规定谁来实现遍历算法。好像理所当然的要在迭代器角色中实现。因为既便于一个容器上使用不同的遍历算法,也便于将一种遍历算法应用于不同的容器。但是这样就破坏掉了容器的封装——容器角色就要公开自己的私有属性,在java中便意味着向其他类公开了自己的私有属性。

  那我们把它放到容器角色里来实现好了。这样迭代器角色就被架空为仅仅存放一个遍历当前位置的功能。但是遍历算法便和特定的容器紧紧绑在一起了。

  而在Java Collection的应用中,提供的具体迭代器角色是定义在容器角色中的内部类。这样便保护了容器的封装。但是同时容器也提供了遍历算法接口,你可以扩展自己的迭代器。

  好了,我们来看下Java Collection中的迭代器是怎么实现的吧。

//迭代器角色,仅仅定义了遍历接口

public interface Iterator {
 boolean hasNext();
 Object next();
 void remove();
}

//容器角色,这里以List为例。它也仅仅是一个接口,就不罗列出来了
//具体容器角色,便是实现了List接口的ArrayList等类。为了突出重点这里指罗列和迭代器相关的内容
//具体迭代器角色,它是以内部类的形式出来的。AbstractList是为了将各个具体容器角色的公共部分提取出来而存在的。

public abstract class AbstractList extends AbstractCollection implements List {
……
//这个便是负责创建具体迭代器角色的工厂方法
public Iterator iterator() {
 return new Itr();
}

//作为内部类的具体迭代器角色

private class Itr implements Iterator {
 int cursor = 0;
 int lastRet = -1;
 int expectedModCount = modCount;

 public boolean hasNext() {
  return cursor != size();
 }

 public Object next() {
  checkForComodification();
  try {
   Object next = get(cursor);
   lastRet = cursor++;
   return next;
  } catch(IndexOutOfBoundsException e) {
   checkForComodification();
   throw new NoSuchElementException();
  }
 }

 public void remove() {
  if (lastRet == -1)
   throw new IllegalStateException();
   checkForComodification();

  try {
   AbstractList.this.remove(lastRet);
   if (lastRet < cursor)
    cursor--;
   lastRet = -1;
   expectedModCount = modCount;
  } catch(IndexOutOfBoundsException e) {
   throw new ConcurrentModificationException();
  }
 }

 final void checkForComodification() {
  if (modCount != expectedModCount)
   throw new ConcurrentModificationException();
 }
}

  至于迭代器模式的使用。正如引言中所列那样,客户程序要先得到具体容器角色,然后再通过具体容器角色得到具体迭代器角色。这样便可以使用具体迭代器角色来遍历容器了……

  四、 实现自己的迭代器

  在实现自己的迭代器的时候,一般要操作的容器有支持的接口才可以。而且我们还要注意以下问题:

  在迭代器遍历的过程中,通过该迭代器进行容器元素的增减操作是否安全呢?

  在容器中存在复合对象的情况,迭代器怎样才能支持深层遍历和多种遍历呢?

  以上两个问题对于不同结构的容器角色,各不相同,值得考虑。

  五、 适用情况

  由上面的讲述,我们可以看出迭代器模式给容器的应用带来以下好处:

  1) 支持以不同的方式遍历一个容器角色。根据实现方式的不同,效果上会有差别。

  2) 简化了容器的接口。但是在java Collection中为了提高可扩展性,容器还是提供了遍历的接口。

  3) 对同一个容器对象,可以同时进行多个遍历。因为遍历状态是保存在每一个迭代器对象中的。

  由此也能得出迭代器模式的适用范围:

  1) 访问一个容器对象的内容而无需暴露它的内部表示。

  2) 支持对容器对象的多种遍历。

  3) 为遍历不同的容器结构提供一个统一的接口(多态迭代)。

  六、 总结

  迭代器模式在我们的应用中很广泛,希望本文能帮助你理解它。如有不对之处,还请不吝指正。

posted @ 2008-01-10 11:42 灵! 阅读(148) | 评论 (0)编辑 收藏

Hibernate 3新增XML关系持久性介绍(转)

非常感谢最近发布的Hibernate 3中的XML持久性特性,Java开发者现在拥有了一个框架组件,它为易于实现的对象关系(OR)和XML持久性提供了高效的和一致的方法。

  Hibernate的易用性、高性能和对象关系持久性等高级特性给IT界带来了很大的惊喜。 Hibernate的最新版本(版本3,3月29日发布的)给产品API带来了一个重要的新特性:XML持久性。有了Hibernate 3之后,Java应用程序开发者可以轻易地把XML文档合并到关系型数据库中。

  这个新特性应该明确地告诉已有的Hibernate开发者,因为它也遵循POJO(纯的旧Java对象)相同的一致性方法,需要学习的知识最少。XML持久性的优点也应该介绍给新用户。本文讲解的是Hibernate 3持久性方法。

  XML持久性为什么重要

  大多数大型商业数据库都支持某种形式的本地XML持久性。由于XML持久性是一个相对较新的机制--即使对大型厂商也是如此,这个领域中的标准还在不断地浮现。其结果是,为了把无处不在的关系型持久性机制与日益增长的XML解决方案集成在一起,架构师必须依赖厂商特定的特性或者实现定制的XML持久性框架组件。这两个选择都没有太大的吸引力。厂商特定的特性不是普及的,因为可能产生厂商封锁(lock-in),而定制的框架组件实现可能耗费大量的时间和财力,导致代码难于维护。

  在OR(对象关系)持久性方面,Hibernate XML持久性是一个自然而然的解决方案。它可以跨越Hibernate支持的所有关系型平台(如虚拟的或真实的关系型平台)移动,允许自由的迁移对象、基于XML的应用程序和集成解决方案而不用担心下层的关系型实现方法。

  体系结构的细节信息

  Hibernate是一个良好架构的框架组件,它无缝地利用了本地的环境,不需要用户进行任何特殊的干涉或安装操作。从一个数据库切换到另外一个数据库通常只需要改变驱动程序,并配置Hibernate(在线配置设置信息)来使用另外一种数据库语言。

  Hibernate利用dom4j框架组件进行XML的分析和维护。如果需要完全利用Hibernate的XML特性,你就必须对dom4j非常熟悉。一般来说,你会发现dom4j比Java提供的JAXP或与JAXP兼容的XML分析器要容易使用一些。它要求我们学习的相关知识较少,并且利用最少的dom4j知识你就能够高效率地使用Hibernate XML持久性。

实际例子:价格目录同步

  通用的电子商务案例可以演示XML关系持久性机制的作用。我们来考虑一个示例,在这个例子中XML集成了在线零售商和供应商之间的产品标价目录。

  该电子目录包含了已标价的产品列表。在线商店销售产品,通过自己的存货清单来管理(类似于Amazon与Toys-R-Us和运动产品商店之间的关系)。为了精确地和有效地反映价格的变化,在线零售商必须频繁地接收产品价格信息。它把这些信息存放为XML文档,如下所示:

<products>
<product prod_id="3" sku="100101">
<description>Athlete mode body fat scale</description>
<list_price>100.00</list_price>
<drop_price>60.00</drop_price>
</product>
<product prod_id="4" sku="100102">
<description>Thermometer</description>
<list_price>20.00</list_price>
<drop_price>11.00</drop_price>
</product>
</products>

  全面的主要的产品价格列表存储在数据库中,如下所示:

CREATE TABLE PRODUCT
(
id INT UNIQUE NOT NULL,
description VARCHAR(45) NOT NULL,
sku VARCHAR(45) UNIQUE NOT NULL,
list_price FLOAT,
base_price FLOAT,
order_price FLOAT,
CONSTRAINT PK_PRODUCT PRIMARY KEY (id )
)

  在线零售商通过已有的OR映射提供定价目录的Web表现形式,定价产品都表现为demo.Product Java对象:

/** Product对象表现了定价目录项*/
public class Product {
int id;
String sku;
String description;
Double listPrice;
Double basePrice;
Double orderPrice;

  这些对象按照下面的方式映射(为了清楚,我们列出了列名,尽管在属性和列名相匹配的时候Hibernate可以自动地把属性映射为列名):

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="demo">
<class name="Product"
table="product"
node="product">
<id name="id"
type="int"
node="@prod_id"
column="id">
</id>
<property name="sku" node="@sku" column="sku" not-null="true"/>
<property name="description" node="description" column="description" not-null="true"/>
<property name="listPrice" node="list_price" column="list_price" />
<property name="basePrice" node="drop_price" column="base_price"/>
<property name="orderPrice" column="order_price"/>
</class>
</hibernate-mapping>

  在这种情况下,Hibernate的XML关系持久性就非常方便了。由于该电子商务应用程序接收了包含产品价格更新的XML,它就利用Hibernate的XML持久性机制把这些XML写入到产品数据库中。Hibernate提供了几种XML持久性选择,包括Hibernate的saveOrUpdate方法:

document = saxReader.read(inputXML);
List users = document.selectNodes("//product");
try {
 Session session = ibernateUtil.sessionFactory.openSession();
 Transaction transaction = session.beginTransaction();
 Session dom4jSession = session.openSession(EntityMode.DOM4J);
 Iterator iter = users.iterator();
 while (iter.hasNext()) {
  Object next = iter.next();
  dom4jSession.saveOrUpdate("demo.Product", next );
 }// end while
transaction.commit();
session.close(); 

  XML映射语法

  上面的例子中使用的映射文件不用于Hibernate 2的映射文件。Hibernate 3引入了几种专门用于XML持久性的新映射类型。

  主要的新映射属性是节点(node),它与被映射的XML文档中的一个元素或文档中的属性相关联。

  一个"节点"可能表现为下面的某种映射:

  · "element-name(元素名)":在例子中,<product></product>元素会被表示为node="product"。

  · "@attribute-name(属性名)":在例子中,node="@sku"会被映射为XML属性<product sku="1001001">。

  · ".(句点)":映射为元素的父元素(例如<products>就<product>是的父元素)。

  · "element-name/@attribute-name(元素名/属性名)":映射为命名元素的属性(product/@sku)。

  XML持久性并非Hibernate的主要任务

  Hibernate 3框架组件高效率地实现了目前最通用的一些方法(除了LDAP之外)。Java社团现在拥有了一套框架组件,它为易于实现的OR和XML持久性提供了高效率的和一致性的方法。

  在我们知道上面一些内容之后,了解Hibernate项目的任务是很重要的。尽管Hibernate 3的XML特性非常有用、有吸引力,但是它们并不是用来代替最流行的XML编组(marshalling)和转换(transformation)框架组件的。不管它的OR映射解决方案多么完善,我们都不应该期待Hibernate成为主流的XML维护框架组件(根据Hibernate的作者Gavin King在TheServerSide Java Symposium 2005上的发言)。

  由于这个原因,你应该把XML持久性特性看作是已有的强大的Hibernate框架组件的有用的扩展,它允许你轻易地把现在流行的其它的数据表现机制合并到自己的应用程序中。但是,如果你必须处理复杂的集成和转换情况,最好去寻找其它的XML专用的框架组件。

posted @ 2008-01-10 11:41 灵! 阅读(195) | 评论 (0)编辑 收藏

hibernate入门

一、首先学习hibernate.cfg.xml配置文件的具体配置
<?xml version="1.0" encoding="UTF-8"?>

<!--指定该文件的官方dtd-->
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" >
<hibernate-configuration>
  <session-factory>
    <!-- 显示sql语言 -->
    <property name="show_sql">true</property>
    <!-- sql语言 -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <!-- jdbc驱动程式 -->
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <!-- jdbc url -->
    <property name="connection.url">jdbc:mysql://localhost:3306/test</property>
    <!-- 数据库用户名 -->
    <property name="connection.username">root</property>
    <!-- 数据库密码 -->
    <property name="connection.password">wyq</property>
    <!-- C3P0连接池设定 -->
    <!--最小连接数-->
    <property name="c3p0.min_size">5</property>
    <!--最大连接数-->
    <property name="c3p0.max_size">20</property>
   <!--延迟所允许的时间-->
    <property name="c3p0.timeout">1800</property>
   <!--缓存所允许的最大连接数-->
    <property name="c3p0.max_statements">50</property>
    <!-- 每隔100笔资料送入资料库,清除缓存(定期清除缓存,减小压力) -->
    <property name="hibernate.jdbc.batch_size">100</property>
    <!-- 设定事务管理的工厂类 -->
    <property name="hibernate.transaction.factiory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
   <mapping resource="com/wyq/hibernate/pojo/User.hbm.xml"/>
   <mapping resource="com/wyq/hibernate/pojo/TUser.hbm.xml"/>
   <mapping resource="com/wyq/hibernate/pojo/Room.hbm.xml"/>
  </session-factory>
</hibernate-configuration>
需要的jar包有c3p0.jar,hibernate3.jar,数据库.jar,log4j.jar


------------------------------------------------------------------------------------------------------------------------

1、读取配置文件获得连接
   读取hibernate.cfg.xml配置文件,hibernate.cfg.xml文件放在Classpath下,使用下面的方式读入该文件
      //Configuration 负责管理hibernate配置信息
      Configuration config=new Configuration().configure();
      //根据config建立SessionFactory
      //SessionFactory用于建立Session
      SessionFactory sessionFactory=config.buildSessionFactory();
      //开启session,相当于jdbc的Connection
      session = sessionFactory.openSession();

2、Criteria 基本资料查询
(1)标准查询:
      //创建查询标准
      Criteria criteria=session.creteCriteria(User.class);
      //查询条件
      criteria.add(Expression.eq("name","caterpillar"));
************************************************************************************
Expression.eq(String s1,String s2)---------->相等s1=s2
Expression.allEq(Map map)    --------------->多个属性-值对应关系,多个Expression.eq叠加
Expression.gt(String s1,String s2)----------->大于s1>s2
Expression.ge(String s1,String s2)----------->大于等于s1>=s2
Expression.lt(String s1,String s2)------------>小于s1<s2
Expression.le(String s1,String s2)------------>小于等于s1<=s2
Expression.between(String s1,int s2,int s3)--->s2<s1<s3
Expression.like(String s1,String s2)------------>s1 like s2
比较2个属性
Expression.eqProperty(String s1,String s2)--->s1=s2
Expression.gtProperty(String s1,String s2)---->s1>s2
Expression.geProperty(String s1,String s2)---->s1>=s2
Expression.ltProperty(String s1,String s2)----->s1<s2
Expression.leProperty(String s1,String s2)----->s1<=s2
Expression.and()----->Expression.and(Expression.eq("String s1,String s2"),Expression.eq(String s3,String s4))
Expression.or()
************************************************************************************
(2)高级查询
一、可以使用Criteria进行查询,并用order对结果进行排序。
//设置从第几条开始取的记录
criteria.setFirstResult(100);
//最多取的几条记录
criteria.setMaxResults(20);
//对结果进行排序
criteria.addOrder(Order.asc(String s1));
criteria.addOrder(Order.desc(String s2));

二、可以对查询结果进行统计操作,使用Projections的rowCount(),count(),max(),min(),countDistinct()等方法:
例如:criteria.setProjection(Projections.max("age"));

三、还可以用Projections的groupProperty()来对结果进行分组
例如:criteria.setProjection(Projections.groupProperty("age"));

(***)四、结合统计与分组的功能,可以用ProjectionList
例如:ProjectionList projectionList =Projections.projectionList();
            projectionList.add(Projections.groupProperty("age"));
            projectionList.add(Projections.rowCount());
            criteria.setProjection(projectionList);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      //查询所有记录
      List users=criteria.list();
      Iterator iterator=users.iterator();
      while(iterator.hasNext()){
         User user=(User)iterator.next();
         System.out.println(user.getId()+"\t"+user.getName()+"/"+user.getAge());
}
3、criteria的增、删、改(还不完善)
在用到增、删、改时,必须先声明事务
增加:
  Transaction tx = session.beginTransaction();//Transaction表示一组会话操作
  session.save(user);//将事物映射到数据库进行存储
  tx.commit();
  session.close();
删除:
  Session session=this.getSession();
  User user=(User)session.get(User.class, new Integer(1));
  Transaction tx = session.beginTransaction();//Transaction表示一组会话操作
  session.delete(user);//将事物映射到数据库进行存储
  tx.commit();
  session.close();

修改:
  Session session=this.getSession();
  User user =(User)session.get(User.class,new Integer(2));//创建持久化的事物
  user.setName("wyqqqqqqqqqq");
  user.setAge(new Integer(30));
  Transaction tx = session.beginTransaction();//Transaction表示一组会话操作
  session.update(user);//将事物映射到数据库进行存储
  tx.commit();
  session.close();
----------------------------------------------------------------------------------------------------------------------
一、Query查询可以先设定查询参数,之后通过set等方法,将指定的参数值添入.还可以使用命名参数
Session session = sessionFactory.openSession();
Query query = session.createQuery("select user.name from User as user where user.age>?(
:minAge )");
query.setInteger(0,25);
query.setInteger("minAge",25);
List names=query.list();
Iterator iterator = names.iterator();
while(iterator.hasNext()){
      System.out.println(iterator.next());
}
session.close();

二、如果查询整个表直接使用from User如果针对某个属性使用select user.name from User as user
使用hql可以更接近我们平时的jdbc编程,和把sql语句写在程序中差不多,另外,也可以将sql语句写在配置文件中。



--------------------------------------------------------------------------------------------------------------------------
   多表关联
一、多对一进行关联(多个学生对应同一间宿舍)---学生是主体,宿舍是附体,关联关系<many-to-one>在主体学生中设置,在学生类中设置宿舍类,由于宿舍类只有一个可以直接用类来设置,在映射学生类(User)中包含宿舍这个类(Room),在映射配置文件(User.hbm.xml)中定义

<many-to-one name="room" column="room_id" cascade="save-update" class="com.wyq.hibernate2.Room"></many-to-one>

哪个是主体类就在哪个配置文件定义关联关系.

cascade属性:表示关联对象的持久化,该属性也要设置在主体中,作用就是当主控方执行操作时,关联对象(被动方)是否同步执行同一操作.
cascade的值:all:表示所有情况下都进行级联操作.
                        none:所有情况下都不进行级联操作
                        save-update:在执行save-update时进行级联操作.
                        delete:在执行delete时进行级联操作.

注意:使用cascade自動持久化時,會先檢查被關聯物件的id屬性,未被持久化的物件之id屬性是由unsaved-value決定,預設是null,如果您使用long這樣的原生型態(primitive type)時,則必須自行指定預設值.

例如:<id name="id" column="ROOM_ID" unsaved-value="0">
            <generator class="increment"/>
        </id>

如果您不想額外設定unsaved-value資訊,則可以將long改為Long,這可以符合預設的unsaved-value為null的設定 .

二、一对多进行关联(一间宿舍对应多个学生)---宿舍是主体,学生是附体,关联关系<one-to-many>在主体宿舍中设置,由于要在宿舍类中设置学生类,一个宿舍包含多个学生,所以在宿舍类中要用Set类来进行设置,用set类(private Set users = new HashSet();)来存储多个学生类,在映射宿舍类(Room)中要包含<set>这个节点,用来与user相关联

例如:<set name="users" table="USER">
            <key column="ROOM_ID"/>
            <one-to-many class="onlyfun.caterpillar.User"/>
        </set>

name:表示属性,table:表示关联的表名,key:表示通过什么字段进行关联,<one-to-many>:表示关联类。这里也可以使用cascade属性。

三、在表关联的设计中,不论是一对多还是多对一,都要将关联字段设置在多的那一方。
例如:user表格和room表格,要将关联字段room_id设置在user表格中。

四、一对一进行关联(一个人只有一个房间,一个房间也只有一个人)。
可以通过2中方式进行关联:

(1)、通过外键进行关联:在多对一的例子中就是通过外键进行关联的.
在user-room的设置中(user.hbm.xml):
<many-to-one name="room"
                     column="ROOM_ID"
                     class="onlyfun.caterpillar.Room"
                     cascade="all"
                     unique="true"/>

其中unique表示限制一個User有一獨有的 Room,这只是单向的,说明一个user只有一个room.
在room-user的设置中(room.hbm.xml):
<one-to-one name="user"
                    class="onlyfun.caterpillar.User"
                    property-ref="room"/>
这样就完成了双向的一对一关联,property-ref告诉hibernate,查询出user并将其参考至room。
(2)、通过主键进行关联:限制兩個資料表的主鍵使用相同的值,如此一個User與Room就是一對一關係
user.hbm.xml:
<one-to-one name="room"
                    class="onlyfun.caterpillar.Room"
                    cascade="all"/>
room.hbm.xml:
<one-to-one name="user"
                    class="onlyfun.caterpillar.User"
                    constrained="true"/>

使用constrained="true"告訴Hibernate參考至User的主鍵

五、双向关联,就是将一和二结合起来,如果將關聯的維護交給User的話會比較容易,因為每個User都對應至一個Room,在儲存時並用像Room一樣必須對Set中的每個物件作檢查,為了將關聯的維護交給User,我們可以在Room.hbm.xml中的<set>修改,加上inverse="true",表示將關聯的維護「反過來」交給User作

 例如:<set name="users" table="users" iinverse="true" cascade="all">
              <key  column="room_id"/>
              <one-to-many class="onlyfun.caterpillar.User"/>

在設立雙向關聯時,關聯由多對一中「多」的哪一方維護,會比由「一」的哪一方維護來的方便,在Hibernate可以藉由inverse來設定,不設定inverse基本上也可以運行,但是效能會較差。


------------------------------------------------------------------------------------------------------------------------
      在Hibernate中,集合類的映射可以延遲初始(Lazy Initialization),在多对一或者一对多中,都可以使用延遲初始,例如:一个用户(user对应user表)有多个email地址(address对应address表),也就是在真正索取該物件的資料時,才向資料庫查詢,就上次例子來說,就是我們在讀取User時,先不取得其中的 addrs屬性中之物件資料,由於只需要讀取User的name屬性,此時我們只要執行一次select即可,真正需要addrs的資料時,才向資料庫要求。在含有集合类的user.hbm.xml中要如下设置:

  <set name="addrs" table="ADDRS" lazy="true">
            <key column="USER_ID"/>
            <element type="string" column="ADDRESS" not-null="true"/>
        </set>

--------------------------------------------------------------------------------------------------------------------------
      session是hibernate运做的核心,是有SessionFactory所创建,sessionFactory是线程安全的,你可以让多个线程同时存取SessionFactory,而不会有资源共用的问题,然而session不是设计为线程安全的,所以让多个线程共用一个session,将发生资料共用而发生混乱的问题.下面是一个标准类.

import java.io.Serializable;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;
public class HibernateSessionUtil implements Serializable
{
     //创建线程局部变量 tLocalsess 
    public static final ThreadLocal tLocalsess = new ThreadLocal();
   //创建线程局部变量 tLocaltx
public static final ThreadLocal tLocaltx = new ThreadLocal();
      //取得session
    public static Session currentSession(){
         //从线程变量tLocalsess中,取得当前session
Session session = (Session) tLocalsess.get();
//判断session是否为空,如果为空,将创建一个session,并付给线程变量tLocalsess
    try{
if (session == null){
session = openSession();
tLocalsess.set(session);
}
}catch (HibernateException e){
throw new InfrastructureException(e);
}
return session;
}
//关闭当前session
    public static void closeSession(){
         //从线程变量tLocalsess中,取得当前session
Session session = (Session) tLocalsess.get();
         //设置线程变量tLocalsess为空
tLocalsess.set(null);
try{
            //关闭session
if (session != null && session.isOpen()){
session.close();
}
}catch (HibernateException e){
throw new InfrastructureException(e);
}
}
//事物处理
    public static void beginTransaction(){
      //从线程变量tLocaltx中取得事物管理对象Transaction
        Transaction tx = (Transaction) tLocaltx.get();
try{
            //如果为空就从session中创建一个tx
if (tx == null){
tx = currentSession().beginTransaction();
tLocaltx.set(tx);
}
}catch (HibernateException e){
throw new InfrastructureException(e);
}
}
//提交事物
    public static void commitTransaction(){
      //取得事物
Transaction tx = (Transaction) tLocaltx.get();
try{
            //如果不为空就提交
if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack())
tx.commit();
tLocaltx.set(null);
}catch (HibernateException e){
throw new InfrastructureException(e);
}
}
    //事物回滚    
    public static void rollbackTransaction(){
         //取得tx事物
Transaction tx = (Transaction) tLocaltx.get();
try{
            //将变量清空
tLocaltx.set(null);
if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()){
                //事物回滚
tx.rollback();
}
}catch (HibernateException e){
throw new InfrastructureException(e);
}
}
   //取得session
private static Session openSession() throws HibernateException{
return getSessionFactory().openSession();
}
   //取得sessionFactory
private static SessionFactory getSessionFactory() throws HibernateException{
return SingletonSessionFactory.getInstance();
}
}
filter的代码:
public class HibernateSessionCloser implements Filter{
protected FilterConfig filterConfig = null;
public void init(FilterConfig filterConfig)throws ServletException{
this.filterConfig = filterConfig;
}
public void destroy(){
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
try{
chain.doFilter(request, response);
}
finally{
try{
HibernateSessionUtil.commitTransaction();
}catch (InfrastructureException e){
HibernateSessionUtil.rollbackTransaction();
}finally{
HibernateSessionUtil.closeSession();
}
}
}
}
---------------------------------------------------------------------------------------

      (1)、悲觀鎖定(Pessimistic Locking)一如其名稱所示,悲觀的認定每次資料存取時,其它的客戶端也會存取同一筆資料,因此對該筆資料進行鎖定,直到自己操作完成後解除鎖定。 

      悲觀鎖定通常透過系統或資料庫本身的功能來實現,依賴系統或資料庫本身提供的鎖定機制,Hibernate即是如此,可以利用Query或 Criteria的setLockMode()方法來設定要鎖定的表或列(Row)及其鎖定模式,可設定的鎖定模式有以下的幾個:
  • LockMode.WRITE:在insert或update時進行鎖定,Hibernate會在save()方法時自動獲得鎖定。
  • LockMode.UPGRADE:利用SELECT ... FOR UPDATE進行鎖定。
  • LockMode.UPGRADE_NOWAIT:利用SELECT ... FOR UPDATE NOWAIT進行鎖定,在Oracle環境下使用。
  • LockMode.READ:在讀取記錄時Hibernate會自動獲得鎖定。
  • LockMode.NONE:沒有鎖定。

          (2)、樂觀鎖定(Optimistic locking)則樂觀的認為資料的存取很少發生同時存取的問題,因而不作資料庫層次上的鎖定,為了維護正確的資料,樂觀鎖定使用應用程式上的邏輯實現版本控制的解決。 

          在不實行悲觀鎖定策略的情況下,資料不一致的情況一但發生,有幾個解決的方法,一種是先更新為主,一種是後更新的為主,比較複雜的就是檢查發生變動的資料來實現,或是檢查所有屬性來實現樂觀鎖定。
          要注意的是,由於樂觀鎖定是使用系統中的程式來控制,而不是使用資料庫中的鎖定機制,因而如果有人特意自行更新版本訊息來越過檢查,則鎖定機制就會無效,例如在上例中自行更改userV2的version屬性,使之與資料庫中的版本號相同的話就不會有錯誤,像這樣版本號被更改,或是由於資料是由外部系統而來,因而版本資訊不受控制時,鎖定機制將會有問題,設計時必須注意。

  • posted @ 2008-01-10 11:40 灵! 阅读(197) | 评论 (0)编辑 收藏

    持久层的组成(转)

    持久层的组成
        这一节的名字应该换成“基于Hibernate的持久层的组成”更合适一点,可是它太长了。既然Hibernate是用来开发持久层,那么我先介绍一下这个持久层中的各个元素。
    1.    POJO:Plain Old Java Object,你可以把它看作是简单的JavaBean。一般说来,一张数据库表对应一个POJO,也就是对象/关系的一一映射。
    2.    DAO:对于每一个POJO,一般都有一个DAO与之对应,承担所有关于该POJO的访问控制。实际上也就是控制了对数据库中一张表的访问控制。
    3.    *.hbm.xml文件:这个文件定义了POJO和数据库中的表是如何映射的,比如POJO中的字段对应数据库表中的哪个字段等等。一般每个映射都用单独的文件来描述,也就是有一个POJO就有一个*.hbm.xml文件。
    4.    *.cfg.xml文件:这个文件定义了Hibernate的基本信息,比如数据库驱动,用户名,密码等等连接信息,也包括了所有要用的*.hbm.xml文件,在初始化的时候,Hibernate会读取这个文件来找相应的映射文件完成对象/关系。
    我们还是以上文的例子来详细描述一下这里提到的各个元素的内容。
    1.    Student.java:
    代码片段4:
    1. public class Student  implements java.io.Serializable 
    2. {
    3.     private String id;
    4.     private String name;
    5.     private Set courseSelections = new HashSet(0);
    6.     public Student() 
    7.     {
    8.     }
    9.     public String getId() 
    10.     {
    11.         return this.id;
    12.     }
    13.     
    14.     public void setId(String id) 
    15.     {
    16.         this.id = id;
    17.     }
    18.     public String getName() 
    19.     {
    20.         return this.name;
    21.     }
    22.     
    23.     public void setName(String name) 
    24.     {
    25.         this.name = name;
    26.     }
    27.     public Set getCourseSelections() 
    28.     {
    29.         return this.courseSelections;
    30.     }
    31.     
    32.     public void setCourseSelections(Set courseSelections) 
    33.     {
    34.         this.courseSelections = courseSelections;
    35.     }
    36. }

    这个类就是一个POJO,你可以很明显的看出来它就是一个JavaBean。我想解释它的courseSelection字段。很显然,在数据库表student中,没有这个字段。这里的这个字段是因为一个外键引用,course_selection的student_id是一个外键,引用了student表中的id字段。那么在Student类中courseSelection来记录这样的外键关系,也就是说,当我们获取了Student对象以后,就可以直接获取他的选课记录,这样就为上层的调用提供了很大的方便。这里有点模糊没关系,我在介绍映射定义文件(*.hbm.xml)的时候还会提到这个问题。
    2.    StudentDAO.java
    代码片段5:
    1. public class StudentDAO 
    2. {
    3.     Session session;
    4.     public StudentDAO()
    5.     {
    6.         Configuration cfg = new Configuration();
    7.         cfg.configure("/hibernate.cfg.xml");
    8.         SessionFactory sessionFactory = cfg.buildSessionFactory();
    9.         session = sessionFactory.openSession();
    10.     }
    11.     
    12.     public void save(Student transientInstance) 
    13.     {
    14.         session.save(transientInstance);
    15.     }
    16.     
    17.     public void delete(Student persistentInstance) 
    18.     {
    19.         session.delete(persistentInstance);
    20.     }
    21.     
    22.     public Student findById(java.lang.String id) 
    23.     {
    24.         List list = session.createCriteria(Student.class).add(
    25. Expression.eq("id", id)).list();
    26.         if (list.size() > 0) 
    27.         {
    28.             return (Student)list.get(0);
    29.         }
    30.         return null;
    31.     }
    32. }

    这里的构造函数是用来启动Hibernate,并获取session。打开一个session就相当于打开了一个数据库连接,然后我们就可以对这个session进行操作,完成数据库操作,完全不用写SQL语句。我这里Hibernate的启动方式写的很不规范,系统应该只需要完成一次Hibernate启动就可以在不同的DAO中使用,我把它写在构造函数里面纯粹是为了简化演示代码。
    你可以看到save和delete方法都很简单直接对对象操作,而findById就有些麻烦,因为这里有一个查询过程在里面。Hibernate里面查询可以用Criteria这个类来完成,我们也常用Hibernate独有的HQL(Hibernate Query Language)来完成查询。当然Hibernate也是支持原生SQL的。关于查询的详细信息请参考其他文章或书籍,我只是演示一个流程,介绍一些概念。
    3.    Student.hbm.xml
    代码片段6:
    1. <hibernate-mapping>
    2.     <class name="Student" table="STUDENT">
    3.         <id name="id" type="string">
    4.             <column name="ID" length="10" />
    5.             <generator class="assigned" />
    6.         </id>
    7.         <property name="name" type="string">
    8.             <column name="NAME" not-null="true" />
    9.         </property>
    10.         <set name="courseSelections" inverse="true">
    11.             <key>
    12.                 <column name="STUDENT_ID" length="10" 
    13. not-null="true" />
    14.             </key>
    15.             <one-to-many class="CourseSelection" />
    16.         </set>
    17.     </class>
    18. </hibernate-mapping>

    这个文件定义了Student类和Student表是如何映射的。class元素定义了Sudent类和STUDENT表映射,然后就定义了各个属性是如何映射的。如果一个属性是数据库的key,那么会用id标签来定义,column定义了当前类的属性和数据库中的哪个字段对应,generator是id特有的。一般来说id是自增的,由于我的数据库是用的Oracle,它没有自增字段,要实现自增必须用Sequence,这超出了本文的范围,所以我就用assigned来简化示例代码。assigned表示id是用户给定的。
    有一个比较特别的标签是set,它对应着数据库中的外键关系,上文我提到的通过Student对象可以获得所有相关的选课记录就是通过这里的定义实现的。name属性对应了Student类中的字段名,key表示哪个字段是外键,one-to-many表示Student和CourseSelection是一对多关系,这和事实相符。类似的还有many-to-one,many-to-many,不过这些都不常用,我不介绍了。Hibernate根据这个映射定义文件,在实例化一个POJO(比如Student)的时候,会自动的把定义过映射的属性用数据库中的数据填充,set也包括在内。
    4.    hibernate.cfg.xml
    代码片段7:
    1. <hibernate-configuration>
    2.     <session-factory>
    3.         <property name="connection.username">test</property>
    4.         <property name="connection.url">
    5. jdbc:oracle:thin:@10.85.33.199:1521:glee</property>
    6.         <property name="dialect">
    7. org.hibernate.dialect.Oracle9Dialect</property>
    8.         <property name="connection.password">test</property>
    9.         <property name="connection.driver_class">
    10. oracle.jdbc.OracleDriver</property>
    11.         <mapping resource="Student.hbm.xml"></mapping>
    12.         <mapping resource="CourseSelection.hbm.xml"></mapping>
    13.         <mapping resource="Course.hbm.xml"></mapping>
    14.     </session-factory>
    15. </hibernate-configuration>

    这个文件我不解释了,自己看吧。结合上文StudentDAO的例子,我想你应该能看明白。
    看了这么多,或许你会有点头皮发麻,POJO,DAO,配置文件...好像要写的东西还是很多。值得庆幸的是现在Hibernate已经发展的比较成熟了,有很多工具来帮助我们完成这些工作,比如MiddleGen,Hibernate Synchronizer等等。我使用的开发工具是Eclipse+MyEclipse,我所要做的只是把数据库表建好,然后MyEclipse提供的工具会自动根据数据库表生成POJO,DAO,*.hbm.xml,甚至hibernate.cfg.xml都是自动完成的(前提是MyEclipse知道你的数据库连接信息)。我并不打算介绍如何用IDE来开发Hibernate,你可以参考IDE的帮助文档。
    到这里为止,使用Hibernate进行开发的基本组成元素我都介绍好了,强烈建议你马上实践一遍,即使有些不理解,也先依葫芦画瓢一个。对了,别忘了把Hibernate的包down下来放到classpath里面。

    三、Session与SessionFactory
    Session可以说是Hibernate的核心,Hibernate对外暴露的接口就是Session。所以我这里讲一下有关Session的常用函数和特性。
    在讲Session之前,我想先提一下SessionFactory,这个东西不复杂,只要配置好就行了。顾名思义,SessionFactory就是用来创建Session的。SessionFactory是线程安全的,也就是说对于同一个数据库的所有操作共享一个SessionFactory就行了。回头看代码片段5,我们可以看到SessionFactory的常用配置方式。
    代码片段8:
    1. Configuration cfg = new Configuration();
    2. cfg.configure("/hibernate.cfg.xml");
    3. SessionFactory sessionFactory = cfg.buildSessionFactory();

    我们通过Configuration来读取配置文件,然后就可以创建SessionFactory,这段代码在    所有系统中都大同小异,一般就是xml配置文件的名字不一样,所以也没什么好说的。
    当我们有了SessionFactory以后就可以获取Session了。调用SessionFactory.openSession()就会返回一个Session实例,然后我们操作这个Session来访问数据库。值得一提的是Session并不是线程安全的,也就是每一个线程都必须有自己的Session。所以我们一般通过以下方法来获取和关闭Session:
    代码片段9:
    1. public static Session currentSession() throws HibernateException 
    2.     {
    3.         Session session = (Session) threadLocal.get();
    4.         if (session == null || !session.isOpen()) 
    5.         {
    6.             if (sessionFactory == null
    7.             {
    8.                 try 
    9.                 {
    10.                     cfg.configure(CONFIG_FILE_LOCATION);
    11.                     sessionFactory = cfg.buildSessionFactory();
    12.                 } 
    13.                 catch (Exception e) 
    14.                 {
    15.                     e.printStackTrace();
    16.                 }
    17.             }
    18.             session = (sessionFactory != null) ?
    19.                  sessionFactory.openSession(): null;
    20.             threadLocal.set(session);
    21.         }
    22.         return session;
    23. }
    24. public static void closeSession() throws HibernateException 
    25.     {
    26.         Session session = (Session) threadLocal.get();
    27.         threadLocal.set(null);
    28.         if (session != null
    29.         {
    30.             session.close();
    31.         }
    32. }

    可以看到,我们通过threadLocal来保存每个线程的session,这样就保证了各个线程之    间的互不干扰,也保证了系统只有一个SessionFactory实例(对于大多数应用来说已经    足够了)。如果你使用MyEclipse进行开发的话,它会自动生成一个    HibernateSessionFactory.java,其中就包含了以上代码。
    好了,现在我们已经获得了Session,下面我来介绍以下Session的常用函数,这些函数都有很多重载函数,我只介绍以下大概是干嘛的,不一一解释,详细信息你可以查看Hibernate的API。
    1.Session.get(),获取某个类的实例,一般都是通过id来获取比如
    Session.get(Student.class, "0361095");
    这句话的意思就是获取id(primary key)为“0361095”的Student对象。这里要注    意的是第二个参数必须是Object,也就是说,如果是long类型的1,那么必须转换    成new Long(1)再传入。
    2.Session.load(),用法和意义都和get一样,不过它们还是有点区别,我稍后解释。
    3.Session.save(),将某个实例保存到数据库中去(往往在数据库中形成一条新的记录)。
    4.Session.update(),更新某个实例,这个实例必须和数据库中有对应,否则会报错。
    5.Session.delete(),删除某个实例,也就是删除这个实例对应的数据表中的数据。
    6.Session.saveOrUpdate(),保存或者更新某个实例,调用这个方法你就不用去关心到        底是save还是update了,它会自己判断,然后调用相应的函数。其实save和update        涉及到实体对象生命周期中的三种状态,这个比较重要,我在后面会单独讲的。
    对于get和load的区别,很难讲清楚,这里涉及到Hibernate的缓存机制,是一个非常    复杂的话题,我不打算深入讨论这个内容。简单的来讲,Session实现了Hibernate的一    级缓存,SessionFactory实现了Hibernate的二级缓存。load方法会先查找一级缓存再查    找二级缓存,最后再去数据库中找,而get只会查找一级缓存,然后就去数据库中找了。    这只是是get和load的一个区别,另外的区别如果你有兴趣的话自己去google吧。关于Hibernate的缓存机制,如果你只是一般用用Hibernate的话没有必要深入研究,就当它不存在好了,get和load到底用哪个也不用非常讲究,如果你用工具生成DAO的话,    生成的代码用什么就用什么吧。

    四、关键概念的理解
    在使用Hibernate进行开发的时候有几个概念在我看来是必须理解的,否则在开发的时候会遇到很多问题而摸不着头脑。
    1.Lazy loading,懒加载(延迟加载)
    这个技术在很多地方被应用,比如Eclipse的插件管理也是用的延迟加载。在Hibernate中,所谓延迟加载就是返回一个POJO但是某些数据(往往是实体类型或者Set类型)并没有被真正的被填充,直到POJO的某个字段真正被引用的时候才从数据库中读取相应的数据来填充POJO中的字段。这样就能有效的避免很多不必要的数据库操作,因为POJO的有些数据我们并不需要,而且数据库操作是很费时间的。在Hibernate2中,默认是非延迟加载的,而在Hibernate3中,默认就是延迟加载了。
    如果使用了延迟加载,那么在读取数据的时候有一个问题必须注意,那就是在数据真正被加载之前,Session不能被关闭。你可以回头看一下代码片段5,我在构造函数里面open了session以后就没有关闭这个session,所以我在使用的时候没有什么问题,但这样总占着数据库连接也不好,用好了应该及时关闭给别人用。我上文给的例子中没有关闭Session的代码,要加的话给DAO加一个方法调用Session.close(),然后在代码片段1中的return之前调用这个方法就行了。
    Hibernate的延迟加载机制远不是这么简单,但是普通的应用没有必要去深究这些东西,了解这么多就够了。

    2. Object lifecycle,对象生命周期
    在Hibernate中,对象分为三种状态,Transient(自由状态)、Persistent(持久状态),Detached(游离状态),下面我分别解释一下。
    1、自由状态:所谓自由状态就是说这个对象是自由的,与Hibernate无关,比       如:
    Student student = new Student();
        student.setId("0361095");
                    这里的student就是一个普通的对象与hibernate无关,称为自由状态。

    2、持久状态:所谓持久状态就是指对象和数据库中的数据(持久状态的数据)       有关联,也就是说对象被Hibernate所管理了,比如:
    session.save(student);
       这样student对象就从自由状态变为持久状态了。持久状态的对象在Session       与数据库中的数据进行同步时(比如commit)会把数据更新到数据库。而         其他状态的则不会。我觉得可以这样来理解持久状态,可以看成Hibernate       也拥有一份对象的引用,那么如果你对持久状态对象的属性进行更改的话,       Hibernate看到的对象的状态也更改了,而Hibernate所看到的对象和数据       库中的数据是等价的。也正是这样,Hibernate才实现了Object/Relation       的映射。类似的,load和get方法也一样会获取Persistent状态的对象。

    3、游离状态:每次调用Session.close以后,所有跟这个session有关的处于
    Persistant的对象就变成了游离状态。也许你要问Detached和Transient有什么区别。其实从我给的例子来说看不出什么区别,因为我这里ID是给定的,而真正开发的时候ID往往是自增的,那么Transient的对象是没有ID    的,当save了以后就有了,显而易见Detached的对象也是有ID,只不过这个对象已经和Hibernate脱离了关系。但是游离状态的对象仍然和数据库    中的记录有一定联系,至少游离状态的对象知道数据库中有条记录的ID为xxx。从这一点上来讲,游离状态是可以自己创造出来的,只要你知道数据库中的主键信息。
    在使用Hibernate开发的时候要分清楚这三种状态,否则很容易出错。比如不能去save一个游离状态的对象,不能去update一个自由状态的对象等等。

    五、结束语
    我要讲的就这么多,这篇文章不是详细介绍Hibernate,我只是总结了自己学习和使用Hibernate的一些感受和经验,希望能给没有用过Hibernate的开发者一个上手的指引。如果你看完了这篇文章仍然满头雾水,无从下手的话,我只能向你表示歉意,浪费你的时间了。不管怎样,我强烈推荐一本书《深入浅出Hibernate》,这本书既能作为学习的教程,也能作为日后的查询用书,相当实用。

    posted @ 2008-01-10 11:39 灵! 阅读(218) | 评论 (0)编辑 收藏

    JAVA数据类型转换

    基本类型有以下四种:
    int长度数据类型有:byte(8bits)、short(16bits)、int(32bits)、long(64bits)、
    float长度数据类型有:单精度(32bits float)、双精度(64bits double)
    boolean类型变量的取值有:ture、false
    char数据类型有:unicode字符,16位
    对应的类类型:
    Integer、Float、Boolean、Character、Double、Short、Byte、Long


    转换原则:
    从低精度向高精度转换
    byte 、short、int、long、float、double、char
    注:两个char型运算时,自动转换为int型;当char与别的类型运算时,也会先自动转换为int型的,再做其它类型的自动转换

    基本类型向类类型转换

    正向转换:
    通过类包装器来new出一个新的类类型的变量
    Integer a= new Integer(2);

    反向转换:
    通过类包装器来转换
    int b=a.intValue();
    类类型向字符串转换


    正向转换:
    因为每个类都是object类的子类,而所有的object类都有一个toString()函数,所以通过toString()函数来转换即可

    反向转换:
    通过类包装器new出一个新的类类型的变量
    eg1: int i=Integer.valueOf(“123”).intValue()
    说明:上例是将一个字符串转化成一个Integer对象,然后再调用这个对象的intValue()方法返回其对应的int数值。
    eg2: float f=Float.valueOf(“123”).floatValue()
    说明:上例是将一个字符串转化成一个Float对象,然后再调用这个对象的floatValue()方法返回其对应的float数值。
    eg3: boolean b=Boolean.valueOf(“123”).booleanValue()
    说明:上例是将一个字符串转化成一个Boolean对象,然后再调用这个对象的booleanValue()方法返回其对应的boolean数值。
    eg4:Double d=Double.valueOf(“123”).doubleValue()
    说明:上例是将一个字符串转化成一个Double对象,然后再调用这个对象的doubleValue()方法返回其对应的double数值。
    eg5: long l=Long.valueOf(“123”).longValue()
    说明:上例是将一个字符串转化成一个Long对象,然后再调用这个对象的longValue()方法返回其对应的long数值。
    eg6: char=Character.valueOf(“123”).charValue()
    说明:上例是将一个字符串转化成一个Character对象,然后再调用这个对象的charValue()方法返回其对应的char数值。


    基本类型向字符串的转换

    正向转换:
    如:int a=12;
    String b;
    b=a+””;

    反向转换:
    通过类包装器
    eg1:
    int i=Integer.parseInt(“123”)
    说明:此方法只能适用于字符串转化成整型变量
    eg2: float f=Float.valueOf(“123”).floatValue()
    说明:上例是将一个字符串转化成一个Float对象,然后再调用这个对象的floatValue()方法返回其对应的float数值。
    eg3: boolean b=Boolean.valueOf(“123”).booleanValue()
    说明:上例是将一个字符串转化成一个Boolean对象,然后再调用这个对象的booleanValue()方法返回其对应的boolean数值。
    eg4:Double d=Double.valueOf(“123”).doubleValue()
    说明:上例是将一个字符串转化成一个Double对象,然后再调用这个对象的doubleValue()方法返回其对应的double数值。
    eg5: long l=Long.valueOf(“123”).longValue()
    说明:上例是将一个字符串转化成一个Long对象,然后再调用这个对象的longValue()方法返回其对应的long数值。
    eg6: char=Character.valueOf(“123”).charValue()
    说明:上例是将一个字符串转化成一个Character对象,然后再调用这个对象的charValue()方法返回其对应的char数值。

    posted @ 2008-01-10 11:38 灵! 阅读(163) | 评论 (0)编辑 收藏

    java 数据库基本操作

    java 数据库基本操作

      1、java数据库操作基本流程

      2、几个常用的重要技巧:

      ·可滚动、更新的记录集

      ·批量更新

      ·事务处理

      java数据库操作基本流程:取得数据库连接 - 执行sql语句 - 处理执行结果 - 释放数据库连接

      1、取得数据库连接

      1)用DriverManager取数据库连接

      例子

      String className,url,uid,pwd;

      className = "oracle.jdbc.driver.OracleDriver";

      url = "jdbc:oracle:thin:@127.0.0.1:1521:orasvr;

      uid = "system";

      pwd = "manager";

      Class.forName(className);

      Connection cn = DriverManager.getConnection(url,uid,pwd);

      2)用jndi(java的命名和目录服务)方式

      例子

      String jndi = "jdbc/db";

      Context ctx = (Context) new InitialContext().lookup("java:comp/env");

      DataSource ds = (DataSource) ctx.lookup(jndi);

      Connection cn = ds.getConnection();

      多用于jsp中

      2、执行sql语句

      1)用Statement来执行sql语句

      String sql;

      Statement sm = cn.createStatement();

      sm.executeQuery(sql); // 执行数据查询语句(select)

      sm.executeUpdate(sql); // 执行数据更新语句(delete、update、insert、drop等)statement.close();

      2)用PreparedStatement来执行sql语句

      String sql;

      sql = "insert into user (id,name) values (?,?)";

      PreparedStatement ps = cn.prepareStatement(sql);

      ps.setInt(1,xxx);

      ps.setString(2,xxx);

      ...

      ResultSet rs = ps.executeQuery(); // 查询

      int c = ps.executeUpdate(); // 更新

      3、处理执行结果

      查询语句,返回记录集ResultSet

      更新语句,返回数字,表示该更新影响的记录数

      ResultSet的方法

      1、next(),将游标往后移动一行,如果成功返回true;否则返回false

      2、getInt("id")或getSting("name"),返回当前游标下某个字段的值

      4、释放连接

      cn.close();

      一般,先关闭ResultSet,然后关闭Statement(或者PreparedStatement);最后关闭Connection

      可滚动、更新的记录集

      1、创建可滚动、更新的Statement

      Statement sm = cn.createStatement(ResultSet.TYPE_SCROLL_ENSITIVE,ResultSet.CONCUR_READ_ONLY);

      该Statement取得的ResultSet就是可滚动的

      2、创建PreparedStatement时指定参数

      PreparedStatemet ps = cn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);

      ResultSet.absolute(9000);

      ·批量更新

      1、Statement

      Statement sm = cn.createStatement();

      sm.addBatch(sql1);

      sm.addBatch(sql2);

      ...

      sm.executeBatch()

      一个Statement对象,可以执行多个sql语句以后,批量更新。这多个语句可以是delete、update、insert等或兼有

      2、PreparedStatement

      PreparedStatement ps = cn.preparedStatement(sql);

      {

      ps.setXXX(1,xxx);

      ...

      ps.addBatch();

      }

      ps.executeBatch();

      一个PreparedStatement,可以把一个sql语句,变换参数多次执行,一次更新。

      ·事务的处理

      1、关闭Connection的自动提交

      cn.setAutoCommit(false);

      2、执行一系列sql语句

      要点:执行每一个新的sql语句前,上一次执行sql语句的Statement(或者PreparedStatemet)必须先close

      Statement sm ;

      sm = cn.createStatement(insert into user...);

      sm.executeUpdate();

      sm.close();

      sm = cn.createStatement("insert into corp...);

      sm.executeUpdate();

      sm.close();

      3、提交

      cn.commit();

      4、如果发生异常,那么回滚

      cn.rollback();

    posted @ 2008-01-10 11:37 灵! 阅读(166) | 评论 (0)编辑 收藏

    可以开始用Struts2.0了

    Apache已经发布了Struts2.0的正式版,即2.0.6GA版本。这个版本已经可以在项目中正式使用了。当然大家一定很关心,从webwork2.2迁移到struts2.0麻烦不麻烦,请看Struts2.0的FAQ:

    引用
    Essentially, Struts 2.0 is the technical equivalent of WebWork 2.3. Aside from the package and property renaming, it isn't much different than, say, migrating from WebWork 2.1 to 2.2.


    Struts2.0其实就是webwork2.3而已,从webwork2.2迁移到struts2.0不会比从webwork2.1到2.2更麻烦。

    webwork2.2和struts2.0差异对比:
    http://struts.apache.org/2.x/docs/key-changes-from-webwork-2.html

    迁移步骤:
    http://struts.apache.org/2.x/docs/webwork-2-migration-strategies.html

    总结:

    大致来说,struts2.0就是把package和配置文件的名字改了改而已,别的没有做什么改动,所以现在用struts2.0和用webwork2.2没有多大区别。当然这迁移一迁就是将近两年,还是有点进步的:

    1、搭配struts2.0的xwork版本必须使用xwork2.0.1,而xwork2.0.1集成了可选的Google Guice IoC容器
    2、Struts2.0弄了一个plugin机制,来适配各种扩展机制
    3、全面引入annotation语法,验证,拦截都可以用annotation了。

    所以用webwork的同志们,大胆的迁移到struts2.0来吧。

    posted @ 2008-01-08 20:21 灵! 阅读(259) | 评论 (1)编辑 收藏

    缓存简述

    缓存实现的层面有很多:

    1、对象缓存
    由ORM框架提供,透明性访问,细颗粒度缓存数据库查询结果,无需业务代码显式编程。当软件结构按照ORM框架的要求进行针对性设计,使用对象缓存将会极大降低web系统对于数据库的访问请求。因为类似Hibernate这样的ORM,良好的设计数据库结构和利用对象缓存,在大负载网站,能够提供极高的性能。因为使用对象缓存也无需显式编程,所以适用范围也最广泛。

    2、查询缓存
    对数据库查询结果行集进行缓存,适用于一些耗时,但是时效性要求比较低的场景。iBATIS就只能使用查询缓存,而无对象缓存。查询缓存和对象缓存适用的场景不一样,是互为补充的。

    3、片断缓存
    针对动态页面的局部片断内容进行缓存,适用于一些个性化但不经常更新的页面(例如博客)。OSCache提供了相当简陋的片断缓存,而RoR则提供了相当好的片断缓存机制。

    4、Action缓存
    针对URL访问返回的页面结果进行缓存,适用于粗粒度的页面缓存,例如新闻发布。OScache提供了相当简陋的Action缓存(通过web.xml中的配置),而RoR提供了相当好的Action缓存。

    缓存不能一概而论,以上每种缓存分别适用于各自的场景,缓存不同的层面。当然你可以在应用程序当中把4种缓存一起用上。

    posted @ 2008-01-08 20:19 灵! 阅读(149) | 评论 (0)编辑 收藏

    iReport 报表在应用程序中的应用代码(转载)

    import dori.jasper.engine.*;
    import dori.jasper.engine.util.*;
    import java.sql.*;
    import java.util.*;
    import dori.jasper.engine.JasperReport;
    import java.util.Date;
    import java.text.SimpleDateFormat;
    import dori.jasper.view.*;
    import org.apache.commons.logging.LogFactory;
    import com.lowagie.text.DocumentException;
    import com.lowagie.text.*;
    import dori.jasper.engine.design.*;
    import org.apache.commons.digester.Digester;
    import org.apache.commons.beanutils.BeanUtils;

    public class myreport
    {
     public void reportName(String strBbmc)
     {
      JRResultSetDataSource jrds = null;
      JasperPrint jasperPrint = null;
      Map reportParams = new HashMap();
      ResultSet rs = null;
      Connection con = null;
      Statement stmt = null;
      String sql = "select * from  bbmc";
      try
       {
        //动态获取
        JasperDesign jasperDesign = JasperManager.loadXmlDesign("./bbmc.jrxml");
        JasperReport jasperreport = JasperManager.compileReport(jasperDesign);
        //建立连接
        ConnectionpoolManager mgr = new ConnectionpoolManager();
        mgr.setMonitorThread(520);
        mgr.addAlias("jdbcConnecpool","com.microsoft.jdbc.sqlserver.SQLServerDriver","jdbc:microsoft:sqlserver://192.168.45.233:1433;DatabaseName = ysgl ","sa","sa",10,300,520,30,false);
        con = DriverManager.getConnection(ConnectionPoolManager.URL_PREFIX+ConnectionPoolManager.getPoolName(),null,null);
        stmt = con.creatStatement();
        rs = stmt.executeQuery(sql);
        jrds = new JRResultSetDataSource(rs);
        jasperPrint = JasperFillManager.fillReport(jasperReport,reportParams,jrds);
        //调出JasperViewer进行打印预览
        JasperViewer.viewReport(jasperPrint);
       }
       catch(ClassNotFoundException ee)
        {
         ee.printStackTrace();
        }
       catch(SQLException ex)
        {
         ex.pritStackTrace;
        }
       catch(JRException e)
        {
         e.getMessage();
        }
     }
    }

    posted @ 2008-01-08 20:08 灵! 阅读(214) | 评论 (0)编辑 收藏

    JSP实现论坛树型结构的算法(非递归)

    实现论坛树型结构的算法很多,这里是一个不用递归实现树型结构的算法

    1.演示表的结构: 

        表名:mybbslist 
       字段     数据类型  说明 
       BBSID    自动编号   
       RootID    Int     根帖ID,本身为根帖则RootID = BBSID 
       FID     Int     父帖ID,上一层帖子的ID,如是根帖则FID = 0 
       DEPTH    Int     根帖Level=0,其他依据回复的深度递增 
       BBSSubject  Char    主题 



    2.创建表(可根据此表的结构在ACCESS中创建表): 


     create table mybbslist ( 
     forumID int(20) not null, 
     bbsID int auto_increment primary key, 
     rootid int(20) not null, 
     fid int(20) not null, 
     depth int(20) not null, 
     userID int(20) not null, 
     bbsUser varchar(24) not null, 
     bbsSubject varchar(100) not null, 
     bbsContent text, 
     bbsTime varchar(30), 
     bbsRead int(20), 
     bbsReply int(20), 
    INDEX forumID (forumID))  




    3.演示论坛树型结构的JSP程序,注意此程序只对一个根贴进行了演示(数据库用ACCESS)

     <%@ page contentType="text/html;charset=gb2312" %> 
    <%@ page import="java.io.*" %> 
    <%@ page import="java.sql.*" %> 
    <% 
     String driverName = "sun.jdbc.odbc.JdbcOdbcDriver"; 
     String connURL= "jdbc:odbc:cwb"; 
     Connection conn = null; 
     Statement stmt = null; 

    int intRowCount; 
    out.print("显示论坛树形结构"); 
    out.print("<br><br>"); 
    try { 
         Class.forName(driverName); 
         conn = DriverManager.getConnection(connURL); 
         stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
         String sql="select * from mybbslist order by rootid desc,depth,fid,bbsid"; 
         ResultSet rs = stmt.executeQuery(sql); 
         if (rs.next()){ 
                     rs.last(); 
                     intRowCount=rs.getRow(); 
                     out.print("论坛树中有"); 
                     out.print(intRowCount); 
                     out.print("个叶子节点"); 
                     rs.first(); 
                     int j=0; 
                     int Depth = 0; 
                     out.print("<ul>"); 
                     while(j<intRowCount){ 
                           int rsDepth=rs.getInt("depth"); 
                           if (rsDepth>Depth){ 
                                          out.print("<ul>"); 
                            } 
                            out.print("<li>"); 
                            String bbssubject=rs.getString("bbsSubject"); 
                            out.print(bbssubject); 
                            out.print("</li>"); 
                            Depth=rsDepth;
                            j=j+1; 
                            rs.next(); 
                     } 
                     for(int i=0;i<Depth+1;i=i+1) { 
                        out.print("</ul>"); 
                     } 
        }else{ 
                out.print("数据库中无记录"); 
        } 
    }catch (SQLException E) { 
          out.println("SQLException: " + E.getMessage()); 
          out.println("SQLState: " + E.getSQLState()); 
          out.println("VendorError: " + E.getErrorCode()); 

    %> 
    <% //关闭mysql连接 
    try { 
          if(conn!=null)  conn.close(); 
    } catch (Exception ex) { 
          System.err.println("closeConn: " + ex.getMessage()); 

    %> 

    posted @ 2008-01-08 20:07 灵! 阅读(202) | 评论 (0)编辑 收藏

    J2ME的高级图形界面

      最近在SUN的网站上看到一则关于J2ME GUI的文章:《The Java ME GUI APIs at a Glance 》。文章对MIDP 1.0, 2.0, 3.0的图形界面进行了阐述和比较。最吸引我的是Advanced Graphics and User Interface (AGUI),看这界面是不是很COOL,不过要CDC1.1才能运行,希望以后手机能发展到可以支持这样的图形界面。


    posted @ 2008-01-08 19:38 灵! 阅读(177) | 评论 (0)编辑 收藏

    如何做好质量保证工作(转)

        软件质量保证和软件控制都是得罪人的工作,并不是太好的做。经常是费力不讨好,最后人得罪了不少,力气费了不少,成效不大。而很多质量保证人员也不得不离开所在的单位。很多著名的公司为了搞好质量工作,采用国外先进的管理方法进行质量保证,但也往往遇到水土不服的问题,因为这个问题下岗的高级管理人员也不是一个两个了。为什么在国外很好的质量保证手段在中国就水土不服?为什么质量保证人员总是打一枪换一个地方(很多质量保证人员在一个地方工作的时间往往是2年左右)。如果我们一味强调客观因素,而不是从我们自身找问题,是没有办法真正找到解决这个的方法的。下边就我说说我自己的一些感受。

    1 质量保证工作,重流程,轻实施是我们的一个问题。

        现在的质量保证人员一般手里都不乏这样或那样的证书,拿我们软件质量保证人员来说,最基本的是ISO9000的证书,然后是CMM/CMMI,似乎没有这些证书就不适合搞质量保证工作。如果让他们规范单位开发流程,他们在几天之内就可以给你拿出一大堆流程文件来,而且可以保证这些问题是符合质量的要求。但一旦到了实施阶段,就会发现这些流程不能适应公司的具体要求,不是太繁琐,就是开发人员搞不明白,和技术人员矛盾不断涌现,如果你的对手只是普通的技术人员那算你走运,你还可以挺几年,但如果是和公司几个核心的开发人员产生矛盾,那你准备卷铺盖走人吧。一个公司没有质量保证人员不会死,但核心技术人员如果走了,公司就会面临倒闭的问题,再傻的老板到这个时候都会挥泪斩马谡的。所以,想真正实施好公司的质量保证一定要重流程,更重实施。

    2 质量保证工作,重知识,轻经验。

        我这里说的知识是指质量保证知识,经验是指实际工作经验,拿我们做SQA的来说就是你的开发经验,我遇到了很多SQA只有1-2年的开发经验,或者干脆就没有开发经验。想一下,没有调研经验的人去给一帮参加过7,8个大项目调研的人将如何调研,一个没有编写过设计文档的人,在给一群架构师讲解如何设计软件,一个没有代码编程经验的人给一帮代码量超过20万行的程序员讲代码规范,你说是不是一个可笑的事情,开发人员都是很实在的人(甚至有时候可以说比较傻的人),他们长期的工作经验使他们只信服那些实力比他们强的人,如果你有充足的实际工作经验(软件开发经验),说的问题到位,能够将质量保证理论和实际开发结合,可以帮助他们解决实际问题,他们很快就会接受你,否则他们会对你不屑一顾。而你的质量保证根本无法实施。

    3 质量保证人员不要抢功劳。

        一个公司就象一个盘子,盘子里的蛋糕就这么大。你进来了需要从别人的蛋糕里切一块,别人自然会有反弹,作为质量保证人员在这个时候最好的方法就是退后一步,将功劳让给开发人员。质量保证工作会涉及到公司的各个部门,各项工作,会影响公司几乎所有的工作人员,如果在这个时候,你想把所有的功劳都抢到自己手里,会树敌无数,一旦这种情况出现,一个是你的工作无法推行(基本没有人支持你),另外一个就是你不得不离开这个公司了。但如果你是聪明人,你帮助开发人员不断的改善他们的工作,他们可以很好的完成自己的开发工作,加班时间大大减少,产品质量不断提高,不断获得客户和领导的表扬,而且加了工资,你想在这种情况下,他们怎么会不配合你的工作?所以说,好的质量保证人员永远是站在成功者背后的那个人,他默默地做着自己的工作,为别人做绿叶。一个良好的心态才能真正搞好质量保证工作。在这里再多说一句,任何人的功劳都会得到回报。当公司的整体质量提升了,公司的效益提高了,你觉得老板会不明白这是谁的功劳吗?

    4 质量保证工作,不能一开始就全面开花,而要由点到线,由线到面。

        上边说了质量保证工作会涉及到单位工作的各个方面,在你刚进入到公司的时候,立刻会发现很多问题,但如何着手,需要一个谋划,一般来说比较容易见效果的,投入不大的方面是你首先要考虑的(有时候还不是公司最主要的质量问题)。如果你能在短时间让别人看到你的工作效果,见到成果,认可你的实力,才可能和他们达成一定的协作关系,为以后的质量保证工作铺平道路。另外需要说的,质量保证需要不断的投入人力和物力,而这些东西在你刚进入公司的时候往往是不具备的,分清事情的轻重缓急,难易程度,逐步实施质量保证。可以保证你的工作的顺利实施。

    5 做质量保证工作,最重要的是做人的工作,这里分两个问题来说明,一个是你要有自己可信赖的人员。

        打铁先要自身硬,做质量保证工作,不但你最好有技术背景,精通软件开发,遵守公司的规章制度,你还要有一支可培养,可信赖的质量保证队伍,一个人的精力和能力毕竟是有限的,而一旦你形成了一个良好的质量保证队伍就可以保证你的工作越做越有成效。另外一个就是善于借力打力。上边说过,绝大多数开发人员都渴望成功,他们缺少的只是经验,将你的经验和知识和他们分享,让他们成为的朋友,成为工作的伙伴,成为你的编外质量人员,这对那些质量保证人员编制比较少的质量保证部门格外重要。

    6 质量保证工作,遇到问题,先解决问题,找出原因,进行改进,而不要一味地追查责任。

        质量保证人员的责任是改进质量工作,提高整个公司的工作效率,而不是老板,去追查这是谁的责任。当一个问题发生的时候,所有的人员都在往后躲。怕承担责任,作为质量人员如果在这个时候,首先去追查责任,那你就大错特错了,首先我们要解决问题,看有什么补救的方法,先想办法将事情办好,然后仔细分析问题产生的原因,找到如何避免这个问题再次发生,至于责任在哪个责任人,自有具体的管理人员负责,这不是我们的责任,说简单一点,我们的责任就是协助一切工作人员做好他们的工作,而不是给人员裹乱。

    posted @ 2008-01-08 19:31 灵! 阅读(217) | 评论 (0)编辑 收藏

    SQA到底是什么?(转)

    一、 前言

    本文作者在企业从事SQA工作,同时兼任SEPG的工作进行基于CMM3的过程改进,在实践过程中,对SQA的工作有了较多的想法和认识。本文是个人看法,请大家指教,如果要和本人联系,请发Email到:heqingemail@163.net

    二、SQA的理论探索

    2.1、过程的;认识

    我们都知道一个项目的主要内容是:成本、进度、质量;良好的项目管理就是综合三方面的因素,平衡三方面的目标,最终依照目标完成任务。项目的这三个方面是相互制约和影响的,有时对这三方面的平衡策略甚至成为一个企业级的要求,决定了企业的行为,我们知道IBM的软件是以质量为最重要目标的,而微软的“足够好的软件”策略更是耳熟能详,这些质量目标其实立足于企业的战略目标。所以用于进行质量保证的SQA工作也应当立足于企业的战略目标,从这个角度思考SQA,形成对SQA的理论认识。

    软件界已经达成共识的:影响软件项目进度、成本、质量的因素主要是“人、过程、技术”。
    首先要明确的是这三个因素中,人是第一位的。
    现在许多实施CMM的人员沉溺于CMM的理论过于强调“过程”,这是很危险的倾向。这个思想倾向在国外受到了猛烈抨击,从某种意义上各种敏捷过程方法的提出就是对强调过程的一种反思。
    “XP”中的一个思想“人比过程更重要” 是值得我们思考的。我个人的意见在进行过程改进中坚持“以人为本”,强调过程和人的和谐。
    根据现代软件工程对众多失败项目的调查,发现管理是项目失败的主要原因。这个事实的重要性在于说明了“要保证项目不失败,我们应当更加关注管理”,注意这个事实没有说明另外一个问题“良好的管理可以保证项目的成功”。现在很多人基于一种粗糙的逻辑,从一个事实反推到的这个结论,在逻辑上是错误的,这种错误形成了更加错误的做法,这点在SQA的理解上是体现较深。
    如果我们考证一下历史的沿革,应当更加容易理解CMM的本质。CMM首先是作为一个“评估标准”出现的,主要评估的是美国国防部供应商保证质量的能力。CMM关注的软件生产有如下特点:
    质量重要
    规模较大
    这是CMM产生的原因。它引入了“全面质量管理”的思想,尤其侧重了“全面质量管理”中的“过程方法”,并且引入了“统计过程控制”的方法。可以说这两个思想是CMM背后的基础。
    上面这些内容形成了我对软件过程地位、价值的基本理解;在这个基础上我们可以引申讨论SQA。

    2.2、生产线的隐喻

    如果将一个软件生产类比于一个工厂的生产。那么生产线就是过程,产品按照生产线的规定过程进行生产。SQA的职责就是保证过程的执行,也就是保证生产线的正常执行。
    抽象出管理体系模型的如下,这个模型说明了一个过程体系至少应当包含“决策、执行、反馈”三个重要方面。QA的职责就是确保过程的有效执行,监督项目按照过程进行项目活动;它不负责监管产品的质量,不负责向管理层提供项目的情况,不负责代表管理层进行管理,只是代表管理层来保证过程的执行。

    2.3、SQA和其他工作的组合

    在很多企业中,将SQA的工作和QC、SEPG、组织级的项目管理者的工作混合在一起了,有时甚至更加注重其他方面的工作而没有做好SQA的本职工作。
    根据hjhza 的意见“中国现在基本有三种QA(按照工作重点不同来分):一是过程改进型,一是配置管理型,一是测试型”。我个人认为是因为SQA工作和其他不同工作组合在一起形成的。
    下面根据本人经验对它们之间的关系进行一个说明。

    2.4、QA和QC

    两者基本职责
    QC:检验产品的质量,保证产品符合客户的需求;是产品质量检查者;
    QA:审计过程的质量,保证过程被正确执行;是过程质量审计者;
    注意区别检查和审计的不同
    检查:就是我们常说的找茬,是挑毛病的;
    审计:来确认项目按照要求进行的证据;仔细看看CMM中各个KPA中SQA的检查采用的术语大量用到了“证实”,审计的内容主要是过程的;对照CMM看一下项目经理和高级管理者的审查内容,他们更加关注具体内容。

    对照上面的管理体系模型,QC进行质量控制,向管理层反馈质量信息;QA则确保QC按照过程进行质量控制活动,按照过程将检查结果向管理层汇报。这就是QA和QC工作的关系。在这样的分工原则下,QA只要检查项目按照过程进行了某项活动没有,产出了某个产品没有;而QC来检查产品是否符合质量要求。如果企业原来具有QC人员并且QA人员配备不足,可以先确定由QC兼任QA工作。但是只能是暂时的,独立的QA人员应当具备,因为QC工作也是要遵循过程要求的,也是要被审计过程的,这种混合情况,难以保证QC工作的过程质量。

    2.5、QA和SEPG

    两者基本职责

    SEPG:制定过程,实施过程改进;
    QA: 确保过程被正确执行

    SEPG应当提供过程上的指导,帮助项目组制定项目过程,帮助项目组进行策划;从而帮助项目组有效的工作,有效的执行过程。如果项目和QA对过程的理解发生争持,SEPG作为最终仲裁者。为了进行有效过程改进,SEPG必须分析项目的数据。

    QA本也要进行过程规范,那么所有QA中最有经验、最有能力的QA可以参加SEPG,但是要注意这两者的区别。

    如果企业的SEPG人员具有较为深厚的开发背景,可以兼任SQA工作,这样利于过程的不断改进;但是由于立法、执法集于一身也容易造成SQA过于强势,影响项目的独立性。管理过程比较成熟的企业,因为企业的文化和管理机制已经健全,SQA职责范围的工作较少,往往只是针对具体项目制定明确重点的SQA计划,这样SQA的审计工作会大大减少,从而可以同时审计较多项目。

    另一方面,由于分工的细致化,管理体系的复杂化,往往需要专职的SEPG人员,这些人员要求了解企业的所有管理过程和运作情况,在这个基础上才能统筹全局的进行过程改进,这时了解全局的SQA人员就是专职SEPG的主要人选;这些SQA人员将逐渐的转化为SEPG人员,并且更加了解管理知识,而SQA工作渐渐成为他们的兼职工作。

    这种情况在许多CMM5企业比较多见,往往有时看不见SQA人员在项目组出现或者很少出现,这种SEPG和SQA的融合特别有利于组织的过程改进工作。SEPG确定过程改进内容,SQA计划重点反映这些改进内容,从保证有效的改进,特别有利于达到CMM5的要求。从这个角度,国外的SQA人员为什么高薪就不难理解了,也决定了当前中国SQA人员比较被轻视的原因;因为管理过程还不完善,我们的SQA人员还没有产生这么大的价值嘛!

    2.6、QA和组织级的监督管理

    有的企业为了更好的监督管理项目,建立了一个角色,我取名为“组织级的监督管理者”,他们的职责是对所有项目进行统一的跟踪、监督、适当的管理,来保证管理层对所有项目的可视性、可管理性。

    为了有效管理项目,“组织级的监督管理者”必须分析项目的数据。

    他们的职责对照上图的模型,就是执行“反馈”职能。

    QA本身不进行反馈工作,最多对过程执行情况的信息进行反馈。

    SQA职责最好不要和“组织级的项目管理者”的职责混合在一起,否则容易出现SAQ困境:一方面SQA不能准确定位自己的工作,另一方面过程执行者对SQA人员抱有较大戒心。

    如果建立了较好的管理过程,那么就会增强项目的可视性,从而保证企业对所有项目的较好管理;而QA来确保这个管理过程的运行。

    三、SQA的工作内容和工作方法

    3.1、 计划

    针对具体项目制定SQA计划,确保项目组正确执行过程。制定SQA计划应当注意如下几点:
    有重点:依据企业目标以及项目情况确定审计的重点
    明确审计内容:明确审计哪些活动,那些产品
    明确审计方式:确定怎样进行审计
    明确审计结果报告的规则:审计的结果报告给谁

    3.2、审计/证实

    依据SQA计划进行SQA审计工作,按照规则发布审计结果报告。
    注意审计一定要有项目组人员陪同,不能搞突然袭击。双方要开诚布公,坦诚相对。
    审计的内容:是否按照过程要求执行了相应活动,是否按照过程要求产生了相应产品。

    3.3、问题跟踪
    对审计中发现的问题,要求项目组改进,并跟进直到解决。

    四、SQA的素质

    过程为中心:应当站在过程的角度来考虑问题,只要保证了过程,QA就尽到了责任。

    服务精神:为项目组服务,帮助项目组确保正确执行过程
    了解过程:深刻了解企业的工程,并具有一定的过程管理理论知识
    了解开发:对开发工作的基本情况了解,能够理解项目的活动
    沟通技巧:善于沟通,能够营造良好的气氛,避免审计活动成为一种找茬活动。

    posted @ 2008-01-08 19:31 灵! 阅读(157) | 评论 (0)编辑 收藏

    如何实施软件质量保证(转)

    软件质量保证(即SQA——Software Quality Assurance),是CMM2级中的一个关键过程域,它是贯穿整个软件过程的第三方独立审查活动,出现在大多数关键过程域的检查与验证的公共特性中,在整个软件开发过程中充当重要角色。

    从CMM2级中包含的6个关键过程域来看,无论是需求管理、软件项目计划、软件项目跟踪与监控,还是软件子合同管理、软件配置管理,都不同程度地存在于我们现在正在进行的软件项目开发过程中,对于它们的了解我们已经不再陌生,只有SQA这个关键过程域,是在我们准备以CMM2级要求的关键过程域为基础进行软件过程改进前未接触过的。

    在很多软件企业中还没有与之相对应的人员和工作方法,整套关注软件开发过程的软件质量保证体系还没有建立起来。所以,在企业以CMM2级关键过程域为参考进行软件过程改进时,SQA往往是一个难点,直接涉及到组织结构的变化。

    实施SQA的目的

    软件质量保证的目标是以独立审查方式,从第三方的角度监控软件开发任务的执行,就软件项目是否正遵循已制定的计划、标准和规程给开发人员和管理层提供反映产品和过程质量的信息和数据,提高项目透明度,同时辅助软件工程组取得高质量的软件产品。主要包括以下四个方面:

    ● 通过监控软件开发过程来保证产品质量;

    ● 保证开发出来的软件和软件开发过程符合相应标准与规程;

    ● 保证软件产品、软件过程中存在的不符合问题得到处理,必要时将问题反映给高级管理者;

    ● 确保项目组制定的计划、标准和规程适合项目组需要,同时满足评审和审计需要;

    除了以上四点之外,我们还希望SQA能作为软件工程过程小组(SEPG)在项目组中的延伸,能够收集项目中好的实施方法和发现实施不利的原因,为修改企业内部软件开发整体规范提供依据,为其他项目组的开发过程实施提供先进方法和样例。

    对SQA人员的素质要求

    1. SQA人员(有时简称SQA)要有很强的沟通能力。从实施SQA的目的中可以看出,SQA不在项目中,是独立于软件项目的第三方,但他要了解项目的开发过程和进度,捕捉到项目中不符合要求的问题,这就要求SQA能够深入项目,和软件开发经理以及项目组中的开发人员保持很好的沟通,这样才能及时获得真实的项目情况。

    2. SQA要熟悉软件开发过程。作为SQA,既然要确保项目组制定的计划、标准和规程,要符合项目组要求,那么SQA首先自己就要了解软件项目开发过程,以及企业内部已经有的开发过程规范。

    3. SQA本身要有很强的计划性。SQA一方面要监督软件项目组编写计划,另一方面SQA自身的工作也要有计划,并且能够按照计划开展工作。

    4. SQA要能应对繁杂的工作。作为SQA,在跟踪项目进行过程的时候要对项目组的很多工作产品进行审计,而且会参与项目组中的多种活动。同时一个SQA还有可能会面对多个项目组,所以任务相对繁杂细碎,这就要求SQA在处理这些事物的时候要耐心细致。

    5. SQA要客观,有责任心。作为第三方对项目过程进行监督,SQA要能保持自己的客观性,不能一味讨好项目经理,也不能成为项目组中的宪兵,否则会影响工作的开展。对于项目组中多次协调解决不了的问题,能够向项目的高层经理进言,完成SQA的使命。

    以上五点是作为SQA应该具备的基本素质,除此之外,一个好的SQA还应该在软件开发过程中作为开发人员或测试人员参与过一个或多个环节,这样他们才能在过程监督中比较准确地抓住重点,同时他们的意见和提出的解决办法也会更贴近项目组,容易被项目组接受。

    SQA人员的组成

    软件企业中的SQA人员既可以由全职人员担任,也可以由企业内具有相关素质、经过SQA培训的人员兼职担任。由此组成的SQA小组可能是一个真正的物理上存在的独立部门,也可以是一个逻辑上存在的平台。但不管是真正的独立部门还是逻辑上的平台,它都需要有一个灵魂人物——SQA小组组长,来组织SQA小组的日常活动。

    在给一个项目组分配负责监督其项目过程的SQA时,一定要注意一点:就是该项目的SQA不能是该项目组的开发人员、配置管理人员或测试人员,一个项目的SQA除了监控项目过程,完成SQA相关工作以外,不应该参与项目组的其他实质性工作,否则他会与项目组捆绑在一起,很难保持客观性。

    SQA工作的内容

    SQA的工作内容主要包括以下六类:

    1. 与SQA计划直接相关的工作:SQA在项目早期要根据项目计划制定与其对应的SQA计划,定义出各阶段的检查重点,标识出检查、审计的工作产品对象,以及在每个阶段SQA的输出产品。定义越详细,对于SQA今后的工作的指导性就会越强,同时也便于软件项目经理和SQA组长对其工作的监督。编写完SQA计划后要组织SQA计划的评审,并形成评审报告,把通过评审的SQA计划发送给软件项目经理、项目开发人员和所有相关人员。

    2. 参与项目的阶段性评审和审计:在SQA计划中通常已经根据项目计划定义了与项目阶段相应的阶段检查,包括参加项目在本阶段的评审和对其阶段产品的审计。对于阶段产品的审计通常是检查其阶段产品是否按计划按规程输出并内容完整,这里的规程包括企业内部统一的规程也包括项目组内自己定义的规程。但是SQA对于阶段产品内容的正确性一般不负责任检查,对于内容的正确性通常交由项目中的评审来完成。SQA参与评审是从保证评审过程有效性方面入手,如参与评审的人是否具备一定资格、是否规定的人员都参见了评审、评审中对被评审的对象的每个部分都进行了评审、并给出了明确的结论等等。

    3. 对项目日常活动与规程的符合性进行检查: 这部分的工作内容是SQA的日常工作内容。由于SQA独立于项目组,如果只是参与阶段性的检查和审计很难及时反映项目组的工作过程,所以SQA也要在两个阶段点之间设置若干小的跟踪点,来监督项目的进行情况,以便能及时反映出项目组中存在的问题,并对其进行追踪。如果只在阶段点进行检查和审计,即便发现了问题也难免过于滞后,不符合尽早发现问题、把问题控制在最小的范围之内的整体目标。

    4. 对配置管理工作的检查和审计:SQA要对项目过程中的配置管理工作是否按照项目最初制定的配置管理计划进行监督,包括配置管理人员是否定期进行该方面的工作、是否所有人得到的都是开发过程产品的有效版本。这里的过程产品包括项目过程中产生的代码和文档。

    5. 跟踪问题的解决情况: 对于评审中发现的问题和项目日常工作中发现的问题,SQA要进行跟踪,直至解决。对于在项目组内可以解决的问题就在项目组内部解决,对于在项目组内部无法解决的问题,或是在项目组中跟催多次也没有得到解决的问题,可以利用其独立汇报的渠道报告给高层经理。

    6. 收集新方法,提供过程改进的依据:此类工作很难具体定义在SQA的计划当中,但是SQA有机会直接接触很多项目组,对于项目组在开发管理过程中的优点和缺点都能准确的获得第一手资料。他们有机会了解项目组中管理好的地方是如何做的,采用了什么有效的方法,在SQA小组的活动中与其他SQA共享。这样这些好的实施实例就可以被传播到更多的项目组中。对于企业内过程规范定义的不准确或是不方便的地方,软件项目组也可以通过SQA小组反映到软件工程过程小组,便于下一步对规程进行修改和完善。

    SQA与几类角色间的关系

    一个企业内的部门设置可能会各有不同,但是很多角色设置是相同的,从一个项目的SQA出发,我们可以把SQA与其他相关角色的关系表示为下图: 以上图示只说明SQA与高层经理、项目组和其他相关组之间的关系,并不是以上几个角色之间所有关系的描述,所以即便项目组会直接向高层经理汇报,但与SQA无直接关系,在图中就没有表现出来。

    SQA工作中常见的几个问题

    1. 最初给项目组配置SQA人员的时候,SQA的价值不被认可因为是新工作的初次开展,已经习惯了自己管理项目,向高层经理汇报的项目组难免会有抵触情绪。要从两个方面解决这个问题:一方面,从组织的角度,要明确SQA的角色及其合法性; 另一方面,SQA也要以其专业的工作赢得项目组认可,为项目组增加价值。

    2. 一个全职的SQA可以同时兼任多少个项目的SQA工作对于不同的项目规模和组织管理方式,这个问题会有不同的答案,根据实施中的一些经验总结,通常在第一次实施时,承担一个20人左右的项目组的SQA工作需要占用一个人30%左右的工作量,随着SQA的成熟,这个比例会降低到15%。对于一个10人以内的项目组,SQA需要投入其10%左右的工作量。当然,项目越大SQA的投入就越多。

    3. SQA与项目组的关系难处理对于SQA与项目组的关系,应该遵循以下两条原则: 要在过程方面成为项目组的严师,有错必纠,但不能有错全报;要做项目组的朋友,但不能对项目组包庇纵容。

    4. 项目组有了SQA,可是需求文档和设计文档的质量还是不高对不起,这不是SQA的直接工作范围。提高需求和设计的质量,要从人员培训和严格评审入手,让有经验有资格的人来完成需求和设计文档。SQA只能从规程符合方面进行监督。

    总之,在软件企业中建立SQA体系,是软件项目管理由人治到法治的一个必经阶段,也是软件企业以CMM模型为参考,进行软件过程改进中一个不可缺少的部分。软件企业只要真正建立了SQA规范,培养了专业的SQA人员就会真正从中体会到它的好处。

    posted @ 2008-01-08 19:30 灵! 阅读(205) | 评论 (1)编辑 收藏

    什么是基金

           作为一种投资工具,证券投资基金把众多投资人的资金汇集起来,由基金托管人(例如银行)托管,由专业的基金管理公司管理和运用,通过投资于股票和债券等证券,实现收益的目的。

            对于个人投资者而言,倘若你有1万元打算用于投资,但其数额不足以买入一系列不同类型的股票和债券,或者你根本没有时间和精力去挑选股票和债券,购买基金是不错的选择。例如,申购某只开放式基金,你就成为该基金的持有人,上述1万元扣除申购费后折算成一定份额的基金单位。所有持有人的投资一起构成该基金的资产,基金管理公司的专业团队运用基金资产购买股票和债券,形成基金的投资组合。你所持有的基金份额,就是上述投资组合的缩影。

            专家理财是基金投资的重要特色。基金管理公司配备的投资专家,一般都具有深厚的投资分析理论功底和丰富的实践经验,以科学的方法研究股票、债券等金融产品,组合投资,规避风险。

           相应地,每年基金管理公司会从基金资产中提取管理费,用于支付公司的运营成本。另一方面,基金托管人也会从基金资产中提取托管费。此外,开放式基金持有人需要直接支付的有申购费、赎回费以及转换费。封闭式基金持有人在进行基金单位买卖时要支付交易佣金。

          基金有几种类型

           ◇按照组织形式,有公司型基金和契约型基金两类,目前国内基金均为契约型。

           ◇按照基金规模是否固定,可分为封闭式基金和开放式基金。

           至2003年9月中旬,国内已有86只证券投资基金,总规模达到1616亿份基金单位,其中封闭式基金54只,开放式基金32只。

    美国共同基金业20世纪70年代以后迅速发展。截至2003年7月,美国共同基金(开放式基金)约8300只,资产净值达到6870亿美元,其中70%以上的资产为个人投资者持有。美国家庭对共同基金的投资自1990年以来稳步增长。根据投资公司协会2002年5月的统计数据,有5420万户家庭(共计9490万名个人投资者)持有共同基金,约占美国家庭户数的一半。而1990年,参与共同基金投资的家庭为2340万户,所占比重为25%。

          ◇按照投资对象的不同,可分为股票基金、债券基金、混合基金、货币市场基金、期货基金、期权基金等。

           ◇按照投资运作的特点,可分为成长型、收入型、平衡型基金。

            美国晨星公司(Morningstar)1985年推出基金星级评价体系时,把美国市场的基金按照资产分布分为四类:美国股票基金,国际股票基金,应税债券基金和市政债券基金。2002年,晨星公司在上述分类的基础上,按照投资风格、投资的行业、地域等将基金类型进一步细分至50种。

            澄清几个认识误区

           ◇基金不是股票

           有的投资人将基金和股票混为一谈,其实不然。一方面,投资者购买基金只是委托基金管理公司从事股票、债券等的投资,而购买股票则成为上市公司的股东。另一方面,基金投资于众多股票,能有效分散风险,收益比较稳定;而单一的股票投资往往不能充分分散风险,因此收益波动较大,风险较大。

            ◇基金不同于储蓄

           由于开放式基金通过银行代销,许多投资人因此认为基金同银行存款没太大区别。其实两者有本质的区别:储蓄存款代表商业银行的信用,本金有保证,利率固定,基本不存在风险;而基金投资于证券市场,要承担投资风险。储蓄存款利息收入固定,而投资基金则有机会分享基础股票市场和债券市场上涨带来的收益。

           ◇基金不同于债券

           债券是约定按期还本付息的债权债务关系凭证。国内债券种类有国债、企业债和金融债,个人投资者不能购买金融债。国债没有信用风险,利息免税;企业债利息较高,但要交纳20%的利息税,且存在一定的信用风险。相比之下,主要投资于股票的基金收益比较不固定,风险也比较高;而只投资于债券的债券基金可以借助组合投资,提高收益的稳定性,并分散风险。

          ◇基金是有风险的

          投资基金是有风险的。换言之,你起初用于购买基金的1万元,存在亏损的可能性。基金既然投资于证券,就要承担基础股票市场和债券市场的投资风险。当然,在招募说明书中有明确保证本金条款的保本基金除外。此外,当开放式基金出现巨额赎回或者暂停赎回时,持有人将面临变现困难的风险。

            ◇基金适合长期投资

           有的投资人抱着股市上博取短期价差的心态投资基金,例如频繁买卖开放式基金,结果往往以失望告终。因为一来申购费和赎回费加起来并不低,二来基金净值的波动远远小于股票。基金适合于追求稳定收益和低风险的资金进行长期投资。

    posted @ 2008-01-08 19:27 灵! 阅读(98) | 评论 (0)编辑 收藏

    海外上市流程

       首先,在纳斯达克上市的中国公司市盈率普遍都高于美国其他的市场。同时,也高于世界其他的主要市场,包括像历史最悠久的伦

    敦交易所、区域性的香港和新加坡交易所等。  
      目前,在纳斯达克上市的中国公司市盈率平均波动范围是在30—40倍的区间内。而新加坡、香港大概在13—16倍的市盈率范围内波

    动,伦敦可能更低一点。这样,从最“实在”的角度来讲,纳斯达克给了中国公司高的市盈率或者高的评估值。像盛大这样的公司,市

    值20亿美元,高出30多倍的市盈率,就等于是6000万美元。一下多出6000万美元,对盛大公司来说是一笔丰厚的财富,这是实实在在的

    利益。    
      其次,中国企业到纳斯达克上市,在融资的同时还可以提高自己的国际知名度。    
      再次,可以提高自己企业的信誉评级。    
      最后,通过到纳斯达克去可以为上市公司开展国际国内的合作提供舞台。
      此外,纳斯达克还为上市公司提供一系列的增值服务。最重要的是后续融资的便利,纳斯达克在后续融资上没有时间的限制,最快

    6个月就可以做二次融资。二次融资有四种方式:一是股权的二次融资;二是可以发企业债;三是银行融资,在美国,如果信誉好的话

    ,容易得到商业贷款,甚至不需要抵押就可以得到信誉贷款;四是可以把自己的公司变成一个“硬通货”。最典型的有盛大,中海油。

    盛大就是在上市之后,因为现金充裕 并购了新浪。  
      那么,什么样的公司可以去纳斯达克上市呢?关键在于公司本身的成长性和质量。  
      在纳斯达克有三套财务标准来考核什么样的公司可以上市。其中有一套是针对盈利模式的,即净资产1500万以上,市场流动值超过

    800万美元就可以了。这个标准对于国内大多数上市公司来说,条件并不高,甚至可以说是比较低的。  
      虽然当前有的中国公司在纳斯达克和别的海外资本市场上遭遇到困境。但这是必然经-历的两个阶段:国外的投资者在第一个阶段

    对所有的“中国概念”公司充满了兴趣,这可以看作是从一个比较盲目的阶段到成熟阶段的过渡。最终要进入了第二阶段,海外投资者

    已经开始挑选个股,新浪、搜狐和网易这三个都是门户网站,它们的市盈率和价格相差却很大。但是,不能说价格差得大,就一定不好

    ,投资者有一个选择性,这是一个非常重要的问题。  
      现在有很多人把纳斯达克和国内的创业板相比较。其实,把创业板和纳斯达克等同是一个错误的概念,纳斯达克是一个门类齐全、

    综合平衡的交易所,把它当成一个创业板的交易所已经不准确了。  
      但是纳斯达克有没有符合创业板概念的机制?确实有。所以,纳斯达克本身是世界上股票交易所的主要基地,在一系列的主要数据

    上都属世界前列。同时,纳斯达克又适合于各个行业的公司和一个公司在不同阶段的时候来进行融资和上市,这是纳斯达克最值得骄傲

    的地方。  
      纳斯达克有一个很值得借鉴的地方,这就是服务。纳斯达克坚持以服务至上为宗旨,这是很多交易所都应该借鉴学习的。同时纳斯

    达克还在不断改善自身的服务和商业模型。作为一只股票,纳斯达克自己也上市了,后来又并购了一些机构,与路透社有了战略合作的

    协-议,出台了一些合伙的协-议和增值服务。纳斯达克已-不完全局限于一个交易所的工作,它提供“一揽子”的系列合作和增值服务

    。 

      2005年7月13日,分众传媒在美国纳斯达克上市,融资总金额达1.717亿美元。上市首日的开盘价为18.75美元,整个交易期间股价

    一路攀升。  
      对此,江-南春就直截了当地说:“这家公司注定是要被推动到资本市场上去的,因为它当时缺少资金。2003年我们开始做分众传

    媒,然而一到2003年5月份,就出现了非典,当时我们投入的钱已经差不多了。如果还想发展,就需要展开融资。过了一段时间,我们

    进了CDH,在两年之中,一直伴随着风险投资。风险投资之后把业务从上海发展到了75个城市。在我们非常迅速的成长中,资金有非常

    大的需求量,融资是一个非常重要的过程,也是一个必经-的阶段。上市前,在楼宇电视广告行业,分众传媒仅处于主导者地位,还不

    是领导者。而分众收购了框架传媒后,业务从写字楼扩展到公寓。然后分众又收购竞争对手聚众传媒,确定了行业绝对领导者的地位。

    收购的资金从哪里来?上市为我们提供了非常好的资本工具。”
    上市之利  
      实际上,首次公开招股是中国公司进行改革和实施广泛重组、从而提高在行业内竞争力的良机。同时,上市还有其他一些益处:  
      更高的披露要求:上市的公司须遵照更严格的法律、信息披露和其他司法要求。取得在美上市资格将有助于中国公司改善公司治理

    ,表明其致力于提高企业管理水平的决心。  
      接触更大规模的资本市场:比如在美国上市,美国是全球规模最大的资本市场。截止2005年12月,有近460家非美国公司在纽约证

    交所挂牌,上市证券总值达71000亿美元。虽然企业在海外可以根据144A条例接触到美国机构投资者,但在美国上市可进入美国散户零

    售市场,进一步丰富和扩大投资者群体。此外,在美上市更可接触到专注于个别行业的投资者,他们当中有很多是行业专家,但只被允

    许投资美国的或以美元为计价单位的证券。  
      全球的认可:仍以美国为例,接触美国投资者、美国研究分析师以及美国的金融媒体将有助提升公司的声誉,从而令投资者对公司

    的投资理念有更好的理解和传播,提高投资价值,使潜在客户对公司的认可程度提高,业务得到扩大。  
      在海外上市的中国公司要取得持续的成功,有赖于很多关键因素,包括:树立国际资本市场认可的公司形象——选择合适的财务、

    法律和会计顾问;遵守-发行过程,尤其是上市促销程序;强劲的后市支持。  
      树立国际资本市场认可的公司形象:欲赢得国际投资者的青睐,计划在纽约证交所上市的公司需要具备一些特质,包括在行业内具

    优势地位、清晰的业务策略、品牌知名度、稳健的资产负债表、合理的增长和盈利前景和优秀的公司管理层,尤为重要的是企业治理能

    力。这些都是一家公司在考虑上市前应具备的关键性条件。  
      那么,如何做好上市的准备呢?我们分别以美国和香港市场为例加以分析。  
      美国市场  
      首先要选择合适的顾问。  
      公司内部要挑选合适人选,建立一个全力投入的团队,这是上市过程的重要基石。这个团队应包括熟悉公司运营、财务、法律和其

    他一般事宜的成员。高级管理层应该准备好为上市工作倾注相当的时间,尤其是在尽职调查和促销阶段。被聘为帐簿管理人(Book

    Runner)和联席全球协调人的投资银行将在协调和领导各个顾问工作的过程中扮演重要的角色。投资银行负责领导整个交易和承销过程

    。公司应考虑投资银行过去在类似的国际和美国上市交易方面的经验、对行业的理解、股票销售能力(如机构销售和散户零售队伍的规

    模) ,需要的话,还应考虑其引入战略投资者的能力。  
      公司选择的法律顾问必须拥有履行美国法律的资格,有协助接受美国证监会审核和在纽约证交所上市的经验,并且能够提供全套的

    相关法律意见。另一方面,对公司行业的了解也很重要,因为律师事务所需要负责起草招股书并保证信息披露的准确性。同样地,公司

    和承销团聘请的当地律师应有能力执行在中国国内的监管程序。承销团会负责选聘为他们服务的当地和国际律师。  

      会计师事务所将根据美国会计准则独立审查公司的财务状况。会计师事务所也应对中国的会计准则有全面的了解,以便将若干数据

    调节以符合美国会计准则的报表要求。  
      存托银行负责为上市公司建立美国存股证或称预托证券(American Deposit Receipt; “ADR”) 项目。大多数非美国公司都通过

    这种方式在纽约证交所上市。ADR就如中国公司的股票一样,只是它以美元交易,股息用美元支付。股票存放在托管人处,托管人再向

    投资者发行ADR。挑选承销团的标准与挑选账簿管理人和联席全球协调人的标准相似,其中尤其强调(1) 与账簿管理人一起工作的能力

    ;(2) 研究实力;(3) 分销能力; (4) 对特定地区和行业的认识。除上文提及的顾问外,中国公司也许需要其他顾问的协助,如地产

    和物业评估师,以满足国内的监管规定。  
      在正式向纽约证交所申请上市之前,一家国有企业可能需要进行广泛的重组,并确定从母公司剥离出的核心资产。重组的主要目标

    是建立一家上市公司,从投资者角度看,资产应具有相当的市场地位、合理的法律、运营和资本结构、以及与母公司明确清晰的关系。

    重组所需时间将因上市公司情况有别而有所不同。
      第二步也是关键的一步——行业重组。  
      显然,如果一个行业的监管机制,定价政策,以及竞争关系还没有确立,那么,政府和监管部门就需要在银行家、律师和其它顾问的协助下修改或建立新的政策和结构资产构成和资本结构:为了使价值最大化,并激发投资者的兴趣,并入上市公司的资产应该反映公司的长期战略,并且强调其在经济上独立运作也是可行的。一旦做出了决定,这些被选入的资产就需要清晰的剥离。如果要上市的公司是一家子公司,则需要准备母公司与上市公司之间全套的关联交易指引文件,并获得批准。这种情况在中国是很普遍的。在公司选择资产、设计合适的资本结构、考虑上市公司目前和未来的资本需求、债务水平以及投资者的主要偏好方面,由投资银行提供的专业意见将起到十分关键的作用。  
      第三步是建立组织和管理结构。  
      海外投资人对一个清晰、有效并具有高度灵活性的组织和管理结构是十分看中的。有效的结构使上市公司的董事和管理层能够向着一个共同的目标并肩工作。帮助提高效率的系统有管理信息系统(MIS) 和企业资源规划系统(Enterprise Resource Planning Systems),此外,重要的公司职能如采购、市场销售、研发、现金流管理、商业规划、资本开支计划等应该在公司层面加以整合,从而使整合效果最优化及保证资本的合理运用。最后,还应利用会计、信息和汇报体系,及时提供按照美国会计准则要求而编制的财务报告。  
      管理层/员工激励计划:一个清晰明确的管理层/员工激励计划是上市过程中十分重要的一部份,它可以使管理层的利益与股东保持一致,将管理层的薪酬与公司的经营业绩和股价表现挂钩。  
      第四步就是国内监管审批。  
      中国公司在纽约证交所上市之前,必须得到国内监管机构一系列的批准。主要的监管实体是中国证监会。但是,在证监会批准企业在纽约证交所上市之前,国有企业还必须得到国务院、财政部和国家经贸委的批准。中国公司最好与一家经-验丰富的国内顾问合作,以保证顺利及时地完成国内审批程序。准备符合美国会计准则的财务报告公司必须准备一套符合美国会计准则的财务报告,并且要经过公司的独立审计师的审核。  
    香港市场  
      香港上市相对简单。上市申请涉及多方专业人士,在申请上市过程中各司其职。本文旨在阐释新上市涉及的各个关键机构。  
      1. 保荐人  
      计划上市的公司必须委任合适的保荐人。主板上市保荐人须为交易所会员、发行商、商业银行或交易所接纳的其他人士。此外,创业板上市保荐人须依照《证券及期货条例》获发牌及注册。计划申请在创业板上市的公司必须从交易所核准的创业板保荐人名单中挑选一名保荐人。  
      保荐人负责为新申请人筹备上市事宜,将正式上市申请表格及一切有关的文件呈交交易所,并处理交易所就有关申请的一切事宜所提出的问题。  
      对主板公司来说,要求委任保荐人的规定,于新申请人获准上市后即告终止,但交易所建议上市发行人于上市后至少一年内继续留用其保荐人。然而,根据《主板上市规则》,中国发行人须于上市后至少一年内继续聘任其保荐人,或交易所接纳的其他财务顾问或专业券商。此外,创业板公司委任的保荐人必须有固定任期,至少含盖上市时该财政年度的余下时间及其后两个财政年度。  
      在委任保荐人之前,公司务须与多家保荐人会晤,以评估他们是否适合作为公司的上市保荐人。公司应挑选可就上市程序各方面提供全面及公正意见的保荐人。  
      2. 申报会计师  
      所有会计师报告,均须由具备《专业会计师条例》所规定可获委任为公司核数师资格的专业会计师编制。该等专业会计师须独立于发行人。  
      申报会计师负责审核公司的财务记录及财务状况,并根据相关会计准则及监管指引编制新申请人的集团账目,使准投资者能作出充分掌握资料的投资决定。  
      3. 法律顾问  
      法律顾问负责确保新申请人遵照各个相关司法管辖区的法律,并与保荐人及申报会计师就新申请人须进行的重组事宜紧密合作。
      4. 包销商/配售代理  
      一般为证券行及交易所参与者,负责在股份发售期间分销公司的证券。包销商须包销投资者未认购的股份。  
      5. 估值师  
      新申请人须在上市前委任估值师对其物业进行估值。公司也可委任估值师对公司的其他资产进行估值。  
      上市的具体步骤  
      无论美国、香港或是欧洲,具体的上市步骤大同小异。  
      尽职调查阶段  
      在起草招股说明书之前,所有顾问都需要进行尽职调查,以便于了解与公司相关的事实情况。投资银行将帮助公司用便于投资者理解的方式准确明了地说明这些事实情况。尽职调查是一个全面的调查过程,它将保护发行公司的市场声誉和未来资本市场的融资渠道,有效地加强和简化文件起草过程,帮助管理层为路演作准备,保护发行公司及承销商免受法律和名誉上的风险。  
      全面的尽职调查主要包括业务、法律和财务。  
      根据尽职调查结果,以及对国际资本市场的理解,作为账簿管理人的投资银行将与公司一起制定既符合公司情况,又吸引投资者的估值主题。估值的过程需要考虑很多变数,包括市场环境、可比公司的估值、发行公司相对于可比公司的业务/财务前景等。  
    上市阶段  
      美国证监会审核程序  
      根据纽约证交所上市标准,所有股票在上市之前必须在美国证监会登记。登记说明是促销材料或招股书的基础,必须由公司准备,然后提交给美国证监会审批。  
      文件存档和审核  
      在美国律师的帮助下,公司将向美国证监会秘密存档(Confidential filing)通常称为“粉色招股书”(Pink Herring)的登记文件。美国证监会一般需要四到六周时间来审核文件是否妥当,然后回复公司或提出后续问题和意见。公司将与律师、审计师和投资银行家回答关于登记文件的问题。美国证监会对所有经过修改的内容表示满意后,公司再按要求把称为“RedHerring” 的初步招股书公开存档。这标志着发行的正式启动。
      启动准备  
      在证监会审核登记文件的同时,投资银行和公司准备促销故事和路演说明材料。  
      先要设计一个股本故事:公司需要向投资者证明这个股票是具吸引力的投资,而这亦是一次成功的发行最重要的组成部分之一。投资银行通过他们对市场运作的熟悉和了解,以及对投资者心态的深刻理解,和公司合作设计一个具吸引力的投资故事。  
      设计投资故事时,公司和投资银行都应考虑上市公司的背景和过往业绩、竞争优势、迄今为止取得的成就、增长策略、潜在投资者关注和忧虑的问题。  
      然后是准备促销材料:投资银行也会利用他们的经验,通过准备与投资者会面时有说服力的演示材料以及起草管理层发言稿来帮助公司讲述和推介它的股本故事。这两份材料,一份书面,一份口头,是公司向潜在投资者进行促销的重要手段。  
      准备   
      市场促销的首要目标是向机构和散户投资者说明发行公司的业务,为首次公开发行和后市交易提供强而有力的支持。作为全球协调人的投资银行将协调和安排承销团分析师与管理层的介绍会,向承销团说明前市促销应注意的事项,并严格控制前市促销材料的传播,以保证投资者获得一致的信息及所有演示材料都符合上市规则。  
      前市促销是向外推销发行的第一步。这过程包括投资银行与投资者进行直接的面对面会议,作为验证促销故事、修改估值主题、衡量投资者兴趣以及确立定价范围的重要策略。  
      路演(国际巡回推介活动)紧接着前市促销的项目正式启动,亦即路演促销活动正式开始。已向证监会存档的初步招股书(即“Red Herring”) 将成为促销的核心文件,让公司与美国投资者讨论发行细节。这份文件也确定了发行的定价范围。  
      在促销过程中,公司管理层将参与为期一至两周的路演,与主要机构投资者进行一对一会议,并出席投资者小组说明会。全球协调人的代表也将参与路演和所有会议,随时向公司提供反馈信息和指引,确保路演活动取得成功。 

    posted @ 2008-01-08 19:26 灵! 阅读(374) | 评论 (0)编辑 收藏

    什么是股票

    股票是股份公司发给股东证明其所入股份的一种有价证券,它可以作为买卖对象和抵押品,是资金市场主要的长期信用工具之一。


    股票作为股东向公司入股,获取收益的所有者凭证,持有它就拥有公司的一份资本所有权,成为公司的所有者之一,股东不仅有权按公司章程从公司领取股息和分享公司的经营红利,还有权出席股东大会,选举董事会,参与企业经营管理的决策。从而,股东的投资意愿通过其行使股东参与权而得到实现。同时股东也要承担相应的责任和风险。


    股票是一种永不偿还的有价证券,股份公司不会对股票的持有者偿还本金。一旦购入股票,就无权向股份公司要求退股,股东的资金只能通过股票的转让来收回,将股票所代表着的股东身份及其各种权益让渡给受让者,而其股价在转让时受到公司收益、公司前景、市场供求关系、经济形势等多种因素的影响。所以说,投资股票是有一定风险的。


    在股票市场中,发行股票的公司根据不同投资者的投资需求,发行不同的股票。按照不同的标准,股票可分好几类。我们通常所说的股票是指在上海、深圳证券交易所挂牌交易的A股,这些A股也可称为流通股、社会公众股、普通股。


    股票作为一种所有权证书,最初是采取有纸化印刷方式的,如上海的老八股。在这种有纸化方式中,股票纸面通常记载着股票面值、发行公司名称、股票编号、发行公司成立登记的日期、该股票的发行日期、董事长及董事签名、股票性质等事项,随着现代电子技术的发展,电子化股票应运而生,这种股票没有纸面凭证,它一般将有关事项储存于电脑中心,股东只持有一个股东帐户卡,通过电脑终端可查到持有的股票品种和数量,这种电子化股票又称为无纸化股票。目前,我国在上海和深圳交易所上市的股票基本采取这种方式。

    posted @ 2008-01-08 19:26 灵! 阅读(235) | 评论 (0)编辑 收藏

    如何进行股票交易

        由于我国证券市场的快速发展,目前深、沪两地交易所均实现了交易无纸化、电子 化,投资者进入股市必须先到当地证券登记机构分别开立上海、深圳股票帐户,只有拥有股票帐户,才能进行股票交易。

        开立股票时投资者必须持本人有效身份证件(一般为身份证),并提供投资者的详细资料,这些资料包括:姓名、性别身份证号码、家庭住址、联系电话等。


        投资者办理了股票帐户后还需在券商(证券公司)办理资金帐户,而这个资金帐户 也仅仅在该券商交易有效。投资者如需在别的券商交易,需另外开立资金帐户,因此,一个投资者可拥有多个资金帐户。投资者资金帐户的存款,券商按银行活期存款利率支 付利息。


        投资者在办妥股票帐户及资金帐户后即可进入市场买卖,客户填写的委托买卖股票 的委托单是客户与券商之间确定代理关系的文件,具有法律效力。目前在我国券商提供的委托方式除填单委托外,还有自助委托、电话委托、可视电话委托、委托机委托、网上委托等,其委托内容券商必须如实受理,如果成交结果与委托内容不符,客户可向券 商提出交涉,以维护自己的合法权益。券商受理客户委托一般先由券商的电脑委托系统 进行审查,审查无误后,直接进入交易所内计算机主机进行撮合成交。交易所的自动撮合系统按“价格优先、时间优先”原则进行,即在一定价格范围内(昨收盘价的上下 10%之间),优先撮合最高买入价或最低卖出价。


    现在证券市场的运作是以交易的自动化和股份清算与过户的无纸化为特征的,客户 在委托买卖的次交易日必须到券商处办理交割,也就是客户与券商就成交的买卖办理资金清算与股份过户业务的手续,此手续俗称“一手交钱、一手交货”,券商向客户提供的交割单需列出客户本次买卖交易的详细资料,至此客户的股票交易才结束。

    posted @ 2008-01-08 19:25 灵! 阅读(255) | 评论 (0)编辑 收藏

    股票交易有哪些费用

    我国的证券投资者在委托买卖证券时应支付各种费用和税收,这些费用按收取机构可分为证券商费用、交易场所费用和国家税收。

        目前,投资者在我国券商交易上交所和深交所挂牌的A股、基金、债券时,需交纳 的各项费用主要有:委托费、佣金、印花税、过户费等。


       1、委托费,这笔费用主要用于支付通讯等方面的开支。一般按笔计算,交易上海股票、基金时,上海本地券商按每笔1元收费,异地券商按每笔5元收费;交易深圳股票、基金时,券商按1元收费。


        2、佣金,这是投资者在委托买卖成交后所需支付给券商的费用。上海股票、基金及深 圳股票均按实际成交金额的千分之三点五向券商支付,上海股票、基金成交佣金起点为 10元;深圳股票成交佣金起点为5元;深圳基金按实际成交金额的千分之三收取佣金; 债券交易佣金收取最高不超过实际成交金额的千分之二,大宗交易可适当降低。


        3、印花税,投资者在买卖成交后支付给财税部门的税收。上海股票及深圳股票均按单项成交金额的千分之一支付(2005年1月24日起),此税收由券商代扣后由交易所统一代缴。债券与基金交易均免交此项税收。


        4、过户费,这是指股票成交后,更换户名所需支付的费用。由于我国两家交易所不同的运作方式,上海股票采取的是“中央登记、统一托管”,所以此费用只在投资者进行 上海股票、基金交易中才支付此费用,深股交易时无此费用。此费用按成交股票数量(以每股为单位)的千分之一支付,不足1元按1元收。


        5、转托管费,这是办理深圳股票、基金转托管业务时所支付的费用。此费用按户计算,每 户办理转托管时需向转出方券商支付30元。

    posted @ 2008-01-08 19:25 灵! 阅读(99) | 评论 (0)编辑 收藏

    发现你的领导力,做好领导者

    一、发现你的领导力

      (一)领导和领导力的概念

      关于“领导”在现代汉语词典的471页有个解释,就是率领和引导朝着一定方向前进。领导力就是影响别人的能力,特别你能激励你的团队和他人完成一个具有挑战性的目标,完成这样的任务才能说明你具备了一个良好的领导力。但什么是影响他人的能力呢?大家说法各异,有的说是个人魅力,有个人魅力的领导可以带领自己的团队朝着既定的目标前进。有的说是实力和勇气,个人或企业的实力和勇气也能够团结和带领一支团队。还有人说是学识渊博,知识和智慧也同样能够感染和影响你的团队。最后是激励和热情,通过给你的团队一个恰当的激励,通过你自己满腔热情地做事,来感染和影响你的团队,来做出一番事业。

      (二)领导和管理的区别

      1.概念

      在去年的“批判和再造”活动中曾经涉及过此类的问题。王董事长在谈及领导和管理的区别时说过领导就是领而导之,管理就是管得住、理得清,实际上领而导之的解释和现代汉语词典中关于领导的解释很接近。管理在汉语字典中的解释是能负责某项工作顺利进行。如果用经济学的语言来解释领导和管理的话,领导就是要做正确的事,即负责正确的决策。管理就是正确地做事,就是将所交待的任务顺利地完成。

      2.管理和领导的区别

      (1)管理的起源。管理和处理复杂的情况有关。在二十世纪,随着国际大型组织包括大型跨国公司如通用电器、沃尔玛、摩托罗拉,以及国家间联盟如北美自由同盟、亚太经合组织等的出现,管理就成为应对这些大型组织出现的必然反应。这些组织的规模可能涉及到几十万人的企业,或是几亿人口的几个国家的同盟,如果没有一个好的管理,那么这些组织必然将杂乱无章,散沙一堆。因此,管理学自上世纪四十年代后就开始蓬勃发展,在七、八十年代初形成的一套管理学的理论,并诞生了一些经典管理学著作。当然由于种种原因,直到现在我们才开始学习国外六七十年代的管理学著作。

      (2)领导则是与应对变革有关。领导力是现代社会激烈竞争的产物。随着“地球村”的形成,国际间的竞争日益激烈。如技术的更新速度已经快到连我们都觉得不可思议,快到领域内的专业人士都觉得始料不及。随着国际竞争的加剧,国际劳动力结构的变化也越来越快。那么在这个变革的时代中,要生存,要想取得优势,领导和领导力就愈显重要。重大的变革也将不在是偶然现象,面对变革我们天然需要一个好的领导和统率来面对变革,掌握局势,在瞬息万变中把握住企业发展的方向和未来。

      (三)具体到某个企业来说,领导和管理的内容也是不同的

      在企业中,领导,尤其是董事长和总经理的主要任务,就是要为企业确定一个方法来实现公司的既定目标,而管理主要是做计划和预算。用经济学的语言来表述领导就是运筹和战略,管理更多的是一种程序。在运筹和计划运行的过程中,领导的任务就是使员工的行为能够协调一致,调和不同单位和部门间利益的平衡。而管理主要任务是组织和配备人员,这两者实际上就是教练员和主力队员的关系。在实施战略规划的过程中,领导最重要的职责就是激励你的员工。激励的方式主要是通过领导制定和宣传企业的远景目标,就像酒店集团的战略发展规划中具体地描述了我们的远景目标和核心竞争力。作为领导,一方面就要为员工描述一幅美丽的图画,否则这个企业的未来将可能是一片黯然;另一方面还要给员工一个跟踪指导和培训,让他们能够充分理解并接受这幅图画和远景,愿意为企业付出自己的辛勤劳动;第三方面,还有要给员工适当的奖励。领导要将公司和自己的成果和员工及追随者一起分享,这样的过程才是快乐的。管理作为一种流程,就是要控制和解决问题。领导是重在规划,是一种远景的激励。在管理学中,基本概念就是控制、协调、规划、监督。

      (四)要相信自己,树立“天生我材必有用”的信念

      领导不是天生的,我们每个人来到世上都是一种奇迹,每个人都有成为卓越领导者的可能和潜力,除非有先天的不足或智障。关键是要靠自己。大家都知道“书中自有颜如玉,书中自有黄金屋”这句话。颜如玉就是美女,黄金屋就是做官。湖南有位老师曾经说求学的目的是为了自己,为了能使自己有个更美好的未来和前途,让自己过得更优越些,本来是无可厚非的,但后来竟因此被辞退了,可见教育部门也存在很多不实事求是的人。但是我觉得我们的工作学习不是为了别人或老板,而是自己未来更充裕更美好的生活。我们在座的大多数人都受过高等教育,那么我们为的是什么?不也是为了使自己生活的更好一点。比如说大学同学三五年之内一般不会有太大的差别,但是十年八年后差别已经是非常的大,大家的智商都是一样的,但为什么待遇会差很多,可能有工作环境的原因,如单位、城市或社会关系的差异,但最关键的还是你个人对将来的把握和付出的努力。我始终认为,你想让自己成为什么样的人,你才有可能成为什么样的人,你想都没想过,那怎么可能会有结果呢。物理学家阿基米德曾经说过:给我一个支点我可以撬动地球。希望大家一定要树立“天生我材必有用”的信念。我曾和我们的高管人员说过,永远不要漠视我们的员工,这是中国企业的诟病。大家都一样是从最基层走过来的,都曾有过相同的感受。我们如果在自己的位置上能尽可能为他们创造机会的话,那么将有相当一部分员工会还给公司和社会很多的惊喜。那么我们何乐而不为呢?“自信人生两百年,会当击水三千里”,希望各位一定要有舍我取谁的信心和勇气。

      二、要成为一个优秀的领导者,你准备好了吗

      (一)态度决定一切

      这是米卢说的,他曾经带领五个足球水平中下等的国家挺进过世界杯。2002年担任中国国家足球队主教练,带领中国队44年来第一次杀进世界杯的决赛圈。米卢的魔力何在?其实他在中国的法宝就两句话:快乐足球和态度决定一切。快乐足球,是米卢一语道破了中国足球最大的毛病,就是中国足球是不快乐的。动辄就是为国争光,为中华民族争气,尤其让那些没受过多少教育的足球运动员去背负如此沉重的十字架,能不累吗,能不输吗?在我看来,足球是中国人并不擅长的一项运动,不像乒乓球和羽毛球。在关键时刻,连马来西亚都打不过,这就是心理负担太重的原因。而他的第二句话“态度决定一切”道出了我们每个人生活和工作的本源。心态和态度反映出一个人的世界观和价值观。如果心态调整好了,用良好的心态看待问题,用美好的愿望来看待别人,就会有正确的思路,思路决定出路,态度决定过程,过程决定结果。如果心态不好,那什么事都办不成。印度有个故事说有个穷人没鞋穿,整天的埋怨自己命苦,但当他有一天看见一个没有脚的人时,他再也不埋怨了。如果你想要有所作为的话,那么调整好心态比什么都重要。

      (二)脚踏实地,甘当蘑菇

      在国外企业有种对刚参加工作的新人的管理方法,蘑菇一般都生长在阴暗潮湿的角落里,不被人重视和看见。就是给新人在工作中设置重重的障碍,如将其放到一个不受重视的部门,做一些琐碎的事情,有时可能还会受到冷嘲热讽,得不到一些好的培训,代人受过,甚至任其自生自灭。我们每个人可能都有当蘑菇的经历,当然国内的企业不一定是有意识这样做。但是当你被别人忽视的时候或不得志时,你千万不要消沉,这可能是件好事,会消除很多不切实际的幻想,能使我们更加清楚地认识到脚踏实地才能走好自己的路。

      (三)做有责任心的老实人

      现在一提到老实人,好像有些贬义的味道,好像就是那种木讷呆板,只知道老老实实干事,甚至连女朋友也找不到的人,这是我们民族的悲哀。我们古井的第一条价值观就是“老老实实做人,实实在在做事,一切对事业高度负责”。中华民族是礼仪之邦,礼义诚信是我们的立身之本。但是很多人都已经忘记了,现在安徽提出要打造“诚信安徽”的口号,那何尝不是说明我们现在很多人不够诚信。诚信是做人的一项基本道德,做事的基本原则。今年二月份我参加省政法委召开的一个合肥地区企业家座谈会,讨论一个净化经济环境的文件,并对此提出合理化意见。我发言时谈了两点:首先,转换思想观念和意识比出台任何政策都重要。我们的优惠政策不比任何省市的政策差,甚至更优惠,但是为什么安徽的经济长期落后,就是思想观念和意识的问题。如现在的国外跨国投资正在由长三角和珠三角向中西部地区转移,我们现在最需要做的就是加强基础设施建设,为外商投资一个宽松的政策环境。让我们的政府和执法人员意识到他们是衣食父母,而不是臣民,这样我们的经济环境才能得到有效净化。很多外商投资倒不是很看中你的优惠政策了,而是城市环境和基础设施的建设。如果别人来投资时,地方政府机关门难进,脸难看,事难办的情况,那谁敢来投资?南方城市在转换思想观念做得不错,政府职能正在向服务性转变。其次,要创造一个让老实人不吃亏的环境。我们古井的价值观就是对做人做事本源的回归。在来酒店集团的八年间,我也在努力地创造一个让老实人不吃亏的小环境。不管做的如何,但我的确一直在努力这样做。

      要成为有责任心的老实人必须做到两点:第一就是公平正直。第二是要以公事为重。每个人都是在为了更好的生活而努力工作,人有自己的欲望也无可厚非,就像一首打油诗:“终日奔波只为饥,方才一饱便思衣。衣食两番皆俱足,又想娇柔美貌妻。娶得美妻生下子,恨无田园少根基。买得田园多广阔,出入无车少马骑,院内备有车和马,叹无官职被人欺。县官主丞还嫌小,只想宫中挂紫衣。做得皇帝求仙术,便想登仙跨鹤飞。若想世人心意足,除非南柯一梦西。”但是君子爱财,要取之有道,这样才能拿的舒心,花的安心。

      (四)胸怀大志,志存高远

      拿破仑有两句话我是最欣赏的:让驴子和学者走在中间。因为在冬天打败仗后,由于天气寒冷,驴子作为运载工具相当重要,保护驴子成为士兵的最重要的任务,让学者走在中间表明了他对知识的尊重。第二句话就是不想当元帅的士兵不是好士兵。对事业没有抱负那必将是一事无成。如果想也不敢想,更不可能有成功的机会。合肥酒店当时上五星级,但是很多人都提出置疑,连叶海华先生也觉得不可思议,但是结果我们经过不懈的努力成为了安徽省第一家五星级酒店。现在我们之所以有这么好的经营业绩,除了我们的经营管理层和各级员工的努力外,五星级也为我们挣得了不少生意和利润。

      (五)了解自己

      人贵有自知之明,因为只有你了解自己,才能给自己定好位,别人不知道你在想些什么,老实说,不是大喜大悲时,别人也不知道你是好人还是坏人。在体现人的本质时有三种情况:大喜、大悲和喝醉酒的时候。大喜,有的人得意忘形,大红大紫,但是一紫就烂。在大悲时,又意志消沉。我经常勉励自己,得意不要忘形,失意不要失志。有的人满口的仁义道德,但一喝醉酒什么丑态都出来了。所以在平常工作生活中,别人都不一定了解你,只有你自己才能定好位,树立一个明确的目标,把握好自己的未来。在我们的生活和工作中,就像金字塔一样,每个人都想站在塔尖上,但是不现实。所以我们一定要给自己定好位。在生活中有些人没给自己定好位,老是想怎么样,结果做什么,败什么。如真是给自己定好位,那么生活的空间就会广阔很多。如果你觉得自己是个很有激情的人或感染力的人,你有成为A 角的实力和冲动,那你就努力成为A角,成为一个领导者;或者不愿意抛头露面,成为B角也是个不错的选择,而且B角往往是企业的中坚力量。A角的流动性比较大。如通用电器的韦尔奇在经过层层筛选过后,从两百四十人中选择10位作为重点培养对象,后来又经筛选留下三人,后来实在难以取舍,因为他们都有可能取得成功。他经过痛苦的取舍后选择了一位,并使公司在三年内使通用电器的业绩增长了14%。而另外两人离开通用后,一人成为3M公司的CEO,另一人成为家具储运的公司的CEO,并都取得了成功。

      三、领导力成长的条件

      (一)充满理想的使命感

      作为一个领导者应该是一个充满幻想的理想主义者。作为领导者首先要充满理想、热情和激情,用这种发自内心热情和激情来支持自己的理想,这时你的使命感才会形成一种充满人气的凝聚力,才能带领自己的团队走向成功。这种使命感有三个目的:第一、激励你的员工。第二、凝聚一个团队。第三、使团队走向正确的方向。同时要注意在合适的场合、适当的方式、清晰的语言来表达公司的远景目标和战略规划。这也关系到领导者个人的沟通能力、影响能力和表达能力。

      (二)果断而正确的决策

      决策过程是个复杂的过程,需要果断而且要正确。正确的决策是评判一个领导是否称职的一个基本标准。如果领导者能够快速制定一个好的决策,就能够赢得大家对你的信任和尊重,增强所在团队的凝聚力。首先,当一把手最主要的要学会画句号。你要敢于承担起主要的责任,如何画这个句号,何时画,就要靠你正确的决策。如果你优柔寡断,同样办不成事。其次,选择员工。选择和配置员工是企业最困难的一件事。让什么员工做什么岗位的工作,提拔谁不提拔谁,或处理谁,纵然选择都是很困难的决定,但也不得不做,所以领导要勇于承担责任。再次,宣布的方式本身和决策同样重要。要选择一个尽可能隆重的场合,并经过充分的酝酿,要注意场合、方式、内容、语言,让大家心甘情愿地追随你。最后,要勇于承认错误。当你犯错误时,迅速反应过来,勇于承认错误,比你优柔寡断,掩盖事实真相好得多。在一个公司里,每天每个人都可能在犯错误。但要作为一个好的领导者,要勇于承认和承担自己的错误,这样你的部下才愿意追随你,动辄出卖自己的部下的领导终将无所作为的。

      (三)共享报酬

      1.作为一个成功的领导者,要给部下树立权利、责任和义务。既要有授权,也要明确他的权力、责任和义务。企业发展大了,如不适当释放权力,那么积怨将越来越大,导致团队军心涣散,人心不稳。让你的部下分享你的权力,承担你部分的责任和义务的话,这样的团队才是比较优秀和合理的。

      2.作为领导者要代表你的团队去改善团队的报酬。这里的报酬不单单指薪水,要站在团队的立场上考虑团队应该获得什么样的报酬、补偿和培训,并且将恰当的方式和数量相结合。(1)彼得原理中这样说道:“在一个等级制度中,每个职工趋向于上升到他所不能胜任的地位”。彼得指出,每一个职工由于在原有职位上工作成绩表现好,就将被提升到更高一级职位,因此每个单位总有些人呆在他不称职的岗位上。如果一位员工在自身的岗位上干得非常出色,但由于不适合更高的位置,那你将用什么样的报酬去改善他的状况,并最终解决这类不称职员工的问题?我认为可以通过加薪、免费假期、奖金等其它形式,让员工同样感到愉快。如果非要将不合适的人推向不合适的岗位,必将给公司和个人带来损失。(2)而作为领导人要了解自己的下属。还有些人是单位里的污水,他能将一个好的团队搅得人心不安,怨声载道。如果是一个好的同志,进入到一个差的团队,同样他也生存不下去,除非同流合污。有时我们也称他们是钻进瓷器店里的驴子,要不将它赶走,要不就把它拴起来。(3)通过分享劳动成果等方式与你的追随者共享报酬会激励他们。(4)领导者为你的团队提供的最好的报酬就是你的领导力。你的领导力强,公司就会沿着向正确的方向前进,团队都能得到进步,收入都能得到提高。作为团队能为领导者提供的最好的报酬是什么?是生产力。大家都能尽职尽责地工作,就会产生越来越多的生产力,企业才能走向健康持续发展的道路。

      (四)高效沟通

      沟通包括上与下、同级间的交流,甚至是亲人间也需要经常沟通。作为领导者只有和员工进行有效沟通,才能将自己的思想灌输给员工。我将从五个要点简单地谈一下:

      1.面对面的谈非常重要。领导者一定要抽出一定的时间和员工进行交流。员工也不要有任何畏惧的心理。

      2.肢体语言交流有时胜过语言的交流。有句俗话叫“身体力行”,行为和方式有时比语言更重要。

      3.学会锻炼自己的表达能力。当你面对不同的人群,都能进行比较好的演讲时,就能极大地巩固你的形象。因此,我希望大家也要可以有意识地锻炼自己的这种能力,并注意控制好语速和节奏。在前段时间的批判与再造活动中,我让每个人都充分准备,人人发言,有些同志本来连说话声音很小,经过几次锻炼后,到后来也能侃侃而谈,确实在表达能力上有了提高。在天柱山战略发展务虚会上,我就让每个人都上台演讲,阐述自己的观点。

      4.充分地理解别人,领悟团队的力量。要站在对方的立场,领悟团队的力量,一个企业的发展不是一个人行为,团队的力量很重要。我一直以我们的团队而自豪,我们的团队在安徽是个优秀的团队,因为我们的企业在安徽的同行业里都名列前茅。记得去年当选“安徽省十大经济人物”时,主持人问我的感受,我发自内心地说,首先我就要感谢我的团队,没有大家的努力就没有我们酒店集团的今天。我们成立时负债4000多万,现在虽然将近两亿,但是我们的资产和企业都有了长足的发展,这就是团队的力量。

      5.为了保持你的见多识广和正确的决策,对内要建立员工畅所欲言的环境。对外,行业内外的消息要了解,并且要不断地学习,保持与时俱进。

      (五)影响他人的能力

      这个能力分为两种:角色的力量和人格的力量,这两种力量都可以深刻地影响你周围的人。

      1.作为一个管理者影响力往往是基于他角色的力量,即他的职位。作为领导者经常需要运用人格的力量,这种力量来自于道德范畴的公平、正直还有知识,要通过人格的力量来描述和体现你的领导力。

      2.作为领导者应当把角色的力量作为权力的基础。角色是行使权力的基础,当然其他力量更重要,如做不到这一点,就不是一个好的领导者。不能用你的人格魅力来影响别人就带不好一个团队。

      3.要恰当地设置自己的权威底线。就是你能容忍一件事的最低底线。我有两个底线:(1)我允许大家犯错误,但是不允许欺骗我。(2)你可以随时给我提意见,有不同的意见非常正常,作为领导者应该具有广纳贤言的心胸,但是不能不尊重我。设置权威底线,也是影响他人能力的一个重要方面。

      (六)积极的态度

      心态问题在前面我已经谈了很多,在此不作赘述。

      (七)有效地管理你的时间

      如何将你的时间用在刀刃上,这是非常关键的。本来我准备作个专题讲座,但考虑到有效地管理时间对于提高领导能力有着重要的意义,所以,我放在这里简单地说一下。我们的领导和管理者通常都很忙碌,但是每天结束后也不记得忙的什么。而且很多负责人在忙碌时,你的下属却无所事事。这就是你没管理好自己的时间。我们的时间可以分为三块:一是受上级支配的时间,在这段时间把领导安排的事情做好。二是受组织和同事支配的时间。三是个人支配的时间,可分为受下属支配的时间和自由支配的时间。作为我们应该尽量减少受下属支配的时间。这样就可以抽出更多的时间来完成上司和组织交待的任务。在此前提下,尽量扩大你自由支配的时间。但是往往事与愿违,大量时间都被下属所占用了。美国经济学家威廉和唐纳德合作写了一篇文章《MONKEYONTHEBACK》被列入哈佛经典论文。文中把问题当成猴子,当下属把问题推给你时,猴子就跳到你背上了,直到替下属解决问题后,猴子才会跳走。解决的方法两条:一是约时间,十分钟内,面谈,我告诉你方法,你去做,这也是适当放权的一种方式。二是树立时间管理的概念。在管理时间的过程中,整理出哪些是事情的主要矛盾和矛盾的主要方面。只有在管理中抓住事情的主要矛盾和矛盾的主要方面,就可以做到工作生活两不误。

      四、我心目中的领导者
     
      我心目中的领导人应该是谦逊、意志坚定、学识渊博、公平待人。谦逊和意志坚定就是平和而执着,谦逊而无畏。带领团队主要是靠你的品质,如果一个人表现地张扬甚至张狂,那么他绝对不可能成为一个成功企业的领导人。匹夫之勇别于天下之大勇在于:匹夫之勇,拔剑而起,挺身而斗,免冠徒跣,以头抢地;天下之大勇就是猝然临之而不惊,无故加之而不怒,忍小忿而就大谋。

    posted @ 2008-01-08 19:24 灵! 阅读(169) | 评论 (0)编辑 收藏

    企业流程建设的一些建议(转)

      1、一个目标:管理规范化、优化。

      2、两种途径:固化和优化

      (1)固化:是指把以前做的好的,顺畅的、科学的东西通过流程固定下来,把好的东西保留下来;

      (2)优化:是指原来做的不好的,包括缺陷的、多余的、不科学的、不经济的、不顺畅的、缺乏的东西健全和调优,调优之后再固化。

      3、三项工具

      (1)程序文件:即对每个流程的描述性说明;

      (2)流程图:即将流程通过图示表示出来;

      (3)流程表/工具:是今后流程在运行的时候所使用的表单、工具、记录、审查、审批等。

      4、四个阶段

      (1)系统调查:对现行的流程系统进行调查,摸清现状;

      (2)流程分析:哪些是好的?哪些还需要改进,如何改进,与相关部门充分沟通,提出解决办法;

      (3)流程建设:即针对相关流程进行建设,提出流程文件和流程规则;

      (4)实施优化:持续优化流程、在实施中不断改进和完善流程。

      5、五点提示

      (1)业务流程建设不是孤立的,要和业务特点结合

      (2)业务流程建设不是孤立的,必要是需要优化组织和职能;

      (3)业务流程建设不是孤立的,其有效实施需要必要的制度保障和执行力建设;

      (4)业务流程建设不是孤立的,应该和绩效管理、考核活动挂钩起来;

      (5)流程优化、流程重组的根本实质和手段是信息化。

      流程建设是一个系统工程,要做好,远远不止上面的几点提示。以上意见,是我们在企业流程建设咨询的一些体会,仅供参考,建议在初次建设,贵单位还是委托咨询公司的专业力量进行,企业也可以从中获得一套有效的流程建设方法,在后续建设和流程改进中加以运用。

    posted @ 2008-01-08 19:23 灵! 阅读(167) | 评论 (0)编辑 收藏

    何拥有成功CEO的演讲口才技巧

        给听众明确的主题 每一场演讲、报告或其他信息交流,都需要一个主题。大部分所能记得的就是一个主题而已。一个重要的概念自有它的生命,它不需要出现在一场大型的“演说”里头。它之所以了不起是因为它所传递的信息,而非它的长度。简短的演说,有突破性的想法,这就是秘诀。

        针对当下 谁都不喜欢听罐头式的演讲。罐头式的演讲令人倒胃口。你必须对时事发表谈话。“如果你讲的都是老生常谈,”某CEO说,“坐在那儿的听众会说:‘这家伙是谁,为什么找他来演讲?’”你谈的内容必须跟他们有关,跟当下的时事有关,才能获得听众的欢心,否则他们不见得打算听下去。

        讲话简单明了 许多演说的问题出在信息量过大。信息要简洁明确,人家才会记得。

        有话直说 我曾经做过一个针对沟通的问卷调查,发现大家最希望领导者能够具备的特质是诚实和正直。讲话要像个CEO,就是你讲的信息要真实。听众需要的领导人不只是一个优秀的演说家,他们希望领导者能够说真话,不管真相如何。

        乐观以待 当上CEO,你所面对的时代有好有坏,你必须怀抱希望以平衡现实。乐观主义似乎是领导阶层的特点,CEO必须预见还要谈论未来的“可能”。

        放眼未来 在困难的时候,人们仰望领导者寻求希望。在911事件发生后,纽约市长朱利安尼发表讲话,他将重点放在希望上,把人们的注意力转移到未来:“纽约市民会康复,在情感和政治方面变得更坚强,彼此之间更亲密,我们的经济也会更强大。”发言的时候,要让听众知道你的信念大有可能。放眼未来,人们自然会起身相随,让美梦成真。

        脚踏实地 CEO和许多听众之间的沟通显然处于不利地位,你的头衔令人退避三舍,听众觉得他们跟你之间毫无共同之处。演讲、会议甚或闲聊一开始就这样,真是糟糕透顶。你的任务就是找到建立关系的渠道。欲建立关系,就必须真诚。

        有所主张 人不是光为一张饭票做事。人们做事是为了参与一份伟大的事业,他们希望工作?荩能够有目的,组织能够有它的使命。他们想要知道尽一己之力多少能够起点作用。CEO就是将组织的任务和目的具体呈现的那个人。

        常犯的沟通错误

        低估向公众演说对个人生涯的重要性 一个零售业主管在提升后总是不声不响地去上班,不动声色。她不是会引起别人注意或寻求协助的那种人。她也避免做任何报告,开会时总是沉默不发一言,除非人家有问题问她。这种态度在过去也许有用,如今却注定要失败。她后来因为一次不得已的机会做了一场演示而彻底转变态度,她总结教训说:“花了7年的时间,我才明白很久以前就该学会这一点。”

        忘记听众的存在 把重点放在听众身上。不论是对同事、客户或员工讲话,在提笔写下演讲稿之前,以你的听众为念。为了确保你记得听众的存在,最好的办法就是发掘他们想要知道的内容。打个电话,问问了解与会者层次的人,搞清楚你的谈话内容对他们价值何在。

     

        第一个问题就搞砸了 身为电视节目主持人,有时候我的访问会如此开场:“谈谈你的书。”然后就看到知识渊博的专家回答得结结巴巴。你一定要准备好面对最简单、明显的问题。想想这样的问题有哪些,准备好答案,一开始才会顺。也许你需要找个人,一个了解听众或媒体的人,提醒你最明显的问题有哪些。一旦问题了然于胸,就想出一个最了不起的答案。简单为要,不要用细节把听众搞得不知所措。如果你准备好简单的问题,困难的问题也会变得简单多了。

         不知道何时该继续,何时该结束 没什么比得上一个不知何时该坐下来的演讲者更让人讨厌了。谁也不喜欢找一个罗嗦的演讲者,而他自己还未察觉。你已经超前了,如何停下来?首先,要抓好讲话的时间,站起来讲,不要坐在原地念稿子。进到里面,准备好随时修整讲稿,要体谅听众。假如第六感告诉你,你在哪儿站太久了,情况可能确实如此。注意看是不是有人接近讲台,对你使眼色。很少人会因为你讲的太少表示有意见。

    posted @ 2008-01-08 19:22 灵! 阅读(138) | 评论 (0)编辑 收藏

    如何做好质量保证工作(转)

        软件质量保证和软件控制都是得罪人的工作,并不是太好的做。经常是费力不讨好,最后人得罪了不少,力气费了不少,成效不大。而很多质量保证人员也不得不离开所在的单位。很多著名的公司为了搞好质量工作,采用国外先进的管理方法进行质量保证,但也往往遇到水土不服的问题,因为这个问题下岗的高级管理人员也不是一个两个了。为什么在国外很好的质量保证手段在中国就水土不服?为什么质量保证人员总是打一枪换一个地方(很多质量保证人员在一个地方工作的时间往往是2年左右)。如果我们一味强调客观因素,而不是从我们自身找问题,是没有办法真正找到解决这个的方法的。下边就我说说我自己的一些感受。

    1 质量保证工作,重流程,轻实施是我们的一个问题。

        现在的质量保证人员一般手里都不乏这样或那样的证书,拿我们软件质量保证人员来说,最基本的是ISO9000的证书,然后是CMM/CMMI,似乎没有这些证书就不适合搞质量保证工作。如果让他们规范单位开发流程,他们在几天之内就可以给你拿出一大堆流程文件来,而且可以保证这些问题是符合质量的要求。但一旦到了实施阶段,就会发现这些流程不能适应公司的具体要求,不是太繁琐,就是开发人员搞不明白,和技术人员矛盾不断涌现,如果你的对手只是普通的技术人员那算你走运,你还可以挺几年,但如果是和公司几个核心的开发人员产生矛盾,那你准备卷铺盖走人吧。一个公司没有质量保证人员不会死,但核心技术人员如果走了,公司就会面临倒闭的问题,再傻的老板到这个时候都会挥泪斩马谡的。所以,想真正实施好公司的质量保证一定要重流程,更重实施。

    2 质量保证工作,重知识,轻经验。

        我这里说的知识是指质量保证知识,经验是指实际工作经验,拿我们做SQA的来说就是你的开发经验,我遇到了很多SQA只有1-2年的开发经验,或者干脆就没有开发经验。想一下,没有调研经验的人去给一帮参加过7,8个大项目调研的人将如何调研,一个没有编写过设计文档的人,在给一群架构师讲解如何设计软件,一个没有代码编程经验的人给一帮代码量超过20万行的程序员讲代码规范,你说是不是一个可笑的事情,开发人员都是很实在的人(甚至有时候可以说比较傻的人),他们长期的工作经验使他们只信服那些实力比他们强的人,如果你有充足的实际工作经验(软件开发经验),说的问题到位,能够将质量保证理论和实际开发结合,可以帮助他们解决实际问题,他们很快就会接受你,否则他们会对你不屑一顾。而你的质量保证根本无法实施。

    3 质量保证人员不要抢功劳。

        一个公司就象一个盘子,盘子里的蛋糕就这么大。你进来了需要从别人的蛋糕里切一块,别人自然会有反弹,作为质量保证人员在这个时候最好的方法就是退后一步,将功劳让给开发人员。质量保证工作会涉及到公司的各个部门,各项工作,会影响公司几乎所有的工作人员,如果在这个时候,你想把所有的功劳都抢到自己手里,会树敌无数,一旦这种情况出现,一个是你的工作无法推行(基本没有人支持你),另外一个就是你不得不离开这个公司了。但如果你是聪明人,你帮助开发人员不断的改善他们的工作,他们可以很好的完成自己的开发工作,加班时间大大减少,产品质量不断提高,不断获得客户和领导的表扬,而且加了工资,你想在这种情况下,他们怎么会不配合你的工作?所以说,好的质量保证人员永远是站在成功者背后的那个人,他默默地做着自己的工作,为别人做绿叶。一个良好的心态才能真正搞好质量保证工作。在这里再多说一句,任何人的功劳都会得到回报。当公司的整体质量提升了,公司的效益提高了,你觉得老板会不明白这是谁的功劳吗?

    4 质量保证工作,不能一开始就全面开花,而要由点到线,由线到面。

        上边说了质量保证工作会涉及到单位工作的各个方面,在你刚进入到公司的时候,立刻会发现很多问题,但如何着手,需要一个谋划,一般来说比较容易见效果的,投入不大的方面是你首先要考虑的(有时候还不是公司最主要的质量问题)。如果你能在短时间让别人看到你的工作效果,见到成果,认可你的实力,才可能和他们达成一定的协作关系,为以后的质量保证工作铺平道路。另外需要说的,质量保证需要不断的投入人力和物力,而这些东西在你刚进入公司的时候往往是不具备的,分清事情的轻重缓急,难易程度,逐步实施质量保证。可以保证你的工作的顺利实施。

    5 做质量保证工作,最重要的是做人的工作,这里分两个问题来说明,一个是你要有自己可信赖的人员。

        打铁先要自身硬,做质量保证工作,不但你最好有技术背景,精通软件开发,遵守公司的规章制度,你还要有一支可培养,可信赖的质量保证队伍,一个人的精力和能力毕竟是有限的,而一旦你形成了一个良好的质量保证队伍就可以保证你的工作越做越有成效。另外一个就是善于借力打力。上边说过,绝大多数开发人员都渴望成功,他们缺少的只是经验,将你的经验和知识和他们分享,让他们成为的朋友,成为工作的伙伴,成为你的编外质量人员,这对那些质量保证人员编制比较少的质量保证部门格外重要。

    6 质量保证工作,遇到问题,先解决问题,找出原因,进行改进,而不要一味地追查责任。

        质量保证人员的责任是改进质量工作,提高整个公司的工作效率,而不是老板,去追查这是谁的责任。当一个问题发生的时候,所有的人员都在往后躲。怕承担责任,作为质量人员如果在这个时候,首先去追查责任,那你就大错特错了,首先我们要解决问题,看有什么补救的方法,先想办法将事情办好,然后仔细分析问题产生的原因,找到如何避免这个问题再次发生,至于责任在哪个责任人,自有具体的管理人员负责,这不是我们的责任,说简单一点,我们的责任就是协助一切工作人员做好他们的工作,而不是给人员裹乱。

    posted @ 2008-01-08 19:21 灵! 阅读(394) | 评论 (0)编辑 收藏

    改进管理方法,增进员工激情 (转)


    制造激情第一招,改变并制造危机:

    变化能让人心理上有新鲜感,新鲜带来好奇,没有人不图新鲜,新的东西对老人不能躺在原有的功劳簿上睡大觉,他为了维持自己的权威不得不奋勇争先,新人可算有了颠覆格局的机会,一马当先,激情澎湃,都是常见的现象。很多创业团队的人,既没有股份,也不是什么经理,依然那么强的归属感,那么拼命,反而是公司发展起来后,待遇好了,激情却褪了。所以要改变,并在改变的时候制造出危机来,让核心团队成员生活在市场竞争和市场危机中,不过注意一点,大家辛辛苦苦干半天,生于忧患了,不要太吝惜金钱,该奖励就要奖励点,以免心力交瘁时还要考虑家庭生活负担,那他极有可能就真得不玩了。

    制造激情第二招,制造势均力敌的竞争:

    在日常生活和工作中设置竞争的组织机构职责和评价方法,让经理之间竞争去。注意两个问题:竞争者之间要势均力敌,差得太多也就没近了;对放弃竞争的要处理,对竞争成的要精神奖励;让受奖励的是70%以上的人,寒碜的是小部分人,千万不要做反了,人都有从众心理,奖励人多的,差的小部分会努力往上靠,少数优秀的被奖励,优秀的往庸人堆里扎,切记。

    制造激情第三招,让我干的管理模式改成我要干的模式:

    刘绍勇董事长发现飞行员缺乏激情,于是开启了自费学飞行的先河,符合条件的人都可以报名,缺钱公司可以贷款,飞行员是公司的资源,最难管,老人躺着睡大觉也不敢把他怎么样,刘先生的一招使许多具备专业素质的年轻人积极参与进来,后备梯队就有了,以积极的后备梯队给老的人制造了无形的压力。原来是公司认为需要必须把某人派去,这是让我干,现在是通过放开,成了我要干。你不干,别人干,原来比你下一层次的人要干,上一层的人就坐不住了。

    制造激情第四招,强压并有让其有成就:

    下属不能主动进取,就强行加压,让他加班,频繁检查,并让他有短期的成就,几个要素缺一不可。

    维持激情第五招,不断发展自己的组织

    对下属最大的激励是不断发展你的组织,不断膨胀的规模,不断增加的市场份额,忙不过来的业务让员工会有很强的受感染力,究竟是为什么我也不知道原因。

    创造激情第六招,选择认同这个业务并能在执行中发现乐趣和知识点的人:

    有的人就从来不缺乏激情,只是能否找到宣泄的窗口,所以一定要找到这种人,他认同这个业务,并能在这个业务的执行中发现很多的学习点和乐趣,然后他才能执行好。天生缺乏激情的人,不能感染他人,有激情但没在您所希望他负责的岗位职责上的人,通过描述业务的点看能否点燃他的激情,因为有的年轻人可能接触某类业务少,不了解细节的学问,一旦深入可能会沉迷其中,这时候就需要引路人指给他。

    维持激情第七招,领导者个人感染力和管理方法:

    以上都是外围的因素,领导者本身也是有文章可做的,激情的创造和维持基本上来自于中上层管理者,基层经理如果被授权足够多,也能起到一点作用,比如个人的激情能感染周围的人,再加上一些具体方法,让团队的气氛和谐,争论但不诋毁。具体的术方面的方法和工具未来会有专门的文章讲述,不再细化了。

    内因决定外因,外因通过内因起作用,激情是内心的表现,是内因,攻心为上,有了内因,外因的条件再艰苦,都将无往而不胜。泥腿子赶走了日本鬼子,土八路打败了蒋正规军,靠的是激情,革命歌曲大比赛,连队之间大比武,支部建在连上,严明的纪律,整齐划一的生活规矩等等细节都是创造和维持激情的战术。激情的人、激情的方法将创造出激情的事业。

    posted @ 2008-01-08 19:21 灵! 阅读(134) | 评论 (0)编辑 收藏

    自我训练

    自我训练
     
    1.程序
     
    (1)训练员询问成员,怎样才算自我肯定的人?摘要写在海报纸上。
     
    (2)说明坚定者与软弱者的特质,请成员三人一小组讨论其影响。
     
    (3)说明妨碍自我肯定的内在恐惧,请成员三人一小组填表,并分享填写内容。
     
    (4)说明反应类型表,请成员阅读资料(之二)的情境,并填入自己的反应,三人小组
     
    并核对反应类别。
     
    (5)说明权利的意义与重要性,请成员填写“我有哪些权利”,三人小组分享,并推派一
     
    人报告填写的内容。
     
    (6)三人小组讨论、练习资料的例子,训练员检核成是否确实了解自我肯定行为的做法。
     
    (7)请成员回想自己在生活中有哪些不能自我肯定的行为,填入资料(之五),并斟酌自我肯定反应的行为,由三人小组讨论,直到满意为止。
     
    (8)团体统整,训练员检核成员不能自我肯定的行为,进行讨论或演练。
     
    2.注意事项
     
    (1)训练员于活动中应多联系,例如成员间相似的软弱点、权利与成就,须以客观的角度观察,不能自我肯定的原因是否来自文化、角色或社会阶层,引发成员信任、开放的气氛 ,促成行动改变的意愿。
     
    (2)注意传统规范所造成的不能自我肯定行为,不必急于要求成员改变,让成员体验这些规范他的关系,协助成员了解这些规范对他的意义与影响。
     
    (3)三人小组于活动开始即成立,全部活动组内人员不变动,以增加安全感,组成三人小组时,训练员可鼓励成员,主动邀请自己关心的组员。
     
    3.资料
     
    [之一] 妨碍自我肯定的内在恐惧
     
    1.害怕伤了别人的感情
     
    例:_________________________________________________________
     
    2.害怕被拒绝
     
    例:_________________________________________________________
     
    3.害怕失败
     
    例:_________________________________________________________
     
    4.害怕被伤害
     
    例:_________________________________________________________
     
    5.害怕有经济困难
     
    例:_________________________________________________________
     
    [之二] 分辨你的行为反应模式
     
    1.情境
     
    你正搭高速列车到纽约途中,邻座男士抽起烟来,于是空气变得很差,使你难以忍受。在这种情况下,你会如何反应?阅读下面的反应,并找出最接近你自己反应的句子。
     
    2.我的反应是
     
    (1)我觉得生气、愤怒,可是我不会有什么反应。 
    (2)我觉得生气、愤怒,而且会用攻击性字眼和声调告诉对方他不应该在车上抽烟。
     
    (3)我觉得生气,但我会用平静的语调告诉他,请他不要在车上抽烟。
     
    (4)我觉得生气、愤怒,但不对他说什么,而是去对乘务员抱怨这个人抽烟,看看她以 做什么。 
    3.反应类型
     
    (1)非肯定型。
     
    (2)直接攻击型。
     
    (3)自我肯定型。
     
    (4)间接攻击型。 
    [之三] 我有哪些权利?
     
    1、生涯计划与事业选择方面
     
    (1)我有没有权利去要求别人帮助?
     
    (2)我有没有权利决定是否继续进修?
     
    (3)那些对我很重要的选择,我有没有权利不同意父母的意思而自己决定?
     
    (4)我有没有权利不接受别人给我的忠告?
     
    (5)我有没有权利决定如何利用我自己的时间?
     
    (6)--------------------------------------------------------------
     
    (7)--------------------------------------------------------------
     
    (8)--------------------------------------------------------------
     
    (9)--------------------------------------------------------------
     
    (10)-------------------------------------------------------------
     
    2.人际关系方面
     
    (1)我有没有权利让别人知道我很生气?
     
    (2)我有没有权利选择与谁做朋友,不与谁做朋友?
     
    (3)我有没有权利拒绝人情请托?
     
    (4)与朋友交谈,当不想继续时,我有没有权利停止这个谈话?
     
    (5)我有没有权利请邻座的人不要吸烟?
     
    (6) ------------------------------------------------------------
     
    (7) ------------------------------------------------------------
     
    (8) ------------------------------------------------------------
     
    (9) ------------------------------------------------------------
     
    (10)------------------------------------------------------------
     
    3.感情婚姻方面
     
    (1)在男女朋友之间,我有没有权利拒绝对方的亲密举动?
     
    (2)我有没有权利主动追求我喜欢的异性朋友?
     
    (3)我有没有权利让对方了解我的感觉?
     
    (4)我有没有权利决定自己的终身伴侣?
     
    (5)我有没有权利决定自己什么时候结婚?
     
    (6) ----------------------------------------------------------
     
    (7)----------------------------------------------------------
     
    (8)----------------------------------------------------------
     
    (9)----------------------------------------------------------
     
    (10)---------------------------------------------------------
     
    [之四]:我肯定行为练习
     
    1.主管对部属说:“你必须更努力工作,我们需要的是一个在这个领域中的哈佛经理,而不是一个跟随者,我实在很怀疑你是不是有这个能力?”
     
    如果你是部属,你是反应是:
     
    _______________________________________________________________
     
    请对照“反应型表”,看看你的反应是属于哪一型?
     
    如果不是自我肯定型,请修改成自我肯定型的反应:
     
    _______________________________________________________________
     
    2你排队买票,要看七点的电影。这是一部精采的得奖影片,所以观众很多,排在你
     
    前面的人不少,你耽心若是买不到票,又得排两小时等下一场。但这时候,却有人在你面前
     
    插队。你的反应是:
     
    _______________________________________________________________
     
    请对照“反应类型表”,看看你的反应是属于哪一型?
     
    如果不是自我肯定型,请修改成我肯定型的反应:
     
    ________________________________________________________________
     
    [之五] 我不能自我肯定的行为
     
    请你想一想,在生活中有哪些你觉得不甘心 、委屈、挫折或误解的经验?在这些经验中是不是有些你重视的权利被侵犯被压抑了?请把这些经验写下来,并尝试将自我肯定的反应方式写出来。
     
    经验一:________________________________________________________
     
    自我肯定的反应:________________________________________________
     
    经验二:________________________________________________________
     
    自我肯定的反应:________________________________________________
     
    [之六] 自我肯定量表
     
    姓名: 性别: 日期:
     
    评分标准:1.从来没有 2.很少 3.偶尔 4.大多是 5.经常是
     
    1.当一个人对你非常不公平时,你是否让他知道? 1 2 3 4 5
     
    2.你是否容易作决定? 1 2 3 4 5
     
    3.当别人占了你的 位置时,你是否告诉他? 1 2 3 4 5
     
    4.你是否经常对你的判断有信心? 1 2 3 4 5
     
    5.你是否能控制你的脾气? 1 2 3 4 5
     
    6.在讨论或辩论中你是否觉得很容易发表意见? 1 2 3 4 5
     
    7.通常你是否表达你的感受? 1 2 3 4 5
     
    8.当你工作时如果有人注意你,你是否不受影响? 1 2 3 4 5
     
    9.当你和别人说话时,你是否能轻易地注视对方的眼睛?1 2 3 4 5
     
    10.你是否易于开口赞美别人? 1 2 3 4 5
     
    11.你是否因很难对推销售员说不,而买些自己实在不需要或并不想要的东西? 1 2 3 4 5
     
    12.当你有充分的理由退货给店方时,你是否迟疑不决? 1 2 3 4 5
     
    13.在社交场合你是否觉得没有困难去保持交谈? 1 2 3 4 5
    14.你是否觉得别人在言行中很少表示不欢迎你? 1 2 3 4 5
    15.如果有位朋友提出一种无理要求,你能拒绝吗? 1 2 3 4 5
     
    16.如果有人恭维你,你知道说些什么吗? 1 2 3 4 5
     
    17.当你和异性谈话时,你是否感到紧张? 1 2 3 4 5
     
    18.当你生气时是否会严厉地责骂对方? 1 2 3 4 5
     
    [之七]:自我肯定量表计分与解释
     
    1.高度自我肯定:分数相加,得分在77分以上者,表示非常自我肯定,经常能适当、时地表露自己的意见与感受。
    2.中偏高度自我肯定:分数相加,得分在52—76分之间,表示大多数时候能表露自己的意见与感受,但偶尔做不到。
     
    3.中偏低度自我肯定:分数相加,得分在26—51分之间,表示偶尔能自我肯定,但大多数时候不能表达自己的意见和感受。
     
    4.低度自我肯定:分数相加,得分在26分以下者,表示非常不自我肯定,经常不能表露自己的意见与感受。

    posted @ 2008-01-08 19:20 灵! 阅读(126) | 评论 (0)编辑 收藏

    将培训融入游戏

           80后可望迅速挤满IBM光板凳

      “80后这一代非常渴望学习,渴望为自己的职业生涯做出更好的规划。现在每个人都是知识工作者,如果今天企业不对他们做一些投资,他们马上就会找另一家愿意做投资的人。”

      IBM大中华区人力资源总监郭希文说,IBM为员工提供了一个不断学习和进步的环境,具有一整套完善而创新的体制。在和IBM共事的时间,员工可以学习到很多东西,展现自己的能力,同时我们还可以帮助他们挖掘潜能,在这样双赢的情况下双方会有很好的伙伴关系。

      “不学习的人呆不下去”

      庞大全面的培训系统一直是IBM的骄傲。

      进入IBM的新员工首先会按照职属不同进行相应的集中培训,考核合格后,进入实习期,每个新员工都会有一位指定的师傅一对一进行帮带。师徒共同制定一个实习计划,定期反馈实习情况。实习结束后,员工可以提出还需要哪些培训内容,也可以要求继续有一个师傅。 

      对老员工也有非常完备的员工培训制度,有传统的教师培训和网上培训等多种方式。员工还可以提出公司外部的培训要求,只要要求合理,公司都会同意并给予经费。

      对一些优秀有潜力的员工,IBM提供了经理培训,即将升职的员工在升任之前有本地化培训;升任后有为期一年、全球统一的e-learning或其他培训,同时也会为参加这类培训的经理各自指定辅导员。

      另外,IBM每个主管级以上员工在上任伊始都有一个硬性目标:确定自己的位置未来由谁接任。接班人的成长关系到主管自己的位置和未来,也作为业绩进行考核,所以经理层员工会尽力培养他们的接班人,这就是著名的“长板凳计划”。它使IBM有备无患,每个重要的管理职位都有“替补队员”。

      在IBM,培训从来都不会停止。鼓励员工学习和提高,是IBM培训文化的精髓。
    将传统培训融入现代游戏

      在虚拟学习的趋势日渐兴起时,IBM大中华区人力资源总监郭希文开始着手推动IBM的培训方式变革。

      今年7月IBM人力资源部门主导开发的“Sales Quest”培训游戏正式面向400名销售人员试推行。在“Sales Quest”中,参与游戏的玩家(员工),需要在限定的时间内,了解客户、代理和竞争对手的情况,建立整体的销售策略,维护客户关系,满足客户的需求,最后完成项目目标,虚拟完成整个销售过程。IBM培训部门将一些真实案例加入游戏中,通过智能引擎对玩家(员工)表现做出判断。游戏过后,会给出玩家一份报告,指出优点和不足,督促下次改进。

      据调查有80%的受试者玩了这个游戏,其中有1/3的人玩了两次,1/6以上的人玩了三次或更多。IBM大中华区人力资源部学习总监Lauge Sorensen说,这一代年轻人从小就生活在电子游戏、电脑游戏的环境中,因此“Sales Quest”这个环境对于他们来说非常自然。在第一个试点成功推出后,IBM计划把受众进一步扩大到IBM中国的1500人,同时准备面向印度销售人员推行这款游戏培训方式。除了销售人员外,IBM也在考虑为项目经理人和新员工等提供以游戏为基础的虚拟环境学习。

      此前,IBM已经通过Second Life上的虚拟岛屿,帮助新员工尽快熟悉和适应工作,他们在这个虚拟岛上沟通交流,解决他们在业务中遇到困难。

    posted @ 2008-01-08 19:20 灵! 阅读(130) | 评论 (0)编辑 收藏

    CMM的结构和基本内容

    CMM描述了五个级别的软件过程成熟度(初始级可重复级已定义级已管理级优化级 ,成熟度反映了软件过程能力(Software Process Capability)的大小,任何一个软件机构的软件过程必定属于其中某个级别。除了第一级以外,每级成熟度又由若干关键过程域(Key Process Area)构成。五个成熟度及其关键过程领域如图所示:

    图中的每个关键过程域分别针对软件过程的某一方面,具体描述了某级成熟度下软件过程在该方面所应达到的的一组目标和实现这些目标的一组关键活动(Key Practice)。所有关键活动被划分为五类,分别为完成该组目标所需的承诺(Commitment to Perform)、前提条件(Ability to Perform)、实际动作(Activities performed)、度量分析(Measurement and Analysis)以及验证(Verifying Implementation)。上述五方面被称为五个Common Features。

    CMM的结构如图所示:

     

    需要提出的是,任何一个成熟度级别的关键过程域集都是本级描述的关键过程域集和所有下级的关键过程域集的并集。如3级的关键过程域就应有13个不同的域,其中7个是3级自己包含的,6个属于2级成熟度,而4级应有15个域。

    第一级:初始级( The Initial Level

    初始级的软件机构缺乏对软件过程的有效管理,其软件项目的成功来源于个人英雄主义而非机构行为,因此它不是可重复的。

    第二级:可重复级( The Repeatable Level

    概述:

    第二级软件机构的主要特点是:项目计划和跟踪的稳定性,项目过程的可控性和以往成功的可重复性。更具体的说:

    • 机构建立了管理软件项目的策略和实现这些策略的过程。
    • 新项目的计划和管理基于类似项目的经验。
    • 过程能力的增强基于以各个项目为基础的有纪律的基本过程管理。
    • 不同的项目可有不同的过程,而对机构的要求是具有指导项目建立适当管理过程的策略。
    • 每个项目都确定了基本的软件管理控制,包括:
      • 基于前面项目的经验和新项目特点,做出现实的项目承诺(如预算、交付期、软件质量等);
      • 软件项目管理者要跟踪开支、日程、软件功能;
      • 满足承诺的过程中的出现的问题要及时发现,妥善解决;
      • 定义了软件项目标准,且机构确保其被遵守。

    构成:

    本级的关键过程领域(KPA)包括:

     

    客户的需求是软件项目的基础。软件需求管理的目的是在客户和软件项目之间达成对客户需求的一致理解。

     

    为软件工程和项目管理建立一个合理的计划。

     

    使管理者对实际的软件项目进展过程有足够的了解,以在项目效能偏离计划太多是采取有效措施。

     

    选择合格的分包商,并有效管理之。

     

    对软件项目过程及其间生产的各个产品进行监管以保证最终软件质量。

     

    在整个软件生命周期里建立并维护软件项目的工作产品的完整性。

     

    第三级:已定义级( The Defined Level

    概述

    第三级的主要特征在于软件过程已被提升成标准化过程,从而更加具有稳定性、可重复性和可控性。处于第三级的企业具有如下一些特征:

    • 机构采用标准的软件过程,软件工程和管理活动被集成为一个有机的整体。标准化的目的是使之可使管理者和技术人员有效工作。
    • 有一组人员专门负责机构的软件过程,并且在机构中有培训计划来确保 stuff manager 有知识和技能完成所赋予的角色。
    • 标准的软件过程结合项目的特点即形成定义的软件过程,它包括一组集成的定义良好的软件工程和管理过程。
    • 一个定义良好的过程包括就绪准则、输入、完成工作过程、验证机制、输出和完成准则。
    • 在已建立的产品线上 cost, schedule, functionality 均可控制,软件质量被加以跟踪。
    • 过程能力体现在在机构范围内对一个定义的软件过程活动、角色和责任的共同理解。

    构成

    第三级主要处理以下的 KPA:

    确立机构对于改进机构的软件过程能力的软件过程活动的责任。

     

    开发和维护一组有用的软件过程assets和提供一个用于定义定量过程管理的有意义的数据的基础

     

    开发个体的技能和知识以使他们能够更加有效的完成他们的角色

     

    基于业务环境和项目的技术需要,从机构的标准软件过程和相关的过程assets经过剪裁,将软件工程和管理活动集成为一个有机的定义的软件过程。

     

    一致地完成定义良好的工程过程。它描述了项目的技术活动,如需求分析,设计,编码和测试。

     

    确立软件工程组主动介入其它工程组以便项目能更好满足客户要求的手段

     

    早而且有效的排除软件工作产品中的缺陷。它可通过 inspection,structured walkthrough等手段进行。

     

    概括来说,第三级企业的重点是 Engineering processes and organizational support

     

    第四级:已管理级( The Managed Level

    概述:

    第四级的软件机构中软件过程和软件产品都有定量的目标,并被定量地管理,因而其软件过程能力是可预测的,其生产的软件产品是高质量的。具体地说,第四季的机构具有如下特征:

    • 软件过程和产品有定量质量目标。
      • 重要的软件过程活动均配有生产率和质量度量;
      • 数据库被用来收集和分析定义软件过程的数据;
      • 项目的软件过程和质量的评价有定量的基础;
    • 项目的产品和过程控制具有可预测性。
      • 缩小过程效能落在可接受的定量界限内的偏差;
      • 可区分过程效能的有效偏差和随机偏差;
      • 面向新领域的风险是可知并被仔细管理;

    构成

    本级的关键过程领域包括:

         定量地控制软件项目的过程效能。

     

          定量了解项目软件产品的质量,并达到既定的质量目标。

     

     

    第五级: The Optimizing Level

    概述

    概括来说,第五级的主要特点是技术和过程改进被作为常规的业务活动加以计划和管理。处于第五级的企业具有如下一些特征:

    • 机构集中于连续的过程改进
      • 具有标识弱点和增强过程的手段。
      • 采用过程数据分析使用新技术的代价效益并提出改进。
      • 项目队伍能够分析出错原因并防止其再次出现。
      • 防止浪费是第五级的重点。
    • 改进的途径在于已有过程的增量改进和使用新技术和新方法的革新

    构成

    识别出错原因,防止错误再现 (通过改变定义的软件过程)

     

    识别有益的新技术 (工具、方法和过程),并按有序的方式将其转移至机构之中。其重点在于在变化的世界中有效的完成革新。

     

    连续改进机构所采用的软件过程,以改进软件质量,提高生产率和减少产品开发时间

    概括来说,第五级企业的重点是连续的过程改进  

     

    纵观整个 CMM,软件企业提高自身成熟度的历程是一个从无序到有序,从特殊到一般,从定性到定量,最后不断自我完善的过程。

    posted @ 2008-01-08 19:18 灵! 阅读(199) | 评论 (0)编辑 收藏

    CMM简介

    从第一台计算机出现至今,计算机的发展速度令人瞠目。在应用方面,计算机从由少数科学家从事数学计算到今天遍及社会生活的各个领域,人们可以通过它对弈,也可以通过它预测天气。在技术方面,计算机硬件的发展是日新月异,例如中央处理器(CPU)的速度是每隔6个月翻一倍,而成本则是每隔6个月减少一倍。但在计算机软件方面,其发展却是差强人意,虽然也有很多新的软件开发方法和技术不断提出,但软件无论在生产率还是在质量方面总是达不到预期效果。

    计算机软件开发的问题一直是困扰软件企业的关键问题。随着时代的发展人们开始意识到这些企业的基本问题不在于新技术是否使用,而在于软件过程的管理问题。软件过程包括两个方面,其一是软件开发的管理过程(Software Management Process),其二则是软件开发的工程过程(Software Engineering Process)。软件企业的开发机构在形成一套完整而成熟的软件过程后,软件的开发才能够步入正轨,才能保证在约定的期限内以固定的成本生产出客户满意的产品。

    软件机构形成一套完整而成熟的软件过程不是一蹴而就的,它需要一个从无序到有序,从特殊到一般,从定性到定量,最后再从静态到动态的历程,或者说软件机构在形成成熟的软件过程之前必须经历一系列的成熟阶段(Maturity Level)。软件机构首先要判断自己属于哪一个成熟阶段,然后再根据自身的实际情况决定应该重点采取哪一些活动(Activity)来更有效地改进自己的软件过程。其他企业在同软件企业订立软件开发合同时也可以根据该企业机构所处的成熟阶段判断其软件开发能力,进而判断相关的软件风险。所有这些都需要一个理论指导来作出相关判断,能力成熟度模型(CMM)就是这样一个理论模型,它规定了机构成熟阶段的框架,以及如何据之判断软件机构所处的成熟阶段和机构为改进自己的软件过程应该采取的办法。

    CMM产生背景

    主要问题

    在过去的二十年里,新的软件开发方法和技术的使用并未使软件生产率和生产质量得到有效的提高。软件生产商开始意识到他们的基本问题在于对软件的生产过程管理不力,主要体现在:软件产品不能按时完成、超出预算的成本、以及采用新的技术和工具后其好处难以体现。

    主要作用

    CMM可以指导软件机构如何控制软件产品的开发和维护过程,以及如何向成熟的软件工程体系演化,并形成一套良性循环的管理文化。具体说来,一个企业要想改进其生产过程,应该采取如下策略和步骤:

    • 确定软件企业当前所处的过程成熟级别;
    • 了解对改进软件生产质量和加强生产过程控制起关键作用的因素;
    • 将工作重点集中在有限几个关键目标上,有效达到改进机构软件生产过程的效果,进而可持续地改进其软件生产能力。

    CMM的基本概念

    • 软件过程

    人们在开发和维护软件及其相关产品时所涉及的各种活动、方法、实践和改革等。其中软件相关产品包括软件项目计划、设计文档、程序代码、测试用例和用户手册等。

    • 软件过程能力

    当遵循某个软件过程时所能达到的期望效果,它可以有效预测企业接收新的软件项目时可能得到的结果。

    • 软件过程性能

    当遵循某个软件过程时所达到的实际效果。它可以用于验证软件过程能力。

    • 软件过程成熟度

    指一个特定的软件过程被显式定义、管理、度量、控制和能行的程度。成熟度可以用于指示企业加强其软件过程能力的潜力。 当一个企业达到了一定的软件过程成熟级别后,它将通过制定策略、建立标准和确立机构结构使它的软件过程制度化。而制度化又促使企业通过建立基础设施和公司文化来支持相关的方法、实践和过程。从而使之可以持续并维持一个良性循环。

    • 成熟与不成熟

    企业要通过选择最关键的目标来进行过程改进,应该搞清成熟的软件过程和不成熟的过程之间的差异。

    不成熟的企业有如下标志:

    • 缺乏确定的软件过程和相应的管理和控制;
    • 即使给出了软件过程,也不严格的遵循和强制执行;
    • 管理是完全被动的,管理者采用的策略是救火式的,即出了事才去解决,解决的时候也难以纵观全局,往往只顾眼前;
    • 由于缺乏有依据的估算,制订软件预算和生产计划时往往跟着感觉走,实际生产时则常常超标;
    • 如果强制在预定期限内完成,那么软件的功能和质量肯定是得不到保证;
    • 缺乏评价软件产品质量和解决产品缺陷和过程问题的客观基础。

    成熟的企业则有如下标志:

    • 具有在企业范围内管理、控制软件开发和维护过程的能力;
    • 现有人员和新进人员均了解所遵循的软件过程,且工作活动均按照事先的计划完成;
    • 在定义好的软件过程中,所有项目和机构中的角色和责任分明;
    • 制定的计划是有效的且与实际的工作进展一致;
    • 软件过程在必要时可按照一定规则和程序加以修改;
    • 软件产品和过程的具有一定的可控性。这主要体现在:
      1. 管理者能够监督软件产品的质量和生产过程;
      2. 具有客观的和定量化的措施来判断产品质量并分析产品与生产过程中的问题;
      3. 计划和预算有章可循,它是基于历史数据的,从而是实际可行的;
      4. 预算的结果,包括成本、时间表、产品功能和质量等,通常能够达到;
      5. 有关的参与者完全理解遵循软件过程的价值并认真地遵循之;
      6. 具有支撑软件过程的基础设施,如标准过程库、历史数据库等。

    CMM的五级成熟度

    基本前提

    • 软件质量在很大程度上取决于产生软件的软件过程的质量和能力;
    • 软件过程是一个可管理、可度量并不断改进的过程;
    • 软件过程的质量受到用以支撑它的技术和设施的影响;
    • 企业在软件过程中所采用的技术层次应适应于软件过程的成熟度。

    基本原理

    • CMM强调连续的软件过程改进。该连续的改进基于多个演化步骤。CMM将这些演化步骤划分成五个级别。这种分级结构的理论依据是软件质量原理。
    • 每一级别都包括若干目标。当满足某一目标后,软件过程的相应部分便确定下来。
    • 五级成熟度定义了一个标准,用以度量机构的软件过程成熟度和评价其软件过程能力。

    基本内容

    CMM的成熟度理论目前主要涉及如下内容:

    • 机构和资源的管理: 涉及机构本身的责任,人员和其它资源设施。
    • 软件工程过程及其管理: 涉及软件工程过程,即软件过程的深度、范围和完整性以及如何度量、管理和改进这样的过程。
    • 工具和技术: 软件工程过程中使用的开发工具和技术。

    五个成熟度级别

    • 初始级
    • 可重复级:有规章的过程
    • 定义级:标准化、一致的过程
    • 管理级:可预测过程
    • 优化级:可持续改进的过程

    成熟度的行为刻划

    第一级:初始级

    • 成功来源于个人英雄主义而非机构行为,因此它不可重复,更换人员后成功便难以维持。

    第二级:可重复级

    • 针对特定软件项目建立管理该项目的策略和实现这些策略的过程。
    • 新项目的计划和管理基于类似项目的经验。
    • 软件过程能力主要通过管理单个项目的软件生产过程来得到提高和增强。
    • 不同的项目可有不同的软件过程,机构应当建立一定的方针和策略以针对具体的项目选择合适的软件生产过程并进行管理。

    可重复级的主要特点在于确定了基本的软件生产管理和控制,具体来讲,有:

    • 结合已有项目的经验和新项目的特点来确定本项目的责任和承诺;
    • 软件生产成本、时间表和实现的功能被有效跟踪;
    • 识别实现承诺所需解决的关键问题;
    • 定义软件项目过程标准,机构要确保其被遵守。

    概括来说,第二级的主要特点是项目计划和跟踪是确定且有效的,项目的软件过程是可控的,以及已有的成功经验是可重复的。

    第三级:定义级

    • 有一个机构范围内标准的软件过程,软件工程活动和管理活动被集成为一个有机的整体。标准化的目的是使高层管理者和软件技术人员能够有效合作。
    • 有一个组例如软件工程组(SEPG)专门负责订立机构的标准软件过程,并且在机构中制定培训计划来确保相关人员和管理者有足够的知识和技能完成标准过程所赋予的角色。
    • 标准的软件过程结合具体项目的特点经过裁剪即形成项目定义软件过程,它是一组集成的完善定义的软件工程和管理过程。
    • 一个完善定义的软件过程应包括就绪准则、输入、工作过程、验证机制、输出和完成准则。
    • 对于已建立的产品生产线,其成本、时间表和实现功能均可跟踪和控制,软件产品的质量可以得到保证。
    • 软件过程能力的实现主要基于在机构范围内对一个定义软件过程的活动、角色和责任的共同理解。

    概括来说,第三级的主要特征在于软件过程已被提升成标准化过程,从而更加具有稳定性、重复性和可控性。

    第四级:管理级

    • 软件的过程和产品有定量的质量指标。
      • 重要的软件过程活动均配有生产率和质量方面的度量指标;
      • 应用数据库来收集和分析定义软件过程中涉及的各种数据;
      • 对项目软件过程和软件质量的评价有定量的基准。
    • 软件项目的产品和生产过程的控制具有可预测性。
      • 将软件过程性能可能出现的偏差控制在可接受的量化界限内;
      • 具体区分影响过程性能发生偏差的有效因素和偶然因素;
      • 向新领域拓展的风险是可预知的并被仔细管理和权衡。

    概括来说,第四级的主要特征是定量化、可预测、异常控制和高质量。

    第五级:优化级

    • 机构集中于持续的过程改进
      • 具有标识过程缺陷和增强过程能力的有效手段。
      • 利用试验数据分析使用新技术所需的代价和带来的效益,然后再有选择地采用。
      • 当出现偏差时,软件项目人员能够分析出错原因并采取有效手段防止其再次出现。
      • 防止不必要的浪费是第五级的重点。
    • 改进的途径有两个,一个是对已有过程的渐进式改进;另一个则是有选择地使用新技术和新方法所带来的革新。

    概括来说,第五级的主要特征是新技术的采用和软件过程的改进被作为日常的业务活动来加以计划和管理。

    posted @ 2008-01-08 19:17 灵! 阅读(129) | 评论 (0)编辑 收藏

    Eclicpse3.1.1下配置SWT,打包发布SWT程序,转EXE一条龙过程记录

    1.www.eclipse.org上下载SWT.

    我这里用的是1.1.0.1,并且页面上就有推荐的Eclipse3.1.1EMF,GEF。都下载了!

    2.按照Eclipse安装插件的方法,安装SWT,EMF,GEF

    3.如果不出意外,就可以正常使用了!

    这里有一个建议:最好使用纯的Eclipse,我开始用WTP版的,怎么配置也不行。

    可以建立Visual Class,但是不能可视化添加控件,或者看不到控件的属性,或者Text,TextArea控件无法添加。后来按照以上方法,重新来了一次,OK!

    二打包发布SWT程序

    1.因为需要SWTjar.但是Eclipse3.1.1配合的的SWT不是通过SWT.jar发布的!是org.eclipse.swt.win32.win32.x86_3.1.0.jar。里面包括了JINIDLLSWT类文件。

    需要下载

    http://www.eclipse.org/downloads/download.php?file=/eclipse/dow ... 09290840/swt-3.1.1-win32-win32-x86.zip

    这里有SWT.jar,和3DLL,把他们解压缩出来,备用!

    2.通过Eclipse的导出功能,生成一个可执行的jarMANIFEST.MF文件选择由Eclipse生成,并且保存到项目中。

    3.上面2的步骤,只是为了得到MANIFEST.MF文件。下面修改一下这个文件。

    加上 Class-Path: SWT.jar

    如果还有其他的jar,用空格分开,加到后面

    4.再生成一次jar,MANIFEST.MF选择修改后的。

    5.将打包的jar,SWT.jar,3DLL放到一个文件夹下,双击可执行的jar,程序运行!

    jarEXE

    1.打开JSmooth0.9.9-7http://www610.fixdown.com/jsmooth-0.9.9-7-setup.exe

    2.选择skeleton,skeleton properties中先把Launch java app in the exe process,Debug console选中。可以查看生成EXE文件执行过程信息。

    3.选择Executable.

    选择生成的EXE文件存放位置。

    选择EXE文件图标

    设置当前路径,选择要转换的jar文件所在文件夹

    4.选择Application

    设置Main Class,可执行jar中的Main Class注意写类全名

    设置Application Argument,如果需要传入参数,写到这里

    设置Embedded jar: 可执行的jar

    设置ClasspathSWT.jar 如果有其他的继续添加

    5.选择JVM Selection。默认吧。

    6.JVM Configuration:

    可以设置java properties,内存使用

    7.点齿轮。生成!看是否有错误。

    8.EXE执行需要的文件:EXE,3DLLSWT.jar

    把他们考到其他目录,一样可以执行!

    9.去掉skeleton properties中的Launch java app in the exe process,Debug console选项。

    重新生成。应该OK了!

    -----

    看了这个,终于完成了SWT程序打包,太爽了

    posted @ 2008-01-08 19:12 灵! 阅读(303) | 评论 (0)编辑 收藏

    Spring实现发送邮件功能(简易篇)

    1.Spring配制文件(bean.xml):

     1<?xml version="1.0" encoding="UTF-8"?>
     2<beans xmlns="http://www.springframework.org/schema/beans"
     3    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
     5
     6    <bean id="mailSender"
     7        class="org.springframework.mail.javamail.JavaMailSenderImpl">
     8        <property name="host">
     9            <!-- 公司的郵件服務器 -->
    10            <value>mail.xxx.com</value>
    11        </property>
    12    </bean>
    13    
    14</beans>

    2.测试类(SendMail.java):

     1import org.springframework.context.ConfigurableApplicationContext;
     2import org.springframework.context.support.ClassPathXmlApplicationContext;
     3import org.springframework.mail.MailSender;
     4import org.springframework.mail.SimpleMailMessage;
     5
     6public class SendMail {
     7
     8    public static void main(String[] args) {
     9        SimpleMailMessage message = new SimpleMailMessage();
    10
    11        message.setFrom("zzk@gmail.com");  //髮送者郵件地阯
    12        message.setTo("jakin@xxx.com");            //接收者郵件地阯
    13        message.setSubject("Test SendMail");    //郵件主題
    14        message.setText("Success");                //郵件內容
    15
    16        ConfigurableApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
    17        ((MailSender) applicationContext.getBean("mailSender")).send(message);
    18    }

    19}

    posted @ 2008-01-08 19:00 灵! 阅读(188) | 评论 (0)编辑 收藏

    Ant在eclipse中的build.xml的配置

    Ant在eclipse中的build.xml的配置
    <?xml version="1.0" ?>
    - <project name="webmodulebuilder" default="deploy" basedir=".">
    - <!--
    set global properties for this build
    -->
    - <!--
    发布WEB路径
    -->
    <property name="DEPLOY_PATH" value="C:\Tomcat 5.5\webapps\jieshengda" />
    - <!--
    源WEB路径
    -->
    <property name="WEB_PATH" value="D:\EclipseWork\jiedasheng\WebRoot" />
    - <!--
    源编译的jar包路径
    -->
    <property name="JAR_PATH" value="D:\EclipseWork\jiedasheng\WebRoot\WEB-INF\lib" />
    - <!--
    源java文件路径
    -->
    <property name="SCR_PATH" value="D:\EclipseWork\jiedasheng\src" />
    - <!--
    源class文件路径
    -->
    <property name="CLASS_PATH" value="D:\EclipseWork\jiedasheng\WebRoot\WEB-INF\classes" />
    - <!--
    定义classpath
    -->
    - <path id="LIB_CLASS_PATH">
    <fileset file="${JAR_PATH}/*.jar" />
    <pathelement path="${CLASS_PATH}" />
    </path>
    - <!--
    初试化
    -->
    - <target name="init">
    <mkdir dir="${DEPLOY_PATH}" />
    <mkdir dir="${DEPLOY_PATH}/WEB-INF" />
    <mkdir dir="${DEPLOY_PATH}/WEB-INF/classes" />
    <mkdir dir="${DEPLOY_PATH}/WEB-INF/lib" />
    </target>
    - <!--
    编译类
    -->
    - <target name="compile" depends="init" description="compile the source files">
    <mkdir dir="${CLASS_PATH}" />
    - <javac srcdir="${SCR_PATH}" destdir="${CLASS_PATH}">
    <classpath refid="LIB_CLASS_PATH" />
    </javac>
    </target>
    - <!--
    Copy发布
    -->
    - <target name="deploy" depends="init,compile">
    - <copy todir="${DEPLOY_PATH}">
    - <fileset dir="${WEB_PATH}">
    <include name="**/*.*" />
    <exclude name="**/jsp_servlet/*.class" />
    <exclude name="**/build.xml" />
    <exclude name="**/deploy.xml" />
    <exclude name="**/build.properties" />
    <exclude name="**/servers.xml" />
    <exclude name="**/targets.xml" />
    <exclude name="**/*.war" />
    </fileset>
    </copy>
    </target>
    </project>

    posted @ 2008-01-08 18:46 灵! 阅读(2230) | 评论 (0)编辑 收藏

    JAVA ant build.xml

    内容摘要:
    ANT是一个基于Java的自动化脚本引擎,脚本格式为XML。除了做Java编译相关任务外,ANT还可以通过插件实现很多应用的调用。
    1)ANT的基本概念:
    2)ANT的安装:解包,设置路径
    3)ANT的使用:最好的学习只不过是一个简单实用的例子起步……

    ANT的基本概念:Java的Makefile

    当一个代码项目大了以后,每次重新编译,打包,测试等都会变得非常复杂而且重复,因此c语言中有make脚本来帮助这些工作的批量完成。在Java中应用是平台无关性的,当然不会用平台相关的make脚本来完成这些批处理任务了,ANT本身就是这样一个流程脚本引擎,用于自动化调用程序完成项目的编译,打包,测试等。除了基于JAVA是平台无关的外,脚本的格式是基于XML的,比make脚本来说还要好维护一些。

    每个ant脚本(缺省叫build.xml)中设置了一系列任务(target):比如对于一个一般的项目可能需要有以下任务。

    任务1:usage 打印本脚本的帮助信息(缺省)
    任务2:clean <-- init 清空初始化环境
    任务3:javadoc <-- build <-- init 生成JAVADOC
    任务4:jar <-- build <-- init 生成JAR
    任务5:all <-- jar + javadoc <-- build <-- init 完成以上所有任务:jar javadoc

    而多个任务之间往往又包含了一定了依赖关系:比如把整个应用打包任务(jar)的这个依赖于编译任务(build),而编译任务又依赖于整个环境初始化任务(init)等。

    注:我看到很多项目的ant脚本中的命名基本上都是一致的,比如:编译一般叫build或者compile;打包一般叫jar或war;生成文档一般命名为javadoc或javadocs;执行全部任务all。在每个任务的中,ANT会根据配置调用一些外部应用并配以相应参数执行。虽然ANT可调用的外部应用种类非常丰富,但其实最常用的就2,3个:比如javac javadoc jar等。

    ANT的安装

    解包后在系统可执行路径中加入指向ant的bin的路径就可以了,比如可以在GNU/Linux上把以下配置加入/etc/profile中:
    export ANT_HOME=/home/ant
    export JAVA_HOME=/usr/java/j2sdk1.4.1
    export PATH=$PATH:$JAVA_HOME/bin:$ANT_HOME/bin

    这样执行ant 后,如果不指定配置文件ant会缺省找build.xml这个配置文件,并根据配置文件执行任务,缺省的任务设置可以指向最常用的任务,比如:build,或指向打印帮助信息:usage,告诉用户有那些脚本选项可以使用。

    ANT的使用

    最好的学习过程就是看懂那些open source项目中的build.xml脚本,然后根据自己的需要简化成一个更简单的,ANT和APACHE上很多非常工程派的项目:简单易用,而且适应性非常强,因为这些项目的建立往往来源于开发人员日常最直接的需求。
    参考资料:http://www.javafan.net/article/20041207142012728.html

    posted @ 2008-01-08 18:44 灵! 阅读(921) | 评论 (0)编辑 收藏

    一个简单的Ant的build.xml示例(附:jar包的正确运行方法)

         以前在写作业时曾经尝试用过Ant去编译和运行Java程序,不过后来好久没用,都不怎么会用了。下边是前几天写的一个build.xml文件的例子,以后可以拿来当参照了,不过有点小问题还不知道怎么改!以前忘了Jar包的正确运行方式,导致不能正确运行打包以后的jar包,现已更正!

          说明:lib目录存放第三方类库,src目录存放待编译的Java源文件!

    <?xml version="1.0" encoding="GB2312" ?>

    <!DOCTYPE project>

    <project name="JavaMailClient" default="usage" basedir=".">
          <property name="project-name" value="JavaMailClient"/>

          <property name="build" value="build"/>
          <property name="lib" value="lib"/>
          <property name="src" value="src"/>
          <property name="build.classes"      value="${build}/classes" />
          <property file="build.properties"/>
     

          <property name="jar.dir"     value="jar"/>
          <property name="jar-file-name"      value="${project-name}" />

          <path id="Third-Part Lib">
                <fileset dir="${lib}">
                      <include name="**/*.jar" />
                </fileset>
          </path>
     
          <target name="usage" description="Build file usage info (default task)">
                <echo message=" " />
                <echo message="${project-name} " />
                <echo message="-------------------------------------------------------" />
                <echo message="Available Targets:" />
                <echo message=" ***" />
                <echo message=" Compiling:" />
                <echo message="  compile  - Compiles the source code" />
                <echo message=" ***" />
                <echo message=" Cleaning up:" />
                <echo message="  clean - Delete class files" />
                <echo message=" ***" />
                <echo message=" JAR:" />
                <echo message="  jar  - Generate an .jar for source code" />
                <echo message=" ***" />
                <echo message=" Executing:" />
                <echo message="  run  - Execute the  JavaMail client ! Get email of the latest two days  from server" />
                <echo message=" ***" />
                <echo message="-------------------------------------------------------" />
          </target>

          <target name="prepare" >
                <mkdir dir="${build.classes}" />
                <mkdir dir="${jar.dir}" />
          </target>

          <target name="clean" >
                <delete dir="${build}" />
                <delete dir="${jar.dir}" />
          </target>
     
          <target name="compile" depends="clean,prepare">
          <echo message="Compiling the source code!"/>
                <javac
                      srcdir="${src}"
                      destdir="${build.classes}"
                      deprecation="true"
                      failonerror="true" debug="true"
                      >
                      <classpath refid="Third-Part Lib"/> 
                </javac>
          </target>


          <!-- <target name="run" description="Receive email! "  depends="compile"> -->
          <!-- 已经可以正确运行!注意:classpath="${build.classes}" 一定要加上,否则会报"java.lang.NoClassDefFoundError"的错误!-->
          <!--
          <target name="run" description="Receive email! ">
                <java classname="POP3MailReceiver" classpath="${build.classes}" fork="true" maxmemory="256m">
                      <classpath refid="Third-Part Lib"/> 
                </java>
          </target>
          -->

          
          <target name="run"  description="Receive email! ">
                <java jar="${jar.dir}/${jar-file-name}.jar" fork="true" maxmemory="256m"/>
          </target>

          <target name="jar" depends="compile">
                <jar destfile="${jar.dir}/${jar-file-name}.jar" basedir="${build.classes}">
                      <manifest>
                            <!-- 此处需要根据需要进行修改 -->
                            <attribute name="Main-Class" value="POP3MailReceiver"/>
                            <attribute name="Class-Path" value="../${lib}/commons-email-1.0.jar ../${lib}/mail.jar ../${lib}/activation.jar"/>
                      </manifest>
                </jar>
          </target>
    </project>


    附:Jar包的正确运行方法(转)

    -jar参数运行应用时classpath的设置方法 

           你是否在使用java -jar参数运行打包好的jar应用程序的时候发现应用程序无法找到classpath下设置好的第三方类库的内容?无论怎么设置classpath参数都无济于事,总是会报ClassNotFound的错误?那么本篇帖子可以帮助你摆脱烦恼 :)
          当用java -jar yourJarExe.jar来运行一个经过打包的应用程序的时候,你会发现如何设置-classpath参数应用程序都找不到相应的第三方类,报ClassNotFound错误。实际上这是由于当使用-jar参数运行的时候,java VM会屏蔽所有的外部classpath,而只以本身yourJarExe.jar的内部class作为类的寻找范围。

    解决方案

    一 BootStrap class扩展方案
          Java 命令行提供了如何扩展bootStrap 级别class的简单方法:
                -Xbootclasspath:     完全取代基本核心的Java class 搜索路径.
                                       不常用,否则要重新写所有Java 核心class
                -Xbootclasspath/a: 后缀在核心class搜索路径后面.常用!!
                -Xbootclasspath/p: 前缀在核心class搜索路径前面.不常用,避免
                                       引起不必要的冲突.
    语法如下:
     (分隔符与classpath参数类似,unix使用:号,windows使用;号,这里以unix为例)
     java -Xbootclasspath/a:/usrhome/thirdlib.jar: -jar yourJarExe.jar

    二 extend class 扩展方案
          Java exten class 存放在{Java_home}\jre\lib\ext目录下.当调用Java时,对扩展class路径的搜索是自动的.总会搜索的.这样,解决的方案就很简单了,将所有要使用的第三方的jar包都复制到ext 目录下.
          (自评:不推荐使用,自适应性很差!)

    三 User class扩展方案
         
    当使用-jar执行可执行Jar包时,JVM将Jar包所在目录设置为codebase目录,所有的class搜索都在这个目录下开始.所以如果使用了其他第三方的jar包,一个比较可以接受的可配置方案,就是利用jar包的Manifest扩展机制.
    步骤如下:
    1.将需要的第三方的jar包,复制在同可执行jar所在的目录或某个子目录下. 比如:jar 包在 /usrhome/yourJarExe.jar 那么你可以把所有jar包复制到/usrhome目录下或/usrhome/lib 等类似的子目录下.
    2.修改Manifest 文件
     在Manifest.mf文件里加入如下行
     Class-Path:classes12.jar lib/thirdlib.jar
     Class-Path 是可执行jar包运行依赖的关键词.详细内容可以参考:http://java.sun.com/docs/books/tutorial/ext/index.html


          以上三种方法推荐第一种,扩展性好,操作起来也最方便.
          另外编写自己的ClassLoader,来动态载入class,是更加复杂和高级技术.限于篇幅,不赘述.有兴趣了解可以去google一下custom classloader

          Java的安全机制随不同的JDK版本有不同的变化,会影响很多核心CLASS,比如Thread,所以很多大型商业软件,要求JDK的版本很严格.部分原因也在此.这也要求在发布自己编写的应用时候,不管大小,都要说明开发和测试的JDK版本.


    本文所述方法测试基于j2sdk 1.4.2_04-b05

    ----------------------------------------------------------------------------------------------

    附:背景知识

          自JDK 1.2以后,JVM采用了委托(delegate)模式来载入class.采用这种设计的原因可以参考http://java.sun.com/docs/books/tutorial/ext/basics/load.html

          归纳来讲:是基于JVM sandbox(沙盒)安装模型上提供应用层的可定制的安全机制.

          Java虚拟机(JVM)寻找Class的顺序

    1. Bootstrap classes

    属于Java 平台核心的class,比如java.lang.String等.及rt.jar等重要的核心级别的class.这是由JVM Bootstrap class loader来载入的.一般是放置在{java_home}\jre\lib目录下

    2. Extension classes

    基于Java扩展机制,用来扩展Java核心功能模块.比如Java串口通讯模块comm.jar.一般放置在{Java_home}\jre\lib\ext目录下

    3. User classes

    开发人员或其他第三方开发的Java程序包.通过命令行的-classpath或-cp,或者通过设置CLASSPATH环境变量来引用.JVM通过放置在{java_home}\lib\tools.jar来寻找和调用用户级的class.常用的javac也是通过调用tools.jar来寻找用户指定的路径来编译Java源程序.这样就引出了User class路径搜索的顺序或优先级别的问题.

     3.1 缺省值:调用Java或javawa的当前路径(.),是开发的class所存在的当前目录
     3.2 CLASSPATH环境变量设置的路径.如果设置了CLASSPATH,则CLASSPATH的值会覆盖缺省值
     3.3 执行Java的命令行-classpath或-cp的值,如果制定了这两个命令行参数之一,它的值会覆盖环境变量CLASSPATH的值
     3.4 -jar 选项:如果通过java -jar 来运行一个可执行的jar包,这当前jar包会覆盖上面所有的值.换句话说,-jar 后面所跟的jar包的优先级别最高,如果指定了-jar选项,所有环境变量和命令行制定的搜索路径都将被忽略.JVM APPClassloader将只会以jar包为搜索范围.
    有关可执行jar有许多相关的安全方面的描述,可以参考http://java.sun.com/docs/books/tutorial/jar/ 来全面了解.

    这也是为什么应用程序打包成可执行的jar包后,不管你怎么设置classpath都不能引用到第三方jar包的东西了.
     

    posted @ 2008-01-08 18:43 灵! 阅读(4942) | 评论 (1)编辑 收藏

    Java反射机制学习笔记

    一. 反射机制描述
          Java的反射机制允许程序在运行时透过反射API取得任何一个已知名称的class的内部信息,主要包括属性名,属性名的修饰符,方法名,方法返回值,方法修饰符等信息。

    二. Java类反射中的主要方法
         Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数,

         Constructor[] getConstructors() -- 获得类的所有公共构造函数

         Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关)

         Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关) 

         获得字段信息的Class 反射调用不同于那些用于接入构造函数的调用,在参数类型数组中使用了字段名:

         Field getField(String name) -- 获得命名的公共字段

         Field[] getFields() -- 获得类的所有公共字段

         Field getDeclaredField(String name) -- 获得类声明的命名的字段

         Field[] getDeclaredFields() -- 获得类声明的所有字段 

         用于获得方法信息函数:

         Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法

         Method[] getMethods() -- 获得类的所有公共方法

         Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法

         Method[] getDeclaredMethods() -- 获得类声明的所有方法 

    三. Java反射机制应用初探
       
         现在一堆框架搞得人云里雾里的,例如spring等等,大都利用了Java的反射机制,eg. 大名鼎鼎的IOC.昨天晚上闲着没事的时候,初试了下反射,下面是一个简单的测试例子:
       

    import java.awt.Button;
    import java.lang.reflect.Method;
    import java.util.Hashtable;

    /**
     * 测试Java的反射机制
     * 
    @author Amigo Xie(xiexingxing1121@126.com)
     * 
    @since 2007/04/20 21:40
     
    */

    public class ReflectionTest {

        
    /**
         * 
    @param args
         
    */

        
    public static void main(String[] args) throws Exception {
            ReflectionTest reflection 
    = new ReflectionTest();
            reflection.getNameTest();
            System.out.println(
    "");
            reflection.getMethodTest();
        }

        
        
    /**
         * Class的getName()