WebService

Posted 狼_少_年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebService相关的知识,希望对你有一定的参考价值。

1.什么是WebService?

WebService是一种跨编程语言,跨操作系统平台的远程调用技术.

即使服务端和客户端程序的编程语言,操作系统不同,客户端上的程序也可以调用到服务端接口提供的方法

举例:

1)商家的pos机调用银行服务器上的方法进行转账

2)百度调用天气预报系统

2.WebService的三个规范

1)JAX-WS(Java API for XML-Based Webservices)规范

采用基于http应用层的协议Soap(Simple Object Access Protocol),Soap协议传输的是xml数据,xml是WebService可以跨操作系统平台的基础,因为xml主要的优点就是它既与平台无关,也与厂商无关.

W3C为WebService制定了一套传输数据类型,使用xml进行描述,即XSD(XML Schema Datatypes),任何编程语言写的WebService接口在发送数据时都要转换成WebService标准的XSD发送.

1.1)JAX-WS三要素

1.SOAP:基于HTTP协议,采用XML格式,用来传递信息的格式

2.WSDL:用来描述如何访问具体服务的文档(JAX-WS可自动生成对外接口的\\说明文档,但此文档并不是给程序员提供的,而是给JDK提供的)

3.UDDI:用户可以按UDDI标准搭建UDDI服务器,用来管理分发查询WebService(类似目录收集)

2)JAX-RS规范

是JAVA针对REST风格制定的一套Web服务规范,rest风格的WebService不采用SOAP协议传输,而是采用http协议,可以返回xml或json.

Apache CXF(Celtix+Xfire)是一个开源的WebService框架,支持多种协议,包括SOAP,XML/HTTP,RESTFUL,正是因为CXF支持RESTFUL风格,所以CXF也是支持JAX-RS服务规范的框架.

3)JAXM&SAAJ

编码麻烦,暴露SOAP的底层细节,废弃

3.JAX_RS整合Spring案例

3.1 模拟服务提供方(生产者)

3.1.1 创建服务提供者,项目名称:spring_jax_rs_server

 

3.1.2 引入依赖,指定打包方式war

<dependencies>
        <!-- cxf 进行rs开发 必须导入  -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
            <version>3.0.1</version>
        </dependency>
        <!-- 日志引入  -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
        <!-- 客户端 -->
        <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>
        <!-- 转换json工具包,被extension providers 依赖 -->
        <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>4.2.4.RELEASE</version>
        </dependency>
        <!-- spring web集成 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <!-- spring 整合junit  -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <!-- junit 开发包 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

3.1.3 编写实体类

注意:@XmlRootElement注解作用:指明xml中根标签的名称,可对比下面的服务端返回的xml

package com.jaxrs.domain;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "User")
public class User {
    private Integer id;
    private String username;
    private String city;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}

3.1.4 编写提供给客户端的接口及实现类

注意:@Produces注解作用:用来指定资源能够生成并发送给客户端的MIME媒体类型

         @Consumes注解作用:用来指定资源能够接受的客户端发送的MIME媒体类型

package com.jaxrs.service;

import com.jaxrs.domain.User;

import javax.ws.rs.*;
import java.util.List;

/**
 * @author Adil
 * @date 2020-03-21 13:32:18
 */
@Path("/userService")
@Produces("*/*")
public interface UserService {

    @POST
    @Path("/user")
    @Consumes({"application/xml", "application/json"})
    public void saveUser(User user);

    @PUT
    @Path("/user")
    @Consumes({"application/xml", "application/json"})
    public void updateUser(User user);

    @GET
    @Path("/user")
    @Produces({"application/xml", "application/json"})
    public List<User> findAllUsers();

    @GET
    @Path("/user/{id}")
    @Consumes("application/xml")
    @Produces({"application/xml", "application/json"})
    public User finUserById(@PathParam("id") Integer id);

    @DELETE
    @Path("/user/{id}")
    @Consumes({"application/xml", "application/json"})
    public void deleteUser(@PathParam("id") Integer id);
}
package com.jaxrs.service.impl;

import com.jaxrs.domain.User;
import com.jaxrs.service.UserService;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Adil
 * @date 2020-03-21 13:33:49
 */
public class UserServiceImpl implements UserService {
    public void saveUser(User user) {
        System.out.println("save user:" + user);
    }

    public void updateUser(User user) {
        System.out.println("update user:" + user);
    }

    public List<User> findAllUsers() {
        List<User> users = new ArrayList<User>();
        User user1 = new User();
        user1.setId(1);
        user1.setUsername("小明");
        user1.setCity("北京");
        users.add(user1);
        User user2 = new User();
        user2.setId(2);
        user2.setUsername("小丽");
        user2.setCity("上海");
        users.add(user2);
        return users;
    }

    public User finUserById(Integer id) {
        if (id == 1) {
            User user1 = new User();
            user1.setId(1);
            user1.setUsername("小明");
            user1.setCity("北京");
            return user1;
        }
        return null;
    }

    public void deleteUser(Integer id) {
        System.out.println("delete user id :" + id);
    }
}

3.1.5 编写applicationContext.xml

注意:address属性作用:添加路由(可写可不写,如果写了,客户端发送的url中就要包含此路径)

        serviceClass属性作用:映射到实现类

<?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:cxf="http://cxf.apache.org/core"
    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.xsd
        http://cxf.apache.org/core
        http://cxf.apache.org/schemas/core.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
        ">
    <jaxrs:server address="/toUserService" serviceClass="com.jaxrs.service.impl.UserServiceImpl"></jaxrs:server>
</beans>

3.1.6 编写web.xml

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

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!--全局加载监听器,监听applicationContext.xml配置文件-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- CXF的核心控制器 如果与spring整合需要配置 CXF核心控制器 作用跟DispathcerServlet一样 -->
    <servlet>
        <servlet-name>cxfServlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>cxfServlet</servlet-name>
        <url-pattern>/rs/*</url-pattern>
    </servlet-mapping>
</web-app>

 以上简单模拟了一个服务端,实际服务端是不需要我们自己写的,因为使用WebService,就是调用其他的系统,肯定是已经写好并对你开放的,接下来我们配置tomcat,就可以启动服务了.

我们先通过浏览器端进行访问:http://localhost:8080/rs/toUserService/userService/user/1

<User>
<city>北京</city>
<id>1</id>
<username>小明</username>
</User>

<User>就是@XmlRootElement注解指定的根标签的名称

3.2基于JAX-RS的客户端

3.2.1 创建客户端项目

3.2.2 引入依赖(与服务端保持一致)

3.2.3 编写实体类(与服务端保持一致)

3.2.3 调用服务

注意:调用的url路径及传入的参数要遵守服务端的规定

package com.jaxrs.client;

import com.jaxrs.domain.User;
import org.apache.cxf.jaxrs.client.WebClient;

/**
 * @author Adil
 * @date 2020-03-21 14:11:19
 */
public class JaxRsClient {
    public static void main(String[] args) {
        WebClient webClient = WebClient.create("http://localhost:8080/rs/toUserService/userService/user/1");
        User user = webClient.get(User.class);
        System.out.println(user);
    }
}

接下来,启动main方法,可以看到控制台打印服务端返回的User对象

4.JAX-WS整合Spring调用互联网系统(IP地址来源搜索)案例

4.1 创建客户端项目 

 

4.2 引入依赖

<dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.0.1</version>
        </dependency>
        <!-- 日志引入  -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
        <!-- 转换json工具包,被extension providers 依赖 -->
        <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.0.5.RELEASE</version>
        </dependency>
        <!-- spring web集成 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
        <!-- spring 整合junit  -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
        <!-- junit 开发包 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

4.3 通过JDK解析WDSL文档生成代码

在JAX-WS规范的介绍中,我们就说了,它有自己的对外接口说明文档,而JDK是可以解析该文档生成代码的.命令如图

执行完该命令后,我们会在java下看到多了几个包和很多文件,其中.class文件我们全部删除掉.

4.4 配置Spring整合

address指定WSDL文件的位置

serviceClass指定生成的接口的位置

<?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:cxf="http://cxf.apache.org/core"
       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/core
        http://cxf.apache.org/schemas/core.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:client id="ipAddress" address="http://www.webxml.com.cn/WebServices/IpAddressSearchWebService.asmx?wsdl"
                  serviceClass="cn.com.webxml.IpAddressSearchWebServiceSoap"></jaxws:client>
</beans>

4.5 调用服务

通过id得到接口对象,打点可以查看其中的方法,这里是getCountryCityByIp(),即通过ip查看所在城市位置

package cn.com.client;

import cn.com.webxml.ArrayOfString;
import cn.com.webxml.IpAddressSearchWebServiceSoap;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

/**
 * @author Adil
 * @date 2020-03-21 18:36:22
 */
public class JaxwsClient {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-cxf-client.xml");
        IpAddressSearchWebServiceSoap ipAddress = (IpAddressSearchWebServiceSoap) context.getBean("ipAddress");
        ArrayOfString city = ipAddress.getCountryCityByIp("111.198.224.201");
        System.out.println(city.getString())

返回结果

以上是关于WebService的主要内容,如果未能解决你的问题,请参考以下文章

C#动态调用webService出现 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。

Java RMI地址解析问题

当我们在webservice.asmx.cs中编写所有代码时,webservice.asmx有啥用?

自动生成webservice客户端代码后怎么调用

在idea中,怎么生成cxf webservice的客户端代码

如何调用webservice接口 ajax