一直在忙項目上的事情,更新的有點兒晚了,今天抽空來說一講在osgi下經過cxf發佈服務,具體能夠參看osgi-http組件。html
http://git.oschina.net/wyuxiao729/osmp/tree/master/osmp-http?dir=1&filepath=osmp-http&oid=c57f2e1633345a9298a42656cf707505f88edf1e&sha=e09ee23dba8ee3ef0239747604f6f1179eae0168java
其實使用在osgi環境下使用cxf發佈服務很是簡單。cxf已經封裝好了jaxws和jaxrs這種原生的ws服務的發佈,實現起來也比較簡單,定義接口,發佈實現就Ok了。在osgi-http本例經過cxf發佈了兩種方式:restful和ws的服務。git
定義接口很簡單,代碼以下:web
接口定義:spring
/* * Project: OSMP * FileName: IRestPlatformTransport.java * version: V1.0 */ package com.osmp.http.transport; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Response; /** * Description:統一服務接口 REST * @author: wangkaiping * @date: 2016年8月9日 上午9:14:42上午10:51:30 */ public interface IRestPlatformTransport { /** * 獲取數據 * @param source 來源 json格式{from:xx} * @param interfaceName 接口名稱,對應服務 * @param parameter 接口參數,對應服務參數 * @return */ public Response data(String source,String interfaceName,String parameter,HttpServletRequest request); /** * 獲取數據 * @param source 來源 json格式{from:xx} * @param interfaceName 接口名稱,對應服務 * @param parameter 接口參數,對應服務參數 * @return */ public Response dataPost(String source,String interfaceName,String parameter,HttpServletRequest request); /** * 提交任務 * @param source 來源 json格式{from:xx} * @param interfaceName 接口名稱,對應服務 * @param parameter 接口參數,對應服務參數 * @return */ public Response task(String source,String interfaceName,String parameter); }
接口實現:apache
/* * Project: OSMP * FileName: RestPlatformTransport.java * version: V1.0 */ package com.osmp.http.transport; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import com.osmp.http.define.ResponseBody; import com.osmp.http.define.RtCodeConst; import com.osmp.http.service.DataServiceProxy; import com.osmp.http.service.ServiceFactoryManager; import com.osmp.http.tool.ExceptionHandleProvider; import com.osmp.intf.define.config.FrameConst; import com.osmp.intf.define.model.InvocationDefine; import com.osmp.intf.define.model.ServiceContext; import com.osmp.utils.base.JSONUtils; import com.osmp.utils.net.RequestInfoHelper; /** * * Description:統一服務接口REST * @author: wangkaiping * @date: 2016年8月9日 上午9:16:20上午10:51:30 */ public class RestPlatformTransport implements IRestPlatformTransport, InitializingBean { private Logger logger = LoggerFactory.getLogger(RestPlatformTransport.class); @POST @Path(value = "/{svcName}") @Produces(MediaType.APPLICATION_JSON) public Response dataPost(@FormParam(FrameConst.SOURCE_NAME) String source, @PathParam("svcName") String interfaceName, @FormParam(FrameConst.PARAMETER_NAME) String parameter, @Context HttpServletRequest request) { return data(source, interfaceName, parameter, request); } @GET @Path(value = "/{svcName}") @Produces(MediaType.APPLICATION_JSON) public Response data(@QueryParam(FrameConst.SOURCE_NAME) String source, @PathParam("svcName") String interfaceName, @QueryParam(FrameConst.PARAMETER_NAME) String parameter, @Context HttpServletRequest request) { return Response.ok().entity("ok") .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); } @GET @Path(value = "/task") @Produces(MediaType.APPLICATION_JSON) public Response task(String source, String interfaceName, String parameter) { return null; } }
在這裏咱們使用jsr註解來定義接口請求類型,接口請求url和接口中mediaType類型json
代碼裏註解restful
@POST 定義請求的類型app
@Path(value="/{svcName}") restful風格請求路徑maven
固然註解也能夠寫在接口上!
因爲這裏只是講解發布restful接口。方法具體實現我已經去掉了,有興趣的能夠去看一下osmp-http裏代碼。
接下來webservice接口:
/* * Project: OSMP * FileName: ISoapPlatformTransport.java * version: V1.0 */ package com.osmp.http.transport; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebService; import com.osmp.http.define.ResponseBody; import com.osmp.intf.define.config.FrameConst; /** * Description:統一服務接口 soap * @author: wangkaiping * @date: 2016年8月9日 上午9:15:42上午10:51:30 */ @WebService(targetNamespace = "osmp.soap") public interface ISoapPlatformTransport { @WebMethod(action = "data", operationName = "data") public ResponseBody data(@WebParam(name=FrameConst.SOURCE_NAME) String source, @WebParam(name=FrameConst.SERVICE_NAME) String interfaceName, @WebParam(name=FrameConst.PARAMETER_NAME) String parameter); }
接口使用jdk原生的 jws註解定義接口的namespace和方法action和 operationName和參數等。具體能夠查看jws和soap協議相關資料。
webservice接口實現:
/* * Project: OSMP * FileName: SoapPlatformTransport.java * version: V1.0 */ package com.osmp.http.transport; import java.util.Map; import javax.jws.WebService; import javax.servlet.http.HttpServletRequest; import org.apache.cxf.message.Message; import org.apache.cxf.phase.PhaseInterceptorChain; import org.apache.cxf.transport.http.AbstractHTTPDestination; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import com.osmp.http.define.ResponseBody; import com.osmp.http.define.RtCodeConst; import com.osmp.http.service.DataServiceProxy; import com.osmp.http.service.ServiceFactoryManager; import com.osmp.intf.define.config.FrameConst; import com.osmp.intf.define.model.InvocationDefine; import com.osmp.intf.define.model.ServiceContext; import com.osmp.utils.base.JSONUtils; import com.osmp.utils.net.RequestInfoHelper; /** * * Description:統一服務接口SOAP * @author: wangkaiping * @date: 2016年8月9日 上午9:17:10上午10:51:30 */ @WebService(portName="port",serviceName="data",endpointInterface = "com.osmp.http.transport.ISoapPlatformTransport") public class SoapPlatformTransport implements ISoapPlatformTransport,InitializingBean{ private Logger logger = LoggerFactory.getLogger(RestPlatformTransport.class); private ServiceFactoryManager serviceFactoryManager; public void afterPropertiesSet() throws Exception { Assert.notNull(serviceFactoryManager,"PlatformServiceTransport property dataServiceManager not set.."); } public void setServiceFactoryManager(ServiceFactoryManager serviceFactoryManager) { this.serviceFactoryManager = serviceFactoryManager; } public ResponseBody data(String source, String interfaceName, String parameter) { Message message = PhaseInterceptorChain.getCurrentMessage(); HttpServletRequest request = (HttpServletRequest)message.get(AbstractHTTPDestination.HTTP_REQUEST); String ip = RequestInfoHelper.getRemoteIp(request); System.out.println("requstId:"+request.getAttribute(FrameConst.CLIENT_REQ_ID)); System.out.println("ip:"+ip); ResponseBody res = new ResponseBody(); // 獲取對應服務 InvocationDefine define = serviceFactoryManager.getInvocationDefine(interfaceName); if (define == null) { res.setCode(RtCodeConst.ERR_CODE); res.setMessage("未找到服務"); logger.warn("未找到服務..."); return res; } // 接口參數驗證 Map<String, String> sourceMap = JSONUtils.jsonString2Map(source); if (sourceMap == null || sourceMap.get(FrameConst.CLIENT_FROM) == null) { res.setCode(RtCodeConst.ERR_CODE); res.setMessage("接口參數非法"); logger.warn("接口參數非法..."); return res; } sourceMap.put(FrameConst.CLIENT_IP, ip); // 調用服務 ServiceContext serviceContext = new ServiceContext(sourceMap, interfaceName, parameter); DataServiceProxy serviceProxy = new DataServiceProxy(define, serviceContext); Object result = serviceProxy.execute(); res.setCode(RtCodeConst.SUCC_CODE); res.setData(result); return res; } }
完成接口定義和實現後。咱們能夠經過cxf將此接口暴露爲服務供外部調用。
能夠經過spring的方式或者buleprint的方式。在這裏我爲兼容使用spring的方式。配置文件以下:
<?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:context="http://www.springframework.org/schema/context" xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xsi:schemaLocation="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-3.0.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd"> <cxf:bus> <cxf:inInterceptors> <ref bean="requestParser"/> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean> </cxf:inInterceptors> <cxf:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean> </cxf:outInterceptors> </cxf:bus> <bean id="webserver" class="com.osmp.http.transport.RestPlatformTransport"> </bean> <bean id="soapServer" class="com.osmp.http.transport.SoapPlatformTransport"> </bean> <bean id="objectMapper" class="com.osmp.http.tool.DefaultObjectMapper"></bean> <jaxrs:server id="restServiceContainer" address="/service"> <jaxrs:serviceBeans> <ref bean="webserver" /> </jaxrs:serviceBeans> <jaxrs:providers> <bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"> <constructor-arg index="0" ref="objectMapper"></constructor-arg> </bean> </jaxrs:providers> <jaxrs:extensionMappings> <entry key="json" value="application/json" /> </jaxrs:extensionMappings> <jaxrs:languageMappings> <entry key="en" value="en-gb" /> </jaxrs:languageMappings> </jaxrs:server> <jaxws:server id="soapServiceContainer" address="/soap"> <jaxws:serviceBean> <ref bean="soapServer" /> </jaxws:serviceBean> </jaxws:server> </beans>
到此爲止,代碼部分完成。若是是傳統的j2ee的項目。能夠直接經過http://ip:port/cxf來訪問了。
那麼在osgi的環境下咱們怎樣發佈呢,這裏其實也很簡單,我使用的是servicemix做爲容器。其自己已經集成了cxf,咱們直接打成bundle部署就ok了,若是是karaf或原生的felix那就比較麻煩點兒,須要先安裝cxf-bundle的依賴支持,這裏不做說明,你們有空本身去研究!
這裏pom須要依賴的jar包爲
<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-bundle</artifactId> </dependency> <dependency> <groupId>org.springframework.osgi</groupId> <artifactId>spring-osgi-core</artifactId> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.core</artifactId> </dependency>
使用maven插件構建bundle須要使用 maven-bundle-plgin插件,在這裏咱們能夠定義導入,導出package,bundle內嵌jar包等設置。詳細設置見:
http://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html
完整的pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-parent</artifactId> <version>1.0.0</version> </parent> <artifactId>osmp-http</artifactId> <packaging>bundle</packaging> <name>osmp-http</name> <properties> <maven.test.skip>true</maven.test.skip> </properties> <build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> <configuration> <instructions> <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName> <DynamicImport-Package>*;resolution:=optional</DynamicImport-Package> <Import-Package>com.osmp.intf.define.config, com.osmp.intf.define.interceptor, com.osmp.intf.define.model, com.osmp.intf.define.factory, com.osmp.intf.define.service, com.osmp.utils.net, com.osmp.utils.base</Import-Package> <Embed-Dependency>jackson-jaxrs,jackson-xc</Embed-Dependency> </instructions> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-intf-define</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-resource</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-tools</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-utils</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>com.osmp.baseweb</groupId> <artifactId>osmp-log</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.osgi</groupId> <artifactId>spring-osgi-core</artifactId> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.core</artifactId> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-jaxrs</artifactId> <version>1.9.13</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-xc</artifactId> <version>1.9.13</version> </dependency> </dependencies> </project>
打出來的jar包是bundle類型。能夠跑在osgi環境下。
在servicemix環境訪問:http://ip:8181/cxf 能夠看到咱們定義好的restful接口和soap接口
cxf默認訪問根路徑是cxf 能夠經過servicemix配置修改
快下班了,先寫到這兒吧,其實發佈一個cxf的restful和soap仍是很是簡單,網上例子一大把,若是在osgi環境下部署。建議使用karaf或者servicemix。