Spring Boot集成webService

在pom添加依赖

<!--WerbService CXF依赖 start-->
<dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxws</artifactId>
</dependency>
<dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId>
</dependency>
<!--WerbService CXF依赖 end-->

提供webservice接口

@WebService(name = "MesService", // 暴露服务名称targetNamespace = "http://mes.jingchuang.com/"// 命名空间,一般是接口的包名倒序
)
public interface T100Service {/*** 1.【sendMaterialInfo】接收T100料件信息** @param requestMaterialInfoData* @return Result*/@WebMethodResult sendMaterialInfo(RequestMaterialInfoData requestMaterialInfoData);
}

实现webservice的方法

@Service
@Transactional
@WebService(// 对外发布的服务名,指定Web Service的服务名称:wsdl:service。缺省值为 Java 类的简单名称 + ServiceserviceName = "MesService",//portName:wsdl:portName的值。缺省值为WebService.name+PortportName = "UserServiceImpl",// 命名空间(默认的值为 “http://包名/” (也可为域名) ,可以通过此变量指定一个自定义的targetNamespace值)targetNamespace = "http://mes.jingchuang.com/",// 对外提供的接口endpointInterface = "com.jingchuang.mes.t100service.service.T100Service")
@Component
@Slf4j
public class T100ServiceImpl implements T100Service {/*** 1.【sendMaterialInfo】接收****料件信息 ** @param requestMaterialInfoData* @return*///region 接收料件信息@Override@Transactionalpublic Result sendMaterialInfo(RequestMaterialInfoData requestMaterialInfoData) {return ResultGenerator.fail("请输入正确的操作码");}//endregion
}

配置并发布

@Configuration
public class WebServiceConfig {// 注意更改此方法名:public ServletRegistrationBean dispatcherServlet()  // 把默认映射覆盖掉了,把这个名字改掉,控制类方法就能访问了,可以正常其他请求url,webservice服务也正常。@Beanpublic ServletRegistrationBean disServlet(){return new ServletRegistrationBean(new CXFServlet(),"/service/*");//发布服务名称}@Bean(name = Bus.DEFAULT_BUS_ID)public SpringBus springBus(){return  new SpringBus();}@Autowiredpublic T100Service t100Service;@Beanpublic Endpoint endpoint() {EndpointImpl endpoint=new EndpointImpl(springBus(), t100Service);//绑定要发布的服务endpoint.publish("/zhlxmes"); //显示要发布的名称endpoint.getInInterceptors().add(new AuthInterceptor()); //增加用户名密码验证return endpoint;}
}

增加用户名,密码验证配置

public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {private static final Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);private SAAJInInterceptor saa = new SAAJInInterceptor();private static final String USER_NAME = "t100";private static final String USER_PASSWORD = "t100";public AuthInterceptor() {super(Phase.PRE_PROTOCOL);getAfter().add(SAAJInInterceptor.class.getName());}@Overridepublic void handleMessage(SoapMessage message) throws Fault {SOAPMessage mess = message.getContent(SOAPMessage.class);if (mess == null) {saa.handleMessage(message);mess = message.getContent(SOAPMessage.class);}SOAPHeader head = null;try {head = mess.getSOAPHeader();} catch (Exception e) {logger.error("getSOAPHeader error: {}", e.getMessage(), e);}if (head == null) {throw new Fault(new IllegalArgumentException("找不到Header,无法验证用户信息"));}NodeList users = head.getElementsByTagName("username");NodeList passwords = head.getElementsByTagName("password");if (users.getLength() < 1) {throw new Fault(new IllegalArgumentException("找不到用户信息"));}if (passwords.getLength() < 1) {throw new Fault(new IllegalArgumentException("找不到密码信息"));}String userName = users.item(0).getTextContent().trim();String password = passwords.item(0).getTextContent().trim();if (USER_NAME.equals(userName) && USER_PASSWORD.equals(password)) {logger.debug("admin auth success");} else {SOAPException soapExc = new SOAPException("认证错误");logger.debug("admin auth failed");throw new Fault(soapExc);}}
}

客户端

客户端可以通过两种方式调用服务端。

1 .通过JaxWsDynamicClientFactory方式

public static Object doPostSoap(Class<?> clazz, String postUrl, String methodName, String xml) {try {Object[] objects;if (postUrl.equals("dev")) {objects = new Object[]{TestConten};} else {log.info("【T00/doPostSoap发送】:\n" + xml);// 创建动态客户端JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();Client client = dcf.createClient(postUrl);// 设置超时单位为毫秒HTTPConduit conduit = (HTTPConduit) client.getConduit();HTTPClientPolicy policy = new HTTPClientPolicy();policy.setConnectionTimeout(15000);policy.setAllowChunking(false);policy.setReceiveTimeout(30000);conduit.setClient(policy);// invoke("方法名",参数1,参数2,参数3....);objects = client.invoke(methodName, xml);log.info("【T00/doPostSoap接收】:\n" + objects[0].toString());// 需要密码的情况需要加上用户名和密码
//                 client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME,PASS_WORD));}Log loginfo = new Log();loginfo.setType("info");loginfo.setName("【请求T100接口】-doPostSoap");loginfo.setContent(xml);loginfo.setMethodName(methodName);loginfo.setCreateTime(new Date());loginfo.setCreateUserId(BaseContextHandler.getUserID());loginfo.setCreateUserName(BaseContextHandler.getUsername());loginfo.setResult(objects[0].toString());try {logService.save(loginfo);} catch (Exception ex) {log.info("保存日志错误" + ex.getMessage());}if (objects.length <= 0) {return null;}ReceivingData receivingData = (ReceivingData) XsteamUtil.toBean(ReceivingData.class, objects[0].toString());
//            receivingData = (ReceivingData)XsteamUtil.toBean(ReceivingData.class,TestConten);Object rulest = XsteamUtil.toBean(clazz, receivingData.getPayload().getParam().getData());return rulest;} catch (Exception e) {System.out.println("错误信息:" + e.getMessage());return null;}}

这种方式要注意的就是,如果调用的服务接口返回的是一个自定义对象,那么结果Object[]中的数据类型就成了这个自定义对象(组件帮你自动生成了这个对象),

但是你本地可能并没有这个类,所以需要自行转换处理,最简单的是新建一个跟返回结果一模一样的类进行强转。

客户端需要在header中添加用户信息,这样才能通过服务器的验证。

public class ClientLoginInterceptor  extends AbstractPhaseInterceptor<SoapMessage> {private String username;private String password;public ClientLoginInterceptor(String username, String password) {super(Phase.PREPARE_SEND);this.username = username;this.password = password;}@Overridepublic void handleMessage(SoapMessage soap) throws Fault {List<Header> headers = soap.getHeaders();Document doc = DOMUtils.createDocument();Element auth = doc.createElement("authrity");Element username = doc.createElement("username");Element password = doc.createElement("password");username.setTextContent(this.username);password.setTextContent(this.password);auth.appendChild(username);auth.appendChild(password);headers.add(0, new Header(new QName("tiamaes"),auth));}
}

2、通过wsimport生成客户端代码
通过jdk自带的wsimport生成客户端代码。进入$JAVA_HOME/bin下,新建bin和src两个文件夹,执行以下命令:
wsimport -d ./bin -s ./src -keep http://localhost:8080/services/layout?wsdl
其中几个参数有以下几个,
-d:生成客户端执行类的class文件存放目录,
-s:生成客户端执行类的源文件存放目录,
-p:定义生成类的包名
  -verbose:显示生成过程
需要注意的是:无论-d或是-s后的目录必须在文件系统中存在,否则报错。

将src下连同包一起复制到程序中,编写客户端入口类:


public class WSClient {private static final Logger LOG = LoggerFactory.getLogger(WSClient.class);private static final String USER_NAME = "admin";private static final String PASS_WORD = "pass";public static void main(String[] args) {//方式二:通过wsimport生成客户端代码LayoutServiceImpl impl = new LayoutServiceImpl();impl.setHandlerResolver(new HandlerResolver() {@Overridepublic List<Handler> getHandlerChain(PortInfo portInfo) {List<Handler> handlerList = new ArrayList<Handler>();handlerList.add(new ClientHandler(USER_NAME, PASS_WORD));return handlerList;}});try {LayoutService layoutService = impl.getLayoutImpl();String result_1 = layoutService.sayHello("jack");LOG.debug("[2]sayHello:" + result_1);OperationResult result_2 = layoutService.addLayout("name", "content");LOG.debug("[2]addLayout result_succeed:" + result_2.isSucceed());LOG.debug("[2]addLayout result_msg:" + result_2.getMsg());} catch (SOAPFaultException e) {LOG.error("SOAPFaultException occurs:{}", e.getMessage());}}

该方式的好处是可以像调用本地接口一样调用服务端方法,简单明了。缺点就是会生成一堆文件。

用户的头信息设置类:

public class ClientHandler implements SOAPHandler<SOAPMessageContext> {private String username;private String password;public ClientHandler(String username, String password) {this.username = username;this.password = password;}public boolean handleMessage(SOAPMessageContext ctx) {//出站,即客户端发出请求前,添加表头信息Boolean request_p = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);if (request_p) {try {SOAPMessage msg = ctx.getMessage();SOAPEnvelope env = msg.getSOAPPart().getEnvelope();SOAPHeader hdr = env.getHeader();if (hdr == null) hdr = env.addHeader();//添加认证信息头QName name = new QName("http://service.webservice.com/", "LayoutImpl");SOAPHeaderElement header = hdr.addHeaderElement(name);SOAPElement userElement = header.addChildElement("username");userElement.addTextNode(username);SOAPElement passElement = header.addChildElement("password");passElement.addTextNode(password);msg.saveChanges();return true;} catch (Exception e) {e.printStackTrace();}}return false;}@Overridepublic boolean handleFault(SOAPMessageContext context) {// TODO Auto-generated method stubreturn false;}@Overridepublic void close(MessageContext context) {// TODO Auto-generated method stub}@Overridepublic Set<QName> getHeaders() {// TODO Auto-generated method stubreturn null;}
}

springboot 整合xcf 发布 webservice相关推荐

  1. IDEA中进行SpringBoot整合spring-ws开发webservice接口后期要修改xsd文件流程

    场景 SpringBoot整合spring-ws开发webservice接口(全流程详细教程) 参照: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/articl ...

  2. 基于Springboot整合RestTemplate调用Webservice接口

    1.基于Springboot整合RestTemplate调用Webservice接口,如果感觉使用webservice客户端调用服务器端不会,或者不方便 的时候,可以尝试使用RestTemplate来 ...

  3. SpringBoot整合spring-ws开发webservice接口(全流程详细教程)

    场景 spring-ws spring-ws官网: https://spring.io/projects/spring-ws SpringWebServices(Spring-WS)是Spring社区 ...

  4. java - springmvc整合cxf发布webservice

    1.jar包已上传百度云盘,在jar包目录下 2.web.xml配置 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-inst ...

  5. IDEA快速 实现 SpringMVC 整合xfire 发布 WebService 服务

    文章目录 一.idea快速搭建web项目 二.xfire 服务方搭建 1. pom依赖 2. web.xml 3. 创建一个entity 4. 创建一个接口 5. 创建接口实现类 6. 在WEB-IN ...

  6. spring boot整合cxf发布和调用webservice

    一.前言 说起web service最近几年restful大行其道,大有取代传统soap web service的趋势,但是一些特有或相对老旧的系统依然使用了传统的soap web service,例 ...

  7. springboot整合dubbo\zookeeper做注册中心

    springboot整合dubbo发布服务,zookeeper做注册中心.前期的安装zookeeper以及启动zookeeper集群就不说了. dubbo-admin-2.5.4.war:dubbo服 ...

  8. SpringBoot整合WebService(服务端+客户端)

    SpringBoot整合WebService(服务端+客户端) 文章目录 SpringBoot整合WebService(服务端+客户端) 一.服务端 1.项目结构 2.创建好SpringBoot项目后 ...

  9. Spring和CXF整合发布WebService(服务端、客户端)

    参考Spring和CXF整合发布WebService(服务端.客户端) 转载于:https://www.cnblogs.com/timspace/p/11113576.html

最新文章

  1. 微信扫描二维码登入实现,网页端
  2. Heinz College of Information Systems and Public Policy Carnegie Mellon University
  3. USACO1.3.4 Prime Cryptarithm 牛式 解题报告(模拟)
  4. anaconda中gurobi下载_Anaconda是什么?Anconda下载安装教程 - python基础入门(16)
  5. 作者:陈兴鹏(1963-),男,兰州大学资源环境学院教授、博士生导师。
  6. mysql如何查看dbid_如何获得数据库的DBID
  7. Luogu2467 SDOI2010 地精部落 DP
  8. oracle 索引监控
  9. c语言函数定义的语法格式,C语言函数 -C语言函数定义的语法格式
  10. python提取句子_关于python:从句子中提取介词短语
  11. php设置pdf下载加密文件,pdf文件加密方法 PDF文件怎样加密 如何给PDF文件添加打开口令...
  12. IT人才外包的合作流程是怎样的?
  13. php手机网页下载文件,php 手机下载 POST 类
  14. 扩展Euclidean算法求乘法逆原理详解与算法实现
  15. Git 版本控制工具学习
  16. adb 强制删除系统应用
  17. SQL Server 中WITH (NOLOCK)浅析 2014-08-30 11:58 by 潇湘隐者, 58264 阅读, 33 评论, 收藏, 编辑 概念介绍 开发人员喜欢在SQL脚本
  18. iOS 苹果审核被下架的部分原因
  19. Go语言模板脚本语法——详细
  20. Linux 路由实现原理

热门文章

  1. AndroidStudio1.4 安卓平台架构
  2. oracle查找分区重建,Oracle中重建表分区
  3. 小样本学习--学习记录
  4. CG100-13景程-9S12HZ256VAL
  5. 来自一位应届生的建议
  6. (附源码)php积极心理学交流学习网站 毕业设计 100623
  7. vue 签署文件两张图合并成一张图 h5页面转换成图片并长按保存在本地
  8. struts filter
  9. c语言编程 插队排身高,【C语言刷LeetCode】406. 根据身高重建队列(M)
  10. SQLSTATE=2300