Java-WebService的发布和客户端调用

本文详细介绍了如何使用Java和ApacheCXF框架创建WebService服务端和客户端。服务端涉及依赖引入、配置类、接口定义及实现类的编写。客户端部分讲解了依赖配置、创建动态客户端和调用服务的方法。整个过程涵盖了从服务发布到客户端调用的完整流程。
摘要由CSDN通过智能技术生成

Java使用WebService

说明:仅提供了如何使用,原理无

一、服务端

1、引入依赖
        <!--    webservice    -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.3.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.1.12</version>
        </dependency>

        <!--    有的需要这个有的不需要这个,我没用到    -->
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>
2、编写配置类
package com.access.config;

import javax.xml.ws.Endpoint;

import com.access.service.AccessService;
import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 * webservice配置类
 *
 * @author 微笑
 * @version 1.0
 * @since 2023/2/23 15:52
 */
@Slf4j
@Configuration
public class WebServiceConfig {

    @Resource
    private AccessService accessService;

    /**
     * Apache CXF 核心架构是以BUS为核心,整合其他组件。
     * Bus是CXF的主干, 为共享资源提供一个可配置的场所,作用类似于Spring的ApplicationContext,这些共享资源包括
     * WSDl管理器、绑定工厂等。通过对BUS进行扩展,可以方便地容纳自己的资源,或者替换现有的资源。默认Bus实现基于Spring架构,
     * 通过依赖注入,在运行时将组件串联起来。BusFactory负责Bus的创建。默认的BusFactory是SpringBusFactory,对应于默认
     * 的Bus实现。在构造过程中,SpringBusFactory会搜索META-INF/cxf(包含在 CXF 的jar中)下的所有bean配置文件。
     * 根据这些配置文件构建一个ApplicationContext。开发者也可以提供自己的配置文件来定制Bus。
     */
    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        return new SpringBus();
    }

    /**
     * 此方法作用是改变项目中服务名的前缀名,此处127.0.0.1或者localhost不能访问时,请使用ipconfig查看本机ip来访问
     * 此方法被注释后, 即不改变前缀名(默认是services), wsdl访问地址为 http://127.0.0.1:8080/services/ws/api?wsdl
     * 去掉注释后wsdl访问地址为:http://127.0.0.1:8080/soap/ws/api?wsdl
     * http://127.0.0.1:8080/soap/列出服务列表 或 http://127.0.0.1:8080/soap/ws/api?wsdl 查看实际的服务
     * 新建Servlet记得需要在启动类添加注解:@ServletComponentScan
     * <p>
     * 如果启动时出现错误:not loaded because DispatcherServlet Registration found non dispatcher servlet dispatcherServlet
     * 可能是springboot与cfx版本不兼容。
     * 同时在spring boot2.0.6之后的版本与xcf集成,不需要在定义以下方法,直接在application.properties配置文件中添加:
     * cxf.path=/service(默认是services)
     */
    //@Bean
    //public ServletRegistrationBean dispatcherServlet() {
    //    return new ServletRegistrationBean(new CXFServlet(), "/soap/*");
    //}
    @Bean
    public Endpoint endpoint() {
        Endpoint endpoint = new EndpointImpl(springBus(), accessService);
        endpoint.publish("/ws/accessApi");
        log.info("---[WebService]---暴露地址为:[http://本机IP:PORT/项目名/services/ws/accessApi?wsdl]");
        return endpoint;
    }

}

3、编写接口
package com.access.service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import java.text.ParseException;

/**
 * @author 微笑
 * @version 1.0
 * @since 2023/2/23 15:41
 */
@WebService(name = AccessService.WEBSERVICE_NAME, targetNamespace = AccessService.TARGET_NAMESPACE)
public interface AccessService {

    String WEBSERVICE_NAME = "AccessService";
    String TARGET_NAMESPACE = "http://service.access.com";
    String WEBSERVICE_INTERFACE_NAME = "com.access.service.AccessService";

    /**
     * 获取标准
     */
    @WebMethod
    String getShuiqiBiaoZhun(@WebParam(name = "param") String param);
}
4、编写实现类
package com.access.service.impl;

import com.access.common.constant.WebServiceConstant;
import com.access.dao.one.AccessShuiqiDao;
import com.access.dao.two.AccessHuaXueDao;
import com.access.dao.two.AccessSystemCheckDao;
import com.access.dto.ChemicalCheApiDto;
import com.access.dto.ChemicalDrugApiDto;
import com.access.dto.ChemicalHydrogenApiDto;
import com.access.entity.AccessAddHydrogenStation;
import com.access.entity.AccessChe;
import com.access.entity.AccessDrug;
import com.access.service.AccessService;
import com.access.util.DateUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.jws.WebService;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * WebService涉及到的有这些 "四解三类 ", 即四个注解,三个类
 *
 * @author shanhy
 * @WebMethod
 * @WebService
 * @WebResult
 * @WebParam SpringBus
 * Endpoint
 * EndpointImpl
 * <p>
 * 一般我们都会写一个接口,然后再写一个实现接口的实现类,但是这不是强制性的
 * @WebService 注解表明是一个webservice服务。
 * name:对外发布的服务名, 对应于<wsdl:portType name="ServerServiceDemo"></wsdl:portType>
 * targetNamespace:命名空间,一般是接口的包名倒序, 实现类与接口类的这个配置一定要一致这种错误
 * Exception in thread "main" org.apache.cxf.common.i18n.UncheckedException: No operation was found with the name xxxx
 * 对应于targetNamespace="http://server.webservice.example.com"
 * endpointInterface:服务接口全路径(如果是没有接口,直接写实现类的,该属性不用配置), 指定做SEI(Service EndPoint Interface)服务端点接口
 * serviceName:对应于<wsdl:service name="ServerServiceDemoImplService"></wsdl:service>
 * portName:对应于<wsdl:port binding="tns:ServerServiceDemoImplServiceSoapBinding" name="ServerServiceDemoPort"></wsdl:port>
 * @WebMethod 表示暴露的服务方法, 这里有接口ServerServiceDemo存在,在接口方法已加上@WebMethod, 所以在实现类中不用再加上,否则就要加上
 * operationName: 接口的方法名
 * action: 没发现又什么用处
 * exclude: 默认是false, 用于阻止将某一继承方法公开为web服务
 * @WebResult 表示方法的返回值
 * name:返回值的名称
 * partName:
 * targetNamespace:
 * header: 默认是false, 是否将参数放到头信息中,用于保护参数,默认在body中
 * @WebParam name:接口的参数
 * partName:
 * targetNamespace:
 * header: 默认是false, 是否将参数放到头信息中,用于保护参数,默认在body中
 * model:WebParam.Mode.IN/OUT/INOUT
 */
@Slf4j
@Service
@WebService(name = AccessService.WEBSERVICE_NAME, targetNamespace = AccessService.TARGET_NAMESPACE,
        endpointInterface = AccessService.WEBSERVICE_INTERFACE_NAME)
public class AccessServiceImpl implements AccessService {

    /**
     * 服务对象
     */
    @Resource
    private AccessShuiqiDao accessShuiqiDao;

    /**
     * reportTableName
     */
    @Override
    public String getShuiqiBiaoZhun(String param) {
        if (StringUtils.isEmpty(param)) {
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(param);
        String reportTableName = jsonObject.get(WebServiceConstant.PARAM1).toString();

        List<Integer> idList = null;
        switch (reportTableName) {
            case "一二期": {
                idList = Arrays.asList(1, 2, 3, 4);
                break;
            }
            case "三期": {
                idList = Arrays.asList(1, 2);
                break;
            }
            case "四期": {
                idList = Arrays.asList(3, 4);
                break;
            }
        }
        List<HashMap<String, String>> biaoZhunList = accessShuiqiDao.getShuiqiBiaoZhun(reportTableName, idList);
        if (CollectionUtils.isEmpty(biaoZhunList)) {
            return null;
        } else {
            return JSON.toJSONString(biaoZhunList);
        }
    }
}

二、客户端

1、引入依赖
        <!--    webservice 我默认和服务端一样,可以只是用最后一个    -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
            <version>3.3.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.1.12</version>
        </dependency>
2、配置
waternet:
  ws:
    wsdlUrl: http://172.10.10.236:8888/accessRead/services/ws/accessApi?wsdl
3、创建客户端
package com.hxlinks.waternet.config;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 水网-WS-单例
 *
 * @author 微笑
 * @version 1.0
 * @since 2023/2/24 15:34
 */
@Data
@Slf4j
@Component
public class WaterWsClient {

    // 注入水网wsdl地址
    @Value(value = "${waternet.ws.wsdlUrl}")
    private String waterAccessWsdlUrl;
    private static String staticWaterAccessWsdlUrl;

    // 静态注入
    @PostConstruct
    private void set() {
        staticWaterAccessWsdlUrl = waterAccessWsdlUrl;
    }

    // 水网-Ws-实例
    private volatile static Client instance;

    // 私有构造,防止调用构造方法来创造实例对象
    private WaterWsClient() {
    }

    // 单例实现,采用双重检索
    public static Client getClient() {

        if (instance == null) {

            synchronized (WaterWsClient.class) {

                if (instance == null) {
                    log.info(">>> WS服务连接...[" + staticWaterAccessWsdlUrl + "]");
                    // 创建动态客户端
                    JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
                    instance = dcf.createClient(staticWaterAccessWsdlUrl);

                }

            }

        }
        return instance;
    }

}

4、创建使用工具类
package com.hxlinks.common.util;

import com.alibaba.fastjson.JSON;
import com.hxlinks.common.exception.CustomException;
import org.apache.cxf.endpoint.Client;

import java.util.Map;

/**
 * @author 微笑
 * @version 1.0
 * @since 2023/2/24 15:50
 */
public class WebServiceUtils{

    public static String getData(Client client, String method, Map<String, Object> params) {
        Object[] objects = new Object[0];
        try {
            objects = client.invoke(method, JSON.toJSONString(params));
            if (objects[0] == null) {
                return null;
            } else {
                return objects[0].toString();
            }
        } catch (java.lang.Exception e) {
            e.printStackTrace();
            throw new CustomException("WebService服务处理异常");
        }
    }

    public static <T> String getData(Client client, String method, T entity) {
        Object[] objects = new Object[0];
        try {
            objects = client.invoke(method, JSON.toJSONString(entity));
            if (objects[0] == null) {
                return null;
            } else {
                return objects[0].toString();
            }
        } catch (java.lang.Exception e) {
            e.printStackTrace();
            throw new CustomException("WebService服务处理异常");
        }
    }

}

5、接口共通
package com.access.common.constant;

/**
 * WS 共通类
 *
 * @author 微笑
 * @version 1.0
 * @since 2023/2/24 16:06
 */
public class WebServiceConstant {

    /**
     * 获取水汽报表的标准接口
     */
    public static final String METHOD1 = "getShuiqiBiaoZhun";
}
6、调用
    public PageInfo<AccessAddHydrogenStation> getAccessBuQingZhanData(ChemicalHydrogenApiDto chemicalHydrogenApiDto) {
        // 查询Access数据
        String dataJsonStr = WebServiceUtils.getData(WaterWsClient.getClient(), WebServiceConstant.METHOD5, chemicalHydrogenApiDto);
        // 将数据转为map List类型
        List<AccessAddHydrogenStation> list = JSON.parseObject(dataJsonStr, new TypeReference<List<AccessAddHydrogenStation>>() {
        });
        return PageUtils.listPage(list, chemicalHydrogenApiDto.getCurrentPage(), chemicalHydrogenApiDto.getDataNumber());
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值