用dubbo框架寫的簡單的介面作為客戶端
阿新 • • 發佈:2019-01-23
在客戶端需要依賴服務端的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);
}
}