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-8
        response.setContentType("text/xml");   //设置响应mime类型为text/xml
        //获取请求的url,wsdl问了里面需要使用该url
        String 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/xml
        response.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:Envelope
            Element root = document.getDocumentElement();
            //获取根节点名称
            String rootname = root.getNodeName();
            //节点名称":"号的前缀根据不同的请求会有差异,所以这里取出来,响应的soap文档的节点前缀也是用这个
            String nodename_pre = "";
            if (rootname.contains(":")) {
                nodename_pre = rootname.split(":")[0];
            }
            // 获取soap的body
            Node body = null;   //soap body
            Node 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);
                    }
                }
                //没有配到对应参数默认String
                if (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和body
            if (body != null) {
                root.removeChild(body);
            }
            if (header != null) {
                root.removeChild(header);
            }
            //构造新的header和body
            //构建header
            Node 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);
        } 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("&", "&");
        xml = xml.replace("<", "<");
        xml = xml.replace(">", ">");
        xml = xml.replace("'", "'");
        xml = xml.replace("\"", """);
        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 = "";

    /**
     * 命名空间
     */
    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调用
JRT实现原生Webservice发布_第1张图片

实现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
     */
    @WebMethod
    public String Test1(String arg0, String arg1)
    {
        return "参数:" + arg0 + "," + arg1;
    }

    /**
     * 测试2
     * @param arg0 参数
     * @param arg1 参数
     * @param arg2 参数
     * @return
     */
    @WebMethod
    public 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
JRT实现原生Webservice发布_第2张图片

用soapui测试
JRT实现原生Webservice发布_第3张图片

用我以前包的动态调用Webservice工具测试
JRT实现原生Webservice发布_第4张图片

用VS生成的代理类测试
JRT实现原生Webservice发布_第5张图片
能调到后台,但是取不到返回结果,比较奇怪,应该是实现不全的事,无所谓了,一般也不这么弄
JRT实现原生Webservice发布_第6张图片

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

你可能感兴趣的:(java)