Webservice+CXF 自动发布接口(包含注意事项)

1.pom依赖

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
    <version>${cxf.version}</version>
</dependency>

2.发布地址接口(用作标记)

public interface WebServices {
    //发布地址
    @WebMethod(exclude = true)
    String getUrl();
}

3.发布接口的类:

@WebService(serviceName = "SceneInvestApiService",
        targetNamespace = "http://service.investment.api.openapi.bi.com/")
@XmlSeeAlso(value = {RetireAgeQry.class,AssetPaymentQry.class, AssetInfoQry.class, ProductInfoQry.class,
        PensionLevelDTO.class,InvestmentAdviceDto.class,InvestmentAdviceQry.class, ArrayList.class})
public interface SceneInvestApiService extends WebServices {
    /**
     *
     * @param request 期望退休金试算请求实体
     * @return 期望退休金试算返回实体
     */
    @WebMethod
    APIResult<ExpectAmountRes> expectAmountAnalyse(@WebParam(name = "request",targetNamespace = "http://service.investment.api.openapi.bi.com/", mode = WebParam.Mode.IN) ExpectAmountReq request);

    /**
     *
     * @param request 养老资金缺口请求体
     * @return 养老资金缺口试算返回实体
     */
    @WebMethod
    APIResult<PensionGapRes> pensionGapAnalyse(@WebParam(name = "request",targetNamespace = "http://service.investment.api.openapi.bi.com/",mode = WebParam.Mode.IN) PensionGapReq request);
}

4.实现类:

@Slf4j
@Service("sceneInvestApiService")
@WebService(serviceName = "SceneInvestApiService",
        targetNamespace = "http://service.investment.api.openapi.bi.com/",
        endpointInterface = "com.bi.openapi.api.investment.service.SceneInvestApiService")
public class SceneInvestApiServiceImpl implements SceneInvestApiService {
	 @Override
    public APIResult<ExpectAmountRes> expectAmountAnalyse(@WebParam(name = "request",targetNamespace = "http://service.investment.api.openapi.bi.com/", mode = WebParam.Mode.IN) ExpectAmountReq request) {
        return APIResult.ok();
    }

    @Override
    public APIResult<PensionGapRes> pensionGapAnalyse(@WebParam(name = "request",targetNamespace = "http://service.investment.api.openapi.bi.com/", mode = WebParam.Mode.IN) PensionGapReq request) { 
        return APIResult.ok();
    }
}

5.自动发布:

/**
 * @Author: K.Chan
 * @Date: Created in 14:17 2022/7/12
 * @Description: open-api自动发布接口启动类  需要发布的接口写到openapi模块中,实现{@link WebServices} 接口,重写地址即可。
 * @attention: 发布时,入参和返回参数如果是内部类 不能是三层复杂参数。 内部类尽量放到外面引用 最好不要用 public static class className{}
 */
@Slf4j
@Component
public class AutoPublishBoot implements CommandLineRunner {

    @Autowired
    private SpringBus springbus;
    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public ServletRegistrationBean<CXFServlet> cxfServlet() {
        //发布地址前缀
        return new ServletRegistrationBean<>(new CXFServlet(), TOTAL_PATH);
    }

    @Override
    public void run(String... args) throws Exception {
        log.info("--------------自动发布开始--------");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        log.info("--------------开始发布时间 :{}--------", sdf.format(new Timestamp(System.currentTimeMillis()).getTime()));
        try {
            //获取所有需要发布的bean
            Map<String, WebServices> beansOfType = applicationContext.getBeansOfType(WebServices.class);
            //用来标记注入endpoint的名称
            int count = 1;
            for (Map.Entry<String, WebServices> entry : beansOfType.entrySet()) {
                //获取发布地址
                String publishPath = entry.getValue().getUrl();
                Endpoint endpoint = new EndpointImpl(springbus, entry.getValue());
                log.info("[{}]:发布成功!",entry.getKey());
                SpringUtil.registerBean(entry.getKey() + count, endpoint);
                //发布接口
                endpoint.publish(publishPath);
                count++;
            }
            log.info("--------------自动发布结束--------");
            log.info("--------------发布结束时间 :{}--------", sdf.format(new Timestamp(System.currentTimeMillis()).getTime()));
        } catch (Exception e) {
            throw new BIRuntimeException(String.format("webService动态发布失败![%s]", e.getMessage()));
        }
    }
}

6.发布结果:

在这里插入图片描述

7.SoapUI工具测试:

Webservice+CXF 自动发布接口(包含注意事项)_第1张图片
上图中wealthservice是自动发布时的前缀。如果不写就是CXF自带的services/* ;srcb是你需要发布接口的实现类重写的地址;
通过http://ip:port/wealthservice/srcb?wsdl 在SoapUI中调用就可以看到发布的接口了

8.注意事项:(Marshalling Error: class nor any of its super class is known to this context)

在这里插入图片描述
如果出现这种问题:那就是跨包问题导致类无法在webservice调用时透明。需要在接口类上加上注解然后里面加上报错信息中的类对象。

@WebService(serviceName = "SceneInvestApiService",
        targetNamespace = "http://service.investment.api.openapi.bi.com/")
@XmlSeeAlso(value = {RetireAgeQry.class,AssetPaymentQry.class, AssetInfoQry.class, ProductInfoQry.class,
        PensionLevelDTO.class,InvestmentAdviceDto.class,InvestmentAdviceQry.class, ArrayList.class})
public interface SceneInvestApiService extends WebServices {

问题解决后:再请求(如有更好的办法请指正)
Webservice+CXF 自动发布接口(包含注意事项)_第2张图片

你可能感兴趣的:(java,spring,boot,spring)