一、WebService概述
1、是什么?
WebService是一种跨语言编程语言和跨操作系统平台的远程调用技术。是一种RPC。
2、干什么用的?
不同系统、平台、不同语言之间的通信访问和远程调用。
应用程序的集成,不同业务的整合。
3、两种类型:
一种是以SOAP协议风格的WebService
一种是RestFul风格的WebService
二、SOAP
1、整体结构
客户端利用代理方式,中间通过xml类型传输文件。(只支持xml)
核心组件:
XML和HTTP
SOAP:简单对象访问协议
WSDL:webservice描述语言
UDDI:统一描述、发现和集成协议
目前以SOAP为协议的主流是cxf:
Apache CXF = Celtix + Xfire
是Apache的顶级项目。
2、CXF WebService搭建步骤:
服务端:1、接口;2、实现类;3、发布服务
客户端:4、调用。
2.1服务端
// 服务接口
@WebService
public interface IHelloWebServiceClient {
public String sayHello(String name, int age);
}
// 服务接口实现类
public class HelloWebServiceClientImpl implements IHelloWebServiceClient{
@Override
public String sayHello(String name, int age) {
// TODO Auto-generated method stub
System.out.println("Server: name=" + name + ", age=" + age);
return "Server return: name=" + name + ", age=" + age;
}
}
// 服务启动类
public class HelloMain {
/**
*
* @param args
*/
public static void main(String[] args) {
JaxWsServerFactoryBean jaxWsServer = new JaxWsServerFactoryBean();
jaxWsServer.setAddress("http://127.0.0.1:9999/hello");
jaxWsServer.setServiceClass(HelloWebServiceClientImpl.class);
Server server = jaxWsServer.create();
server.start();
System.out.println("Server start ....");
}
}
利用Ecliipse自带的工具进行测试:
输入url:http://localhost:9999/Cxf_test?wsdl
可以進一步點開“operations”中的方法看詳情,看可以看到有參數信息。
2.2 客户端
如果服务端和客户端在同一个项目中则可以:
WSDL报文总体概述:
客户端可以根据以上信息生成接口。有工具可以直接生成:JAX-WS工具:
三、RestFul Web Service ( JAX-RS )
3.1 服务端开发
3.2 客户端开发
3.3 代码
Get请求:
1、Server
定义实体类
@XmlRootElement // 必须要加,这是转换格式用的
public class Customer {
private Integer id;
private String name;
private int age;
get/set/toString/Constructor
}
定义service类
@Path("/crm")
public class CustomerSerivceImpl implements ICustomerService {
@Override
@Path("/customer/{id}")
@GET
@Produces("application/json") // 或者是@Produces("application/xml")
public Customer getCustomerById(@PathParam(value = "id") int id) {
// TODO Auto-generated method stub
return new Customer(1, "Huxuekao", 32);
}
}
启动服务:
public static void main(String[] args) {
JAXRSServerFactoryBean jaxrsServerFactoryBean = new JAXRSServerFactoryBean();
jaxrsServerFactoryBean.setAddress("http://127.0.0.1:9999/customerService");
jaxrsServerFactoryBean.setResourceClasses(CustomerSerivceImpl.class);
jaxrsServerFactoryBean.create().start();
System.out.println("Server(Restful) Start .....");
}
2、客户端Client
public static void main(String[] args) throws Exception {
int id = 33;
// 1、创建HttpClient实例
// HttpClient httpClient = new HttpClient();
CloseableHttpClient httpClient = HttpClientBuilder.create().build(); // 可关闭的
// 2、创建get/post连接方法的实例
// 因为是要请求数据,所以使用HttpRequest,这是一个接口,又因为要使用get请求所以:
HttpGet httpGet = new HttpGet("http://127.0.0.1:9999/customerService/crm/customer/" + id);
// 3、调用httpClient实例的execute方法来执行连接方法的实例
HttpResponse httpResponse = httpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode()==org.apache.http.HttpStatus.SC_OK) {
// 4、读取response获取HttpEntity(流,要关闭)
HttpEntity entity = httpResponse.getEntity(); // 得到的就是一个IO网络流
// 5、对得到后的内容进行处理 (Apache已经提供了相应的方法)
String result = EntityUtils.toString(entity);
System.out.println("Information from Server: " + result);
EntityUtils.consume(entity); // 关闭流
}
// 6、释放连接
httpClient.close();
}
Post请求:
1、Server
定义实体类
@XmlRootElement // 必须要加,这是转换格式用的
public class Customer {
@FormParam("id") // 指定post传来的参数中键的对应关系
private Integer id;
@FormParam("name") // 指定post传来的参数中键的对应关系
private String name;
@FormParam("age") // 指定post传来的参数中键的对应关系
private int age;
get/set/toString/Constructor
}
定义service类
@Path("/crm")
public class CustomerSerivceImpl implements ICustomerService {
@Override
@Path("customer")
@POST
@Consumes("application/x-www-form-urlencoded") // 规定传参形式——名值对(Rs目前不能自动装配,所以要用@BeanParam在方法的参数中指定,并且在实体类中指定各个参数取值)
public String addCustomer(@BeanParam Customer customer) {
// TODO Auto-generated method stub
String customerStr = customer.toString();
System.out.println(customerStr);
return "Add Success: " + customerStr;
}
启动服务:
public static void main(String[] args) {
JAXRSServerFactoryBean jaxrsServerFactoryBean = new JAXRSServerFactoryBean();
jaxrsServerFactoryBean.setAddress("http://127.0.0.1:9999/customerService");
jaxrsServerFactoryBean.setResourceClasses(CustomerSerivceImpl.class);
jaxrsServerFactoryBean.create().start();
System.out.println("Server(Restful) Start .....");
}
2、客户端Client
public static void main(String[] args) throws Exception {
// 1、创建HttpClient实例
// HttpClient httpClient = new HttpClient();
CloseableHttpClient httpClient = HttpClientBuilder.create().build(); // 可关闭的
// 2、创建get/post连接方法的实例
// 因为是要请求数据,所以使用HttpRequest,这是一个接口,又因为要使用get请求所以:
HttpPost httpPost = new HttpPost("http://127.0.0.1:9999/customerService/crm/customer");
// 因为是post请求,所以就要把参数放到httpPost中,因为setEntity要求的是HttpEntity,但是我们在服务器端使用的是application/x-www-form-urlenconded(名值对),所以,查HttpEntity的继承可知UrlEncodedFormEntity
List<BasicNameValuePair> parameters = new ArrayList<>();
parameters.add(new BasicNameValuePair("id", "3"));
parameters.add(new BasicNameValuePair("name", "台达电子有限公司"));
parameters.add(new BasicNameValuePair("age", "44"));
HttpEntity entity = new UrlEncodedFormEntity(parameters, "utf-8"); // 同时一定要指定字符集
httpPost.setEntity(entity);
// 3、调用httpClient实例的execute方法来执行连接方法的实例(关键在于如何传post的参数)
HttpResponse httpResponse = httpClient.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode()==org.apache.http.HttpStatus.SC_OK) {
// 4、读取response获取HttpEntity(流,要关闭)
HttpEntity entityResponse = httpResponse.getEntity(); // 得到的就是一个IO网络流
// 5、对得到后的内容进行处理 (Apache已经提供了相应的方法)
String result = EntityUtils.toString(entityResponse, "utf-8"); // 指定从网络上拿到的字节流转换为String时的字符编码
System.out.println("Information from Server: " + result);
EntityUtils.consume(entity); // 关闭流
}
// 6、释放连接
httpClient.close();
}
一定要注意Post请求中参数的传入方式。
四、Spring整合CXF
容器一启动就应该把webservice启动,整合的过程的目标就是要把上面的Server端的启动程序替换。
主要修改两个配置文件:
4.1 web.xml中:注册servlet(CXFServlet),并指定发布的服务
4.2 配置Spring——applicationContext.xml
<import resource=”classpath:META-INF/cxf/cxf.xml” />
<jaxws:endpoint id=”helloworld” implementor=”实现类” address=”/helloWorld”>
</ jaxws:endpoint >
对于RS:
最后:
此篇文章中的工程项目也可在CSDN中寻找:
webservice -soap的Demo
webservice -Restful的Demo