springBoot + CXF webservice development services

Foreword

It has recently been developed a webservice interface, because it is the first contact webservice, but also the development in the case of combination spingBoot and CXF framework, it is the beginning of a bit ignorant force, encountered various problems. But, after all, is complete, in order to share my development process.

Development Process

Add CXF dependence

According to the project build tool to use, add the appropriate jar package, because my project is to use gradle, adding a dependency as follows:

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

Interface directory structure is as follows:

Interface Directory Structure

Entity class

Requesting entity classes:

@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方法
}
复制代码

Return value categories:

@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方法
}
复制代码

About @ XmlAccessorType, @ XmlType, @ XmlElement annotations related to use, you can refer to the following tutorial: JABX Tutorial

interface

@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;
}
复制代码

Interface

@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;
    }
}
复制代码

Service Publishing Tools

@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;
        }
    }
}
复制代码

The code is done, the next step is to start the project, access to the service. After the successful release of my service as follows:

  • Service interface corresponding method:
  • wsdl document:

Epilogue

Above is my entire process of development webservice interface, we want to help, thank you!

Guess you like

Origin juejin.im/post/5dd3b9426fb9a020013d78ee