概述
近来,学习有关WebService的内容,应业务需求探索下关于Spring WebService知识,需要快速生成对数据库表的一些操作,然后其他系统调用,和一般的大型网站一样,为第三方生成有关的服务。找了下网上,没有比较全面具体的文章介绍关于这方面的内容。自己逛了下Spring社区找了些资料和自己学习总结,进行了一番探索,完成了一个关于这方面的demo,虽然只是实现了简单的对数据库的增删改,但是个人认为还是比较完整的,可以给这方面有需求的开发者一个抛砖引玉的一个作用,博客中如有不准确的地方,还请交流指正,好了,不多说了,进入正题:
Lorin.Mitchell
近来,学习有关WebService的内容,应业务需求探索下关于Spring WebService知识,需要快速生成对数据库表的一些操作,然后其他系统调用,和一般的大型网站一样,为第三方生成有关的服务。找了下网上,没有比较全面具体的文章介绍关于这方面的内容。自己逛了下Spring社区找了些资料和自己学习总结,进行了一番探索,完成了一个关于这方面的demo,虽然只是实现了简单的对数据库的增删改,但是个人认为还是比较完整的,可以给这方面有需求的开发者一个抛砖引玉的一个作用,博客中如有不准确的地方,还请交流指正,好了,不多说了,进入正题:
开发工具
1. IntelliJ IDEA
2. Maven 3.0+
3. 测试WebService工具,如SOAPUI
开始开发
1.新建Maven工程,在pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
</parent>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>${project.basedir}/src/main/resources/</schemaDirectory>
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>
</plugins>
</build>
2.添加配置application.yml
spring:
datasource:
driver-class-name: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@localhost:1521:xe
username: xxxx
password: xxxx
jpa:
hibernate:
ddl-auto: update
show-sql: true
jackson:
serialization: true
server:
port: 9000
3.加入xmlSchame定义WSDL
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.com"
targetNamespace="http://www.example.com" elementFormDefault="qualified">
<xs:element name="deleteCountryByCapitalRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="capital" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="deleteCountryByCapitalResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="result" type="xs:string" fixed="OK"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getCountryRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getCountryResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="country" type="tns:country"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getCountriesRequest">
<xs:complexType>
<xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getCountriesResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="country" type="tns:country"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="createCountryRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="population" type="xs:int"/>
<xs:element name="capital" type="xs:string"/>
<xs:element name="currency" type="tns:currency"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="createCountryResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="result" type="xs:string" fixed="OK"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="country">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="population" type="xs:int"/>
<xs:element name="capital" type="xs:string"/>
<xs:element name="currency" type="tns:currency"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="currency">
<xs:restriction base="xs:string">
<xs:enumeration value="GBP"/>
<xs:enumeration value="EUR"/>
<xs:enumeration value="PLN"/>
<xs:enumeration value="RMB"/>
<xs:enumeration value="JPY"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
4.使用IDE,有xsd自动生成Java Class
5.因为我们需要对数据库表进行操作,所以,需要对生成的Country类进行修改,从而可以映射到数据库表
@Id
@Column
@XmlElement(namespace = "http://www.example.com", required = true)
protected String name;
@Column
@XmlElement(namespace = "http://www.example.com")
protected int population;
@Column
@XmlElement(namespace = "http://www.example.com", required = true)
protected String capital;
@Column
@XmlElement(namespace = "http://www.example.com", required = true)
@XmlSchemaType(name = "currency")
protected Currency currency;
接下来是jpa的操作,熟悉jpa的朋友可以跳过6,7
6.新建接口继承JpaRepository
@Repository
public interface InfCountryRepository extends JpaRepository<Country,String>{
Country findCountriesByCapital(String capital);
}
在这里我自定义了一个查询方法
7.实现改接口
import com.example.entity.Country;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.List;
/*******************Copyright Information************************
* AUTHOR: Lorin.Mitchell *
* DATE: 2017/11/6 *
* TIME: 19:05 *
****************************************************************/
@Component
public class CountryRepository {
@Autowired
private InfCountryRepository repository;
public Country findCountry(String name){
Assert.notNull(name, "The country's name must not be null");
Country country = this.repository.findOne(name);
return country;
}
public List<Country> findCountries() {
List<Country> list = this.repository.findAll();
return list;
}
public void save(Country country){
repository.save(country);
}
public void deleteByCap(String cap){
repository.delete(repository.findCountriesByCapital(cap));
}
}
8.实现对请求的处理逻辑
import com.example.dao.CountryRepository;
import com.example.entity.GetCountriesRequest;
import com.example.entity.GetCountriesResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
/*******************Copyright Information************************
* AUTHOR: Lorin.Mitchell *
* DATE: 2017/11/7 *
* TIME: 19:27 *
****************************************************************/
@Endpoint
public class CountriesEndpoint {
private static final String NAMESPACE_URI = "http://www.example.com";
@Autowired
private CountryRepository countryRepository;
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountriesRequest")
@ResponsePayload
public GetCountriesResponse getCountries(@RequestPayload GetCountriesRequest request) {
GetCountriesResponse response = new GetCountriesResponse();
response.setCountries(countryRepository.findCountries());
return response;
}
}
这里xsd定义了4个请求,处理方式和上述方式类似
import com.example.dao.CountryRepository;
import com.example.entity.GetCountryRequest;
import com.example.entity.GetCountryResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
/*******************Copyright Information************************
* AUTHOR: Lorin.Mitchell *
* DATE: 2017/11/6 *
* TIME: 19:39 *
****************************************************************/
//@Endpoint注解将该类标注为SOA的传入信息类
@Endpoint
public class CountryEndpoint {
private static final String NAMESPACE_URI = "http://www.example.com";
@Autowired
private CountryRepository countryRepository;
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
@ResponsePayload
public GetCountryResponse getCountry(@RequestPayload GetCountryRequest request) {
GetCountryResponse response = new GetCountryResponse();
response.setCountry(countryRepository.findCountry(request.getName()));
return response;
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
/*******************Copyright Information************************
* AUTHOR: Lorin.Mitchell *
* DATE: 2017/11/8 *
* TIME: 14:14 *
****************************************************************/
@Endpoint
public class CreateCountryEndpoint {
private static final String NAMESPACE_URI = "http://wwwexample.com";
@Autowired
private CountryRepository countryRepository;
//@PayloadRoot注解,表示该方法将处理以namespace和localPart的xml请求信息
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "createCountryRequest")
//@ResponsePayload注解,表示将返回值映射到reponse中
@ResponsePayload
public CreateCountryResponse createCountryResponse(@RequestPayload CreateCountryRequest request){
Country country = new Country();
country.setName(request.getName());
country.setCapital(request.getCapital());
country.setCurrency(request.getCurrency());
country.setPopulation(request.getPopulation());
countryRepository.save(country);
return new CreateCountryResponse();
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
/*******************Copyright Information************************
* AUTHOR: Lorin.Mitchell *
* DATE: 2017/11/8 *
* TIME: 15:25 *
****************************************************************/
@Endpoint
public class DeleteCountryByCapEndpoint {
private static final String NAMESPACE_URI = "http://www.example.com";
@Autowired
private CountryRepository countryRepository;
//@PayloadRoot注解,表示该方法将处理以namespace和localPart的xml请求信息
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "deleteCountryByCapitalRequest")
//@ResponsePayload注解,表示将返回值映射到reponse中
@ResponsePayload
public DeleteCountryByCapitalResponse deleteCountryByCapitalResponse(
@RequestPayload DeleteCountryByCapitalRequest request) {
countryRepository.deleteByCap(request.getCapital());
return new DeleteCountryByCapitalResponse();
}
}
9.加入ws配置类
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;
/*******************Copyright Information************************
* AUTHOR: Lorin.Mitchell *
* DATE: 2017/11/6 *
* TIME: 19:48 *
****************************************************************/
@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/webservice/*");
}
@Bean(name = "countries")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("CountriesPort");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setTargetNamespace("http://www.example.com");
wsdl11Definition.setSchema(countriesSchema);
return wsdl11Definition;
}
@Bean
public XsdSchema countriesSchema() {
return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));
}
}
10.最后加入程序主类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/*******************Copyright Information************************
* AUTHOR: Lorin.Mitchell *
* DATE: 2017/11/6 *
* TIME: 18:59 *
****************************************************************/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
11.整个Spring WebService开发已经完成了
测试
可以使用SOAPUI进行测试WSDL的地址URL:http://localhost:9000/webservice/countries.wsdl
欢迎转载,转载请注明出处,谢谢
Lorin.Mitchell