webservice服务调用

一、简介

1、什么是 Web Service?

Web Service是一种跨编程语言和操作系统平台的远程调用技术。Web Service采用标准的SOAP(Simple Object Access Protocol,简单对象访问协议,属于w3c标准。并且是基于 http 的应用层协议传输xml数据)协议传输。Web Service采用WSDL作为描述语言,并且W3C为Web Service制定了一套传输数据类型,使用xml进行描述,即XSD(XML Schema Datatypes),任何语言写的web Service 接口在发送数据的时候都要转换成WebService标准的XSD发送。

2、Web Service三要素

Web Services 平台的元素:

  • SOAP(简易对象访问协议);
  • UDDI(通用描述、发现及整合);
  • WSDL(Web services 描述语言)。

2.1、SOAP

SOAP也叫做简单对象访问协议,是一种简单的基于xml的协议,它使应用程序通过HTTP来交换数据,可以简单的理解为SOAP= http+xml。SOAP协议目前的主流版本为:SOAP1.1和SOAP1.2。SOAP也不是Web Service的专有协议,其它的应用程序也可以用soap传输数据。

2.1.1、SOAP协议格式

一条 SOAP 消息就是一个普通的 XML 文档,包含下列元素:

  • 必需的 Envelope 元素,可把此 XML 文档标识为一条 SOAP 消息;
  • 可选的 Header 元素,包含头部信息;
  • 必需的 Body 元素,包含所有的调用和响应信息;
  • 可选的 Fault 元素,提供有关在处理此消息所发生错误的信息。
    所有以上的元素均被声明于针对 SOAP 封装的默认命名空间中:http://www.w3.org/2001/12/soap-envelope,以及针对 SOAP 编码和数据类型的默认命名空间:
    http://www.w3.org/2001/12/soap-encoding。

SOAP 消息的基本结构如下:

<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header>
...
</soap:Header>

<soap:Body>
...
  <soap:Fault>
  ...
  </soap:Fault>
</soap:Body>
</soap:Envelope>

2.2、WSDL

WSDL(网络服务描述语言,Web Services Description Language)是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问(方法,入参,返回值)。简单地说就是Web Service的使用说明书。
WSDL文档结构主要包括5个标签:

  • <service> :服务视图,Web Service的服务结点,它包括服务端点;
  • <binding> :为每个服务端口定义消息格式和协议细节;
  • <portType> :最重要的 WSDL 元素,它可描述一个 web service、可被执行的操作,以及相关的消息,可以把 元素比作传统编程语言中的一个函数库(或一个模块、或一个类);
  • <message> :定义一个操作的数据元素,每个消息均由一个或多个部件组成。可以把这些部件比作传统编程语言中一个函数调用的参数;
  • <type> :定义 web service 使用的数据类型,为了最大程度的平台中立性,WSDL 使用 XML Schema 语法来定义数据类型。

下面是一个 WSDL 文档的简化的片段:

<!--定义数据类型-->
<wsdl:types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://WebXml.com.cn/">
        <s:element name="getMobileCodeInfo">
            <s:complexType>
                <s:sequence>
                    <s:element minOccurs="0" maxOccurs="1" name="mobileCode" type="s:string"/>
                    <s:element minOccurs="0" maxOccurs="1" name="userID" type="s:string"/>
                </s:sequence>
            </s:complexType>
        </s:element>
        <s:element name="getMobileCodeInfoResponse">
            <s:complexType>
                <s:sequence>
                    <s:element minOccurs="0" maxOccurs="1" name="getMobileCodeInfoResult" type="s:string"/>
                </s:sequence>
            </s:complexType>
        </s:element>
    </s:schema>
</wsdl:types>

<!--定义操作的数据元素-->
<wsdl:message name="getMobileCodeInfoSoapIn">
    <wsdl:part name="parameters" element="tns:getMobileCodeInfo"/>
</wsdl:message>
<wsdl:message name="getMobileCodeInfoSoapOut">
    <wsdl:part name="parameters" element="tns:getMobileCodeInfoResponse"/>
</wsdl:message>

<!--定义可执行的操作-->
<wsdl:portType name="MobileCodeWSSoap">
    <wsdl:operation name="getMobileCodeInfo">
        <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><br /><h3>获得国内手机号码归属地省份、地区和手机卡类型信息</h3><p>输入参数:mobileCode = 字符串(手机号码,最少前7位数字),userID = 字符串(商业用户ID) 免费用户为空字符串;返回数据:字符串(手机号码:省份 城市 手机卡类型)。</p><br /></wsdl:documentation>
        <wsdl:input message="tns:getMobileCodeInfoSoapIn"/>
        <wsdl:output message="tns:getMobileCodeInfoSoapOut"/>
    </wsdl:operation>
</wsdl:portType>

<!--定义消息格式和协议细节-->
<wsdl:binding name="MobileCodeWSSoap" type="tns:MobileCodeWSSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getMobileCodeInfo">
        <soap:operation soapAction="http://WebXml.com.cn/getMobileCodeInfo" style="document"/>
        <wsdl:input>
            <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output>
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>
</wsdl:binding>

<!--定义服务端点-->
<wsdl:service name="MobileCodeWS">
    <wsdl:port name="MobileCodeWSSoap" binding="tns:MobileCodeWSSoap">
        <soap:address location="http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx"/>
    </wsdl:port>
</wsdl:service>

2.3、UDDI

UDDI(Universal Description, Discovery and Integration),通用描述、发现与集成服务,通过它,企业可注册并搜集Web Service。企业将自己提供的Web Service注册在UDDI,也可以使用别的企业在UDDI注册Web Service服务,从而达到资源共享。UDDI旨在将全球的Web Service资源进行共享。

3、开发规范

3.1、JAX-WS

JAX-WS(Java API for XML-Based Web Service):一个远程调用可以转换为基于XML协议(例如:SOAP协议),在使用JAX-WS过程中,开发者不需要使用任何代码来编写生成和处理SAOP。JAX-WS运行时会自动将这些API调用转换为SAOP协议的消息。
在服务端,通过Java语言定义远程调用所需要实现的接口(SEI:Service EndPoit Interface),并对其提供相关的实现,通过调用JAX-WS的服务来发布接口就可以发布一个Web Service 服务。
在客户端,通过JAX-WS的API来创建一个代理来(用本地代理对象来替代远程的服务对象)实现远程服务端的调用。

3.1、JAX-RS

JAX-RS(Java API for RESTful Web Services)是JAVA EE6 引入的一个新技术。 是一个Java 编程语言的应用程序接口,支持按照表述性状态转移(Restful)架构风格创建Web服务。

4、应用场景

4.1、优缺点

Web Service的优点:

  • 发送方式采用 http 的 post 发送,http默认端口是80,防火墙默认不拦截80,所以跨防火墙;
  • 采用xml格式封装数据,xml是跨平台的,跨系统的。

Web Service缺点:

  • 采用xml格式封装数据,所以在传输过程中,要传输额外的标签,随着soap协议的不断完善,标签越来越大,导致webservice的性能下降。

4.2、适用场景

Web Service是一个 SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过 Internet 进行基于 Http 协议的网络应用间的交互。适用于:

  • 异构系统(不同语言)的整合;
  • 不同客户端的整合,例如:浏览器、移动app、小程序。

二、Web Service 实战

基于JAX-WS和JAX-RS规范的框架实现有很多,Apache CXF 就是一个开源的 Web Service 框架,CXF 简化了 Web Service 的构建和开发 。

1、基于JAX-WS规范的 Web Service 构建

1.1、基于原生CXF实现

1.1.1、服务端

第一步,创建maven项目,引入CXF相关坐标:

<!--cxf 对 jaxws 的支持-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>3.0.1</version>
</dependency>
<!--内置 jetty web服务器-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http-jetty</artifactId>
    <version>3.0.1</version>
</dependency>
<!--依赖日志-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.6.6</version> 
</dependency>

第二步,编写实体类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private static final long serialVersionUID = 4005775933334039922L;

    private Long id;

    private String name;

    private Integer age;

    private Integer sex;
}

第三步,编写服务接口和实现:

/**
 * @Des 定义用户服务(服务端)
 * @Author jidi
 * @Email jidi_jidi@163.com
 * @WebService注解:表示是一个Web Service服务。
 */
@WebService(serviceName = "userService", portName="userPort")
public interface UserService {

    /**
     * 保存用户
     */
    void saveUser(User user);


    /**
     * 查询所有用户
     */
    List<User> getAllUsers();

    /**
     * 根据用户id查询用户
     */
    User getUserById(Long id);
}


public class UserServiceImpl implements UserService {
    @Override
    public void saveUser(User user) {
        System.out.println("保存用户:" + user);
    }

    @Override
    public List<User> getAllUsers() {
        List<User> users = new ArrayList<>(6);
        users.add(new User(1L, "基地", 25, 1));
        users.add(new User(2L, "怀勇", 24, 1));
        users.add(new User(3L, "gala", 27, 0));
        return users;
    }

    @Override
    public User getUserById(Long id) {
        return new User(3L, "gala", 27, 0);
    }
}

第四步,发布服务:

public class UserServicePublish {

    public static void main(String[] args) {
        // 1、创建工厂对象
        JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();

        // 2、设置参数
        // 客户端访问地址
        factory.setAddress("http://localhost:8089/userService");
        // 接口类型
        factory.setServiceClass(UserService.class);
        // 接口实现类
        factory.setServiceBean(new UserServiceImpl());

        // 设置拦截器
        // 输入日志拦截器(拦截客户端请求)
        factory.getInInterceptors().add(new LoggingInInterceptor());
        // 输出日志拦截器(拦截服务端响应)
        factory.getOutInterceptors().add(new LoggingOutInterceptor());

        // 3、发布服务
        factory.create();
    }
}

第五步,浏览器访问测试,输入地址:http://localhost:8089/userService?wsdl,能够访问到wsdl描述信息,并且控制台无报错,那么服务发布成功:

1.1.2、客戶端

第一步,创建maven项目,引入CXF相关坐标(跟服务端保持一致);
第二步,编写客户端调用:

public class UserServiceCall {

    public static void main(String[] args) {
        // 1、创建工厂
        JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();

        // 2、设置参数
        // 设置服务接口(引用服务端接口)
        proxyFactory.setServiceClass(UserService.class);
        // 访问地址
        proxyFactory.setAddress("http://localhost:8089/userService");

        // 3、创建接口代理对象
        UserService userService = (UserService) proxyFactory.create();

        // 设置日志拦截器
        Client client = ClientProxy.getClient(userService);
        // 输入拦截器(拦截服务器响应)
        client.getInInterceptors().add(new LoggingInInterceptor());
        // 输出拦截器(拦截客户端请求)
        client.getOutInterceptors().add(new LoggingOutInterceptor());

        // 4、调用服务端方法
        userService.saveUser(new User(1L, "基地", 25, 1));
        List<User> users = userService.getAllUsers();
        System.out.println(users);
    }
}

1.2、Spring整合CXF实现

1.2.1、服务端

第一步,创建基于maven的web项目,导入相关依赖:

<!--cxf 对 jaxws 的支持-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>3.0.1</version>
</dependency>

<!--spring-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.2.3.RELEASE</version>
</dependency>

第二步,创建实体类、服务接口和接口实现类(与原生CXF实现保持一致);
第三步,编写spring配置文件,发布服务:

<?xml version="1.0" encoding="UTF-8"?>
<!--引入命名空间,jaxws 是CXF对于JAX-WS模式的支持-->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/jaxws
        http://cxf.apache.org/schemas/jaxws.xsd
">

    <!--发布服务-->
    <jaxws:server address="/userService" serviceClass="com.jidi.learn.ws.spring.web.UserService">
        <!--服务实现类-->
        <jaxws:serviceBean>
            <bean class="com.jidi.learn.ws.spring.web.UserServiceImpl"/>
        </jaxws:serviceBean>
        <!--定义输入、输出拦截器-->
        <jaxws:inInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
        </jaxws:inInterceptors>
        <jaxws:outInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
        </jaxws:outInterceptors>
    </jaxws:server>

</beans>

第四步,在 web.xml文件中配置CXFServlet:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
          http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
id="WebApp_ID" version="4.0">

    <display-name>cxf-ws-spring-server</display-name>

    <!-- 指定Spring的配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>

    <!-- 实例化Spring容器 -->
    <!-- 应用启动时,该监听器被执行,它会读取Spring相关配置文件,其默认会到WEB-INF中查找applicationContext.xml -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--CXF框架核心控制器CXFServlet-->
    <servlet>
        <servlet-name>cxf</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>cxf</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

第五步,启动web项目,通过地址:http://localhost:8080/cxf-ws-spring-server/userService?wsdl,访问服务说明文件。

1.2.2、客户端

第一步,创建基于maven的web项目,导入相关依赖;
第二步,编写spring配置文件,声明服务代理对象:

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/jaxws
        http://cxf.apache.org/schemas/jaxws.xsd
">

    <!--创建服务接口代理对象-->
    <jaxws:client
            id="userService"
            address="http://localhost:8080/cxf-ws-spring-server/userService"
            serviceClass="com.jidi.learn.ws.spring.web.UserService">
        <!--定义输入、输出拦截器-->
        <jaxws:inInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
        </jaxws:inInterceptors>
        <jaxws:outInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
        </jaxws:outInterceptors>
    </jaxws:client>
</beans>

第三步,编写测试类调用服务:

public class UserServiceTest {

    public static void main(String[] args) {
        // 1、加载配置文件,创建spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        // 2、获取接口代理对象
        UserService userService = (UserService)context.getBean("userService");

        // 3、调用服务方法
        userService.saveUser(new User(123L, "jidi",  25,2));
    }
}

1.3、Spring Boot整合CXF实现

第一步,创建maven项目,引入相关依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>

<!--cxf(ws模式)-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
    <version>3.2.4</version>
</dependency>

第二步,创建实体类,服务接口和实现类(同上);
第三步,编写配置类,发布服务:

/**
 * @Des 发布服务
 * @Author jidi
 * @Email jidi_jidi@163.com
 */
@Configuration
public class JaxWsConfig {
    @Autowired
    private Bus bus;

    @Autowired
    private UserService userService;

    /**
     * wsdl默认访问地址为 :http://127.0.0.1:8081/services/userService?wsdl
     * 此bean可以将默认的前缀 services 更改为自定义的访问前缀
     */
    @Bean
    public ServletRegistrationBean cxfServlet() {
        return new ServletRegistrationBean(new CXFServlet(), "/ws/*");
    }

    /**
     * 发布服务
     */
    @Bean
    public Endpoint userService(){
        Endpoint endpoint = new EndpointImpl(bus, userService);
        endpoint.publish("/userService");
        return endpoint;
    }
}

第四步,测试服务是否发布成功,能够访问服务说明文件即可。

2、基于JAX-RS规范的 Web Service 构建

JAX-RS 是一个 Java 编程语言接口,被设计用来简化使用 REST 架构的应用程序的开发。JAX-RS API 使用 Java 编程语言的注解来简化 RESTful web service 的开发。开发人员使用 JAX-RS 的注解修饰Java编程语言的类文件来定义资源和能够应用在资源上的行为。JAX-RS的注解是运行时的注解,因此运行时的映射会为资源生成辅助类和其他的辅助文件。包含 JAX-RS 资源类的 Java EE 应用程序中资源是被配置好的,辅助类和辅助文件是生成的,资源通过被发布到 Java EE 服务器上来公开给客户端。

2.1、基于原生CXF实现

2.1.1、服务端

第一步,创建maven项目,引入CXF相关坐标:

<!--cxf 对 jaxrs 的支持-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxrs</artifactId>
    <version>3.0.1</version>
</dependency>

<!--内置 jetty web服务器-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http-jetty</artifactId>
    <version>3.0.1</version>
</dependency>
<!--json转换-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-rs-extension-providers</artifactId>
    <version>3.0.1</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jettison</groupId>
    <artifactId>jettison</artifactId>
    <version>1.3.7</version>
</dependency>

第二步,定义实体类(需要添加 @XmlRootElement 注解):

/**
 * @Des
 * @Author jidi
 * @Email jidi_jidi@163.com
 * 注解 @XmlRootElement 可以实现对象和xml数据的转换
 */
@XmlRootElement
public class Student implements Serializable {
    private static final long serialVersionUID = -8981858391555915143L;

    private Long id;

    private String number;

    private Long classNo;

    private String name;
}

第三步,定义服务接口(使用restful风格的注解)和实现类:

/**
 * @Des restful 风格,服务接口
 * @Author jidi
 * @Email jidi_jidi@163.com
 */
@Path("/")
public interface StudentService {

    @POST
    void saveStudent(Student student);

    @PUT
    void modifyStudent(Student student);

    @DELETE
    @Path("/{id}")
    void deleteStudent(@PathParam("id") Long id);

    @GET
    @Path("/{id}")
    Student getById(@PathParam("id") Long id);

    /**
     * 指定使用 json 格式返回
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    List<Student> getAllStudents();
}

public class StudentServiceImpl implements StudentService{
    private static Map<Long, Student> map = new HashMap(8);
    static {
        map.put(1L, new Student(1L, "1000123", 1001L, "基地"));
        map.put(2L, new Student(2L, "1000111", 2001L, "懷擁"));
        map.put(3L, new Student(3L, "1000222", 3001L, "毛毛"));
    }

    @Override
    public void saveStudent(Student student) {
        System.out.println("添加學生:" + student);
    }

    @Override
    public void modifyStudent(Student student) {
        System.out.println("修改學生:" + student);
    }

    @Override
    public void deleteStudent(Long id) {
        System.out.println("刪除學生:" + id);
    }

    @Override
    public Student getById(Long id) {
        System.out.println("根據id查詢學生。。。");
        return map.get(id);
    }

    @Override
    public List<Student> getAllStudents() {
        List<Student> list = new ArrayList(5);
        for (Map.Entry<Long, Student> entry : map.entrySet()) {
            System.out.println(entry.getValue());
            list.add(entry.getValue());
        }
        System.out.println("查詢所有的學生信息。。。。");
        return list;
    }
}

第四步,发布服务:

public class StudentServicePublish {

    public static void main(String[] args) {
        // 1、创建工厂对象
        JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();

        // 2、设置参数
        // 设置访问地址
        factory.setAddress("http://localhost:8888/rs/studentService");

        // 设置服务接口实现类
        factory.setServiceBean(new StudentServiceImpl());

        // 设置日志拦截器
        factory.getInInterceptors().add(new LoggingInInterceptor());
        factory.getOutInterceptors().add(new LoggingOutInterceptor());

        // 发布服务
        factory.create();
    }
}

第五步,通过restful风格请求,调用服务,以查詢所有的學生信息为例,访问:http://localhost:8888/rs/studentService,可以看到响应内容:
在这里插入图片描述

2.1.2、客户端

第一步,创建maven工厂,导入相关依赖:

<!--restful 风格客户端-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-rs-client</artifactId>
    <version>3.0.1</version>
</dependency>

<!--json转换-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-rs-extension-providers</artifactId>
    <version>3.0.1</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jettison</groupId>
    <artifactId>jettison</artifactId>
    <version>1.3.7</version>
</dependency>

第二步,使用restful客户端调用服务:

/**
 * @Des restuful 风格,webservice服务发布,客户端测试类
 * @Author jidi
 * @Email jidi_jidi@163.com
 */
public class StudentServiceTest {

    /**
     * 测试保存
     */
    @Test
    public void add(){
        WebClient.create("http://localhost:8888/rs/studentService")
                .post(new Student(1L, "122312", 23L, "teswt"));
    }

    /**
     * 测试修改
     */
    @Test
    public void modify(){
        WebClient.create("http://localhost:8888/rs/studentService")
                .put(new Student(1L, "122312", 23L, "teswt"));
    }

    /**
     * 测试删除
     */
    @Test
    public void delete(){
        WebClient.create("http://localhost:8888/rs/studentService/1")
                .delete();
    }

    /**
     * 测试查询
     */
    @Test
    public void select(){
        Student student = WebClient.create("http://localhost:8888/rs/studentService/"+1)
                .get(Student.class);
        System.out.println(student);
    }


    /**
     * 测试查询(使用json格式接收返回结果)
     */
    @Test
    public void selectAll(){
        ArrayList<Student> list = (ArrayList<Student>)WebClient.create("http://localhost:8888/rs/studentService")
                .accept(MediaType.APPLICATION_JSON)
                .getCollection(Student.class);
        System.out.println(list);
    }
}

2.2、spring整合CXF实现

2.2.1、服务端

第一步,创建基于maven的web项目,导入相关依赖:

<!--cxf 对 jaxrs 的支持-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxrs</artifactId>
    <version>3.0.1</version>
</dependency>
<!--json转换-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-rs-extension-providers</artifactId>
    <version>3.0.1</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jettison</groupId>
    <artifactId>jettison</artifactId>
    <version>1.3.7</version>
</dependency>

<!--spring-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.2.3.RELEASE</version>
</dependency>

第二步,定义实体类,服务接口和实现类(同上);
第三步,编写spring配置文件,发布基于restful风格的服务:

<?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:jaxrs="http://cxf.apache.org/jaxrs"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/jaxrs
        http://cxf.apache.org/schemas/jaxrs.xsd
">

    <!--发布接口-->
    <jaxrs:server address="/studentService">
        <jaxrs:serviceBeans>
            <bean class="com.jidi.learn.rs.web.StudentServiceImpl"/>
        </jaxrs:serviceBeans>
        <!--定义输入、输出拦截器-->
        <jaxrs:inInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
        </jaxrs:inInterceptors>
        <jaxrs:outInterceptors>
            <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
        </jaxrs:outInterceptors>
    </jaxrs:server>
</beans>

第四步,在 web.xml文件中配置CXFServlet:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
          http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         id="WebApp_ID" version="4.0">

  <display-name>cxf-rs-spring-server</display-name>

  <!-- 指定Spring的配置文件 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

  <!-- 实例化Spring容器 -->
  <!-- 应用启动时,该监听器被执行,它会读取Spring相关配置文件,其默认会到WEB-INF中查找applicationContext.xml -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!--webservice-->
  <servlet>
    <servlet-name>cxf</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>cxf</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>

第五步,启动应用,调用服务,以查詢所有的學生信息为例,访问:http://localhost:8080/cxf-rs-spring-server/studentService,可以看到响应内容:
在这里插入图片描述

2.2.2、客户端

客户端同原生CXF的一样,没有任何区别。

2.3、Spring Boot整合CXF实现

第一步,创建maven项目,引入相关依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>

<!--cxf(rs模式)-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-spring-boot-starter-jaxrs</artifactId>
    <version>3.2.4</version>
</dependency>

<!--json转换-->
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-rs-extension-providers</artifactId>
    <version>3.2.4</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jettison</groupId>
    <artifactId>jettison</artifactId>
    <version>1.3.7</version>
</dependency>

第二步,创建实体类,服务接口和实现类(同上);
第三步,编写配置类,发布服务:

/**
 * @Des
 * @Author jidi
 * @Email jidi_jidi@163.com
 */
@Configuration
public class JaxRsConfig {

    @Autowired
    private Bus bus;

    @Autowired
    private StudentService studentService;

    /**
     * 此bean可以将默认的前缀 services 更改为自定义的访问前缀
     */
    @Bean
    public ServletRegistrationBean cxfServlet() {
        return new ServletRegistrationBean(new CXFServlet(), "/rs/*");
    }

    /**
     * 发布服务
     */
    @Bean
    public Server studentService(){
        JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
        factory.setBus(bus);
        factory.setAddress("/student");
        factory.setServiceBean(studentService);
        return factory.create();
    }
}

第四步,测试服务是否发布成功。

三、调用第三方服务

在 Web Service 演示了同构系统之间,服务的发布和调用,但是实际上使用 Web Service 实现同构系统之间调用的情况是极少的,更多的是调用第三方异构系统发布的服务。此时,第三方异构系统内部的实现细节是无法知道的,只会暴露相关的wsdl描述文件,需要通过wsdl描述文件实现第三方服务的调用。下面以调用国内手机号码归属地查询WEB服务为例,讲解一下具体实现过程。

第一步,下载apache-cxf发布包:http://cxf.apache.org/download.html:
在这里插入图片描述
第二步,解压发布包,设置 CXF_HOME 变量,并添加 %CXF_HOME %/bin 到path环境变量:
在这里插入图片描述

第三步,CMD命令行输入wsdl2java -help,有正常提示说明环境已经正确配置:
在这里插入图片描述

第四步,通过 wsdl2java 生成webservice的客户端代码,命令如下:

// -encoding 表示生成的Java文件编码格式为utf8,
// -d 表示代码生成路径为E:/test
// -all 表示生成服务端跟客户端 
wsdl2java -encoding utf-8 -d E:/test -all http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl

第五步,创建maven工程,将生成的代码全部复制到项目工程中,包名使用其自动生成的,结构如下:在这里插入图片描述

第六步,根据自动生成的客户端代码,实现自己的业务处理逻辑:

/**
 * @Des 国内手机号码归属地查询WEB服务测试
 *      wsdl:http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
 * @Author jidi
 * @Email jidi_jidi@163.com
 */
public class MobileTest {

    @Test
    public void test(){
        // 创建服务调用客户端
        MobileCodeWS ws = new MobileCodeWS();

        // 获取调用服务接口
        MobileCodeWSSoap soap = ws.getMobileCodeWSSoap();

        // 通过接口调用服务
        String info = soap.getMobileCodeInfo("15271833124", null);
        
        // 处理逻辑
        System.out.println(info);
    }
}

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值