osgi實戰項目(osmp)一步一步玩轉osgi之cxf發佈服務(3)

一直在忙項目上的事情,更新的有點兒晚了,今天抽空來說一講在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

@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>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。

相關文章
相關標籤/搜索