背景:
公司新项目,后端服务需要调用一个第三方的基础服务,提供一些基础数据,第三方基础服务使用的是webservice,以前没用过,所以速成了一下,达到能调用webservice服务的状态,在这里提供一个关于webservice服务发布及调用的基础入门速成博客。
1.项目整体结构
项目分为ws服务发布与调用ws服务客户端,其中持久层框架使用mybatis-plus,ws就一个方法为添加用户。其中用户模型为
@Data
public class People {
/**
* 主键id
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 名字
*/
private String name;
/**
* 住址
*/
private String address;
/**
* 记录创建时间
*/
private Long createTime;
/**
* 记录更新时间
*/
private Long updateTime;
}
2.WebService注释
具体的注释可参照https://blog.csdn.net/helongzhong/article/details/52636296,这里我列出了本编博客需要的注释。
@WebService
1、serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service。缺省值为 Java 类的简单名称 + Service。(字符串)
2、endpointInterface: 服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口
3、name:此属性的值包含XML Web Service的名称。在默认情况下,该值是实现XML Web Service的类的名称,wsdl:portType 的名称。缺省值为 Java 类或接口的非限定名称。(字符串
4、portName: wsdl:portName。缺省值为 WebService.name+Port。
5、targetNamespace:指定你想要的名称空间,认是使用接口实现类的包名的反缀
6、wsdlLocation:指定用于定义 Web Service 的 WSDL 文档的 Web 地址。Web 地址可以是相对路径或绝对路径。(字符串)
注意:实现类上可以不添加Webservice注解
@WebMethod
注释表示作为一项 Web Service 操作的方法,将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,或者应用于 JavaBeans 端点的服务器端点实现类。
要点:
仅支持在使用 @WebService 注释来注释的类上使用 @WebMethod 注释
1、operationName:指定与此方法相匹配的wsdl:operation 的名称。缺省值为 Java 方法的名称。(字符串)
2、action:定义此操作的行为。对于 SOAP 绑定,此值将确定 SOAPAction 头的值。缺省值为 Java 方法的名称。(字符串)
3、exclude:指定是否从 Web Service 中排除某一方法。缺省值为 false。(布尔值)
3.发布webservice服务
@WebService(endpointInterface = "com.honorzhang.web.service.server.service.PeopleService",
targetNamespace = "http://service.people.com/wsdl", serviceName = "PeopleServiceImpl", portName = "dao")
@Slf4j
public class PeopleServiceImpl implements PeopleService {
@Override
public People insertPeople(People people) {
PeopleMapper peopleMapper = SpringUtil.getBean(PeopleMapper.class);
try {
boolean flag = peopleMapper.insert(people) > 0;
if (flag) {
return peopleMapper.selectById(people.getId());
} else {
return new People();
}
} catch (Exception e) {
log.error("添加人员出错", e);
return new People();
}
}
}
其中有一个需要注意的地方在mapper的注入方式,使用传统的@AutoWired注入mapper层是不能使用的,这个和webservice注释有关系,我使用了一个工具类来实现mapper的注入。
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
public SpringUtil() {
}
@Override
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
if (applicationContext == null) {
applicationContext = arg0;
}
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static void setAppCtx(ApplicationContext webAppCtx) {
if (webAppCtx != null) {
applicationContext = webAppCtx;
}
}
/**
* 拿到ApplicationContext对象实例后就可以手动获取Bean的注入实例对象
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
public static <T> T getBean(String name, Class<T> clazz) throws ClassNotFoundException {
return getApplicationContext().getBean(name, clazz);
}
public static final Object getBean(String beanName) {
return getApplicationContext().getBean(beanName);
}
public static final Object getBean(String beanName, String className) throws ClassNotFoundException {
Class clz = Class.forName(className);
return getApplicationContext().getBean(beanName, clz.getClass());
}
public static boolean containsBean(String name) {
return getApplicationContext().containsBean(name);
}
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return getApplicationContext().isSingleton(name);
}
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return getApplicationContext().getType(name);
}
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
return getApplicationContext().getAliases(name);
}
}
在run函数中发布服务
@SpringBootApplication
public class WebServiceServer {
public static void main(String[] args) {
SpringApplication.run(WebServiceServer.class, args);
System.out.println("启动并发布webservice远程服务");
Endpoint.publish("http://127.0.0.1:8099/PeopleServiceImpl/dao?wsdl", new PeopleServiceImpl());
System.out.println("启动并发布webservice远程服务,服务发布成功....");
}
}
服务发布调用wsdl地址,得到对应的xml文件
4.ws服务的调用
webservice的服务调用就是像调用本地的方法一样简单,所以第一步,需要通过java安装目录下的一个工具wsdl2java把对应的ws服务生成java代码,具体的用法可以查询,这里我直接贴出我的结果。
编写调用服务的代码,可以看到,和调用本地的方法没有任何区别
import com.honorzhang.web.service.client.service.ClientService;
import com.honorzhang.web.service.client.ws.People;
import com.honorzhang.web.service.client.ws.PeopleService;
import com.honorzhang.web.service.client.ws.PeopleServiceImpl;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
/**
* @program: webservice-example
* @author: zgr
* @create: 2020-09-16 16:24
**/
@Service
public class ClientServiceImpl implements ClientService {
private PeopleService wsClient;
@PostConstruct
public void init() {
PeopleServiceImpl peopleService = new PeopleServiceImpl();
wsClient = peopleService.getDao();
}
@Override
public People insertPeople(People people) {
return wsClient.insertPeople(people);
}
}
5.postman实验结果
6.总结
本篇博客简单的实现了webservice服务的发布与调用,最后通过postman接口测试工具进行了测试。有很多细节的地方本博客没有介绍,但有一定基础的人肯定能明白。整个项目的github地址为https://github.com/airhonor/WebService。