webservice用于不同应用之间(通信)共享数据和服务的。(应用内部通信一般通过上线文实现。)
WebService三种基本元素:
- SOAP: Simple Object Access Protocol (简单对象访问协议);
- WSDL: Web Service Description Language(Web服务描述语言);
- UDDI: Universal Description, Discovery and Integration(通用的描述、发现以及整合);
工作模式(图):
**目前三种主流的WebService实现方法: **
- REST(新型):表象化状态转变 (软件架构风格)RESTEasy、Wink、CXF、Axis2…….
- SOAP(比较成熟):简单对象访问协议 Xfire、Axis2、CXF、Axis1
- XML-RPC(淘汰):远程过程调用协议(慢慢被SOAP所取代) REST 简单易用,效率高,貌似未来有很大的发展空间,也有宣称rest性能个方便比soap强大的,已经有很多框架宣称对rest进行支持. SOAP比较成熟,安全性好。
Java开源Web Service列表:http://www.open-open.com/27.htm 开源框架实现实例:
1.Apache Axis2
Apache Axis2是一个WebService/SOAP/我收到了engine; 支持SOPA1.1,SOAP1.2, REST style of webservice。
实例:Axis2 1.6, jdk 1.8, Tomcat 1.8, eclipse Mars 2 (待补充)
2.Apche CXF
实例:CXF 3.x.x, Tomcat 8, jdk 1.8, eclipse Mars 2
一、准备环境
-
安装配置Eclipse Mars2, jdk 1.8, Tomcat 8;
-
下载CXF运行时环境: 如下载apache-cxf-3.0.10-src.tar.gz包http://cxf.apache.org/download.html; 解压放到指定目录即可。
-
在eclipse中配置CXF运行时环境: windows > Reference > Web Service >Add > 将路径配置为CXF包的目录。
![]
二、在eclipse中新建项目(此处命名为CXFService) New > Dynamic Web Project
三、将CXF二进制包apache-cxf-3.0.12中的lib文件夹拷贝到项目WebContent/WEB-INF/下面。
四、配置 web.xml 和 cxf-servlet.xml web.xml配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>CXFService</display-name> <servlet> <description>Apache CXF Endpoint</description> <display-name>cxf</display-name> <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>/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>60</session-timeout> </session-config> <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>
cfx-servel.xml配置
<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- START SNIPPET: beans --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <import resource="classpath:META-INF/cxf/cxf.xml"/> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> <bean id="SayHello" class="CxfWBImpl" /> <jaxws:endpoint id="sayHello" implementor="#SayHello" address="/sayHello"/> <!-- <jaxws:endpoint id="sayHello" implementor="CxfWBImpl" address="/sayHello"/> --> </beans> <!-- END SNIPPET: beans -->
五、创建WebService服务类(接口类与实现类)
import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebService; @WebService public interface IcxfWB { @WebMethod String sayHello(@WebParam(name="name") String name); }
public class CxfWBImpl implements IcxfWB { @Override public String sayHello(String name) { return "Hello "+name; } }
六、webservice的发布
import javax.xml.ws.Endpoint; import org.apache.cxf.frontend.ServerFactoryBean; import org.apache.cxf.jaxws.JaxWsServerFactoryBean; /* * webservice 服务发布的三种方式:http://www.xuebuyuan.com/1955910.html */ public class ServicePublish { public static void main(String args[]) { ServicePublish.method3(); } public static void method1() { IcxfWB service = new CxfWBImpl(); //调用Endpoint的publish方法发布web service Endpoint.publish("http://localhost", service); System.out.println("publich success!"); //之后可以在浏览器中访问http//localhost/?wsdl来查看 } public static void method2() { String url="http://127.0.0.1:8080/hello2"; JaxWsServerFactoryBean factoryBean=new JaxWsServerFactoryBean(); factoryBean.setAddress(url); factoryBean.setServiceClass(IcxfWB.class); factoryBean.setServiceBean(new CxfWBImpl()); factoryBean.create(); System.out.println("publich success!"); } public static void method3() { ServerFactoryBean svrFactory = new ServerFactoryBean(); //设置服务接口类 svrFactory.setServiceClass(IcxfWB.class); svrFactory.setAddress("http://localhost:8080/queryUser"); //设置服务实现接口类 svrFactory.setServiceBean(new CxfWBImpl()); svrFactory.create(); } }
以上WebService服务端创建完毕,通过运行服务端程序来启动服务。
七、WebService的客户端创建 1.在eclipse中创建一个客户端项目(依然可以是Dynamic Web Project,名为CXFServiceClient) 2.跟服务端一样进行拷贝lib 3.跟服务端一样进行配置web.xml和cxf-servlet.xml 4.创建客户端测试类:
import javax.xml.namespace.QName; import org.apache.cxf.endpoint.Client; import org.apache.cxf.interceptor.LoggingInInterceptor; import org.apache.cxf.interceptor.LoggingOutInterceptor; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; import namespace.unknown.IcxfWB; /* ref:http://www.mamicode.com/info-detail-181915.html just copy lib from cxf-binary to webcontent/web-info... */ public class CxfServiceClient { //wsdl2java工具为我们生成了需要的類 public static void method1() { //depend on client-beans.xml ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"client-beans.xml"}); IcxfWB client = (IcxfWB)context.getBean("sayHello2"); //beanid in lient-benas.xml String response = client.sayHello("World"); System.out.println("Response: " + response); System.exit(0); } //使用CXF中JaxWsProxyFactoryBean客户端代理工厂调用web服务 public static void method2() { JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean(); factoryBean.getInInterceptors().add(new LoggingInInterceptor()); factoryBean.getOutInterceptors().add(new LoggingOutInterceptor()); factoryBean.setServiceClass(IcxfWB.class); factoryBean.setAddress("http://localhost:8080/CXFService/sayHello?wsdl"); IcxfWB impl = (IcxfWB) factoryBean.create(); System.out.println(impl.sayHello("World")); } //使用CXF中JaxWsDynamicClientFactory动态代理工厂 //success here, 弄dependent class or xml public static void method3() { JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); String wsUrl = "http://localhost:8080/CXFService/sayHello?wsdl"; Client client = dcf.createClient(wsUrl); String method = "sayHello";//webservice的方法名 try { Object[] result = client.invoke(method, "World");// 调用webservice for (Object o : result) { System.out.println(o.toString()); } } catch (Exception e) { e.printStackTrace(); } } //error solution: https://community.oracle.com/blogs/vivekp/2007/05/25/how-deal-unresolved-xsschema-references-wsdl //error:because wsdl from .net has different tag. public static void method4whether()//error { JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); String wsUrl = "http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl"; Client client = dcf.createClient(wsUrl); try { String method = "getRegionCountry";// webservice的方法名 QName qname = new QName("http://WebXml.com.cn/", "getRegionCountry"); Object obj = new Object(); Object[] result = client.invoke("getRegionCountry");// 调用webservice System.out.println(result[0].toString()); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { CxfServiceClient.method4whether(); } }
以上先启动服务端提供的服务(run on server),再运行客户端的测试方法(run as application)即可。
3.Jersey 开发 RESTful Web Service
简单示例: http://www.voidcn.com/article/p-ccihaftk-gs.html
接口的测试: Advanced REST client 下载安装后,直接输入网址,即可返回接口获取的结果信息。
Jersey API: https://jersey.java.net/documentation/latest/user-guide.html#d0e1961
JAX-RS中提取输入参数的annotation:
@PathParam URL Syntax http://localhost:8080/myapp/customers/100/Java4s @QueryParam URL Syntax http://localhost:8080/myapp/customers?custNo=100&custName=Java4s @MatrixParam URL Syntax http://localhost:8080/myapp/customers;custNo=100;custName=Java4s @FormParam URL Syntax If we have a HTML form having two input fields and submit button. Lets client enter those details and submit to the RESTful web service. Then the rest service will extract those details by using this @FormParam annotation.
服务端接口定义 @Component @Path("/") public class LYYApiService { private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private InstanceInfoService instanceService; /* 无输入参数的接口 获取实例的连接数 url: http://ip:8080/myapp/api/getInstanceConnSize method: GET 返回数据: 类型:ResultTO<Integer> 数据形式: { "success": true "message": null "returnCode": 0 "data": 6 } */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("getInstanceConnSize") public ResultTO<Integer> getInstanceConnSize() { logger.debug("Enter"); int instanceCurrentConn = -1; instanceCurrentConn = instanceService.getConnSize(); ResultTO<Integer> result = new ResultTO<>(); if (instanceCurrentConn >= 0) { result.setData(instanceCurrentConn); result.setSuccess(true); } return result; } /* 有输入参数的接口 新建用户 url: http://localhost:8080/myapp/api/addUser/username/userpassword method: GET 返回数据形式: 类型:ResultTO<Long> 数据形式: { "success": false "message": "User name already exits." "returnCode": 0 "data": 1 } data是int类型, data=-1时 message=Create user failed. data=0时message=Create user successfully. data=1时 message=User name already exits. */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("addUser/{user}/{pwd}") public ResultTO<Void> addUser(@PathParam("user")String username, @PathParam("pwd")String userpwd) { logger.debug("Enter:user="+username+", pwd="+userpwd); ResultTO<Void> result = new ResultTO<>(); int status = instanceService.addUser(username, userpwd); result.setReturnCode(status); if(status == -1) { result.setSuccess(false); result.setMessage("Create user failed."); } else if(status==0) { result.setSuccess(true); result.setMessage("Create user successfully."); }else if(status ==1) { result.setSuccess(false); result.setMessage("User name already exits."); } return result; } }
客户端接口测试 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class RESTfulClient { private static final String baseURL = "http://localhost:8080/hgcloud/api/"; public static void method1()//GET { try { URL restServiceURL = new URL(baseURL+"addUser/qq2/qq2"); HttpURLConnection httpConnection = (HttpURLConnection) restServiceURL.openConnection(); httpConnection.setRequestMethod("GET"); httpConnection.setRequestProperty("Accept", "application/json"); if (httpConnection.getResponseCode() != 200) { throw new RuntimeException("HTTP GET Request Failed with Error code: " + httpConnection.getResponseCode()); } BufferedReader responseBuffer = new BufferedReader(new InputStreamReader((httpConnection.getInputStream()))); System.out.println("Output from Server: \n"); String output; while ((output = responseBuffer.readLine()) != null) { System.out.println(output); } httpConnection.disconnect(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static void method2()//post { try { URL targetUrl = new URL(baseURL+"addUser"); HttpURLConnection httpConnection = (HttpURLConnection) targetUrl.openConnection(); httpConnection.setDoOutput(true); httpConnection.setRequestMethod("POST"); httpConnection.setRequestProperty("Content-Type", "application/json"); String input = "{\"user\":\"testuser\",\"pwd\":\"testuser\"}"; OutputStream outputStream = httpConnection.getOutputStream(); outputStream.write(input.getBytes()); outputStream.flush(); if (httpConnection.getResponseCode() != 200) { throw new RuntimeException("Failed : HTTP error code : " + httpConnection.getResponseCode()); } BufferedReader responseBuffer = new BufferedReader(new InputStreamReader((httpConnection.getInputStream()))); String output; System.out.println("Output from Server:\n"); while ((output = responseBuffer.readLine()) != null) { System.out.println(output); } httpConnection.disconnect(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { RESTfulClient.method1(); } }