1. 什么是WebService
Web Service也称为web服务,它是一种跨编程语言和操作系统平台的远程调用技术。Web Service采用标准的SOAP协议传输(SOAP:Simple Object Access Protocol简单对象访问协议,soap属于w3c标准。并且soap协议是基于http的应用层协议传输xml数据)。Web Service采用WSDL作为描述语言,也就是Web Service 的使用说明书。并且W3C为Web Service制定了一套传输数据类型,使用xml进行描述,即XSD(XML Schema Datatypes),任何语言写的web Service 接口在发送数据的时候都要转换成WebService标准的XSD发送。
2. WebService的三要素
2.1 SOAP
SOAP也叫做简单对象访问协议,是一种简单的基于xml的协议,它使应用程序通过HTTP来交换数据,可以简单的理解为SOAP= http+xml。SOAP协议目前的主流版本为:SOAP1.1和SOAP1.2(soap1.2是被纳入w3c标准后的版本)。SOAP也不是WebService的专有协议,其它的应用程序也是用soap传输数据。例如:tr069也是使用soap协议来传输数据。
区分http请求和SOAP(SOAP=Http+XML)请求:
2.1.1SOAP协议格式
1.必须有Envelope元素,此元素将整个xml文档表示为一条SOAP消息。
2.可选Header元素,包含头部信息。
3.必须有Body元素,包含所有的调用和响应信息。
4.可选的Fault元素,提供有关在处理此消息所发生的错误信息。
2.1.2 SOAP1.1协议:
Jaxws支持SOAP1.1服务端发布:
请求信息:
POST /weather HTTP/1.1 Accept: text/xml, multipart/related Content-Type: text/xml; charset=utf-8 SOAPAction: "http://ws.jaxws.ws.itcast.cn/WeatherInterfaceImpl/queryWeatherRequest" User-Agent: JAX-WS RI 2.2.4-b01 Host: 127.0.0.1:54321 Connection: keep-alive Content-Length: 214 <?xml version="1.0" ?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body><ns2:queryWeather xmlns:ns2="http://ws.jaxws.ws.itcast.cn/"><arg0>北京</arg0></ns2:queryWeather> </S:Body> </S:Envelope> |
响应信息:
HTTP/1.1 200 OK Transfer-encoding: chunked Content-type: text/xml; charset=utf-8 Date: Thu, 26 Nov 2015 03:14:29 GMT <?xml version="1.0" ?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:queryWeatherResponse xmlns:ns2="http://ws.jaxws.ws.itcast.cn/"><return>晴</return></ns2:queryWeatherResponse> </S:Body> </S:Envelope> |
2.13 SOAP1.2
Jaxws不支持支持直接SOAP1.2服务端发布,直接发布会报ServiceRtException异常。
那么该怎么发布SOAP1.2的服务端呢?1.需要导入第三方jar包(jaxws-ri-2.2.8)2.在实现类中添加@BindingType(SOAP12HTTP_BINDING)注解。
请求信息:
POST /weather HTTP/1.1 Accept: application/soap+xml, multipart/related Content-Type: application/soap+xml; charset=utf-8; action="http://ws.jaxws.ws.itcast.cn/WeatherInterfaceImpl/queryWeatherRequest" User-Agent: JAX-WS RI 2.2.4-b01 Host: 127.0.0.1:54321 Connection: keep-alive Content-Length: 212 <?xml version="1.0" ?> <S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"> <S:Body><ns2:queryWeather xmlns:ns2="http://ws.jaxws.ws.itcast.cn/"><arg0>北京</arg0></ns2:queryWeather> </S:Body> </S:Envelope> |
HTTP/1.1 200 OK Transfer-encoding: chunked Content-type: application/soap+xml; charset=utf-8 Date: Thu, 26 Nov 2015 03:25:24 GMT <?xml version='1.0' encoding='UTF-8'?> <S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"> <S:Body> <ns2:queryWeatherResponse xmlns:ns2="http://ws.jaxws.ws.itcast.cn/"><return>晴</return></ns2:queryWeatherResponse> </S:Body> </S:Envelope> |
2.1.4 SOAP1.1和SOAP1.2区别
相同点:
1.请求方式都是采用的POST方式
2.协议内容相同:都有Envelope和Body标签。
不同的:
1.数据格式不同:content-type不同。
SOAP1.1:text/xml;charset=utf-8
SOAP1.2:application/soap+xml;charset=utf-8
2.命名空间不同。
SOAP1.1:http://schemas.xmlsoap.org/soap/envelope/
SOAP1.2:http://www.w3.org/2003/05/soap-envelope
2.2 WSDL
WSDL是基于XML的用于描述Web Service 及其函数(方法)、参数和返回值。也就是说wsdl是对发布出来的服务中的方法和返回值以及参数的描述(可以成为是WebService的使用说明书)。
WSDL文档结构:
WSDL文档主要包括5个标签:
1.<service> :服务视图,WebService的服务结点,它包括服务端点。
2.<binding> :为每个服务端点定义消息格式和协议细节。
3.<portType> :服务端点,描述WebService可执行的操作方法,以及相关的消息,通过binding指向portType。
4.<message> :定义一个操作(方法)的数据参数(可有多个参数)
5.<type> :定义WebService使用的全部数据类型。
WSDL文档阅读方式:从下往上。
2.3 UDDI
UDDI是一种目录服务,通过它,企业可注册并搜集Web Service。企业将自己提供的Web Service注册在UDDI,也可以使用别的企业在UDDI注册Web Service服务,从而达到资源共享。UDDI旨在将全球的Web Service资源进行共享。
3. WebService开发规范
3.1 JAX-WS
JAX-WS(Java API for XML-Based Web Service):一个远程调用可以转换为基于XML协议(例如:SOAP协议),在使用JAX-WS过程中,开发者不需要使用任何代码来编写生成和处理SAOP。JAX-WS运行时会自动将这些API调用转换为SAOP协议的消息。
在服务端,用户只需要通过Java语言定义远程调用所需要实现的接口(SEI:Service EndPoit Interface),并对其提供相关的实现,通过调用JAX-WS的服务来腹部接口就可以发布为Web Service 接口啦。
在客户端,用户可以通过JAX-WS的API来创建一个代理来(用本地代理对象来替代远程的服务对象)实现远程服务端的调用。(在使用JAX-WS生成远程服务端的代理可以使用 wsimport(这个命令是jdk自带的)命令来自动生成,下面会对其进行具体讲解)
从Java5开始就支持JAX-WS2.0版本,Java6以后的版本支持JAX-WS2.1版本,Java1.7支持JAX-WS2.2的版本。
3.2 JAXM&SAAJ
JAXM(Java API for XML Message):主要定义了包含接收信息和发送信息所需要的API,SAAJ(SOAP With Attachment API For Java)是与JAXM搭配使用的API,为构建SOAP和解析SOAP包提供了重要的支持,支持附件传输等。
3.3 JAX-RS
JAX-RS是Java针对REST(Representtation state Transfer)风格制定的一套Web服务规范,由于该规范推出来的较晚,因此该规范(JAX-WS的版本为1.0)并未随Java6一起发行。
4. WebService应用场景
适用场景:
1.用于软件集成和复用。
2.用于接口服务,不考虑客户端类型,不考虑性能。
3.服务端已经确定使用了WebService,客户端只能选择WebService使用。
不适用场景:
1.对性能要求比较高(因为WebService是采用http发送soap协议的数据,该协议迭代了太多的标签,导致数据很多,因此性 能也有所降低)。
2.同构程序之间不建议使用。
5. wsimport命令介绍
wsimport命令是jdk自带的web service 客户端工具,可以根据wsdl文档生成对服务带代理类(客户端调用类),当然不管服务端是用什么语言写的,都可以生成调用WebService的客户端代码,服务端通过客户端调用WebService。
wsimport命令常用参数为:
-d<目录> :指定放置生成的输出文件的位置。
-s<目录> :指定放置生成的源文件的位置。
-p<包名> : 指定目标程序包。
例如:wsimport -p com.test -s . http://webService.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
6. 发布第一个JAX-WS的Web Service服务
第一步创建SEI接口(本质上就是Java接口):
public interface WeatherInterface { public String querryWeather(String cityName); }
第二步创建接口的实现类:
@WebService注解:表示该实现类是一个Web Service服务。
targetNamespace属性:指定命名空间。
name属性:指定portType的名称。
serviceName属性:服务名称。
@WebMethod注解:定义公共方法。
operationName属性:方法的名称。(也就是WSDL中的operation的名称)
exclude属性:如果设置为true表示该方法不是Web Service服务中的方法。反之则是WebService中的方法。默认也是false。
@WebResult注解:定义返回值。
name属性:返回结果值的名称
@WebParam注解:定义参数。
name属性:指定参数的名称。
@WebService( targetNamespace="http://service.cn_lc", name="WeatherWSSoap", portName="WeatherWSSoapPort", serviceName="WeatherWS" )//只加这个注解就只能生成SAOP1.1的WSDL //@BindingType(SOAPBinding.SOAP12HTTP_BINDING) public class WeatherInterfaceImpl implements WeatherInterface { @WebMethod( operationName="getWeather", exclude=false ) @Override public @WebResult(name="resultWeather")String querryWeather(@WebParam(name="cityName")String cityName) { System.out.println("form client ..." + cityName); String weather = "晴"; return weather; } }第三步,通过Endpoint发布Web Service 服务(Endpoint只能发布实现类,而不能发布接口):
public class WeatherServer { public static void main(String[] args) { /** * 参数解释: * address:服务器地址 * implementor:实现类 */ Endpoint.publish("http://127.0.0.1:12345/weather",new WeatherInterfaceImpl()); } }
第四步,测试服务是否发布成功,通过阅读发布服务的WSDL就可以验证。访问:http://127.0.0.1:12345/weather?wsdl(由于服务发布在本机上,所以地址是:127.0.0.1):
通过访问该地址浏览到WSDL就证明该服务发布成功:
7. WebService的四种客户端调用方式
7.1第一种通过wsimport生成客户端方式调用
第一步:通过wsimport生成客户端代码:
wsimport -p com.test.jaxws -s . http://127.0.0.1:12345/weather?wsdl
第二步:阅读使用说明书WSDL,使用生成客户端代码调用服务端:
public class WeatherClient { public static void main(String[] args) { //创建服务视图 WeatherWS weatherInterfaceImplService = new WeatherWS(); //通过服务视图对象获取服务实现类 WeatherWSSoap weatherInterfaceImpl = weatherInterfaceImplService.getPort(WeatherWSSoap.class); //通过服务实现对象调用查询方法 System.out.println(weatherInterfaceImpl.getWeather("北京")); } }采用wsimport生成客户端代码方式的特点:这种方式使用简单,但是一些关键的元素(比如wsdl地址、命名空间、服务类名等都写死在生成的客户端代码中)写死在代码中,不方便后期维护,可以用于测试。
7.2第二种通过Service编程调用方式
第一步:通过wsimport生成客户端代码:
wsimport -p com.test.jaxws -s . http://127.0.0.1:12345/weather?wsdl
第二步:自己编写服务视图类,并通过该服务视图类来获取服务实现类实例:
public class WeatherClientDemo2 { public static void main(String[] args) throws IOException { //创建WSDL的URL,注意不是服务地址 URL url = new URL("http://127.0.0.1:12345/weather?wsdl"); //创建服务名称 //namespaceURI:命名空间地址。 //localPart:服务视图名。 QName qname = new QName("http://service.cn_lc","WeatherWS"); //创建服务视图 //1.wsdlDocumentLocation - wsdl地址 //2.serviceName - 服务名称 Service service = Service.create(url, qname); WeatherWSSoap weatherWSSoap = service.getPort(WeatherWSSoap.class); String result = weatherWSSoap.getWeather("成都"); System.out.println(result); } }采用service编程方式特点:该种方式可以自定义关键元素,方便以后维护,是一种标准开发方式。
7.3第三种通过HttpURLConnection调用方式
第一步:创建服务地址。
第二步:打开一个通向服务地址的连接。
第三步:设置参数(例如请求方式为POST)。
第四步:组织SOAP数据发送数据。
第五步:接收服务端响应,并打印。
public class WeatherClientDemo3 { public static void main(String[] args) throws IOException { //第一步:创建服务地址 URL url = new URL("http://127.0.0.1:54321/weather"); //第二步:打开一个通向服务端地址的连接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); //设置参数 connection.setRequestMethod("POST"); connection.setRequestProperty("content-type", "text/xml;charset=utf-8"); //设置输入输出 connection.setDoOutput(true); connection.setDoInput(true); //准备SOAP数据,发送请求 String soapxml = getXML("成都"); OutputStream out = connection.getOutputStream(); OutputStreamWriter writer = new OutputStreamWriter(out, "utf-8"); writer.write(soapxml); writer.close(); out.close(); //第五步接收服务端响应并打印 if(connection.getResponseCode()==HttpURLConnection.HTTP_OK) { InputStream input = connection.getInputStream(); InputStreamReader reader = new InputStreamReader(input,"utf-8"); BufferedReader buffered = new BufferedReader(reader); String temp = null; StringBuilder sb = new StringBuilder(); while((temp=buffered.readLine())!=null) { sb.append(temp); } buffered.close(); reader.close(); input.close(); System.out.println(sb.toString()); } } public static String getXML(String cityName) { return "<?xml version=\"1.0\" ?>" + "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">" + "<S:Body>" + "<ns2:getWeather xmlns:ns2=\"http://service.cn_lc\">" + "<cityName>"+cityName+"</cityName>" + "</ns2:getWeather>" + "</S:Body>" + "</S:Envelope>"; } }
7.4第四种,通过ajax方式调用服务端
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>查询天气</title> <script type="text/javascript"> function querryWeather(){ var xhr = new XMLHttpRequest(); xhr.open("post","http://127.0.0.1:12345/weather",true); //设置数据类型 xhr.setRequestHeader("content-type","text/xml;charset=utf-8"); //设置回调函数 if(4==xhr.readState && 200 == xhr.status){ alert(xhr.responseText); } //组织数据 var soapXml = "<?xml version=\"1.0\" ?>" + "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">" + "<S:Body>" + "<ns2:getWeather xmlns:ns2=\"http://service.cn_lc\">" + "<cityName>"+document.getElementById("cityName").value+"</cityName>" + "</ns2:getWeather>" + "</S:Body>" + "</S:Envelope>"; alert(soapXml); //发送数据 xhr.send(soapXml); } </script> </head> <body> <center> 天气查询:<input type="text" id="cityName" /><input type="button" value="查询" onclick="javascript:querryWeather();" /> </center> </body> </html>
8. CXF
8.1CXF介绍
第一:CXF是一个开源的Web Service 框架,提供了很多完善的功能,可以实现快速开发。
第二:CXF支持的协议有SOAP1.1/SOAP1.2,REST。
第三:CXF支持数据格式有XML,JSON(仅在REST方式下支持,不在SOAP方式下支持,因为SOAP是http+xml)
CXF的下载位置:http://cxf.apache.org/
CXF的安装和配置环境变量就不做详细介绍了,可以参考百度
8.2 CXF发布SOAP协议的服务
服务端:
第一步:导入下载下来的CXF文件下的lib文件下所有的jar包。
第二步:创建SEI接口,并在SEI接口上加@WebService注解表示当前接口为WebService的服务。
其它注解和上文中一样。
@WebService //@BindingType(SOAPBinding.SOAP12HTTP_BINDING)//发布SOAP1.2协议的服务 public interface WeatherInterface { public @WebResult(name="weatherResult")String querryWeather(@WebParam(name="cityName")String cityName); }
第三步:创建SEI的实现类。
public class WeatherInterfaceImpl implements WeatherInterface{ @Override public String querryWeather(String cityName) { System.out.println("from client ..." + cityName); return "晴"; } }
第四步:通过JaxWsServiceFactoryBean来发布服务。使用JaxWsServiceFactoryBean来发布服务需要设置接口、实现类和服务地址。也可以在发布之前添加拦截器。(Endpoint仅支持发布实现类,JaxWsServiceFactoryBean支持发布接口)
public class WeatherServer { public static void main(String[] args) { //通过JaxWsServerFactoryBean来发布服务 JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean(); //设置接口 jaxWsServerFactoryBean.setServiceClass(WeatherInterface.class); //设置实现类 jaxWsServerFactoryBean.setServiceBean(new WeatherInterfaceImpl()); //设置服务地址 jaxWsServerFactoryBean.setAddress("http://127.0.0.1:12345/weather"); //加入拦截器 jaxWsServerFactoryBean.getInInterceptors().add(new LoggingOutInterceptor()); jaxWsServerFactoryBean.getOutInterceptors().add(new LoggingInInterceptor()); //发布服务 jaxWsServerFactoryBean.create(); } }
第五步:测试发布服务是否成功。通访问WSDL地址是否存在。
客户端:
第一步:通过wsdl2java命令生成客户端代码。
1. wsdl2java命令是CXF提供的生成客户端的工具,他和wsimport类似,可以根据WSDL生成客户端代码。
2. wsdl2java常用参数:
-d指定输出目录。
-p指定包名,如果不指定该参数,默认包名就按命名空间的倒序。
-wsdl2java支持SOAP1.1和SOAP1.2(wsimport仅支持SOAP1.1)。
第二步:使用说明书,使用第一步生成的代码调用服务端。通过JaxWsProxyFactoryBean来获取服务端接口实例。在使用JaxWsProxyFactoryBean获取服务端接口实例需要设置服务端接口和设置服务端地址。
public class WeatherClient { public static void main(String[] args) { //通过JaxWsProxyFactoryBean来调用服务端 JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean(); //设置服务端接口 jaxWsProxyFactoryBean.setServiceClass(WeatherInterface.class); //设置服务端地址 jaxWsProxyFactoryBean.setAddress("http://127.0.0.1:12345/weather"); //获取服务接口实例 WeatherInterface weatherInterface =jaxWsProxyFactoryBean.create(WeatherInterface.class); //调用查询方法 String weather = weatherInterface.querryWeather("北京"); System.out.println(weather); } }
8.3 CXF+Spring整合发布SOAP协议的服务
服务端:
第一步:创建web项目并引用cxf相关的包。
第二步:创建SEI接口。
@WebService @BindingType(SOAPBinding.SOAP12HTTP_BINDING) public interface WeatherInterface { public @WebResult(name="weatherResult")String querryWeather(@WebParam(name="cityName")String cityName); }
第三步:创建SEI实现类。
public class WeatherInterfaceImpl implements WeatherInterface{ @Override public String querryWeather(String cityName) { System.out.println("from client ..." + cityName); return "晴"; } }
第四步:配置Spring配置文件applicationContext.xml来发布服务。
在Spring文件中配置发布服务是采用<jaxws:server>标签(也可以使用<jaxws:endpoint>标签来发布,该标签时对EndPoint的封装)来配置(jaxws标签就是JaxWsServiceFactoryBean的封装,因此在标签中需要设置服务地址和服务接口以及服务接口实现类。),因此需要给Spring的配置文件加载头信息。
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
http://cxf.apache.org/ http://cxf.apache.org/schemas/jaxrs. http://cxf.apache.org/ http://cxf.apache.org/schemas/jaxws.xsd
Spring配置文件内容为:
<?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"> <!-- 通过jaxws:server标签发布SOAP协议的服务。 该标签是对JaxWsServerFactoryBean的封装--> <jaxws:server address="/weather" serviceClass="com.lc.cxf_jaxws.WeatherInterface"> <jaxws:serviceBean> <ref bean="WeatherInterface"/> </jaxws:serviceBean> <!-- 添加拦截器 --> <jaxws:inInterceptors> <ref bean="inIntercepter"/> </jaxws:inInterceptors> <jaxws:outInterceptors> <ref bean="outIntercepter"/> </jaxws:outInterceptors> </jaxws:server> <!-- 配置拦截器 --> <bean id="inIntercepter" class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean> <bean id="outIntercepter" class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean> <!-- 配置服务实现类 --> <bean id="WeatherInterface" class="com.lc.cxf_jaxws.WeatherInterfaceImpl"></bean> </beans>
第五步:配置web.xml。在web.xml中主要配置Spring的配置文件地址和Spring监听器和CXFServlet。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>ws_2_cxf_spring_server</display-name> <!-- 配置Spring配置文件的位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!-- 配置Spring的监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置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> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
第六步:启动tomcat,并测试服务是否发布成功。(通过访问wsdl地址是否有使用说明书来判断是否发布成功:http://127.0.0.1:8080/spring_cxf_demo1(项目名称)/ws/weather?wsdl)。
客户端:
第一步:引入jar包。
第二步:采用wsdl2java命令生成客户端代码。
第三步:配置Spring的配置文件。
<?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"> <!-- 通过jaxws:client标签编写客户端。 该标签是对JaxWsClientProxyFactoryBean的封装--> <jaxws:client id="weather" address="http://127.0.0.1:12345/weather" serviceClass="com.lc.cxf_weather.WeatherInterface"/> </beans>
第四步:从Spring上下文件中获得服务实现类,并调用查询方法。
public class WeatherClient { public static void main(String[] args) { //初始化spring的上下文 ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); WeatherInterface weatherInterface = (WeatherInterface) context.getBean("weather"); String weather = weatherInterface.querryWeather("成都"); System.out.println(weather); } }
8.4 CXF发布REST的服务
什么是REST的服务:REST就是一种编程风格,它可以精确定位网上资源(服务接口、方法、参数)
REST支持数据格式:XML、JSON
REST支持发送方式:GET、POST。
这里就通过查询一个学生和查询多个学生来演示CXF发布REST服务。
服务端:
第一步:导入CXF的jar包。
第二步:创建学生Pojo类,并且在学生类上加上@XmlRootElement注解代表该类可以实现和XML数据之间的转换。
@XmlRootElement(name="student")//注解@XmlRootElement可以实现对象和xml数据的转换,name属性是改变xml数据的根标签 public class Student { private long id; private String name; private Date date; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }
第二步:创建SEI接口。
@WebService注解代表该类为WebService的服务。
@Path("/student")注解表示将接口映射到/student地址中。
@POST注解指定该方式是采用POST方式请求。
@Produces(String)注解指定服务数据类型。(也就是说服务是以xml还是其他方式来展示数据,一般都是设置为xml和json)
@Path("/querry/{id}/{name})注解表示把querry方法映射到/querry地址中,把参数映射到/{id}地址中。
@WebService @Path("/student")//注解@Path就是将/student路径映射到接口上 public interface StudentInterface { //查询一个学生 @POST @Produces(MediaType.APPLICATION_XML)//指定服务数据类型 @Path("/query/{id}")//注解@Path就是将请求路径/query映射到query方法上,并且把id映射到参数上多个参数以/分开,参数是写在{}中。 public Student query(@PathParam("id")long id); //查询多个学生 @GET @Produces({"application/xml","application/json;charset=utf-8"}) @Path("/queryList/{name}") public List<Student> queryList(@PathParam("name")String name); //根据多条件查询一个学生 @GET @Produces("application/xml") @Path("/query/{id}/{name}") public Student query(@PathParam("id")long id,@PathParam("name")String name); }
第三步:创建SEI的实现类。
public class StudentInterfaceImpl implements StudentInterface{ @Override public Student query(long id) { Student st = new Student(); st.setId(id); st.setName("张三"); st.setDate(new Date()); return st; } @Override public List<Student> queryList(String name) { Student st = new Student(); st.setId(100); st.setName("张三"); st.setDate(new Date()); Student st1 = new Student(); st1.setId(110); st1.setName("张三"); st1.setDate(new Date()); List<Student> list = new ArrayList<Student>(); list.add(st); list.add(st1); return list; } @Override public Student query(long id, String name) { Student st = new Student(); st.setId(id); st.setName(name); st.setDate(new Date()); return st; } }
第四步:通过JAXRSServiceFactoryBean发布服务,需要设置服务实现类、设置资源类、服务地址。
public class StudentServer { public static void main(String[] args) { //JAXRSServerFactoryBean 来发布服务 JAXRSServerFactoryBean jaxRSServerFactoryBean = new JAXRSServerFactoryBean(); //设置实现类 jaxRSServerFactoryBean.setServiceBean(new StudentInterfaceImpl()); //设置资源类 jaxRSServerFactoryBean.setResourceClasses(StudentInterfaceImpl.class); //设置服务地址 jaxRSServerFactoryBean.setAddress("http://127.0.0.1:12345/user"); //发布服务 jaxRSServerFactoryBean.create(); } }
第五步:测试服务是否发布成功。通过浏览器访问GET请求方式的方法,就用queryList方法为例:http://127.0.0.1:12345/user/student/queryList/张三。
客户端:
客户端可以通过HttpUrlConnection来访问,也可以通过ajax方式来访问,也可以通过HttpClient方式来访问(HttpClient是apahce的开源项目)
这里采用HttpUrlConnection来开发客户端:
public class StudentClient { public static void main(String[] args) throws IOException { //创建URL连接 URL url = new URL("http://127.0.0.1:12345/user/student/query/132"); //打开连接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); //设置请求方式 connection.setRequestMethod("POST"); //设置可输入 connection.setDoInput(true); //获取数据 if(connection.getResponseCode()==HttpURLConnection.HTTP_OK) { InputStream in = connection.getInputStream(); InputStreamReader reader = new InputStreamReader(in,"utf-8"); BufferedReader bReader = new BufferedReader(reader); String line = null; StringBuilder sb = new StringBuilder(); while((line=bReader.readLine())!=null) { sb.append(line); } in.close(); reader.close(); bReader.close(); System.out.println(sb.toString()); } } }
8.5 CXF+Spring整合发布REST的服务
服务端:
第一步:创建web工程并导入jar包
第二步:创建pojo类(上同)
第三步:创建SEI接口(上同)
第四步:创建SEI接口类的实现(上 同)
第五步:配置Spring的配置文件。采用<jaxrs:server>标签来配置发布REST服务,需要设置服务地址和服务实现类。(不需要设置资源类。)
<?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"> <!-- 通过jaxrs:server标签发布REST的服务。 该标签是对JAXRSServerFactoryBean的封装--> <jaxrs:server address="/user"> <jaxrs:serviceBeans> <ref bean="studentInterface"/> </jaxrs:serviceBeans> </jaxrs:server> <bean id="studentInterface" class="com.lc.ws_rest.server.StudentInterfaceImpl"></bean> </beans>
第六步:配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>ws_4_cxf_rest_spring_server</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <!-- 配置Spring配置文件的位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!-- 配置Spring的监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置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> </web-app>第七步:启动Tomcat服务器,并测试服务是否发布成功。通过浏览器访问GET方式的方法。例如:http://127.0.0.1:8080/spring_cxf_rest(项目名称)/ws/user/student/queryList/张三。
客户端:
客户端同样可以采用HttpUrlConnection或者HttpClient或者ajax方式来访问。这里同样采用HttpUrlConnection方式来编写客户端:
public class StudentClient { public static void main(String[] args) throws IOException { //创建URL连接 URL url = new URL("http://127.0.0.1:8080/spring_cxf_rest/ws/user/student/query/1"); //打开连接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); //设置请求方式 connection.setRequestMethod("POST"); //设置可输入 connection.setDoInput(true); //获取数据 if(connection.getResponseCode()==HttpURLConnection.HTTP_OK) { InputStream in = connection.getInputStream(); InputStreamReader reader = new InputStreamReader(in,"utf-8"); BufferedReader bReader = new BufferedReader(reader); String line = null; StringBuilder sb = new StringBuilder(); while((line=bReader.readLine())!=null) { sb.append(line); } in.close(); reader.close(); bReader.close(); System.out.println(sb.toString()); } } }