1. 程式人生 > >用dubbo框架寫的簡單的介面作為客戶端

用dubbo框架寫的簡單的介面作為客戶端

在客戶端需要依賴服務端的jar包和類,在客戶端也新建和服務端一樣的介面和實現類


consumer.xml配置如下

<?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:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://code.alibabatech.com/schema/dubbo
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        ">

    <!-- 消費方應用名,用於計算依賴關係,不是匹配條件,不要與提供方一樣 -->
    <dubbo:application name="hehe_consumer" />

    <!-- 使用zookeeper註冊中心暴露服務地址 -->
    <!--<dubbo:registry address="multicast://127.0.0.1:1234" />-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
    <!--<dubbo:dubooTestDemo address="127.0.0.1:20880"></dubbo:registry>-->

    <!-- 生成遠端服務代理,可以像使用本地bean一樣使用demoService -->
    <dubbo:reference id="dubooTestDemo" group="jd" version="1.0" timeout="2000" interface="com.jd.service.DubboTestService"/>
    <dubbo:reference id="registerService" interface="com.jd.service.RegisterService"/>
</beans>

新建類DubboConsumer 內容有如下,這種方式是整合spring去掉用服務端介面
import com.alibaba.fastjson.JSON;
import com.jd.domain.ResponseMessage;
import com.jd.domain.User;
import com.jd.service.DubboTestService;
import com.jd.service.RegisterService;
import javafx.application.Application;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import javax.xml.ws.spi.Invoker;
import java.io.IOException;

/**
 * Created by Administrator on 2017/9/2 0002.
 */
public class DubboConsumer {
    public static void main(String[] args) throws IOException {
        //classpath去執行時的環境去找這個檔案
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo/consumer.xml");
        //如果consumer.xml不放在resources下,可以使用檔案路徑FileSystemXmlApplication這個介面,填寫絕對路徑
        //ApplicationContext context1 = new FileSystemXmlApplicationContext("D:\\dubboController\\xml\\consumer.xml");
        DubboTestService dubboTestService = (DubboTestService)context.getBean("dubooTestDemo");
        String name = dubboTestService.getName();
        System.out.println(name);
        dubboTestService.say();
        //返回的是一個物件,物件輸出必須得轉化成字串形式,用fastjson
        ResponseMessage responseMessage = dubboTestService.getUserById(55);
        System.out.print("responseMessage"+ JSON.toJSONString(responseMessage));

        RegisterService registerService = (RegisterService)context.getBean("registerService");
        User user = new User();
        user.setUsername("niu");
        //{"username":"niuniu"}

        registerService.registerUser(user);

    }
}

第二種方法用泛化的方式去掉用
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.MethodConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.fastjson.JSON;
import com.jd.service.DubboTestService;
import com.jd.service.RegisterService;
import javafx.application.Application;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/9/3 0003.
 */
public class GenericConsumer {
    //api呼叫方式
    @Test
    public void genericTest() {
        //對應配置檔案中的<dubbo:application name="hehe_consumer" />
        ApplicationConfig application = new ApplicationConfig();
        application.setName("xixi");

        // 對應配置檔案中的暴露中心連結地址
        RegistryConfig registry = new RegistryConfig();
        registry.setAddress("multicast://224.5.6.7:1234");
//        registry.setUsername("aaa");
//        registry.setPassword("bbb");
        // 注意:ReferenceConfig為重物件,內部封裝了與註冊中心的連線,以及與服務提供方的連線

        // 引用遠端服務
        // 服務實現,對應配置中的 <dubbo:reference id="dubooTestDemo" group="jd" version="1.0" timeout="2000" interface="com.jd.service.DubboTestService"/>
        ReferenceConfig<DubboTestService> reference = new ReferenceConfig<DubboTestService>();// 此例項很重,封裝了與註冊中心的連線以及與提供者的連線,請自行快取,否則可能造成記憶體和連線洩漏
        reference.setApplication(application);
        reference.setRegistry(registry);// 多個註冊中心可以用setRegistries()
        reference.setInterface(DubboTestService.class);
        reference.setVersion("1.0");
        reference.setGroup("jd");
        reference.setTimeout(2000);
//        reference.setUrl("dubbo://127.0.0.1:20880/com.longteng.service.DubboTestService?application=xixi_provider&callbacks=10000&connect.timeout=10000&method=getUsers");
// 和本地bean一樣使用xxxService
        //方法的設定
        List<MethodConfig> methods = new ArrayList<MethodConfig>();
        MethodConfig method = new MethodConfig();
        method.setName("getName");
        method.setTimeout(10000);
        //方法重試
        method.setRetries(0);
        methods.add(method);
        reference.setMethods(methods);// 設定方法級配置

        //相當於api的方式呼叫
        //長連線,一個介面只需要做一次就好了 get相當於spring裡的getbean 那一段一樣,和spring那個相對應理解
        DubboTestService xxxService = reference.get();// 注意:此代理物件內部封裝了所有通訊細節,對
        Object o = "jiaou";
        System.out.println(JSON.toJSONString(xxxService.getUserById(1)));
        System.out.println(JSON.toJSONString(xxxService.sayHello("jiaou")));
        System.out.println();
    }


}

第三種方式用telnet去呼叫

com.test.DemoService
檢視服務中的介面
dubbo>ls com.test.DemoService
queryDemoPageList
insertDemolist
uploadDemoList
deleteDemolist
ls
(list services and methods)
ls
顯示服務列表。
ls -l
顯示服務詳細資訊列表。
ls XxxService
顯示服務的方法列表。
ls -l XxxService
顯示服務的方法詳細資訊列表。
3.呼叫服務介面
呼叫介面時,以JSON格式傳入引數(這點很方便 :-D),然後列印返回值和所用時間。
dubbo>invoke com.test.DemoService.queryDemoPageList({"id":"100"}, 1, 2)
{"totalCount":1,"data":[{date":"2011-03-23 14:10:32","name":"張三","keyword":null}]}

elapsed: 10 ms.
invoke
invoke XxxService.xxxMethod({"prop": "value"})
呼叫服務的方法。
invoke xxxMethod({"prop": "value"})

寫程式碼作為TelnetSocket

/**
 * Created by Administrator on 2017/9/3 0003.
 */
import org.apache.log4j.Logger;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;


public class TelnetSocket {

    private final static Logger LOGGER = Logger.getLogger(TelnetSocket.class);
    /**
     * socket函式
     */
    private Socket socket;

    /**
     * 換行符
     */
    private final static String LINE_SEPARATOR = System.getProperty("line.separator");
    /**
     * 預設讀字元編碼
     */
    private String readEncoding = "UTF-8";

    /**
     * 預設寫字元編碼
     */
    private String writeEncoding = "UTF-8";

    /**
     * DubboTelnetClient 構造
     *
     * @param ip
     *            ip地址
     * @param port
     *            埠
     * @throws java.net.UnknownHostException
     * @throws java.io.IOException
     */
    public TelnetSocket(String ip, int port) throws UnknownHostException,
            IOException {
        this.socket = new Socket(ip, port);
    }

    /**
     * DubboTelnetClient 構造
     *
     * @param ip
     *            ip地址
     * @param port
     *            埠
     * @param connTimeout
     *            連線超時時間超時時間
     * @throws java.net.UnknownHostException
     * @throws java.io.IOException
     */
    public TelnetSocket(String ip, int port, int connTimeout)
            throws UnknownHostException, IOException {
        this(ip, port, connTimeout, 5000);
    }

    public boolean isConnected(){
        return socket.isConnected();
    }

    /**
     * DubboTelnetClient 構造
     *
     * @param ip
     *            ip地址
     * @param port
     *            埠
     * @param connTimeout
     *            連線超時時間
     * @param soTimeout
     *            讀取超時時間
     * @throws java.net.UnknownHostException
     * @throws java.io.IOException
     */
    public TelnetSocket(String ip, int port, int connTimeout, int soTimeout)
            throws UnknownHostException, IOException {
        try {
            this.socket = new Socket();
            socket.setSoTimeout(soTimeout);
            socket.connect(new InetSocketAddress(ip, port), connTimeout);
        } catch (Exception e) {
            LOGGER.error("連線"+ip+":"+port+"異常"+e.getMessage(), e);
        }
    }

    /**
     * 傳送訊息
     *
     * @param msg
     *            訊息
     * @param times
     *            讀取次數(即遇到dubbo>結尾代表一次)
     * @return 返回訊息
     * @throws java.io.IOException
     */
    public String send(String msg, int times) throws IOException {

        String result = "";
        InputStream in = null;
        OutputStream out = null;
        ByteArrayOutputStream baout = null;
        try {
            // 初始化通道
            //傳送訊息
            in = socket.getInputStream();
            out = socket.getOutputStream();
            // 傳送請求
            out.write(msg.getBytes(writeEncoding));
            out.write(LINE_SEPARATOR.getBytes(writeEncoding));
            out.flush();    //重新整理快取

            //接收訊息
            baout = new ByteArrayOutputStream();
            // 解析得到的響應
            StringBuffer sb = new StringBuffer();
            byte[] bs = new byte[1024];
            int len = 0;
            int i = 0;
            while (i < 1024 && (len = in.read(bs)) != -1) {
                //if (i > 1024) { // 防止無限迴圈 最多取 1M的資料
                //	break;
                //}
                String data = new String(bs, 0, len, readEncoding);
                baout.write(bs, 0, len);
                sb.append(data);

                String last = sb.substring(sb.length()-6);
                if (last.endsWith("jsf>") || "dubbo>".equals(last) || "lnet> ".equals(last)) {
                    if (--times < 1) {
                        break; // 讀到這個就斷開連線返回
                    }
                }
                i++;
            }
            result = new String(baout.toByteArray(), readEncoding);
            return result;
        } catch (Exception e) {
            LOGGER.error("執行socket命令"+msg+"結束, 結果為"+e.getMessage(), e);
        }finally {
            if(baout!=null){
                baout.close();
            }
            if (out != null) {
                out.close();
            }
            if (in != null) {
                in.close();
            }
        }
        return result;
    }
    /**
     * 傳送訊息
     *
     * @param msg
     *            訊息
     * @return 返回訊息
     * @throws java.io.IOException
     */
    public String send(String msg) throws IOException {
        int time = 1;
        if (msg.startsWith("count")) {
            time = 2; // count命令會返回2次dubbo
        } else if (msg.startsWith("trace")) {
            String[] cmds = msg.split("\\s+"); // trace幾次返回幾次
            time = cmds.length > 2 ? Integer.valueOf(cmds[cmds.length - 1]
                    .trim()) : 1;
        }
        return send(msg, time);
    }

    /**
     * 傳送訊息
     *
     * @param msg
     *            訊息
     * @return 返回訊息
     * @throws java.io.IOException
     * @deprecated use {@link #send(String)}
     */
    public String sendOld(String msg) throws IOException {
        String result = "";
        BufferedReader in = null;
        PrintWriter out = null;
        try {
            // 初始化通道
            in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);

            // 傳送請求
            out.println(msg);
            out.flush();

            // 解析得到的響應
            StringBuffer sb = new StringBuffer();
            char[] cbuf = new char[10240];
            in.read(cbuf);
			/*try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}*/
            sb.append(cbuf, 0, cbuf.length);
            result = sb.toString();
            return result;
        } finally {
            if (out != null) {
                out.close();
            }
            if (in != null) {
                in.close();
            }
        }
    }

    /**
     * 關閉連線
     */
    public void close() {
        try {
            if (socket != null && !socket.isClosed())
                socket.close();
        } catch (IOException e) {
            // ignore
            // e.printStackTrace();
        }
    }

    /**
     * @return the readEncoding
     */
    public String getReadEncoding() {
        return readEncoding;
    }

    /**
     * @param readEncoding the readEncoding to set
     */
    public void setReadEncoding(String readEncoding) {
        this.readEncoding = readEncoding;
    }

    /**
     * @return the writeEncoding
     */
    public String getWriteEncoding() {
        return writeEncoding;
    }

    /**
     * @param writeEncoding the writeEncoding to set
     */
    public void setWriteEncoding(String writeEncoding) {
        this.writeEncoding = writeEncoding;
    }

    public static void main(String[] args) {
        String[] cmds = new String[] { "invoke com.jd.ecc.delivery.service.AddressBaseService.getAddressesByCode(\"3301\")" };
//		String[] cmds = new String[] { "ls -l", "count com.jd.testsaf.HelloService", "trace com.jd.testsaf.HelloService"};
        TelnetSocket client = null;
        long time0 = System.currentTimeMillis();
        try {
            for (int i = 0; i < cmds.length; i++) {
                client = new TelnetSocket("192.168.192.153", 32000,5000,30000);
//				client = new DubboTelnetClient("10.12.120.121", 20880,5000);
                client.setReadEncoding("gbk");
                String res = client.send(cmds[i]);
                System.out.println("命令:" + cmds[i] + "   返回");
                System.out.println(res);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (client != null) {
                client.close();
            }
        }
        long time1 = System.currentTimeMillis();
        System.out.println("耗時:" + (time1 - time0) + "ms");
    }
}


TelnetConsumer
import java.io.IOException;

/**
 * Created by Administrator on 2017/9/3 0003.
 */
public class TelnetConsumer {
    public static void main(String[] args) throws IOException {
        String ip = "127.0.0.1";
        int port = 20880;
        TelnetSocket telnetSocket = new TelnetSocket(ip,port);
        String interfaceName = "com.jd.service.DubboTestService";
        String methodName = "getUserById";
        String param = "0";
        //invoke com.jd.service.DubboTestService.getUserById(0) 命令的組裝
        String cmd = "invoke "+interfaceName+"."+methodName+"(\""+param+"\")";
        System.out.print(cmd);
        String result = telnetSocket.send(cmd);

        System.out.print("返回的結果:"+result);

    }
}