webservice 抓取客户端发送包_WebService接口实战(一)

WebService使用HTTP协议发送请求, 使用XML格式封装数据,本文讲述WebService接口开发与调用。
  1. 使用JAVA原生WS注解完成WebService接口服务端开发

创建WS接口与实现类

//接口@WebService(targetNamespace = "http://cxf.test", name = "WSTest")@XmlSeeAlso({ObjectFactory.class})@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)public interface WSTest {    @WebMethod(action = "http://cxf.test/ws")    public WSResponse test(        @WebParam(name = "WSHeader", targetNamespace = "http://cxf.test",header = true)        WSHeader WSHeader,        @WebParam(name = "WSRequest", targetNamespace = "http://cxf.test")        WSRequest WSRequest    );}//实现类@WebService(        serviceName = "WSTest",        portName = "WSTest",        targetNamespace = "http://cxf.test",        endpointInterface = "cxf.server.WSTest")public class WSTestImpl implements WSTest{    @Override  public WSResponse test(WSHeader WSHeader, WSRequest WSRequest) {    Logger.getLogger(this.getClass().getName()).info("请求已接收");    WSResponse response = new WSResponse();    response.setTestResponseBody(WSHeader.getTestHeader()+"==>"+WSRequest.getTestRequestBody());    return response;  }}

创建命名空间规范

@XmlRegistrypublic class ObjectFactory {    private final static QName _WSRequest_QNAME = new QName("http://cxf.test", "WSRequest");    private final static QName _WSResponse_QNAME = new QName("http://cxf.test", "WSResponse");    private final static QName _WSHeader_QNAME = new QName("http://cxf.test", "WSHeader");    public ObjectFactory() {    }        public WSRequest createWSRequest(){      return new WSRequest();    }        public WSResponse createWSResponse(){      return new WSResponse();    }        public WSHeader createWSHeader(){      return new WSHeader();    }    @XmlElementDecl(namespace = "http://cxf.test", name = "WSRequest")    public JAXBElementcreateWSRequest(WSRequest value) {        return new JAXBElement(_WSRequest_QNAME, WSRequest .class, null, value);    }    @XmlElementDecl(namespace = "http://cxf.test", name = "WSResponse")    public JAXBElementcreateWSResponse(WSResponse value) {        return new JAXBElement(_WSResponse_QNAME, WSResponse .class, null, value);    }    @XmlElementDecl(namespace = "http://cxf.test", name = "WSHeader")    public JAXBElementcreateWSHeader(WSHeader value) {        return new JAXBElement(_WSHeader_QNAME, WSHeader.class, null, value);    }}

创建请求头类、请求体类、响应类,与接口启动类

public class WSServer {  public static void main(String[] args) {    Object implementor = new WSTestImpl();        String address = "http://127.0.0.1:55555/cxf/test";        Endpoint.publish(address, implementor);        Logger.getLogger(Thread.currentThread().getName()).info("启动成功");  }}

使用apache的CXF组件生成客户端代码,进行调用

//CXF生成代码的命令wsdl2java -encoding utf8 -p cxf.client -d C:\work\STS\cxf\src -client http://127.0.0.1:55555/cxf/test?wsdl#-encoding utf8:设置文件编码#-p cxf.client:设置包名#-d C:\work\STS\cxf\src:设置生成路径#-client:生成客户端代码//客户端代码如下:public final class WSTest_WSTest_Client {    private static final QName SERVICE_NAME = new QName("http://cxf.test", "WSTest");    private WSTest_WSTest_Client() {    }    public static void main(String args[]) throws java.lang.Exception {        URL wsdlURL = WSTest_Service.WSDL_LOCATION;        if (args.length > 0 && args[0] != null && !"".equals(args[0])) {            File wsdlFile = new File(args[0]);            try {                if (wsdlFile.exists()) {                    wsdlURL = wsdlFile.toURI().toURL();                } else {                    wsdlURL = new URL(args[0]);                }            } catch (MalformedURLException e) {                e.printStackTrace();            }        }        WSTest_Service ss = new WSTest_Service(wsdlURL, SERVICE_NAME);        WSTest port = ss.getWSTest();        {        System.out.println("Invoking test...");        cxf.client.WSHeader _test_wsHeader = null;        cxf.client.WSRequest _test_wsRequest = null;        cxf.client.WSResponse _test__return = port.test(_test_wsHeader, _test_wsRequest);        System.out.println("test.result=" + _test__return);        }        System.exit(0);    }}

使用SoapUI+postman生成OkHttp调用代码,并通过JAVA对象构建请求报文与解析响应报文

很多时候由于服务端并没有按照SOAP协议开发,导致CXF生成的客户端代码并不能实现调用,因此需要使用SoapUI工具根据wsdl文件生成调用示例,然后使用postman(下文以快递侠命名)工具把SoapUI的调用示例转换为快递侠的调用示例,最后生成OkHttp调用代码。一、将WSDL导入 SoapUI    

c0a66513a799edd3d4fb45796e9d2601.png

69e9e1dc29170d885a2a32f029b7f697.png

二、转换为快递侠调用示例

fa988567477577c51f4901e189f70f48.png

2500f8abefa40406abc6d861b5b6f142.png

三、生成OkHttp调用代码

dc24968781524169238cf308186c65ac.png

四、实际代码

//调用示例public class Test {  public static void main(String[] args) {    //1、根据请求报文的格式与命名空间构建请求报文的类,并生成请求报文    String json = "";    try (StringWriter writer = new StringWriter()) {      JAXBContext context = JAXBContext.newInstance(RequestEnvelope.class);      Marshaller marshal = context.createMarshaller();      marshal.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);      marshal.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");      marshal.setProperty(Marshaller.JAXB_FRAGMENT, false);      marshal.setProperty("jaxb.encoding", "utf-8");      RequestEnvelope root = new RequestEnvelope();      RequestBody body = new RequestBody();      WSRequest request = new WSRequest();      request.setTestRequestBody("啊");      body.setWSRequest(request);      RequestHeader header = new RequestHeader();      WSHeader wsHeader = new WSHeader();      wsHeader.setTestHeader("我是java");      header.setWSHeader(wsHeader);      root.setHeader(header);      root.setBody(body);      marshal.marshal(root,writer);      json = new String(writer.getBuffer());    } catch (Exception e) {      e.printStackTrace();    }    System.out.println(json);    //2、使用快递侠生成的OkHttp代码调用WS接口    OkHttpClient client = new OkHttpClient().newBuilder().build();    MediaType mediaType = MediaType.parse("text/xml");    okhttp3.RequestBody body = okhttp3.RequestBody.create(mediaType,json);    Request request = new Request.Builder()        .url("http://127.0.0.1:55555/cxf/test")        .method("POST", body)        .addHeader("Content-Type", "text/xml")        .build();    //3、拿到返回值后,继续根据响应报文的格式与命名空间,解析响应报文的类,拿到响应对象    try (Response response = client.newCall(request).execute()) {      String xml = response.body().string();      SAXParserFactory spf = SAXParserFactory.newInstance();      spf.setFeature("http://xml.org/sax/features/external-general-entities", false);      spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);      spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);      spf.setNamespaceAware(true);      JAXBContext context = JAXBContext.newInstance(ResponseEnvelope.class);      Unmarshaller unmarshaller = context.createUnmarshaller();      Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(new StringReader(xml)));      ResponseEnvelope root = (ResponseEnvelope) unmarshaller.unmarshal(xmlSource);      System.out.println(root.getBody().getTestResponse().getTestResponseBody());    } catch (Exception e) {      e.printStackTrace();    }  }}//OkHttp的maven依赖      com.squareup.okhttp3      okhttp      3.11.0

其他文章推荐:

Centos 7 安装指定版本的docker(如19.03.9)

容器级别redis问题探讨

巧用VPN打通容器云网络

本文中用到的文件,百度网盘下载地址如下:

链接:https://pan.baidu.com/s/1VtBlq7Pge4QB50gi7Zs0Ig

提取码:s7fd

266484632ca7c87a9536432e5443b153.png

关注此微信公众号,获得每日程序员干货推送

50d5fbb57e41a01bb88aa283a01b487c.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值