博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Boot实践--集成WebServices基础开发
阅读量:7100 次
发布时间:2019-06-28

本文共 14559 字,大约阅读时间需要 48 分钟。

hot3.png

Spring Boot实践--集成Web Services基础开发

Spring Web Services(下简称ws)本质上是基于SpringBoot的项目,因此如果有对SpringBoot不太了解的同学,回头再来看比较合适。

ws分为server端与client端两个部分,本文旨在介绍框架搭建的流程与重点。

一、ws.server端搭建

建立Server的关键是首先建立xsd文件。xsd文件是xml文件的定义与基础,你希望别人如何访问与获取你的数据都需要在xsd文件中说明。

countries.xsd

users.xsd

这两个文件默认请存放于 src/main/resources 目录下,如下图所示:

建立完成以后我们可以着手编写pom.xml文件,即建立工程依赖。

4.0.0
org.learnhow
ws.server
0.0.1-SNAPSHOT
jar
ws.server
http://maven.apache.org
org.springframework.boot
spring-boot-starter-parent
1.5.4.RELEASE
1.8
1.8
UTF-8
org.springframework.boot
spring-boot-starter-web-services
wsdl4j
wsdl4j
junit
junit
test
org.codehaus.mojo
jaxb2-maven-plugin
1.6
xjc
xjc
${project.basedir}/src/main/resources/
${project.basedir}/src/main/java
false

重点是最后的一项maven plugin,它会读取resources目录下的xsd文件并在 src/main/java 目录下建立.java文件。需要注意的是代码的package路径是通过xsd的targetNamespace事先指定的。

代码文件被maven创建完成以后代表第一段工作顺利完成。下面我们需要人工编写Endpoint类,即建立对外访问的服务接口。通常你提供了几分xsd文件就应该创建几个Endpoint类。Endpoint本质上是接收一个request,然后经过你的业务逻辑再返回一个response。与传统意义上的浏览器不同,后者通常传输json字符串,而前者则是xml。

CountryEndpoint

package org.learnhow.ws.server;import org.learnhow.ws.schema.GetCountryRequest;import org.learnhow.ws.schema.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;@Endpointpublic class CountryEndpoint {    private static final String NAMESPACE_URI = "http://learnhow.org/ws/schema";    @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;    }}

UserEndpoint

package org.learnhow.ws.server;import org.learnhow.ws.schema.GetUserRequest;import org.learnhow.ws.schema.GetUserResponse;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;@Endpointpublic class UserEndpoint {    private static final String NAMESPACE_URI = "http://learnhow.org/ws/schema";    @Autowired    private UserRepository userRepository;    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getUserRequest")    @ResponsePayload    public GetUserResponse getUser(@RequestPayload GetUserRequest request) {        GetUserResponse response = new GetUserResponse();        response.setUser(userRepository.findUser(request.getName()));        return response;    }}

很显然你的业务逻辑应该封装在CountryRepository和UserRepository对象里。接下来创建CountryRepository对象。

CountryRepository

package org.learnhow.ws.server;import java.util.HashMap;import java.util.Map;import javax.annotation.PostConstruct;import org.learnhow.ws.schema.Country;import org.learnhow.ws.schema.Currency;import org.learnhow.ws.schema.Language;import org.springframework.stereotype.Component;@Componentpublic class CountryRepository {    private static final Map
countries = new HashMap<>(); @PostConstruct public void initData() { Country spain = new Country(); spain.setName("Spain"); spain.setCapital("Madrid"); spain.setCurrency(Currency.EUR); spain.setPopulation(46704314); Language spanish = new Language(); spanish.setName("spanish"); spain.setLanguage(spanish); Country poland = new Country(); poland.setName("Poland"); poland.setCapital("Warsaw"); poland.setCurrency(Currency.PLN); poland.setPopulation(38186860); Language polish = new Language(); polish.setName("polish"); poland.setLanguage(polish); Country uk = new Country(); uk.setName("United Kingdom"); uk.setCapital("London"); uk.setCurrency(Currency.GBP); uk.setPopulation(63705000); Language english = new Language(); english.setName("english"); uk.setLanguage(english); countries.put(spain.getName(), spain); countries.put(poland.getName(), poland); countries.put(uk.getName(), uk); } public Country findCountry(String name) { return countries.get(name); }}

UserRepository(略)

最后是编写configuration,它是整个框架调用的核心。

package org.learnhow.ws.server;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;@EnableWs@Configurationpublic class WebServiceConfig extends WsConfigurerAdapter {    @Bean    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {        MessageDispatcherServlet servlet = new MessageDispatcherServlet();        servlet.setApplicationContext(applicationContext);        servlet.setTransformWsdlLocations(true);        return new ServletRegistrationBean(servlet, "/ws/*");    }    @Bean(name = "countries")    public DefaultWsdl11Definition defaultWsdl11DefinitionCountry() {        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();        wsdl11Definition.setPortTypeName("CountriesPort");        wsdl11Definition.setLocationUri("/ws");        wsdl11Definition.setTargetNamespace("http://learnhow.org/ws/schema");        wsdl11Definition.setSchema(countriesSchema());        return wsdl11Definition;    }    @Bean(name = "users")    public DefaultWsdl11Definition defaultWsdl11DefinitionUser() {        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();        wsdl11Definition.setPortTypeName("CountriesPort");        wsdl11Definition.setLocationUri("/ws");        wsdl11Definition.setTargetNamespace("http://learnhow.org/ws/schema");        wsdl11Definition.setSchema(usersSchema());        return wsdl11Definition;    }    @Bean    public XsdSchema countriesSchema() {        return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));    }    @Bean    public XsdSchema usersSchema() {        return new SimpleXsdSchema(new ClassPathResource("users.xsd"));    }}

最后一步:编写启动项Application

package org.learnhow.ws;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class Application {    public static void main(String[] args) {        SpringApplication.run(Application.class, args);    }    }

完成的目录结构如下:

二、测试

启动application,打开浏览器访问:http://localhost:8080/ws/countries.wsdl

与http://localhost:8080/ws/users.wsdl 如果页面分别展示了两份xml文件代表服务器已经可以正常运行了。也可以用SoapUI Pro进一步测试数据的读取和发送是否正常。

三、ws.client端搭建

如果说server端是通过xsd产生java与WSDL的过程那么client端就恰恰相反。我们还是使用maven工具通过服务器暴露在外的wsdl文件建立java对象。首先编辑pom.xml文件配置依赖和wsdl访问路径。

4.0.0
org.learnhow
ws.client
jar
0.0.1-SNAPSHOT
1.8
1.8
org.springframework.boot
spring-boot-starter-parent
1.5.4.RELEASE
org.springframework.boot
spring-boot-starter
org.springframework.ws
spring-ws-core
org.springframework.boot
spring-boot-maven-plugin
org.jvnet.jaxb2.maven2
maven-jaxb2-plugin
0.13.2
generate
WSDL
ws.wsdl
http://localhost:8080/ws/countries.wsdl
http://localhost:8080/ws/users.wsdl

这里要注意,如果此时你已经将server的进程停止,也就是wsdl无法访问,pom.xml文件会报错。看上去大概会像这样:

正常情况下maven会自动帮你在target目录下建立java对象,目录结构如下:

如果你发现无法正常建立java对象,请首先检查以下两点:

maven引入的依赖是否完整:国内的网络环境不是很好,有时候通过maven搭建环境经常会在运行时报出各种莫名其妙的错误。其中绝大多数其实都是由于依赖引入不完整造成的。此时你可能需要对Maven Dependencies目录下的jar包逐一检查。

maven结构错误:maven的版本很多,不同的版本间可能在元素的结构定义上有所差距。如果在<plugins>节点报错可以考虑在外层再包一层<pluginManagement>节点。具体原因我也没有深究,只能说“有时管用”,如果你对maven有深入的了解也希望告诉我。

如果以上环境你进行的都很顺利,那么恭喜你80%的工作已经完成了。

下面是编写client客户端代码:

package org.learnhow.ws.client;import org.springframework.ws.client.core.support.WebServiceGatewaySupport;import org.springframework.ws.soap.client.core.SoapActionCallback;import ws.wsdl.GetCountryRequest;import ws.wsdl.GetCountryResponse;public class CountryClient extends WebServiceGatewaySupport {    public static final String URI = "http://localhost:8080/ws";    public static final String SOAPACTION = "http://learnhow.org/ws/schema/getUserRequest";    public GetCountryResponse getCountry(String countryName) {        GetCountryRequest request = new GetCountryRequest();        request.setName(countryName);        GetCountryResponse response = (GetCountryResponse) getWebServiceTemplate().marshalSendAndReceive(URI, request,                new SoapActionCallback(SOAPACTION));        return response;    }}

然后依然是创建configuration供框架调用

package org.learnhow.ws.client;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.oxm.jaxb.Jaxb2Marshaller;@Configurationpublic class AppConfiguration {    @Bean    public Jaxb2Marshaller marshaller() {        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();        marshaller.setContextPath("ws.wsdl");        return marshaller;    }    @Bean("country")    public CountryClient counrtyClient(Jaxb2Marshaller marshaller) {        CountryClient client = new CountryClient();        client.setDefaultUri(CountryClient.URI);        client.setMarshaller(marshaller);        client.setUnmarshaller(marshaller);        return client;    }    @Bean("user")    public UserClient userClient(Jaxb2Marshaller marshaller) {        UserClient client = new UserClient();        client.setDefaultUri(UserClient.URI);        client.setMarshaller(marshaller);        client.setUnmarshaller(marshaller);        return client;    }}

最后是编写Application启动项

package org.learnhow.ws;import org.learnhow.ws.client.CountryClient;import org.learnhow.ws.client.UserClient;import org.springframework.boot.CommandLineRunner;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;import ws.wsdl.GetCountryResponse;import ws.wsdl.GetUserResponse;@SpringBootApplicationpublic class Application {    public static void main(String[] args) {        SpringApplication.run(Application.class, args);    }    @Bean    CommandLineRunner lookup(CountryClient client) {        return args -> {            String countryName = "Spain";            if (args.length > 0) {                countryName = args[0];            }            GetCountryResponse response = client.getCountry(countryName);            System.out.println("response: " + response.getCountry().getName());        };    }}

运行application,如果你能看到控制台有 "response: Spain" 打出代表数据已经能够正常获取。

 

后记:

本文的代码逻辑主要参考了Spring Web Services官网文档。另外WebService除了通过Spring还有多种实现手段,感兴趣的同学可以看看如何使用wsimport工具以及Tomcat发布WebService的例子。这里不再赘述。

转载于:https://my.oschina.net/spinachgit/blog/1617063

你可能感兴趣的文章
Sql Server导入Access数据库报不可识别的数据库格式 Microsoft JET Database Engine
查看>>
存储设备形成的层次结构
查看>>
http://knockoutjs.com/工作杂记
查看>>
Http协议中的Header与Body
查看>>
窗口大小改变绑定resize事件
查看>>
python数据结构之二叉树遍历的实现
查看>>
进出口流程 & 报关单据
查看>>
各主流浏览器内核介绍
查看>>
[LeetCode] Copy List with Random Pointe
查看>>
我使用中的Linux命令和快捷键(For Ubuntu)
查看>>
如何更深入地学习Linux?
查看>>
目标检測的图像特征提取之(一)HOG特征
查看>>
MySQL-EXPLAIN用法详解
查看>>
du 命令
查看>>
jdbctemplate中的query(sql,params,mapper)与queryForList(sql,params,class)区别
查看>>
C++ 虚函数表解析
查看>>
Responder一点也不神秘————iOS用户响应者链完全剖析
查看>>
Type mismatch: cannot convert from java.sql.PreparedStatement to com.mysql.jdbc.PreparedStatement
查看>>
SharePoint 2013 工作流平台的选项不可用
查看>>
thinkphp 重定向redirect
查看>>