`
cyxlgzs
  • 浏览: 90083 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Java实践之路——WebService

 
阅读更多

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);
}

这里使用到了注解@WebService,表明了接口是用来提供服务的

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;
	}

}

(2)、发布服务。代码如下

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));
	}

}

注释掉的部分是调用CXF对WS的支持,没注释部分是调用JDK的API来实现。

好,到这里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;
	}

}

以上定义了要发布的服务,其中用到了很多annotation,可以查阅相关的文档进行了解他们的作用,这里只大致讲一下开发过程

(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>


(4)客户端调用。REST的客户端调用相对于JAX-WS简单得很多,不在需要先生成一些java类然后倒入项目中,REST方式能自己自动的生成,只需要访问相应的地址就行了

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());
	}

}

结果显示user。

这样REST的方式也差不多这样了,具体的URL中各部分的意思对照着IUserService里面的annotation就可以理解了

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics