最近工做中须要作产品之间的对接工做,做为服务器端对外开放服务接口,而本次所采用的是webservice开放接口。在选择使用何种技术开放接口,曾考虑使用http开放接口,最终选择webservice缘由有:一、此接口非网络公开接口,只适用于本次产品对接。二、webservice接口稳定且支持跨域,使用http还要考虑跨域的问题。三、webservice支持复杂类型的数据传输。基于此,选用webservice开放接口。java
考虑到简化webservice开发过程,在开发中并未对每一个功能开放webservice接口,而是依赖于接口文档,开放统一的webservice接口,用业务编号区分不一样的接口,统一调用。如下是开发过程:web
一、导入依赖包(cxf)spring
<apache.cxf.version>3.1.10</apache.cxf.version> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>${apache.cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>${apache.cxf.version}</version> </dependency>
二、配置服务(web.xml)apache
<!-- cxf --> <servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/webservice/*</url-pattern> </servlet-mapping>
三、配置spring自动扫描json
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd" default-autowire="byName"> <!-- spring自动扫包 --> <context:component-scan base-package="com.my.webservice" /> <bean id="myWebServiceExcuteUtil" class="com.my.webservice.utils.MyWebServiceExcuteUtil" init-method="init" lazy-init="default"></bean> <bean id="MyWebService" class="com.my.webservice.impl.MyWebServiceImpl"> </bean> <!-- 导入jar包中的cxf配置文件。这里不用写,是写好的放在jar包里,直接引入便可。 --> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <!-- define web service provider --> <!-- 要暴露给外部调用的接口,address:请求路径 --> <jaxws:endpoint implementor="com.my.webservice.impl.TestWebServiceImpl" address="/testWebServiceImpl" /> <jaxws:endpoint implementor="com.my.webservice.impl.MyWebServiceImpl" address="/myWebServiceImpl" /> </beans>
四、编写webservice接口及实现类跨域
/** * $Id:$ * Copyright 2014-2018 Hebei Sinounited Technology Company Ltd. All rights reserved. */ package com.my.webservice; import javax.jws.WebParam; import javax.jws.WebService; /** * * @author Heller.Zhang * @since 2018年11月1日 下午5:30:02 */ @WebService(targetNamespace = "com.my.webservice.TestWebService") public interface TestWebService { public String test(@WebParam(name = "type") Integer type, @WebParam(name = "data") String data); }
/** * $Id:$ * Copyright 2014-2018 Hebei Sinounited Technology Company Ltd. All rights reserved. */ package com.my.webservice.impl; import javax.jws.WebService; import org.springframework.stereotype.Component; import com.my.webservice.TestWebService; /** * * @author Heller.Zhang * @since 2018年11月1日 下午5:12:08 */ @WebService(targetNamespace="com.my.webservice.TestWebService",endpointInterface="com.my.webservice.TestWebService") @Component("TestWebService") public class TestWebServiceImpl implements TestWebService { @Autowired private MyWebServiceExcuteUtil myWebServiceExcuteUtil; @Override public String test(Integer type, String data) { return myWebServiceExcuteUtil.excute(type, data); } }
/** * $Id:$ * Copyright 2014-2018 Hebei Sinounited Technology Company Ltd. All rights reserved. */ package com.my.webservice.utils; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import com.my.webservice.contant.GpWebServiceEnum; import com.my.webservice.model.MyWebServiceModel; import com.my.framework.common.spring.utils.SpringContextUtils; import com.my.framework.exception.DaoException; import com.my.framework.exception.ManagerException; import com.my.framework.exception.ServiceException; import com.my.framework.model.ResultDTO; import com.my.framework.util.JsonHelper; /** * webservice调用统一工具类 * * @author Heller.Zhang * @since 2018年11月2日 上午9:30:04 */ public class MyWebServiceExcuteUtil { Logger logger = LoggerFactory.getLogger(MyWebServiceExcuteUtil .class); Map<Integer, MyWebServiceModel> map = new HashMap<Integer, MyWebServiceModel>(); /** * 初始化 * * @author Heller.Zhang * @since 2018年11月2日 下午12:48:07 */ public void init() { logger.debug("-------------init MyWebServiceExcuteUtil-----------------"); for (MyWebServiceEnume : MyWebServiceEnum.values()) { MyWebServiceModelmodel = new MyWebServiceModel(); model.setType(e.getType()); Object bean = SpringContextUtils.getBean(e.getBean()); model.setBean(bean); Class<?> dataType = null; try { dataType = Class.forName(e.getDataType()); model.setDataClass(dataType); } catch (ClassNotFoundException e1) { throw new RuntimeException("未找到【" + e.getDataType() + "】实体类!", e1); } Method method = BeanUtils.findMethod(bean.getClass(), e.getMethod(), new Class[] { dataType}); model.setMethod(method); map.put(e.getType(), model); } } /** * webservice接口调用 * * @param type 业务类型 * @param data 数据 * @return * @author Heller.Zhang * @since 2018年11月2日 上午9:32:52 */ public String excute(Integer type, String data) { // 获取到webservice配置信息 MyWebServiceModel model = map.get(type); if (model == null) { ResultDTO<Object> faildResult = new ResultDTO<Object>(); faildResult.setSuccess(false); faildResult.setMsg("错误的业务编号!"); return JsonHelper.serialize(faildResult); } // 将data转换为相应类型的数据 Object dataObj = JsonHelper.readValueCustom(data, model.getDataClass()); // 调用方法 try { Object result = model.getMethod().invoke(model.getBean(), dataObj); return JsonHelper.serialize(result); } catch (ServiceException | ManagerException | DaoException e) { logger.error(e.getMessage(), e); ResultDTO<Object> faildResult = new ResultDTO<Object>(); faildResult.setSuccess(false); faildResult.setMsg(e.getMessage()); return JsonHelper.serialize(faildResult); } catch (Exception e1) { logger.error("调用webservice接口失败!", e1); ResultDTO<Object> faildResult = new ResultDTO<Object>(); faildResult.setSuccess(false); faildResult.setMsg("调用webservice接口失败!"); return JsonHelper.serialize(faildResult); } } }
/** * $Id:$ * Copyright 2014-2018 Hebei Sinounited Technology Company Ltd. All rights reserved. */ package com.my.webservice.contant; /** * 业务及实现对应枚举 * * @author Heller.Zhang * @since 2018年11月2日 上午9:34:51 */ public enum MyWebServiceEnum { SERVICE1(0, "*****Impl", "******", "com.my.qo.******"),// NL,因涉及业务,故以*代替具体配置 ; /** 业务编号 */ private Integer type; /** 业务实现类(必须是业务模块的service bean名称) */ private String bean; /** 业务实现方法名称 */ private String method; /** 接收数据类型(全称) */ private String dataType; MyWebServiceEnum(Integer type, String bean, String method, String dataType) { this.type = type; this.bean = bean; this.method = method; this.dataType = dataType; } /** * @return the type */ public Integer getType() { return type; } /** * @param type the type to set */ public void setType(Integer type) { this.type = type; } /** * @return the bean */ public String getBean() { return bean; } /** * @param bean the bean to set */ public void setBean(String bean) { this.bean = bean; } /** * @return the method */ public String getMethod() { return method; } /** * @param method the method to set */ public void setMethod(String method) { this.method = method; } /** * @return the dataType */ public String getDataType() { return dataType; } /** * @param dataType the dataType to set */ public void setDataType(String dataType) { this.dataType = dataType; } public static MyWebServiceEnum of(Integer type) { for (MyWebServiceEnum e : MyWebServiceEnum .values()) { if (e.getType().equals(type)) { return e; } } return null; } }
以上,便将webservice配置完成并与springMVC相结合,在定义业务实现时,须要遵循必定的规则(由于依赖于接口文档,因此须要必定的开发规则),如:入参类型、出参类型、解析方式等。上述例子中对外接口使用业务编号的方式指定不一样的业务接口调用,数据传输使用json格式字符串进行序列化和反序列化。webservice接口使用统一接口。服务器
webservice地址能够配置多个,同时每个webservice地址下能够有多个webservice接口,本例只提供了一个接口test,以上接口结构适合于接口参数、返回数据的格式一致且接口数量较多的状况,依赖于webservice接口文档用以对接,因此对文档的严谨和准确性要求较高。若是接口量很少,或者接口参数、返回数据的格式大多不一致的状况下,可以使用开放多接口的形式,在webservice实现类中直接调用业务实现方法,作到一个webservice接口对应一个业务方法的结构。网络
结语:webservice是对外开放服务接口的一种方式,在技术选型、模式选型时不必生搬硬套,适合项目的才是最好的。app