love fish大鵬一曰同風(fēng)起,扶搖直上九萬里

          常用鏈接

          統(tǒng)計(jì)

          積分與排名

          friends

          link

          最新評(píng)論

          JDK6的新特性(轉(zhuǎn))

          SystemTray類
          在JDK6中 ,AWT新增加了兩個(gè)類:Desktop和SystemTray,前者可以用來打開系統(tǒng)默認(rèn)瀏覽器瀏覽指定的URL,打開系統(tǒng)默認(rèn)郵件客戶端給指定的郵箱發(fā)郵件,用默認(rèn)應(yīng)用程序打開或編輯文件(比如,用記事本打開以txt為后綴名的文件),用系統(tǒng)默認(rèn)的打印機(jī)打印文檔;后者可以用來在系統(tǒng)托盤區(qū)創(chuàng)建一個(gè)托盤程序.下面代碼演示了Desktop和SystemTray的用法.

          /**
          *
          * @author chinajash
          */
          import java.awt.Desktop;
          import java.awt.SystemTray;
          import java.awt.TrayIcon;
          import java.awt.Toolkit;
          import java.awt.Image;
          import java.awt.PopupMenu;
          import java.awt.Menu;
          import java.awt.MenuItem;
          import java.awt.AWTException;
          import java.io.File;
          import java.io.IOException;
          import java.net.URI;
          import java.net.URISyntaxException;
          import java.awt.event.ActionEvent;
          import java.awt.event.ActionListener;

          public class DesktopTray {
            private static Desktop desktop;
            private static SystemTray st;
            private static PopupMenu pm;
            public static void main(String[] args) {
              if(Desktop.isDesktopSupported()){//判斷當(dāng)前平臺(tái)是否支持Desktop類
                  desktop = Desktop.getDesktop();
              }
              if(SystemTray.isSupported()){//判斷當(dāng)前平臺(tái)是否支持系統(tǒng)托盤
                  st = SystemTray.getSystemTray();
                  Image image = Toolkit.getDefaultToolkit().getImage("netbeans.png");//定義托盤圖標(biāo)的圖片        
                  createPopupMenu();
                  TrayIcon ti = new TrayIcon(image, "Desktop Demo Tray", pm);
                  try {
                    st.add(ti);
                  } catch (AWTException ex) {
                    ex.printStackTrace();
                  }
              }
            }
           
            public static void sendMail(String mail){
              if(desktop!=null && desktop.isSupported(Desktop.Action.MAIL)){
                  try {
                    desktop.mail(new URI(mail));
                  } catch (IOException ex) {
                    ex.printStackTrace();
                  } catch (URISyntaxException ex) {
                    ex.printStackTrace();
                  }
              }        
            }
           
            public static void openBrowser(String url){
              if(desktop!=null && desktop.isSupported(Desktop.Action.BROWSE)){
                  try {
                    desktop.browse(new URI(url));
                  } catch (IOException ex) {
                    ex.printStackTrace();
                  } catch (URISyntaxException ex) {
                    ex.printStackTrace();
                  }
              }
            }
           
            public static void edit(){
              if(desktop!=null && desktop.isSupported(Desktop.Action.EDIT)){
                  try {
                    File txtFile = new File("test.txt");
                    if(!txtFile.exists()){
                      txtFile.createNewFile();
                    }
                    desktop.edit(txtFile);
                  } catch (IOException ex) {
                    ex.printStackTrace();
                  }
              }
            }
           
            public static void createPopupMenu(){
              pm = new PopupMenu();
              MenuItem openBrowser = new MenuItem("Open My Blog");
              openBrowser.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                    openBrowser("http://blog.csdn.net/chinajash");
                  }
              });
             
              MenuItem sendMail = new MenuItem("Send Mail to me");
              sendMail.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                    sendMail("mailto:chinajash@yahoo.com.cn");
                  }
              });
             
              MenuItem edit = new MenuItem("Edit Text File");
              sendMail.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                    edit();
                  }
              });
             
              MenuItem exitMenu = new MenuItem("&Exit");
              exitMenu.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                  }
              });
              pm.add(openBrowser);
              pm.add(sendMail);
              pm.add(edit);
              pm.addSeparator();
              pm.add(exitMenu);  
            }
          }

          如果在Windows中運(yùn)行該程序,可以看到在系統(tǒng)托盤區(qū)有一個(gè)圖標(biāo),右擊該圖標(biāo)會(huì)彈出一個(gè)菜單,點(diǎn)擊Open My Blog會(huì)打開IE,并瀏覽"http://blog.csdn.net/chinajash";點(diǎn)擊Send Mail to me會(huì)打開Outlook Express給我發(fā)郵件;點(diǎn)擊Edit Text File會(huì)打開記事本編輯在程序中創(chuàng)建的文件test.txt
          sunyfun 2007-04-01 11:38
          JDK6的新特性之二:使用JAXB2來實(shí)現(xiàn)對(duì)象與XML之間的映射

          JDK6的新特性之二:使用JAXB2來實(shí)現(xiàn)對(duì)象與XML之間的映射
          JAXB是Java Architecture for XML Binding的縮寫,可以將一個(gè)Java對(duì)象轉(zhuǎn)變成為XML格式,反之亦然。我們把對(duì)象與關(guān)系數(shù)據(jù)庫(kù)之間的映射稱為ORM, 其實(shí)也可以把對(duì)象與XML之間的映射稱為OXM(Object XML Mapping). 原來JAXB是Java EE的一部分,在JDK6中,SUN將其放到了Java SE中,這也是SUN的一貫做法。JDK6中自帶的這個(gè)JAXB版本是2.0, 比起1.0(JSR 31)來,JAXB2(JSR 222)用JDK5的新特性Annotation來標(biāo)識(shí)要作綁定的類和屬性等,這就極大簡(jiǎn)化了開發(fā)的工作量。實(shí)際上,在Java EE 5.0中,EJB和Web Services也通過Annotation來簡(jiǎn)化開發(fā)工作。另外,JAXB2在底層是用StAX(JSR 173)來處理XML文檔。 閑話不多說了,下面用代碼演示在JDK6中如何來用JAXB2

          public class JAXB2Tester {
            public static void main(String[] args) throws JAXBException,IOException {
              JAXBContext context = JAXBContext.newInstance(Person.class);
              //下面代碼演示將對(duì)象轉(zhuǎn)變?yōu)閤ml
              Marshaller m = context.createMarshaller();
              Address address = new Address("China","Beijing","Beijing","ShangDi West","100080");
              Person p = new Person(Calendar.getInstance(),"JAXB2",address,Gender.MALE,"SW");
              FileWriter fw = new FileWriter("person.xml");
              m.marshal(p,fw);

              //下面代碼演示將上面生成的xml轉(zhuǎn)換為對(duì)象
              FileReader fr = new FileReader("person.xml");
              Unmarshaller um = context.createUnmarshaller();
              Person p2 = (Person)um.unmarshal(fr);
              System.out.println("Country:"+p2.getAddress().getCountry());
            }
          }

          @XmlRootElement//表示person是一個(gè)根元素
          class Person {  
            @XmlElement
            Calendar birthDay; //birthday將作為person的子元素

            @XmlAttribute
            String name; //name將作為person的的一個(gè)屬性

            public Address getAddress() {
              return address;
            }

            @XmlElement
            Address address; //address將作為person的子元素

            @XmlElement
            Gender gender; //gender將作為person的子元素

            @XmlElement
            String job; //job將作為person的子元素

            public Person(){
            }
           
            public Person(Calendar birthDay, String name, Address address, Gender gender, String job) {
              this.birthDay = birthDay;
              this.name = name;
              this.address = address;
              this.gender = gender;
              this.job = job;
            }
          }

          enum Gender{
            MALE(true),
            FEMALE (false);
            private boolean value;
            Gender(boolean _value){
              value = _value;
            }
          }

          class Address {
            @XmlAttribute
            String country;
            @XmlElement
            String state;
            @XmlElement
            String city;
            @XmlElement
            String street;
            String zipcode; //由于沒有添加@XmlElement,所以該元素不會(huì)出現(xiàn)在輸出的xml中

            public Address() {
            }

            public Address(String country, String state, String city, String street, String zipcode) {
              this.country = country;
              this.state = state;
              this.city = city;
              this.street = street;
              this.zipcode = zipcode;
            }


            public String getCountry() {
              return country;
            }
          }

          運(yùn)行該程序,我們會(huì)得到一個(gè)person.xml的文件,如下:

          <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>

          <person name="JAXB2">
              <birthDay>2006-12-28T08:49:27.203+00:00</birthDay>
              <address country="China">
                  <state>Beijing</state>
                  <city>Beijing</city>
                  <street>ShangDi West</street>
          </address>
              <gender>MALE</gender>
              <job>SW</job>
          </person>
          控制臺(tái)會(huì)輸出

          Country:China

          最后,想說一點(diǎn),除了JAXB之外,我們還可以通過XMLBeans和Castor等來實(shí)現(xiàn)同樣的功能。

          sunyfun 2007-04-01 11:39
          JDK6的新特性之三:理解StAX
          JDK6的新特性之三:理解StAX
          StAX(JSR 173)是JDK6.0中除了DOM和SAX之外的又一種處理XML文檔的API

          StAX的來歷

          在JAXP1.3(JSR 206)有兩種處理XML文檔的方法:DOM(Document Object Model)和SAX(Simple API for XML).由于JDK6.0中的JAXB2(JSR 222)和JAX-WS 2.0(JSR 224)都會(huì)用到StAX所以Sun決定把StAX加入到JAXP家族當(dāng)中來,并將JAXP的版本升級(jí)到1.4(JAXP1.4是JAXP1.3的維護(hù)版本). JDK6里面JAXP的版本就是1.4.

          StAX簡(jiǎn)介

          StAX是The Streaming API for XML的縮寫,一種利用拉模式解析(pull-parsing)XML文檔的API.StAX通過提供一種基于事件迭代器(Iterator)的API讓程序員去控制xml文檔解析過程,程序遍歷這個(gè)事件迭代器去處理每一個(gè)解析事件,解析事件可以看做是程序拉出來的,也就是程序促使解析器產(chǎn)生一個(gè)解析事件然后處理該事件,之后又促使解析器產(chǎn)生下一個(gè)解析事件,如此循環(huán)直到碰到文檔結(jié)束符;SAX也是基于事件處理xml文檔,但卻是用推模式解析,解析器解析完整個(gè)xml文檔后,才產(chǎn)生解析事件,然后推給程序去處理這些事件;DOM采用的方式是將整個(gè)xml文檔映射到一顆內(nèi)存樹,這樣就可以很容易地得到父節(jié)點(diǎn)和子結(jié)點(diǎn)以及兄弟節(jié)點(diǎn)的數(shù)據(jù),但如果文檔很大,將會(huì)嚴(yán)重影響性能。下面是這幾種API的比較(轉(zhuǎn)載自http://www.aygfsteel.com/hsith/archive/2006/06/29/55817.html)

          XML Parser API Feature Summary Feature StAX SAX DOM TrAX
          API Type Pull, streaming Push, streaming In memory tree XSLT Rule
          Ease of Use High Medium High Medium
          XPath Capability No No Yes Yes
          CPU and Memory Efficiency Good Good Varies Varies
          Forward Only Yes Yes No No
          Read XML Yes Yes Yes Yes
          Write XML Yes No Yes Yes
          Create, Read, Update, Delete No No Yes No


          StAX代碼演示

          下面代碼演示了如何通過StAX讀取xml文檔和生成xml文檔

          public class StaxTester {
            public static void main(String[] args) throws XMLStreamException, FileNotFoundException {
              readXMLByStAX();//用XMLEventReader解析xml文檔
              writeXMLByStAX();//用XMLStreamWriter寫xml文檔
            }

            private static void readXMLByStAX() throws XMLStreamException, FileNotFoundException {
              XMLInputFactory xmlif = XMLInputFactory.newInstance();
              XMLEventReader xmler = xmlif.createXMLEventReader(StaxTester.class.getResourceAsStream("test.xml"));
              XMLEvent event;
              StringBuffer parsingResult = new StringBuffer();
              while (xmler.hasNext()) {
                  event = xmler.nextEvent();        
                  if (event.isStartElement()) { //如果解析的是起始標(biāo)記
                    StartElement se = event.asStartElement();
                    parsingResult.append("<");
                    parsingResult.append(se.getName());
                    if(se.getName().getLocalPart().equals("catalog")) {
                      parsingResult.append(" id=\"");
                      parsingResult.append(se.getAttributeByName(new QName("id")).getValue());
                      parsingResult.append("\"");
                    }
                    parsingResult.append(">");
                  } else if (event.isCharacters()) { //如果解析的是文本內(nèi)容
                    parsingResult.append(event.asCharacters().getData());
                  } else if(event.isEndElement()){ //如果解析的是結(jié)束標(biāo)記
                    parsingResult.append("</");
                    parsingResult.append(event.asEndElement().getName());
                    parsingResult.append(">");
                  }
              }
              System.out.println(parsingResult);
            }

            private static void writeXMLByStAX() throws XMLStreamException, FileNotFoundException {
              XMLOutputFactory xmlof = XMLOutputFactory.newInstance();
              XMLStreamWriter xmlw = xmlof.createXMLStreamWriter(new FileOutputStream("output.xml"));

              // 寫入默認(rèn)的 XML 聲明到xml文檔
              xmlw.writeStartDocument();
              xmlw.writeCharacters("\n");
              // 寫入注釋到xml文檔
              xmlw.writeComment("testing comment");
              xmlw.writeCharacters("\n");
              // 寫入一個(gè)catalogs根元素
              xmlw.writeStartElement("catalogs");
              xmlw.writeNamespace("myNS", "http://blog.csdn.net/Chinajash");
              xmlw.writeAttribute("owner","Chinajash");
              xmlw.writeCharacters("\n");
              // 寫入子元素catalog
              xmlw.writeStartElement("http://blog.csdn.net/Chinajash", "catalog");
              xmlw.writeAttribute("id","007");
              xmlw.writeCharacters("Apparel");
              // 寫入catalog元素的結(jié)束標(biāo)簽
              xmlw.writeEndElement();
              // 寫入catalogs元素的結(jié)束標(biāo)簽
              xmlw.writeEndElement();
              // 結(jié)束 XML 文檔
              xmlw.writeEndDocument();    
              xmlw.close();
            }
          }

          test.xml文件內(nèi)容如下:

          <?xml version="1.0" encoding="UTF-8"?>
          <catalogs>
            <catalog id="001">Book</catalog>
            <catalog id="002">Video</catalog>
          </catalogs>

          運(yùn)行上面程序后,控制臺(tái)輸出如下:

          <catalogs>
            <catalog id="001">Book</catalog>
            <catalog id="002">Video</catalog>
          </catalogs>

          運(yùn)行上面程序后,產(chǎn)生的output.xml文件如下:

          <?xml version="1.0" ?>
          <!-- testing comment-->
          <catalogs xmlns:myNS="http://blog.csdn.net/Chinajash" owner="Chinajash">
            <myNS:catalog id="007">Apparel</myNS:catalog>
          </catalogs>

          sunyfun 2007-04-01 11:39
          JDK6的新特性之四:使用Compiler API
          JDK6的新特性之四:使用Compiler API
          現(xiàn)在我們可以用JDK6 的Compiler API(JSR 199)去動(dòng)態(tài)編譯Java源文件,Compiler API結(jié)合反射功能就可以實(shí)現(xiàn)動(dòng)態(tài)的產(chǎn)生Java代碼并編譯執(zhí)行這些代碼,有點(diǎn)動(dòng)態(tài)語(yǔ)言的特征。這個(gè)特性對(duì)于某些需要用到動(dòng)態(tài)編譯的應(yīng)用程序相當(dāng)有用, 比如JSP Web Server,當(dāng)我們手動(dòng)修改JSP后,是不希望需要重啟Web Server才可以看到效果的,這時(shí)候我們就可以用Compiler API來實(shí)現(xiàn)動(dòng)態(tài)編譯JSP文件,當(dāng)然,現(xiàn)在的JSP Web Server也是支持JSP熱部署的,現(xiàn)在的JSP Web Server通過在運(yùn)行期間通過Runtime.exec或ProcessBuilder來調(diào)用javac來編譯代碼,這種方式需要我們產(chǎn)生另一個(gè)進(jìn)程去做編譯工作,不夠優(yōu)雅而且容易使代碼依賴與特定的操作系統(tǒng);Compiler API通過一套易用的標(biāo)準(zhǔn)的API提供了更加豐富的方式去做動(dòng)態(tài)編譯,而且是跨平臺(tái)的。 下面代碼演示了Compiler API的使用

          public class CompilerAPITester {
            private static String JAVA_SOURCE_FILE = "DynamicObject.java";
            private static String JAVA_CLASS_FILE = "DynamicObject.class";
            private static String JAVA_CLASS_NAME = "DynamicObject";
            public static void main(String[] args) {
              JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
              StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
              generateJavaClass();
              try {
                  //將產(chǎn)生的類文件拷貝到程序的ClassPath下面,下面這一行代碼是特定于Windows+I(xiàn)ntelliJ IDEA 6.0項(xiàng)目,不具有移植性
                  Runtime.getRuntime().exec("cmd /c copy "+JAVA_CLASS_FILE+" classes\\production\\JDK6Features");
                  Iterable<? extends JavaFileObject> sourcefiles = fileManager.getJavaFileObjects(JAVA_SOURCE_FILE);
                  compiler.getTask(null, fileManager, null, null, null, sourcefiles).call();
                  fileManager.close();
                  Class.forName(JAVA_CLASS_NAME).newInstance();//創(chuàng)建動(dòng)態(tài)編譯得到的DynamicObject類的實(shí)例
              } catch (Exception ex) {
                  ex.printStackTrace();
              }
            }

            public static void generateJavaClass(){
              try {
                  FileWriter fw = new FileWriter(JAVA_SOURCE_FILE);
                  BufferedWriter bw = new BufferedWriter(fw);
                  bw.write("public class "+JAVA_CLASS_NAME+"{");
                  bw.newLine();
                  bw.write("public "+JAVA_CLASS_NAME+"(){System.out.println(\"In the constructor of DynamicObject\");}}");
                  bw.flush();
                  bw.close();
              } catch (IOException ex) {
                  ex.printStackTrace();
              }
            }
          }

          程序運(yùn)行后,會(huì)產(chǎn)生DynamicObject.java和DynamicObject.class兩個(gè)文件,并在控制臺(tái)輸出

          In the constructor of DynamicObject

          sunyfun 2007-04-01 11:40
          JDK6的新特性之五:輕量級(jí)Http Server

          JDK6的新特性之五:輕量級(jí)Http Server
          JDK6提供了一個(gè)簡(jiǎn)單的Http Server API,據(jù)此我們可以構(gòu)建自己的嵌入式Http Server,它支持Http和Https協(xié)議,提供了HTTP1.1的部分實(shí)現(xiàn),沒有被實(shí)現(xiàn)的那部分可以通過擴(kuò)展已有的Http Server API來實(shí)現(xiàn),程序員必須自己實(shí)現(xiàn)HttpHandler接口,HttpServer會(huì)調(diào)用HttpHandler實(shí)現(xiàn)類的回調(diào)方法來處理客戶端請(qǐng)求,在這里,我們把一個(gè)Http請(qǐng)求和它的響應(yīng)稱為一個(gè)交換,包裝成HttpExchange類,HttpServer負(fù)責(zé)將HttpExchange傳給HttpHandler實(shí)現(xiàn)類的回調(diào)方法.下面代碼演示了怎樣創(chuàng)建自己的Http Server

          /**
          * Created by IntelliJ IDEA.
          * User: Chinajash
          * Date: Dec 30, 2006
          */
          public class HTTPServerAPITester {
            public static void main(String[] args) {
              try {
                  HttpServer hs = HttpServer.create(new InetSocketAddress(8888),0);//設(shè)置HttpServer的端口為8888
                  hs.createContext("/chinajash", new MyHandler());//用MyHandler類內(nèi)處理到/chinajash的請(qǐng)求
                  hs.setExecutor(null); // creates a default executor
                  hs.start();
              } catch (IOException e) {
                  e.printStackTrace();
              }
            }
          }

          class MyHandler implements HttpHandler {
          public void handle(HttpExchange t) throws IOException {
              InputStream is = t.getRequestBody();
              String response = "<***>Happy New Year 2007!--Chinajash</***>";
              t.sendResponseHeaders(200, response.length());
              OutputStream os = t.getResponseBody();
              os.write(response.getBytes());
              os.close();
          }
          }

          運(yùn)行程序后,在瀏覽器內(nèi)輸入http://localhost:8888/chinajash,瀏覽器輸出

          Happy New Year 2007!--Chinajash

          sunyfun 2007-04-01 11:40
          JDK6的新特性之六:插入式注解處理API
          JDK6的新特性之六:插入式注解處理API(Pluggable Annotation Processing API)

          插入式注解處理API(JSR 269)提供一套標(biāo)準(zhǔn)API來處理Annotations(JSR 175),實(shí)際上JSR 269不僅僅用來處理Annotation,我覺得更強(qiáng)大的功能是它建立了Java 語(yǔ)言本身的一個(gè)模型,它把method, package, constructor, type, variable, enum, annotation等Java語(yǔ)言元素映射為Types和Elements(兩者有什么區(qū)別?), 從而將Java語(yǔ)言的語(yǔ)義映射成為對(duì)象, 我們可以在javax.lang.model包下面可以看到這些類. 所以我們可以利用JSR 269提供的API來構(gòu)建一個(gè)功能豐富的元編程(metaprogramming)環(huán)境. JSR 269用Annotation Processor在編譯期間而不是運(yùn)行期間處理Annotation, Annotation Processor相當(dāng)于編譯器的一個(gè)插件,所以稱為插入式注解處理.如果Annotation Processor處理Annotation時(shí)(執(zhí)行process方法)產(chǎn)生了新的Java代碼,編譯器會(huì)再調(diào)用一次Annotation Processor,如果第二次處理還有新代碼產(chǎn)生,就會(huì)接著調(diào)用Annotation Processor,直到?jīng)]有新代碼產(chǎn)生為止.每執(zhí)行一次process()方法被稱為一個(gè)"round",這樣整個(gè)Annotation processing過程可以看作是一個(gè)round的序列. JSR 269主要被設(shè)計(jì)成為針對(duì)Tools或者容器的API. 舉個(gè)例子,我們想建立一套基于Annotation的單元測(cè)試框架(如TestNG),在測(cè)試類里面用Annotation來標(biāo)識(shí)測(cè)試期間需要執(zhí)行的測(cè)試方法,如下所示:

          @TestMethod
          public void testCheckName(){
              //do something here
          }

          這時(shí)我們就可以用JSR 269提供的API來處理測(cè)試類,根據(jù)Annotation提取出需要執(zhí)行的測(cè)試方法.

          另一個(gè)例子是如果我們出于某種原因需要自行開發(fā)一個(gè)符合Java EE 5.0的Application Server(當(dāng)然不建議這樣做),我們就必須處理Common Annotations(JSR 250),Web Services Metadata(JSR 181)等規(guī)范的Annotations,這時(shí)可以用JSR 269提供的API來處理這些Annotations. 在現(xiàn)在的開發(fā)工具里面,Eclipse 3.3承諾將支持JSR 269

          下面我用代碼演示如何來用JSR 269提供的API來處理Annotations和讀取Java源文件的元數(shù)據(jù)(metadata)

          /**
          * Created by IntelliJ IDEA.
          * User: Chinajash
          * Date: Dec 31, 2006
          */
          @SupportedAnnotationTypes("PluggableAPT.ToBeTested")//可以用"*"表示支持所有Annotations
          @SupportedSourceVersion(SourceVersion.RELEASE_6)
          public class MyAnnotationProcessor extends AbstractProcessor {
            private void note(String msg) {
              processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg);
            }
            public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
              //annotations的值是通過@SupportedAnnotationTypes聲明的且目標(biāo)源代碼擁有的所有Annotations
              for(TypeElement te:annotations){
                  note("annotation:"+te.toString());
              }
              Set<? extends Element> elements = roundEnv.getRootElements();//獲取源代碼的映射對(duì)象
              for(Element e:elements){
                  //獲取源代碼對(duì)象的成員
                  List<? extends Element> enclosedElems = e.getEnclosedElements();
                  //留下方法成員,過濾掉其他成員
                  List<? extends ExecutableElement> ees = ElementFilter.methodsIn(enclosedElems);
                  for(ExecutableElement ee:ees){
                    note("--ExecutableElement name is "+ee.getSimpleName());
                    List<? extends AnnotationMirror> as = ee.getAnnotationMirrors();//獲取方法的Annotations
                    note("--as="+as);
                    for(AnnotationMirror am:as){
                      //獲取Annotation的值
                      Map<? extends ExecutableElement, ? extends AnnotationValue> map= am.getElementValues();
                      Set<? extends ExecutableElement> ks = map.keySet();
                      for(ExecutableElement k:ks){//打印Annotation的每個(gè)值
                          AnnotationValue av = map.get(k);
                          note("----"+ee.getSimpleName()+"."+k.getSimpleName()+"="+av.getValue());
                      }
                    }
                  }
              }
              return false;
            }
          }

          @Retention(RetentionPolicy.RUNTIME)
          @Target(ElementType.METHOD)
          @interface ToBeTested{
            String owner() default "Chinajash";
            String group();
          }

          編譯以上代碼,然后再創(chuàng)建下面的Testing對(duì)象,不要編譯Testing對(duì)象,我在后面會(huì)編譯它

          public class Testing{  
            @ToBeTested(group="A")
            public void m1(){
            }
            @ToBeTested(group="B",owner="QQ")
            public void m2(){
            }  
            @PostConstruct//Common Annotation里面的一個(gè)Annotation
            public void m3(){
            }  
          }

          下面我用以下命令編譯Testing對(duì)象

          javac -XprintRounds -processor PluggableAPT.MyAnnotationProcessor Testing.java

          -XprintRounds表示打印round的次數(shù),運(yùn)行上面命令后在控制臺(tái)會(huì)看到如下輸出:

          Round 1:
              input files: {PluggableAPT.Testing}
              annotations: [PluggableAPT.ToBeTested, javax.annotation.PostConstruct]
              last round: false
          Note: annotation:PluggableAPT.ToBeTested
          Note: --ExecutableElement name is m1
          Note: --as=@PluggableAPT.ToBeTested(group="A")
          Note: ----m1.group=A
          Note: --ExecutableElement name is m2
          Note: --as=@PluggableAPT.ToBeTested(group="B", owner="QQ")
          Note: ----m2.group=B
          Note: ----m2.owner=QQ
          Note: --ExecutableElement name is m3
          Note: --as=@javax.annotation.PostConstruct
          Round 2:
              input files: {}
              annotations: []
              last round: true

          本來想用JDK6.0的Compiler API來執(zhí)行上面編譯命令,可是好像現(xiàn)在Compiler API還不支持-processor參數(shù),運(yùn)行時(shí)總報(bào)以下錯(cuò)誤

          Exception in thread "main" java.lang.IllegalArgumentException: invalid flag: -processor PluggableAPT.MyAnnotationProcessor

          調(diào)用Compiler API的代碼是這樣的

          JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
          StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
          Iterable<? extends JavaFileObject> sourcefiles = fileManager.getJavaFileObjects("Testing.java");
          Set<String> options = new HashSet<String>();
          options.add("-processor PluggableAPT.MyAnnotationProcessor");
          compiler.getTask(null, fileManager, null, options, null, sourcefiles).call();

          不知道這是不是Compiler API的一個(gè)bug.

          sunyfun 2007-04-01 11:41
          JDK6的新特性之七:用Console開發(fā)控制臺(tái)程序
          JDK6的新特性之七:用Console開發(fā)控制臺(tái)程序

          JDK6中提供了java.io.Console類專用來訪問基于字符的控制臺(tái)設(shè)備. 你的程序如果要與Windows下的cmd或者Linux下的Terminal交互,就可以用Console類代勞. 但我們不總是能得到可用的Console, 一個(gè)JVM是否有可用的Console依賴于底層平臺(tái)和JVM如何被調(diào)用. 如果JVM是在交互式命令行(比如Windows的cmd)中啟動(dòng)的,并且輸入輸出沒有重定向到另外的地方,那么就可以得到一個(gè)可用的Console實(shí)例. 下面代碼演示了Console類的用法:

          /**
          * @author chinajash
          */
          public class ConsoleTest {
           
            public static void main(String[] args) {
              Console console = System.console();//獲得Console實(shí)例
              if(console!=null){//判斷console是否可用
                  String user = new String(console.readLine("Enter user:")); //讀取整行字符
                  String pwd = new String(console.readPassword("Enter passowrd:")); //讀取密碼,密碼輸入時(shí)不會(huì)顯示
                  console.printf("User is:"+user+"\n");
                  console.printf("Password is:"+pwd+"\n");
              }else{
                  System.out.println("Console is unavailable");
              }
            }
          }

          如果在NetBean5.5里面運(yùn)行上面程序,會(huì)輸出

          Console is unavailable

          表示Console不可獲得,那是因?yàn)镴VM不是在命令行中被調(diào)用的或者輸入輸出被重定向了. 但是如果我們?cè)诿钚兄羞\(yùn)行上面程序(java ConsoleTest),程序能夠獲得Console實(shí)例,并執(zhí)行如下:

          Enter user:chinajash
          Enter passowrd:
          User is:chinajash
          Password is:chinajash

          在這里可以看到輸入密碼時(shí),控制臺(tái)時(shí)不顯示這些密碼字符的,但是程序可以得到輸入的密碼字符串,這與Linux下面輸入密碼的情況是一樣的

          sunyfun 2007-04-01 11:41
          JDK6.0新特性之八:用Console開發(fā)控制臺(tái)程序
          JDK6中提供了java.io.Console類專用來訪問基于字符的控制臺(tái)設(shè)備. 你的程序如果要與Windows下的cmd或者Linux下的Terminal交互,就可以用Console類代勞. 但我們不總是能得到可用的Console, 一個(gè)JVM是否有可用的Console依賴于底層平臺(tái)和JVM如何被調(diào)用. 如果JVM是在交互式命令行(比如Windows的cmd)中啟動(dòng)的,并且輸入輸出沒有重定向到另外的地方,那么就可以得到一個(gè)可用的Console實(shí)例. 下面代碼演示了Console類的用法:

          /**
          * @author chinajash
          */
          public class ConsoleTest {
           public static void main(String[] args) {
            Console console = System.console();//獲得Console實(shí)例
            if(console!=null){//判斷console是否可用
             String user = new String(console.readLine("Enter user:")); //讀取整行字符
             String pwd = new String(console.readPassword("Enter passowrd:")); //讀取密碼,密碼輸入時(shí)不會(huì)顯示
             console.printf("User is:"+user+"\n");
             console.printf("Password is:"+pwd+"\n");
            }else{
             System.out.println("Console is unavailable");
            }
           }
          }
          如果在NetBean5.5里面運(yùn)行上面程序,會(huì)輸出

            Console is unavailable

            表示Console不可獲得,那是因?yàn)镴VM不是在命令行中被調(diào)用的或者輸入輸出被重定向了. 但是如果我們?cè)诿钚兄羞\(yùn)行上面程序(java ConsoleTest),程序能夠獲得Console實(shí)例,并執(zhí)行如下:
          Enter user:chinajash
          Enter passowrd:
          User is:chinajash
          Password is:chinajash
          在這里可以看到輸入密碼時(shí),控制臺(tái)時(shí)不顯示這些密碼字符的,但是程序可以得到輸入的密碼字符串,這與Linux下面輸入密碼的情況是一樣的。

          sunyfun 2007-04-01 11:42
          JDK6的新特性之九:Common Annotations
          JDK6的新特性之九:Common Annotations

          Common annotations原本是Java EE 5.0(JSR 244)規(guī)范的一部分,現(xiàn)在SUN把它的一部分放到了Java SE 6.0中.隨著Annotation元數(shù)據(jù)功能(JSR 175)加入到Java SE 5.0里面,很多Java 技術(shù)(比如EJB,Web Services)都會(huì)用Annotation部分代替XML文件來配置運(yùn)行參數(shù)(或者說是支持聲明式編程,如EJB的聲明式事務(wù)), 如果這些技術(shù)為通用目的都單獨(dú)定義了自己的Annotations,顯然有點(diǎn)重復(fù)建設(shè), 所以,為其他相關(guān)的Java技術(shù)定義一套公共的Annotation是有價(jià)值的,可以避免重復(fù)建設(shè)的同時(shí),也保證Java SE和Java EE 各種技術(shù)的一致性.下面列舉出Common Annotations 1.0里面的10個(gè)Annotations

          Common Annotations
          Annotation Retention Target Description
          Generated Source ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE 用于標(biāo)注生成的源代碼
          Resource Runtime TYPE, METHOD, FIELD 用于標(biāo)注所依賴的資源,容器據(jù)此注入外部資源依賴,有基于字段的注入和基于setter方法的注入兩種方式
          Resources Runtime TYPE 同時(shí)標(biāo)注多個(gè)外部依賴,容器會(huì)把所有這些外部依賴注入
          PostConstruct Runtime METHOD 標(biāo)注當(dāng)容器注入所有依賴之后運(yùn)行的方法,用來進(jìn)行依賴注入后的初始化工作,只有一個(gè)方法可以標(biāo)注為PostConstruct
          PreDestroy Runtime METHOD 當(dāng)對(duì)象實(shí)例將要被從容器當(dāng)中刪掉之前,要執(zhí)行的回調(diào)方法要標(biāo)注為PreDestroy
          RunAs Runtime TYPE 用于標(biāo)注用什么安全角色來執(zhí)行被標(biāo)注類的方法,這個(gè)安全角色必須和Container 的Security角色一致的
          RolesAllowed Runtime TYPE, METHOD 用于標(biāo)注允許執(zhí)行被標(biāo)注類或方法的安全角色,這個(gè)安全角色必須和Container 的Security角色一致的
          PermitAll Runtime TYPE, METHOD 允許所有角色執(zhí)行被標(biāo)注的類或方法
          DenyAll Runtime TYPE, METHOD 不允許任何角色執(zhí)行被標(biāo)注的類或方法,表明該類或方法不能在Java EE容器里面運(yùn)行
          DeclareRoles Runtime TYPE 用來定義可以被應(yīng)用程序檢驗(yàn)的安全角色,通常用isUserInRole來檢驗(yàn)安全角色


          注意:

          1.RolesAllowed,PermitAll,DenyAll不能同時(shí)應(yīng)用到一個(gè)類或方法上

          2.標(biāo)注在方法上的RolesAllowed,PermitAll,DenyAll會(huì)覆蓋標(biāo)注在類上的RolesAllowed,PermitAll,DenyAll

          3.RunAs,RolesAllowed,PermitAll,DenyAll和DeclareRoles還沒有加到Java SE 6.0上來

          4.處理以上Annotations的工作是由Java EE容器來做, Java SE 6.0只是包含了上面表格的前五種Annotations的定義類,并沒有包含處理這些Annotations的引擎,這個(gè)工作可以由Pluggable Annotation Processing API(JSR 269)來做

          sunyfun 2007-04-01 11:42
          JDK6的新特性之十:Web服務(wù)元數(shù)據(jù)(Web Services metadata)

          JDK6的新特性之十:Web服務(wù)元數(shù)據(jù)(Web Services metadata)

          .Net的Web Services元數(shù)據(jù)
          早在.Net Framework 1.0中,微軟就用元數(shù)據(jù)功能(.net的attribute特性)來標(biāo)注要暴露成Web Service的方法,下面是用C#演示的利用.net的元數(shù)據(jù)功能暴露Web Service方法的代碼片斷.
          public class TestWS{
            [WebMethod]
            public String sayHi(){
                return "Hi!";
            }  
            public int add(int d1,int d2){
                return d1+d2;
            }
          }
          上面的[WebMethod]是加在方法sayHi上面的元數(shù)據(jù),用來告訴Web Services引擎(一般是ASP.NET Runtime), 我這個(gè)方法需要暴露為一個(gè)Web Service,你需要幫我生成相應(yīng)的WSDL描述及相關(guān)支持文件.而另一個(gè)方法add沒有加這個(gè)元數(shù)據(jù),所以Web Services引擎就不會(huì)為該方法生成WSDL及相關(guān)支持文件

          Java的Web Services元數(shù)據(jù)
          Java 里的Web服務(wù)元數(shù)據(jù)跟微軟的方案基本沒有語(yǔ)義上的區(qū)別,自從JDK5添加了元數(shù)據(jù)功能(Annotation)之后,SUN幾乎重構(gòu)了整個(gè)J2EE體 系, 由于變化很大,干脆將名字也重構(gòu)為Java EE, Java EE(當(dāng)前版本為5.0)將元數(shù)據(jù)納入很多規(guī)范當(dāng)中,這其中就包括Web Services的相關(guān)規(guī)范, 加入元數(shù)據(jù)之后的Web Services服務(wù)器端編程模型就跟上面看到的C#片斷差不多了, 這顯然比以前的JAX-RPC編程模型簡(jiǎn)單(當(dāng)然, Axis的編程模型也很簡(jiǎn)單).這里要談的Web服務(wù)元數(shù)據(jù)(JSR 181)只是Java Web 服務(wù)規(guī)范中的一個(gè),它跟Common Annotations, JAXB2, StAX, SAAJ和JAX-WS等共同構(gòu)成Java EE 5的Web Services技術(shù)堆棧.

          JSR-181的元數(shù)據(jù)清單
          下面介紹JSR-181里面各個(gè)元數(shù)據(jù)的相關(guān)參數(shù)及用途
          Annotation Retention Target Description
          WebService Runtime Type
          標(biāo)注要暴露為Web Services的類或接口
          WebParam Runtime Parameter 自定義服務(wù)方法參數(shù)到WSDL的映射
          WebResult Runtime Method 自定義服務(wù)方法返回值到WSDL的映射
          WebMethod Runtime Method 自定義單個(gè)服務(wù)方法到WSDL的映射
          Oneway Runtime Method 必須與@WebMethod連用,表明被標(biāo)注方法只有輸入沒有輸出,這就要求被標(biāo)注方法不能有返回值,也不能聲明checked exception

          HandlerChain Runtime Type,Method,Field 將Web服務(wù)與外部Handler chain關(guān)聯(lián)起來
          SOAPBinding Runtime Type,Method 自定義SOAPBinding

          JSR-181元數(shù)據(jù)使用示例

          package WebServices;

          import java.io.File;
          import java.io.IOException;
          import javax.jws.Oneway;
          import javax.jws.WebMethod;
          import javax.jws.WebParam;
          import javax.jws.WebResult;
          import javax.jws.WebService;
          import javax.xml.ws.Endpoint;

          /**
          * @author chinajash
          */
          @WebService(targetNamespace="http://blog.csdn.net/chinajash",serviceName="HelloService")
          public class WSProvider {
            @WebResult(name="Greetings")//自定義該方法返回值在WSDL中相關(guān)的描述  
            @WebMethod
            public String sayHi(@WebParam(name="MyName") String name){
              return "Hi,"+name; //@WebParam是自定義參數(shù)name在WSDL中相關(guān)的描述
            }  
            @Oneway //表明該服務(wù)方法是單向的,既沒有返回值,也不應(yīng)該聲明檢查異常
            @WebMethod(action="printSystemTime",operationName="printSystemTime")//自定義該方法在WSDL中相關(guān)的描述
            public void printTime(){
              System.out.println(System.currentTimeMillis());
            }
            public static void main(String[] args) {
              Thread wsPublisher = new Thread(new WSPublisher());
              wsPublisher.start();
            }  
            private static class WSPublisher implements Runnable{
              public void run() {
                  //發(fā)布WSProvider到http://localhost:8888/chinajash/WSProvider這個(gè)地址,之前必須調(diào)用wsgen命令
                  //生成服務(wù)類WSProvider的支持類,命令如下:
                  //wsgen -cp . WebServices.WSProvider
                  Endpoint.publish("http://localhost:8888/chinajash/WSProvider",new WSProvider());
              }    
            }
          }

          如果想看到Web Services Engine生成的WSDL文件是否遵守上面的元數(shù)據(jù), 我們沒有必要將上面的WSProvider部署到支持JSR-181的應(yīng)用服務(wù)器或Servlet形式的Web Services Engine,現(xiàn)在JDK6已經(jīng)提供了一個(gè)很簡(jiǎn)單的機(jī)制可以用來測(cè)試和發(fā)布Web Services,下面講講如何在JDK6環(huán)境下發(fā)布Web Services和查看生成的WSDL
          1.將<JDK_HOME>/bin加入path環(huán)境變量
          2.在命令行下切換當(dāng)前目錄到WSProvider的class文件所在的目錄,運(yùn)行下面命令
          wsgen -cp . WebServices.WSProvider
          在這個(gè)例子中會(huì)生成以下3個(gè)類的源代碼文件及class文件
          SayHi
          SayHiResponse
          PrintTime
          3.執(zhí)行如下代碼發(fā)布WSProvider到http://localhost:8888/chinajash/WSProvider,在這里可以執(zhí)行WSProvider類的main方法就可以
          Endpoint.publish("http://localhost:8888/chinajash/WSProvider",new WSProvider());
          4.在瀏覽器輸入http://localhost:8888/chinajash/WSProvider?wsdl就可以看到生成的WSDL文件,為了節(jié)省篇幅,這里就不把生成的WSDL文件貼上了,大家可以自己動(dòng)手試試

          sunyfun 2007-04-01 11:42
          JDK6的新特性之十一:更簡(jiǎn)單,更強(qiáng)大的JAX-WS

          JDK6的新特性之十一:更簡(jiǎn)單,更強(qiáng)大的JAX-WS

          JAX-WS2.0的來歷

          --------------------------------------------------------------------------------
          JAX-WS(JSR-224) 是Java Architecture for XML Web Services的縮寫,簡(jiǎn)單說就是一種用Java和XML開發(fā)Web Services應(yīng)用程序的框架, 目前版本是2.0, 它是JAX-RPC 1.1的后續(xù)版本, J2EE 1.4帶的就是JAX-RPC1.1, 而Java EE 5里面包括了JAX-WS 2.0,但為了向后兼容,仍然支持JAX-RPC. 現(xiàn)在,SUN又把JAX-WS直接放到了Java SE 6里面,由于JAX-WS會(huì)用到Common Annotation(JSR 250),Java Web Services Metadata(JSR 181), JAXB2(JSR 222), StAX(JSR 173), 所以SUN也必須把后幾個(gè)原屬于Java EE范疇的Components下放到Java SE, 現(xiàn)在我們可以清楚地理解了為什么Sun要把這些看似跟Java SE沒有關(guān)系的Components放進(jìn)來,終極目的就是要在Java SE里面支持Web Services.

          JAX-WS2.0的架構(gòu)

          --------------------------------------------------------------------------------
          JAX-WS不是一個(gè)孤立的框架,它依賴于眾多其他的規(guī)范,本質(zhì)上它由以下幾部分組成
          1.用來開發(fā)Web Services的Java API
          2.用來處理Marshal/Unmarshal的XML Binding機(jī)制,JAX-WS2.0用JAXB2來處理Java Object與XML之間的映射,Marshalling就是把Java Object映射到XML,Unmarshalling則是把XML映射到Java Object.之所以要做Java Object與XML的映射,是因?yàn)樽罱K作為方法參數(shù)和返回值的Java Object要通過網(wǎng)絡(luò)傳輸協(xié)議(一般是SOAP)傳送,這就要求必須對(duì)Java Object做類似序列化和反序列化的工作,在SOAP中就是要用XML來表示Java object的內(nèi)部狀態(tài)
          3.眾多元數(shù)據(jù)(Annotations)會(huì)被JAX-WS用來描述Web Services的相關(guān)類,包括Common Annotations, Web Services Metadata, JAXB2的元數(shù)據(jù)和JAX-WS2.0規(guī)范自己的元數(shù)據(jù).
          4.Annotation Processing Tool(APT)是JAX-WS重要的組成部分,由于JAX-WS2.0規(guī)范用到很多元數(shù)據(jù),所以需要APT來處理眾多的Annotations.在<JDK_HOME>/bin下有兩個(gè)命令wsgen和wsimport,就是用到APT和Compiler API來處理碰到的Annotations,wsgen可以為Web Services Provider產(chǎn)生并編譯必要的幫助類和相關(guān)支持文件,wsimport以WSDL作為輸入為Web Service Consumer產(chǎn)生并編譯必要的幫助類和相關(guān)支持文件.
          5.JAX-WS還包括JAX-WS Runtime與應(yīng)用服務(wù)器和工具之間的契約關(guān)系

          JAX-WS2.0的編程模型

          --------------------------------------------------------------------------------
          現(xiàn)在用JAX-WS2.0來編寫Web Services非常簡(jiǎn)單,不像JAX-RPC,JAX-WS可以把任意POJO暴露為Web Services,服務(wù)類不需要實(shí)現(xiàn)接口,服務(wù)方法也沒有必要拋出RMI異常.下面介紹在JDK6環(huán)境下用JAX-WS2.0開發(fā)和測(cè)試Web Services的步驟
          1.編寫服務(wù)類,并用Web Services Metadata(JSR-181)標(biāo)注這個(gè)服務(wù)類,我用我的另一篇BlogJDK6的新特性之十:Web服務(wù)元數(shù)據(jù)中的WSProvider類作為服務(wù)類的例子,在此我重復(fù)貼一下WSProvider類的源代碼:
          /**
          * @author chinajash
          */
          @WebService(targetNamespace="http://blog.csdn.net/chinajash",serviceName="HelloService")
          public class WSProvider {
            @WebResult(name="Greetings")//自定義該方法返回值在WSDL中相關(guān)的描述  
            @WebMethod
            public String sayHi(@WebParam(name="MyName") String name){
              return "Hi,"+name; //@WebParam是自定義參數(shù)name在WSDL中相關(guān)的描述
            }  
            @Oneway //表明該服務(wù)方法是單向的,既沒有返回值,也不應(yīng)該聲明檢查異常
            @WebMethod(action="printSystemTime",operationName="printSystemTime")//自定義該方法在WSDL中相關(guān)的描述
            public void printTime(){
              System.out.println(System.currentTimeMillis());
            }
            public static void main(String[] args) {
              Thread wsPublisher = new Thread(new WSPublisher());
              wsPublisher.start();
            }  
            private static class WSPublisher implements Runnable{
              public void run() {
                  //發(fā)布WSProvider到http://localhost:8888/chinajash/WSProvider這個(gè)地址,之前必須調(diào)用wsgen命令
                  //生成服務(wù)類WSProvider的支持類,命令如下:
                  //wsgen -cp . WebServices.WSProvider
                  Endpoint.publish("http://localhost:8888/chinajash/WSProvider",new WSProvider());
              }    
            }
          }
          2.用wsgen生成上面服務(wù)類的必要的幫助類,然后調(diào)用用EndPoint類的靜態(tài)方法publish發(fā)布服務(wù)類(步驟請(qǐng)參考我的另一篇Blog JDK6的新特性之十:Web服務(wù)元數(shù)據(jù)),我在這里是將服務(wù)類發(fā)布到http://localhost:8888/chinajash/WSProvider
          3.用wsimport為服務(wù)消費(fèi)者(也就是服務(wù)的客戶端)生成必要的幫助類,命令如下:
          wsimport http://localhost:8888/chinajash/WSProvider?wsdl
          這會(huì)在<當(dāng)前目錄>\net\csdn\blog\chinajash下生成客戶端的幫助類,在這個(gè)例子中會(huì)生成7個(gè)類
          HelloService.class
          ObjectFactory.class
          package-info.class
          PrintSystemTime.class
          SayHi.class
          SayHiResponse.class
          WSProvider.class
          4.在客戶端用下面代碼即可調(diào)用步驟1定義的Web Service
          HelloService hs = new HelloService();
          WSProvider ws = hs.getWSProviderPort();
          System.out.println(ws.sayHi("chinajash"));
          ws.printSystemTime();
          調(diào)用上述代碼后客戶端控制臺(tái)輸出
          hi,chinajash
          服務(wù)端控制臺(tái)輸出服務(wù)器當(dāng)前系統(tǒng)時(shí)間

          sunyfun 2007-04-01 11:43
          JDK6的新特性之十二:腳本語(yǔ)言支持(Scripting)
          JDK6的新特性之十二:腳本語(yǔ)言支持(Scripting)

          概述

          --------------------------------------------------------------------------------
          JDK6增加了對(duì)腳本語(yǔ)言的支持(JSR 223),原理上是將腳本語(yǔ)言編譯成bytecode,這樣腳本語(yǔ)言也能享用Java平臺(tái)的諸多優(yōu)勢(shì),包括可移植性,安全等,另外,由于現(xiàn)在是編譯成bytecode后再執(zhí)行,所以比原來邊解釋邊執(zhí)行效率要高很多。加入對(duì)腳本語(yǔ)言的支持后,對(duì)Java語(yǔ)言也提供了以下好處。
          1、許多腳本語(yǔ)言都有動(dòng)態(tài)特性,比如,你不需要用一個(gè)變量之前先聲明它,你可以用一個(gè)變量存放完全不同類型的對(duì)象,你不需要做強(qiáng)制類型轉(zhuǎn)換,因?yàn)檗D(zhuǎn)換都是自動(dòng)的。現(xiàn)在Java語(yǔ)言也可以通過對(duì)腳本語(yǔ)言的支持間接獲得這種靈活性。
          2、 可以用腳本語(yǔ)言快速開發(fā)產(chǎn)品原型,因?yàn)楝F(xiàn)在可以Edit-Run,而無需Edit-Compile-Run,當(dāng)然,因?yàn)镴ava有非常好的IDE支持,我 們完全可以在IDE里面編輯源文件,然后點(diǎn)擊運(yùn)行(隱含編譯),以此達(dá)到快速開發(fā)原型的目的,所以這點(diǎn)好處基本上可以忽略。
          3、通過引入腳本語(yǔ)言可以輕松實(shí)現(xiàn)Java應(yīng)用程序的擴(kuò)展和自定義,我們可以把原來分布在在Java應(yīng)用程序中的配置邏輯,數(shù)學(xué)表達(dá)式和業(yè)務(wù)規(guī)則提取出來,轉(zhuǎn)用JavaScript來處理。

          Sun的JDK6實(shí)現(xiàn)包含了一個(gè)基于Mozilla Rhino的 腳本語(yǔ)言引擎,支持JavaScript,這并不是說明JDK6只支持JavaScript,任何第三方都可以自己實(shí)現(xiàn)一個(gè)JSR-223兼容的腳本引擎 使得JDK6支持別的腳本語(yǔ)言,比如,你想讓JDK6支持Ruby,那你可以自己按照J(rèn)SR 223的規(guī)范實(shí)現(xiàn)一個(gè)Ruby的腳本引擎類,具體一點(diǎn),你需要實(shí)現(xiàn)javax.script.ScriptEngine(簡(jiǎn)單起見,可以繼承javax.script.AbstractScriptEngine)和javax.script.ScriptEngineFactory兩個(gè)接口。當(dāng)然,在你實(shí)現(xiàn)自己的腳本語(yǔ)言引擎之前,先到scripting.dev.java.net project 這里看看是不是有人已經(jīng)幫你做了工作,這樣你就可以直接拿來用就行。

          Scripting API

          --------------------------------------------------------------------------------
          Scripting API是用于在Java里面編寫腳本語(yǔ)言程序的API, 在Javax.script中可以找到Scripting API,我們就是用這個(gè)API來編寫JavaScript程序,這個(gè)包里面有一個(gè)ScriptEngineManager類,它是使用Scripting API的入口,ScriptEngineManager可以通過jar服務(wù)發(fā)現(xiàn)(service discovery)機(jī)制尋找合適的腳本引擎類(ScriptEngine),使用Scripting API的最簡(jiǎn)單方式只需下面三步
          1、創(chuàng)建一個(gè)ScriptEngineManager對(duì)象
          2、通過ScriptEngineManager獲得ScriptEngine對(duì)象
          3、用ScriptEngine的eval方法執(zhí)行腳本

          下面是一個(gè)Hello World程序

          /** * @author chinajash */public class HelloScript {public static void main(String[] args) throws Exception {     ScriptEngineManager factory = new ScriptEngineManager();//step 1     ScriptEngine engine = factory.getEngineByName("JavaScript");//Step 2         engine.eval("print('Hello, Scripting')");//Step 3   }   }運(yùn)行上面程序,控制臺(tái)會(huì)輸出Hello, Scripting上面這個(gè)簡(jiǎn)單的Scripting程序演示了如何在Java里面運(yùn)行腳本語(yǔ)言,除此之外,我們還可以利用Scripting API實(shí)現(xiàn)以下功能1、暴露Java對(duì)象為腳本語(yǔ)言的全局變量2、在Java中調(diào)用腳本語(yǔ)言的方法3、腳本語(yǔ)言可以實(shí)現(xiàn)Java的接口4、腳本語(yǔ)言可以像Java一樣使用JDK平臺(tái)下的類下面的類演示了以上4種功能package Scripting;import java.io.File;import javax.script.Invocable;import javax.script.ScriptEngine;import javax.script.ScriptEngineManager;import javax.script.ScriptException;/** * @author chinajash */public class ScriptingAPITester {   public static void main(String[] args) throws Exception {     ScriptEngineManager manager = new ScriptEngineManager();     ScriptEngine engine = manager.getEngineByName("JavaScript");     testScriptVariables(engine);//演示如何暴露Java對(duì)象為腳本語(yǔ)言的全局變量     testInvokeScriptMethod(engine);//演示如何在Java中調(diào)用腳本語(yǔ)言的方法     testScriptInterface(engine);//演示腳本語(yǔ)言如何實(shí)現(xiàn)Java的接口     testUsingJDKClasses(engine);//演示腳本語(yǔ)言如何使用JDK平臺(tái)下的類   }     public static void testScriptVariables(ScriptEngine engine) throws ScriptException{     File file = new File("test.txt");     engine.put("f", file);     engine.eval("println('Total Space:'+f.getTotalSpace())");         }     public static void testInvokeScriptMethod(ScriptEngine engine) throws Exception{     String script = "function hello(name) { return 'Hello,' + name;}";     engine.eval(script);     Invocable inv = (Invocable) engine;     String res = (String)inv.invokeFunction("hello", "Scripting" );     System.out.println("res:"+res);   }     public static void testScriptInterface(ScriptEngine engine) throws ScriptException{     String script = "var obj = new Object(); obj.run = function() { println('run method called'); }";     engine.eval(script);     Object obj = engine.get("obj");     Invocable inv = (Invocable) engine;     Runnable r = inv.getInterface(obj,Runnable.class);     Thread th = new Thread(r);     th.start();   }     public static void testUsingJDKClasses(ScriptEngine engine) throws Exception{     //Packages是腳本語(yǔ)言里的一個(gè)全局變量,專用于訪問JDK的package     String js = "function doSwing(t){var f=new Packages.javax.swing.JFrame(t);f.setSize(400,300);f.setVisible(true);}";     engine.eval(js);     Invocable inv = (Invocable) engine;     inv.invokeFunction("doSwing", "Scripting Swing" );   }}Scripting Tool

          --------------------------------------------------------------------------------
          SUN提供的JDK6中有一個(gè)命令行工具??jrunscript,你可以在<JDK6_Home>/bin下面找到這個(gè)工具,jrunscript是一個(gè)腳本語(yǔ)言的解釋程序,它獨(dú)立于腳本語(yǔ)言,但默認(rèn)是用JavaScript,我們可以用jrunscript來測(cè)試自己寫的腳本語(yǔ)言是否正確,下面是一個(gè)在命令行運(yùn)行jrunscript的簡(jiǎn)單例子
          jrunscript
          js>println("Hello,JrunScript");
          Hello,JrunScript
          js>9*8
          72.0
          js>

          sunyfun 2007-04-01 11:43
          JDK6的新特性之十三:JTable的排序和過濾

          JDK6的新特性之十三:JTable的排序和過濾

          原來的JTable基本上是只能顯示數(shù)據(jù),在JDK6新增了對(duì)JTable的排序和過濾功能,下面代碼演示了這兩個(gè)功能

          /**
          * @author chinajash
          */
          public class JTableTester {
            static String data[][] = {
              {"China","Beijing","Chinese"},
              {"America","Washington","English"},
              {"Korea","Seoul","Korean"},
              {"Japan","Tokyo","Japanese"},
              {"France","Paris","French"},
              {"England","London","English"},
              {"Germany","Berlin","German"},
            };
            static String titles[] = {"Country","Capital","Language"};
            public static void main(String[] args) {    
              DefaultTableModel m = new DefaultTableModel(data,titles);
              JTable t = new JTable(m);
              final TableRowSorter sorter = new TableRowSorter(m);
              t.setRowSorter(sorter); //為JTable設(shè)置排序器
             
              JScrollPane sPane = new JScrollPane();
              sPane.setViewportView(t);
             
              JPanel p = new JPanel();
              p.setLayout(new BoxLayout(p,BoxLayout.X_AXIS));
              JLabel l = new JLabel("Criteria:");
              final JTextField tf = new JTextField();
              JButton b = new JButton("Do Filter");
              p.add(l);
              p.add(tf);
              p.add(b);
              b.addActionListener(new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                    if(tf.getText().length()==0){
                      sorter.setRowFilter(null);
                    }else{
                      sorter.setRowFilter(RowFilter.regexFilter(tf.getText()));//為JTable設(shè)置基于正則表達(dá)式的過濾條件
                    }
                  }
              });
             
              JFrame f = new JFrame("JTable Sorting and Filtering");
              f.getContentPane().add(sPane,BorderLayout.CENTER);    
              f.getContentPane().add(p,BorderLayout.SOUTH);
              f.setSize(400,300);
              f.setVisible(true);
            }
          }
          運(yùn)行上面程序,單擊JTable的某一個(gè)title,這個(gè)title對(duì)應(yīng)的列就會(huì)按照升序/降序重新排列;在下面的Criteria文本框中輸入"ese",點(diǎn)擊"Do Filter"按鈕,JTable將只顯示帶有"ese"字符串的行,也就是China和Japan兩行,如果文本框里面什么都沒有,點(diǎn)擊"Do Filter"按鈕,這時(shí)JTable會(huì)顯示所有的行。

          sunyfun 2007-04-01 11:45
          JDK6新特性之Compiler
          創(chuàng)建Compiler.java和Hello.java
          1.Compiler.java

          import java.io.File;

          import javax.tools.JavaCompiler;
          import javax.tools.StandardJavaFileManager;
          import javax.tools.ToolProvider;

          public class Compiler {
            public static void main(String args[]) {
              try {
                JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
                StandardJavaFileManager sjfm = jc.getStandardFileManager(null, null, null);
             
                File javaFile = new File("Hello.java");

                Iterable fileObjects = sjfm.getJavaFileObjects(javaFile);
                jc.getTask(null, sjfm, null, null, null, fileObjects).call();
                // Add more compilation tasks
                sjfm.close();
              } catch (Exception e) {
                e.printStackTrace();
              }
            }
          }

          2.Hello.java

          import java.util.Date;
          public class Hello
          {
            public String getHelloWorld()
            {
              return "現(xiàn)在的時(shí)間為:"+new Date();
            }
          }


          編譯運(yùn)行即可,在工作目錄下你會(huì)發(fā)現(xiàn):Hello.class表示Compiler run OK.

          posted on 2007-05-24 11:47 liaojiyong 閱讀(3649) 評(píng)論(0)  編輯  收藏 所屬分類: Java

          主站蜘蛛池模板: 镇巴县| 米易县| 桃园市| 咸阳市| 清远市| 舒城县| 文化| 安平县| 安乡县| 华阴市| 宝坻区| 泗阳县| 启东市| 自贡市| 莫力| 黄梅县| 长白| 乐至县| 雷波县| 绵竹市| 莱州市| 濮阳县| 津市市| 龙岩市| 温宿县| 岳阳县| 温州市| 平凉市| 吉水县| 中阳县| 孝义市| 正阳县| 巴青县| 长宁区| 平武县| 东乡族自治县| 平江县| 师宗县| 无为县| 荔浦县| 镇康县|