电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

Java Socket實現Redis客戶端的詳細說明

瀏覽:95日期:2022-08-11 17:30:17

Redis是最常見的緩存服務中間件,在java開發中,一般使用 jedis 來實現。

如果不想依賴第三方組件,自己實現一個簡單的redis客戶端工具,該如何實現呢?本文就是介紹這樣一種方法。

Redis的協議非常簡單,而且輸入數據和輸出數據都遵循統一的協議,具體規則參考這里:

http://redisdoc.com/topic/protocol.html

Redis的命令協議:

$參數數量n

$參數1的值的字節數組長度

$參數1的值的字符串表示

$參數2的值的字節數組長度

$參數2的值的字符串表示

...

$參數n的值的字節數組長度

$參數n的值的字符串表示

Redis的返回協議:

1、狀態回復(status reply)的第一個字節是 '+',單行字符串;2、錯誤回復(error reply)的第一個字節是 '-';3、整數回復(integer reply)的第一個字節是 ':';4、批量回復(bulk reply)的第一個字節是 '$';5、多條批量回復(multi bulk reply)的第一個字節是 '*';6、所有的命令都是以 rn 結尾。

Java代碼說明

針對上述規則,我們用兩個類來實現:

1、SimpleRedisClient類,主要用于發送請求,并讀取響應結果(字符串);

整體比較簡單,稍微復雜點的地方就是讀取流數據,遇到兩種情況就該結束循環,一是返回長度為-1,二是返回字符串以 rn 結尾。

如果處理不當,可能會導致 read 阻塞,Socket卡住。

2、SimpleRedisData類,用于解析響應結果,把redis統一協議的字符串,解析為具體的對象。

這部分代碼完全是按照協議規則來實現的,通過一個游標 pos 來向前移動,在移動過程中識別不同格式的數據。

最復雜的是 list 類型的數據,以 * 開頭,后面跟著一個整數,表示列表中所有元素的數量,然后就是每一個列表元素的值,循環解析即可。

package demo;import java.io.Closeable;import java.io.IOException;import java.net.Socket;import java.util.List;public class SimpleRedisClient implements Closeable { private String host; private int port; private String auth; private Socket socket = null; public SimpleRedisClient(String host, int port, String auth) {this.host = host;this.port = port;this.auth = auth;try { socket = new Socket(this.host, this.port); socket.setSoTimeout(8 * 1000);//8秒} catch (Exception ex) { socket = null; ex.printStackTrace();} } public boolean connect() throws IOException {if (socket == null || auth == null || auth.length() <= 0) { return false;}String response = execute('AUTH', auth);if (response == null || response.length() <= 0) { return false;}String res = new SimpleRedisData(response).getString();return 'OK'.compareTo(res) == 0; } @Override public void close() {try { if (socket != null) {socket.shutdownOutput();socket.close(); } //System.out.println('closed');} catch (Exception ex) { ex.printStackTrace();} } public String getString(String key) {if (socket == null || key == null || key.isEmpty()) { return null;}try { String response = execute('GET', key); return new SimpleRedisData(response).getString();} catch (Exception ex) { ex.printStackTrace(); return null;} } public String setString(String key, String value) {if (socket == null || key == null || key.isEmpty()) { return null;}try { String response = execute('SET', key, value); return new SimpleRedisData(response).getString();} catch (Exception ex) { ex.printStackTrace(); return null;} } public String deleteKey(String key) throws IOException {if (socket == null || key == null || key.isEmpty()) { return null;}String response = execute('DEL', key);return new SimpleRedisData(response).getString(); } public List<String> getKeys(String pattern) throws IOException {if (socket == null || pattern == null || pattern.isEmpty()) { return null;}String response = execute('KEYS', pattern);return new SimpleRedisData(response).getStringList(); } public String execute(String... args) throws IOException {if (socket == null || args == null || args.length <= 0) { return null;}//System.out.println(StringUtil.join(args, ' '));StringBuilder request = new StringBuilder();request.append('*' + args.length).append('rn');//參數的數量for (int i = 0; i < args.length; i++) { request.append('$' + args[i].getBytes('utf8').length).append('rn');//參數的長度 request.append(args[i]).append('rn');//參數的內容}socket.getOutputStream().write(request.toString().getBytes());socket.getOutputStream().flush();StringBuilder reply = new StringBuilder();int bufSize = 1024;while (true) { byte[] buf = new byte[bufSize]; int len = socket.getInputStream().read(buf); if (len < 0) {break; } String str = new String(buf, 0, len); reply.append(str); if (str.endsWith('rn')) {break; }}String response = reply.toString();//System.out.println('response: ' + response);return response; }}

package demo;import java.util.ArrayList;import java.util.List;public class SimpleRedisData { public SimpleRedisData(String rawData) {this.rawData = rawData;//System.out.println(rawData); } private int pos; private String rawData; public String getString() {if (rawData == null || rawData.length() <= 0) { return null;}int i = rawData.indexOf('rn', pos);if (i <= 0) { return null;}char c = rawData.charAt(pos);if (c == ’+’) { int from = pos + 1; int to = i; String v = rawData.substring(from, to); pos = to + 2; return v;} else if (c == ’-’) { int from = pos + 1; int to = i; String v = rawData.substring(from, to); pos = to + 2; return v;} else if (c == ’:’) { int from = pos + 1; int to = i; String v = rawData.substring(from, to); pos = to + 2; return v;} else if (c == ’$’) { int from = pos + 1; int to = i; int bulkSize = Integer.parseInt(rawData.substring(from, to)); pos = to + 2; from = pos; to = pos + bulkSize; try {//$符號后面的數值是指內容的字節長度,而不是字符數量,所以要轉換為二進制字節數組,再取指定長度的數據byte[] buf = rawData.substring(from).getBytes('utf-8');String v = new String(buf, 0, bulkSize);pos = to + 2;return v; } catch (Exception ex) {ex.printStackTrace();return null; }} else { return null;} } public List<String> getStringList() {if (rawData == null || rawData.length() <= 0) { return null;}int i = rawData.indexOf('rn', pos);if (i <= 0) { return null;}char c = rawData.charAt(pos);if (c == ’*’) { List<String> values = new ArrayList<>(); int from = pos + 1; int to = i; int multSize = Integer.parseInt(rawData.substring(from, to)); pos = to + 2; for (int index = 0; index < multSize; index++) {values.add(getString()); } return values;} else { return null;} }}

package demo;import org.junit.jupiter.api.Test;import java.util.List;public class RedisTest { @Test public void test() {SimpleRedisClient client = null;try { client = new SimpleRedisClient('127.0.0.1', 6379, '123456'); System.out.println('connected: ' + client.connect()); List<String> keyList = client.getKeys('api_*'); for (int i = 0; i < keyList.size(); i++) {System.out.println((i + 1) + 't' + keyList.get(i)); } System.out.println('keys: ' + keyList != null ? keyList.size() : 'null'); System.out.println(client.getString('api_getCustomerName'));} catch (Exception ex) { ex.printStackTrace();} finally { if (client != null) {client.close(); }} }}

優點:

1、不依賴任何第三方組件,可以順利編譯通過;

2、代碼極其簡單。

不足之處:

1、未考慮并發訪問;

2、未提供更多的數據類型,以及讀寫方法,大家可以在此基礎上包裝一下。

以上就是如何用Java Socket實現一個簡單的Redis客戶端的詳細內容,更多關于Java Socket Redis客戶端的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 智慧物联网行业一站式解决方案提供商-北京东成基业 | 苏州教学设备-化工教学设备-环境工程教学模型|同科教仪 | MVE振动电机_MVE震动电机_MVE卧式振打电机-河南新乡德诚生产厂家 | 天空彩票天下彩,天空彩天空彩票免费资料,天空彩票与你同行开奖,天下彩正版资料大全 | 电销卡 防封电销卡 不封号电销卡 电话销售卡 白名单电销卡 电销系统 外呼系统 | 山东集装箱活动房|济南集装箱活动房-济南利森集装箱有限公司 | 手持式3d激光扫描仪-便携式三维立体扫描仪-北京福禄克斯 | 医学动画公司-制作3d医学动画视频-医疗医学演示动画制作-医学三维动画制作公司 | 液氨泵,液化气泵-淄博「亚泰」燃气设备制造有限公司 | 上海办公室装修,办公楼装修设计,办公空间设计,企业展厅设计_写艺装饰公司 | 淘气堡_室内儿童乐园_户外无动力儿童游乐设备-高乐迪(北京) | 波纹补偿器_不锈钢波纹补偿器_巩义市润达管道设备制造有限公司 | 药品冷藏箱厂家_低温冰箱_洁净工作台-济南欧莱博电子商务有限公司官网 | 防爆鼓风机-全风-宏丰鼓风机-上海梁瑾机电设备有限公司 | 双能x射线骨密度检测仪_dxa骨密度仪_双能x线骨密度仪_品牌厂家【品源医疗】 | 全温度恒温培养摇床-大容量-立式-远红外二氧化碳培养箱|南荣百科 | 河北码上网络科技|邯郸小程序开发|邯郸微信开发|邯郸网站建设 | 交通信号灯生产厂家_红绿灯厂家_电子警察监控杆_标志杆厂家-沃霖电子科技 | 物流之家新闻网-最新物流新闻|物流资讯|物流政策|物流网-匡匡奈斯物流科技 | 视觉检测设备_自动化检测设备_CCD视觉检测机_外观缺陷检测-瑞智光电 | 世界箱包品牌十大排名,女包小众轻奢品牌推荐200元左右,男包十大奢侈品牌排行榜双肩,学生拉杆箱什么品牌好质量好 - Gouwu3.com | 远程会诊系统-手术示教系统【林之硕】医院远程医疗平台 | 写方案网_方案策划方案模板下载| LED显示屏_LED屏方案设计精准报价专业安装丨四川诺显科技 | 硫酸亚铁-聚合硫酸铁-除氟除磷剂-复合碳源-污水处理药剂厂家—长隆科技 | 硅胶布|电磁炉垫片|特氟龙胶带-江苏浩天复合材料有限公司 | 浙江皓格药业有限公司| 安徽合肥项目申报咨询公司_安徽合肥高新企业项目申报_安徽省科技项目申报代理 | 卧涛科技有限公司科技项目申报公司|高新技术企业申报|专利申请 | 面粉仓_储酒罐_不锈钢储酒罐厂家-泰安鑫佳机械制造有限公司 | 彭世修脚_修脚加盟_彭世修脚加盟_彭世足疗加盟_足疗加盟连锁_彭世修脚技术培训_彭世足疗 | 正压送风机-多叶送风口-板式排烟口-德州志诺通风设备 | 食品质构分析仪-氧化诱导分析仪-瞬态法导热系数仪|热冰百科 | 骁龙云呼电销防封号系统-axb电销平台-外呼稳定『免费试用』 | 广州展台特装搭建商|特装展位设计搭建|展会特装搭建|特装展台制作设计|展览特装公司 | 首页|专注深圳注册公司,代理记账报税,注册商标代理,工商变更,企业400电话等企业一站式服务-慧用心 | 砂磨机_立式纳米砂磨机_实验室砂磨机-广州儒佳化工设备厂家 | 踏板力计,制动仪,非接触多功能速度仪,逆反射系数测试仪-创宇 | China plate rolling machine manufacturer,cone rolling machine-Saint Fighter | 胀套-锁紧盘-风电锁紧盘-蛇形联轴器「厂家」-瑞安市宝德隆机械配件有限公司 | 恒温恒湿试验箱_高低温试验箱_恒温恒湿箱-东莞市高天试验设备有限公司 |