介绍
公司遗留老系统是一个产品化的ERP,只支持webService的发布,且调用方仅能调用webService.ERP发布的webservice依赖了很多产品化的其他组件,现在想脱离这些组件。于是直接连数据库,然后自己写webService来调用。因为本机Gradle版本是4.9,所以spring boot无法用最新版本。
环境介绍
- jdk:11
- gradle:4.9
- springBoot:2.1.3
- apache-cxf:3.2.4
- lombok
- h2
测试过程设计
- 使用h2数据库建表,保存几个测试数据
- 发布2个webservice接口,一个是生成测试数据的(insertFooBean),一个是查询数据的(queryFooBean)
- 考虑spring boot与cxf的集成
- 考虑jdk11下jax-ws相关包被移除的问题
废话少说上代码
gradle的配置
plugins {
id 'org.springframework.boot' version '2.1.3.RELEASE'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
group = 'com.jde.ws'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
maven {
url 'https://maven.aliyun.com/repository/public/'
}
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.apache.cxf:cxf-spring-boot-starter-jaxws:3.2.4'
implementation 'com.sun.xml.ws:jaxws-ri:2.3.3'//javax.xml.ws相关包
implementation 'javax.xml.ws:jaxws-api:2.3.1' //javax.jws相关包
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
spring boot配置
application.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=sa
#声明h2
spring.datasource.platform=h2
#开启web访问
spring.h2.console.settings.web-allow-others=true
#配置console的URI
spring.h2.console.path=/h2
#配置跟随程序启动
spring.h2.console.enabled=true
建表及数据的sql文件,data.sql与schema.sql
INSERT INTO FOO (BAR) VALUES ('aaa');
CREATE TABLE FOO (ID INT IDENTITY, BAR VARCHAR(64));
spring boot启动类,初始化建表
package com.jde.ws.jdebpmws;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import javax.sql.DataSource;
@SpringBootApplication
@Slf4j
public class JdebpmwsApplication {
@Bean
@Autowired
public SimpleJdbcInsert simpleJdbcInsert(JdbcTemplate jdbcTemplate) {
return new SimpleJdbcInsert(jdbcTemplate)
.withTableName("FOO").usingGeneratedKeyColumns("ID");
}
@Bean
@Autowired
public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) {
return new NamedParameterJdbcTemplate(dataSource);
}
public static void main(String[] args) {
SpringApplication.run(JdebpmwsApplication.class, args);
}
}
接口声明及实现类
FooService
package com.jde.ws.jdebpmws.service;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService(targetNamespace = "http://jdebpmws.ws.jde.com/")
public interface FooService {
@WebMethod
String queryFooBean(@WebParam(name = "id") Long id);
@WebMethod
String insertFooBean();
}
FooServiceImpl
package com.jde.ws.jdebpmws.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jde.ws.jdebpmws.Foo;
import com.jde.ws.jdebpmws.FooDao;
import com.jde.ws.jdebpmws.service.FooService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.jws.WebService;
@WebService(serviceName = "fooService"
, targetNamespace = "http://jdebpmws.ws.jde.com/"
, endpointInterface = "com.jde.ws.jdebpmws.service.FooService")
@Service
@Slf4j
public class FooServiceImpl implements FooService {
@Autowired
private FooDao fooDao;
@Override
public String queryFooBean(Long id) {
ObjectMapper mapper = new ObjectMapper();
Foo foo = fooDao.queryFooBean(id);
String resJson = "{"code":"%s", "data":%s}";
if (null != foo) {
try {
String fooJson = mapper.writeValueAsString(foo);
resJson = String.format(resJson, "200", fooJson);
} catch (Exception e) {
resJson = String.format(resJson, "0", e.toString());
e.printStackTrace();
log.error(e.toString());
}
} else {
resJson = String.format(resJson, "0", "");
}
return resJson;
}
@Override
public String insertFooBean() {
fooDao.insertData();
return "OK";
}
}
数据库DAO
FooDao
package com.jde.ws.jdebpmws;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Repository
public class FooDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private SimpleJdbcInsert simpleJdbcInsert;
public void insertData() {
Arrays.asList("b", "c").forEach(bar -> {
jdbcTemplate.update("INSERT INTO FOO (BAR) VALUES (?)", bar);
});
HashMap<String, String> row = new HashMap<>();
row.put("BAR", "d");
Number id = simpleJdbcInsert.executeAndReturnKey(row);
log.info("ID of d: {}", id.longValue());
}
public void listData() {
log.info("Count: {}",
jdbcTemplate.queryForObject("SELECT COUNT(*) FROM FOO", Long.class));
List<String> list = jdbcTemplate.queryForList("SELECT BAR FROM FOO", String.class);
list.forEach(s -> log.info("Bar: {}", s));
List<Foo> fooList = jdbcTemplate.query("SELECT * FROM FOO", new RowMapper<Foo>() {
@Override
public Foo mapRow(ResultSet rs, int rowNum) throws SQLException {
return Foo.builder()
.id(rs.getLong(1))
.bar(rs.getString(2))
.build();
}
});
fooList.forEach(f -> log.info("Foo: {}", f));
}
public Foo queryFooBean(Long id) {
List<Foo> fooList = jdbcTemplate.query("SELECT * FROM FOO", new RowMapper<Foo>() {
@Override
public Foo mapRow(ResultSet rs, int rowNum) throws SQLException {
return Foo.builder()
.id(rs.getLong(1))
.bar(rs.getString(2))
.build();
}
});
Map<Long, Foo> fooMap = fooList.stream().collect(Collectors.toMap(Foo::getId, a -> a, (k1, k2) -> k1));
return fooMap.get(id);
}
}
测试的实体对象Foo
package com.jde.ws.jdebpmws;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class Foo {
private Long id;
private String bar;
}
cxf的配置类
CxfConfig
package com.jde.ws.jdebpmws.config;
import com.jde.ws.jdebpmws.service.FooService;
import org.apache.cxf.Bus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.xml.ws.Endpoint;
@Configuration
public class CxfConfig {
@Autowired
private Bus bus;
@Autowired
private FooService fooService;
@Bean
public Endpoint fooServiceEndpoint() {
EndpointImpl endpoint = new EndpointImpl(bus, fooService);
endpoint.publish("/fooService");
return endpoint;
}
}
使用SOAP-UI测试
测试添加数据的接口,截图如下:
查看数据库中的数据,截图如下:
测试查询数据接口,截图如下: