JKD6 对WebService的支持
JDK6提供了对Web Service原生的支持,对Web Service进行了完美的封装,完全隐藏了底层内容,甚至可以不用了解wsdl的具体规范。使用Web Service就像使用本地方法一样简单。下面来举个例子,依然从最简单的HelloWorld入手。
Java6提供了WebService运行宿主,实现了一个内置的轻量级SOAP服务器,我们可以把WebService部署到Java平台中,并进行简单的测试,不需要Web服务器(如Tomcat)就能提供WebService服务测试
HelloWorld例子
STEP 1,服务器端Bean说明
服 务器端的Java类若要成为一个实现了Web Service的bean,它需要遵循下边这些原则:这个类必须是public类、不能是final的或者abstract、必须有一个公共的默认构造函 数、绝对不能有finalize()方法。若要成为一个实现了Web Service的Bean的方法必须遵循这些原则:
这个方法必须是public,它的参数、返回值、和异常在每个JAX RPC规范中都描述了Java转化成XML/WSDL映射文件的规则,参数和返回值可以是原始类型、数组等等。
这个方法必须是public,它的参数、返回值、和异常在每个JAX RPC规范中都描述了Java转化成XML/WSDL映射文件的规则,参数和返回值可以是原始类型、数组等等。
下面是服务器端的类HelloWorld.java:
|
package org.young.ws;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
@WebService(targetNamespace = "http://localhost")
@SOAPBinding(style = SOAPBinding.Style.RPC)
publicclass HelloWorld {
@WebMethod(action="toSayHello",operationName="toSayHello",exclude=false)
@WebResult(name="returnWord")//自定义该方法返回值在WSDL中相关的描述
public String sayHello(@WebParam(name="userName")String userName) {
return"Hello:" + userName;
}
@WebMethod
publicint getExp(int i, int j) {
return i / j;
}
}
|
这是服务器端普通的业务类,通过@WebService、@WebMethod等注释描述来生成WSDL文件。
STEP 2,执行wsgen命令
本 例中到HelloWorld类所在的目录中新建一个命名为wsdl的文件夹,运行:wsgen -cp ./bin -r ./wsdl -s ./src -d ./bin -wsdl org.young.ws.HelloWorld。执行后会在wsdl文件夹中生成HelloWorld的wsdl描述文件,src文件夹中生成 依赖类,如异常说明类,bin中生成依赖类的class文件
STEP 3,发布Web Service Bean ---JDK6内置的http server
启动服务类StartService.java:
|
package org.young.ws;
import javax.xml.ws.Endpoint;
publicclass StartService {
publicstaticvoid main(String[] args) {
Endpoint.publish("http://localhost:8080/webservice/hws", new HelloWorld());
}
}
|
此类很简单,能过Endpoint类的publish()方法发布实例发布地址为:
http://localhost:8080/webservice/hws,必需明确指明http协议,主机IP 地址及端口号,在IE上输入http://localhost:8080/webservice/hws?wsdl返回以下内容说明发布成功
|
<?xml version="1.0" encoding="UTF-8" ?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://localhost"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
targetNamespace="http://localhost"
name="HelloWorldService">
<types />
<message name="toSayHello">
<part name="userName" type="xsd:string" />
</message>
<message name="toSayHelloResponse">
<part name="returnWord" type="xsd:string" />
</message>
<message name="getExp">
<part name="arg0" type="xsd:int" />
<part name="arg1" type="xsd:int" />
</message>
<message name="getExpResponse">
<part name="return" type="xsd:int" />
</message>
<portType name="HelloWorld">
<operation name="toSayHello" parameterOrder="userName">
<input message="tns:toSayHello" />
<output message="tns:toSayHelloResponse" />
</operation>
<operation name="getExp" parameterOrder="arg0 arg1">
<input message="tns:getExp" />
<output message="tns:getExpResponse" />
</operation>
</portType>
<binding name="HelloWorldPortBinding" type="tns:HelloWorld">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="toSayHello">
<soap:operation soapAction="toSayHello" />
<input>
<soap:body use="literal"
namespace="http://localhost" />
</input>
<output>
<soap:body use="literal"
namespace="http://localhost" />
</output>
</operation>
<operation name="getExp">
<soap:operation soapAction="" />
<input>
<soap:body use="literal"
namespace="http://localhost" />
</input>
<output>
<soap:body use="literal"
namespace="http://localhost" />
</output>
</operation>
</binding>
<service name="HelloWorldService">
<port name="HelloWorldPort"
binding="tns:HelloWorldPortBinding">
<soap:address
location="http://localhost:8080/webservice/hws" />
</port>
</service>
</definitions>
|
增加一个Servlet,用于启动时注册服务
| package org.young.ws.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.xml.ws.Endpoint; import org.young.ws.HelloWorld; public class WebServiceStarter extends HttpServlet { public WebServiceStarter() { super(); } public void destroy() { super.destroy(); } public void init() throws ServletException { System.out.println("准备启动服务"); Endpoint.publish("http://localhost:8080/webservice/hws", new HelloWorld()); System.out.println("服务启动完毕"); } } |
web.xml
| <?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" metadata-complete="true"> <description> WebService Examples. </description> <display-name>WebService Examples</display-name> <!-- Define servlets that are included in the example application --> <servlet> <servlet-name>WebServiceStarter</servlet-name> <servlet-class>org.young.ws.servlet.WebServiceStarter</servlet-class> <load-on-startup>1</load-on-startup> </servlet> </web-app> |
STEP 4,生成客户端执行类
在cmd命令中执行 wsimport -d ./bin -s ./src - p org.young.ws.client
http://10.168.189.182:8080/webservice/hws?wsdl 后在在src目录下生成客户端调用的两个类:
org.young.ws.client.HelloWorld.java 根据wsdl描述生成的客户端执行类
org.young.ws.client.HelloWorldServices.java 通过此类负责解悉wsdl初始化客户端HelloWorld实例
在bin目录下生成对应的类文件。
注意:执行wsimport命令时STEP 3的服务必需启动,否则无法生成
STEP 5,客户端调用
客户端调用过程ClientRun.java:
|
package org.young.ws.client;
import org.young.ws.*;
publicclass ClientTest {
publicstaticvoid main(String[] args) {
HelloWorldService hws = new HelloWorldService();
HelloWorld hw = hws.getHelloWorldPort();
System.out.println(hw.getExp(9, 3));
System.out.println(hw.toSayHello("kevin"));
}
}
|
启动STEP 3中的服务,运行Client后,制控台输出:
3
Hello:kevin
注意:经测试,用Endpoint.publish("http://localhost:8080/webservice/hws", new HelloWorld())方式在Tomcat6中发布,不会存在端口号与路径冲突。
JKD6 中定义的Web Service注释
1. @WebService 标注要暴露为Web Services的类或接口 ,用于申修饰类或接口,包含属性
targetNamespace 定义命名空间,默认为”http://”+”包名倒排”
name Web Service 的名称,默认为类名,例如:
<definitions targetNamespace="http://localhost/"
name="HelloWorldService">
portName Web Service 的端口名称
serviceName Web Service 的服务名称,例如
<service name="HelloWorldService">
<port name="HelloWorldPort"
binding="tns:HelloWorldPortBinding">
...
</port>
</service>
2. @SOAPBinding 定义Web Service 在SOAP中的消息协议,用于申修饰类或接口,包含属性
style 定义消息的编码类型
user 定义消息的格式化类型
3. @WebMethod 定义Web Service运作的方法,包含属性
action 操作的活动
operationName与此方法匹配的 wsdl:operation 的名称
exclude 标注此方法是否被暴露,默认为false
4. @WebResult 定义返回值,返回值类型不能为接口类或抽象类,而且必须有个不带参的构造函数,包含属性
name返回值的名称
partName表示此返回值的 wsdl:part 的名称
targetNamespace返回值的 XML 名称空间
header如果为 true,则结果是从消息头而不是消息正文获取的
5. @WebParam 定义方法的参数,参数类型不能为接口类或抽象类,而且必须有个不带参的构造函数,包含属性
name参数名称
partName表示此参数的 wsdl:part 的名称
targetNamespace参数的 XML 名称空间
header如果为 true,则结果是从消息头而不是消息正文获取的
mode参数的流向(IN、OUT 或 INOUT 之一)
JDK6.0的新特性:轻量级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
package jdk6;
import java.io.IOException;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpServer;
public class HTTPServerAPITester {
/**
* The main method.
*
* @param args the args
*/
public static void main(String[] args) {
try {
HttpServer hs = HttpServer.create(new InetSocketAddress(8888),0);//设置HttpServer的端口为8888
hs.createContext("/soddabao", new MyHandler());//用MyHandler类内处理到/chinajash的请求
hs.setExecutor(null); // creates a default executor
hs.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpServer;
public class HTTPServerAPITester {
/**
* The main method.
*
* @param args the args
*/
public static void main(String[] args) {
try {
HttpServer hs = HttpServer.create(new InetSocketAddress(8888),0);//设置HttpServer的端口为8888
hs.createContext("/soddabao", new MyHandler());//用MyHandler类内处理到/chinajash的请求
hs.setExecutor(null); // creates a default executor
hs.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package jdk6;
import java.io.IOException;
import java.io.OutputStream;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
// TODO: Auto-generated Javadoc
/**
* The Class MyHandler.
*/
public class MyHandler implements HttpHandler {
/* (non-Javadoc)
* @see com.sun.net.httpserver.HttpHandler#handle(com.sun.net.httpserver.HttpExchange)
*/
public void handle(HttpExchange httpexchnge) throws IOException {
httpexchnge.getRequestBody();
String response = "<h3>Happy New Year 2007!--Soddabao</h3>";
httpexchnge.sendResponseHeaders(200, response.length());
OutputStream os = httpexchnge.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
import java.io.IOException;
import java.io.OutputStream;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
// TODO: Auto-generated Javadoc
/**
* The Class MyHandler.
*/
public class MyHandler implements HttpHandler {
/* (non-Javadoc)
* @see com.sun.net.httpserver.HttpHandler#handle(com.sun.net.httpserver.HttpExchange)
*/
public void handle(HttpExchange httpexchnge) throws IOException {
httpexchnge.getRequestBody();
String response = "<h3>Happy New Year 2007!--Soddabao</h3>";
httpexchnge.sendResponseHeaders(200, response.length());
OutputStream os = httpexchnge.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
浙公网安备 33010602011771号