WebService使用介绍(三)
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
第八步:编写客户端工程
客户端创建同前边章节,此处不再赘述。