Apache Camel - 25 - CXF - WebService(Code First)

本篇文章对应的完整项目源码地址:

15-ApacheCamel-CXF-Demo-Server(Code First)

16-ApacheCamel-CXF-Demo

_16-ApacheCamel-CXF-Demo-Client

"15-ApacheCamel-CXF-Demo-Server(Code First)" 是参照官方Demo例子写的:https://github.com/apache/camel/tree/master/examples/camel-example-cxf

"16-ApacheCamel-CXF-Demo" 是根据日常最简原则写的Demo。

 

Apache Camel 相关所有Demo代码,已上传GitHub,需要的请自取:GitHub - Apache Camel 完整Demo

如果觉得还不错,请点star

 

前言

首先假定,你是使用过Apache CXF 或者 WebService的,如不了解,请先移步 WebService(Apache CXF)分享。

如果你之前看过Apache Camel 集成 CXF的前两篇:

Apache Camel - 14 - CXF组件、Apache Camel - 15 - CXF组件(2)

你会发现,其中的Demo样例,都是基于WSDL文件来发布WebService的。

因为在此之前,没有在官方Demo中找到,也有可能是我看走眼了没有发现(心塞...)。

言归正传,下面看下基于代码优先方式发布WebService

 

 

Apache Camel 集成 Apache CXF 发布WebService,基于代码优先的方式

这里先介绍下WebService(CXF)服务端发布的两种方式:基于WSDL方式 和 纯代码方式

  • 基于WSDL方式:这种方式一般情况是第三方给你一个WSDL文档,然后你根据这个WSDL文档生成服务端代码,JDK原生的我并没有试过,我之前用的都是CXF的命令方式生成的服务端代码,然后在开发业务代码,启动服务端,发布WebService
  • 纯代码方式:这种方式是最原始的方式,也是字面意思,只要你写过WebService,就一定能理解,参考:WebService(3)_开发流程(原生/JDK自带工具)

Apache Camel 集成 CXF 也是可以用以上两种方式来发布WebService,可惜之前我只找到基于WSDL的,可能是我英文不好,错过了。

下面看下关键代码:

pom.xml


        
            org.apache.camel
            camel-core
            2.22.0
        

        
            org.apache.camel
            camel-jetty
            2.22.0
        

        
            org.apache.camel
            camel-cxf
            2.22.0
        

        
        
            org.apache.cxf
            cxf-rt-transports-http-jetty
            3.2.5
        

        
        
            ch.qos.logback
            logback-core
            1.2.3
        

        
            ch.qos.logback
            logback-access
            1.2.3
        

        
            ch.qos.logback
            logback-classic
            1.2.3
        

        
        
            commons-lang
            commons-lang
            2.6
        

        
            org.apache.commons
            commons-lang3
            3.7
        

        
            org.apache.commons
            commons-collections4
            4.1
        

        
            commons-collections
            commons-collections
            3.2.2
        

        
            commons-io
            commons-io
            2.6
        

发布的接口,就像开发普通WebService一样,添加@WebService以及@WebMethod注解

package com.server.service;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

/**
 * @author CYX
 * @create 2018-12-27-19:59
 */
@WebService
public interface BaseicQuery {

    /**
     * 查询人员信息
     *
     * @param queryCondition 基础查询
     * @return
     */
    @WebMethod
    String queryPeopleInfo(@WebParam(name = "queryCondition") String queryCondition);

}

发布接口的实现类

package com.server.service.impl;

import com.server.service.BaseicQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author CYX
 * @create 2018-12-27-20:00
 */
public class BaseicQueryImpl implements BaseicQuery {

    private static final Logger LOGGER = LoggerFactory.getLogger(BaseicQueryImpl.class);

    @Override
    public String queryPeopleInfo(String queryCondition) {

        LOGGER.info("queryCondition : " + queryCondition);

        return "copy that";
    }
}

路由的process处理类:

package com.server.process;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.component.cxf.common.message.CxfConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
 * @author CYX
 * @create 2018-12-27-20:36
 */
public class BaseicQueryProcess implements Processor {

    private static final Logger LOGGER = LoggerFactory.getLogger(BaseicQueryProcess.class);

    private Class beanClass;
    private Object instance;

    public BaseicQueryProcess(Object object) {
        beanClass = object.getClass();
        instance = object;
    }

    @Override
    public void process(Exchange exchange) throws Exception {

        String inputMessage = exchange.getIn().getBody(String.class);
        LOGGER.info("inputMessage : " + inputMessage);

        String operationName = exchange.getIn().getHeader(CxfConstants.OPERATION_NAME, String.class);
        Method method = findMethod(operationName, exchange.getIn().getBody(Object[].class));

        Object response = method.invoke(instance, exchange.getIn().getBody(Object[].class));

        exchange.getOut().setBody(response);
    }

    private Method findMethod(String operationName, Object[] parameters) throws SecurityException, NoSuchMethodException {
        return beanClass.getMethod(operationName, getParameterTypes(parameters));
    }

    private Class[] getParameterTypes(Object[] parameters) {

        if (parameters == null) {
            return new Class[0];
        }
        Class[] answer = new Class[parameters.length];
        int i = 0;
        for (Object object : parameters) {
            answer[i] = object.getClass();
            i++;
        }
        return answer;
    }

}

这个类是关键,它通过反射来调用接口实现类中的方法,仔细看。

路由类:

package com.server.route;

import com.server.App;
import com.server.process.BaseicQueryProcess;
import com.server.service.impl.BaseicQueryImpl;
import org.apache.camel.builder.RouteBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author CYX
 * @create 2018-12-27-20:05
 */
public class BaseQueryRoute extends RouteBuilder {

    private static final Logger LOGGER = LoggerFactory.getLogger(BaseQueryRoute.class);

    @Override
    public void configure() throws Exception {

        from(App.BASEQUERY_SERVICE_URL_ADDRESS).process(new BaseicQueryProcess(new BaseicQueryImpl()));

    }
}

将接口实现类传到process 构造函数中。

主类:

package com.server;

import com.server.conf.LogBackConfigLoader;
import com.server.route.BaseQueryRoute;
import org.apache.camel.CamelContext;
import org.apache.camel.impl.DefaultCamelContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Apache Camel With CXF-JAXRS(Code First)
 * 

* Apache Camel集成Apache CXF-JAXRS,发布WebService(代码优先) * * @author CYX */ public class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); private static final String LOGBACK_FILENAME = "./conf/logback.xml"; public static final String BASEICQUERY_SERVICE_URL = "http://localhost:9999/baseQueryService"; public static final String BASEQUERY_SERVICE_URL_ADDRESS = "cxf://" + BASEICQUERY_SERVICE_URL + "?serviceClass=com.server.service.BaseicQuery"; public static void main(String[] args) { try { LogBackConfigLoader.loadLogBack(LOGBACK_FILENAME); CamelContext camelContext = new DefaultCamelContext(); camelContext.start(); camelContext.addRoutes(new BaseQueryRoute()); LOGGER.info("baseic query service address : " + BASEICQUERY_SERVICE_URL + "?wsdl"); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } } }

主类 启动类 没啥好解释的吧。

以上Demo中,最关键的是process处理类,没有这层调用关系,就没法调用到接口实现类,这个需要注意。

 

看下Demo启动测试,启动服务端:

Apache Camel - 25 - CXF - WebService(Code First)_第1张图片

看下WSDL文档:

Apache Camel - 25 - CXF - WebService(Code First)_第2张图片

然后我们用标准流程生成 Client 客户端代码,调用测试一下:

/**
 * Hello world!
 */
public class ClientApp {

    public static void main(String[] args) {

        BaseicQueryService baseicQueryService = new BaseicQueryService();
        BaseicQuery baseicQuery = baseicQueryService.getBaseicQueryPort();
        String resultMessage = baseicQuery.queryPeopleInfo("server , do you copy");
        System.out.println(resultMessage);

    }

}

 

服务端日志:

Apache Camel - 25 - CXF - WebService(Code First)_第3张图片

客户端接收日志:

Apache Camel - 25 - CXF - WebService(Code First)_第4张图片

 

你可能感兴趣的:(Apache,Camel,Apache,Camel,使用教程)