Webservice是一套遠程調用技術規範javascript
遠程調用RPC, 實現了系統與系統進程間的遠程通訊.
java領域有不少可實現遠程通信的技術,如:RMI(Socket + 序列化)、Binary-RPC(Http+二進制, 表明Hessian)、XML-RPC(Http+XML, 表明Burlap, WebService用的SOAP)、JMS(使用消息機制)、Mina(使用NIO)等, 底層都是基於http/socket和網絡IO來實現的.
從效率上來說, RMI > Hessian >> Burlap >> web service.html
構成webservice的幾個要素:java
1.WSDL:web服務描述語言. 即webservice服務的使用說明書, 自動生成,無需編寫web
經過訪問相似http://127.0.0.1:12345/weather?wsdl的地址能夠查看
它長以下這樣子, 閱讀順序從下往上spring
2.SOAP:簡單對象訪問協議 http post + xml
必有 envelope 標籤,將XML文檔標識爲一條 SOAP 消息
必有 body 標籤,傳輸的信息
可選 header 標籤,包含頭部信息
可選 fault 標籤,提供有關在處理此消息所發生錯誤的信息apache
SOAP經常使用有1.1, 1.2兩個版本. jdk的Jaxws只支持發佈SOAP1.1服務.json
如要SOAP1.2服務, 須要引入jaxws-ri, 並在實現類上加入註解@BindingType(SOAPBinding.SOAP12HTTP_BINDING)
3.UDDI:提供webservice服務的註冊和搜索功能, 不實用瀏覽器
服務端網絡
public interface WeatherInterface { public String queryWeather(String cityName); }
// 實現類前加WebService註解
//@BindingType(SOAPBinding.SOAP12HTTP_BINDING) @WebService public class WeatherImpl implements WeatherInterface { @Override public String queryWeather(String cityName) { String weather = "晴"; return weather; } }
public class WeatherServer { public static void main(String[] args) { //Endpoint發佈服務, 參數1: 服務地址, 參數2: 服務實現類 Endpoint.publish("http://127.0.0.1:12345/weather", new WeatherImpl()); } }
對於定義的服務實現類, 能夠用註解進行修飾app
@WebService 定義服務,在類上邊
targetNamespace:指定命名空間
name:portType的名稱
portName:port的名稱
serviceName:服務名稱
endpointInterface:若是一個服務類實現了多個服務接口,但只須要發佈一個接口的方法,可經過此註解指定要發佈服務的接口
@WebMethod 定義方法,在方法上邊
operationName:方法名
exclude:設置爲true表示此方法不是webservice方法,不會發布,默認是false
@WebResult 定義返回值,在方法返回值前邊
name:返回結果值的名稱
@WebParam 定義參數,在方法參數前邊
name:指定參數的名稱
客戶端
首先, 用命令wsimport -s . http://127.0.0.1:12345/weather?wsdl生成支持類, 導入工程中
第一種使用方式 使用相關類
public class Client1 { public static void main(String[] args) throws IOException { // WSDL的地址, 非服務地址 URL url = new URL("http://127.0.0.1:12345/weather?wsdl"); //建立服務名稱 //參數一: namespaceURI – WSDL文檔中 types/targetNamespace //參數二: localPart - 服務視圖名, WSDL文檔中 service-name QName qname = new QName("http://WebXml.com.cn/", "WeatherWS"); //建立服務視圖 //參數1: wsdlDocumentLocation WSDL地址 //參數2: serviceName 服務名稱 Service service = Service.create(url, qname); //獲取服務類 getPort(WSDL文檔中portType-name) WeatherWSSoap weatherWSSoap = service.getPort(WeatherWSSoap.class); //調用方法 WSDL文檔中portType-operation-name String result = weatherWSSoap.queryWeather("北京"); System.out.println(result); } }
第二種使用方式 http工具訪問
public class Client2 { public static void main(String[] args) throws IOException { // 服務地址 URL url = new URL("http://127.0.0.1:12345/weather"); // 建立鏈接對象 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 設置參數 // Http發送方式:POST必須大寫 connection.setRequestMethod("POST"); // content-type connection.setRequestProperty("content-type", "text/xml;charset=utf-8"); // 設置輸入輸出,默認connection沒有讀寫權限, connection.setDoInput(true); connection.setDoOutput(true); // 發送請求 String soapXML = getXML("北京"); OutputStream os = connection.getOutputStream(); os.write(soapXML.getBytes()); // 接收響應 int responseCode = connection.getResponseCode(); if(200 == responseCode){ InputStream is = connection.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); StringBuilder sb = new StringBuilder(); String temp = null; while(null != (temp = br.readLine())){ sb.append(temp); } System.out.println(sb.toString()); is.close(); isr.close(); br.close(); } os.close(); } // 組織SOAP數據 public static String getXML(String cityName){ String soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +"<soap:Body>" +"<getWeatherInfo xmlns=\"http://WebXml.com.cn/\">" +"<cityName>"+cityName+"</cityName>" +"<userID></userID>" +"</getWeatherInfo>" +"</soap:Body>" +"</soap:Envelope>"; return soapXML; } }
第三種使用方式 瀏覽器訪問
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javascript"> function queryWeather() { var xhr = new XMLHttpRequest(); xhr.open("post", "http://127.0.0.1:12345/weather", true); xhr.setRequestHeader("content-type","text/xml;charset=utf-8"); //設置回調函數 xhr.onreadystatechange=function(){ if(4 == xhr.readyState && 200 == xhr.status){ alert(xhr.responseText); } } //組織SOAP協議數據 var soapXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +"<soap:Body>" +"<getWeatherInfo xmlns=\"http://WebXml.com.cn/\">" +"<cityName>"+document.getElementById("cityName").value+"</cityName>" +"<userID></userID>" +"</getWeatherInfo>" +"</soap:Body>" +"</soap:Envelope>"; //發送數據 xhr.send(soapXML); } </script> </head> <body> 天氣查詢:<input type="text" id="cityName"/> <input type="button" value="查詢" onclick="javascript:queryWeather();"/> </body> </html>
CXF是一個開源的webservice框架
CXF支持SOAP1.1/1.2,REST 協議
CXF支持XML,JSON(僅REST下) 的數據格式
服務端 JAX-WS方式(SOAP)
//@BindingType(SOAPBinding.SOAP12HTTP_BINDING) 默認發佈SOAP1.1, 該註解發佈SOAP1.2 @WebService public interface WeatherInterface { public String queryWeather(String cityName); }
public class WeatherImpl implements WeatherInterface { @Override public String queryWeather(String cityName) { String weather = "晴"; return weather; } }
//與spring整合後可不要該類 public class WeatherServer { public static void main(String[] args) { JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean(); //設置服務接口 jaxWsServerFactoryBean.setServiceClass(WeatherInterface.class); //設置服務實現類 jaxWsServerFactoryBean.setServiceBean(new WeatherImpl()); //設置服務地址 jaxWsServerFactoryBean.setAddress("http://127.0.0.1:12345/ws/weather"); //發佈 jaxWsServerFactoryBean.create(); } }
與web整合, spring+CXFservlet替代WeatherServer類
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd"> <!-- 服務實現類 --> <bean id ="weatherImpl" class="com.zx.server.WeatherImpl"/> <!-- 攔截器 -- <bean id ="inIntercepter" class="org.apache.cxf.interceptor.LoggingInInterceptor"/> <bean id ="outIntercepter" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/> --> <!-- 方式1 用JaxWsServerFactoryBean發佈SOAP協議的服務 --> <jaxws:server address="/weather" serviceClass="com.zx.server.WeatherInterface"> <jaxws:serviceBean> <ref bean="weatherImpl"/> <!-- 實現類 --> </jaxws:serviceBean> <!-- 配置攔截器 -- <jaxws:inInterceptors> <ref bean="inIntercepter"/> </jaxws:inInterceptors> <jaxws:outInterceptors> <ref bean="outIntercepter"/> </jaxws:outInterceptors> --> </jaxws:server> <!-- 方式2 用Endpoint發佈SOAP協議的服務 --> <jaxws:endpoint address="/weather" implementor="com.zx.server.WeatherImpl"/> </beans>
endPoint 只支持發佈實現類
JaxWsServerFactoryBean還能夠發佈接口
web.xml
<!-- 配置CXF的Servlet --> <servlet> <servlet-name>CXF</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CXF</servlet-name> <url-pattern>/ws/*</url-pattern> </servlet-mapping>
客戶端
首先, 相似wsimport, 使用CXF下的Wsdl2java生成支持類, 導入工程中
public class WeatherClient { public static void main(String[] args) { JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean(); //設置服務接口 jaxWsProxyFactoryBean.setServiceClass(WeatherInterface.class); //設置服務地址 jaxWsProxyFactoryBean.setAddress("http://127.0.0.1:12345/ws/weather"); //獲取服務接口, 可與spring整合替代 WeatherInterface weatherInterface = jaxWsProxyFactoryBean.create(WeatherInterface.class); //調用查詢方法 String weather = weatherInterface.queryWeather("保定"); System.out.println(weather); } }
與spring整合後由spring生成weatherInterface實例
<!-- 用JaxWsProxyFactoryBean創建客戶端 --> <jaxws:client id="weatherClient" address="http://127.0.0.1:12345/ws/weather" serviceClass="com.zx.WeatherInterface"/>
服務端 JAX-RS方式(REST風格)
基礎bean
@XmlRootElement(name="student") //能被格式化爲XML public class Student { private long id; private String name; private Date birthday; public getXXX(), setXXX(); // get set方法 }
服務接口
@WebService @Path("/student") //將請求路徑「/student」映射到接口上 public interface StudentInterface { @POST // 指定請求方式 GET / POST @Produces(MediaType.APPLICATION_XML) //指定服務數據類型 XML / JSON @Path("/query/{id}") //將請求路徑/query映射到方法上, 參數注入配合@PathParam註解 public Student query(@PathParam("id")long id); @GET @Produces({"application/json;charset=utf-8",MediaType.APPLICATION_XML}) //同時指定json和xml, 添加訪問參數?_type=json返回json; 添加?_type=xml返回XML @Path("/queryList/{name}") public List<Student> queryList(@PathParam("name")String name); }
服務實現, 僅舉例
public class StudentImpl implements StudentInterface { @Override public Student query(long id) { Student st = new Student(); st.setId(110); st.setName("張三"); st.setBirthday(new Date()); return st; } @Override public List<Student> queryList(String name) { Student st = new Student(); st.setId(110); st.setName("張三"); st.setBirthday(new Date()); List<Student> list = new ArrayList<Student>(); list.add(st); return list; } }
發佈
public class StudentServer { public static void main(String[] args) { //JAXRSServerFactoryBean 發佈REST的服務 JAXRSServerFactoryBean jaxRSServerFactoryBean = new JAXRSServerFactoryBean(); jaxRSServerFactoryBean.setServiceBean(new StudentImpl()); jaxRSServerFactoryBean.setResourceClasses(StudentImpl.class); jaxRSServerFactoryBean.setAddress("http://127.0.0.1:12345/ws/user"); jaxRSServerFactoryBean.create(); } }
與web整合, spring+CXFservlet替代StudentServer類
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd"> <!-- 配置服務實現類 --> <bean id = "studentImpl" class="com.zx.StudentImpl"/> <!-- 使用JAXRSServerFactoryBean發佈REST的服務 --> <jaxrs:server address="/user"> <jaxrs:serviceBeans> <ref bean="studentImpl"/> </jaxrs:serviceBeans> </jaxrs:server> </beans>
web.xml
<!-- 配置CXF的Servlet --> <servlet> <servlet-name>CXF</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CXF</servlet-name> <url-pattern>/ws/*</url-pattern> </servlet-mapping>
REST風格下WSDL訪問網址爲http://127.0.0.1:12345/ws/user?_wadl