Spring Boot 开发 WebService 服务
https://www.cnblogs.com/fishpro/p/spring-boot-study-webservice.html
验证通过
WebService 虽然现在大部分互联网企业不太提倡使用,但在以第三方接口为主导的市场,对方来什么接口你还得用什么接口,不可能把接口重写了。例如大部分传统的大型企业都在用 WebService,并且版本还不一样。
本章主要介绍在 Spring Boot 下有常用的整合 WebService 的方法并给出示例。为了方便测试,本章有两个独立的项目
- 用户的获取、增加、更新、删除 webservice 服务
- 用于调用 1 的webservice 服务的客户端
1 新建 Spring Boot Maven 示例工程项目
注意:是用来 IDEA 开发工具
- File > New > Project,如下图选择
Spring Initializr
然后点击 【Next】下一步 - 填写
GroupId
(包名)、Artifact
(项目名) 即可。点击 下一步
groupId=com.fishpro
artifactId=webservice - 选择依赖
Spring Web Starter
前面打钩。 - 项目名设置为
spring-boot-study-webservice
.
2 引入依赖 Pom.xml
这里主要是引入 org.apache.cxf
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf-spring-boot-starter-jaxws -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3 编写一个用户获取、新增、修改、删除服务
3.1 传输对象 UserDto
通常我们把展示层与服务层之间传输的对象使用Dto后缀来标识。
UserDto(路径 src/main/java/com/fishpro/webservice/dto/UserDto.java)
/**
* 用户传输实体对象 通常我们把展示层与服务层之间传输的对象使用Dto后缀来标识。
* */
public class UserDto {
private Integer userId;//用户id
private String userName;//用户名称
private String password;//用户密码
private Integer sex;//用户性别 0女 1男
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
}
3.2 用户服务类
UserService 接口类(路径 src/main/java/com/fishpro/webservice/service/UserService.java)
/**
* 用户服务类 必须使用 @WebService
* */
@WebService(targetNamespace = WsConst.NAMESPACE_URI ,name = "userPortType")
public interface UserService {
/**
* 根据用户id获取用户信息
* */
@WebMethod(operationName="getUserById")
UserDto get(@WebParam(name = "id") String id);
/**
* 获取全部用户信息
* */
@WebMethod(operationName="getUsers")
List<UserDto> list();
/**
* 获取用户数
* */
@WebMethod(operationName="count")
int count(@);
/**
* 新增用户
* */
@WebMethod(operationName="save")
int save(@WebParam(name = "user") UserDto user);
/**
* 更新用户
* */
@WebMethod(operationName="update")
int update(@WebParam(name = "user") UserDto user);
/**
* 删除用户
* */
@WebMethod(operationName="remove")
int remove(@WebParam(name = "id") Integer id);
/**
* 批量删除用户
* */
@WebMethod(operationName="batchRemove")
int batchRemove(@WebParam(name = "ids") Integer[] ids);
}
UserServiceImpl 接口类(路径 src/main/java/com/fishpro/webservice/service/UserServiceImpl.java)
@WebService(
targetNamespace = WsConst.NAMESPACE_URI, //wsdl命名空间
name = "userPortType", //portType名称 客户端生成代码时 为接口名称
serviceName = "userService", //服务name名称
portName = "userPortName", //port名称
endpointInterface = "com.fishpro.webservice.service.UserService")//指定发布webservcie的接口类,此类也需要接入@WebService注解
public class UserServiceImpl implements UserService {
@Override
public UserDto get(String id){
if(null==id){
return null;
}
List<UserDto> list= getData();
UserDto UserDto=null;
for (UserDto user:list
) {
if(id.equals(user.getUserId().toString())){
UserDto=user;
break;
}
}
return UserDto;
}
@Override
public List<UserDto> list(){
List<UserDto> list=new ArrayList<>();
list=getData();
return list;
}
@Override
public int count(){
return getData().size();
}
@Override
public int save(UserDto user){
return 1;
}
@Override
public int update(UserDto user){
return 1;
}
@Override
public int remove(Integer id){
return 1;
}
@Override
public int batchRemove(Integer[] ids){
return 1;
}
/**
* 模拟一组数据
* */
private List<UserDto> getData(){
List<UserDto> list=new ArrayList<>();
UserDto UserDto=new UserDto();
UserDto.setUserId(1);
UserDto.setUserName("admin");
list.add(UserDto);
UserDto=new UserDto();
UserDto.setUserId(2);
UserDto.setUserName("heike");
list.add(UserDto);
UserDto=new UserDto();
UserDto.setUserId(3);
UserDto.setUserName("tom");
list.add(UserDto);
UserDto=new UserDto();
UserDto.setUserId(4);
UserDto.setUserName("mac");
list.add(UserDto);
return list;
}
}
4 服务发布
编写 CxfWebServiceConfig(路径 src/main/java/com/fishpro/webservice/config/CxfWebServiceConfig.java)
import com.fishpro.websevice.service.UserService;
import com.fishpro.websevice.service.impl.UserServiceImpl;
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.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Endpoint;
@Configuration
public class CxfWebServiceConfig {
/**
*
* */
@Bean("cxfServletRegistration")
public ServletRegistrationBean dispatcherServlet(){
return new ServletRegistrationBean(new CXFServlet(),"/ws/*");
}
/**
* 申明业务处理类 当然也可以直接 在实现类上标注 @Service
*/
@Bean
public UserService userService() {
return new UserServiceImpl();
}
/*
* 非必要项
*/
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
SpringBus springBus = new SpringBus();
return springBus;
}
/*
* 发布endpoint
*/
@Bean
public Endpoint endpoint( ) {
EndpointImpl endpoint = new EndpointImpl(springBus(), userService());
endpoint.publish("/user");//发布地址
return endpoint;
}
}
打开浏览器输入 http://localhost:8080/ws/user?wsdl 可以见到发布的效果
如何使用 Spring Boot 调用 WebService ,请阅读 Spring Boot 使用 CXF 调用 WebService 服务
5 问题
- cxf 的服务方法中,是不能使用java.util.Map作为参数的,因为本身不支持转换
cxf对很多复杂类型支持并不友好,建议参数能使用简单的类型,就使用简单的类型
spring boot 下开发webservice接口
1、引入pom依赖
-
<!-- 引入CXF jar包 -->
-
<dependency>
-
<groupId>org.apache.cxf</groupId>
-
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
-
<version>3.3.3</version>
-
</dependency>
2、编写webservice服务端
2.1 新建接口,并添加targetNamespace,targetNamespace是接口所在包的倒序,如果不添加,在动态调用接口的时候,会报错误信息。
-
-
import javax.jws.WebParam;
-
import javax.jws.WebService;
-
-
// ~ File Information
-
/**
-
* @author zxy
-
* @date 2019年9月23日 下午2:45:10
-
* 类说明:定义接口,targetNamespace是当前所在包的倒序。
-
*/
-
@WebService(targetNamespace="http://webservice.common.bmSystem.com")
-
public interface IHelloWord {
-
-
// ~ Methods
-
public String say(@WebParam(name="helloName") String helloName);
-
-
}
2.2 新建接口实现类,targetNamespace与实现接口保持一致,endpointInterface为接口所在包的全路径。
-
-
import javax.jws.WebService;
-
-
import org.springframework.stereotype.Component;
-
-
import com.bmSystem.common.webservice.IHelloWord;
-
-
// ~ File Information
-
/**
-
* @author zxy
-
* @date 2019年9月23日 下午2:46:18
-
* 类说明:接口实现类,targetNamespace是当前所在包的倒序。
-
*/
-
-
-
-
public class HelloWordImpl implements IHelloWord{
-
-
-
public String say(String str) {
-
System.out.println("进入接口...");
-
return str;
-
}
-
-
}
3、发布webservice接口
-
package com.bmSystem.common.sys.config.webservice;
-
-
import javax.xml.ws.Endpoint;
-
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.boot.web.servlet.ServletRegistrationBean;
-
import org.springframework.context.annotation.Bean;
-
import org.springframework.context.annotation.Configuration;
-
-
import com.bmSystem.common.webservice.impl.HelloWordImpl;
-
-
// ~ File Information
-
/**
-
* @author zxy
-
* @date 2019年9月23日 下午3:12:00
-
* 类说明:webservice发布,默认访问地址为:localhost:8080/services/helloWord?wsdl
-
*
-
*/
-
-
public class WebServiceConfig {
-
-
// ~ Fields
-
-
private HelloWordImpl helloWord;//接口实现类
-
-
// ~ Methods
-
-
/**
-
* 此方法作用是改变项目中服务名的前缀名,此处127.0.0.1或者localhost不能访问时,请使用ipconfig查看本机ip来访问
-
* 此方法被注释后:wsdl访问地址为http://127.0.0.1:8080/services/user?wsdl
-
* 去掉注释后:wsdl访问地址为:http://127.0.0.1:8080/soap/user?wsdl
-
* @return
-
*/
-
/*
-
* @SuppressWarnings("all")
-
*
-
* @Bean public ServletRegistrationBean dispatcherServlet() { return new
-
* ServletRegistrationBean(new CXFServlet(), "/soap/*"); }
-
*/
-
-
-
public SpringBus springBus() {
-
return new SpringBus();
-
}
-
-
-
public Endpoint endpoint() {
-
EndpointImpl endpoint=new EndpointImpl(springBus(), helloWord);
-
endpoint.publish("/helloWord");//访问地址
-
return endpoint;
-
}
-
-
}
4、开发webservice客户端调用,这里采用的是动态调用方式(推荐)
-
-
import java.util.HashMap;
-
import java.util.Map;
-
-
import org.apache.cxf.endpoint.Client;
-
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
-
-
import com.google.gson.Gson;
-
-
/**
-
* @author zxy
-
* @date 2020年6月5日 上午9:05:06
-
* @Description : 动态调用webservice接口
-
*/
-
public class TestWebservice {
-
-
public static void main(String[] args) {
-
// 创建动态客户端
-
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
-
Client client = dcf.createClient("http://127.0.0.1:8085/services/helloWord?wsdl");
-
// 需要密码的情况需要加上用户名和密码
-
// client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD));
-
Object[] objects = new Object[0];
-
try {
-
// invoke("方法名",参数1,参数2,参数3....);
-
//json的形式
-
Map<String,Object> params=new HashMap<String,Object>();
-
params.put("name", "dasda");
-
Gson gson = new Gson();
-
String json = gson.toJson(params);
-
objects = client.invoke("say", json);
-
System.out.println("返回数据:" + objects[0]);
-
} catch (java.lang.Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}
axis方式调用webservice接口:
-
import javax.xml.namespace.QName;
-
import javax.xml.rpc.ParameterMode;
-
-
import org.apache.axis.client.Call;
-
import org.apache.axis.client.Service;
-
import org.apache.axis.encoding.XMLType;
-
-
public class Test01 {
-
public static void main(String[] args) {
-
try {
-
//1、直接引用远程的wsdl文件
-
String endpoint = "接口访问路径";
-
Service service = new Service();
-
Call call = (Call) service.createCall(); //创建服务
-
call.setTargetEndpointAddress(endpoint);
-
//2、定义报名和接口方法
-
call.setOperationName(new QName("targetNamespace", //wsdl文件中的targetNamespace
-
"getAllResourceDetail") //接口实现功能的方法
-
);
-
-
//3、设置参数
-
call.addParameter("resType", XMLType.XSD_INT,ParameterMode.IN);// 接口的参数
-
call.addParameter("nodeIndexCode",XMLType.XSD_STRING,ParameterMode.IN);// 接口的参数
-
call.setReturnType(XMLType.XSD_STRING);// 设置返回类型
-
-
int resType=1000;
-
String nodeIndexCode="";
-
-
//4、给方法传递参数,并且调用方法
-
String result = (String) call.invoke(new Object[] {nodeIndexCode ,resType});
-
System.out.println(result);
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}