SpringBoot+cxf发布WebService

介绍

公司遗留老系统是一个产品化的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测试

测试添加数据的接口,截图如下:

查看数据库中的数据,截图如下:

测试查询数据接口,截图如下:

完整测试demo

https://github.com/canGBean/springboot_cxf_webservice_demo

原文地址:https://www.cnblogs.com/GYoungBean/p/13806497.html