• WebService总结


    目录

    WebService简介

    WebService架构图

    理解:

    WebService的开发规范

    SOAP协议

    soap的组成

    WSDL 

    UDDI

    WebService的优缺点

    WebService优点

    WebService缺点

    SOA

    ApacheCXF框架

    CXF分为JAX-WS和JAX-RS两种开发方式

    ApacheCXF实现WebService(JAX-WS)

    服务端发布服务

    客户端访问服务

    ApacheCXF实现WebService(JAX-RS)

    服务端发布服务

    客户端访问服务

    WebService简介

    含义:webService即web服务,他是一种跨编程语言和跨操作系统平台的远程调用技术。

    WebService架构图

    理解:

    • 跨语言:右侧为服务端,左侧为客户端;若右边的服务使用PHP语言实现的,那么调用右边服务端的客户端不管是用什么语言实现的,都可以去远程访问右边的客户端的接口。
    • 跨平台:无论右边的服务端部署在那个系统平台,只要其提供了一个接口给外界去调用,那么左边的客户端部署在哪里,使用什么语言,一样可以远程调用服务端。
    • WebService主要适用于多个系统之间的交互以及数据传递

    注意:客户端与服务端可能使用不同语言开发的,但是通过webservice提供的服务接口,客户端与服务端之间可以传递对象。

    WebService的开发规范

    JAX-WS:java API for XML-WebService,jdk1.6版本自带JAX-WS2.1,其底层支持JAXB;JAX-WX规范的API位于javax.xml.ws.*包内,其中大部分都是注解,提供API操作web服务

    JAXM&SAAJ:

    • JAXM:java API for XML Message,其主要定义了包含发送和接收消息的API,相当于Web服务的服务器端,其API位于javax.messaging.*包,他是javaEE的可选包,因此需要单独下载
    • SAAJ:soap with Attachment API for java,其为与JAXM搭配使用的API,为构建soap包和解析soap包提供了重要的支持;其支持附件传输,他在客户端和服务端都需要使用,其API位于javax.xml.soap.*包

    JAX-RS:java API for RESTful Web Services,其是java针对REST风格定制的一套web服务规范,该API位于javax.ws.rs.*包内。

    注意:

    • JAX-WS和JAXM&SAAJ是基于soap协议,而JAX-RS基于http协议。
    • 三者规范中,只有jax-rs规范支持传递json数据,其他的规范都仅支持传递xml数据

    SOAP协议

    含义:simple object access protocol——简单对象访问协议,它是用于交换XML编码信息的轻量级协议。

    soap的组成

    • Envelope:其为必须的部分,以XML的根元素出现
    • Headers:可选的
    • Body:必须的,在body部分包含了要执行的服务器的方法和发送给服务器的数据

    理解:

    • soap作为一个基于XML语言的协议用于网上传输数据
    • soap是基于http的,他相当于在http的基础上+xml数据格式
    • soap可以运行在任何其他传输协议上
    • XML-envelope为描述信息内容和如何处理内容定义了框架,将程序编码成了XML对象的规则,执行远程调用(RPC)的约定 

    WSDL 

    含义:WSDL(网络服务描述语言,Web Services Description Language)是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问。

    理解:

    • 通过wsdl说明书,就可以描述webservice服务端对外发布的服务
    • wsdl说明书基于XML文件,其可以通过XML语言来描述整个服务
    • 在wsdl中描述了:对外发布的服务名称(类)、接口的方法名称(方法)、接口参数(方法参数)、服务返回的数据类型(方法返回值)
    • 一般在webservice的url后面跟上?wsdl来获取WSDL信息

    UDDI

    含义:UDDI是一个跨产业、跨平台的开放性架构,其可帮助web服务提供商在互联网上发布web服务的信息

    理解:

    • UDDI就是一种目录服务,企业可以通过UDDI来注册和搜索web服务
    • UDDI通过soap进行通讯,其构建于.NET之上

    WebService的优缺点

    WebService优点

    • 异构平台的互通性(跨平台)
    • 更广泛的软件复用(远程调用实现复用)
    • 成本低,可读性强,应用范围广(基于soap协议)
    • 更迅捷的软件发行方式

    WebService缺点

    由于soap是基于xml传输的,本身使用xml传输会传输一些无关的内容进而影响效率,随着soap的完善,soap协议增加了许多内容,这样就导致了使用soap去完成简单的数据传输而携带的信息变得更多进而影响效率

    注意:基于JAX-RS规范下的webservice也可以传输json格式数据,这在一定程度上弥补了传输效率问题

    SOA

    含义:面向服务架构,其是一种思想,它将应用程序的不通功能单元通过中立的契约联系起来,使得各种形式的功能单元相互集成,目前来说webservice是soa的一种较好的实现方式。

    ApacheCXF框架

    含义:其是Apache开源基金组织提供的优秀的webservice实现框架

    CXF分为JAX-WS和JAX-RS两种开发方式

    • JAX-WS:基于xml协议的WebService技术
    • JAX-RS:基于restful风格的开发方式

    ApacheCXF实现WebService(JAX-WS)

    服务端发布服务

    导入依赖

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.apache.cxfgroupId>
    4. <artifactId>cxf-rt-frontend-jaxwsartifactId>
    5. <version>3.0.1version>
    6. dependency>
    7. <dependency>
    8. <groupId>org.apache.cxfgroupId>
    9. <artifactId>cxf-rt-transports-http-jettyartifactId>
    10. <version>3.0.1version>
    11. dependency>
    12. <dependency>
    13. <groupId>org.slf4jgroupId>
    14. <artifactId>slf4j-log4j12artifactId>
    15. <version>1.7.12version>
    16. dependency>
    17. <dependency>
    18. <groupId>junitgroupId>
    19. <artifactId>junitartifactId>
    20. <version>4.11version>
    21. <scope>testscope>
    22. dependency>
    23. dependencies>

    在resources文件内添加日志(log4j.properties) 

    1. #info等级的日志输出到CONSOLE和LOGFILE这两个目的地(LOGFILE表示将日志写到文件中,CONSOLE则将日志写到控制台)
    2. log4j.rootCategory=info,CONSOLE,LOGFILE
    3. #设置日志优先控制台输出
    4. log4j.logger.org.apache.axis.enterprise=FATAL,CONSOLE
    5. #定义控制台日志输出器
    6. log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
    7. #控制台日志布局
    8. log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
    9. #控制台日志布局的设置
    10. log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601}%-6r[%15.15t]%-5p %30.30c %x-%m\n
    11. #定义文件日志输出器
    12. log4j.appender.LOGFILE=org.apache.log4j.FileAppender
    13. #日志的存放位置
    14. log4j.appender.LOGFILE.File=C:\\All\\jax.log
    15. #启用文件日志追加模式
    16. log4j.appender.LOGFILE.Append=true
    17. #文件日志布局
    18. log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout

    创建服务接口

    1. @WebService
    2. public interface HelloWorld {
    3. //对外发布服务的接口的方法
    4. public String sayHello(String name);
    5. }

    注意:对外发布服务的接口,需要用@webservice注解来标识这是一个webservice接口

    创建接口实现类

    1. public class HelloWorldImpl implements HelloWorld {
    2. public String sayHello(String name) {
    3. return name+"hello webservice!";
    4. }
    5. }

    测试类内发布服务

    1. public class WsTest {
    2. public static void main(String[] args) {
    3. //创建发布服务的工厂
    4. JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
    5. //设置服务地址
    6. factory.setAddress("http://localhost:8000/ws/hello");
    7. //设置发布的服务类
    8. factory.setServiceBean(new HelloWorldImpl());
    9. //添加日志输入、输出拦截器,观察soap请求以及soap响应内容
    10. factory.getInInterceptors().add(new LoggingInInterceptor());
    11. factory.getOutInterceptors().add(new LoggingOutInterceptor());
    12. //发布服务
    13. factory.create();
    14. System.out.println("发布服务成功,端口8000放行");
    15. }
    16. }

    访问wsdl说明书

    访问:http://localhost:8000/ws/hello?wsdl

    注意:在之前设置服务的地址后面加?wsdl

    1. <wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://impl.tedu.cn/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns2="http://schemas.xmlsoap.org/soap/http" xmlns:ns1="http://tedu.cn/" name="HelloWorldImplService" targetNamespace="http://impl.tedu.cn/">
    2. <wsdl:import location="http://localhost:8000/ws/hello?wsdl=HelloWorld.wsdl" namespace="http://tedu.cn/"> wsdl:import>
    3. <wsdl:binding name="HelloWorldImplServiceSoapBinding" type="ns1:HelloWorld">
    4. <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    5. <wsdl:operation name="sayHello">
    6. <soap:operation soapAction="" style="document"/>
    7. <wsdl:input name="sayHello">
    8. <soap:body use="literal"/>
    9. wsdl:input>
    10. <wsdl:output name="sayHelloResponse">
    11. <soap:body use="literal"/>
    12. wsdl:output>
    13. wsdl:operation>
    14. wsdl:binding>
    15. <wsdl:service name="HelloWorldImplService">
    16. <wsdl:port binding="tns:HelloWorldImplServiceSoapBinding" name="HelloWorldImplPort">
    17. <soap:address location="http://localhost:8000/ws/hello"/>
    18. wsdl:port>
    19. wsdl:service>
    20. wsdl:definitions>

    客户端访问服务

    导入依赖(和服务端使用的依赖一样)

    获得服务端接口

    1. @WebService
    2. public interface HelloWorld {
    3. public String sayHello(String name);
    4. }

    注意:客户端获得的服务端接口的包名.接口名必须与服务端的包名.接口名都相同才可以进行远程调用(也必须有@WebService注解)

    远程访问服务端

    1. public class ClientTest {
    2. public static void main(String[] args) {
    3. //服务接口的访问地址:http://localhost:8000/ws/hello
    4. //创建cxf代理工厂
    5. JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
    6. //设置远程访问服务端的地址
    7. factory.setAddress("http://localhost:8000/ws/hello");
    8. //设置接口的类型
    9. factory.setServiceClass(HelloWorld.class);
    10. //对该接口生成代理对象
    11. HelloWorld helloWorld = factory.create(HelloWorld.class);
    12. //打印代理对象类型
    13. System.out.println(helloWorld.getClass());
    14. //远程访问服务端方法
    15. String msg = helloWorld.sayHello("lili");
    16. System.out.println(msg);
    17. }
    18. }

    ApacheCXF实现WebService(JAX-RS)

    服务端发布服务

    导入依赖

    1. org.apache.cxf
    2. cxf-rt-frontend-jaxrs
    3. 3.0.1
    4. org.apache.cxf
    5. cxf-rt-transports-http-jetty
    6. 3.0.1
    7. org.slf4j
    8. slf4j-log4j12
    9. 1.7.12
    10. org.apache.cxf
    11. cxf-rt-rs-client
    12. 3.0.1
    13. org.apache.cxf
    14. cxf-rt-rs-extension-providers
    15. 3.0.1
    16. org.codehaus.jettison
    17. jettison
    18. 1.3.7
    19. junit
    20. junit
    21. 4.11
    22. test
    23. org.apache.maven.plugins
    24. maven-compiler-plugin
    25. 3.1
    26. 1.8
    27. 1.8
    28. UTF-8
    29. true

    在resources文件内添加日志(log4j.properties) 

    1. #info等级的日志输出到CONSOLE和LOGFILE这两个目的地(LOGFILE表示将日志写到文件中,CONSOLE则将日志写到控制台)
    2. log4j.rootCategory=info,CONSOLE,LOGFILE
    3. #设置日志优先控制台输出
    4. log4j.logger.org.apache.axis.enterprise=FATAL,CONSOLE
    5. #定义控制台日志输出器
    6. log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
    7. #控制台日志布局
    8. log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
    9. #控制台日志布局的设置
    10. log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601}%-6r[%15.15t]%-5p %30.30c %x-%m\n
    11. #定义文件日志输出器
    12. log4j.appender.LOGFILE=org.apache.log4j.FileAppender
    13. #日志的存放位置
    14. log4j.appender.LOGFILE.File=C:\\All\\jax.log
    15. #启用文件日志追加模式
    16. log4j.appender.LOGFILE.Append=true
    17. #文件日志布局
    18. log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout

    创建实体类(User)

    1. @XmlRootElement(name="User")
    2. public class User {
    3. private String name;
    4. private String city;
    5. public String getName() {
    6. return name;
    7. }
    8. public void setName(String name) {
    9. this.name = name;
    10. }
    11. public String getCity() {
    12. return city;
    13. }
    14. public void setCity(String city) {
    15. this.city = city;
    16. }
    17. @Override
    18. public String toString() {
    19. return "User{" +
    20. "name='" + name + '\'' +
    21. ", city='" + city + '\'' +
    22. '}';
    23. }
    24. }

    @XmlRootElement(name="User")

    作用:基于restful风格的webservice,客户端与服务端之间的通讯可以传递xml数据、json数据;而@XmlRootElement用于指定对象序列化为xml或json数据时根节点的名称。

    1. xml形式
    2. 张三
    3. 北京
    4. json形式
    5. {"User":{"name":"张三","city":"北京"}}

    创建服务端接口(IUserService)

    1. @Path("/userService")
    2. @Produces("*/*")
    3. public interface IUserService {
    4. @POST
    5. @Path("/save")
    6. @Consumes({"application/xml","application/json"})
    7. String saveUser(User user);
    8. @GET
    9. @Path("/get/{name}")
    10. @Consumes("application/xml")
    11. @Produces({"application/xml","application/json"})
    12. User findUserByName(@PathParam("name") String name);
    13. }

    @Path("/userService")

    理解:该注解可以用在类上以及方法上,表示当前服务接口或接口方法对应的路径(若要访问接口方法则必须先访问接口,在接口的基础上进行path路径拼接)

    @POST或@GET

    含义:处理接口对应方法的请求类型

    @Produces({"application/xml","application/json"})

    含义:服务器所支持的返回的数据格式(xml格式或json格式)

    @Consumes("application/xml")

    含义:服务器所支持的请求数据的格式类型

    @PathParam

    作用:注解用于路径中的参数与接口方法中的参数进行绑定

    创建接口实现类(UserServiceImpl)

    1. public class UserServiceImpl implements IUserService {
    2. @Override
    3. public String saveUser(User user) {
    4. System.out.println("保存了"+user.toString());
    5. return "user保存成功";
    6. }
    7. @Override
    8. public User findUserByName(String name) {
    9. User user = new User();
    10. if ("lili".equals(name)){
    11. user.setName("lili");
    12. user.setCity("北京");
    13. }else {
    14. user.setName("随机");
    15. user.setCity("随机");
    16. }
    17. return user;
    18. }
    19. }

    发布服务

    1. public class JaxrsTest {
    2. public static void main(String[] args) {
    3. //创建发布服务的工厂
    4. JAXRSServerFactoryBean factoryBean = new JAXRSServerFactoryBean();
    5. //设置服务地址
    6. factoryBean.setAddress("http://localhost:8001/");
    7. //设置服务类
    8. factoryBean.setServiceBean(new UserServiceImpl());
    9. //添加日志输入输出拦截器
    10. factoryBean.getInInterceptors().add(new LoggingInInterceptor());
    11. factoryBean.getOutInterceptors().add(new LoggingOutInterceptor());
    12. //发布服务
    13. factoryBean.create();
    14. System.out.println("发布服务成功。端口:8001");
    15. }
    16. }

    访问:http://localhost:8001/userService/get/lili

    客户端访问服务

    导入依赖(和服务端使用的依赖一样)

    制作需要使用的实体类

    1. @XmlRootElement(name="User")
    2. public class User {
    3. private String name;
    4. private String city;
    5. public String getName() {
    6. return name;
    7. }
    8. public void setName(String name) {
    9. this.name = name;
    10. }
    11. public String getCity() {
    12. return city;
    13. }
    14. public void setCity(String city) {
    15. this.city = city;
    16. }
    17. @Override
    18. public String toString() {
    19. return "User{" +
    20. "name='" + name + '\'' +
    21. ", city='" + city + '\'' +
    22. '}';
    23. }
    24. }

    注意:这里实体类所用的包名可以和服务端的不一样,但是@XmlRootElement(name="User")注解必须存在

    远程调用服务端

    前言:这里远程调用服务端只需要使用WebClient工具类即可完成,他调用请求方法后所返回的返回值为Response对象,该对象可以通过readEntity()方法来获取特定类型的返回值供我们使用。

    WebClient中的静态方法

    • create(String url):表示请求的服务端url地址
    • type(String type):指定请求的数据格式(xml、json)
    • accept(String type):指定接收响应的数据格式(xml、json)
    • post(请求参数):表示要带着该参数来发起post请求

    注意:以上方法除了post()和get()等请求的方法返回值为Response类型,其他方法的返回值均为WebClient类型,所以可以实现链式调用

    1. public class ClientTest {
    2. public static void main(String[] args) {
    3. User user = new User();
    4. user.setName("nana");
    5. user.setCity("广东");
    6. //通过WebClient对象远程调用服务端(post请求)
    7. Response response = WebClient.create("http://localhost:8001/userService/save").type("xml").accept("json").post(user);
    8. //读取response中请求体的内容,并获取特定类型的返回值
    9. String s = response.readEntity(String.class);
    10. System.out.println(s);
    11. //通过WebClient对象远程调用服务端(get请求)
    12. Response response1 = WebClient.create("http://localhost:8001/userService/get/lili").accept("xml").type("json").get();
    13. //读取response中请求体的内容,并获取特定类型的返回值
    14. User user1 = response1.readEntity(User.class);
    15. System.out.println(user1);
    16. }
    17. }

  • 相关阅读:
    【计算机网络】第四章 网络层
    Mysql的索引
    livekit 源码编译
    Python 断言的使用
    day01-4-订座功能
    【牛客网-前端笔试题】——Javascript专项练习
    SSM整合Thymeleaf时,抽取公共页面并向其传递参数
    【LeetCode Cookbook(C++ 描述)】一刷二叉树之递归遍历(DFS)(下)
    本周投融报:CeFi积聚风投吸引力
    每日leetcode[最后一个单词的长度】
  • 原文地址:https://blog.csdn.net/m0_60027772/article/details/127774760