第一章-WebService概述

1什么是WebService

能在不同语言、不同平台之间实现调用,归功于HTTP,XML与SOAP

实现信息在Internate上共享

SOAP、WSDL、Apache CXF

SOAP (Simple Object Access Protocol) 简单对象传输协议

SOAP是一种中立的信息传递协议。SOAP消息都是XML格式的。虽然SOAP协议没有指明一定要用HTTP协议传输消息,但我们一般还是都采用HTTP协议发送请求的SOAP消息和回应的SOAP消息。 SOAP消息的具体格式:每一个SOAP消息都有一个根元素Envelope(信封),它包含header和body两个部分。Header包含了上下文数据,可以不存在,而body包含了具体的消息,必须存在。下面是一个通过HTTP协议请求Borland公司股票价格的SOAP消息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
POST 网络地址 HTTP/1.1 
Host:  www.stock.com
Content-Type: text/xml; charset="utf-8"
Content-Length: SOAP消息长度
SOAPAction: "urn:stock-quote-services"w
<SOAP-ENV:Envelope xmlns:SOAP-ENV="命名空间" SOAP-ENV:encodingStyle="命名空间">
    <SOAP-ENV:Body> 
        <m:GetLastTradePrice xmlns:m="Some-URI">   
             <symbol>Borland公司股票代码</symbol>   
        </m:GetLastTradePrice>   
    </SOAP-ENV:Body>   
</SOAP-ENV:Envelope>

WSDL (Web Services Description Language) Web Services 描述语言

如果你提供了一个很好的Web Services,但是别人不知道你的Web Services能做什么,以及如何调用,那么它一点用都没有,我们必须为他写一个说明文档。WSDL就是做这个的,WSDL采用XML格式描述Web Services的用途,和调用它需要的参数,这样客户端就可以通过WSDL文件获致Web Services的信息。

Apache CXF 的前身是叫Apache CeltiXfire CXF继承自 Celtix 和 XFire 两大开源项目 提供对 JAX-WS全面的支持 提供了多种 Binding 、Data Binding、Transport 以及 Format的支持 可以采用 Code First 或者 WSDL First 来实现 Web Services 的发布和使用

2快速入门

需要有两个模块:provider /prəˈvaɪdər/ 服务提供者、Consumer

即两个spring boot项目:

1-服务提供者provider

1加入jar 2编写对外提供服务的接口 3编写接口实现类 4编写配置类

1加入Jar

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<!--CXF webservice-->
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
      <version>3.3.6</version>
    </dependency>
  
  <!--新版的cxf需要依赖 hibernate的验证器-->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.1.5.Final</version>
    </dependency>

    <!--springBoot依赖 tomcat,dispatcherServlet,xml -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

2编写对外提供服务的接口

可以直接写在 服务提供者里,provider。

也可以新建一个项目jar包类型,Maven中执行install可以加入maven仓储。

1
2
3
4
5
pom.xml的坐标  在服务器生产者和服务消费者引用
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>serviceCXF1-consumer</artifactId>
<packaging>jar</packaging>

3编写服务实现类

注意endpointInterface接口全路径要正确

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.lx.service.impl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;

import javax.jws.WebService;

@Component
@WebService(serviceName = "empService", // 对外发布的服务名
        // 指定你想要的名称空间,通常使用使用包名反转
        targetNamespace = "http://service.lx.com",
        // 对外提供服务接口全路径
        endpointInterface = "com.lx.service.EmpService")
public class EmpServiceImpl implements EmpService {
    @Override
    public String getEmpById(Integer id)  {
        ZzEmployee emp=new ZzEmployee();
        emp.setOid(id);

        ObjectMapper objectMapper=new ObjectMapper();
        String s = null;
        try {
            s = objectMapper.writeValueAsString(emp);
        } catch (JsonProcessingException e) {
        }

        return s;
    }
}

4编写配置类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Configuration
public class CxfConfig {
	/**@Autowired
	private Bus bus;
	@Autowired
	UserService userService;
	可以通过属性注入
	*/
  
	/**
     * 此方法被注释后:wsdl访问地址为http://127.0.0.1:8080/services/user?wsdl
     * 去掉注释后:wsdl访问地址为:http://127.0.0.1:8080/soap/user?wsdl
     */
    @SuppressWarnings("all")
    @Bean
    public ServletRegistrationBean<Servlet> dispatcherServlet() {
        return new ServletRegistrationBean(new CXFServlet(), "/soap/*");
    }
    //JAX-WS站点服务
  @Bean
    public Endpoint endpoint(Bus bus, EmpService empService){
        Endpoint endpoint=new EndpointImpl(empService);
        endpoint.publish("/emp");
        return endpoint;
    }
}

注意访问地址:http://127.0.0.1:8080/services/user?wsdl

2-服务消费者consumer

consumer可以是java项目,也可以是web项目

1加入jar、2调用其它项目接口

1加入jar

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.3.1.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>org.example</groupId>
<artifactId>serviceCXF1-consumer0</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<name>serviceCXF1-consumer0 Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>

  <!--CXF webservice-->
  <dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
    <version>3.3.6</version>
  </dependency>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.1.5.Final</version>
  </dependency>

  <!--springBoot依赖 tomcat,dispatcherServlet,xml -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
    <artifactId>serviceCXF1-consumer</artifactId>
  </dependency>
</dependencies>

2调用其它项目接口:方式一 通过接口调用(适合同一项目,依赖易导入)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.lx.factory;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lx.entity.ZzEmployee;
import com.lx.service.EmpService;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

public class t1 {
    public static void main(String[] args) {
        //接口地址
        String address="http://localhost:8080/services/emp?wsdl";

        //代理工厂
        JaxWsProxyFactoryBean factoryBean=new JaxWsProxyFactoryBean();

        //设置代理设置
        factoryBean.setAddress(address);

        //设置接口类型
        factoryBean.setServiceClass(EmpService.class);

        //创建一个代理接口实现
        EmpService emp= (EmpService) factoryBean.create();

        //调用代理接口方法并返回结果
        String result=emp.getEmpById(15);
        ObjectMapper objectMapper=new ObjectMapper();
        ZzEmployee zzEmployee=null;
        try {
             zzEmployee = objectMapper.readValue(result, ZzEmployee.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        System.out.println("结果:"+result);
        System.out.println("对象:"+zzEmployee);
    }
}

3调用其它项目接口:方式二 动态调用,不需要接口。适合各个不同服务器调用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.lx.dynamic;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.xml.internal.ws.handler.ClientLogicalHandlerTube;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

public class consumert1 {
    public static void main(String[] args) {
        //创建动态客户端
        JaxWsDynamicClientFactory dcf=JaxWsDynamicClientFactory.newInstance();
        Client client=dcf.createClient("http://localhost:8080/services/emp?wsdl");

        //需要密码情况加上用户名密码
      //  boolean add = Client.getOutInterceptors().add(new ClientLogicalHandlerTube("name", "password"));

        Object[] objs=null;
        try {
            objs=client.invoke("getEmpById",1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(objs[0]);
    }
}

3JSON数据转换

java对象—>JSON 使用Jackson

1
2
3
4
5
6
7
ObjectMapper objectMapper=new ObjectMapper();
String s = null;
try {
    s = objectMapper.writeValueAsString(emp);
} catch (JsonProcessingException e) {
    e.printStackTrace();
}

JSON—>java对象

1
2
3
4
5
6
7
ObjectMapper objectMapper=new ObjectMapper();
ZzEmployee zzEmployee=null;
try {
  zzEmployee = objectMapper.readValue(result, ZzEmployee.class);
} catch (JsonProcessingException e) {
  e.printStackTrace();
}

第二章-