您的位置:首页 > 其它

[置顶] osgi实战项目(osmp)一步一步玩转osgi之cxf发布服务(3)

2017-03-29 16:57 423 查看
一直在忙项目上的事情,更新的有点儿晚了,今天抽空来讲一讲在osgi下通过cxf发布服务,具体可以参看osgi-http组件。
http://git.oschina.net/wyuxiao729/osmp/tree/master/osmp-http?dir=1&filepath=osmp-http&oid=c57f2e1633345a9298a42656cf707505f88edf1e&sha=e09ee23dba8ee3ef0239747604f6f1179eae0168
 

其实使用在osgi环境下使用cxf发布服务非常简单。cxf已经封装好了jaxws和jaxrs这种原生的ws服务的发布,实现起来也比较简单,定义接口,发布实现就Ok了。在osgi-http本例通过cxf发布了两种方式:restful和ws的服务。

 

定义接口很简单,代码如下:

接口定义:

 

 

/*
* 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);
}

 

 

接口实现:

 

 

/*
* 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类型

代码里注解

@POST 定义请求的类型

@Path(value="/{svcName}")  restful风格请求路径

@Produces(MediaType.APPLICATION_JSON) 定义请求数据的提交方式为JSON方式,如果需要支持多种提交方式。这个地方可以不写直接默认*,默认是支持所有提交方式。
 

 当然注解也可以写在接口上!

 

由于这里只是讲解发布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
c096
>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。

 

 

 





大小: 19.7 KB




大小: 436.4 KB




大小: 176.9 KB
查看图片附件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: