java服务写在哪里_【Java学习笔记】如何写一个简单的Web Service
本Guide利用Eclipse以及Ant建立一個簡單的Web Service,以演示W(wǎng)eb Service的基本開發(fā)過程:
1.系統(tǒng)條件: Eclipse Java EE IDE for Web Developers
Java SE 6
Windows XP
2.基本環(huán)境搭建:
1)Java SE6 JDK的安裝:下載Java SE6 JDK,雙擊,安裝默認(rèn)選項進(jìn)行安裝即可。
2)Eclipse的安裝與配置:
安裝時直接解壓。
配置處有兩點,Window>Preferences>Java>Installed JREs確保如下設(shè)置:
安裝路徑可能略有不同。
Window>Preferences>Java>Compiler 確保如下設(shè)置:
3.建立Server端工程和相關(guān)包與類:
創(chuàng)建一個Java Project,命名為wsServerHelloWorld:
在這個項目下建立包:org.gnuhpc.wsServer
在這個包下邊建立類:SayHello
在SayHello.java文件中輸入以下代碼: package org.gnuhpc.wsServer;
import javax.jws.WebService;
@WebServicepublic class SayHello {
private static final String SALUTATION = "Hello";
public String getGreeting(String name) {
return SALUTATION + " " + name;
}
}
其中注意到@WebService ,這個稱作annotation或者metadata,Java SE 5中的Web Services Metadata Specification引入的。Java SE 6中對于Web Services規(guī)范的升級以及JAX-WS(Java API for XML Web Services)2.0規(guī)范,這些升級使得我們Web Services的創(chuàng)建和調(diào)用變得更加容易。使用這些新功能,我們可以僅僅使用簡單的Annotations注釋從一個Java類創(chuàng)建Web Services。開發(fā)者將其類和方法之前用該annotations指定,類告訴runtime engine以Web Service的方式和操作來使能該類和方法。這個annotations可以產(chǎn)生一個可布署的Web Service,是一個WSDL映射annotations,將Java源代碼與代表Web Service的WSDL元素連接在了一起。
4.使用Ant產(chǎn)生Server端代碼:
首先在項目中新建一個文件:build.xml,然后使用OpenWith>AntEditor打開,輸入以下腳本代碼:
org.gnuhpc.wsServer.SayHello"/>
default指定了默認(rèn)執(zhí)行的Target為wsgen,wsgen可以創(chuàng)建一個能夠使用WebService的類,它生成所有用于WebService發(fā)布的源代碼文件和經(jīng)過編譯過的二進(jìn)制類文件。它還生成WSDL和符合規(guī)范的該類的WebService。
Target名稱為wsgen,具體執(zhí)行的命令的參數(shù):
-cp 為類路徑
-keep后產(chǎn)生的java文件
-s 產(chǎn)生的源文件放在哪
-d 產(chǎn)生的輸出問價放在哪
然后使用Ant Build選項運行:
在成功執(zhí)行的提示后,我們刷新一下Project
我們在Project區(qū)域可以看到,結(jié)果如下:
5.分布Web Service
org.gnuhpc.wsServer下建立一個類RunService: package org.gnuhpc.wsServer;
import javax.xml.ws.Endpoint;
public class RunService {
/**
*@paramargs
*/
public static void main(String[] args) {
System.out.println("SayHello Web Service started.");
Endpoint.publish(",
new SayHello());
}
}
運行Run As>Java Application。我們得到結(jié)果,說明這個web service的Server端已經(jīng)啟動。
6.查看WSDL:
Window>Show View>Other>General>Internal Web Browser,在其中輸入:http://localhost:8080/wsServerExample?wsdl
你可以看看到底WSDL都記錄了哪些信息??赐旰罂梢酝V乖揝erver。
7.監(jiān)測Server
我們創(chuàng)建完Server可以用過Eclipse Web Services Explorer監(jiān)測Server,
Window>Open Perspective>Other >JavaEE
打開Eclipse Web Services Explorer
點擊右上角的WSDL Page按鈕:
我們可以觸發(fā)一個Web Service操作:點擊getGreetings,添加一個參數(shù),比如gnuhpc,然后點擊Go按鈕:
8.創(chuàng)建Client端 工程和相關(guān)包與類:
創(chuàng)建一個Java Project,命名為wsClientHelloWorld,在這個項目下建立包:org.gnuhpc.wsClient
9.使用Ant產(chǎn)生Client代碼框架:
編寫Web service時,可以使用工具來利用WSDL生成進(jìn)行調(diào)用的客戶端樁;或者也可以使用底層API來手動編寫Web service。前者方便,后者靈活,現(xiàn)在我們通過前者做說明:
新建文件build.xml
New>File>build.xml
-d ./bin http://localhost:8080/wsServerExample?wsdl"/>
注意:wsgen 支持從 Java class 創(chuàng)建 Web services,wsimport 支持從 WSDL 創(chuàng)建 Web services,分別對應(yīng)于 JAX-RPC 方式下的 Java2WSDL 和 WSDL2Java。要根據(jù)發(fā)布的WSDL進(jìn)行創(chuàng)建,這也就是為什么要先運行RunServer的原因了。
運行Server的RunService : Run As>Java Application>
運行該Ant腳本,產(chǎn)生Client代碼:Run As>Ant Build
運行成功的提示如下:
生成的代碼如下:
這一步讀取WSDL并生成客戶端樁。這些樁是將為我們的代碼所用的Java類和接口。這些樁給服務(wù)器端功能提供了一個客戶端接口。例如,如果我們的服務(wù)器提供一個Maths服務(wù),該服務(wù)帶有一個叫做add的方法。我們的客戶端代碼將調(diào)用樁上的一個方法,而樁實現(xiàn)將對該方法使用參數(shù)封裝,把Java方法調(diào)用變?yōu)閃eb service請求。這個請求將基于HTTP發(fā)送給服務(wù)器,而且將使用SOAP作為RPC協(xié)議。監(jiān)聽服務(wù)器接收該SOAP消息,然后(十有八九)將其轉(zhuǎn)換為服務(wù)器處的一次方法調(diào)用。
10.編寫Client代碼
創(chuàng)建一個類:SayHelloClient
package org.gnuhpc.wsClient;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.xml.ws.BindingProvider;
public class SayHelloClient {
/**
* @param args
*/
public static void main(String[] args) {
SayHelloService shs = new SayHelloService();
SayHello sh = (SayHello) shs.getSayHelloPort();
((BindingProvider) sh).getRequestContext().put(
BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"System.out.println(((BindingProvider) sh).toString());
String userName = null;
boolean exit = false;
while (!exit) {
System.out.print("/n Please enter yourname (type 'quit' to exit): ");
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
try {
userName = br.readLine();
} catch (IOException e) {
System.out.println("Errorreadingname.");
System.exit(1);
}
if (!(exit = userName.trim().equalsIgnoreCase("quit")
|| userName.trim().equalsIgnoreCase("exit"))) {
System.out.println(sh.getGreeting(userName));
}
}
System.out.println("/nThank you for running the client.");
}
}
當(dāng)你運行SayHelloClient時,它創(chuàng)建了一個新的Service--SayHelloService,這是通過Ant腳本調(diào)用wsimport產(chǎn)生的一個proxy,用來調(diào)用目標(biāo)服務(wù)端點的操作。然后Client得到請求上下文,添加端點地址http://localhost:8080/wsServerExample,在這里處理請求消息。
11.運行Client
右鍵SayHelloClient.java,選擇Run As> Java Application,得到:
可以使用腳本完成對Server和Client的調(diào)用:
在Client中建立文件buildall.xml:
Read the WSDL and generate the required artifacts">
http://localhost:8080/wsServerExample?wsdl"/>
Runs the Web service server from a terminal">
Running the following command from the terminal to run the server:
${java.home}/bin/java -cp "C:/Documents and Settings/Administrator/workspace/wsServerHelloWorld/bin"
org.gnuhpc.wsServer.RunService
os="Windows XP"description="runs on XP">
"C:/Documents and Settings/Administrator/workspace/wsServerHelloWorld/bin"
org.gnuhpc.wsServer.RunService'/>
Pauses briefly while the server starts">
Runs a Web service client from a terminal">
Running the following command from the terminal to run the client:
${java.home}/bin/java -cp "c:/DOCUME~1/Administrator/workspace/wsClientHelloWorld/bin"
org.gnuhpc.wsClient.SayHelloClient
os="Windows XP"description="Runs on XP">
org.gnuhpc.wsClient.SayHelloClient'/>
Running the following command from the terminal to run the server: ${java.home}/bin/java -cp "C:/Documents and Settings/Administrator/workspace/wsServerHelloWorld/bin" org.gnuhpc.wsServer.RunService Running the following command from the terminal to run the client: ${java.home}/bin/java -cp "c:/DOCUME~1/Administrator/workspace/wsClientHelloWorld/bin" org.gnuhpc.wsClient.SayHelloClient
注意其中的路徑名稱,選擇與你自己系統(tǒng)的路徑名即可。
在這個腳本中,默認(rèn)target為runClient,但是在運行runClient之前還有一個依賴:pause,意味著runClient之前一定要運行pause,而pause的依賴是runServer,那么運行順序就是
runServer先運行,pause再運行,最后runClient運行。
另一個需要注意的是os值:只有當(dāng)前系統(tǒng)與指定的OS匹配時才會被執(zhí)行。
為顯示命令。
用Ant Build運行得到一個Server,5秒鐘后出現(xiàn)一個Client。
12.使用SOAP監(jiān)視器監(jiān)視C-S的通信:
到這一步,我們已經(jīng)建立了一個Server 一個Client端,我們現(xiàn)在想使用Eclipse的TCP/IP Monitor監(jiān)視SOAP通信。
打開:Window>Show View>Other>Debug>TCP/IP Monitor
配置:Windows>Preferences >Run/Debug > TCP/IPMonitor
添加一個TCP/IP Monitor:
Port為遠(yuǎn)端服務(wù)器端口,Local Monitoring Port為本地監(jiān)聽端口
現(xiàn)在我們需要更新一下Client代碼(將端口8080,設(shè)置為8081),將Web Service通過Monitor重定向。然后運行腳本:
左右分別的文本全文為: POST /wsServerExample HTTP/1.1
SOAPAction: ""
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Content-Type: text/xml; charset=utf-8
User-Agent: Java/1.6.0_13
Host: localhost:8081
Connection: keep-alive
Content-Length: 210
http://schemas.xmlsoap.org/soap/envelope/">http://wsServer.gnuhpc.org/">gnuhpc HTTP/1.1 200 OK
Transfer-encoding: chunked
Content-type: text/xml; charset=utf-8
5d
http://schemas.xmlsoap.org/soap/envelope/">
8f
>http://wsServer.gnuhpc.org/">Hello gnuhpc
0
其中的含義不言自明。
所有代碼下載:
http://cid-a0a0b50959052db4.skydrive.live.com/self.aspx/.Public/WebService.rar
2010.1.5 補(bǔ)充:
1.網(wǎng)友Alexander Ananiev在其Blog上表示在他看來還是手工寫WSDL和schemas比較靠譜,更加有重用性和擴(kuò)展性,并不推薦使用annotations自動生成WSDL。
2.JAX-WS 包括了 Java Architecture for XML Binding (JAXB) 和 SOAP with Attachments API for Java (SAAJ).
前者為從XML Schema到Java代碼表示提供了一個方便的映射方法,屏蔽了從SOAP消息中的XML Schema到Java代碼之間轉(zhuǎn)換的具體細(xì)節(jié)。而SAAJ則為處理在SOAP消息中附帶的XML提供了一個標(biāo)準(zhǔn)的方法。另外,JAX-WS還定義了從WSDL上定義的服務(wù)到實現(xiàn)這些服務(wù)的Java類之間的映射,任何定義在WSDL中的復(fù)雜類型都將根據(jù)JAXB定義的標(biāo)準(zhǔn)轉(zhuǎn)換到Java類中。
3.開發(fā)JAX-WS有兩種思路: Contract first:先寫好WSDL,然后從中生成Java 代碼來實現(xiàn)。
Code first:先寫好一些plain old Java object (POJO) classes,然后使用annotations產(chǎn)生WSDL和Java類。
前者需要很好的WSDL和XSD知識,初學(xué)者一般建議后者,另外要是將一個已經(jīng)實現(xiàn)的類以Web Service的方式呈現(xiàn)也建議用后者。前者的一個例子是:http://myarch.com/create-jax-ws-service-in-5-minutes
4.常見Annotations含義:
Property DescriptionSpecifies the name of the service interface. This property is mapped to thenameattribute of thewsdl:portTypeelement that defines the service's interface in a WSDL contract. The default is to appendPortTypeto the name of the implementation class.[a]
Specifies the target namespace under which the service is defined. If this property is not specified, the target namespace is derived from the package name.
Specifies the name of the published service. This property is mapped to thenameattribute of thewsdl:serviceelement that defines the published service. The default is to use the name of the service's implementation class.[a]
Specifies the URI at which the service's WSDL contract is stored. The default is the URI at which the service is deployed.
Specifies the full name of the SEI that the implementation class implements. This property is only used when the attribute is used on a service implementation class.
Specifies the name of the endpoint at which the service is published. This property is mapped to thenameattribute of thewsdl:portelement that specifies the endpoint details for a published service. The default is the appendPortto the name of the service's implementation class.[a][a]When you generate WSDL from an SEI the interface's name is used in place of the implementation class' name
@XmlSeeAlso:
Suppose you want to build a web service that manages the inventory for a store that sells wakeboards and related equipment. Wakeboards are short boards made of buoyant material that are used to ride over the surface of a body of water, typically behind a boat or with a cable-skiing apparatus.
For simplicity, let's assume that the store sells only three types items: wakeboards, bindings, and towers for boats. You want the web service to be fairly simple to use and have a minimal amount of exposed operations. So to keep things simple, the web service uses an abstractItemclass in its operations instead of using type-specific operations. The followingItemclass can be used to model any inventory object that you might want to expose through your web service:
public abstract class Item implements Serializable {
private long id;
private String brand;
private String name;
private double price;
...
}
Extending theItemclass, you can define the followingWakeboard,WakeboardBindingandTowerclasses:
public class Wakeboard extends Item {
private String size;
}
public class WakeboardBinding extends Item {
private String size;
}
public class Tower extends Item {
private Fit fit;
private String tubing;
public static enum Fit { Custom, Exact, Universal };
}
Because this example is about type substitution, let's make the inheritance hierarchy a little more interesting by introducing aWearableabstract class.Wearableholds the size attribute for both theWakeboardandWakeboardBindingclasses. TheWearableclass is defined as follows:
public abstract class Wearable extends Item {
protected String size;
}
And the resultingWakeboardandWakeboardBindingclasses are:
public class Wakeboard extends Wearable {
}
public class WakeboardBinding extends Wearable {
}
Also, because the web service manages inventory, you'll want the inventory items to be persisted to a database using the Java Persistence API (sometimes referred to as JPA). To do this, you need to add an@Entityannotation to each of the classes that will be persisted. The only class that you probably don't want to persist is theWearableclass. You can add the@MappedSuperclassannotation to this class so that the JPA will use the attributes of this class for persisting subclasses. Next, you need to add the@Idand the@GeneratedValue(strategy = GenerationType.AUTO)annotations to theItem.Idfield. As a result, the field will be used as the primary key in the database and the Id will be automatically generated if not provided. Finally, because you might add new types ofItems into the system at a later time, you should add the@Inheritance(strategy=InheritanceType.JOINED)annotation to theItemclass. This will store each subclass in its own database table.
The final data classes look like the following:
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class Item implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String brand;
private String itemName;
private double price;
// Getters & setters
...
}
@MappedSuperclass
public abstract class Wearable extends Item {
protected String size;
...
}
@Entity
public class Wakeboard extends Wearable {}
@Entity
public class WakeboardBinding extends Wearable {}
@Entity
public class Tower extends Item {
private Fit fit;
private String tubing;
public static enum Fit { Custom, Exact, Universal };
...
}
Now that you defined the data model for the application, you can now define the web service interface. Because the application manages information about wakeboard equipment, let's call the web serviceWakeRiderand let's expose four operations in the web service:addItem,updateItem,removeItem, andgetItems.
Here is what theWakerRiderclass looks like:
@WebService()
public class WakeRider {
...
public List getItems() {...}
public boolean addItem(Item item) {...}
public boolean updateItem(Item item) {...}
public boolean removeItem(Item item) {...}
}
If you deployed this web service and then looked at the generated WSDL and schema, you would notice that only theItemtype is defined -- there is no mention ofWearable,Wakeboard,WakeboardBinding, orTower. This is because when JAX-WS introspects theWakeRiderclass there is no mention of the other classes. To remedy that you can use the new@XmlSeeAlsoannotation and list the other classes that you want to expose through theWakeRiderweb service.
Here is what theWakeRiderclass looks like with the@XmlSeeAlsoannotation:
@WebService()
@XmlSeeAlso({Wakeboard.class,
WakeboardBinding.class,
Tower.class})
public class WakeRider {
...
}
Now when you deploy theWakeRiderservice and look at the generated schema, you will see types forItem,Wearable,Wakeboard,WakeboardBinding, andToweras well as some other types used internally by JAX-WS and JAXB.
@WebResult含義:specifies that the name of the result of the operation in the generated WSDL
targetNamespace含義:The XML namespace used for the WSDL and XML elements generated from this Web Service.
@RequestWrapper 含義:生成的請求包裝器 bean、元素名稱和名稱空間,用于對在運行時使用的請求包裝器 bean 進(jìn)行序列化和反序列化。
@ResponseWrapper 含義:提供 JAXB 生成的響應(yīng)包裝器 bean、元素名稱和名稱空間,用于對在運行時使用的響應(yīng)包裝器 bean 進(jìn)行序列化和反序列化。
@WebParam 含義:用于定制從單個參數(shù)至 Web Service 消息部件和 XML 元素的映射。
@WebMethod annotation :表示作為一項 Web Service 操作的方法。
@WebService annotation: 定義了一個Web Service端點接口(service endpoint interface (SEI)),聲明了一個Client在這個Service上可能invoke 的方法,所有在這個類中定義的public方法都會被映射到WSDL中,除非有一個@WebMethod中設(shè)置有排他元素為true的。
5.在Web Service完成后要將相關(guān)文件打包生成WAR文件,然后將該文件部署到支持JAX-WS 2.0標(biāo)準(zhǔn)的Web Server上,Java 6有一個輕量級的Web server,通過簡單的API就可以將Web Service發(fā)布。
總結(jié)
以上是生活随笔為你收集整理的java服务写在哪里_【Java学习笔记】如何写一个简单的Web Service的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图像去暗角
- 下一篇: 时间复杂度(算法的渐进时间复杂度)