新建服务端项目server
CalculatorService
package com.lct.web_service;
import javax.jws.*;
/**
* 计算器接口
* SEI(Service Endpoint Interface):服务终端接口,即webService提供的服务接口
* SIB(Service Implemention Bean):服务实现类,即webService提供的服务接口的实现类
*
* @javax.jws.WebService : 将 Java 类标记为实现 Web Service,或者将 Java 接口标记为定义 Web Service 接口
* 不过是服务端还是客户端,接口上都必须写上此注解
*/
@WebService
public interface CalculatorService {
//加法
//@WebService 中的方法上可以加上 @WebMethod 注解,也可以不加
//@WebMethod 注解写或不写,服务端都会将 @WebSerivce 中的所有方法提供给客户端掉
//写上的好处就是看起来更加直观而已,如同 @Override 重写注解意义,删除也无影响
public float addition(float a, float b);
//乘法
public float multiplication(float a, float b);
}
CalculatorServiceImpl
package com.lct.web_service;
import javax.jws.WebService;
import java.util.logging.Logger;
/**
* SEI(Service Endpoint Interface):服务终端接口,即webService提供的服务接口
* SIB(Service Implemention Bean):服务实现类,即webService提供的服务接口的实现类
*
* @javax.jws.WebService : 将 Java 类标记为实现 Web Service,或者将 Java 接口标记为定义 Web Service 接口
* endpointInterface:终端接口,定义服务抽象 Web Service 协定的服务端点接口的完整名称,通常设置为服务实现类的全路径
* 接口要写,实现类也必须写 @WebService
* @WebService 接口一共提供了以下属性,而且都有默认值,它们将来都会出现在 wsdl 的 xml 文件中
* String name() default "";
* String targetNamespace() default "";
* String serviceName() default "";
* String portName() default "";
* String wsdlLocation() default "";
* String endpointInterface() default "";
*/
@WebService(endpointInterface = "com.lct.web_service.CalculatorService")
public class CalculatorServiceImpl implements CalculatorService {
//日志记录器
public static final Logger logger = Logger.getGlobal();
@Override
public float addition(float a, float b) {
logger.info("加法计算:" + a + " + " + b + " = " + (a + b));
return a + b;
}
@Override
public float multiplication(float a, float b) {
logger.info("乘法计算:" + a + " x " + b + " = " + (a * b));
return a * b;
}
}
Web_Service
package com.lct.web_service;
import javax.xml.ws.Endpoint;
/**
* webServer 启动类
*/
public class Web_Service {
public static void main(String[] args) {
/**webService服务器提供给客户端访问的地址
* 192.168.1.20 为服务器 ip、3333为指定的端口号、web_server 为应用名称、calculator为标识
* 这个地址符合 http 地址即可,为了看起来更像是 web访问,所以才写了应用名,其实 http://192.168.1.20:3333/xxx 都是可以的
*/
String wsUrl = "http://127.0.0.1:4444/web_server/calculator";
/**
* javax.xml.ws.Endpoint 表示一个 web service 终端,这是一个抽象类,其中提供了静态方法可以直接调用
* Endpoint publish(String address, Object implementor)
* address:传输协议的 url 地址;
* implementor(实现者):web service 终端的实现类,因为一个 ws 接口可能会有多个实现类
*/
Endpoint.publish(wsUrl, new CalculatorServiceImpl());
}
}
新建客户端项目client
CalculatorService
package com.lct.web_service;
import javax.jws.WebService;
/**
* 计算器接口
* SEI(Service Endpoint Interface):服务终端接口,即webService提供的服务接口
* SIB(Service Implemention Bean):服务实现类,即webService提供的服务接口的实现类
*
* @javax.jws.WebService : 将 Java 类标记为实现 Web Service,或者将 Java 接口标记为定义 Web Service 接口
* 无论作为服务端还是客户端都必须写 @WebService 注解
*/
@WebService
public interface CalculatorService {
//加法
public float addition(float a, float b);
//乘法
public float multiplication(float a, float b);
}
package com.lct.web_service;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Logger;
/**
*/
public class Web_service {
//日志记录器
public static final Logger logger = Logger.getGlobal();
public static void main(String[] args) {
try {
/** url:webservice 服务端提供的服务地址,结尾必须加 "?wsdl"*/
URL url = new URL("http://127.0.0.1:4444/web_server/calculator?wsdl");
/** QName 表示 XML 规范中定义的限定名称,QName 的值包含名称空间 URI、本地部分和前缀。
* QName(final String namespaceURI, final String localPart):指定名称空间 URI 和本地部分的 QName 构造方法。
* 如下所示的两个数据都可以浏览器访问服务端时返回 xml 中第一行找到,如:
* <definitions xmlns:wsu=xxxxxxx targetNamespace="http://web_service.lct.com/" name="CalculatorServiceImplService">
*/
QName qName = new QName("http://web_service.lct.com/", "CalculatorServiceImplService");
/**
* Service 对象提供 Web 服务的客户端视图
* Service 作为以下内容的工厂:1、目标服务端点的代理,2、用于远程操作的动态面向消息调用的 javax.xml.ws.Dispatch 实例。
* create(java.net.URL wsdlDocumentLocation,QName serviceName):创建 Service 实例。
* wsdlDocumentLocation : 服务 WSDL 文档位置的 URL
* serviceName : 服务的 QName
*/
Service service = Service.create(url, qName);
/**
* 使用 getPorts 方法可以对服务上可用的端口/接口进行枚举
* getPort(Class<T> serviceEndpointInterface):获取支持指定服务端点接口的对象实例
* serviceEndpointInterface:指定返回的代理所支持的服务端点接口
*/
CalculatorService calculatorService = service.getPort(CalculatorService.class);
float added = calculatorService.addition(100, 80);
float multied = calculatorService.multiplication(2.5F, 100);
logger.info("added:" + added);
logger.info("multied:" + multied);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
创建服务端
创建客户端
格式说明
1)definitions 元素
A、WSDL 文档的根元素都是 definition 元素,其中主要的是最后的两个属性,targetNameSpace 与 name。
B、targetNameSpace 属性 对应 @WebService 注解的 targetNameSpace属性,name 属性对应 @WebService 注解的 serviceName 属性。
C、可以在 webService 服务端的接口实现类中的 @WebService 注解中通过修改属性,从而修改 wsdl 文件的definition 元素的属性值,否则 targetNameSpace 为 "http://" 加 "包名的反写",name 为 "实现类名称"+"Service"。
2)types 元素:定义访问的类型,如请求的方法名,参数,以及返回值等。
(url为: http://127.0.0.1:4444/web_server/calculator?wsdl )
<types>
<xsd:schema>
<xsd:import namespace="http://web_service.lct.com/" schemaLocation="http://127.0.0.1:4444/web_server/calculator?xsd=1"/>
</xsd:schema>
</types>
可以浏览器访问 schemaLocation 属性的值,看到详细信息。
(url为: http://127.0.0.1:4444/web_server/calculator?xsd=1 )
(请求:name="multiplication",响应:name="multiplicationResponse")
<xs:complexType name="multiplication">
<xs:sequence>
<xs:element name="arg0" type="xs:float"/>
<xs:element name="arg1" type="xs:float"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="multiplicationResponse">
<xs:sequence>
<xs:element name="return" type="xs:float"/>
</xs:sequence>
</xs:complexType>
3)message:SOAP 协议消息传递的参数,同样包括请求与返回两部分。
(url为: http://127.0.0.1:4444/web_server/calculator?wsdl )
(请求:name="addition",响应:name="additionResponse")
<message name="addition">
<part name="parameters" element="tns:addition"/>
</message>
<message name="additionResponse">
<part name="parameters" element="tns:additionResponse"/>
</message>
message 的元素会和 types 中的元素进行对应。
4)portType:指明服务器的接口,并且通过 operation 绑定相应的 input、ouput 消息。
<portType name="CalculatorService">
<operation name="addition">
<input wsam:Action="http://web_service.lct.com/CalculatorService/additionRequest" message="tns:addition"/>
<output wsam:Action="http://web_service.lct.com/CalculatorService/additionResponse" message="tns:additionResponse"/>
</operation>
</portType>
5)binding:指定消息传到所使用的格式
6)service:指定服务所发布的名称
JLA
//请求头
String url= ""; //请求url
HttpPost httpPost = new HttpPost(url);
String invoke = ""; //方法名
httpPost.addHeader("Content-Length", "<calculated when request is sent>"); //默认
httpPost.addHeader("Host", "10.0.71.79");
httpPost.addHeader("Content-Type", "text/xml;charset=utf-8");
httpPost.addHeader("SOAPAction","http://tempuri.org/"+invoke);
String param = ""; //数据
StringEntity se = new StringEntity(param);
se.setContentEncoding("UTF-8");
httpPost.setEntity(se);
HttpResponse response = httpClient.execute(httpPost);
String res = EntityUtils.toString(response.getEntity()); //得到回复
测试: http://192.168.11.251:9570/DrillSvr.asmx
发送请求: Drill_PartNumByLot
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<Drill_PartNumByLot xmlns="http://tempuri.org/">
<InStr>{"keyvalue1":"MP2401000244"}</InStr>
</Drill_PartNumByLot>
</soap:Body>
</soap:Envelope>
解析:<soap:Envelope><soap:Body></soap:Body></soap:Envelope> 默认格式,
<Drill_PartNumByLot></Drill_PartNumByLot> 为请求的方法名,http://tempuri.org/ 为域名。
<InStr></InStr> 参数名,里面为具体的请求内容。
得到回复:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<Drill_PartNumByLotResponse xmlns="http://tempuri.org/">
<Drill_PartNumByLotResult>{"Message":"OK","Result":[{"partnum":"S746GZ066C","revision":"E ","flag":1,"Qnty":60}]}</Drill_PartNumByLotResult>
</Drill_PartNumByLotResponse>
</soap:Body>
</soap:Envelope>
解析:<soap:Envelope><soap:Body></soap:Body></soap:Envelope> 默认格式,
<Drill_PartNumByLotResponse></Drill_PartNumByLotResponse> 为回复请求的方法名,http://tempuri.org/为域名。
<Drill_PartNumByLotResult></Drill_PartNumByLotResult> 为回复请求的参数名,里面为具体的回复内容。
**********GetDrillDailyByLot begin**********
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetDrillDailyByLot xmlns="http://tempuri.org/">
<lotNum>MP2402000276</lotNum>
</GetDrillDailyByLot>
</soap:Body>
</soap:Envelope>
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetDrillDailyByLotResponse xmlns="http://tempuri.org/">
<GetDrillDailyByLotResult>[{"Machine":"75#","STime":"2024-02-21 14:00:00","Qnty":"1","SizingX":"","SizingY":""}]</GetDrillDailyByLotResult>
</GetDrillDailyByLotResponse>
</soap:Body>
</soap:Envelope>
**********GetDrillDailyByLot over**********
**********Drill_PartNumByLot begin**********
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<Drill_PartNumByLot xmlns="http://tempuri.org/">
<InStr>{"keyvalue1":"MP2402000276"}</InStr>
</Drill_PartNumByLot>
</soap:Body>
</soap:Envelope>
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<Drill_PartNumByLotResponse xmlns="http://tempuri.org/">
<Drill_PartNumByLotResult>{"Message":"OK","Result":[{"partnum":"A068E0869A","revision":"B ","flag":1,"Qnty":100}]}</Drill_PartNumByLotResult>
</Drill_PartNumByLotResponse>
</soap:Body>
</soap:Envelope>
**********Drill_PartNumByLot over**********
**********UploadDrillDailyRecord开始 begin **********
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<UploadDrillDailyRecord xmlns="http://tempuri.org/">
<machine>75#</machine>
<lotNum>MP2402000276</lotNum>
<sEmpId>180649</sEmpId>
<sTime>2024-02-21 14:00:00</sTime>
<eEmpId>string</eEmpId>
<eTime>string</eTime>
<qnty>1</qnty>
<bbd>string</bbd>
<bbc>string</bbc>
<bba>string</bba>
<wwc>string</wwc>
<equation>H-HFTD.txt</equation>
<remark>test</remark>
<sizeFileName>s732ez067dd.exp</sizeFileName>
<uploadType>Start</uploadType>
</UploadDrillDailyRecord>
</soap:Body>
</soap:Envelope>
**********UploadDrillDailyRecord开始 over**********
**********UploadDrillDailyRecord结束 begin**********
**********bbc和wwc 有约束**********
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<UploadDrillDailyRecord xmlns="http://tempuri.org/">
<machine>75#</machine>
<lotNum>MP2402000276</lotNum>
<sEmpId>180649</sEmpId>
<sTime>2024-02-21 14:00:00</sTime>
<eEmpId>string</eEmpId>
<eTime>string</eTime>
<qnty>1</qnty>
<bbd>string</bbd>
<bbc>0</bbc>
<bba>string</bba>
<wwc>1</wwc>
<equation>H-HFTD.txt</equation>
<remark>test</remark>
<sizeFileName>s732ez067dd.exp</sizeFileName>
<uploadType>End</uploadType>
</UploadDrillDailyRecord>
</soap:Body>
</soap:Envelope>
**********UploadDrillDailyRecord结束 over**********