SpringBoot整合WebService的实现示例

网友投稿 270 2022-11-18

SpringBoot整合WebService的实现示例

目录SpringBoot搭建WebService程序一、定义规范接口二、搭建WebService服务端三、搭建WebService客户端

WebService是一种传统的SOA技术架构,它不依赖于任何的编程语言,也不依赖于任何的技术平台,可以直接基于HTTP协议实现网络应用间的数据交互。

面向服务架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和协议联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。

WebService主要用于异构平台之间的整合与调用,例如请求者使用的是java语言开发,而提供者是golang语言开发。使用XML进行接口的描述(SOAP协议)。

SpringBoot搭建WebService程序

在springboot-webservice项目中新建3个模块,webservice-server、webservice-client、webservice-common。

webservice-common项目引入项目依赖,webservice-server和webservice-client项目引入webservice-common项目。

com.sun.xml.ws

jaxws-ri

2.3.5

pom

org.hibernate.validator

hibernate-validator

7.0.1.Final

org.apache.cxf

cxf-spring-boot-starter-jaxws

3.4.3

org.apache.cxf

cxf-rt-transports-http

3.4.3

org.springframework.boot

spring-boot-starter-web

2.6.0

org.springframework.boot

spring-boot-starter-web-services

2.6.0

一、定义规范接口

WebService服务端以远程接口为主,在Java实现的WebService技术中,使用CXF开发框架可以直接将接口发布成WebService。

webservice-common模块在com.it.service包下新建MessageService接口。

package com.it.service;

import javax.jws.WebMethod;

import javax.jws.WebParam;

import javax.jws.WebService;

@WebService(name = "MessageService", targetNamespace = "http://service.it.com/")

public interface MessageService {

@WebMethod // webservice方法标注

String echo(@WebParam String message);

}

二、搭建WebService服务端

webservice-server模块定义MessageService的实现子类。

package com.it.service.impl;

import com.it.service.MessageService;

import org.springframework.stereotype.Service;

import javax.jws.WebService;

@WebService(serviceName = "MessageService",

targetNamespace = "http://service.it.com/", // 接口命名空间

endpointInterface = "com.it.service.MessageService") // 接口名称

@Service // 注册到Spring容器

public class MessageServiceImpl implements MessageService {

@Override

public String echo(String message) {

return "[echo]: " + message;

}

}

基于拦截器实现安全配置。

package com.it.interceptor;

import lombok.extern.slf4j.Slf4j;

import org.apache.cxf.binding.soap.SoapMessage;

import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;

import org.apache.cxf.interceptor.Fault;

import org.apache.cxf.phase.AbstractPhaseInterceptor;

import org.apache.cxf.phase.Phase;

import org.springframework.stereotype.Component;

import org.w3c.dom.NodeList;

import javax.xml.soap.SOAPException;

import javax.xml.soap.SOAPHeader;

import javax.xml.soap.SOAPMessage;

import java.util.Objects;

@Slf4j

@Component

public class WebServiceAuthInterceptor extends AbstractPhaseInterceptor {

private static final String USER_NAME = "admin"; // 用户名

private static final String USER_PASSWORD = "123456"; //密码

private final SAAJInInterceptor interceptor = new SAAJInInterceptor(); // 创建拦截器

public WebServiceAuthInterceptor() {

super(Phase.PRE_PROTOCOL);

super.getAfter().add(SAAJInInterceptor.class.getName()); // 添加拦截器

}

@Override

public void handleMessage(SoapMessage message) throws Fault {

// 获取指定信息

SOAPMessage soapMessage = message.getContent(SOAPMessage.class);

if (soapMessage == null) { // 没有消息

this.interceptor.handleMessage(message); // 走默认流程

soapMessage = message.getContent(SOAPMessage.class); // 再次获取消息

}

SOAPHeader header = null; // SOAP头信息

try {

header = soapMessage.getSOAPHeader();

} catch (SOAPException e) {

e.printStackTrace();

}

if (header == null) { // 没有头信息

throw new Fault(new IllegalAccessException("找不到header信息"));

}

// 解析XML文档(SOAP是XML结构的)

NodeList usernameList = header.getElementsByTagName("username");

NodeList passwordList = header.getElementsByTagName("password");

if (usernameList.getLength() < 1) {

throw new Fault(new IllegalAccessException("找不到header信息"));

}

if (passwordList.getLength() < 1) {

throw new Fault(new IllegalAccessException("找不到header信息"));

}

String username = usernameList.item(0).getTextContent().trim(); // 获取用户名

String password = passwordList.item(0).getTextContent().trim(); // 获取密码

if (Objects.equals(USER_NAME, username) && Objects.equals(USER_PASSWORD, password)) {

log.info("用户访问成功");

} else {

SOAPException soapException = new SOAPException("用户认证失败");

log.error("用户认证失败");

throw new Fault(soapException);

}

}

}

由于当前的webservice是基于CXF开发的,所以需要定义CXF配置类。

package com.it.config;

import com.it.interceptor.WebServiceAuthInterceptor;

import com.it.service.MessageService;

import org.apache.cxf.Bus;

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 javax.xml.ws.Endpoint;

@Configuration

public class CXFConfig {

private final Bus bus;

private final MessageService messageService;

private final WebServiceAuthInterceptor webServiceAuthInterceptor;

@Autowired

public CXFConfig(Bus bus, MessageService messageService, WebServiceAuthInterceptor webServiceAuthInterceptor) {

this.bus = bus;

this.messageService = messageService;

this.webServiceAuthInterceptor = webServiceAuthInterceptor;

}

public ServletRegistrationBean getServletRegistrationBean() {

return new ServletRegistrationBean(new CXFServlet(), "/services/*"); // 设置webservice访问父路径

}

@Bean

public Endpoint getMessageEndpoint() {

EndpointImpl endpoint = new EndpointImpl(bus, messageService);

endpoint.publish("/MessageService");

endpoint.getInInterceptors().add(webServiceAuthInterceptor); // 添加拦截器

return endpoint;

}

}

新建SpringBoot启动类,启动程序。

packagsCEWqe com.it;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public chttp://lass StartWebServiceServer {

public static void main(String[] args) {

SpringApplication.run(StartWebServiceServer.class, args);

}

}

浏览器访问:http://localhost:8080/services 发现wehttp://bservice发布成功。

WSDL文档也正常出现。

三、搭建WebService客户端

CXF组件下的WebService调用服务使用如下流程:

webservice-client模块创建客户端登录拦截器,设置认证信息。

package com.it.interceptor;

import org.apache.cxf.binding.soap.SoapMessage;

import org.apache.cxf.headers.Header;

import org.apache.cxf.helpers.DOMUtils;

import org.apache.cxf.interceptor.Fault;

import org.apache.cxf.phase.AbstractPhaseInterceptor;

import org.apache.cxf.phase.Phase;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import javax.xml.namespace.QName;

import java.util.List;

public class ClientLoginInterceptor extends AbstractPhaseInterceptor {

private final String username;

private final String password;

public ClientLoginInterceptor(String username, String password) {

super(Phase.PRE_PROTOCOL);

this.username = username;

this.password = password;

}

@Override

public void handleMessage(SoapMessage message) throws Fault {

List

headers = message.getHeaders(); // 获取全部头信息

Document document = DOMUtils.createDocument(); // 创建xml文档

Element authElement = document.createElement("authority"); // 认证数据节点

Element usernameElement = document.createElement("username");

Element passwordElement = document.createElement("password");

usernameElement.setTextContent(username);

passwordElement.setTextContent(password);

authElement.appendChild(usernameElement);

authElement.appendChild(passwordElement);

headers.add(0, new Header(new QName("authority"), authElement));

}

}

CXF有两种调用方式,代理调用和动态程序调用。使用代理调用:

package com.it.client;

import com.it.interceptor.ClientLoginInterceptor;

import com.it.service.MessageService;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

public class CXFProxyClient {

private static final String ADDRESS = "http://localhost:8080/services/MessageService?wsdl"; // WebService服务地址

public static void main(String[] args) {

JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();

jaxWsProxyFactoryBean.setAddress(ADDRESS);

jaxWsProxyFactoryBean.setServiceClass(MessageService.class);

jaxWsProxyFactoryBean.getOutInterceptors().add(

new ClientLoginInterceptor("admin","123456") // 设置用户名,密码

);

MessageService messageService = (MessageService)jaxWsProxyFactoryBean.create();

String echo = messageService.echo("[webservice proxy invoke]");

System.out.println("echo = " + echo);

}

}

执行程序,接口调用成功。

动态调用:

package com.it.client;

import com.it.interceptor.ClientLoginInterceptor;

import org.apache.cxf.endpoint.Client;

import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

public class CXFDynamicClient {

private static final String ADDRESS = "http://localhost:8080/services/MessageService?wsdl"; // WebService服务地址

public static void main(String[] args) throws Exception {

JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();

Client client = dcf.createClient(ADDRESS);

client.getOutInterceptors().add(new ClientLoginInterceptor("admin","123456"));

String message = "dynamic";

Object[] result = client.invoke("echo", message);

System.out.println(result);

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:注意:IoT时代即将“失业”的十大岗位
下一篇:特征降维
相关文章

 发表评论

暂时没有评论,来抢沙发吧~