java6 新特新

JAVA6新特性介紹java

 

1. 使用JAXB來實現對象與XML之間的映射

JAXB是Java Architecture for XML Binding的縮寫,能夠將一個Java對象轉變成爲XML格式,反之亦然。咱們把對象與關係數據庫之間的映射稱爲ORM, 其實也能夠把對象與XML之間的映射稱爲OXM(Object XML Mapping). 原來JAXB是JavaEE的一部分,在JDK6中,SUN將其放到了Java SE中,這也是SUN的一向作法。JDK6中自帶的這個JAXB版本是2.0, 比起1.0(JSR 31)來,JAXB2(JSR 222)用JDK5的新特性Annotation來標識要做綁定的類和屬性等,這就極大簡化了開發的工做量。實際上,在Java EE 5.0中,EJB和Web Services也經過Annotation 來簡化開發工做。另外,JAXB在底層是用STAX(JSR173)來處理XML文檔。程序員

下面用代碼演示在JDK6中如何來用JAXB數據庫

import java.io.FileReader;編程

import java.io.FileWriter;瀏覽器

import java.io.IOException;安全

import java.util.Calendar;服務器

 

import javax.xml.bind.JAXBContext;網絡

import javax.xml.bind.JAXBException;架構

import javax.xml.bind.Marshaller;app

import javax.xml.bind.Unmarshaller;

import javax.xml.bind.annotation.XmlAttribute;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlRootElement;

 

public class JAXB2Tester {

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

                   JAXBContext context = JAXBContext.newInstance(Person.class);

                   //下面代碼演示將對象轉變爲xml

                   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轉換爲對象

                   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是一個根元素

class Person {

         @XmlElement

         Calendar birthDay; //birthday將做爲person的子元素

         @XmlAttribute

         String name; //name將做爲person的的一個屬性

 

         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,因此該元素不會出如今輸出的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;

         }

}

運行該程序,咱們會獲得一個person.xml 的文件,以下:

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

<person name="JAXB2">

         <birthDay>2010-04-21T18:00:08.187+08:00</birthDay>

         <address country="China">

                   <state>Beijing</state>

                   <city>Beijing</city>

                   <street>ShangDi West</street>

         </address>

         <gender>MALE</gender>

         <job>SW</job>

</person>

控制檯會輸出

Country:China

最後,想說一點,除了JAXB以外,咱們還能夠經過XMLBeans和Castor等來實現一樣的功能。

2. 理解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)都會用到STAX因此Sun決定把STAX加入到JAXP家族當中來,並將JAXP的版本升級到1.4(JAXP1.4是JAXP1.3 的維護版本). JDK6 裏面JAXP的版本就是1.4.

STAX簡介

STAX是The Streaming API for XML的縮寫,一種利用拉模式解析(pull-parsing)XML文檔的API. STAX經過提供一種基於事件迭代器(Iterator)的API讓程序員去控制xml文檔解析過程,程序遍歷這個事件迭代器去處理每個解析事件,解析事件能夠看作是程序拉出來的,也就是程序促使解析器產生一個解析事件而後處理該事件,以後又促使解析器產生下一個解析事件,如此循環直到碰到文檔結束符;SAX 也是基於事件處理xml 文檔,但倒是用推模式解析,解析器解析完整個xml 文檔後,才產生解析事件,而後推給程序去處理這些事件;DOM 採用的方式是將整個xml文檔映射到一顆內存樹,這樣就能夠很容易地獲得父節點和子結點以及兄弟節點的數據,但若是文檔很大,將會嚴重影響性能。

下面代碼演示瞭如何經過STAX讀取xml文檔和生成xml文檔。

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

 

import javax.xml.namespace.QName;

import javax.xml.stream.XMLEventReader;

import javax.xml.stream.XMLInputFactory;

import javax.xml.stream.XMLOutputFactory;

import javax.xml.stream.XMLStreamException;

import javax.xml.stream.XMLStreamWriter;

import javax.xml.stream.events.StartElement;

import javax.xml.stream.events.XMLEvent;

 

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()) { //若是解析的是起始標記

                                     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()) { //若是解析的是文本內容

                                     parsingResult.append(event.asCharacters().getData());

                            } else if (event.isEndElement()) { //若是解析的是結束標記

                                     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"));

                   // 寫入默認的XML 聲明到xml文檔

                   xmlw.writeStartDocument();

                   xmlw.writeCharacters("\n");

                   // 寫入註釋到xml 文檔

                   xmlw.writeComment("testing comment");

                   xmlw.writeCharacters("\n");

                   // 寫入一個catalogs根元素

                   xmlw.writeStartElement("catalogs");

                   xmlw.writeNamespace("myNS", "http://blog.csdn.net/Lj");

                   xmlw.writeAttribute("owner", "Lj");

                   xmlw.writeCharacters("\n");

                   // 寫入子元素catalog

                   xmlw.writeStartElement("http://blog.csdn.net/Lj", "catalog");

                   xmlw.writeAttribute("id", "007");

                   xmlw.writeCharacters("Apparel");

                   // 寫入catalog元素的結束標籤

                   xmlw.writeEndElement();

                   // 寫入catalogs元素的結束標籤

                   xmlw.writeEndElement();

                   // 結束XML 文檔

                   xmlw.writeEndDocument();

                   xmlw.close();

         }

 

}

test.xml文件內容以下:

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

<catalogs>

         <catalog id="001">Book</catalog>

         <catalog id="002">Video</catalog>

</catalogs>

運行上面程序後,控制檯輸出以下:

<catalogs>

         <catalog id="001">Book</catalog>

         <catalog id="002">Video</catalog>

</catalogs>

運行上面程序後,產生的output.xml文件以下:

<?xml version="1.0" ?>

         <!--testing comment-->

<catalogs xmlns:myNS="http://blog.csdn.net/Lj" owner="Lj">

         <myNS:catalog id="007">Apparel</myNS:catalog>

</catalogs>

3. 使用Compiler API

如今咱們能夠用JDK6 的Compiler API(JSR 199)去動態編譯Java源文件,Compiler API結合反射功能就能夠實現動態的產生Java代碼並編譯執行這些代碼,有點動態語言的特徵。這個特性對於某些須要用到動態編譯的應用程序至關有用, 好比JSP Web Server,當咱們手動修改JSP後,是不但願須要重啓Web Server 才能夠看到效果的,這時候咱們就能夠用Compiler API來實現動態編譯JSP文件,固然,如今的JSP Web Server也是支持JSP熱部署的,如今的JSP Web Server經過在運行期間經過Runtime.exec 或ProcessBuilder 來調用javac 來編譯代碼,這種方式須要咱們產生另外一個進程去作編譯工做,不夠優雅並且容易使代碼依賴與特定的操做系統;Compiler API經過一套易用的標準的API提供了更加豐富的方式去作動態編譯,並且是跨平臺的。下面代碼演示了Compiler API的使用

建立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(nullnullnull);

 

                            File javaFile = new File("Hello.java");

                            Iterable fileObjects = sjfm.getJavaFileObjects(javaFile);

                            jc.getTask(null, sjfm, nullnullnullfileObjects).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 "如今的時間爲:" + new Date();

         }

}

編譯運行便可,在工做目錄下你會發現:Hello.class表示Compiler run OK.

4. 輕量級Http Server

JDK6 提供了一個簡單的Http Server API,據此咱們能夠構建本身的嵌入式Http Server,它支持Http 和Https 協議,提供了HTTP1.1的部分實現,沒有被實現的那部分能夠經過擴展已有的Http Server API來實現,程序員必須本身實現HttpHandler接口,HttpServer 會調用HttpHandler 實現類的回調方法來處理客戶端請求,在這裏,咱們把一個Http 請求和它的響應稱爲一個交換,包裝成HttpExchange類,HttpServer負責將HttpExchange傳給HttpHandler實現類的回調方法.下面代碼演示了怎樣建立本身的Http Server

import java.io.IOException;

import java.net.InetSocketAddress;

 

import com.sun.net.httpserver.HttpServer;

 

public class HTTPServerAPITester {

         public static void main(String[] args) {

                   try {

                            HttpServer hs = HttpServer.create(new InetSocketAddress(8888), 0);//設置HttpServer的端口爲8888

                            hs.createContext("/lj", new MyHandler());//用MyHandler類內處理到/lj的請求

                            hs.setExecutor(null); // creates a default executor

                            hs.start();

                   } catch (IOException e) {

                            e.printStackTrace();

                   }

         }

 

}

 MyHandler類:

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

 

import com.sun.net.httpserver.HttpExchange;

import com.sun.net.httpserver.HttpHandler;

 

public class MyHandler implements HttpHandler {

         public void handle(HttpExchange t) throws IOException {

                   InputStream is = t.getRequestBody();

                   String response = "<***>Happy Every Day 2007!--lj</***>";

                   t.sendResponseHeaders(200, response.length());

                   OutputStream os = t.getResponseBody();

                   os.write(response.getBytes());

                   os.close();

         }

}

運行程序後,在瀏覽器內輸入http://localhost:8888/lj,瀏覽器輸出

Happy Every Day 2007!--lj

5. 用Console開發控制檯程序

JDK6 中提供了java.io.Console 類專用來訪問基於字符的控制檯設備. 你的程序若是要與Windows 下的cmd 或者Linux 下的Terminal交互,就能夠用Console類代勞. 但咱們不老是能獲得可用的Console, 一個JVM是否有可用的Console依賴於底層平臺和JVM如何被調用. 若是JVM是在交互式命令行(好比Windows的cmd)中啓動的,而且輸入輸出沒有重定向到另外的地方,那麼就能夠獲得一個可用的Console實例。

下面代碼演示了Console類的用法:

import java.io.Console;

 

public class ConsoleTest {

         public static void main(String[] args) {

                   Console console = System.console();//得到Console實例

                   if (console != null) {//判斷console 是否可用

                            String user = new String(console.readLine("Enter user:")); //讀取整行字符

                            String pwd = new String(console.readPassword("Enter passowrd:")); //讀取密碼,密碼輸入時不會顯示

                            console.printf("User is:" + user + "\n");

                            console.printf("Password is:" + pwd + "\n");

                   } else {

                            System.out.println("Console is unavailable");

                   }

         }

}

若是在eclipse裏面運行上面程序,會輸出

Console is unavailable

表示Console 不可得到,那是由於JVM 不是在命令行中被調用的或者輸入輸出被重定向了. 可是若是咱們在命令行中運行上面程序(java ConsoleTest),程序可以得到Console實例,並執行以下:

在這裏能夠看到輸入密碼時,控制檯時不顯示這些密碼字符的,可是程序能夠獲得輸入的密碼字符串,這與Linux下面輸入密碼的狀況是同樣的。

6. Common Annotations

Common annotations 本來是Java EE 5.0(JSR 244)規範的一部分,如今SUN 把它的一部分放到了Java SE 6.0 中.隨着Annotation元數據功能(JSR 175)加入到Java SE 5.0裏面,不少Java 技術(好比EJB,Web Services)都會用Annotation部分代替XML 文件來配置運行參數(或者說是支持聲明式編程,如EJB的聲明式事務), 若是這些技術爲通用目的都單獨定義了本身的Annotations,顯然有點重複建設, 因此,爲其餘相關的Java 技術定義一套公共的Annotation是有價值的,能夠避免重複建設的同時,也保證Java SE和Java EE 各類技術的一致性.

下面列舉出Common Annotations 1.0裏面的10個Annotations

Common Annotations

Annotation Retention Target Description

Generated Source ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER,TYPE用於標註生成的源代碼

Resource Runtime TYPE, METHOD, FIELD 用於標註所依賴的資源,容器據此注入外部資源依賴,有基於字段的注入和基於setter方法的注入兩種方式

Resources Runtime TYPE 同時標註多個外部依賴,容器會把全部這些外部依賴注入

PostConstruct Runtime METHOD 標註當容器注入全部依賴以後運行的方法,用來進行依賴注入後的初始化工做,只有一個方法能夠標註爲PostConstruct

PreDestroy Runtime METHOD 當對象實例將要被從容器當中刪掉以前,要執行的回調方法要標註爲PreDestroy

RunAs Runtime TYPE 用於標註用什麼安全角色來執行被標註類的方法,這個安全角色必須和Container 的Security 角色一致的

RolesAllowed Runtime TYPE, METHOD 用於標註容許執行被標註類或方法的安全角色,這個安全角色必須和Container 的Security角色一致的

PermitAll Runtime TYPE, METHOD 容許全部角色執行被標註的類或方法

DenyAll Runtime TYPE, METHOD 不容許任何角色執行被標註的類或方法,代表該類或方法不能在Java EE容器裏面運行

DeclareRoles Runtime TYPE 用來定義能夠被應用程序檢驗的安全角色,一般用isUserInRole來檢驗安全角色

注意:

1.RolesAllowed,PermitAll,DenyAll不能同時應用到一個類或方法上

2.標註在方法上的RolesAllowed,PermitAll,DenyAll會覆蓋標註在類上的RolesAllowed,PermitAll,DenyAll

3.RunAs,RolesAllowed,PermitAll,DenyAll和DeclareRoles尚未加到Java SE 6.0上來

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

7. Web服務元數據(Web Services metadata)

JSR-181的元數據清單

下面介紹JSR-181裏面各個元數據的相關參數及用途

Annotation Retention Target Description

WebService Runtime Type標註要暴露爲Web Services 的類或接口

WebParam Runtime Parameter 自定義服務方法參數到WSDL的映射

WebResult Runtime Method 自定義服務方法返回值到WSDL的映射

WebMethod Runtime Method 自定義單個服務方法到WSDL的映射

Oneway Runtime Method 必須與@WebMethod連用,代表被標註方法只有輸入沒有輸出,這就要求被標註方法不能有返回值,也不能聲明checked exception

HandlerChain Runtime Type,Method,Field 將Web 服務與外部Handler chain 關聯起來

SOAPBinding Runtime Type,Method 自定義SOAPBinding

JSR-181元數據使用示例

package WebServices;

 

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;

 

@WebService(targetNamespace = "http://blog.csdn.net/lj", serviceName = "HelloService")

public class WSProvider {

         @WebResult(name = "Greetings")

         //自定義該方法返回值在WSDL中相關的描述

         @WebMethod

         public String sayHi(@WebParam(name = "MyName") String name) {

                   return "Hi," + name; //@WebParam是自定義參數name在WSDL 中相關的描述

         }

 

         @Oneway

         //代表該服務方法是單向的,既沒有返回值,也不該該聲明檢查異常

         @WebMethod(action = "printSystemTime", operationName = "printSystemTime")

         //自定義該方法在WSDL中相關的描述

         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() {

                            //發佈WSProvider 到http://localhost:8888/lj/WSProvider這個地址,以前必須調用wsgen命令

                            //生成服務類WSProvider的支持類,命令以下:

                            //wsgen -cp . WebServices.WSProvider

                            Endpoint.publish("http://localhost:8888/lj/WSProvider", new WSProvider());

                   }

         }

}

若是想看到Web Services Engine生成的WSDL文件是否遵照上面的元數據, 咱們沒有必要將上面的WSProvider部署到支

持JSR-181的應用服務器或Servlet形式的Web Services Engine,如今JDK6已經提供了一個很簡單的機制能夠用來測試和發

布Web Services,下面講講如何在JDK6環境下發布Web Services和查看生成的WSDL

1.將<JDK_HOME>/bin加入path環境變量

2. 執行以下代碼發佈WSProvider到http://localhost:8888/lj/WSProvider,在這裏能夠執行WSProvider類的main方法就能夠.

在這個例子中會生成如下3個類的源代碼文件及class文件

SayHi

SayHiResponse

PrintTime

3.在瀏覽器輸入http://localhost:8888/lj/WSProvider?wsdl就能夠看到生成的WSDL文件,以下圖,你們能夠本身動手試試。

8. 更簡單,更強大的JAX-WS

JAX-WS2.0的來歷

JAX-WS(JSR-224) 是Java Architecture for XML Web Services的縮寫,簡單說就是一種用Java和XML開發Web Services應用程序的框架, 目前版本是2.0, 它是JAX-RPC 1.1的後續版本, J2EE 1.4 帶的就是JAX-RPC1.1, 而Java EE 5裏面包括了JAX-WS 2.0,但爲了向後兼容,仍然支持JAX-RPC. 如今,SUN 又把JAX-WS 直接放到了Java SE 6裏面,因爲JAX-WS 會用到

Common Annotation(JSR 250),Java Web Services Metadata(JSR 181), JAXB2(JSR 222), StAX(JSR 173), 因此SUN也必須把後幾個原屬於Java EE範疇的Components下放到Java SE, 如今咱們能夠清楚地理解了爲何Sun要把這些看似跟JavaSE沒有關係的Components放進來,終極目的就是要在Java SE裏面支持Web Services.

JAX-WS2.0的架構

JAX-WS不是一個孤立的框架,它依賴於衆多其餘的規範,本質上它由如下幾部分組成

1.用來開發Web Services的Java API

2.用來處理Marshal/Unmarshal的XML Binding機制,JAX-WS2.0用JAXB2來處理Java Object與XML之間的映射,Marshalling就是把Java Object 映射到XML,Unmarshalling則是把XML映射到Java Object.之因此要作Java Object與XML的映射,是由於最終做爲方法參數和返回值的Java Object要經過網絡傳輸協議(通常是SOAP)傳送,這就要求必須對Java Object作相似序列化和反序列化的工做,在SOAP中就是要用XML來表示Java object的內部狀態

3.衆多元數據(Annotations)會被JAX-WS 用來描述Web Services 的相關類,包括Common Annotations, Web Services Metadata, JAXB2的元數據和JAX-WS2.0規範本身的元數據.

4.Annotation Processing Tool(APT)是JAX-WS重要的組成部分,因爲JAX-WS2.0規範用到不少元數據,因此須要APT 來處理衆多的Annotations.在<JDK_HOME>/bin 下有兩個命令wsgen 和wsimport,就是用到APT 和Compiler API 來處理碰到的Annotations,wsgen能夠爲Web Services Provider產生並編譯必要的幫助類和相關支持文件,wsimport以WSDL做爲輸入爲Web Service Consumer 產生並編譯必要的幫助類和相關支持文件.

5.JAX-WS還包括JAX-WS Runtime與應用服務器和工具之間的契約關係

JAX-WS2.0的編程模型

如今用JAX-WS2.0 來編寫Web Services 很是簡單,不像JAX-RPC,JAX-WS 能夠把任意POJO暴露爲Web Services,服務類不須要實現接口,服務方法也沒有必要拋出RMI異常.下面介紹在JDK6環境下用JAX-WS2.0開發和測試Web Services的步驟

1.編寫服務類,並用Web Services Metadata(JSR-181)標註這個服務類,用Web 服務元數據中的WSProvider類做爲服務類的例子,源代碼可見上文。

2.用wsgen生成上面服務類的必要的幫助類,而後調用用EndPoint類的靜態方法publish發佈服務類(請參考Web服務元數據),我在這裏是將服務類發佈到http://localhost:8888/lj/WSProvider

3.用wsimport爲服務消費者(也就是服務的客戶端)生成必要的幫助類,命令以下:

wsimport http://localhost:8888/lj/WSProvider?wsdl

這會在<當前目錄>\net\csdn\blog\lj下生成客戶端的幫助類,在這個例子中會生成7個類

HelloService.class

ObjectFactory.class

package-info.class

PrintSystemTime.class

SayHi.class

SayHiResponse.class

WSProvider.class

4.在客戶端用下面代碼便可調用步驟1定義的Web Service

HelloService hs = new HelloService();

WSProvider ws = hs.getWSProviderPort();

System.out.println(ws.sayHi("lj"));

ws.printSystemTime();

調用上述代碼後客戶端控制檯輸出

hi,lj

服務端控制檯輸出服務器當前系統時間

9. 腳本語言支持(Scripting)

概述

JDK6增長了對腳本語言的支持(JSR 223),原理上是將腳本語言編譯成bytecode,這樣腳本語言也能享用Java平臺的諸多優點,包括可移植性,安全等,另外,因爲如今是編譯成bytecode 後再執行,因此比原來邊解釋邊執行效率要高不少。加入對腳本語言的支持後,對Java語言也提供瞭如下好處。

一、許多腳本語言都有動態特性,好比,你不須要用一個變量以前先聲明它,你能夠用一個變量存放徹底不一樣類型的對象,你不須要作強制類型轉換,由於轉換都是自動的。如今Java語言也能夠經過對腳本語言的支持間接得到這種靈活性。

二、能夠用腳本語言快速開發產品原型,由於如今能夠Edit-Run,而無需Edit-Compile-Run,固然,由於Java 有很是好的IDE 支持,咱們徹底能夠在IDE 裏面編輯源文件,而後點擊運行(隱含編譯),以此達到快速開發原型的目的,因此這點好處基本上能夠忽略。

三、經過引入腳本語言能夠輕鬆實現Java應用程序的擴展和自定義,咱們能夠把原來分佈在在Java應用程序中的配置邏輯,數學表達式和業務規則提取出來,轉用JavaScript 來處理。

Sun的JDK6實現包含了一個基於Mozilla Rhino的腳本語言引擎,支持JavaScript,這並非說明JDK6只支持JavaScript,任何第三方均可以本身實現一個JSR-223 兼容的腳本引擎使得JDK6支持別的腳本語言,好比,你想讓JDK6支持Ruby,那你能夠本身按照JSR 223 的規範實現一個Ruby 的腳本引擎類,具體一點,你須要實現javax.script.ScriptEngine(簡單起見,能夠繼承javax.script.AbstractScriptEngine)和javax.script.ScriptEngineFactory 兩個接口。固然,在你實現本身的腳本語言引擎以前,先到scripting.dev.java.net project 這裏看看是否是有人已經幫你作了工做,這樣你就能夠直接拿來用就行。

Scripting API

Scripting API是用於在Java 裏面編寫腳本語言程序的API, 在Javax.script 中能夠找到Scripting API,咱們就是用這個API來編寫JavaScript程序,這個包裏面有一個ScriptEngineManager 類,它是使用Scripting API的入口,ScriptEngineManager能夠經過jar 服務發現(service discovery)機制尋找合適的腳本引擎類(ScriptEngine),使用Scripting API的最簡單方式只需下面三步

一、建立一個ScriptEngineManager 對象

二、經過ScriptEngineManager得到ScriptEngine對象

三、用ScriptEngine的eval方法執行腳本

下面是一個Hello World 程序

import javax.script.ScriptEngine;

import javax.script.ScriptEngineManager;

 

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

         }

}

運行上面程序,控制檯會輸出Hello, Scripting上面這個簡單的Scripting程序演示瞭如何在Java裏面運行腳本語言,除此以外,咱們還能夠利用Scripting API實現如下功能

一、暴露Java對象爲腳本語言的全局變量

二、在Java中調用腳本語言的方法

三、腳本語言能夠實現Java的接口

四、腳本語言能夠像Java同樣使用JDK平臺下的類。

下面的類演示了以上4種功能

package Scripting;

 

import java.io.File;

 

import javax.script.Invocable;

import javax.script.ScriptEngine;

import javax.script.ScriptEngineManager;

import javax.script.ScriptException;

 

public class ScriptingAPITester {

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

                   ScriptEngineManager manager = new ScriptEngineManager();

                   ScriptEngine engine = manager.getEngineByName("JavaScript");

                   testScriptVariables(engine);//演示如何暴露Java對象爲腳本語言的全局變量

                   testInvokeScriptMethod(engine);//演示如何在Java中調用腳本語言的方法

                   testScriptInterface(engine);//演示腳本語言如何實現Java的接口

                   testUsingJDKClasses(engine);//演示腳本語言如何使用JDK平臺下的類

         }

 

         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 是腳本語言裏的一個全局變量,專用於訪問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 中有一個命令行工具??jrunscript,你能夠在<JDK6_Home>/bin 下面找到這個工具,jrunscript 是一個腳本語言的解釋程序,它獨立於腳本語言,但默認是用JavaScript,咱們能夠用jrunscript來測試本身寫的腳本語言是否正確,下面是一個在命令行運行jrunscript 的簡單例子。以下圖:

 
相關文章
相關標籤/搜索