转载

springBoot+CXF开发webservice服务

最近一直开发一个webservice的接口,由于是第一次接触webservice,而且还是在结合spingBoot和CXF框架的情况下开发的,所以刚开始有点懵逼,遇到了各种问题。但是,终究还是完成了,以此分享一下我的开发过程。

开发流程

添加CXF依赖

根据项目使用的构建工具,添加相应的jar包,因为我的项目用到是gradle,添加依赖如下:

compile group: 'org.apache.cxf', name: 'cxf', version: '2.7.6'
复制代码

接口目录结构如下:

springBoot+CXF开发webservice服务

实体类

请求实体类:

@XmlRootElement(name = "ReceiveDisposalPlanMassageRequest")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ReceiveDisposalPlanMassageRequest", propOrder = {
        "year",
        "disposalNumber",
        "planName",
        "planCode",
        "orgId",
        "orgName",
        "estimateAmount",
        "baseAmount",
        "fillUserId",
        "fillUserName",
        "remark",
        "billType",
        "dataAreaName",
        "creatorId",
        "creator",
        "auctionMaterialList",
        "disposalPlanAttachmentList"
})
public class ReceiveDisposalPlanMassageRequest {

    @XmlElement(required = true)
    private String year;//年度

    @XmlElement(required = true)
    private String disposalNumber;//处置批次号

    @XmlElement(required = true)
    private String planName;//处置计划名称

    @XmlElement(required = true)
    private String planCode;//处置计划编号

    @XmlElement(required = true)
    private String orgId;//物资所属单位ID

    @XmlElement(required = true)
    private String orgName;//物资所属单位名称

    @XmlElement(required = true)
    private Double estimateAmount;//预估金额

    @XmlElement(required = true)
    private Double baseAmount;//底价

    @XmlElement(required = true)
    private String fillUserId;//填报人ID

    @XmlElement(required = true)
    private String fillUserName;//填报人

    @XmlElement(required = false)
    private String remark;//备注

    @XmlElement(required = true)
    private String billType;//登记类型

    @XmlElement(required = true)
    private String dataAreaName;//产权持有单位

    @XmlElement(required = true)
    private String creatorId;//制单人ID

    @XmlElement(required = true)
    private String creator;//制单人

    @XmlElement(required = true)
    private List<AuctionMaterial> auctionMaterialList;//物资明细列表

    @XmlElement(required = true)
    private List<SyncAttachmentVO> disposalPlanAttachmentList;//附件列表
    //省略set,get方法
}
复制代码

返回值类:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SoaResponse", propOrder = {
    "status",
    "message"
})
public class SoaResponse {
    @XmlElement(nillable = true)
    protected int status;  //同步结果
    @XmlElement(nillable = true)
    protected String message; //返回信息
    //省略set,get方法
}
复制代码

关于@XmlAccessorType,@XmlType,@XmlElement相关注解的用处,可以参考以下教程: JABX 教程

springBoot+CXF开发webservice服务

接口

@WebService(name = "ReceiveDisposalPlanMassageSer",targetNamespace = Constants_soa.NAME_SPACE)
public interface ReceiveDisposalPlanMassageFacade {

    @WSDLDocumentation("接收处置计划信息")
    @WebResult(name = "receiveDisposalPlanMassageResponse", targetNamespace = Constants_soa.NAME_SPACE)
    @RequestWrapper(localName = "request")
    @ResponseWrapper(localName = "response")
    @WebMethod()
    public SoaResponse receiveDisposalPlanMassage(@WebParam(name = "receiveDisposalPlanMassageRequest", targetNamespace = Constants_soa.NAME_SPACE)ReceiveDisposalPlanMassageRequest receiveDisposalPlanMassageRequest) throws SoaFault;
}
复制代码

接口实现

@WebService(name = "ReceiveDisposalPlanMassageSer",targetNamespace = Constants_soa.NAME_SPACE)
@Component("ReceiveDisposalPlanMassageSer")
public class ReceiveDisposalPlanMassageFacadeImpl implements ReceiveDisposalPlanMassageFacade {

    private static final Logger logger = LoggerFactory.getLogger(ReceiveDisposalPlanMassageFacadeImpl.class);
    @Autowired
    private DisposalPlanFacade disposalPlanFacade;
    @Autowired
    private AuctionMaterialFacade auctionMaterialFacade;
    @Autowired
    private AttachmentFacade attachmentFacade;

    @Override
    public SoaResponse receiveDisposalPlanMassage(ReceiveDisposalPlanMassageRequest request)throws SoaFault {

        SoaResponse response = new SoaResponse();

        try {
            if (request != null) {
            //此处省略业务代码
            }
            response.setStatus(0);
            response.setMessage("ok");
        }catch (Exception e){
            logger.error("服务器发生未知异常!" + e.getMessage());
            response.setStatus(-1);
            response.setMessage(e.getMessage());
        }
        return response;
    }
}
复制代码

服务发布工具类

@Configuration
public class CxfConfig {
    private static final Logger logger = LoggerFactory.getLogger(CxfConfig.class);

    private String scanPath = "xxx";//此处是接口所在的包路径

    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        SpringBus bus = new SpringBus();
        // 日志打印
        bus.getInInterceptors().add(new LoggingInInterceptor());
        bus.getOutInterceptors().add(new LoggingOutInterceptor());
        return bus;
    }

    /**
     * 发布服务名称
     * 访问该路径可以查看发布的服务
     * @return
     */
    @Bean
    public ServletRegistrationBean disServlet() {
        return new ServletRegistrationBean(new CXFServlet(), "/webservice/*");
    }

    @Bean
    @ConditionalOnMissingBean
    public WadlGenerator wadlGenerator() {
        WadlGenerator wadlGenerator = new WadlGenerator();
        return wadlGenerator;
    }

    @Bean
    @ConditionalOnMissingBean
    public ObjectMapper objectMapper() {
        return new ObjectMapper();
    }

    @Bean
    @ConditionalOnMissingBean
    public JacksonJsonProvider jsonProvider(ObjectMapper objectMapper) {
        JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider();
        provider.setMapper(objectMapper);
        return provider;
    }

    @Bean
    @ConditionalOnMissingBean
    public JAXBElementProvider xmlProvider() {
        return new JAXBElementProvider();
    }

    /*
     * 使用cxf发布soap服务
     * */
    @Bean
    public List<Endpoint> endpoints(ApplicationContext ctx) {
        ArrayList<Endpoint> endpoints = new ArrayList<Endpoint>();
        try {
            //从spring上下文里获取含有WebService注解的对象
            List<Object> serviceBeans = new ArrayList<Object>(ctx.getBeansWithAnnotation(WebService.class).values());
            if (ListUtils.isEmpty(serviceBeans)) {
                logger.info("serviceBeans is empty");
                return endpoints;
            }
            EndpointImpl endpoint = null;
            //遍历serviceBeans 发布soap接口
            for (Object webService : serviceBeans) {
                String webServiceClassName = webService.getClass().getName();
                boolean startsWith = webServiceClassName.startsWith(scanPath);
                logger.info("SOAP endpoints:/nwebServiceClassName:{}/nscanPath:{}/nwebServiceClassName.startsWith(scanPath):{}",webServiceClassName,scanPath,startsWith);

                if (startsWith) {
                    WebService annotation = AnnotationUtils.findAnnotation(webService.getClass(),WebService.class);
                    if (annotation == null){
                        continue;
                    }
                    String name = annotation.name();
                    if (StringUtil.isEmpty(name)) {
                        name = annotation.serviceName();
                    }
                    if (StringUtil.isEmpty(name)) {
                        logger.error("webservice " + webService.getClass().getSimpleName() + " 实现类没有 @WebService(name='xxx') 的注解");
                        continue;
                    }
                    endpoint = new EndpointImpl(springBus(), webService);
                    endpoint.publish("/" + name);
                    endpoints.add(endpoint);
                }
            }
        } catch (Exception e) {
            logger.error("cxf soap error……");
            logger.error(e.getMessage(), e);
        }
        return endpoints;
    }


    /*
     * 发布rest
     * */
    @Bean
    @ConditionalOnMissingBean
    public Server jaxRsServer(ApplicationContext ctx) {
        try {
            List<Object> serviceBeans = new ArrayList<Object>(ctx.getBeansWithAnnotation(Path.class).values());
            if(ListUtils.isEmpty(serviceBeans)){
                logger.info("found serviceBeans is empty in spring application context.");
                return null;
            }
            logger.info("serviceBeans:{}",serviceBeans.size());
            Iterator<Object> iterator = serviceBeans.iterator();
            while (iterator.hasNext()) {
                Object next = iterator.next();

                String serviceBeanClassName = next.getClass().getName();
                boolean startsWith = serviceBeanClassName.startsWith(scanPath);
                logger.info("REST endpoints:/nserviceBeanClassName:{}/nscanPath:{}/nwebServiceClassName.startsWith(scanPath):{}",serviceBeanClassName,scanPath,startsWith);
                if (!startsWith) {
                    iterator.remove();
                }
            }
            if (ListUtils.isEmpty(serviceBeans)){
                logger.info("found serviceBeans is empty in {}.",scanPath);
                return null;
            }
            logger.info("serviceBeans:{}",serviceBeans.size());
            List<Object> providers = new ArrayList<Object>(ctx.getBeansWithAnnotation(Provider.class).values());
            providers.add(wadlGenerator());

            Map<Object, Object> extensionMappings = new HashMap<>();
            extensionMappings.put("xml", "application/xml");
            extensionMappings.put("json", "application/json");

            JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();
            factory.setBus(springBus());
            factory.setAddress("/rest");
            factory.setServiceBeans(serviceBeans);
            factory.setProviders(providers);
            factory.setExtensionMappings(extensionMappings);
            Server server = factory.create();
            return server;
        } catch (Exception e) {
            logger.error("cxf rest error……");
            logger.error(e.getMessage(), e);
            return null;
        }
    }
}
复制代码

代码已经完了,接下来就是启动项目,访问服务。我的服务发布成功之后如下所示:

  • 服务接口对应的方法:
    springBoot+CXF开发webservice服务
  • wsdl文档:
springBoot+CXF开发webservice服务

结语

以上内容就是我开发webservice接口的全部过程,希望对大家有所帮助,谢谢!

原文  https://juejin.im/post/5dd3b9426fb9a020013d78ee
正文到此结束
Loading...