JRT实现原生Webservice发布

之前准备试试Java发布Webservice,开始以为很简单,因为C#发布很简单。后面发现太费劲了,依赖一堆包,下面几种都试了一下:

JAX-WS (Java API for XML Web Services):这是Java EE平台的标准,用于创建和发布Web服务。JAX-WS提供了一种简单的方法来发布和调用Web服务,它基于SOAP协议。
Apache CXF:这是一个开源框架,用于构建和开发Web服务和RESTful服务。它支持多种协议,包括SOAP和REST。
Axis2:这是另一个开源框架,用于构建和发布SOAP和RESTful Web服务。Axis2是Apache的一个项目,具有高度的可配置性和灵活性。
Spring Boot + Spring Web Services:如果你使用Spring Boot框架,你可以通过集成Spring Web Services来轻松创建和发布Web服务。
Jersey:这是另一个用于构建RESTful Web服务的开源框架。它是JAX-RS规范的一个实现,并且是Java EE 7的一部分。

依赖太多,补了一个又报一个,最终决定放弃算了,反正对外提供Post也行,调别人的服务自己按soapui的串Post就行了。欢哥业余搞了个基础版的soap协议,支持基础类型,这样也不错。我之前介绍过http的本质就是TCP协议上约束发送和响应格式的TCP,并且用C#和M写过测试。

c语言发布http

Cache实现http

Webservice的本质就是基于http的传输协议约定了请求和响应格式,服务器按请求体执行方法,按响应格式组装响应体。没有那么玄乎,任何有TCP协议的语言自己可以比较简单的实现常规http协议,并且在http基础上实现常规的Webservice协议,当然,要实现全套协议还是很费劲的,但是常用的就是最基本的类型。

下面是欢哥实现的Webservice协议:

首先定义服务的注解,服务实现类申明此注解

package JRT.WebService.WS.Annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** WebService特性,作用类,标识该类可以对外发布服务*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface WebServer
{/*** 服务名称* @return*/public String ServiceName() default "WebServer";/*** 命名空间* @return*/public String XmlNameSpace() default "";
}

然后定义方法注解,要公布Webservice的方法加上此注解

package JRT.WebService.WS.Annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** WebService方法特性,作用于方法,标识方法可对外发布服务,没标识该注解的方法不生成soap文档*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface WebMethod
{
}

让后定义参数注解,可以指定参数名

package JRT.WebService.WS.Annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 标识要发布Webservice的方法的参数对外名称*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface WebParam
{/*** 参数名称* @return*/public String Name() default "";
}

然后抽取Webservice调用接口

package JRT.WebService.Http;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;/*** 抽取的Webservice请求处理接口,WebService基类实现该接口供主请求按接口调用*/
public interface IBaseWebServiceHandler {/*** Http get请求,根据请求处理生成wsdl文档** @param request  请求对象* @param response 响应对象* @throws Exception*/void DealGet(HttpServletRequest request, HttpServletResponse response) throws Exception;/*** Http post请求,解析处理请求的soap文档,反射执行调用方法,并生成项目的soap文档** @param request  请求对象* @param response 响应对象* @throws Exception*/void DealPost(HttpServletRequest request, HttpServletResponse response) throws Exception;
}

实现Webservice基类,返回soap协议和执行请求体,soap协议就在这里面

package JRT.WebService.Http;import JRT.Core.Util.JsonUtil;
import JRT.Core.Util.LogUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.w3c.dom.*;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.nio.charset.Charset;/*** Webservice实现基类,实现soap协议的生成和解析执行,所有webservice实现类都继承该基类*/
public class BaseWebServiceHandler implements JRT.WebService.Http.IBaseWebServiceHandler {/*** Http get请求,根据请求处理生成wsdl文档** @param request  请求对象* @param response 响应对象* @throws Exception*/public void DealGet(HttpServletRequest request, HttpServletResponse response) throws Exception {response.setCharacterEncoding("UTF-8");   //设置响应内容编码UTF-8response.setContentType("text/xml");   //设置响应mime类型为text/xml//获取请求的url,wsdl问了里面需要使用该urlString url = request.getRequestURL().toString();//获取当前类名称Class clz = this.getClass();//根据类名称和请求url生成wsdl文档String xml = JRT.WebService.WS.Wsdl.WsdlXmlUtil.GetWsdlXml(clz, url);response.getWriter().print(xml);}/*** Http post请求,解析处理请求的soap文档,反射执行调用方法,并生成项目的soap文档** @param request  请求对象* @param response 响应对象* @throws Exception*/public void DealPost(HttpServletRequest request, HttpServletResponse response) throws Exception {//设置响应内容编码response.setCharacterEncoding("UTF-8");//设置响应mime类型为text/xmlresponse.setContentType("text/xml");//获取当前类名称,用于反射执行当前类发布的方法Class clazz = this.getClass();try {//获取post提交的内容BufferedInputStream bis = new BufferedInputStream(request.getInputStream());//将请求的内容转换成文本,使用utf-8编码String req = new String(bis.readAllBytes(), Charset.forName("UTF-8"));//简单清理一些格式化字符req = req.replaceAll("\n|\r", "").replaceAll(">\\s+<", "><");//创建字节输入流ByteArrayInputStream bais = new ByteArrayInputStream(req.getBytes("UTF-8"));//创建xml文档构建工厂对象DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();//从字节输入流解析生成xml文档对象Document document = builder.parse(bais);// 获取根节点 soapenv:EnvelopeElement root = document.getDocumentElement();//获取根节点名称String rootname = root.getNodeName();//节点名称":"号的前缀根据不同的请求会有差异,所以这里取出来,响应的soap文档的节点前缀也是用这个String nodename_pre = "";if (rootname.contains(":")) {nodename_pre = rootname.split(":")[0];}// 获取soap的bodyNode body = null;   //soap bodyNode header = null; // soap header//获取根节点的所有子节点NodeList rootchildren = root.getChildNodes();//遍历字节的找到body和header节点,只处理这两个节点for (int i = 0; i < rootchildren.getLength(); i++) {Node node = rootchildren.item(i);String nodename = node.getNodeName();if (nodename.contains("Body")) {body = node;}if (nodename.contains("Header")) {header = node;}}//没有body节点认为请求的soap文档不合要求,抛出异常if (body == null) {throw new Exception("未获取到Body");}// 获取请求的方法节点,此处默认body的第一子节点为请求的方法节点Node method = body.getFirstChild();// 方法名称String methodname = method.getNodeName();String[] name_arr = methodname.split(":");//去除方法名称前缀if (name_arr.length >= 2) {methodname = name_arr[1];}//未获取到方法名称抛出异常if (methodname == null || methodname.isEmpty()) {throw new Exception("未获取到请求方法");}// 处理参数,方法节点的子节点为参数节点NodeList params = method.getChildNodes();//参数个数int length = params.getLength();//参数值,数组Object[] args = new Object[length];//参数类型对象,数组Class<?>[] type_arr = new Class[length];for (int i = 0; i < length; i++) {Node node = params.item(i);String value = node.getTextContent();//获取参数节点属性NamedNodeMap attrs = node.getAttributes();Class<?> clz = null;for (int k = 0; k < attrs.getLength(); k++) {Node attr = attrs.item(k);String attrname = attr.getNodeName();//属性名称包含type,则获取参数类型,并实例化class对象if (attrname.toLowerCase().contains("type")) {String typename = attr.getTextContent();//处理参数名前缀if (typename.contains(":")) {typename = typename.split(":")[1];}clz = GetTypeClass(typename);}}//没有配到对应参数默认Stringif (clz == null) {clz = String.class;}type_arr[i] = clz;args[i] = GetValue(clz, value);}//反射获取当前类方法对象Method objm = null;try {objm = clazz.getMethod(methodname, type_arr);} catch (Exception ex) {JRT.Core.Util.LogUtils.WriteExceptionLog("执行" + clazz.getName() + "的方法" + methodname + "异常", ex);StringWriter stringWriter = new StringWriter();ex.printStackTrace(new PrintWriter(stringWriter));response.getWriter().print(stringWriter.toString());}//方法不存在抛异常if (objm == null) {throw new Exception("请求" + clazz.getName() + "方法不存在!" + methodname);}//反射调用方法Object ret = objm.invoke(this, args);//方法无返回值默认""if (ret == null) {ret = "";}//在原xml上构建新的xml,先移除原有的header和bodyif (body != null) {root.removeChild(body);}if (header != null) {root.removeChild(header);}//构造新的header和body//构建headerNode header_node = document.createElement(nodename_pre + ":Header");root.appendChild(header_node);//构建body及其执行结果子节点Node body_node = document.createElement(nodename_pre + ":Body");Node resp = document.createElement(methodname + "Response");// 获取节点的属性列表NamedNodeMap attributes = method.getAttributes();((Element) resp).setAttribute("xmlns", "http://tempuri.org/");Node res = document.createElement(methodname + "Result");res.setTextContent(ret.toString());resp.appendChild(res);body_node.appendChild(resp);root.appendChild(body_node);//将xml Document转成序列化TransformerFactory trans = TransformerFactory.newInstance();Transformer transformer = trans.newTransformer();transformer.setOutputProperty(OutputKeys.INDENT, "YES");transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");StringWriter sr = new StringWriter();transformer.transform(new DOMSource(document), new StreamResult(sr));String xml = sr.toString().replaceAll("\n|\r", "").replaceAll(">\\s+<", "><");//添加xml头并且响应内容,?头部也可以不用添加response.getWriter().write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + xml);} catch (Exception ex) {StringWriter stringWriter = new StringWriter();ex.printStackTrace(new PrintWriter(stringWriter));response.getWriter().print(stringWriter.toString());JRT.Core.Util.LogUtils.WriteExceptionLog("调用" + clazz.getName() + "异常", ex);}}/*** 根据名称获取类型对象** @param typename* @return*/private Class<?> GetTypeClass(String typename) {Class<?> clz = null;if (typename == null || typename.isEmpty()) {return clz;}switch (typename.toLowerCase()) {case "int": {clz = int.class;break;}case "float": {clz = float.class;break;}case "long": {clz = long.class;break;}case "string": {clz = String.class;break;}case "double": {clz = double.class;break;}case "byte": {clz = byte.class;break;}case "char": {clz = char.class;}default: {clz = String.class;}}return clz;}/*** 根据值类型对象,从字符串转换对应的值** @param clz 值类型对象* @param v   值* @return*/private Object GetValue(Class<?> clz, String v) {Object value = null;if (clz.equals(int.class)) {value = Integer.valueOf(v);if (value == null) {value = 0;}} else if (clz.equals(float.class)) {value = Float.valueOf(v);if (value == null) {value = 0.0f;}} else if (clz.equals(long.class)) {value = Long.valueOf(v);if (value == null) {value = 0L;}} else if (clz.equals(byte.class)) {value = Byte.valueOf(v);} else if (clz.equals(double.class)) {value = Double.valueOf(v);if (value == null) {value = 0D;}} else if (clz.equals(char.class)) {value = v.charAt(0);} else {value = v;}return value;}
}

组装xml用到的节点实体

package JRT.WebService.WS.XML;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** xml节点,供组装wsdl的基础数据结构,存各个块的节点,最后序列化成xml*/
public class XmlNode {/*** 名称** @param name*/public XmlNode(String name) {this.Name = name;}/*** 名称*/public String Name = "";/*** 属性*/public Map<String, String> PropertyList = new HashMap<>();/*** 值*/public String Value = "";/*** 子节点*/public List<XmlNode> ChildNode = new ArrayList<>();/*** 序列化** @return*/public String Serialize() {if (Name == null || Name.isEmpty()) return "";String attrs = "";for (String key : PropertyList.keySet()) {String value = PropertyList.get(key);value = JRT.WebService.WS.XML.XmlUtil.XmlEscape(value);if (attrs.equals("")) {attrs = key + "=\"" + value + "\"";} else {attrs = attrs + " " + key + "=\"" + value + "\"";}}String childStr = "";for (XmlNode node : ChildNode) {childStr += node.Serialize();}StringBuilder xml = new StringBuilder();xml.append("<" + Name);if (!attrs.isEmpty()) {xml.append(" " + attrs);}xml.append(">");xml.append(JRT.WebService.WS.XML.XmlUtil.XmlEscape(Value));xml.append(childStr);xml.append("</" + Name + ">");return xml.toString();}/*** 插入** @param name* @param value*/public void Insert(String name, String value) {XmlNode node = new XmlNode(name);node.Value = value;this.ChildNode.add(node);}/*** 插入** @param node*/public void Insert(XmlNode node) {this.ChildNode.add(node);}
}

xml冲突符处理工具

package JRT.WebService.WS.XML;public class XmlUtil {/*** XML转义工具** @param xml* @return*/public static String XmlEscape(String xml) {if (xml == null || xml.isEmpty()) return "";xml = xml.replace("&", "&amp;");xml = xml.replace("<", "&lt;");xml = xml.replace(">", "&gt;");xml = xml.replace("'", "&apos;");xml = xml.replace("\"", "&quot;");return xml;}
}

用该类存组装的soap

package JRT.WebService.WS.Wsdl;import JRT.WebService.WS.XML.XmlNode;import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;/*** 用来组装Soap文档*/
public class WsdlXml {/*** soap头*/private String xmlheader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";/*** 命名空间*/private String xmlns = "";/*** 定义*/private XmlNode definitions = null;/*** 得到定义的soap的xml** @param tns* @param name* @return*/public XmlNode GetDefinitions(String tns, String name) {if (this.definitions == null) {this.definitions = new XmlNode("wsdl:definitions");this.definitions.PropertyList.put("name", name);this.definitions.PropertyList.put("targetNamespace", tns);this.definitions.PropertyList.put("xmlns:tns", tns);this.definitions.PropertyList.put("xmlns:soap", "http://schemas.xmlsoap.org/wsdl/soap/");this.definitions.PropertyList.put("xmlns:http", "http://schemas.microsoft.com/ws/06/2004/policy/http");this.definitions.PropertyList.put("xmlns:msc", "http://schemas.microsoft.com/ws/2005/12/wsdl/contract");this.definitions.PropertyList.put("xmlns:wsp", "http://schemas.xmlsoap.org/ws/2004/09/policy");this.definitions.PropertyList.put("xmlns:wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");this.definitions.PropertyList.put("xmlns:wsam", "http://www.w3.org/2007/05/addressing/metadata");this.definitions.PropertyList.put("xmlns:wsdl", "http://schemas.xmlsoap.org/wsdl/");this.definitions.PropertyList.put("xmlns:ser", "http://schemas.microsoft.com/2003/10/Serialization/");}return definitions;}/*** 类型*/private XmlNode types = null;/*** 得到类型** @return*/public XmlNode GetTypes() {if (this.types == null) {this.types = new XmlNode("wsdl:types");}return this.types;}/*** 得到schema** @param targetns* @param method* @return*/public XmlNode NewSchema(String targetns, Method method) {XmlNode schema = new XmlNode("xsd:schema");schema.PropertyList.put("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");schema.PropertyList.put("xmlns:ser", "http://schemas.microsoft.com/2003/10/Serialization/");schema.PropertyList.put("attributeFormDefault", "qualified");schema.PropertyList.put("elementFormDefault", "qualified");schema.PropertyList.put("targetNamespace", targetns);schema.PropertyList.put("xmlns:tns", targetns);XmlNode element = null;//形式参数XmlNode complextype = new XmlNode("xsd:complexType");XmlNode sequence = new XmlNode("xsd:sequence");Type[] types = method.getParameterTypes();Parameter[] paras = method.getParameters();for (int i = 0; i < types.length; i++) {Type type = types[i];String tname = type.getTypeName();if (tname.equals("java.lang.String")) {tname = "string";}//从注解获取参数名称JRT.WebService.WS.Annotation.WebParam paraanno = paras[i].getDeclaredAnnotation(JRT.WebService.WS.Annotation.WebParam.class);String paraname = "";if (paraanno != null) {paraname = paraanno.Name();}if (paraname.isEmpty()) {paraname = paras[i].getName();}element = new XmlNode("xsd:element");element.PropertyList.put("minOccurs", "1");element.PropertyList.put("maxOccurs", "1");element.PropertyList.put("nillable", "true");element.PropertyList.put("name", paraname);element.PropertyList.put("type", "xsd:" + tname);sequence.Insert(element);}complextype.Insert(sequence);element = new XmlNode("xsd:element");element.PropertyList.put("name", method.getName());element.Insert(complextype);schema.Insert(element);//返回参数Type rtype = method.getReturnType();element = new XmlNode("xsd:element");String tname = rtype.getTypeName();if (tname.equals("java.lang.String")) {tname = "string";}element.PropertyList.put("minOccurs", "1");element.PropertyList.put("maxOccurs", "1");element.PropertyList.put("nillable", "true");element.PropertyList.put("name", method.getName() + "Response");element.PropertyList.put("type", "xsd:" + tname);sequence = new XmlNode("xsd:sequence");sequence.Insert(element);complextype = new XmlNode("xsd:complexType");complextype.Insert(sequence);element = new XmlNode("xsd:element");element.PropertyList.put("name", method.getName() + "Response");element.Insert(complextype);schema.Insert(element);return schema;}/*** Msg** @param name* @param parttns* @return*/public XmlNode NewMessage(String name, String parttns) {XmlNode message = new XmlNode("wsdl:message");message.PropertyList.put("name", name);XmlNode part = new XmlNode("wsdl:part");part.PropertyList.put("name", "parameters");part.PropertyList.put("element", "tns:" + parttns);message.Insert(part);return message;}/*** 适配类型*/private XmlNode portType = null;/*** 得到适配类型** @param name* @return*/public XmlNode GetPortType(String name) {if (this.portType == null) {this.portType = new XmlNode("wsdl:portType");this.portType.PropertyList.put("name", name);}return this.portType;}/*** @param operName 方法名称* @return*/public XmlNode NewPortOperation(String operName) {XmlNode oper = new XmlNode("wsdl:operation");oper.PropertyList.put("name", operName);XmlNode input = new XmlNode("wsdl:input");input.PropertyList.put("name", operName);input.PropertyList.put("message", "tns:" + operName);XmlNode output = new XmlNode("wsdl:output");output.PropertyList.put("name", operName + "Response");output.PropertyList.put("message", "tns:" + operName + "Response");oper.Insert(input);oper.Insert(output);return oper;}/*** 绑定*/private XmlNode binding = null;/*** 得到绑定** @param name* @param type* @return*/public XmlNode GetBinding(String name, String type) {if (this.binding == null) {this.binding = new XmlNode("wsdl:binding");this.binding.PropertyList.put("name", name);this.binding.PropertyList.put("type", "tns:" + type);XmlNode wsdlsoap = new XmlNode("soap:binding");wsdlsoap.PropertyList.put("style", "document");wsdlsoap.PropertyList.put("transport", "http://schemas.xmlsoap.org/soap/http");this.binding.Insert(wsdlsoap);}return this.binding;}/*** @param operName 方法名称* @return*/public XmlNode NewBindingOperation(String operName) {XmlNode oper = new XmlNode("wsdl:operation");oper.PropertyList.put("name", operName);XmlNode soapact = new XmlNode("soap:operation");soapact.PropertyList.put("soapAction", operName);oper.Insert(soapact);XmlNode input = new XmlNode("wsdl:input");input.PropertyList.put("name", operName);input.PropertyList.put("message", "tns:" + operName);XmlNode sopabody = new XmlNode("soap:body");sopabody.PropertyList.put("use", "literal");input.Insert(sopabody);XmlNode output = new XmlNode("wsdl:output");output.PropertyList.put("name", operName + "Response");output.PropertyList.put("message", "tns:" + operName + "Response");output.Insert(sopabody);oper.Insert(input);oper.Insert(output);return oper;}/*** 得到服务*/private XmlNode service = null;/*** 得到服务节点** @param name* @return*/public XmlNode GetService(String name) {if (this.service == null) {this.service = new XmlNode("wsdl:service");this.service.PropertyList.put("name", name);}return this.service;}/*** 得到约定** @param name* @param binding* @param location* @return*/public XmlNode NewPort(String name, String binding, String location) {XmlNode port = new XmlNode("wsdl:port");port.PropertyList.put("name", name);port.PropertyList.put("binding", "tns:" + binding);XmlNode addr = new XmlNode("soap:address");addr.PropertyList.put("location", location);port.Insert(addr);return port;}/*** 序列化** @return*/public String Serialize() {String xml = this.xmlheader;xml = "";if (this.definitions != null) {xml += this.definitions.Serialize();}return xml;}
}

按类得到soap

package JRT.WebService.WS.Wsdl;import java.lang.reflect.Method;/*** 得到soap文档给调用者*/
public class WsdlXmlUtil {/*** 根据类对象和请求url生成wsdl描述文档,按URL得到类,按类的注解生成wsdl** @param cls* @param url* @return* @throws Exception*/public static String GetWsdlXml(Class<?> cls, String url) throws Exception {JRT.WebService.WS.Annotation.WebServer ws = (JRT.WebService.WS.Annotation.WebServer) cls.getAnnotation(JRT.WebService.WS.Annotation.WebServer.class);String serviceName = ws.ServiceName();JRT.WebService.WS.Wsdl.WsdlXml soapXml = new JRT.WebService.WS.Wsdl.WsdlXml();String targetName = "http://tempuri.org/";JRT.WebService.WS.XML.XmlNode definitions = soapXml.GetDefinitions(targetName, serviceName);JRT.WebService.WS.XML.XmlNode types = soapXml.GetTypes();JRT.WebService.WS.XML.XmlNode portType = soapXml.GetPortType(serviceName + "PortType");JRT.WebService.WS.XML.XmlNode binding = soapXml.GetBinding(serviceName + "Binding", portType.PropertyList.get("name"));JRT.WebService.WS.XML.XmlNode service = soapXml.GetService(serviceName);JRT.WebService.WS.XML.XmlNode port = soapXml.NewPort(serviceName + "Port", binding.PropertyList.get("name"), url);service.Insert(port);Method[] methods = cls.getDeclaredMethods();//遍历方法for (Method method : methods) {JRT.WebService.WS.Annotation.WebMethod wmd = method.getAnnotation(JRT.WebService.WS.Annotation.WebMethod.class);//没标注发布的方法退出if (wmd == null) {continue;}JRT.WebService.WS.XML.XmlNode schema = soapXml.NewSchema(targetName, method);types.Insert(schema);String mdname = method.getName();JRT.WebService.WS.XML.XmlNode porttypeoperation = soapXml.NewPortOperation(mdname);portType.Insert(porttypeoperation);JRT.WebService.WS.XML.XmlNode bindingoperation = soapXml.NewBindingOperation(mdname);binding.Insert(bindingoperation);}definitions.Insert(types);JRT.WebService.WS.XML.XmlNode message = null;for (Method method : methods) {JRT.WebService.WS.Annotation.WebMethod wmd = method.getAnnotation(JRT.WebService.WS.Annotation.WebMethod.class);if (wmd == null) {continue;}String mdname = method.getName();message = soapXml.NewMessage(mdname, mdname);definitions.Insert(message);message = soapXml.NewMessage(mdname + "Response", mdname + "Response");definitions.Insert(message);}definitions.Insert(portType);definitions.Insert(binding);definitions.Insert(service);String wsdl = soapXml.Serialize();return wsdl;}
}

WebBase对接获取soap文档和soap调用
在这里插入图片描述

实现demo

import JRT.WebService.Http.BaseWebServiceHandler;
import JRT.WebService.WS.Annotation.*;/*** 发布Webservice的示例,请求尾部以.asmx请求*/
@WebServer
public class WebServiceDemo extends BaseWebServiceHandler
{/*** 测试1* @param arg0 参数* @param arg1 参数* @return*/@WebMethodpublic String Test1(String arg0, String arg1){return "参数:" + arg0 + "," + arg1;}/*** 测试2* @param arg0 参数* @param arg1 参数* @param arg2 参数* @return*/@WebMethodpublic String Test2(String arg0,String arg1, String arg2){return "参数:" + arg0 + "," + arg1 + "," + arg2;}/*** 参数* @param arg0 参数* @param arg1 参数* @param arg2 参数* @return*/public String Test3(String arg0,String arg1, String arg2){return "参数:" + arg0 + "," + arg1 + "," + arg2;}
}

访问查询soap
在这里插入图片描述

用soapui测试
在这里插入图片描述

用我以前包的动态调用Webservice工具测试
在这里插入图片描述

用VS生成的代理类测试
在这里插入图片描述
能调到后台,但是取不到返回结果,比较奇怪,应该是实现不全的事,无所谓了,一般也不这么弄
在这里插入图片描述

这篇的代码能很好的体现Webservice的本质,服务器按Post的约定格式的xml执行方法后按约定格式的xml返回

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/227376.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nodejs微信小程序+python+PHP的微博网络舆情分析系统-计算机毕业设计推荐

&#xff08;4&#xff09;微博信息交流&#xff1a;在首页导航栏上我们会看到“微博信息交流”这一菜单&#xff0c;我们点击进入进去以后&#xff0c;会看到所有管理员在后台发布的交流信息&#xff1b; &#xff08;5&#xff09;新闻资讯&#xff1a;用户可以查看新闻资讯信…

【STM32入门】4.2对射红外传感器计次

1.接线方式 主要是编写传感器的驱动、配合OLED&#xff0c;每遮挡对射红外传感器&#xff0c;OLED屏幕的计数就加一。 2.驱动编写 首先新建.c文件和.h文件&#xff0c;命名为CountSensor 国际惯例&#xff0c;.c文件内要包含stm32.h头文件&#xff0c;然后编写 CountSensor_…

在Linux上安装配置Nginx高性能Web服务器

1 前言 Nginx是一个高性能的开源Web服务器&#xff0c;同时也可以作为反向代理服务器、负载均衡器、HTTP缓存以及作为一个邮件代理服务器。它以其出色的性能和灵活性而闻名&#xff0c;被广泛用于处理高流量的网站和应用程序。本文将介绍在Linux环境中安装Nginx的步骤&#xf…

new一个对象

1.自己直接调用 function Person(name, age) {this.name name;this.age age;}let a1 new Person("小明", 20);let a2 new Person("小菜", 25);console.log(a1); 打印的对象: 2.自己模拟一个 function Person(name, age) {this.name name;this.age a…

[Linux] LVS负载均衡群集——DR模式

一、 DR模式的特点 直接路由&#xff1a; 在LVS_DR模式下&#xff0c;负载均衡器不修改数据包的IP地址&#xff0c;只修改目的MAC地址。这使得数据包可以直接路由到后端实际服务器上&#xff0c;而不需要返回到负载均衡器。 高性能&#xff1a; 由于数据包在传输过程中不需要回…

本地运行大语言模型并可视化(Ollama+big-AGI方案)

目前有两种方案支持本地部署&#xff0c;两种方案都是基于llamacpp。其中 Ollama 目前只支持 Mac&#xff0c;LM Studio目前支持 Mac 和 Windows。 LM Studio&#xff1a;https://lmstudio.ai/ Ollama&#xff1a;https://ollama.ai/download 本文以 Ollama 为例 step1 首先下…

STM32_启动流程详解

目录标题 前言 启动流程概述复位中断函数详解SystemInit函数详解 __main函数详解 附录 stm32单片机的存储器映像中断向量表的映射 前言 最近在学习IAP远程OTA升级单片机固件程序&#xff0c;发现自己对单片机的启动流程还不是那么了解&#xff0c;就总结整理一下吧。 启动流程…

QT实现四则运算计算器

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);this->setMaximumSize(240,300);this->setMinimumSize(240,300);this->setWindowTitle("计算器&…

node.js mongoose简述

目录 官方文档 mongoose Schema Model Query document 关系 官方文档 Mongoose v8.0.3: Getting Started mongoose Mongoose 是一个 Node.js 环境下 MongoDB 的对象建模工具。它提供了一种在应用程序中与 MongoDB 数据库进行交互的方式&#xff0c;使得开发者能够使用…

NoSQL 数据库有哪些典型应用?

前面的内容介绍了数据库读写分离和分库分表相关知识&#xff0c;都是针对关系型数据库的&#xff0c;即通常说的 RDBMS。除了关系型数据库&#xff0c;NoSQL 在项目开发中也有着越来越重要的作用&#xff0c;与此同时&#xff0c;NoSQL 相关的内容也是面试的常客。今天我们一起…

函数难题:排列

给定一个整数 n&#xff0c;将数字 1∼n 排成一排&#xff0c;将会有很多种排列方法。 现在&#xff0c;请你按照字典序将所有的排列方法输出。 输入格式 共一行&#xff0c;包含一个整数 n。 输出格式 按字典序输出所有排列方案&#xff0c;每个方案占一行。 数据范围 …

【Linux】驱动

驱动 驱动程序过程 系统调用 用户空间 内核空间 添加驱动和调用驱动 驱动程序是如何调用设备硬件 驱动 在计算机领域&#xff0c;驱动&#xff08;Driver&#xff09;是一种软件&#xff0c;它充当硬件设备与操作系统之间的桥梁&#xff0c;允许它们进行通信和协同工作。驱动程…

[已解决】uniapp内置插件,editor富文本报错(附quill.min.js、image-resize.min.js文件)

在使用uni-app运行内置插件editor时&#xff0c;无法输入内容&#xff0c;控制台报错 原因&#xff1a;查看官网得知&#xff0c;需动态引入quill.min.js、image-resize.min.js文件 解决方法&#xff1a; 1.下载quill.min.js、image-resize.min.js到项目static/eidtor文件中 链…

云原生之深入解析Kubernetes Operator的最佳实践和最常见的问题分析

一、Kubernetes Operator 简介 Kubernetes Operator 是通过连接主 API 并 watch 时间的一组进程&#xff0c;一般会 watch 有限的资源类型。当相关 watch 的 event 触发的时候&#xff0c;operator 做出响应并执行具体的动作。这可能仅限于与主 API 交互&#xff0c;但通常会涉…

Linux下FFmepg使用

1.命令行录一段wav,PCM数据 ffmpeg -f alsa -i hw:0,0 xxx.wav//录制 ffplay out.wav//播放ffmpeg -f alsa -i hw:0,0 -ar 16000 -channels 1 -f s16le 1.pcm ffplay -ar 16000 -channels 1 -f s16le 1.pcm -ar freq 设置音频采样率 -ac channels 设置通道 缺省为1 2.将pcm…

Kubernetes实战(十四)-k8s高可用集群扩容master节点

1 单master集群和多master节点集群方案 1.1 单Master集群 k8s 集群是由一组运行 k8s 的节点组成的&#xff0c;节点可以是物理机、虚拟机或者云服务器。k8s 集群中的节点分为两种角色&#xff1a;master 和 node。 master 节点&#xff1a;master 节点负责控制和管理整个集群…

PyTorch官网demo解读——第一个神经网络(1)

神经网络如此神奇&#xff0c;feel the magic 今天分享一下学习PyTorch官网demo的心得&#xff0c;原来实现一个神经网络可以如此简单/简洁/高效&#xff0c;同时也感慨PyTorch如此强大。 这个demo的目的是训练一个识别手写数字的模型&#xff01; 先上源码&#xff1a; fr…

Composer 安装与使用

Composer 是 PHP 的一个依赖管理工具。我们可以在项目中声明所依赖的外部工具库&#xff0c;Composer 会帮你安装这些依赖的库文件&#xff0c;有了它&#xff0c;我们就可以很轻松的使用一个命令将其他人的优秀代码引用到我们的项目中来。 Composer 默认情况下不是全局安装&a…

vue3 element-plus 日期选择器 el-date-picker 汉化

vue3 项目中&#xff0c;element-plus 的日期选择器 el-date-picker 默认是英文版的&#xff0c;如下&#xff1a; 页面引入&#xff1a; //引入汉化语言包 import locale from "element-plus/lib/locale/lang/zh-cn" import { ElDatePicker, ElButton, ElConfigP…

西南科技大学数据库实验二(表数据插入、修改和删除)

一、实验目的 &#xff08;1&#xff09;学会用SQL语句对数据库进行插入、修改和删除数据操作 &#xff08;2&#xff09;掌握insert、update、delete命令实现对表数据插入、修改和删除等更新操作。 二、实验任务 创建数据库&#xff0c;并创建Employees表、Departments表和…