jax-ws開發深入
JAX-WS注解
注解說明
WebService的注解都位於javax.jws包下:
@WebService-定義服務,在public class上邊
targetNamespace:指定命名空間
name:portType的名稱
portName:port的名稱
serviceName:服務名稱
@WebMethod-定義方法,在公開方法上邊
operationName:方法名
exclude:設置為true表示此方法不是webservice方法,反之則表示webservice方法
@WebResult-定義返回值,在方法返回值前邊
name:返回結果值的名稱
@WebParam-定義參數,在方法參數前邊
name:指定參數的名稱
作用:
通過注解,可以更加形像的描述Web服務。對自動生成的wsdl文檔進行修改,為使用者提供一個更加清晰的wsdl文檔。
當修改了WebService注解之后,會影響客戶端生成的代碼。調用的方法名和參數名也發生了變化
注解示例:
/** * 天氣查詢服務接口實現類 * @author SMN * @version V1.0 */ @WebService(targetNamespace="http:// webservice.itcast.cn", serviceName="weatherService", portName="weatherServicePort", name="weatherServiceInterface" ) public class WeatherInterfaceImpl implements WeatherInterface { @WebMethod(operationName="queryWeather") public @WebResult(name="weatherResult")String queryWeather( @WebParam(name="cityName")String cityName) { System.out.println("from client.."+cityName); String result = "晴朗"; System.out.println("to client..."+result); return result; } public static void main(String[] args) { //發送webservice服務 Endpoint.publish("http://192.168.1.100:1234/weather", new WeatherInterfaceImpl()); } }
使用注解注意
@WebMethod對所有非靜態的公共方法對外暴露為服務.
對於靜態方法或非public方法是不可以使用@WebMethod注解的.
對public方法可以使用@WebMethod(exclude=true)定義為非對外暴露的服務。
jax-ws發布為web工程
將webservice發布在web工程可以使用webservice接口和web應用的其它鏈接共存。
Jax-ws開發的webservice 發布至web容器需要使用jax-wsRI(擴展實現), https://jax-ws.java.net/下載jax-wsRI最新版本,本次使用jaxws-ri-2.2.8版本。
第一步:下載jaxws-ri-2.2.8的擴展包
第二步:創建web工程
第三步:將擴展包中的jar拷貝至web工程下
第四步:編寫服務端代碼,編寫方法與之前我們學習的jax-ws方法一致
如果需要生成soap1.2在@WebServer下添加:
@BindingType(value="http://www.w3.org/2003/05/soap/bindings/HTTP/")
package cn.itcast.weather.server; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import javax.jws.WebService; import javax.xml.ws.BindingType; import javax.xml.ws.Endpoint; /** * 使用jax-ws開發webservice * 數據類型采用自定義對象類型,list等 * */ @WebService(name="WeatherServer",serviceName="WeatherServerService",portName="WeatherServerPort") public class ServerJws { /** * 通過城市查詢天氣信息,返回未來兩天的天氣信息 */ public List<WeatherModule> queryWeatherByCity(String city){ System.out.println("正在查詢"+city+"的天氣..."); //未來三天的天氣信息 List<WeatherModule> weathers = new ArrayList<WeatherModule>(); //今天的天氣 WeatherModule weatherModule1 = new WeatherModule(); //城市 weatherModule1.setCityName(city); //日期 Date date1 = new Date(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyy年MM月dd日"); String datesString1 = simpleDateFormat.format(date1); weatherModule1.setDate(datesString1); //天氣 weatherModule1.setWeather("晴"); //溫度 weatherModule1.setTemperature("最高溫度11度,最低溫度1度"); weathers.add(weatherModule1); //明天的天氣 WeatherModule weatherModule2 = new WeatherModule(); //城市 weatherModule2.setCityName(city); //日期 //創建日歷對象 Calendar calendar = Calendar.getInstance(); int day = calendar.get(Calendar.DATE); //明天的日期 calendar.set(Calendar.DATE, day+1); Date date2 = calendar.getTime(); String datesString2 = simpleDateFormat.format(date2); weatherModule2.setDate(datesString2); //天氣 weatherModule2.setWeather("陰"); //溫度 weatherModule2.setTemperature("最高溫度10度,最低溫度-1度"); weathers.add(weatherModule2); return weathers; } public static void main(String[] args) { } }
第五步:使用wsgen生成wsdl
在WEB-INF下創建wsdl目錄,此目錄存放生成的wsdl文件。
1、Cmd進入命令行
2、cd 工程目錄
3、執行wsgen
格式為:
wsgn [–wsdl] –cp <服務接口或類> [-r]
-cp classpath(注意都是相對與當前目錄)
-r wsdl路徑(注意都是相對與當前目錄)
注意:如果要發布soap1.2協議,必須這里使用方法-wsdl:Xsoap1.2生成wsdl,
另外,服務類添加
@BindingType(value="http://www.w3.org/2003/05/soap/bindings/HTTP/")
Soap1.1方式
wsgen -wsdl:soap1.1 -cp WebRoot\WEB-INF\classes cn.itcast.weather.server.ServerJws -r WebRoot\WEB-INF\wsdl
soap1.2方式
wsgen -wsdl:Xsoap1.2 -extension -cp WebRoot\WEB-INF\classes cn.itcast.weather.server.ServerJws -r WebRoot\WEB-INF\wsdl
第六步:在web工程的WEB-INF下創建sun-jaxws.xml文件
如果生成soap1.1內容下:
<?xml version="1.0" encoding="UTF-8"?> <endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'> <endpoint name='ServerJws' implementation='cn.itcast.weather.server.ServerJws' wsdl='WEB-INF/wsdl/WeatherServerService.wsdl' url-pattern='/ webservice /weather' /> </endpoints>
url-pattern:為webservice服務地址
如果生成soap1.2的方式:
<?xml version="1.0" encoding="UTF-8"?> <endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'> <endpoint name='WeatherServer' implementation='cn.itcast.ws.server.WeatherServer' wsdl='WEB-INF/wsdl/WeatherServerService.wsdl' binding="http://www.w3.org/2003/05/soap/bindings/HTTP/" url-pattern='/ webservice /weather '/> </endpoints>
url-pattern:為webservice服務地址
第七步:在web工程的web.xml中添加監聽及servlet
<listener> <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class> </listener> <servlet> <servlet-name> webservice </servlet-name> <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name> webservice </servlet-name> <url-pattern>/webservice/*</url-pattern> </servlet-mapping>
Web.xml中/ webservice /必須和sun-jaxws.xml中的url-pattern="/ webservice / "相匹配。
通常將<url-pattern>定義為/ws/*,以/ws/匹配url,匹配到了則按webservice解析, sun-jaxws.xml的url-pattern也必須配置成/ws/XXXX
第八步:啟動tomcat
訪問tomcat下的web工程即可(http://ip:端口/工程目錄/webservice/weather)
注意:web.xml中servlet解析的路徑要和sun-jaxws.xml中的一致
什么是CXF
Apache CXF = Celtix + Xfire,開始叫 Apache CeltiXfire,后來更名為 Apache CXF 了,以下簡稱為 CXF。Apache CXF 是一個開源的 web Services 框架,CXF 幫助您構建和開發 web Services ,它支持多種協議,比如:SOAP1.1,1,2、XML/HTTP、RESTful HTTP 或者 CORBA。
CORBA(Common Object Request Broker Architecture公共對象請求代理體系結構,早期語言使用的WS。C,c++,C#)
Cxf是基於SOA總線結構,依靠spring完成模塊的集成,最終SOA方式。
靈活的部署:可以運行有Tomcat,Jboss,Jetty(內置),weblogic上面。
CXF的安裝及配置
從官網下載2.7.11

環境變量配置:
JAVA_HOME,
CXF_HOME=cxf的目錄
Path = %JAVA_HOME%\bin;%CXF_HOME%\bin;
CLASSPATH=.;%CXF_HOME%\lib\cxf-manifest.jar
CXF例子
第一步:創建java工程
第二步:將cxf的jar 包加入工程
第三步:創建服務接口和服務實現類
創建服務接口和服務類的方法同上邊章節描述,編寫SEI及SEI的實現。
注意:與jaxws編程不同的是將@WebService注解加在接口上邊。
服務接口:
使用cxf開發webservice這里只需要在接口上加@webservice注解即可,和jaxws開發不同。
@WebService(targetNamespace="http://service.itcast.cn/", name="WeatherInterface",//porttype的名稱 portName="WeatherInterfacePort", serviceName="WeatherInterfaceService" ) @BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING) public interface WeatherInterface { //根據城市名稱查詢未來三天的天氣 public List<WeatherModel> queryWeather(String cityName) throws Exception; }
服務接口實現類:
使用cxf開發不用在接口實現類上加@webservice注解,因為cxf發布服務時可以指定接口。
public class WeatherInterfaceImpl implements WeatherInterface { @Override public List<WeatherModel> queryWeather(String cityName) throws Exception { //構造三天的天氣結果 Calendar calendar = Calendar.getInstance(); int day = calendar.get(Calendar.DATE); WeatherModel weatherModel_1 = new WeatherModel(); weatherModel_1.setDate(new Date()); weatherModel_1.setDetail("晴朗"); weatherModel_1.setTemperature_max(30); weatherModel_1.setTemperature_min(23); WeatherModel weatherModel_2 = new WeatherModel(); calendar.set(Calendar.DATE, day+1); weatherModel_2.setDate(calendar.getTime()); weatherModel_2.setDetail("晴轉多雲"); weatherModel_2.setTemperature_max(28); weatherModel_2.setTemperature_min(21); WeatherModel weatherModel_3 = new WeatherModel(); calendar.set(Calendar.DATE, day+2); weatherModel_3.setDate(calendar.getTime()); weatherModel_3.setDetail("多雲轉小雨"); weatherModel_3.setTemperature_max(25); weatherModel_3.setTemperature_min(18); List<WeatherModel> list = new ArrayList<WeatherModel>(); list.add(weatherModel_1); list.add(weatherModel_2); list.add(weatherModel_3); return list; } }
發布服務類:
package cn.itcast.ws.jaxws.server; import org.apache.cxf.jaxws.JaxWsServerFactoryBean; /** * CXF發布jaxws服務類 * @author Thinkpad * */ public class Server { /** * @param args */ public static void main(String[] args) { //創建服務工廠bean JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean(); //指定服務接口 jaxWsServerFactoryBean.setServiceClass(WeatherServerInterface.class); //指定服務實現對象 jaxWsServerFactoryBean.setServiceBean(new WeatherInterfaceImpl()); //指定webservice的地址 jaxWsServerFactoryBean.setAddress("http://192.168.1.100:1234/weather"); //創建webservice服務 jaxWsServerFactoryBean.create(); } }
第四步:根據wsdl地址生成客戶端代碼
我們分別使用wsimport和wsdl2java生成客戶端代碼,都可以正常使用。
**wsdl2java可以生成soap1.1和soap1.2
wsdl2java生成客戶代碼
先讓我們了解一下cxf的wsdl2java工具,它的功能就如同wsimport一樣,可以生成一堆客戶端調用的代碼。
在命令行執行:
wsdl2java –d . http://192.168.1.100:1234/weather?wsdl
注意:
生成后WeatherService報錯:
原因是cxf需要JAX-WS API 2.2而jdk6的jax-ws是2.1 版本,需要
wsdl2java 使用“-frontend jaxws21“
即如下:
wsdl2java –d . –frontend jaxws21 http://localhost:1234/weather?wsdl
第五步:編寫客戶端:
方式1、使用javax.xml.ws.Service調用客戶端
package cn.itcast.ws.jaxws.client; import java.net.MalformedURLException; import java.net.URL; import javax.xml.namespace.QName; import javax.xml.ws.Service; import cn.itcast.ws.jaxws.server.WeatherServerInterface; public class Client3 { public static void main(String[] args) throws MalformedURLException { //創建URL,資源定位 URL url = new URL("http://192.168.1.100:1234/weather?wsdl"); //Qname,確定命名空間地址,和服務視圖名稱 QName qName = new QName("http://service.itcast.cn/", "WeatherInterfaceService"); //創建service Service service = Service.create(url, qName); //創建porttype(服務端點) WeatherInterface weatherInterface = service.getPort(WeatherInterface.class); //通過服務端點調用服務方法 weatherServerInterface.queryWather("鄭州"); } }
方式2、JaxwsProxyFactoryBean調用服務端:
//創建代碼工廠bean JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean(); //設置接口類型(portType) jaxWsProxyFactoryBean.setServiceClass(WeatherInterface.class); //設置webservice地址 jaxWsProxyFactoryBean.setAddress("http://192.168.1.100:1234/weather"); //創建portType調用實例 WeatherInterface weatherInterface =(WeatherInterface) jaxWsProxyFactoryBean.create(); //調用webservice weatherServerInterface.queryWather("鄭州");
SOAP1.2生成
在服務接口和服務類的上面都添加
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
如下:
@WebService
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface WeatherServerInterface
@WebService(endpointInterface = "cn.itcast.ws.jaxws.server.WeatherServerInterface")
@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public class WeatherServer implements WeatherServerInterface
Cxf與spring集成
第一步:建立一個web項目
第二步:填充CXF JAR包。
第三步:創建服務接口及服務類
服務接口:
@WebService(targetNamespace="http://service.itcast.cn/", name="WeatherInterface",//porttype的名稱 portName="WeatherInterfacePort", serviceName="WeatherInterfaceService" ) @BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING) public interface WeatherInterface { //根據城市名稱查詢公網天氣服務接口 public List<String> queryWeather(String cityName) throws Exception; }
服務實現類:
需求:服務類需要調用公網天氣查詢客戶端。
public class WeatherInterfaceImpl implements WeatherInterface { //此為公網查詢客戶端需要通過spring配置並注入 private WeatherWebServiceSoap weatherWebServiceSoap; @Override public List<String> queryWeather(String cityName) throws Exception { ArrayOfString arrayOfString = weatherWebServiceSoap.getWeatherbyCityName("鄭州"); List<String> results = arrayOfString.getString(); for(String result:results){ System.out.println(result); } return results; } public WeatherWebServiceSoap getWeatherWebServiceSoap() { return weatherWebServiceSoap; } public void setWeatherWebServiceSoap(WeatherWebServiceSoap weatherWebServiceSoap) { this.weatherWebServiceSoap = weatherWebServiceSoap; } }
公網天氣查詢代碼生成
將上邊章節生成的公網天氣查詢客戶端調用代碼考入本工程。
生成方法在此不再贅述。
第四步:創建applicationContext.xml
將applicationContext.xml放在WEB-INF下
內容如下:
<?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"> <!-- 配置發布webservice服務 --> <jaxws:server address="/weather" serviceClass="cn.itcast.webservice.jaxws.server.WeatherInterface"> <jaxws:serviceBean> <ref bean="weatherInterface"/> </jaxws:serviceBean> </jaxws:server> <!-- 公網天氣查詢客戶端 --> <jaxws:client id="weatherClient" serviceClass="cn.com.webxml.WeatherWebServiceSoap" address="http://www.webxml.com.cn/WebServices/WeatherWebService.asmx" /> <!-- 本系統對外服務的天氣查詢service --> <bean id="weatherInterface" class="cn.itcast.webservice.jaxws.server.WeatherInterfaceImpl" > <property name="weatherWebServiceSoap" ref="weatherClient" /> </bean> </beans>
第五步:在web.xml配置Spring環境
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
第六步:在web.xml配置CXF的servlet
<servlet> <servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cxf</servlet-name> <url-pattern>/ws/*</url-pattern> </servlet-mapping>
第七步:啟動web容器
訪問:http://192.168.1.100:8080/.../ws/weather?wsdl
第八步:編寫客戶端工程
客戶端創建同前邊章節,此處不再贅述。
