2025-10-06 17:29:34 新游体验

简介该篇为上一篇的延伸,上一篇知识简单介绍了WebService 的使用,该篇会对代码中模块及功能进行详细介绍,以作对WebService 进一步的理解。

一、Pom文件配置该Pom文件中包含了Provider的配置和Consumer的配置,请自行复制所需。

代码语言:javascript代码运行次数:0运行复制

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.4.0

com.rh

ws_test

0.0.1-SNAPSHOT

ws_test

Demo project for Spring Boot

1.8

org.springframework.boot

spring-boot-starter

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-web-services

org.apache.cxf

cxf-spring-boot-starter-jaxws

3.2.1

org.apache.cxf

cxf-rt-transports-http

3.2.1

org.hibernate

hibernate-validator

6.0.18.Final

org.apache.axis

axis

1.4

javax.xml

jaxrpc

1.1

commons-logging

commons-logging

1.0.4

commons-discovery

commons-discovery

0.5

wsdl4j

wsdl4j

1.6.3

org.springframework.boot

spring-boot-maven-plugin

二、服务端代码ServerServiceDemo接口代码:

代码语言:javascript代码运行次数:0运行复制package com.rh.ws_test;

import javax.jws.WebMethod;

import javax.jws.WebParam;

import javax.jws.WebService;

@WebService(name = "ServerServiceDemo", targetNamespace = "http://server.webservice.example.com")

public interface ServerServiceDemo {

@WebMethod

String emrService(@WebParam String data);

}WebService涉及到的有这些 "四解三类 ", 即四个注解,三个类 @WebMethod, @WebService,@WebResult,@WebParam,SpringBus,Endpoint,EndpointImpl

一般我们都会写一个接口,然后再写一个实现接口的实现类,但是这不是强制性的

@WebService 注解表明是一个webservice服务。name:对外发布的服务名, 对应于,targetNamespace:命名空间,一般是接口的包名倒序, 实现类与接口类的这个配置一定要一致这种错误Exception in thread “main” org.apache.cxf.common.i18n.UncheckedException: No operation was found with the name xxxx 对应于argetNamespace=“http://server.webservice.example.com”, endpointInterface:服务接口全路径(如果是没有接口,直接写实现类的,该属性不用配置), 指定做SEI(Service EndPoint Interface)服务端点接口, serviceName:对应于, portName:对应于

@WebMethod表示暴露的服务方法, 这里有接口ServerServiceDemo存在,在接口方法已加上@WebMethod, 所以在实现类中不用再加上,否则就要加上 operationName: 接口的方法名, action: 没发现又什么用处, exclude: 默认是false, 用于阻止将某一继承方法公开为web服务

@WebResult表示方法的返回值, name:返回值的名称, partName: , targetNamespace:,

header: 默认是false, 是否将参数放到头信息中,用于保护参数,默认在body中

@WebParam name:接口的参数, partName:, targetNamespace:

header: 默认是false, 是否将参数放到头信息中,用于保护参数,默认在body中, model:WebParam.Mode.IN/OUT/INOUT

ServerServiceDemoImpl接口实现类代码:

代码语言:javascript代码运行次数:0运行复制package com.rh.ws_test;

import org.springframework.stereotype.Component;

import javax.jws.WebParam;

import javax.jws.WebService;

@Component

@WebService(name = "ServerServiceDemo", targetNamespace = "http://server.webservice.example.com",

endpointInterface = "com.rh.ws_test.ServerServiceDemo")

public class ServerServiceDemoImpl implements ServerServiceDemo{

@Override

public String emrService(@WebParam String data) {

if(null == data || "".equals(data.trim())){

return "传入的参数为空";

}

return "调用成功";

}

}WebServiceDemoTwo 代码:

代码语言:javascript代码运行次数:0运行复制package com.test.springboot.service;

import javax.jws.WebMethod;

import javax.jws.WebParam;

import javax.jws.WebService;

@WebService(name = "WebServiceDemoTwo", targetNamespace = "http://server.webservice.example.com")

public interface WebServiceDemoTwo {

@WebMethod

String emrServiceThree(@WebParam String data);

@WebMethod

String emrServiceFour(@WebParam String data);

}WebServiceDemoTwoImpl 代码

代码语言:javascript代码运行次数:0运行复制package com.test.springboot.service.impl;

import com.test.springboot.service.WebServiceDemoTwo;

import org.springframework.stereotype.Component;

import javax.jws.WebService;

@Component

@WebService(name = "WebServiceDemoTwo", targetNamespace = "http://server.webservice.example.com",

endpointInterface = "com.test.springboot.service.WebServiceDemoTwo")

public class WebServiceDemoTwoImpl implements WebServiceDemoTwo {

@Override

public String emrServiceThree(String data) {

return null;

}

@Override

public String emrServiceFour(String data) {

return null;

}

}Apache CXF 核心架构是以BUS为核心,整合其他组件。Bus是CXF的主干, 为共享资源提供一个可配置的场所,作用类似于Spring的ApplicationContext,这些共享资源包括WSDl管理器、绑定工厂等。通过对BUS进行扩展,可以方便地容纳自己的资源,或者替换现有的资源。默认Bus实现基于Spring架构,通过依赖注入,在运行时将组件串联起来。BusFactory负责Bus的创建。默认的BusFactory是SpringBusFactory,对应于默认的Bus实现。在构造过程中,SpringBusFactory会搜索META-INF/cxf(包含在 CXF 的jar中)下的所有bean配置文件。根据这些配置文件构建一个ApplicationContext。开发者也可以提供自己的配置文件来定制Bus。

WebServiceConfig配置代码:

代码语言:javascript代码运行次数:0运行复制package com.test.springboot.config;

import com.test.springboot.service.WebServiceDemo;

import com.test.springboot.service.WebServiceDemoTwo;

import org.apache.cxf.Bus;

import org.apache.cxf.bus.spring.SpringBus;

import org.apache.cxf.jaxws.EndpointImpl;

import org.apache.cxf.transport.servlet.CXFServlet;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.boot.web.servlet.ServletRegistrationBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import javax.xml.ws.Endpoint;

@Configuration

public class WebServiceConfig {

@Autowired

private WebServiceDemo serverServiceDemo;

@Autowired

private WebServiceDemoTwo serverServiceDemoTwo;

@Bean(name = Bus.DEFAULT_BUS_ID)

public SpringBus springBus() {

return new SpringBus();

}

/**

* 此方法作用是改变项目中服务名的前缀名,此处127.0.0.1或者localhost不能访问时,请使用ipconfig查看本机ip来访问

* 此方法被注释后, 即不改变前缀名(默认是services), wsdl访问地址为 http://127.0.0.1:8080/services/ws/api?wsdl

* 去掉注释后wsdl访问地址为:http://127.0.0.1:8080/soap/ws/api?wsdl

* http://127.0.0.1:8080/soap/列出服务列表 或 http://127.0.0.1:8080/soap/ws/api?wsdl 查看实际的服务

* 新建Servlet记得需要在启动类添加注解:@ServletComponentScan

*

* 如果启动时出现错误:not loaded because DispatcherServlet Registration found non dispatcher servlet dispatcherServlet

* 可能是springboot与cfx版本不兼容。

* 同时在spring boot2.0.6之后的版本与xcf集成,不需要在定义以下方法,直接在application.properties配置文件中添加:

* cxf.path=/service(默认是services)

*/

// @Bean

// public ServletRegistrationBean dispatcherServlet() {

// return new ServletRegistrationBean(new CXFServlet(), "/aaa/*");

// }

@Bean

public ServletRegistrationBean newServlet() {

return new ServletRegistrationBean(new CXFServlet(), "/aaa/*");

}

@Bean

@Qualifier("sBEASEASImportClaimChannelServiceInfoSrv")

public Endpoint endpoint() {

EndpointImpl endpoint = new EndpointImpl(springBus(), serverServiceDemo);

endpoint.publish("/bbb");

return endpoint;

}

@Bean

@Qualifier("sBEASEASImportClaimChannelServiceInfoSrx")

public Endpoint endpointTwo() {

EndpointImpl endpoint = new EndpointImpl(springBus(), serverServiceDemoTwo);

endpoint.publish("/ccc");

return endpoint;

}

}启动项目后访问: http://localhost:8083/services/

三、客户端编码WebServiceTest 代码:

代码语言:javascript代码运行次数:0运行复制package com.test.springboot.webservice;

import org.apache.cxf.endpoint.Client;

import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

public class WebServiceTest {

public static void main(String[] args) {

String url1 = "http://localhost:8080/test/bbb?wsdl";

String url2 = "http://localhost:8080/test/ccc?wsdl";

// client2(url2);

client1(url1);

}

// 创建动态客户端

public static void client1(String url) {

JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();

Client client = dcf.createClient(url);

Object[] objects = new Object[0];

try {

// invoke("方法名",参数1,参数2,参数3....);

objects = client.invoke("emrService", "zhangsan123456");

System.out.println("emrService返回数据:" + objects[0]);

client.destroy();

} catch (Exception e) {

e.printStackTrace();

}

}

// 创建动态客户端

public static void client2(String url) {

JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();

Client client = dcf.createClient(url);

Object[] objects = new Object[0];

try {

// invoke("方法名",参数1,参数2,参数3....);

objects = client.invoke("emrServiceThree", "zhangsan789");

System.out.println("emrServiceThree返回数据:" + objects[0]);

client.destroy();

} catch (Exception e) {

e.printStackTrace();

}

}

}四、客户端编码(axis方式)代码语言:javascript代码运行次数:0运行复制package com.rh.ws_test.client;

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

import org.apache.axis.encoding.XMLType;

import javax.xml.namespace.QName;

import javax.xml.rpc.ParameterMode;

import java.net.URL;

public class TestSoap {

public static void main(String[] args) throws Exception {

//一般如果没有注解targetNamespace的话,默认生成的就是接口这个文件的路径名

// String nameSpaceURI = "http://service.cm.com";

String nameSpaceURI = "http://server.webservice.example.com";

// String publishUrl = "http://localhost:8087/services/ServiceMonitor?wsdl";

String publishUrl = "http://localhost:8083/services/ws/api?wsdl";

Service service = new Service();

Call call = (Call) service.createCall();

call.setTargetEndpointAddress(new URL(publishUrl));

//指定接口路径,要调用的方法名

// call.setOperationName(new QName(nameSpaceURI, "monitor"));

call.setOperationName(new QName(nameSpaceURI, "emrService"));

//如果没用@WebParam(name="name")来表明参数名,则方法的入参是啥,这边就必须传一样的参数名才行。不然报错。

call.addParameter("arg0", XMLType.XSD_STRING, ParameterMode.IN);

// call.addParameter("age", XMLType.XSD_INT, ParameterMode.IN);

call.setReturnType(XMLType.XSD_STRING);

String name = "zhanglifeng";

int age = 18;

Object[] obj = new Object[] { name};

String result = (String) call.invoke(obj);

System.out.println(result);

}

}注意:springboot开发webservice和axis组件开发webservice用法上有点区别

小结这里的访问路径的关系梳理:http://localhost:8080/test/ccc?wsdl

客户端调用时,确定访问路径后,我们调用时,要指定具体的方法名,可以直接在页面上看到。这样,就可以向具体的方法发起请求了。

参考地址:https://blog.csdn.net/Brave_heart4pzj/article/details/110916127

https://blog.csdn.net/Brave_heart4pzj/article/details/126709107