Soap从入门到实战
Soap从入门到实战
参考文章:https://howtodoinjava.com/spring-boot/spring-soap-client-webservicetemplate/
使用的技术:springboot + jaxb
一.soap是什么
网上是这样解释的:
SOAP 是基于 XML 的简易协议,可使应用程序在 HTTP 之上进行信息交换。或者更简单地说:SOAP 是用于访问网络服务的协议。
我的理解是:
- 1.他是一种网络传输协议
- 2.他的基础是http
- 3.他传输内容不再是常用的文本而是xml
二.soap和http的差别
- 1.soap传输内容的是xml,http传输的内容是文本
- 2.soap的wsdl文件可以暴露访问对象的接口,调用者可以详细的看到访问对象的结构。http只能传输文本没有描述信息,前端如果需要接口信息需要后端使用第三方插件或者自己书写。
三.Wsdl
wsdl是Web Sercivice Descripe Language 的简称,也就是说他是描述Web服务的语言。描述的内容有服务的路由,方法名,返回值等等。
四.Wsdl基本结构
<?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>
Envelope是强制使用的,我认为是一种引用的约束吧,强调我们的xml内容定义为soap消息
五.soap实列
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.definesys.com/xml/employee"
targetNamespace="http://www.definesys.com/xml/employee" elementFormDefault="qualified">
<xs:element name="EmployeeDetailRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="Employee" type="tns:Employee"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="EmployeeDetailResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="Employee" type="tns:Employee"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Employee">
<xs:sequence>
<xs:element name="code" type="xs:string"></xs:element>
<xs:element name="name" type="xs:string"></xs:element>
<xs:element name="email" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
namespace:http://www.definesys.com/xml/employee 自己取的
targetNamespace="http://www.definesys.com/xml/employee" 自己定义的
EmployeeDetailRequest:访问的入口,其中的内容是访问时需要的参数
EmployeeDetailResponse:返回的出口,其中的内容是返回时返回的参数
六.使用Springboot实战
1.建立一个Web Service
File-------> New------->Project-------->Spring Initializer ------>web,web service
2.导入jaxb依赖生成pojo等对象
1.向pom中添加如下内容
<!--插件-->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>${project.basedir}/src/main/resources/</schemaDirectory>
<!--<schemaFiles>employee.xsd</schemaFiles>-->
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<packageName>com.example.webservice.entity</packageName>
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>
${project.basedir}/src/main/java: 定义输出文件的根目录
com.example.webservice.entity :生成pojo的包名称
false是否清空包目录
生成的pojo如下:
Employee:真实的普通java对象
EmployeeDetailRequest: 封装了Emploee可以将请求中的soap对象解析成普通的Employee对象
EmployeeDetaiResponse: 将普通的Employee对象封装成Soap对象
package-info.java:绑定输出对象的命名空间
3.相关注释的解释
@XmlAccessorType(XmlAccessType.FIELD)
定义类级别,将类的字段都写到xml中
@XmlType(name = "Employee", propOrder = { "code", "name", "email"})
类定义级别,定义字段写到xml中的顺序
@XmlElement(required = true)
字段定义级别,将字段写入到xml中
@XmlRootElement(name = "EmployeeDetailRequest")
类定义级别,name指的是映射到xml时的名称
4.写一个配置文件来生成wsdl
package com.example.webservice.config;
import org.springframework.beans.factory.parsing.DefaultsDefinition;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.ws.wsdl.WsdlDefinition;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;
@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
@Bean
public ServletRegistrationBean messageDispathcherServlet(ApplicationContext applicationContext){
MessageDispatcherServlet servlet=new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet,"/cms/*");
}
@Bean(name="employee")
public WsdlDefinition defaultWsdl11Defination(XsdSchema employeeSchema){
DefaultWsdl11Definition wsdl=new DefaultWsdl11Definition();
wsdl.setPortTypeName("EmployeePort");
wsdl.setLocationUri("/cms/employee-detail");
wsdl.setTargetNamespace("http://www.definesys.com/xml/employee");
wsdl.setSchema(employeeSchema);
return wsdl;
}
@Bean
public XsdSchema employeeSchema(){
return new SimpleXsdSchema(new ClassPathResource("employee.xsd"));
}
}
messageDispathcherServlet:方法中指定我们项目访问的路径的根路径
defaultWsdl11Defination:将我们书写的不完整的xsd文件书写成一个完成的wsdl并返回这个wsdl文件,在其中 添加了PortTypeName(似乎没什么用,l类似于端口号),LocationUri(路径),TargetNamespace(没什么大用)
employeeSchema:返回我们自己写的xsd文件
@bean:将我们的wsdl对象注入到spring容器 其中name是我们url访问的路径,因此我访问的employee.wsdl的路径是http://localhost:9999/cms/employee.wsdl
5.书写我们的终端
package com.example.webservice.controller;
import com.example.webservice.entity.Employee;
import com.example.webservice.entity.EmployeeDetailRequest;
import com.example.webservice.entity.EmployeeDetailResponse;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
@Endpoint
public class EmploySoapController {
private static final String NAMESPACE_URI="http://www.definesys.com/xml/employee";
@PayloadRoot(namespace = NAMESPACE_URI,localPart = "EmployeeDetailRequest")
@ResponsePayload
public EmployeeDetailResponse getEmployee1(@RequestPayload EmployeeDetailRequest request){
EmployeeDetailResponse response=new EmployeeDetailResponse();
Employee employee=new Employee();
employee.setCode(2);
employee.setName(2);
employee.setEmail(2);
response.setEmployee(employee);
return response;
}
}
@PayloadRoot:namespace 指定我们的命名空间,客户端和服务端需要保持一致。localPart:在wsdl中访问的接口名,需要和wsdl中接口的名称一致,客户端访问的localPart也必须和wsdl中的接口一致。
@ResponsePayload 说明输出的是一个soap消息,和@ResponseBody有点类似
@RequesPayLoad 说明输入的是一个soap消息 和RequestBody类似
6.测试
1.下载soapui并安装
2.新建一个soap项目
3.添加一个wsdl文件
4.输入wsdl的路径,我的是下图路径,如果报错可以去浏览器看看能不能打开,不能就检查路径是否正确
http://localhost:9999/cms/employee.wsdl。没有改端口的朋友默认是8080
5.在request中输入内容,输出就是相应逻辑的输出
输出结果:
6.客户端访问:url填写wsdl的路径即可,localpart填写:相应的访问接口的localPart即可
Soap从入门到实战的更多相关文章
- 赞一个 kindle电子书有最新的计算机图书可买了【Docker技术入门与实战】
最近对docker这个比较感兴趣,找一个比较完整的书籍看看,在z.cn上找到了电子书,jd dangdang看来要加油啊 Docker技术入门与实战 [Kindle电子书] ~ 杨保华 戴王剑 曹亚仑 ...
- docker-9 supervisord 参考docker从入门到实战
参考docker从入门到实战 使用 Supervisor 来管理进程 Docker 容器在启动的时候开启单个进程,比如,一个 ssh 或者 apache 的 daemon 服务.但我们经常需要在一个机 ...
- webpack入门和实战(一):webpack配置及技巧
一.全面理解webpack 1.什么是 webpack? webpack是近期最火的一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX).coffee.样式(含less/sass).图片等都 ...
- CMake快速入门教程-实战
http://www.ibm.com/developerworks/cn/linux/l-cn-cmake/ http://blog.csdn.net/dbzhang800/article/detai ...
- Sping Boot入门到实战之入门篇(三):Spring Boot属性配置
该篇为Sping Boot入门到实战系列入门篇的第三篇.介绍Spring Boot的属性配置. 传统的Spring Web应用自定义属性一般是通过添加一个demo.properties配置文件(文 ...
- Sping Boot入门到实战之入门篇(二):第一个Spring Boot应用
该篇为Spring Boot入门到实战系列入门篇的第二篇.介绍创建Spring Boot应用的几种方法. Spring Boot应用可以通过如下三种方法创建: 通过 https://start.spr ...
- Sping Boot入门到实战之入门篇(一):Spring Boot简介
该篇为Spring Boot入门到实战系列入门篇的第一篇.对Spring Boot做一个大致的介绍. 传统的基于Spring的Java Web应用,需要配置web.xml, applicationCo ...
- Sping Boot入门到实战之入门篇(四):Spring Boot自动化配置
该篇为Sping Boot入门到实战系列入门篇的第四篇.介绍Spring Boot自动化配置的基本原理与实现. Spring Boot之所以受开发者欢迎, 其中最重要的一个因素就是其自动化配置特性 ...
- Sping Boot入门到实战之实战篇(一):实现自定义Spring Boot Starter——阿里云消息队列服务Starter
在 Sping Boot入门到实战之入门篇(四):Spring Boot自动化配置 这篇中,我们知道Spring Boot自动化配置的实现,主要由如下几部分完成: @EnableAutoConfigu ...
随机推荐
- diff 比较两个文件的不同
1.命令功能 diff 逐行比较文件内容,并输出文件差异. 2.语法格式 diff option file1 file2 diff 选项 文件1 文件2 参数说明 参数 参数说明 ...
- 计蒜客 蓝桥模拟 B.素数个数
用 0,1,2,3⋯70,1,2,3 \cdots 70,1,2,3⋯7 这 888 个数组成的所有整数中,质数有多少个(每个数字必须用到且只能用一次). 提示:以 000 开始的数字是非法数字. 代 ...
- python3-多重继承
继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能. 回忆一下Animal类层次的设计,假设我们要实现以下4种动物: Dog - 狗狗: Bat - 蝙蝠: Parrot - ...
- flask中自定义日志类
一:项目架构 二:自定义日志类 1. 建立log.conf的配置文件 log.conf [log] LOG_PATH = /log/ LOG_NAME = info.log 2. 定义日志类 LogC ...
- ==和is的区别 以及编码和解码
is和==的区别 1. id() id是python的一个内置函数,通过id()可以查看变量表的值在内存中的地址. s1 = 2 print(id(s1)) # 1514368064 s2 = 2 p ...
- GDOI2016总结
前言 第一次GDOI,收获了很多. 这几天下来的生活有趣而精彩,尽管我没有高级的腐败工具,但是还是通过偷抢拐骗各种方法满足了腐败的欲望了. BUT,参加GDOI可不是为了玩耍,而是去提升自己的实力,磨 ...
- vue组件学习(二)
父子组件之间的数据传递, 父传给子: 直接在组件上传,如:<count :number="2"> (冒号和不要冒号的区别,有冒号会自动转为相应的类型)在名为count的 ...
- spring mvc 绑定参数据默认值,是否必传,(RequestParam(value="id",defaultValue="1",required=true) )
@RequestMapping(value = "/detail", method = RequestMethod.GET) public String newDetail(@Re ...
- 【rust】rust安装,运行第一个Rust 程序 (1)
安装 Rust 在 Unix 类系统如 Linux 和 macOS 上,打开终端并输入: curl https://sh.rustup.rs -sSf | sh 回车后安装过程出现如下显示: info ...
- sh_07_买苹果增强版
sh_07_买苹果增强版 # 1. 输入苹果的单价 price_str = input("苹果的单价:") # 2. 输入苹果的重量 weight_str = input(&quo ...