1、概述:下面是摘自百度百科的定义
------------------------------------------------------------------------------------------
它是一种新的webwebservice应用程序分支,是自包含、自描述、模块化的应用,可以发布、定位、通过web调用。Web Service是一个应用组件,它逻辑性的为其他应用程序提供数据与服务.各应用程序通过网络协议和规定的一些标准数据格式(Http,XML,Soap)来访问Web Service,通过Web Service内部执行得到所需结果.Web Service可以执行从简单的请求到复杂商务处理的任何功能。一旦部署以后,其他Web Service应用程序可以发现并调用它部署的服务(可参考http://baike.baidu.com/view/837392.htm)
------------------------------------------------------------------------------------------
通常认为WebService(以下简称WS)是SOA面向服务的架构的一种实现,但是WebService必须使用Soap这种特定的协议来完成,并不严格服务SOA与协议无关性的要求。
2、调用方式:分为以下三种
(1)、RPC远程过程调用
(2)、SOA,面向服务的架构
(3)、REST,表述性状态转移
具体解释可参考(http://zh.wikipedia.org/zh/Web%E6%9C%8D%E5%8A%A1)
3、JAX-WS(Java API For XML-WebService)的实现方式,主要使用到的类在javax.xml.ws和javax.jws中
(1)、首先简单的构建服务,定义一个简单计算器,做加法和n次幂,代码如下
package cyxl.ws; import javax.jws.WebService; @WebService public interface ICalculator { int add(int num1,int num2); int power(int num,int n); }
package cyxl.ws; public class CalculatorImpl implements ICalculator { public int add(int num1, int num2) { // TODO Auto-generated method stub return num1+num2; } public int power(int num, int n) { // TODO Auto-generated method stub int result=1; for(int i=1;i<=n;i++) { result*=num; } return result; } }
package cyxl.ws; import javax.xml.ws.Endpoint; public class SoapServer { public static void main(String[] args) { Endpoint.publish("http://127.0.0.1:8080/calService", new CalculatorImpl()); } }这里发布服务时需要主要的问题,它必须依赖于CXF,下载地址http://www.apache.org/dyn/closer.cgi?path=/cxf/2.5.1/apache-cxf-2.5.1.zip。下完完后,把lib目录中的jar文件全都拷贝到项目中,以防混乱可以自己新建一个用户自定义库,命名为cxf,然后把这些jar文件添加到新建的库中,这样就好管理了。
有了CXF后就可以直接运行main方法来发布服务了。运行完后在浏览器中输入http://127.0.0.1:8080/calService?wsdl,如果可以看到xml文档,那么表示服务发布成功
(3)、客户端调用
客户端要使用WS,必须将WSDL转换为编程语言。有两种方式实现该过程
一是使用MyEclipse生成,过程为“File-New-Other-Web Service-Web Service Client”,然后就根据向导完成了
二是使用CXF提供的工具wsdl2java来实现。找到cxf的bin目录就可以看到很多工具了,其中有一个就是wsdl2java.bat。这个工具就是将wsdl转化成java类以供客户端使用。使用过过程是:在命令行(cmd)中进入到cxf的bin目录,然后执行命令:wsdl2java -p 包名 -d 目标目录 wsdl的URL。如wsdl2java -p cyxl.ws.client -d D:\ http://127.0.0.1:8080/calService?wsdl 。执行成功后在d盘目录下就有cyxl/ws/client目录了,将目录下的java文件拷贝到项目中就可以使用了,客户端调用代码如下
package cyxl.ws.client; import java.net.MalformedURLException; import java.net.URL; import javax.xml.namespace.QName; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import cyxl.ws.CalculatorImplService; import cyxl.ws.ICalculator; public class SoapClient { /** * @param args */ public static void main(String[] args) { // JaxWsProxyFactoryBean bean=new JaxWsProxyFactoryBean(); // bean.setAddress("http://127.0.0.1:8080/calService"); // bean.setServiceClass(ICalculator.class); // Object o=bean.create(); ICalculator cal=null; //cal=(ICalculator)o; QName name=new QName("http://ws.cyxl/","CalculatorImplService"); try { CalculatorImplService service=new CalculatorImplService( new URL("http://127.0.0.1:8080/calService?wsdl"),name ); cal=(ICalculator)service.getPort(ICalculator.class); } catch (MalformedURLException e) { e.printStackTrace(); } System.out.println("1+1="+cal.add(1, 1)); System.out.println("2的4次方是:"+cal.power(2, 4)); } }
好,到这里JAX-WS的使用方式就差不多这样了
4、JAX-RS实现WebService
(1)概述:引用自网络
-----------------------------------------------------------------------
REST(Representational State Transfer表述性状态转移)是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。是一种软件架构模式,只是一种风格,不是像SOAP 那样本身承载着一种消息协议,(两种风格的 Web 服务均采用 HTTP 做传输协议是因为 HTTP 协议能穿越防火墙,JAVA的远程调用RMI等是重量级协议,不能穿越防火墙), 因此你也可以叫做REST是基于HTTP协议的软件架构。REST中重要的两个概念就是资源定位和资源操作,而HTTP 协议恰好完整的提供了这两个要点,HTTP 协议中的 URI 可以完成资源定位,GET、POST、OPTION等方法可以完成资源操作,因此 REST 完全依赖 HTTP 协议就可以完成 Web 服务,而不像SOAP 协议那样只利用HTTP 的传输特性,定位与操作由 SOAP 协议自身完成,也正是由于SOAP 消息的存在,使得 SOAP 笨重。你也可以说 REST 充分利用了 HTTP 协议的特性,而不是像 SOAP 那样只利用了其传输这一特性(事实上大多数人提到 HTTP 协议就只会想到它能用于数据传输)。
-------------------------------------------------------------------------
(2)服务端的实现,JAX-RS 的API在 javax.ws.rs.*包中,建立如下三个java文件
package cyxl.rest; import java.util.Date; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="User") public class User { private long id; private String name; private Date birthday; 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 getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
package cyxl.rest; import javax.ws.rs.*; @Path(value="/user/{id}") @Produces("application/xml") public interface IUserService { @GET @Path(value="/info") public User getUser(@PathParam("id") long id,@QueryParam("name") String name); @GET @Path(value="/info2") public User getUser(@QueryParam("name") String name); }
package cyxl.rest; import java.text.ParseException; import java.text.SimpleDateFormat; public class UserServiceImpl implements IUserService { public User getUser(long id,String name) { User user=new User(); user.setId(id); user.setName(name); try { user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1987-02-01")); } catch (ParseException e) { e.printStackTrace(); } return user; } public User getUser(String name) { User user=new User(); user.setId(1); user.setName(name); try { user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1985-03-01")); } catch (ParseException e) { e.printStackTrace(); } return user; } }
(3)、服务的发布
package cyxl.rest; import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; public class RestServer { public static void main(String[] args) { JAXRSServerFactoryBean bean=new JAXRSServerFactoryBean(); bean.setResourceClasses(UserServiceImpl.class); bean.setAddress("http://127.0.0.1:8080/"); bean.create(); } }运行该main方法,然后再浏览器中访问”http://127.0.0.1:8080/user/2/info?name=cyxl“。如果发布成功,将会看到一个xml文件,结果如下
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <User> <birthday>1987-02-01T00:00:00+08:00</birthday> <id>2</id> <name>cyxl</name> </User>
import org.apache.cxf.jaxrs.client.WebClient; import cyxl.rest.User; public class RestClient { public static void main(String[] args) { WebClient client=WebClient.create("http://127.0.0.1:8080/user/1/info?name=user"); User user=(User)client.accept("application/xml").get(User.class); System.out.println(user.getName()); } }
这样REST的方式也差不多这样了,具体的URL中各部分的意思对照着IUserService里面的annotation就可以理解了