最近一直开发一个webservice的接口,由于是第一次接触webservice,而且还是在结合spingBoot和CXF框架的情况下开发的,所以刚开始有点懵逼,遇到了各种问题。但是,终究还是完成了,以此分享一下我的开发过程。
根据项目使用的构建工具,添加相应的jar包,因为我的项目用到是gradle,添加依赖如下:
compile group: 'org.apache.cxf', name: 'cxf', version: '2.7.6' 复制代码
接口目录结构如下:
@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 教程
@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; } } } 复制代码
代码已经完了,接下来就是启动项目,访问服务。我的服务发布成功之后如下所示:
以上内容就是我开发webservice接口的全部过程,希望对大家有所帮助,谢谢!