Rising Sun

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  148 随笔 :: 0 文章 :: 22 评论 :: 0 Trackbacks

#

filter的用法,的确是比较有扩展性的一种方法...可以通过filter结合读取web.xml中的filter参数来完成一系列的动作,做法如下:

首先,实现javax.servlet.Filter接口,编写一个处理request编码的过滤器类...

package tutorial.struts.filter;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.FilterChain;
import java.io.IOException;
public class SetCharacterEncodingFilter implements Filter {
  protected FilterConfig filterConfig;
  protected String encodingName;
  protected boolean enable;
  public SetCharacterEncodingFilter() {
    this.encodingName = "UTF-8";
    this.enable = false;
  }
  public void init(FilterConfig filterConfig) throws ServletException {
    this.filterConfig = filterConfig;
    loadConfigParams();
  }
  private void loadConfigParams()
 {
    //encoding
    this.encodingName = this.filterConfig.getInitParameter("encoding");
    //filter enable flag...
    String strIgnoreFlag = this.filterConfig.getInitParameter("enable");
    if (strIgnoreFlag.equalsIgnoreCase("true"))
 {
      this.enable = true;
    }
 else
 {
      this.enable = false;
    }
  }
  public void doFilter(ServletRequest request, ServletResponse response,
                       FilterChain chain) throws IOException, ServletException
 {
    if(this.enable) 
{
      request.setCharacterEncoding(this.encodingName);
    }
    chain.doFilter(request, response);
  }
  public void destroy()
 {
  }
}
 

然后,需要在web.xml中注册我们的过滤器类:

  <filter>
    <filter-name>Set Character Encoding</filter-name>
    <filter-class>tutorial.struts.filter.SetCharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>enable</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>Set Character Encoding</filter-name>
    <servlet-name>Action Servlet</servlet-name>
  </filter-mapping>
  <filter-mapping>
    <filter-name>Set Character Encoding</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
  </filter-mapping>
 

这样,任何通过Struts,或是JSF的Controller Servlet处理的request,都会在过滤器中先行处理,才把控制权交还给Struts或是JSF,而且Filter中有一个Process Chain的概念,是一个很吸引人的东东~~!
posted @ 2006-07-27 15:14 brock 阅读(365) | 评论 (0)编辑 收藏

 1 package cn.com.jsp;
 2
 3 import java.io.IOException;
 4 import javax.servlet.Filter;
 5 import javax.servlet.FilterChain;
 6 import javax.servlet.FilterConfig;
 7 import javax.servlet.ServletException;
 8 import javax.servlet.ServletRequest;
 9 import javax.servlet.ServletResponse;
10 import javax.servlet.UnavailableException;
11
12 public   class  SetCharacterEncodingFilter implements Filter  {
13      protected  String encoding  =   null ;
14      protected  FilterConfig filterConfig  =   null ;
15      protected  boolean ignore  =   true ;
16
17      public   void  destroy()  {
18          this .encoding  =   null ;
19          this .filterConfig  =   null ;
20     }

21
22      public   void  doFilter(ServletRequest request, ServletResponse response,
23                          FilterChain chain) throws IOException,
24             ServletException  {
25
26          //  Conditionally select and set the character encoding to be used
27          if  (ignore  ||  (request.getCharacterEncoding()  ==   null ))  {
28             String encoding  =  selectEncoding(request);
29              if  (encoding  !=   null {
30                 request.setCharacterEncoding(encoding);
31             }

32         }

33
34          //  Pass control on to the next filter
35         chain.doFilter(request, response);
36
37     }

38
39      public   void  init(FilterConfig filterConfig) throws ServletException  {
40
41          this .filterConfig  =  filterConfig;
42          this .encoding  =  filterConfig.getInitParameter( " encoding " );
43         String value  =  filterConfig.getInitParameter( " ignore " );
44          if  (value  ==   null {
45              this .ignore  =   true ;
46         }
  else   if  (value.equalsIgnoreCase( " true " ))  {
47              this .ignore  =   true ;
48         }
  else   if  (value.equalsIgnoreCase( " yes " ))  {
49              this .ignore  =   true ;
50         }
  else   {
51              this .ignore  =   false ;
52         }

53
54     }

55
56      protected  String selectEncoding(ServletRequest request)  {
57          return  ( this .encoding);
58     }

59
60 }


相应的web.xml文件里的配置如下:

 1<web-app>
 2  <display-name>wwwrootSPAN style="COLOR: #800000">display-name>
 3  <description>MySQL Test AppSPAN style="COLOR: #800000">description>
 4  <filter>
 5    <filter-name>setCharacterEncodingFilterSPAN style="COLOR: #800000">filter-name>
 6    <display-name>setCharacterEncodingFilterSPAN style="COLOR: #800000">display-name>
 7    <description>setCharacterEncodingFilterSPAN style="COLOR: #800000">description>
 8    <filter-class>cn.com.jsp.SetCharacterEncodingFilterSPAN style="COLOR: #800000">filter-class>
 9    <init-param>
10      <param-name>encodingSPAN style="COLOR: #800000">param-name>
11      <param-value>GBKSPAN style="COLOR: #800000">param-value>
12    SPAN style="COLOR: #800000">init-param>
13  SPAN style="COLOR: #800000">filter>
14  <filter-mapping>
15    <filter-name>setCharacterEncodingFilterSPAN style="COLOR: #800000">filter-name>
16    <url-pattern>/*SPAN style="COLOR: #800000">url-pattern>
17  SPAN style="COLOR: #800000">filter-mapping>
18……
19SPAN style="COLOR: #800000">web-app>

上面的代码我也没更改什么,看了后,了解了其中的些许流程。放入blog,留以备学吧
posted @ 2006-07-27 15:11 brock 阅读(368) | 评论 (0)编辑 收藏

     摘要: 将此页作为电子邮件发送'); //-->    未显示需要 JavaScript 的文档选项 ...  阅读全文
posted @ 2006-07-27 13:33 brock 阅读(173) | 评论 (0)编辑 收藏

JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。

一、JDOM 简介

JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。

JDOM 直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念以及映射),把SAX和DOM的功能有效地结合起来。

在使用设计上尽可能地隐藏原来使用XML过程中的复杂性。利用JDOM处理XML文档将是一件轻松、简单的事。

JDOM 在2000年的春天被Brett McLaughlin和Jason Hunter开发出来,以弥补DOM及SAX在实际应用当中的不足之处。

这些不足之处主要在于SAX没有文档修改、随机访问以及输出的功能,而对于DOM来说,JAVA程序员在使用时来用起来总觉得不太方便。

DOM的缺点主要是来自于由于Dom是一个接口定义语言(IDL),它的任务是在不同语言实现中的一个最低的通用标准,并不是为JAVA特别设计的。JDOM的最新版本为JDOM Beta
 9。最近JDOM被收录到JSR-102内,这标志着JDOM成为了JAVA平台组成的一部分。

二、JDOM 包概览

JDOM是由以下几个包组成的
org.jdom                包含了所有的xml文档要素的java类

 

org.jdom.adapters         包含了与dom适配的java类

 

org.jdom.filter            包含了xml文档的过滤器类

 

org.jdom.input            包含了读取xml文档的类

 

org.jdom.output           包含了写入xml文档的类

 

org.jdom.transform        包含了将jdom xml文档接口转换为其他xml文档接口

 

org.jdom.xpath            包含了对xml文档xpath操作的类三、JDOM 类说明

1、org.JDOM这个包里的类是你J解析xml文件后所要用到的所有数据类型。

Attribute

CDATA

Coment

DocType

Document

Element

EntityRef

Namespace

ProscessingInstruction

Text

2、org.JDOM.transform在涉及xslt格式转换时应使用下面的2个类

JDOMSource

JDOMResult

org.JDOM.input

3、输入类,一般用于文档的创建工作

SAXBuilder

DOMBuilder

ResultSetBuilder

org.JDOM.output

4、输出类,用于文档转换输出

XMLOutputter

SAXOutputter

DomOutputter

JTreeOutputter

使用前注意事项:

1.JDOM对于JAXP 以及 TRax 的支持

JDOM 支持JAXP1.1:你可以在程序中使用任何的parser工具类,默认情况下是JAXP的parser。

制定特别的parser可用如下形式

SAXBuilder parser

  = new SAXBuilder("org.apache.crimson.parser.XMLReaderImpl");

 Document doc = parser.build("http://www.cafeconleche.org/");

 // work with the document...

JDOM也支持TRaX:XSLT可通过JDOMSource以及JDOMResult类来转换(参见以后章节)

2.注意在JDOM里文档(Document)类由org.JDOM.Document 来表示。这要与org.w3c.dom中的Document区别开,这2种格式如何转换在后面会说明。

以下如无特指均指JDOM里的Document。

四、JDOM主要使用方法

1.Ducument类

(1)Document的操作方法:

Element root = new Element("GREETING");

Document doc = new Document(root);

root.setText("Hello JDOM!");

或者简单的使用Document doc = new Document(new Element("GREETING").setText("Hello JDOM!t"));

这点和DOM不同。Dom则需要更为复杂的代码,如下:

DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();

DocumentBuilder builder =factory.newDocumentBuilder();

Document doc = builder.newDocument();

Element root =doc.createElement("root");

Text text = doc.createText("This is the root");

root.appendChild(text);

doc.appendChild(root);

注意事项:JDOM不允许同一个节点同时被2个或多个文档相关联,要在第2个文档中使用原来老文档中的节点的话。首先需要使用detach()把这个节点分开来。

(2)从文件、流、系统ID、URL得到Document对象:

DOMBuilder builder = new DOMBuilder();

Document doc = builder.build(new File("jdom_test.xml"));

SAXBuilder builder = new SAXBuilder();

Document doc = builder.build(url);

在新版本中DOMBuilder 已经Deprecated掉 DOMBuilder.builder(url),用SAX效率会比较快。

这里举一个小例子,为了简单起见,使用String对象直接作为xml数据源:

 public jdomTest() {

    String textXml = null;

    textXml = "<note>";

    textXml = textXml +

        "<to>aaa</to><from>bbb</from><heading>ccc</heading><body>ddd</body>";

    textXml = textXml + "</note>";

    SAXBuilder builder = new SAXBuilder();

    Document doc = null;

    Reader in= new StringReader(textXml);

    try {

      doc = builder.build(in);

      Element root = doc.getRootElement();

      List ls = root.getChildren();//注意此处取出的是root节点下面的一层的Element集合

      for (Iterator iter = ls.iterator(); iter.hasNext(); ) {
 /*for(int i=0;i<ls.size; i++)
 Element el = (Element) list.get(i);
 */
        Element el = (Element) iter.next();

        if(el.getName().equals("to")){

         System.out.println(el.getText());

        }

      }

    }

    catch (IOException ex) {

      ex.printStackTrace();

    }

    catch (JDOMException ex) {

      ex.printStackTrace();

    }

  }

(3)DOM的document和JDOM的Document之间的相互转换使用方法,简单!

DOMBuilder builder = new DOMBuilder();

org.jdom.Document jdomDocument = builder.build(domDocument);

DOMOutputter converter = new DOMOutputter();// work with the JDOM document…

org.w3c.dom.Document domDocument = converter.output(jdomDocument);

// work with the DOM document…

2.XML文档输出

XMLOutPutter类:

JDOM的输出非常灵活,支持很多种io格式以及风格的输出

Document doc = new Document(...);

XMLOutputter outp = new XMLOutputter();

outp.output(doc, fileOutputStream); // Raw output

outp.setTextTrim(true); // Compressed output

outp.output(doc, socket.getOutputStream());

outp.setIndent(" ");// Pretty output

outp.setNewlines(true);

outp.output(doc, System.out);

详细请参阅最新的JDOM API手册

3.Element 类:

(1)浏览Element树

Element root = doc.getRootElement();//获得根元素element

List allChildren = root.getChildren();// 获得所有子元素的一个list

List namedChildren = root.getChildren("name");// 获得指定名称子元素的list

Element child = root.getChild("name");//获得指定名称的第一个子元素

JDOM给了我们很多很灵活的使用方法来管理子元素(这里的List是java.util.List)

List allChildren = root.getChildren();

allChildren.remove(3); // 删除第四个子元素

allChildren.removeAll(root.getChildren("jack"));// 删除叫“jack”的子元素

root.removeChildren("jack"); // 便捷写法

allChildren.add(new Element("jane"));// 加入

root.addContent(new Element("jane")); // 便捷写法

allChildren.add(0, new Element("first"));

(2)移动Elements:

在JDOM里很简单

Element movable = new Element("movable");

parent1.addContent(movable); // place

parent1.removeContent(movable); // remove

parent2.addContent(movable); // add

在Dom里

Element movable = doc1.createElement("movable");

parent1.appendChild(movable); // place

parent1.removeChild(movable); // remove

parent2.appendChild(movable); // 出错!

补充:纠错性

JDOM的Element构造函数(以及它的其他函数)会检查element是否合法。

而它的add/remove方法会检查树结构,检查内容如下:

1.在任何树中是否有回环节点

2.是否只有一个根节点

3.是否有一致的命名空间(Namespaces)

(3)Element的text内容读取

<description>

A cool demo

</description>

// The text is directly available

// Returns "\n A cool demo\n"

String desc = element.getText();

// There's a convenient shortcut

// Returns "A cool demo"

String desc = element.getTextTrim();

(4)Elment内容修改

element.setText("A new description");

3.可正确解释特殊字符

element.setText("<xml> content");

4.CDATA的数据写入、读出

element.addContent(new CDATA("<xml> content"));

String noDifference = element.getText();

混合内容

element可能包含很多种内容,比如说

<table>

<!-- Some comment -->

Some text

<tr>Some child element</tr>

</table>

取table的子元素tr

String text = table.getTextTrim();

Element tr = table.getChild("tr");

也可使用另外一个比较简单的方法

List mixedCo = table.getContent();

Iterator itr = mixedCo.iterator();

while (itr.hasNext()) {

Object o = i.next();

if (o instanceof Comment) {...}

// 这里可以写成Comment, Element, Text, CDATA,ProcessingInstruction, 或者是EntityRef的类型

}

// 现在移除Comment,注意这里游标应为1。这是由于回车键也被解析成Text类的缘故,所以Comment项应为1。

mixedCo.remove(1);

4.Attribute类

<table width="100%" border="0"> </table>

String width = table.getAttributeValue("width");//获得attribute

int border = table.getAttribute("width").getIntValue();

table.setAttribute("vspace", "0");//设置attribute

table.removeAttribute("vspace");// 删除一个或全部attribute

table.getAttributes().clear();

5.处理指令(Processing Instructions)操作

一个Pls的例子

<?br?>

<?cocoon-process type="xslt"?>

          |        |

          |        |

        目标     数据

处理目标名称(Target)

String target = pi.getTarget();

获得所有数据(data),在目标(target)以后的所有数据都会被返回。

String data = pi.getData();

String type = pi.getValue("type");获得指定属性的数据

List ls = pi.getNames();获得所有属性的名称

6.命名空间操作

<xhtml:html

 xmlns:xhtml="http://www.w3.org/1999/xhtml">

<xhtml:title>Home Page</xhtml:title>

</xhtml:html>

Namespace xhtml = Namespace.getNamespace("xhtml", "http://www.w3.org/1999/xhtml");

List kids = html.getChildren("title", xhtml);

Element kid = html.getChild("title", xhtml);

kid.addContent(new Element("table", xhtml));

7.XSLT格式转换

使用以下函数可对XSLT转换

最后如果你需要使用w3c的Document则需要转换一下。

public static Document transform(String stylesheet,Document in)

                                        throws JDOMException {

     try {

       Transformer transformer = TransformerFactory.newInstance()

                             .newTransformer(new StreamSource(stylesheet));

       JDOMResult out = new JDOMResult();

       transformer.transform(new JDOMSource(in), out);

       return out.getDeocument();

     }

     catch (TransformerException e) {

       throw new JDOMException("XSLT Trandformation failed", e);

     }

   }

五、用例:

1、生成xml文档:

 

 

public class WriteXML{

    public void BuildXML() throws Exception {

        Element root,student,number,name,age;        

        root = new Element("student-info"); //生成根元素:student-info

        student = new Element("student"); //生成元素:student(number,name,age)                            

        number = new Element("number");

        name = new Element("name");

        age = new Element("age");

        Document doc = new Document(root); //将根元素植入文档doc中

        number.setText("001");

        name.setText("lnman");

        age.setText("24");

        student.addContent(number);

        student.addContent(name);

        student.addContent(age);

        root.addContent(student);

        Format format = Format.getCompactFormat();

        format.setEncoding("gb2312"); //设置xml文件的字符为gb2312

        format.setIndent("    "); //设置xml文件的缩进为4个空格

        XMLOutputter XMLOut = new XMLOutputter(format);//元素后换行一层元素缩四格

        XMLOut.output(doc, new FileOutputStream("studentinfo.xml")); 

}

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

        WriteXML w = new WriteXML();

        System.out.println("Now we build an XML document .....");

        w.BuildXML();

        System.out.println("finished!");

}

}

生成的xml文档为:

<?xml version="1.0" encoding="gb2312"?>

<student-info>

    <student>

        <number>001</number>

        <name>lnman</name>

        <age>24</age>

    </student>

</student-info>

 

 

创建XML文档2:

 public class CreateXML {

  public void Create() {

   try {

    Document doc = new Document();  

    ProcessingInstruction pi=new ProcessingInstruction("xml-stylesheet","type="text/xsl" href="test.xsl"");

    doc.addContent(pi);   

    Namespace ns = Namespace.getNamespace("http://www.bromon.org" );

    Namespace ns2 = Namespace.getNamespace("other", "http://www.w3c.org" );

    Element root = new Element("根元素", ns);

    root.addNamespaceDeclaration(ns2);

    doc.setRootElement(root);

    Element el1 = new Element("元素一");

    el1.setAttribute("属性", "属性一");   

    Text text1=new Text("元素值");

             Element em = new Element("元素二").addContent("第二个元素");

    el1.addContent(text1);

             el1.addContent(em);            

             Element el2 = new Element("元素三").addContent("第三个元素");

             root.addContent(el1);

             root.addContent(el2);            

             //缩进四个空格,自动换行,gb2312编码

             XMLOutputter outputter = new XMLOutputter("  ", true,"GB2312");

             outputter.output(doc, new FileWriter("test.xml"));

         }catch(Exception e)  {

          System.out.println(e);

         }

     }    

     public static void main(String args[]) {

      new CreateXML().Create();

     }    

 }

2、读取xml文档的例子:

import org.jdom.output.*;

import org.jdom.input.*;

import org.jdom.*;

import java.io.*;

import java.util.*;

public class ReadXML{

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

        SAXBuilder builder = new SAXBuilder();

        Document read_doc = builder.build("studentinfo.xml");

        Element stu = read_doc.getRootElement();

        List list = stu.getChildren("student");

        for(int i = 0;i < list.size();i++) {

            Element e = (Element)list.get(i);

            String str_number = e.getChildText("number");

            String str_name = e.getChildText("name");

            String str_age = e.getChildText("age");

            System.out.println("---------STUDENT--------------");

            System.out.println("NUMBER:" + str_number);

            System.out.println("NAME:" + str_name);

            System.out.println("AGE:" + str_age);

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

            System.out.println();

        } 

       }

}

3、DTD验证的:

 public class XMLWithDTD {

  public void validate()  {

   try {

    SAXBuilder builder = new SAXBuilder(true);

    builder.setFeature("http://xml.org/sax/features/validation";,true);

    Document doc = builder.build(new FileReader("author.xml"));   

    System.out.println("搞掂");

    XMLOutputter outputter = new XMLOutputter();

    outputter.output(doc, System.out);

   }catch(Exception e) {

    System.out.println(e);

   }  

  }

  public static void main(String args[]) {

   new XMLWithDTD().validate();

  } 

 }

   需要说明的是,这个程序没有指明使用哪个DTD文件。DTD文件的位置是在XML中指定的,而且DTD不支持命名空间,一个XML只能引用一个DTD,所以程序直接读取XML中指定的DTD,程序本身不用指定。不过这样一来,好象就只能使用外部式的DTD引用方式了?高人指点。

 

 

4、XML Schema验证的:

 public class XMLWithSchema {

  String xml="test.xml";

  String schema="test-schema.xml";

  public void validate() {

   try {

    SAXBuilder builder = new SAXBuilder(true);

    //指定约束方式为XML schema

    builder.setFeature("http://apache.org/xml/features/validation/schema";,  true);

    //导入schema文件

builder.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation";,schema);

    Document doc = builder.build(new FileReader(xml));   

    System.out.println("搞掂");

    XMLOutputter outputter = new XMLOutputter();

    outputter.output(doc, System.out);

   }catch(Exception e) {

    System.out.println("验证失败:"+e);

   } 

  }

 }

 上面的程序就指出了要引入的XML Schema文件的位置。

 

 

 系统默认输出是UTF-8,这有可能导致出现乱码。

5、Xpath例子:

JDOM的关于XPATH的api在org.jdom.xpath这个包里。这个包下,有一个抽象类XPath.java和实现类JaxenXPath.java,
使用时先用XPath类的静态方法newInstance(String xpath)得到XPath对象,
然后调用它的selectNodes(Object context)方法或selectSingleNode(Object context)方法,
前者根据xpath语句返回一组节点(List对象);后者根据一个xpath语句返回符合条件的第一个节点(Object类型)。
请看jdom-1.0自带的范例程序:

     它分析在web.xml文件中的注册的servlet的个数及参数个数,并输出角色名。

web.xml文件:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!--

<!DOCTYPE web-app

    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"

    "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">

-->

<web-app>

    <servlet>

        <servlet-name>snoop</servlet-name>

        <servlet-class>SnoopServlet</servlet-class>

    </servlet>

    <servlet>

        <servlet-name>file </servlet-name>

        <servlet-class>ViewFile</servlet-class>

        <init-param>

            <param-name>initial</param-name>

            <param-value>1000</param-value>

            <description>The initial value for the counter  <!-- optional --></description>

        </init-param>

    </servlet>

    <servlet-mapping>

        <servlet-name>mv</servlet-name>

        <url-pattern>*.wm</url-pattern>

    </servlet-mapping>

    <distributed/>

    <security-role>

      <role-name>manager</role-name>

      <role-name>director</role-name>

      <role-name>president</role-name>

    </security-role>

</web-app>

处理程序:

import java.io.*;

import java.util.*; 

public class XPathReader {     

    public static void main(String[] args) throws IOException, JDOMException {

        if (args.length != 1) {

            System.err.println("Usage: java XPathReader web.xml");

            return;

        }

        String filename = args[0];//从命令行输入web.xml

        PrintStream out = System.out;

        SAXBuilder builder = new SAXBuilder();

        Document doc = builder.build(new File(filename));//得到Document对象

 

 

        // Print servlet information

        XPath servletPath = XPath.newInstance("//servlet");//,选择任意路径下servlet元素

        List servlets = servletPath.selectNodes(doc);//返回所有的servlet元素。

        out.println("This WAR has "+ servlets.size() +" registered servlets:");

        Iterator i = servlets.iterator();

        while (i.hasNext()) {//输出servlet信息

            Element servlet = (Element) i.next();

            out.print("\t" + servlet.getChild("servlet-name")

                                    .getTextTrim() +

                      " for " + servlet.getChild("servlet-class")

                                       .getTextTrim());

            List initParams = servlet.getChildren("init-param");

            out.println(" (it has " + initParams.size() + " init params)"); 

        }             

        // Print security role information

        XPath rolePath = XPath.newInstance("//security-role/role-name/text()");

        List roleNames = rolePath.selectNodes(doc);//得到所有的角色名

        if (roleNames.size() == 0) {

            out.println("This WAR contains no roles");

        } else {

            out.println("This WAR contains " + roleNames.size() + " roles:");

            i = roleNames.iterator();

            while (i.hasNext()) {//输出角色名

                out.println("\t" + ((Text)i.next()).getTextTrim());

            }

        }

    }    

}

 

 

输出结果:

C:\java>java   XPathReader web.xml

This WAR has 2 registered servlets:

        snoop for SnoopServlet (it has 0 init params)

        file for ViewFile (it has 1 init params)

This WAR contains 3 roles:

        manager

        director

        president

 

 

6、数据输入要用到XML文档要通过org.jdom.input包,反过来需要org.jdom.output。如前面所说,关是看API文档就能够使用。

我们的例子读入XML文件exampleA.xml,加入一条处理指令,修改第一本书的价格和作者,并添加一条属性,然后写入文件exampleB.xml:

//exampleA.xml

<?xml version="1.0" encoding="GBK"?>

<bookList>

<book>

<name>Java编程入门</name>

<author>张三</author>

<publishDate>2002-6-6</publishDate>

<price>35.0</price>

</book>

<book>

<name>XML在Java中的应用</name>

<author>李四</author>

<publishDate>2002-9-16</publishDate>

<price>92.0</price>

</book>

</bookList>

//testJDOM.java

import org.jdom.*;

import org.jdom.output.*;

import org.jdom.input.*;

import java.io.*;

public class TestJDOM{

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

SAXBuilder sb = new SAXBuilder();

//从文件构造一个Document,因为XML文件中已经指定了编码,所以这里不必了

Document doc = sb.build(new FileInputStream("exampleA.xml"));

ProcessingInstruction pi = new ProcessingInstruction//加入一条处理指令

("xml-stylesheet","href=\"bookList.html.xsl\" type=\"text/xsl\"");

doc.addContent(pi);

Element root = doc.getRootElement(); //得到根元素

java.util.List books = root.getChildren(); //得到根元素所有子元素的集合

Element book = (Element)books.get(0); //得到第一个book元素

//为第一本书添加一条属性

Attribute a = new Attribute("hot","true");

book.setAttribute(a);

Element author = book.getChild("author"); //得到指定的字元素

author.setText("王五"); //将作者改为王五

//或 Text t = new Text("王五");book.addContent(t);

Element price = book.getChild("price"); //得到指定的字元素

//修改价格,比较郁闷的是我们必须自己转换数据类型,而这正是JAXB的优势

author.setText(Float.toString(50.0f));

String indent = " ";

boolean newLines = true;

XMLOutputter outp = new XMLOutputter(indent,newLines,"GBK");

outp.output(doc, new FileOutputStream("exampleB.xml"));

}

};

执行结果exampleB.xml:

<?xml version="1.0" encoding="GBK"?>

<bookList>

<book hot=”true”>

<name>Java编程入门</name>

<author>50.0</author>

<publishDate>2002-6-6</publishDate>

<price>35.0</price>

</book>

<book>

<name>XML在Java中的应用</name>

<author>李四</author>

<publishDate>2002-9-16</publishDate>

<price>92.0</price>

</book>

</bookList>

<?xml-stylesheet href="bookList.html.xsl" type="text/xsl"?>

在默认情况下,JDOM的Element类的getText()这类的方法不会过滤空白字符,如果你需要过滤,用setTextTrim() 。

posted @ 2006-07-26 16:05 brock 阅读(337) | 评论 (0)编辑 收藏

  1. /*
  2.  * QuickExcel.java
  3.  * 作者:杨庆成
  4.  * Created on 2004年11月22日, 下午4:05
  5.  * 在实际应用中经常要将数据库中的表导入Excel
  6.  * 本人在Apache的POI基础上写了一个简单的类
  7.  * 有不当指出请指正,谢谢!
  8.  * 
  9.  */
  10. package  yqc.poi;
  11. import  java.sql.*;
  12. import  java.util.*;
  13. import  java.io.*;
  14. import  java.io.ByteArrayInputStream;
  15. import  java.io.FileInputStream;
  16. import  java.io.FileOutputStream;
  17. import  java.io.IOException;
  18. import  org.apache.poi.hssf.usermodel.*;
  19. import  org.apache.poi.poifs.filesystem.POIFSFileSystem;
  20. import  org.apache.poi.hssf.record.*;
  21. import  org.apache.poi.hssf.model.*;
  22. import  org.apache.poi.hssf.usermodel.*;
  23. import  org.apache.poi.hssf.util.*;import yqc.sql.*;
  24. /**
  25.  *
  26.  * @author  Administrator
  27.  */
  28. public  class QuickExcel {
  29.     
  30.     /** Creates a new instance of QuickExcel */
  31.     private QuickExcel(String file){
  32.         _file=file;
  33.     }
  34.     
  35.     private void open()throws IOException{
  36.         InputStream stream = null;
  37.         Record[] records = null;
  38.         POIFSFileSystem fs =
  39.             new POIFSFileSystem(new FileInputStream(_file));
  40.         _wb = new HSSFWorkbook(fs);
  41.     }
  42.     
  43.     private void create(){
  44.         _wb=new HSSFWorkbook();
  45.     }
  46.     
  47.     public static QuickExcel newInstance (String file){
  48.         QuickExcel qe=new QuickExcel(file);
  49.         qe.create();
  50.         return qe;
  51.     }
  52.     
  53.     public static QuickExcel openInstance(String file) throws IOException {
  54.         QuickExcel qe=new QuickExcel(file);
  55.         qe.open();
  56.         return qe;
  57.     }
  58.     
  59.     public void close(){
  60.         try{
  61.             FileOutputStream fileOut = new FileOutputStream(_file);
  62.             _wb.write(fileOut);//把Workbook对象输出到文件workbook.xls中
  63.             fileOut.close();
  64.         }
  65.         catch (Exception ex){
  66.             System.out.println(ex.getMessage());
  67.         }
  68.     }
  69.     
  70.     private void removeSheet(String sheetName){
  71.         int i=_wb.getSheetIndex("sheetName");
  72.         if (i>=0) _wb.removeSheetAt(i);
  73.     }
  74.     
  75.     public int fillSheet (ResultSet rs,String sheetName)throws SQLException {
  76.         HSSFSheet st= _wb.createSheet(sheetName);
  77.         ResultSetMetaData rsmd= rs.getMetaData();
  78.         int index=0;
  79.         int result=0;
  80.         HSSFRow row=st.createRow(index++);
  81.         for(int i=1;i<=rsmd.getColumnCount();++i){
  82.             HSSFCell cell=row.createCell((short)(i-1));
  83.             cell.setCellValue(rsmd.getColumnName(i));
  84.         }
  85.         while(rs.next()) {
  86.             result++;
  87.             row=st.createRow(index++);
  88.             for(int i=1;i<=rsmd.getColumnCount();++i){
  89.                 HSSFCell cell=row.createCell((short)(i-1));
  90.                 cell.setEncoding(cell.ENCODING_UTF_16);
  91.                 cell.setCellValue(rs.getString(i));
  92.             }
  93.         }
  94.         return result;
  95. }
  96.     
  97.     public static void main(String[] args){
  98.         try{
  99.             QuickConnection qc=new MssqlConnection("jdbc:microsoft:sqlserver://192.168.0.100:1433;DatabaseName=ls");
  100.             QuickExcel qe=QuickExcel.newInstance("a.xls");
  101.             qc.connect();
  102.             String sql="select * from ls.dbo.radio1_emcee";
  103.             ResultSet rs=qc.getStatement().executeQuery(sql);
  104.             qe.fillSheet(rs,"MT");
  105.             qe.close();
  106.             qe=QuickExcel.openInstance("a.xls");
  107.             qe.fillSheet(rs,"MO");
  108.             qe.close();
  109.             qc.close();
  110.         }
  111.         catch (SQLException ex){
  112.             System.out.println(ex.getMessage());
  113.         }
  114.         catch (IOException ex){
  115.             System.out.println(ex.getMessage());
  116.         }
  117.     }
  118.     
  119.     HSSFWorkbook _wb;
  120.     String _file="new.xls";
  121. }
posted @ 2006-07-26 15:30 brock 阅读(448) | 评论 (0)编辑 收藏

摘要:

Apache的Jakata项目的POI子项目,目标是处理ole2对象。目前比较成熟的是HSSF接口,处理MS Excel(97-2002)对象
微软在桌面系统上的成功,令我们不得不大量使用它的办公产品,如:Word,Excel。时至今日,它的源代码仍然不公开已封锁了我们的进一步应用和开发。然而在要求更高的服务器领域,微软本身的产品移植性不好,  
性能不佳。在我们实际的开发中,表现层的解决方案虽然有多样,但是Ie浏览器已成为最多人使用的浏览器,因为大家都用Windows。在企业办公系统中,常常有客户这样子要求:你要把我们的报表直接用Excel打开。或者是:我们已经习惯用Excel打印。这样子如果用.net开发是没有问题的,但是有j2ee这个比.net更有前途的开放式的开发环境,难道我为了解决打印的要求去另写客户端的控件?或者在服务器端使用本地代码?第一种方案的问题是关键数据的处理有时候不能在客户端做,第2种方案的问题是牺牲了代码的可移植性和稳定性。如果让客户端只负责处理生成好的报表,那将是一种诱人的选择。

Apache的Jakata项目的POI子项目,目标是处理ole2对象。目前比较成熟的是HSSF接口,处理MS Excel(97-2002)对象。它不象我们仅仅是用csv生成的没有格式的可以由Excel转换的东西,而是真正的Excel对象,你可以控制一些属性如sheet,cell等等。这是一个年轻的项目,所以象HDF这样直接支持Word对象的好东西仍然在设计中。其它支持word格式的纯java方案还有itext,不过也是仍在奋斗中。但是HSSF已经成熟到能够和足够我们使用了。另外,无锡永中Office的实现方案也是纯java的解决方案,不过那也是完全商业的产品,并不是公开代码项目。其实,从开发历史的角度讲,在80年代中期starOffice的原作者在德国成立了StarOffice suite公司,然后到1999年夏天starOffice被sun收购,再到2000年6月starOffice5.2的发布;并且从starOffice6.0开始,starOffice建立在OpenOffice的api的基础上,这个公开代码的office项目已经进行了很长的时间。虽然那是由C++写的,但是POI的代码部分也是由openOffice改过来的。所以,应该对POI充满足够的信心。国内已经有部分公司在他们的办公自动化等Web项目中使用poi了,如日恒的ioffice,海泰的HTOffice等。

java当初把核心处理设成Unicode,带来的好处是另代码适应了多语言环境。然而由于老外的英语只有26个字母,有些情况下,一些程序员用8位的byte处理,一不小心就去掉了CJK的高位。或者是由于习惯在程序中采用硬编码,还有多种原因,使得许多java应用在CJK的处理上很烦恼。还好在POI HSSF中考虑到这个问题,可以设置encoding为双字节。

POI可以到www.apache.org下载到。编译好的jar主要有这样4个:poi包,poi Browser包,poi hdf包,poi hssf例程包。实际运行时,需要有poi包就可以了。如果用Jakarta ant编译和运行,下载apache Jakarta POI的release中的src包,它里面已经为你生成好了build文件了。只要运行ant就可以了(ant 的安装和使用在此不说了)。如果是用Jbuilder 运行,请在新建的项目中加入poi包。以Jbuilder6为例,选择Tools菜单项的config libraries...选项,新建一个lib。在弹出的菜单中选择poi包,如这个jakarta-poi-1.5.1-final-20020820.jar,把poi添加到jbuilder中。然后,右键点击你的项目,在project的properties菜单中path的required Libraries中,点add,添加刚才加入到jbuilder中的poi到你现在的项目中。如果你仅仅是为了熟悉POI hssf的使用,可以直接看POI的samples包中的源代码,并且运行它。hssf的各种对象都有例程的介绍。hssf提供的例程在org.apache.poi.hssf.usermodel.examples包中,共有14个,生成的目标xls都是workbook.xls。如果你想看更多的例程,可以参考hssf的Junit test cases,在poi的包的源代码中有。hssf都有测试代码。

这里只对部分例程的实现做介绍。

HSSF提供给用户使用的对象在org.apache.poi.hssf.usermodel包中,主要部分包括Excell对象,样式和格式,还有辅助操作。有以下几种对象:

HSSFWorkbook excell的文档对象

HSSFSheet excell的表单

HSSFRow excell的行

HSSFCell excell的格子单元

HSSFFont excell字体

HSSFName 名称

HSSFDataFormat 日期格式

在poi1.7中才有以下2项:

HSSFHeader sheet头

HSSFFooter sheet尾

和这个样式

HSSFCellStyle cell样式

辅助操作包括

HSSFDateUtil 日期

HSSFPrintSetup 打印

HSSFErrorConstants 错误信息表

仔细看org.apache.poi.hssf包的结构,不难发现HSSF的内部实现遵循的是MVC模型。

这里我用Rose把org.apache.poi.hssf.usermodel包中的对象反向导入并根据相互关系作了整理,详见下面两图:

  IMG ../upload/article/a2005512101549.jpg[/IMG]

图1 基本对象

从中不难可以发现每一个基本对象都关联了一个Record对象。Record对象是一个参考Office格式的相关记录。

   IMG ../upload/article/2005512101631.jpg[/IMG]


图2 HSSFWorkbook

HSSFWorkbook即是一个Excell对象。这幅类图体现的是HSSFWorkbook和基本对象的相互关系。可见,许多对象中也建立了Workbook的引用。还需要注意的是在HSSFWorkbook和HSSFSheet中建立了log机制POILogger,而且POILogger也是使用apache Log4J实现的。

先看poi的examples包中提供的最简单的例子,建立一个空xls文件。

import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.io.FileOutputStream;

import java.io.IOException;

public class NewWorkbook

{

public static void main(String[] args)

throws IOException

{

HSSFWorkbook wb = new HSSFWorkbook();//建立新HSSFWorkbook对象

FileOutputStream fileOut = new FileOutputStream("workbook.xls");

wb.write(fileOut);//把Workbook对象输出到文件workbook.xls中

fileOut.close();

}

}

通过这个例子,我们建立的是一个空白的xls文件(不是空文件)。在此基础上,我们可以进一步看其它的例子。


import org.apache.poi.hssf.usermodel.*;

import java.io.FileOutputStream;

import java.io.IOException;

public class CreateCells

{

public static void main(String[] args)

throws IOException

{

HSSFWorkbook wb = new HSSFWorkbook();//建立新HSSFWorkbook对象

HSSFSheet sheet = wb.createSheet("new sheet");//建立新的sheet对象


// Create a row and put some cells in it. Rows are 0 based.

HSSFRow row = sheet.createRow((short)0);//建立新行

// Create a cell and put a value in it.

HSSFCell cell = row.createCell((short)0);//建立新cell

cell.setCellValue(1);//设置cell的整数类型的值


// Or do it on one line.

row.createCell((short)1).setCellValue(1.2);//设置cell浮点类型的值

row.createCell((short)2).setCellValue("test");//设置cell字符类型的值

row.createCell((short)3).setCellValue(true);//设置cell布尔类型的值

HSSFCellStyle cellStyle = wb.createCellStyle();//建立新的cell样式

cellStyle.setDataFormat(HSSFDataFormat.getFormat("m/d/yy h:mm"));//设置cell样式为定制的日期格式

HSSFCell dCell =row.createCell((short)4);

dCell.setCellValue(new Date());//设置cell为日期类型的值

dCell.setCellStyle(cellStyle); //设置该cell日期的显示格式

HSSFCell csCell =row.createCell((short)5);

csCell.setEncoding(HSSFCell.ENCODING_UTF_16);//设置cell编码解决中文高位字节截断

csCell.setCellValue("中文测试_Chinese Words Test");//设置中西文结合字符串

row.createCell((short)6).setCellType(HSSFCell.CELL_TYPE_ERROR);//建立错误cell


// Write the output to a file

FileOutputStream fileOut = new FileOutputStream("workbook.xls");

wb.write(fileOut);

fileOut.close();

}

}

我稍微修改了原来的examples包中的CreateCells类写了上面的功能测试类。通过这个例子,我们可以清楚的看到xls文件从大到小包括了HSSFWorkbook HSSFSheet HSSFRow HSSFCell这样几个对象。我们可以在cell中设置各种类型的值。尤其要注意的是如果你想正确的显示非欧美的字符时,尤其象中日韩这样的语言,必须设置编码为16位的即是HSSFCell.ENCODING_UTF_16,才能保证字符的高8位不被截断而引起编码失真形成乱码。

其他测试可以通过参考examples包中的测试例子掌握poi的详细用法,包括字体的设置,cell大小和低纹的设置等。需要注意的是POI是一个仍然在完善中的公开代码的项目,所以有些功能正在不断的扩充。如HSSFSheet的getFooter() getHeader()和setFooter(HSSFFooter hsf) setHeader(HSSFHeader hsh)是在POI1.7中才有的,而POI1.5中就没有。运行测试熟悉代码或者使用它做项目时请注意POI的版本。

另外需要注意的是HSSF也有它的对xls基于事件的解析。可以参考例程中的EventExample.java。它通过实现HSSFListener完成从普通流认知Xls中包含的内容,在apache Cocoon中的org.apache.cocoon.serialization.HSSFSerializer中用到了这个解析。因为Cocoon2是基于事件的,所以POI为了提供快速的解析也提供了相应的事件。当然我们自己也可以实现这个事件接口。

因为POI还不是一个足够成熟的项目,所以有必要做进一步的开发和测试。但是它已经为我们用纯java操作ole2对象提供了可能,而且克服了ole对象调用的缺陷,提供了服务器端的Excel解决方案。

 

posted @ 2006-07-26 15:29 brock 阅读(308) | 评论 (0)编辑 收藏

where 1=1有什么用?在SQL语言中,写这么一句话就跟没写一样。

select * from table1 where 1=1与select * from table1完全没有区别,甚至还有其他许多写法,1<>2,'a'='a','a'<>'b',其目的就只有一个,where的条件为永真,得到的结果就是未加约束条件的。

在SQL注入时会用到这个,例如select * from table1 where name='lala'给强行加上select * from table1 where name='lala' or 1=1这就又变成了无约束的查询了。

最近发现的妙用在于,在不定数量查询条件情况下,1=1可以很方便的规范语句。例如一个查询可能有name,age,height,weight约束,也可能没有,那该如何处理呢?

String sql=select * from table1 where 1=1

为什么要写多余的1=1?马上就知道了。

if(!name.equals("")){
 sql=sql+"name='"+name+"'";
}
if(!age.equals("")){
 sql=sql+"age'"+age+"'";
}
if(!height.equals("")){
 sql=sql+"height='"+height+"'";
}
if(!weight.equals("")){
 sql=sql+"weight='"+weight+"'";
}

如果不写1=1呢,那么在每一个不为空的查询条件面前,都必须判断有没有where字句,否则要在第一个出现的地方加where

posted @ 2006-07-26 14:24 brock 阅读(410) | 评论 (0)编辑 收藏

泛型是J2SE 5.0最重要的特性。他们让你写一个type(类或接口)和创建一个实例通过传递一个或多个引用类型。本文将教你如何操作泛型。它的第一部分是“没有泛型的日子”,先让我们回忆老版本JDK的不便。然后,举一些泛型的例子。在讨论完语法以及有界泛型的使用之后,文章最后一章将解释如何写泛型。
J2SE 5.0中的泛型

作者:Budi Kurniawan

翻译:RR00

email:di_feng_ro@hotmail.com


版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
英文原文地址:
http://www.onjava.com/pub/a/onjava/2005/07/06/generics.html
中文地址:
http://www.matrix.org.cn/resource/article/43/43634_java_generics.html
关键词: java generics java5

摘要
       泛型是J2SE 5.0最重要的特性。他们让你写一个type(类或接口)和创建一个实例通过传递一个或多个引用类型。这个实例受限于只能作用于这些类型。比如,在java 5,java.util.List 已经被泛化。当建立一个list对象时,你通过传递一个java类型建立一个List实例,此list实例只能作用于所传递的类型。这意味着如果你传递一个String ,此List实例只能拥有String对象;如果你传递一个Integer,此实例只能存贮Integer对象。除了创建参数化的类型,你还能创建参数化的函数。
     泛型的第一个好处是编译时的严格类型检查。这是集合框架最重要的特点。此外,泛型消除了绝大多数的类型转换。在JDK 5.0之前,当你使用集合框架时,你不得不进行类型转换。
     本文将教你如何操作泛型。它的第一部分是“没有泛型的日子”,先让我们回忆老版本JDK的不便。然后,举一些泛型的例子。在讨论完语法以及有界泛型的使用之后,文章最后一章将解释如何写泛型。
  

没有泛型的日子
     所有的java类都源自java.lang.Object,这意味着所有的JAVA对象能转换成Object。因此,在之前的JDK的版本中,很多集合框架的函数接受一个Object参数。所以,collections是一个能持有任何对象的多用途工具,但带来了不良的后果。

     举个简单的例子,在JDK 5.0的之前版本中,类List的函数add接受一个Object参数:

public boolean add(java.lang.Object element)


        所以你能传递任何类型给add。这是故意这么设计的。否则,它只能传递某种特定的对象,这样就会出现各种List类型,如,StringList, EmployeeList, AddressList等。
     add通过Object传递能带来好处,现在我们考虑get函数(返回List中的一个元素).如下是JDK 5之前版本的定义:

public java.lang.Object get(int index) throws IndexOutOfBoundsException


get返回一个Object.不幸的事情从此开始了.假如你储存了两个String对象在一个List中:

List stringList1 = new ArrayList();
stringList1.add("Java 5");
stringList1.add("with generics");


当你想从stringList1取得一个元素时,你得到了一个Object.为了操作原来的类型元素,你不得不把它转换为String。

String s1 = (String) stringList1.get(0);


但是,假如你曾经把一个非String对象加入stringList1中,上面的代码会抛出一个ClassCastException. 有了泛型,你能创建一个单一用途的List实例.比如,你能创建一个只接受String对象的List实例,另外一个实例只能接受Employee对象.这同样适用于集合框架中的其他类型.


泛型入门

   像一个函数能接受参数一样,一个泛型也能接受参数.这就是一个泛型经常被称为一个参数化类型的原因.但是不像函数用()传递参数,泛型是用<>传递参数的.声明一个泛型和声明一个普通类没有什么区别,只不过你把泛型的变量放在<>中.
     比如,在JDK 5中,你可以这样声明一个java.util.List :  List<E> myList;
E 称为类型变量.意味着一个变量将被一个类型替代.替代类型变量的值将被当作参数或返回类型.对于List接口来说,当一个实例被创建以后,E 将被当作一个add或别的函数的参数.E 也会使get或别的参数的返回值.下面是add和get的定义:

boolean add<E o>
E get(int index)


NOTE:一个泛型在声明或例示时允许你传递特定的类型变量: E.除此之外,如果E是个类,你可以传递子类;如果E是个接口,你可以传递实现接口的类;

-----------------------------译者添加--------------------
List<Number> numberList= new ArrayList<Number>();
   numberList.add(2.0);
   numberList.add(2);
-----------------------------译者添加--------------------


如果你传递一个String给一个List,比如:

List<String> myList;


那么mylist的add函数将接受一个String作为他的参数,而get函数将返回一个String.因为返回了一个特定的类型,所以不用类型转化了。

NOTE:根据惯例,我们使用一个唯一的大写字目表示一个类型变量。为了创建一个泛型,你需在声明时传递同样的参数列表。比如,你要想创建一个ArrayList来操作String ,你必须把String放在<>中。如:

List<String> myList = new ArrayList<String>();


再比如,java.util.Map 是这么定义的:

public interface Map<K,V>


K用来声明map键(KEY)的类型而V用来表示值(VALUE)的类型。put和values是这么定义的:

V put(K key, V value)
Collection<V> values()


NOTE:一个泛型不准直接的或间接的是java.lang.Throwable的子类。因为异常是在运行时抛出的,所以它不可能预言什么类型的异常将在编译时抛出.

列表1的例子将比较List在JDK 1.4 和JDK1.5的不同

package com.brainysoftware.jdk5.app16;
import java.util.List;
import java.util.ArrayList;

public class GenericListTest {
  public static void main(String[] args) {
    // in JDK 1.4
    List stringList1 = new ArrayList();
    stringList1.add("Java 1.0 - 5.0");
    stringList1.add("without generics");
    // cast to java.lang.String
    String s1 = (String) stringList1.get(0);
    System.out.println(s1.toUpperCase());

    // now with generics in JDK 5
    List<String> stringList2 = new ArrayList<String>();
    stringList2.add("Java 5.0");
    stringList2.add("with generics");
    // no need for type casting
    String s2 = stringList2.get(0);
    System.out.println(s2.toUpperCase());
  }
}


在列表1中,stringList2是个泛型。声明List<String>告诉编译器List的实例能接受一个String对象。当然,在另外的情况中,你能新建能接受各种对象的List实例。注意,当从List实例中返回成员元素时,不需要对象转化,因为他返回的了你想要的类型,也就是String.

NOTE:泛型的类型检查(type checking)是在编译时完成的.

      最让人感兴趣的事情是,一个泛型是个类型并且能被当作一个类型变量。比如,你想你的List储存lists of Strings,你能通过把List<String>作为他的类型变量来声明List。比如:

List<List<String>> myListOfListsOfStrings;


要从myList中的第一个List重新取得String,你可以这么用:

String s = myListOfListsOfStrings.get(0).get(0);


下一个列表中的ListOfListsTest类示范了一个List(命名为listOfLists)接受一个String List作为参数。

package com.brainysoftware.jdk5.app16;
import java.util.ArrayList;
import java.util.List;
public class ListOfListsTest {
  public static void main(String[] args) {
    List<String> listOfStrings = new ArrayList<String>();
    listOfStrings.add("Hello again");
    List<List<String>> listOfLists = new ArrayList<List<String>>();
    listOfLists.add(listOfStrings);
    String s = listOfLists.get(0).get(0);
    System.out.println(s); // prints "Hello again"
  }
}


另外,一个泛型接受一个或多个类型变量。比如,java.util.Map有两个类型变量s。第一个定义了键(key)的类型,第二个定义了值(value)的类型。下面的例子讲教我们如何使用个一个泛型Map.

package com.brainysoftware.jdk5.app16;
import java.util.HashMap;
import java.util.Map;
public class MapTest {
  public static void main(String[] args) {
    Map<String, String> map = new HashMap<String, String>();
    map.put("key1", "value1");
    map.put("key2", "value2");
    String value1 = map.get("key1");
  }
}


在这个例子中,重新得到一个key1代表的String值,我们不需要任何类型转换。

没有参数的情况下使用泛型

    既然在J2SE 5.0中收集类型已经泛型化,那么,原来的使用这些类型的代码将如何呢?很幸运,他们在JAVA 5中将继续工作,因为你能使用没有参数的泛型。比如,你能继续像原来一样使用List接口,正如下面的例子一样。

List stringList1 = new ArrayList();
stringList1.add("Java 1.0 - 5.0");
stringList1.add("without generics");
String s1 = (String) stringList1.get(0);


一个没有任何参数的泛型被称为原型(raw type)。它意味着这些为JDK1.4或更早的版本而写的代码将继续在java 5中工作。

尽管如此,一个需要注意的事情是,JDK5编译器希望你使用带参数的泛型。否则,编译器将提示警告,因为他认为你可能忘了定义类型变量s。比如,编译上面的代码的时候你会看到下面这些警告,因为第一个List被认为是原型。

Note: com/brainysoftware/jdk5/app16/GenericListTest.java
        uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

当你使用原型时,如果你不想看到这些警告,你有几个选择来达到目的:
1.编译时带上参数-source 1.4
2.使用@SupressWarnings("unchecked")注释
3.更新你的代码,使用List<Object>. List<Object>的实例能接受任何类型的对象,就像是一个原型List。然而,编译器不会报错。

使用 ? 通配符
   前面提过,如果你声明了一个List<aType>, 那么这个List对aType起作用,所以你能储存下面这些类型的对象:
1.一个aType的实例
2.它的子类的实例(如果aType是个类)
3.实现aType接口的类实例(如果aType是个接口)
但是,请注意,一个泛型本身是个JAVA类型,就像java.lang.String或java.io.File一样。传递不同的类型变量给泛型可以创建不同的JAVA类型。比如,下面例子中list1和list2引用了不同的类型对象。

List<Object> list1 = new ArrayList<Object>();
List<String> list2 = new ArrayList<String>();


list1指向了一个类型变量s为java.lang.Objects 的List而list2指向了一个类型变量s为String 的List。所以传递一个List<String>给一个参数为List<Object>的函数将导致compile time错误。下面列表可以说明:
package com.brainysoftware.jdk5.app16;
import java.util.ArrayList;
import java.util.List;

public class AllowedTypeTest {
  public static void doIt(List<Object> l) {
  }
  public static void main(String[] args) {
    List<String> myList = new ArrayList<String>();
    // 这里将产生一个错误
    doIt(myList);
  }
}

上面的代码无法编译,因为你试图传递一个错误的类型给函数doIt。doIt的参数是List<Object>二你传递的参数是List<String>。
可以使用 ? 通配符解决这个难题。List<?> 意味着一个对任何对象起作用的List。所以,doIt可以改为:

public static void doIt(List<?> l) {}


    在某些情况下你会考虑使用 ? 通配符。比如,你有一个printList函数,这个函数打印一个List的所有成员,你想让这个函数对任何类型的List起作用时。否则,你只能累死累活的写很多printList的重载函数。下面的列表引用了使用 ? 通配符的printList函数。
package com.brainysoftware.jdk5.app16;
import java.util.ArrayList;
import java.util.List;

public class WildCardTest {

  public static void printList(List<?> list) {
    for (Object element : list) {
      System.out.println(element);
    }
  }
  public static void main(String[] args) {
    List<String> list1 = new ArrayList<String>();
    list1.add("Hello");
    list1.add("World");
    printList(list1);

    List<Integer> list2 = new ArrayList<Integer>();
    list2.add(100);
    list2.add(200);
    printList(list2);
  }
}


这些代码说明了在printList函数中,List<?>表示各种类型的List对象。然而,请注意,在声明的时候使用 ? 通配符是不合法的,像这样:

List<?> myList = new ArrayList<?>(); // 不合法


如果你想创建一个接收任何类型对象的List,你可以使用Object作为类型变量,就像这样:

List<Object> myList = new ArrayList<Object>();


在函数中使用界限通配符
在之前的章节中,你学会了通过传递不同的类型变量s来创建不同JAVA类型的泛型,但并不考虑类型变量s之间的继承关系。在很多情况下,你想一个函数有不同的List参数。比如,你有一个函数getAverage,他返回了一个List中成员的平均值。然而,如果你把List<Number>作为getAverage的参数,你就没法传递List<Integer> 或List<Double>参数,因为List<Number>和List<Integer> 和List<Double>不是同样的类型。

你能使用原型或使用通配符,但这样无法在编译时进行安全类型检查,因为你能传递任何类型的List,比如List<String>的实例。你可以使用List<Number>作为参数,但是你就只能传递List<Number>给函数。但这样就使你的函数功能减少,因为你可能更多的时候要操作List<Integer>或List<Long>,而不是List<Number>。

J2SE5.0增加了一个规则来解决了这种约束,这个规则就是允许你定义一个上界(upper bound) 类型变量.在这种方式中,你能传递一个类型或它的子类。在上面getAverage函数的例子中,你能传递一个List<Number>或它的子类的实例,比如List<Integer> or List<Float>。

使用上界规则的语法这么定义的:GenericType<? extends upperBoundType>. 比如,对getAverage函数的参数,你可以这么写List<? extends Number>. 下面例子说明了如何使用这种规则。
package com.brainysoftware.jdk5.app16;
import java.util.ArrayList;
import java.util.List;
public class BoundedWildcardTest {
  public static double getAverage(List<? extends Number> numberList)
  {
    double total = 0.0;
    for (Number number : numberList)
      total += number.doubleValue();
    return total/numberList.size();
  }

  public static void main(String[] args) {
    List<Integer> integerList = new ArrayList<Integer>();
    integerList.add(3);
    integerList.add(30);
    integerList.add(300);
    System.out.println(getAverage(integerList)); // 111.0
    List<Double> doubleList = new ArrayList<Double>();
    doubleList.add(3.0);
    doubleList.add(33.0);
    System.out.println(getAverage(doubleList)); // 18.0
  }
}

由于有了上界规则,上面例子中的getAverage函数允许你传递一个List<Number> 或一个类型变量是任何java.lang.Number子类的List。

下界规则
关键字extends定义了一个类型变量的上界。通过使用super关键字,我们可以定义一个类型变量的下界,尽管使用的情况不多。比如,如果一个函数的参数是List<? super Integer>,那么意味着你可以传递一个List<Integer>的实例或者任何java.lang.Integer的超类(superclass)。

创建泛型

前面的章节主要说明了如何使使用泛型,特别是集合框架中的类。现在我们开始学习如何写自己的泛型。

基本上,除了声明一些你想要使用的类型变量s外,一个泛型和别的类没有什么区别。这些类型变量s位于类型后面的<>中。比如,下面的Point就是个泛型。一个Point对象代表了一个系统中的点,它有横坐标和纵坐标。通过使Point泛型化,你能定义一个点实例的精确程度。比如,如果一个Point对象需要非常精确,你就把Double作为类型变量。否则,Integer 就够了。
package com.brainysoftware.jdk5.app16;
public class Point<T> {
  T x;
  T y;
  public Point(T x, T y) {
    this.x = x;
    this.y = y;
  }
  public T getX() {
    return x;
  }
  public T getY() {
    return y;
  }
  public void setX(T x) {
    this.x = x;
  }
  public void setY(T y) {
    this.y = y;
  }
}


在这个例子中,T是Point的类型变量 。T是getX和getY的返回值类型,也是setX和setY的参数类型。此外,构造函数结合两个T参数。
使用point类就像使用别的类一样。比如,下面的例子创建了两个Point对象:ponint1和point2。前者把Integer作为类型变量,而后者把Double作为类型变量。

Point<Integer> point1 = new Point<Integer>(4, 2);
point1.setX(7);
Point<Double> point2 = new Point<Double>(1.3, 2.6);
point2.setX(109.91);


总结
泛型使代码在编译时有了更严格的类型检查。特别是在集合框架中,泛型有两个作用。第一,他们增加了对集合类型在编译时的类型检查,所以集合类所能持有的类型对传递给它的参数类型起了限制作用。比如你创建了一个持有strings的java.util.List实例,那么他就将不能接受Integers或别的类型。其次,当你从一个集合中取得一个元素时,泛型消除了类型转换的必要。
泛型能够在没有类型变量的情况下使用,比如,作为原型。这些措施让Java 5之前的代码能够运行在JRE 5中。但是,对新的应用程序,你最好不要使用原型,因为以后Java可能不支持他们。

你已经知道通过传递不同类型的类型变量给泛型可以产生不同的JAVA类型。就是说List<String>和List<Object>的类型是不同的。尽管String是java.lang.Object。但是传递一个List<String>给一个参数是List<Object>的函数会参数会产生编译错误(compile error)。函数能用 ? 通配符使其接受任何类型的参数。List<?> 意味着任何类型的对象。
最后,你已经看到了写一个泛型和别的一般JAVA类没有什么区别。你只需要在类型名称后面的<>中声明一系列的类型变量s就行了。这些类型变量s就是返回值类型或者参数类型。根据惯例,一个类型变量用一个大写字母表示。
posted @ 2006-07-26 13:30 brock 阅读(108) | 评论 (0)编辑 收藏

     摘要: 利用 Java 的 Properties 类读取配置文件信息 ...  阅读全文
posted @ 2006-07-26 12:50 brock 阅读(1451) | 评论 (0)编辑 收藏

Eclipse快捷键指南


Eclipse 快捷键指南
本文档从Eclipse软件上整理,是列出了标准的快捷键,未列出Emacs快捷键。
转贴请注明作者和出处。
 
编辑
作用域
功能
快捷键
全局
查找并替换
Ctrl+F
文本编辑器
查找上一个
Ctrl+Shift+K
文本编辑器
查找下一个
Ctrl+K
全局
撤销
Ctrl+Z
全局
复制
Ctrl+C
全局
恢复上一个选择
Alt+Shift+↓
全局
剪切
Ctrl+X
全局
快速修正
Ctrl1+1
全局
内容辅助
Alt+/
全局
全部选中
Ctrl+A
全局
删除
Delete
全局
上下文信息
Alt+?
Alt+Shift+?
Ctrl+Shift+Space
Java编辑器
显示工具提示描述
F2
Java编辑器
选择封装元素
Alt+Shift+↑
Java编辑器
选择上一个元素
Alt+Shift+←
Java编辑器
选择下一个元素
Alt+Shift+→
文本编辑器
增量查找
Ctrl+J
文本编辑器
增量逆向查找
Ctrl+Shift+J
全局
粘贴
Ctrl+V
全局
重做
Ctrl+Y
 
查看
作用域
功能
快捷键
全局
放大
Ctrl+=
全局
缩小
Ctrl+-
 
窗口
作用域
功能
快捷键
全局
激活编辑器
F12
全局
切换编辑器
Ctrl+Shift+W
全局
上一个编辑器
Ctrl+Shift+F6
全局
上一个视图
Ctrl+Shift+F7
全局
上一个透视图
Ctrl+Shift+F8
全局
下一个编辑器
Ctrl+F6
全局
下一个视图
Ctrl+F7
全局
下一个透视图
Ctrl+F8
文本编辑器
显示标尺上下文菜单
Ctrl+W
全局
显示视图菜单
Ctrl+F10
全局
显示系统菜单
Alt+-
 
导航
作用域
功能
快捷键
Java编辑器
打开结构
Ctrl+F3
全局
打开类型
Ctrl+Shift+T
全局
打开类型层次结构
F4
全局
打开声明
F3
全局
打开外部javadoc
Shift+F2
全局
打开资源
Ctrl+Shift+R
全局
后退历史记录
Alt+←
全局
前进历史记录
Alt+→
全局
上一个
Ctrl+,
全局
下一个
Ctrl+.
Java编辑器
显示大纲
Ctrl+O
全局
在层次结构中打开类型
Ctrl+Shift+H
全局
转至匹配的括号
Ctrl+Shift+P
全局
转至上一个编辑位置
Ctrl+Q
Java编辑器
转至上一个成员
Ctrl+Shift+↑
Java编辑器
转至下一个成员
Ctrl+Shift+↓
文本编辑器
转至行
Ctrl+L
 
搜索
作用域
功能
快捷键
全局
出现在文件中
Ctrl+Shift+U
全局
打开搜索对话框
Ctrl+H
全局
工作区中的声明
Ctrl+G
全局
工作区中的引用
Ctrl+Shift+G
 
文本编辑
作用域
功能
快捷键
文本编辑器
改写切换
Insert
文本编辑器
上滚行
Ctrl+↑
文本编辑器
下滚行
Ctrl+↓
 
文件
作用域
功能
快捷键
全局
保存
Ctrl+X
Ctrl+S
全局
打印
Ctrl+P
全局
关闭
Ctrl+F4
全局
全部保存
Ctrl+Shift+S
全局
全部关闭
Ctrl+Shift+F4
全局
属性
Alt+Enter
全局
新建
Ctrl+N
 
项目
作用域
功能
快捷键
全局
全部构建
Ctrl+B
 
源代码
作用域
功能
快捷键
Java编辑器
格式化
Ctrl+Shift+F
Java编辑器
取消注释
Ctrl+\
Java编辑器
注释
Ctrl+/
Java编辑器
添加导入
Ctrl+Shift+M
Java编辑器
组织导入
Ctrl+Shift+O
Java编辑器
使用try/catch块来包围
未设置,太常用了,所以在这里列出,建议自己设置。
也可以使用Ctrl+1自动修正。
 
运行
作用域
功能
快捷键
全局
单步返回
F7
全局
单步跳过
F6
全局
单步跳入
F5
全局
单步跳入选择
Ctrl+F5
全局
调试上次启动
F11
全局
继续
F8
全局
使用过滤器单步执行
Shift+F5
全局
添加/去除断点
Ctrl+Shift+B
全局
显示
Ctrl+D
全局
运行上次启动
Ctrl+F11
全局
运行至行
Ctrl+R
全局
执行
Ctrl+U
 
重构
作用域
功能
快捷键
全局
撤销重构
Alt+Shift+Z
全局
抽取方法
Alt+Shift+M
全局
抽取局部变量
Alt+Shift+L
全局
内联
Alt+Shift+I
全局
移动
Alt+Shift+V
全局
重命名
Alt+Shift+R
全局
重做
Alt+Shift+Y
 
posted @ 2006-07-26 10:18 brock 阅读(114) | 评论 (0)编辑 收藏

仅列出标题
共15页: First 上一页 7 8 9 10 11 12 13 14 15 下一页