WebService的介绍和使用
概念:Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。是:通过SOAP在Web上提供的软件服务,使用WSDL文件进行说明,并通过UDDI进行注册。分为SOAP和restfull风格
XML:(Extensible Markup Language)扩展型可标记语言。面向短期的临时数据处理、面向万维网络,是Soap的基础。
Soap:(Simple Object Access Protocol)简单对象存取协议。是XML Web Service 的通信协议。当用户通过UDDI找到你的WSDL描述文档后,他通过可以SOAP调用你建立的Web服务中的一个或多个操作。SOAP是XML文档形式的调用方法的规范,它可以支持不同的底层接口,像HTTP(S)或者SMTP。
WSDL:(Web Services Description Language) WSDL 文件是一个 XML 文档,用于说明一组 SOAP 消息以及如何交换这些消息。大多数情况下由软件自动生成和使用。
UDDI (Universal Description, Discovery, and Integration) 是一个主要针对Web服务供应商和使用者的新项目。在用户能够调用Web服务之前,必须确定这个服务内包含哪些商务方法,找到被调用的接口定义,还要在服务端来编制软件,UDDI是一种根据描述文档来引导系统查找相应服务的机制。UDDI利用SOAP消息机制(标准的XML/HTTP)来发布,编辑,浏览以及查找注册信息。它采用XML格式来封装各种不同类型的数据,并且发送到注册中心或者由注册中心来返回需要的数据。
调用原理
实现一个完整的Web服务包括以下步骤:
◆ Web服务提供者设计实现Web服务,并将调试正确后的Web服务通过Web服务中介者发布,并在UDDI注册中心注册; (发布)
◆ Web服务请求者向Web服务中介者请求特定的服务,中介者根据请求查询UDDI注册中心,为请求者寻找满足请求的服务; (发现)
◆ Web服务中介者向Web服务请求者返回满足条件的Web服务描述信息,该描述信息用WSDL写成,各种支持Web服务的机器都能阅读;(发现)
◆ 利用从Web服务中介者返回的描述信息生成相应的SOAP消息,发送给Web服务提供者,以实现Web服务的调用;(绑定)
◆ Web服务提供者按SOAP消息执行相应的Web服务,并将服务结果返回给Web服务请求者。(绑定)
SOAT风格
Helloword
首先下载apache-cxf-3.3.1,里面有jar包
新建一个java web工程,将apache-cxf-3.3.1的lib包的jar拷贝到lib文件夹下
新建一个HelloWord.java的接口和实现它 的HelloWordImpl.java,在接口上注解@WebService
@WebService
public interface HelloWord {
public String sayHello(String name);
}
public class HelloWordImpl implements HelloWord {
@Override
public String sayHello(String name) {
return "name="+name+"------------age=21";
}
}
新建一个MainService.java 来发布服务,运行服务,会发现它不会停止,一直在运行
public class MainService {
public static void main(String[] args) {
JaxWsServerFactoryBean jaxWsServerFactoryBean = new JaxWsServerFactoryBean();
//发布的地址和服务名
jaxWsServerFactoryBean.setAddress("http://192.168.43.53:8888/helloword");
jaxWsServerFactoryBean.setServiceClass(HelloWordImpl.class);
Server server = jaxWsServerFactoryBean.create();
server.start();
System.out.println("======开始服务--------->>>>>>>>");
}
}
打开游览器输入:http://192.168.43.53:8888/helloword?wsdl可以看到如下,说明服务启动正确
新建一个Client,来调用服务,运行程序,输出
public class Client {
public static void main(String[] args) {
/*代理*/
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
/*地址*/
jaxWsProxyFactoryBean.setAddress("http://192.168.43.53:8888/helloword");
/*传入接口*/
jaxWsProxyFactoryBean.setServiceClass(HelloWord.class);
HelloWord helloword = (HelloWord) jaxWsProxyFactoryBean.create();
String str = helloword.sayHello("chenlong");
System.out.println(str);
}
}
一个简单的HelloWord就写好了。这是我们自己手动写代码来调用的,如果不写代理类,怎么实现呢?借助JAX-WS工具。
首先到apache-cxf-3.3.1\bin这个目录下,打开cmd,输入wsdl2java <http://192.168.43.53:8888/helloword?wsdl 然后会发现,该目录下回生成一些代码,将这些类直接复制到项目的一个包中(或者达成jar包放在lib下也可以),新建client2.java
public class Client2 {
public static void main(String[] args) {
HelloWord helloWord = new HelloWordImpl();
String chen = helloWord.sayHello("chen");
System.out.println(chen);
}
}
直接这样就可以了。
Restful Web Services (JAX-RS)
•JAX-RS= Java API For Restful Web Services
• JAX-RS是JAVA EE6 引入的一个新规范。 是一个Java 编程语言的应用程序接口,支持按照表述性状态转移 (REST)架构风格创建Web服务。
• JAX-RS使用了Java标注来简化Web服务的客户端和服务端的开发和部署。
• 除了JAX-RS方式发布Restful风格的Webservice,SpringMVC也可以发布Restful风格的Webservice
JAX-RS提供了一些标注将一个资源类,一个POJO Java类,封装为Web资源。包括:
@Path,标注资源类或者方法的相对路径 @GET,@PUT,@POST,@DELETE,标注方法是HTTP请求的类型。
@Produces,标注返回的MIME媒体类型 @Consumes,标注可接受请求的MIME媒体类型
@PathParam,@QueryParam,@HeaderParam,@CookieParam,@MatrixParam,@FormParam,分别标注方法的参数来自于HTTP请求的不同位置,例如:
@PathParam来自于URL的路径,@QueryParam来自于URL的查询参数,
@HeaderParam来自于HTTP请求的头信息,@CookieParam来自于HTTP请求的Cookie。
基于JAX-RS实现的框架有Jersey,RESTEasy等,这两个框架创建的应用可以很方便地部署到Servlet 容器中
简单实例:
创建一个web工程,添加jar包,要实现的服务是根据ID查用户,添加一个用户的功能
首先创建Customer.java
@XmlRootElement
public class Customer {
@FormParam("id")
private String id;
@FormParam("name")
private String name;
@FormParam("age")
private int age;
public Customer() {}
public Customer(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
@XmlRootElement,可以将customer转为xml
创建一个CustomerService 接口
@WebService
public interface CustomerService {
Customer getCustomerById(String id);
String addCustomer(Customer customer);
}
实现接口,一个get方法,一个post方法
@Path("/crm")
public class CustomerServiceImpl implements CustomerService {
@Override
@GET
@Path("/customer/{id}")
@Produces("application/json")//以什么样的方式返回数据xml,json标注返回的MIME媒体类型
public Customer getCustomerById(@PathParam("id") String id) {
if(id.equals("1")){
return new Customer("1","zhangsan",12);
}
if(id.equals("2")){
return new Customer("2","lisi",13);
}
return new Customer("3","chenlong",11);
}
@Override
@POST
@Path("/customer")
@Consumes("application/x-www-form-urlencoded")
public String addCustomer(@BeanParam Customer customer) {
System.out.println(customer);
return "success:"+customer.toString();
}}
手动发布服务
public class Main {
public static void main(String[] args) {
JAXRSServerFactoryBean jaxrsServerFactoryBean = new JAXRSServerFactoryBean();
//customer为自己写的服务名,客户端用这个地址加方法就可以用了
jaxrsServerFactoryBean.setAddress("http://localhost:8888/customer");
jaxrsServerFactoryBean.setResourceClasses(CustomerServiceImpl.class);
jaxrsServerFactoryBean.create().start();
System.out.println("开始服务------->>>>>>>");
}
}
服务启动之后,在游览器输入:http://localhost:8888/customer/crm/customer/3,可以看到json数据
使用客户端调用,get调用
public class Client {
public static void main(String[] args) throws IOException {
//1. 创建 HttpClient 的实例
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
//2. 创建某种连接方法的实例
HttpGet httpget = new HttpGet("http://localhost:8888/customer/crm/customer/3");
//3. 调用第一步中创建好的实例的execute方法来执行第二步中创建好的链接类实例
HttpResponse response = httpclient.execute(httpget);
//4. 读response获取HttpEntity
HttpEntity entity = response.getEntity();
//5. 对得到后的内容进行处理
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String result = EntityUtils.toString(entity, "UTF-8");
System.out.println(result);
} else {
String result = EntityUtils.toString(entity, "UTF-8");
System.err.println(result);
}
//6. 释放连接。无论执行方法是否成功,都必须释放连接
EntityUtils.consume(entity);
httpclient.close();
}
}
使用客户端post请求
public class PostClient {
public static void main(String[] args) throws Exception {
/*创建HTTPclient的实例*/
CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().build();
/*创建链接的方式*/
HttpPost httpPost = new HttpPost("http://localhost:8888/customer/crm/customer");
/*传递参数*/
List<BasicNameValuePair> list= new ArrayList<>();
list.add(new BasicNameValuePair("id","4"));
list.add(new BasicNameValuePair("name","陈龙"));
list.add(new BasicNameValuePair("age","18"));
HttpEntity httpEntity = new UrlEncodedFormEntity(list,"utf-8");
httpPost.setEntity(httpEntity);
/*调用*/
HttpResponse execute = closeableHttpClient.execute(httpPost);
// 读response获取HttpEntity
HttpEntity entity = execute.getEntity();
if(execute.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
String s = EntityUtils.toString(entity, "Utf-8");
System.out.println(s);
}else {
String s = EntityUtils.toString(entity, "Utf-8");
System.out.println(s);
}
//6. 释放连接。无论执行方法是否成功,都必须释放连接
EntityUtils.consume(entity);
closeableHttpClient.close();
}
}
运行,可在
客户端控制台下输出:success:Customer{id=‘4’, name=‘陈龙’, age=18}
在服务器控制台输出:Customer{id=‘4’, name=‘陈龙’, age=18}
spring + cxf 的整合
工程的结构
创建一个web maven工程,在web.xml加入代码
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springcxf.xml</param-value>
</context-param>
<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>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 本系统的WebService路径必须以/ws/开头 -->
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
将上述的Customer,和CustomerService以及实现类加入工程,以及helloword的服务加进来,在resource目录下新建application.xml
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<jaxws:endpoint id="helloword" implementor="ws.HelloWordImpl" address="/helloword"></jaxws:endpoint>
<jaxrs:server id="customer" address="/customerService">
<jaxrs:serviceBeans>
<bean id="customerService" class="clong.service.impl.CustomerServiceImpl"></bean>
</jaxrs:serviceBeans>
</jaxrs:server>
</beans>
启动Tomcat,在游览器访问http://localhost:8080/ws/,可以看到你发布的服务
这时候用代码调用只需要改:HttpGet httpget = new HttpGet(“http://localhost:8080/ws/customerService/crm/customer/3”);就可以了,我这里不知道为什么掉用这个方法,获取不到json,显示
No message body writer has been found for class clong.bean.Customer, ContentType: application/json
而将这个方法的 @Produces(“application/json”)改为 @Produces(“application/xml”),就可以显示xml数据,不知道哪里有问题,待完善
Post 请求一样的,将HttpPost httpPost = new HttpPost(“http://localhost:8080/ws/customerService/crm/customer”);修改就可以了。
大概的webservice就到这里了。以后有新需求,在添加!