├── .idea └── icon.png ├── .workflow └── pipeline-20250221.yml ├── LICENSE ├── README.md ├── README_EN.md ├── assets ├── jetbrains.svg ├── linux │ └── RedisFront.png ├── logo.png ├── mac │ └── RedisFront.icns ├── qq.jpg ├── version.json ├── weixin.jpg └── windows │ └── RedisFront.ico ├── build.gradle.kts ├── gradlew ├── gradlew.bat ├── screenshot ├── 2024.1 │ ├── 2024.1-dark-1.png │ ├── 2024.1-dark-2.png │ ├── 2024.1-dark-3.png │ ├── 2024.1-dark-4.png │ ├── 2024.1-dark-5.png │ ├── 2024.1-light-1.png │ ├── 2024.1-light-2.png │ ├── 2024.1-light-3.png │ ├── 2024.1-light-4.png │ └── 2024.1-light-5.png ├── history │ ├── redisfront-win11.png │ └── redisfront.png └── latest │ ├── 2025.1-dark-1.png │ ├── 2025.1-dark-2.png │ ├── 2025.1-dark-3.png │ ├── 2025.1-dark-4.png │ └── 2025.1-dark-5.png ├── settings.gradle.kts └── src ├── main ├── java │ └── org │ │ └── dromara │ │ └── redisfront │ │ ├── RedisFrontContext.java │ │ ├── RedisFrontEventListener.java │ │ ├── RedisFrontMain.java │ │ ├── RedisFrontPrefs.java │ │ ├── commons │ │ ├── constant │ │ │ └── Constants.java │ │ ├── enums │ │ │ ├── ConnectType.java │ │ │ ├── KeyTypeEnum.java │ │ │ ├── RedisMode.java │ │ │ └── RedisNodeRole.java │ │ ├── exception │ │ │ ├── RedisFrontException.java │ │ │ └── RedisFrontTimeoutException.java │ │ ├── jsch │ │ │ ├── JschManager.java │ │ │ └── JschUtils.java │ │ ├── lettuce │ │ │ ├── AddressMappingResolver.java │ │ │ └── LettuceUtils.java │ │ ├── pool │ │ │ ├── CleanMode.java │ │ │ ├── ConnectionSupplier.java │ │ │ ├── RedisConnectionFactory.java │ │ │ └── RedisConnectionPoolManager.java │ │ ├── resources │ │ │ └── Icons.java │ │ └── utils │ │ │ ├── AlertUtils.java │ │ │ ├── FutureUtils.java │ │ │ ├── MD5Util.java │ │ │ ├── RedisFrontUtils.java │ │ │ ├── TreeUtils.java │ │ │ └── UpgradeUtils.kt │ │ ├── dao │ │ ├── ConnectDetailDao.java │ │ └── ConnectGroupDao.java │ │ ├── model │ │ ├── ClusterNode.java │ │ ├── DbInfo.java │ │ ├── LogInfo.java │ │ ├── MessageInfo.java │ │ ├── RedisNode.java │ │ ├── context │ │ │ └── RedisConnectContext.java │ │ ├── entity │ │ │ ├── ConnectDetailEntity.java │ │ │ └── ConnectGroupEntity.java │ │ ├── event │ │ │ └── RedisFrontEvent.java │ │ ├── table │ │ │ ├── HashTableModel.java │ │ │ ├── ListTableModel.java │ │ │ ├── PubSubTableModel.java │ │ │ ├── SetTableModel.java │ │ │ ├── SortedSetTableModel.java │ │ │ └── StreamTableModel.java │ │ ├── tree │ │ │ └── TreeNodeInfo.java │ │ └── turbo │ │ │ ├── Turbo1.java │ │ │ ├── Turbo2.java │ │ │ ├── Turbo3.java │ │ │ ├── Turbo4.java │ │ │ ├── Turbo5.java │ │ │ └── Turbo6.java │ │ ├── service │ │ ├── RedisBasicService.java │ │ ├── RedisHashService.java │ │ ├── RedisListService.java │ │ ├── RedisPubSubService.java │ │ ├── RedisSetService.java │ │ ├── RedisStreamService.java │ │ ├── RedisStringService.java │ │ ├── RedisZSetService.java │ │ └── impl │ │ │ ├── RedisBasicServiceImpl.java │ │ │ ├── RedisHashServiceImpl.java │ │ │ ├── RedisListServiceImpl.java │ │ │ ├── RedisPubSubServiceImpl.java │ │ │ ├── RedisSetServiceImpl.java │ │ │ ├── RedisStreamServiceImpl.java │ │ │ ├── RedisStringServiceImpl.java │ │ │ └── RedisZSetServiceImpl.java │ │ └── ui │ │ ├── components │ │ ├── chart │ │ │ ├── AbstractRedisChart.java │ │ │ ├── RedisClientConnectionsChart.java │ │ │ ├── RedisCommandStatsChart.java │ │ │ ├── RedisMemoryChart.java │ │ │ └── RedisNetworkChart.java │ │ ├── editor │ │ │ └── TextEditor.java │ │ ├── extend │ │ │ └── BoldTitleTabbedPaneUI.java │ │ ├── info │ │ │ ├── LogInfoData.java │ │ │ ├── LogStatusHolder.java │ │ │ └── RedisInfoView.java │ │ ├── loading │ │ │ ├── SyncLoadingDialog.java │ │ │ └── SyncLoadingWaiter.java │ │ ├── monitor │ │ │ ├── RedisMonitor.java │ │ │ └── RedisUsageInfo.java │ │ ├── panel │ │ │ ├── BorderNonePanel.java │ │ │ ├── NonePanel.java │ │ │ └── WrapperPanel.java │ │ ├── scanner │ │ │ ├── AbstractRedisDataScanner.java │ │ │ ├── RedisDataScanner.java │ │ │ ├── context │ │ │ │ ├── RedisScanContext.java │ │ │ │ └── RedisScanContextManager.java │ │ │ ├── core │ │ │ │ ├── HashRedisDataScanner.java │ │ │ │ ├── ListRedisDataScanner.java │ │ │ │ ├── SetRedisDataScanner.java │ │ │ │ ├── StreamRedisDataScanner.java │ │ │ │ ├── StringRedisDataScanner.java │ │ │ │ └── ZSetRedisDataScanner.java │ │ │ ├── handler │ │ │ │ └── ScanDataRefreshHandler.java │ │ │ └── model │ │ │ │ └── ScanDataResult.java │ │ └── terminal │ │ │ └── AbstractTerminal.java │ │ ├── dialog │ │ ├── AddConnectDialog.form │ │ ├── AddConnectDialog.java │ │ ├── AddKeyDialog.form │ │ ├── AddKeyDialog.java │ │ ├── AddOrUpdateValueDialog.form │ │ ├── AddOrUpdateValueDialog.java │ │ ├── ImportConfigDialog.form │ │ ├── ImportConfigDialog.java │ │ ├── SettingDialog.form │ │ └── SettingDialog.java │ │ ├── event │ │ ├── AddKeySuccessEvent.java │ │ ├── ClickKeyTreeNodeEvent.java │ │ ├── CommandExecuteEvent.java │ │ ├── DrawerChangeEvent.java │ │ ├── KeyDeleteSuccessEvent.java │ │ ├── OpenRedisConnectEvent.java │ │ └── RefreshConnectTreeEvent.java │ │ ├── handler │ │ ├── ConnectHandler.java │ │ └── DrawerHandler.java │ │ └── widget │ │ ├── RedisFrontComponent.java │ │ ├── RedisFrontWidget.java │ │ ├── main │ │ ├── MainComponent.java │ │ ├── about │ │ │ └── MainAboutPanel.java │ │ ├── fragment │ │ │ ├── MainTabView.java │ │ │ └── scaffold │ │ │ │ ├── PageScaffold.java │ │ │ │ ├── index │ │ │ │ ├── IndexPageView.java │ │ │ │ ├── LeftSearchFragment.form │ │ │ │ ├── LeftSearchFragment.java │ │ │ │ ├── RightViewFragment.form │ │ │ │ └── RightViewFragment.java │ │ │ │ ├── pubsub │ │ │ │ ├── PubSubPageView.form │ │ │ │ └── PubSubPageView.java │ │ │ │ ├── report │ │ │ │ ├── ReportPageView.form │ │ │ │ └── ReportPageView.java │ │ │ │ └── terminal │ │ │ │ ├── RedisFrontTerminal.java │ │ │ │ └── TerminalPageView.java │ │ └── listener │ │ │ └── MouseDraggedListener.java │ │ └── sidebar │ │ ├── SidebarComponent.java │ │ ├── drawer │ │ ├── DrawerAnimationAction.java │ │ └── DrawerMenuItemEvent.java │ │ ├── panel │ │ ├── LogoPanel.java │ │ └── ThemesChangePanel.java │ │ └── tree │ │ ├── RedisConnectTree.java │ │ ├── RedisConnectTreeCellRenderer.java │ │ └── RedisConnectTreeNode.java └── resources │ ├── icons │ ├── CPU.svg │ ├── CPU_dark.svg │ ├── DataTables.svg │ ├── RecentlyUsed.svg │ ├── RedisFront.ico │ ├── add.svg │ ├── add_conn.svg │ ├── add_dark.svg │ ├── buildLoadChanges.svg │ ├── cmd_add.svg │ ├── cmd_add_dark.svg │ ├── command.svg │ ├── command_dark.svg │ ├── commit.svg │ ├── copy.svg │ ├── db_cli2.svg │ ├── db_report2.svg │ ├── delete.svg │ ├── delete_a.svg │ ├── delete_b.svg │ ├── delete_b_dark.svg │ ├── delete_dark.svg │ ├── diff.svg │ ├── download.svg │ ├── favorite.svg │ ├── folder.svg │ ├── forward.svg │ ├── github.svg │ ├── github_dark.svg │ ├── home.svg │ ├── info.svg │ ├── link.svg │ ├── listFiles.svg │ ├── logo.png │ ├── memory.svg │ ├── memory_dark.svg │ ├── menu-cut.svg │ ├── menu-paste.svg │ ├── mode.svg │ ├── mode_dark.svg │ ├── mq.svg │ ├── none.svg │ ├── none_dark.svg │ ├── project.svg │ ├── redisInfo.svg │ ├── refresh.svg │ ├── refresh_a.svg │ ├── refresh_dark.svg │ ├── regex.svg │ ├── regexHovered.svg │ ├── regexSelected.svg │ ├── save.svg │ ├── save_a.svg │ ├── search.svg │ ├── setting.svg │ ├── setting_dark.svg │ ├── show.svg │ ├── status_error.svg │ ├── status_ok.svg │ ├── table.svg │ ├── test-connect.svg │ ├── tree_key.svg │ ├── undo.svg │ ├── wifi.svg │ └── wifi_dark.svg │ ├── org │ └── dromara │ │ └── redisfront │ │ ├── RedisFront.properties │ │ ├── RedisFront_zh_CN.properties │ │ └── theme │ │ ├── FlatDarkLaf.properties │ │ └── FlatLightLaf.properties │ └── svg │ ├── actions │ ├── colors.svg │ ├── copy.svg │ ├── execute.svg │ ├── intentionBulb.svg │ ├── quickfixOffBulb.svg │ └── suspend.svg │ ├── close_.svg │ ├── dark.svg │ ├── errorDialog.svg │ ├── informationDialog.svg │ ├── light.svg │ ├── publish.svg │ ├── publish_dark.svg │ ├── redis-a.svg │ ├── redisfront.svg │ ├── redisfront_text.svg │ ├── redisfront_text_dark.svg │ ├── subscribe.svg │ ├── subscribe_dark.svg │ ├── testBtn.svg │ ├── unSubscribe.svg │ ├── unSubscribe_dark.svg │ └── warningDialog.svg └── test └── java └── org └── dromara └── redisfront └── commons └── utils ├── DerbyUtilTest.java ├── FutureUtilsTest.java ├── LettuceUtilsTest.java ├── TreeTableTest.java └── TreeUtilsTest.java /.idea/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/.idea/icon.png -------------------------------------------------------------------------------- /.workflow/pipeline-20250221.yml: -------------------------------------------------------------------------------- 1 | version: '1.0' 2 | name: pipeline-20250221 3 | displayName: pipeline-20250221 4 | triggers: 5 | trigger: auto 6 | push: 7 | branches: 8 | prefix: 9 | - release- 10 | stages: 11 | - name: stage-571cb146 12 | displayName: 版本构建 13 | strategy: naturally 14 | trigger: auto 15 | executor: [] 16 | steps: 17 | - step: build@gradle 18 | name: build_gradle 19 | displayName: Gradle 构建 20 | jdkVersion: '22' 21 | gradleVersion: '4.4' 22 | commands: 23 | - '# Gradle默认构建命令' 24 | - chmod +x ./gradlew 25 | - ./gradlew build 26 | artifacts: 27 | - name: BUILD_ARTIFACT 28 | path: 29 | - ./target 30 | caches: 31 | - ~/.gradle/caches 32 | notify: [] 33 | strategy: 34 | retry: '0' 35 | - step: publish@release_artifacts 36 | name: publish_release_artifacts 37 | displayName: 发布 38 | dependArtifact: output 39 | version: 2025.1.1.1 40 | autoIncrement: true 41 | notify: [] 42 | strategy: 43 | retry: '0' 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # logo RedisFront - Cross-platform redis GUI 2 | 3 | ------- 4 | 5 | ![JDK](https://img.shields.io/badge/JDK-22-blue.svg) 6 | ![Apache 2.0](https://img.shields.io/badge/Apache-2.0-4green.svg) 7 | ![Release](https://img.shields.io/badge/Release-2025.1-green.svg) 8 | 9 | RedisFront 是一款基于 Java Swing 开发的跨平台 Redis 客户端工具,兼容多种主流操作系统 ( 包括 Windows, macOS 和 Linux ) , 通过可视化界面实现 Redis 数据管理与服务器状态监测,适用于开发调试与生产运维场景。 10 | 11 | * **多模式支持**:无缝对接单机部署、集群架构、哨兵模式等不同 Redis 部署形态,满足多样化环境需求 12 | 13 | * **安全连接**:内置 SSH 隧道功能,保障远程访问 Redis 服务时的数据传输安全性 14 | 15 | * **数据管理**:提供键值浏览、增删改查、过期时间设置、导入导出等完整数据操作功能 16 | 17 | * **状态监控**:实时展示内存用量、连接数、命令统计等关键指标,辅助性能优化 18 | 19 | 20 | [>> Click here to "README.md" with English!](./README_EN.md) 21 | 22 | ![RedisFront](screenshot/latest/2025.1-dark-1.png) 23 | ![RedisFront](screenshot/latest/2025.1-dark-2.png) 24 | ![RedisFront](screenshot/latest/2025.1-dark-5.png) 25 | 26 | ### 🌱 下载 27 | 28 | [https://gitcode.com/dromara/RedisFront/releases](https://gitcode.com/dromara/RedisFront/releases) 29 | 30 | [https://gitee.com/dromara/RedisFront/releases](https://gitee.com/dromara/RedisFront/releases) 31 | 32 | [https://github.com/dromara/RedisFront/releases](https://github.com/dromara/RedisFront/releases) 33 | 34 | ### ⛳ 反馈 35 | 36 | - 微信 `capf4xj` 37 | 38 | capf4xj 39 | 40 | - QQ群 `579454329` `验证信息:RedisFront` 41 | 42 | capf4xj 43 | 44 | ### ❤️ 感谢 45 | * [FlatLaf](https://github.com/JFormDesigner/FlatLaf?from=RedisFront) 46 | * [Lettuce](https://github.com/lettuce-io/lettuce-core?from=RedisFront) 47 | * [Hutool](https://hutool.cn?from=RedisFront) 48 | * [JetBrains](https://www.jetbrains.com?from=RedisFront) 49 | 50 | ![JenBrains logo](assets/jetbrains.svg) 51 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | # logo RedisFront - Cross-platform redis GUI 2 | 3 | ------- 4 | 5 | ![JDK](https://img.shields.io/badge/JDK-22-blue.svg) 6 | ![Apache 2.0](https://img.shields.io/badge/Apache-2.0-4green.svg) 7 | ![Release](https://img.shields.io/badge/Release-2025.1-green.svg) 8 | 9 | RedisFront is a cross-platform Redis client tool developed with Java Swing, compatible with major operating systems (Windows, macOS,Linux). Its visualized interface enables Redis data management and server monitoring, suitable for development debugging and production operations. 10 | 11 | * **Multi-mode Support**: Seamlessly connects to standalone deployments, Cluster mode, and Sentinel mode configurations 12 | 13 | * **Secure Connectivity**: Built-in SSH tunneling ensures secure data transmission for remote Redis access 14 | 15 | * **Data Operations**: Offers complete key-value management including CRUD, TTL settings, and import/export functions 16 | 17 | * **Real-time Monitoring**: Displays critical metrics like memory usage, connection counts, and command statistics for performance optimization 18 | 19 | ![RedisFront](screenshot/latest/2025.1-dark-1.png) 20 | ![RedisFront](screenshot/latest/2025.1-dark-2.png) 21 | ![RedisFront](screenshot/latest/2025.1-dark-5.png) 22 | 23 | ### 🌱 Download 24 | 25 | [https://gitcode.com/dromara/RedisFront/releases](https://gitcode.com/dromara/RedisFront/releases) 26 | 27 | [https://gitee.com/dromara/RedisFront/releases](https://gitee.com/dromara/RedisFront/releases) 28 | 29 | [https://github.com/dromara/RedisFront/releases](https://github.com/dromara/RedisFront/releases) 30 | 31 | ### ❤️ Thanks 32 | * [FlatLaf](https://github.com/JFormDesigner/FlatLaf?from=RedisFront) 33 | * [Lettuce](https://github.com/lettuce-io/lettuce-core?from=RedisFront) 34 | * [Hutool](https://hutool.cn?from=RedisFront) 35 | * [JetBrains](https://www.jetbrains.com?from=RedisFront) 36 | 37 | ![JenBrains logo](assets/jetbrains.svg) 38 | 39 | -------------------------------------------------------------------------------- /assets/linux/RedisFront.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/assets/linux/RedisFront.png -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/assets/logo.png -------------------------------------------------------------------------------- /assets/mac/RedisFront.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/assets/mac/RedisFront.icns -------------------------------------------------------------------------------- /assets/qq.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/assets/qq.jpg -------------------------------------------------------------------------------- /assets/version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2025.1", 3 | "download": "https://gitee.com/dromara/RedisFront/releases/" 4 | } -------------------------------------------------------------------------------- /assets/weixin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/assets/weixin.jpg -------------------------------------------------------------------------------- /assets/windows/RedisFront.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/assets/windows/RedisFront.ico -------------------------------------------------------------------------------- /screenshot/2024.1/2024.1-dark-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/2024.1/2024.1-dark-1.png -------------------------------------------------------------------------------- /screenshot/2024.1/2024.1-dark-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/2024.1/2024.1-dark-2.png -------------------------------------------------------------------------------- /screenshot/2024.1/2024.1-dark-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/2024.1/2024.1-dark-3.png -------------------------------------------------------------------------------- /screenshot/2024.1/2024.1-dark-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/2024.1/2024.1-dark-4.png -------------------------------------------------------------------------------- /screenshot/2024.1/2024.1-dark-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/2024.1/2024.1-dark-5.png -------------------------------------------------------------------------------- /screenshot/2024.1/2024.1-light-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/2024.1/2024.1-light-1.png -------------------------------------------------------------------------------- /screenshot/2024.1/2024.1-light-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/2024.1/2024.1-light-2.png -------------------------------------------------------------------------------- /screenshot/2024.1/2024.1-light-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/2024.1/2024.1-light-3.png -------------------------------------------------------------------------------- /screenshot/2024.1/2024.1-light-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/2024.1/2024.1-light-4.png -------------------------------------------------------------------------------- /screenshot/2024.1/2024.1-light-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/2024.1/2024.1-light-5.png -------------------------------------------------------------------------------- /screenshot/history/redisfront-win11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/history/redisfront-win11.png -------------------------------------------------------------------------------- /screenshot/history/redisfront.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/history/redisfront.png -------------------------------------------------------------------------------- /screenshot/latest/2025.1-dark-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/latest/2025.1-dark-1.png -------------------------------------------------------------------------------- /screenshot/latest/2025.1-dark-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/latest/2025.1-dark-2.png -------------------------------------------------------------------------------- /screenshot/latest/2025.1-dark-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/latest/2025.1-dark-3.png -------------------------------------------------------------------------------- /screenshot/latest/2025.1-dark-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/latest/2025.1-dark-4.png -------------------------------------------------------------------------------- /screenshot/latest/2025.1-dark-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/screenshot/latest/2025.1-dark-5.png -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "RedisFront" 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/RedisFrontEventListener.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront; 2 | 3 | import org.dromara.quickswing.events.QSEvent; 4 | import org.dromara.quickswing.events.QSEventListener; 5 | import org.dromara.redisfront.model.event.RedisFrontEvent; 6 | import org.dromara.redisfront.ui.widget.RedisFrontWidget; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | import java.util.function.Consumer; 12 | 13 | public class RedisFrontEventListener extends QSEventListener { 14 | private static final Map listener = new ConcurrentHashMap<>(); 15 | 16 | public RedisFrontEventListener(RedisFrontWidget source) { 17 | super(source); 18 | RedisFrontContext context = (RedisFrontContext) source.getContext(); 19 | context.getEventBus().subscribe(this); 20 | } 21 | 22 | @Override 23 | protected void onEvent(QSEvent qsEvent) { 24 | if (qsEvent instanceof RedisFrontEvent redisFrontEvent) { 25 | if (redisFrontEvent.getRedisConnectContext() != null) { 26 | EventConsumer eventConsumer = listener.get(redisFrontEvent.getRedisConnectContext().getId()); 27 | if (eventConsumer != null) { 28 | eventConsumer.forEach((name, consumer) -> { 29 | if (name.equals(redisFrontEvent.getClass().getName())) { 30 | consumer.accept(redisFrontEvent); 31 | } 32 | }); 33 | } 34 | } 35 | } else { 36 | listener.forEach((_, eventConsumer) -> eventConsumer.forEach((_, consumer) -> consumer.accept(qsEvent))); 37 | } 38 | } 39 | 40 | public void bind(int id, Class clazz, Consumer consumer) { 41 | String name = clazz.getName(); 42 | if (listener.containsKey(id)) { 43 | EventConsumer eventConsumer = listener.get(id); 44 | if (!eventConsumer.containsKey(name)) { 45 | eventConsumer.put(name, consumer); 46 | } 47 | } else { 48 | listener.put(id, new EventConsumer(name, consumer)); 49 | } 50 | } 51 | 52 | public void unbind(int id) { 53 | listener.remove(id); 54 | } 55 | 56 | private static class EventConsumer extends HashMap> { 57 | public EventConsumer(String name, Consumer consumer) { 58 | this.put(name, consumer); 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/RedisFrontMain.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront; 2 | import lombok.extern.slf4j.Slf4j; 3 | import org.dromara.quickswing.QSApplicationInitializer; 4 | import org.dromara.quickswing.ui.app.QSWidget; 5 | import org.dromara.redisfront.commons.constant.Constants; 6 | 7 | /** 8 | * Application 9 | * 10 | * @author Jin 11 | */ 12 | @Slf4j 13 | public class RedisFrontMain { 14 | public static void main(String[] args) { 15 | QSApplicationInitializer.initialize(args, Constants.APP_NAME, () -> { 16 | RedisFrontContext context = new RedisFrontContext(); 17 | QSWidget application = context.createApplication(args); 18 | application.setLocationRelativeTo(null); 19 | application.setVisible(true); 20 | }); 21 | log.info("RedisFront started"); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/RedisFrontPrefs.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront; 2 | 3 | 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.dromara.quickswing.ui.app.QSPrefs; 6 | 7 | @Slf4j 8 | public class RedisFrontPrefs extends QSPrefs { 9 | @Override 10 | protected String getKeyPrefix() { 11 | return "redis-front"; 12 | } 13 | 14 | public RedisFrontPrefs(String rootPath) { 15 | super(rootPath); 16 | } 17 | 18 | 19 | @Override 20 | protected void initDefaults() { 21 | setDbFileName("redis-front.db"); 22 | } 23 | 24 | public boolean getDBInitialized() { 25 | return getState().getBoolean("redis-front-databaseInitialized", false); 26 | } 27 | 28 | public void setDBInitialized(boolean databaseInitialized) { 29 | getState().putBoolean("redis-front-databaseInitialized", databaseInitialized); 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/constant/Constants.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.constant; 2 | 3 | import cn.hutool.core.io.FileUtil; 4 | import cn.hutool.setting.dialect.PropsUtil; 5 | 6 | import java.io.File; 7 | 8 | /** 9 | * Constant 10 | * 11 | * @author Jin 12 | */ 13 | 14 | public class Constants { 15 | 16 | public static final String APP_NAME = "RedisFront"; 17 | public static final String APP_THEME_PACKAGE = "org.dromara.redisfront.theme"; 18 | public static final String APP_RESOURCE_BUNDLE = "org.dromara.redisfront.RedisFront"; 19 | 20 | public static final String SQL_CREATE_CONNECT_DETAIL = """ 21 | create table connect_detail 22 | ( 23 | id integer not null 24 | constraint connect_detail_pk 25 | primary key autoincrement, 26 | name TEXT, 27 | group_id integer, 28 | host TEXT, 29 | port integer, 30 | username TEXT, 31 | password TEXT, 32 | connect_mode TEXT, 33 | redis_mode TEXT, 34 | setting TEXT, 35 | enable_ssl integer, 36 | ssl_config TEXT, 37 | ssh_config TEXT 38 | ); 39 | """; 40 | public static final String SQL_CREATE_CONNECT_GROUP = """ 41 | create table connect_group 42 | ( 43 | group_id integer not null 44 | constraint connect_group_pk 45 | primary key autoincrement, 46 | group_name TEXT, 47 | enable_ssh integer default 0, 48 | ssh_config TEXT 49 | ); 50 | """; 51 | 52 | 53 | public static final String KEY_THEME = "theme1"; 54 | public static final String KEY_THEME_SELECT_INDEX = "selectThemeIndex"; 55 | 56 | public static final String KEY_FONT_NAME = "fontName"; 57 | 58 | public static final String KEY_FONT_SIZE = "fontSize"; 59 | public static final String KEY_SSH_TIMEOUT = "sshTimeout"; 60 | public static final String KEY_REDIS_TIMEOUT = "redisTimeout"; 61 | 62 | public static final String KEY_KEY_SEPARATOR = "keySeparator"; 63 | 64 | public static final String KEY_KEY_MAX_LOAD_NUM = "keyMaxLoadNum"; 65 | 66 | public static final String KEY_APP_DATABASE_INIT = "appDatabaseInit"; 67 | 68 | public static final String KEY_LANGUAGE = "language"; 69 | 70 | @Deprecated 71 | public static final String DATA_PATH = FileUtil.getUserHomePath() + File.separator + "redis-front"; 72 | @Deprecated 73 | public static final String CONFIG_DATA_PATH = DATA_PATH + File.separator + "config"; 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/enums/ConnectType.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.enums; 2 | 3 | public enum ConnectType { 4 | NORMAL, 5 | SSH; 6 | 7 | public static ConnectType of(String type) { 8 | for (ConnectType connectType : values()) { 9 | if (connectType.name().equals(type)) { 10 | return connectType; 11 | } 12 | } 13 | return NORMAL; 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/enums/KeyTypeEnum.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.enums; 2 | 3 | import java.awt.*; 4 | 5 | public enum KeyTypeEnum { 6 | STRING("String", new Color(20, 92, 205)), 7 | LIST("List", new Color(222, 138, 4)), 8 | HASH("Hash", new Color(56, 176, 63)), 9 | SET("Set", new Color(3, 148, 166)), 10 | ZSET("ZSet", new Color(174, 30, 20)), 11 | JSON("Json", new Color(134, 102, 184)), 12 | STREAM("Stream", new Color(234, 100, 74)); 13 | 14 | 15 | private final Color color; 16 | private final String typeName; 17 | 18 | KeyTypeEnum(String typeName, Color color) { 19 | this.color = color; 20 | this.typeName = typeName; 21 | } 22 | 23 | public String typeName() { 24 | return typeName; 25 | } 26 | 27 | public Color color() { 28 | return color; 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/enums/RedisMode.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.enums; 2 | 3 | public enum RedisMode { 4 | STANDALONE("MainTabbedPanel.RedisMode.standalone"), 5 | SENTINEL("MainTabbedPanel.RedisMode.sentinel"), 6 | CLUSTER("MainTabbedPanel.RedisMode.cluster"); 7 | 8 | public final String modeName; 9 | 10 | RedisMode(String modeName) { 11 | this.modeName = modeName; 12 | } 13 | 14 | public static RedisMode of(String modeName) { 15 | for (RedisMode redisMode : values()) { 16 | if (redisMode.modeName.equals(modeName)) { 17 | return redisMode; 18 | } 19 | } 20 | return STANDALONE; 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/enums/RedisNodeRole.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.enums; 2 | 3 | public enum RedisNodeRole { 4 | MASTER, 5 | SLAVE, 6 | NORMAL; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/exception/RedisFrontException.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.exception; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import javax.swing.*; 7 | import java.util.function.Supplier; 8 | 9 | public class RedisFrontException extends RuntimeException implements Supplier { 10 | 11 | private final Boolean showMessage; 12 | @Getter 13 | @Setter 14 | private JComponent component; 15 | 16 | public Boolean showMessage() { 17 | return showMessage; 18 | } 19 | 20 | public RedisFrontException(String message) { 21 | super(message); 22 | this.showMessage = false; 23 | } 24 | 25 | public RedisFrontException(String message,JComponent component) { 26 | super(message); 27 | this.showMessage = false; 28 | this.component = component; 29 | } 30 | 31 | 32 | 33 | public RedisFrontException(String message, Boolean showMessage) { 34 | super(message); 35 | this.showMessage = showMessage; 36 | } 37 | 38 | public RedisFrontException(String message, Throwable cause, Boolean showMessage) { 39 | super(message, cause); 40 | this.showMessage = showMessage; 41 | } 42 | 43 | public RedisFrontException(Throwable cause, Boolean showMessage) { 44 | super(cause); 45 | this.showMessage = showMessage; 46 | } 47 | 48 | public RedisFrontException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Boolean showMessage) { 49 | super(message, cause, enableSuppression, writableStackTrace); 50 | this.showMessage = showMessage; 51 | } 52 | 53 | @Override 54 | public Object get() { 55 | return null; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/exception/RedisFrontTimeoutException.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.exception; 2 | 3 | public class RedisFrontTimeoutException extends RedisFrontException { 4 | 5 | public RedisFrontTimeoutException(String message) { 6 | super(message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/jsch/JschUtils.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.jsch; 2 | 3 | import cn.hutool.extra.ssh.JschUtil; 4 | import com.jcraft.jsch.Session; 5 | import org.dromara.redisfront.commons.utils.RedisFrontUtils; 6 | import org.dromara.redisfront.model.context.RedisConnectContext; 7 | 8 | /** 9 | * JSchUtil 10 | * 11 | * @author Jin 12 | */ 13 | public class JschUtils { 14 | 15 | 16 | public static Session createSession(RedisConnectContext redisConnectContext) { 17 | RedisConnectContext.SshInfo sshInfo = redisConnectContext.getSshInfo(); 18 | if (RedisFrontUtils.isNotEmpty(sshInfo.getPrivateKeyPath()) && RedisFrontUtils.isNotEmpty(sshInfo.getPassword())) { 19 | return JschUtil.createSession(sshInfo.getHost(), sshInfo.getPort(), sshInfo.getUser(), sshInfo.getPrivateKeyPath(), sshInfo.getPassword().getBytes()); 20 | } else if (RedisFrontUtils.isNotEmpty(sshInfo.getPrivateKeyPath())) { 21 | return JschUtil.createSession(sshInfo.getHost(), sshInfo.getPort(), sshInfo.getUser(), sshInfo.getPrivateKeyPath(), null); 22 | } else { 23 | return JschUtil.createSession(sshInfo.getHost(), sshInfo.getPort(), sshInfo.getUser(), sshInfo.getPassword()); 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/lettuce/AddressMappingResolver.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.lettuce; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import io.lettuce.core.RedisURI; 5 | import io.lettuce.core.resource.SocketAddressResolver; 6 | import org.dromara.redisfront.model.context.RedisConnectContext; 7 | 8 | import java.net.InetSocketAddress; 9 | import java.net.SocketAddress; 10 | 11 | public class AddressMappingResolver extends SocketAddressResolver { 12 | private final RedisConnectContext redisConnectContext; 13 | 14 | public AddressMappingResolver(RedisConnectContext redisConnectContext) { 15 | this.redisConnectContext = redisConnectContext; 16 | } 17 | 18 | 19 | @Override 20 | public SocketAddress resolve(RedisURI redisURI) { 21 | if (redisConnectContext.getSshInfo() != null && CollUtil.isNotEmpty(redisConnectContext.getClusterLocalPort())) { 22 | Integer port = redisConnectContext.getClusterLocalPort().get(redisURI.getPort()); 23 | if (port != null) { 24 | return new InetSocketAddress("127.0.0.1", port); 25 | } 26 | } 27 | return super.resolve(redisURI); 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/pool/CleanMode.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.pool; 2 | 3 | public enum CleanMode { 4 | ALL, 5 | CLUSTER_ONLY, 6 | SENTINEL_ONLY, 7 | CONTEXT, 8 | NORMAL_ONLY 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/pool/ConnectionSupplier.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.pool; 2 | 3 | @FunctionalInterface 4 | public interface ConnectionSupplier { 5 | T get() throws Exception; 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/pool/RedisConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.pool; 2 | 3 | import io.lettuce.core.api.StatefulConnection; 4 | import io.lettuce.core.resource.ClientResources; 5 | import org.apache.commons.pool2.BasePooledObjectFactory; 6 | import org.apache.commons.pool2.PooledObject; 7 | import org.apache.commons.pool2.impl.DefaultPooledObject; 8 | 9 | public class RedisConnectionFactory extends BasePooledObjectFactory { 10 | private final ConnectionSupplier supplier; 11 | 12 | public RedisConnectionFactory(ConnectionSupplier supplier) { 13 | this.supplier = supplier; 14 | } 15 | 16 | @Override 17 | public T create() throws Exception { 18 | return supplier.get(); 19 | } 20 | 21 | @Override 22 | public PooledObject wrap(T obj) { 23 | return new DefaultPooledObject<>(obj); 24 | } 25 | 26 | @Override 27 | public boolean validateObject(PooledObject p) { 28 | if (p.getObject() instanceof StatefulConnection statefulConnection) { 29 | return statefulConnection.isOpen(); 30 | } 31 | return false; 32 | } 33 | 34 | @Override 35 | public void destroyObject(PooledObject p) { 36 | if (p.getObject() instanceof StatefulConnection statefulConnection) { 37 | ClientResources resources = statefulConnection.getResources(); 38 | statefulConnection.flushCommands(); 39 | statefulConnection.close(); 40 | resources.shutdown(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/utils/AlertUtils.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.utils; 2 | 3 | import org.dromara.redisfront.RedisFrontMain; 4 | 5 | import javax.swing.*; 6 | import java.awt.*; 7 | 8 | /** 9 | * DialogUtil 10 | * 11 | * @author Jin 12 | */ 13 | public class AlertUtils { 14 | 15 | private AlertUtils() { 16 | } 17 | 18 | public static void showInformationDialog(Component owner,String message) { 19 | JOptionPane.showMessageDialog(SwingUtilities.windowForComponent(owner), 20 | message, 21 | "RedisFront", JOptionPane.INFORMATION_MESSAGE); 22 | } 23 | 24 | public static void showInformationDialog(Component owner,String message, Throwable ex) { 25 | JOptionPane.showMessageDialog(SwingUtilities.windowForComponent(owner), 26 | message + "\n\n" + ex.getMessage(), 27 | "RedisFront", JOptionPane.INFORMATION_MESSAGE); 28 | } 29 | 30 | public static void showErrorDialog(Component owner,String message, Throwable ex) { 31 | JOptionPane.showMessageDialog(SwingUtilities.windowForComponent(owner), 32 | message + "\n\n" + ex.getMessage(), 33 | "RedisFront", JOptionPane.ERROR_MESSAGE); 34 | } 35 | 36 | 37 | public static int showConfirmDialog(Component owner, String message, int optionType) { 38 | return JOptionPane.showConfirmDialog(SwingUtilities.windowForComponent(owner), 39 | message, 40 | "RedisFront", optionType, JOptionPane.INFORMATION_MESSAGE); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/utils/FutureUtils.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.utils; 2 | 3 | 4 | import java.util.concurrent.CompletableFuture; 5 | import java.util.concurrent.ExecutorService; 6 | import java.util.concurrent.Executors; 7 | import java.util.function.Consumer; 8 | import java.util.function.Supplier; 9 | 10 | /** 11 | * ExectorUtil 12 | * 13 | * @author Jin 14 | */ 15 | public class FutureUtils { 16 | private static final int MAX_WORKER_THREADS = 10; 17 | 18 | private static final ExecutorService executorService; 19 | 20 | static { 21 | executorService = Executors.newFixedThreadPool(MAX_WORKER_THREADS, runnable -> { 22 | final var threadFactory = Executors.defaultThreadFactory(); 23 | final var newThread = threadFactory.newThread(runnable); 24 | newThread.setName("RedisFrontWorker-" + newThread.getName()); 25 | newThread.setDaemon(true); 26 | return newThread; 27 | }); 28 | } 29 | 30 | public static CompletableFuture runAsync(Runnable runnable) { 31 | return CompletableFuture.runAsync(runnable); 32 | } 33 | 34 | public static void runAsync(Runnable runnable, Consumer consumer) { 35 | CompletableFuture.runAsync(runnable, executorService).exceptionallyAsync(throwable -> { 36 | consumer.accept(throwable); 37 | return null; 38 | }); 39 | } 40 | 41 | public static CompletableFuture supplyAsync(Supplier supplier, Consumer consumer) { 42 | return CompletableFuture.supplyAsync(supplier, executorService).thenAccept(t -> { 43 | if (RedisFrontUtils.isNotNull(t)) { 44 | consumer.accept(t); 45 | } 46 | }); 47 | } 48 | 49 | public static CompletableFuture supplyAsync(Supplier supplier) { 50 | return CompletableFuture.supplyAsync(supplier, executorService); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/utils/MD5Util.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.utils; 2 | 3 | import java.nio.charset.StandardCharsets; 4 | import java.security.MessageDigest; 5 | 6 | public class MD5Util { 7 | 8 | public static String encrypt(String input) { 9 | try { 10 | MessageDigest md = MessageDigest.getInstance("MD5"); 11 | byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8)); 12 | return bytesToHex(digest); 13 | } catch (Exception e) { 14 | throw new RuntimeException("MD5加密失败", e); 15 | } 16 | } 17 | 18 | private static String bytesToHex(byte[] bytes) { 19 | StringBuilder hexString = new StringBuilder(); 20 | for (byte b : bytes) { 21 | String hex = Integer.toHexString(0xff & b); 22 | if (hex.length() == 1) hexString.append('0'); 23 | hexString.append(hex); 24 | } 25 | return hexString.toString(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/commons/utils/UpgradeUtils.kt: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.utils 2 | 3 | import cn.hutool.core.swing.DesktopUtil 4 | import cn.hutool.core.util.StrUtil 5 | import cn.hutool.http.HttpUtil 6 | import cn.hutool.json.JSONUtil 7 | import javax.swing.JOptionPane 8 | 9 | /** 10 | * Upgrade 11 | * @author Jin 12 | */ 13 | open class UpgradeUtils { 14 | companion object { 15 | private const val GITEE_URL = "https://gitee.com/dromara/RedisFront/raw/master/assets/version.json" 16 | 17 | @JvmStatic 18 | fun checkVersion(currentVersion: String) { 19 | 20 | val httpRequest = HttpUtil.createGet(GITEE_URL) 21 | val httpResponse = httpRequest.execute() 22 | 23 | if (httpResponse.isOk) { 24 | val body = httpResponse.body() 25 | val versionObject = JSONUtil.parseObj(body) 26 | val newVersion = versionObject.getStr("version") 27 | if (StrUtil.compareVersion(newVersion, currentVersion) == 0) { 28 | return 29 | } 30 | 31 | val downloadUrl = 32 | versionObject.getStr("downloadUrl") ?: "https://gitee.com/dromara/RedisFront/releases/" 33 | 34 | val confirmDialog = 35 | JOptionPane.showConfirmDialog(null, "发现新版本,是否下载?", "发现新版本", JOptionPane.YES_NO_OPTION) 36 | 37 | if (confirmDialog != JOptionPane.YES_OPTION) { 38 | return 39 | } 40 | 41 | DesktopUtil.browse(downloadUrl) 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/dao/ConnectDetailDao.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.dao; 2 | 3 | import cn.hutool.db.DbUtil; 4 | import cn.hutool.db.Entity; 5 | import org.dromara.redisfront.model.entity.ConnectDetailEntity; 6 | 7 | import javax.sql.DataSource; 8 | import java.sql.SQLException; 9 | import java.util.List; 10 | 11 | /** 12 | * ConnectService 13 | * 14 | * @author Jin 15 | */ 16 | public class ConnectDetailDao { 17 | 18 | public static final String TABLE_NAME = "connect_detail"; 19 | 20 | private final DataSource datasource; 21 | 22 | public static ConnectDetailDao newInstance(DataSource datasource) { 23 | return new ConnectDetailDao(datasource); 24 | } 25 | 26 | private ConnectDetailDao(DataSource datasource) { 27 | this.datasource = datasource; 28 | } 29 | 30 | public List loadAll() throws SQLException { 31 | return DbUtil.use(datasource).findAll(Entity.create(TABLE_NAME).set("group_id", -1), ConnectDetailEntity.class); 32 | } 33 | 34 | public List loadAll(Object id) throws SQLException { 35 | return DbUtil.use(datasource).findAll(Entity.create(TABLE_NAME).set("group_id", id), ConnectDetailEntity.class); 36 | } 37 | 38 | public ConnectDetailEntity getById(Object id) throws SQLException { 39 | Entity entity = DbUtil.use(datasource).get(TABLE_NAME, "group_id", id); 40 | return entity.toBean(ConnectDetailEntity.class); 41 | } 42 | 43 | public void save(ConnectDetailEntity connectDetailEntity) throws SQLException { 44 | Entity entity = Entity.create(TABLE_NAME).parseBean(connectDetailEntity, true, true); 45 | DbUtil.use(datasource).insert(entity); 46 | } 47 | 48 | public void update(Object id, ConnectDetailEntity connectDetailEntity) throws SQLException { 49 | Entity entity = Entity.create(TABLE_NAME) 50 | .parseBean(connectDetailEntity, true, true); 51 | DbUtil.use(datasource).update(entity, Entity.create().set("id", id)); 52 | } 53 | 54 | public void delete(Object id) throws SQLException { 55 | DbUtil.use(datasource).del(TABLE_NAME, "id", id); 56 | } 57 | public void deleteByGroupId(Object id) throws SQLException { 58 | DbUtil.use(datasource).del(TABLE_NAME, "group_id", id); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/dao/ConnectGroupDao.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.dao; 2 | 3 | import cn.hutool.db.DbUtil; 4 | import cn.hutool.db.Entity; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.dromara.redisfront.model.entity.ConnectGroupEntity; 7 | 8 | import javax.sql.DataSource; 9 | import java.sql.SQLException; 10 | import java.util.List; 11 | 12 | /** 13 | * ConnectGroupDao 14 | * 15 | * @author Jin 16 | */ 17 | @Slf4j 18 | public class ConnectGroupDao { 19 | private final DataSource datasource; 20 | public static final String TABLE_NAME = "connect_group"; 21 | public static ConnectGroupDao newInstance(DataSource datasource) { 22 | return new ConnectGroupDao(datasource); 23 | } 24 | 25 | private ConnectGroupDao(DataSource datasource) { 26 | this.datasource = datasource; 27 | } 28 | 29 | public long count() throws SQLException { 30 | return DbUtil.use(datasource).count(Entity.create(TABLE_NAME)); 31 | } 32 | 33 | public List loadAll() throws SQLException { 34 | return DbUtil.use(datasource).findAll(Entity.create(TABLE_NAME), ConnectGroupEntity.class); 35 | } 36 | 37 | public ConnectGroupEntity getById(Object id) throws SQLException { 38 | Entity entity = DbUtil.use(datasource).get(TABLE_NAME, "group_id", id); 39 | return entity.toBean(ConnectGroupEntity.class); 40 | } 41 | 42 | public void save(String groupName) throws SQLException { 43 | Entity connectGroup = Entity.create(TABLE_NAME); 44 | connectGroup.set("group_name", groupName); 45 | DbUtil.use(datasource).insert(connectGroup); 46 | } 47 | 48 | public void update(Object id,String groupName) throws SQLException { 49 | DbUtil.use(datasource).update(Entity.create(TABLE_NAME) 50 | .set("group_name", groupName), 51 | Entity.create(TABLE_NAME) 52 | .set("group_id", id)); 53 | } 54 | 55 | public void delete(Object id) throws SQLException { 56 | DbUtil.use(datasource).del(Entity.create(TABLE_NAME).set("group_id", id)); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/ClusterNode.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model; 2 | 3 | public class ClusterNode { 4 | private String id; 5 | private String ipAndPort; 6 | private String flags; 7 | private String master; 8 | private String ping; 9 | private String pong; 10 | private String epoch; 11 | private String state; 12 | private String slot; 13 | private String host; 14 | private Integer port; 15 | 16 | public String id() { 17 | return id; 18 | } 19 | 20 | public ClusterNode setId(String id) { 21 | this.id = id; 22 | return this; 23 | } 24 | 25 | public String ipAndPort() { 26 | return ipAndPort; 27 | } 28 | 29 | public ClusterNode setIpAndPort(String ipAndPort) { 30 | this.ipAndPort = ipAndPort; 31 | return this; 32 | } 33 | 34 | public String flags() { 35 | return flags; 36 | } 37 | 38 | public ClusterNode setFlags(String flags) { 39 | this.flags = flags; 40 | return this; 41 | } 42 | 43 | public String master() { 44 | return master; 45 | } 46 | 47 | public ClusterNode setMaster(String master) { 48 | this.master = master; 49 | return this; 50 | } 51 | 52 | public String ping() { 53 | return ping; 54 | } 55 | 56 | public ClusterNode setPing(String ping) { 57 | this.ping = ping; 58 | return this; 59 | } 60 | 61 | public String pong() { 62 | return pong; 63 | } 64 | 65 | public ClusterNode setPong(String pong) { 66 | this.pong = pong; 67 | return this; 68 | } 69 | 70 | public String epoch() { 71 | return epoch; 72 | } 73 | 74 | public ClusterNode setEpoch(String epoch) { 75 | this.epoch = epoch; 76 | return this; 77 | } 78 | 79 | public String state() { 80 | return state; 81 | } 82 | 83 | public ClusterNode setState(String state) { 84 | this.state = state; 85 | return this; 86 | } 87 | 88 | public String slot() { 89 | return slot; 90 | } 91 | 92 | public ClusterNode setSlot(String slot) { 93 | this.slot = slot; 94 | return this; 95 | } 96 | 97 | public String host() { 98 | return host; 99 | } 100 | 101 | public ClusterNode setHost(String host) { 102 | this.host = host; 103 | return this; 104 | } 105 | 106 | public Integer port() { 107 | return port; 108 | } 109 | 110 | public ClusterNode setPort(Integer port) { 111 | this.port = port; 112 | return this; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/DbInfo.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model; 2 | 3 | import lombok.Setter; 4 | import org.dromara.redisfront.commons.utils.RedisFrontUtils; 5 | 6 | /** 7 | * DbInfo 8 | * 9 | * @author Jin 10 | */ 11 | public class DbInfo { 12 | private String dbName; 13 | private Integer dbIndex; 14 | @Setter 15 | private Long dbSize; 16 | 17 | public DbInfo(String dbName, Integer dbIndex) { 18 | this.dbName = dbName; 19 | this.dbIndex = dbIndex; 20 | } 21 | 22 | public String dbName() { 23 | return dbName; 24 | } 25 | 26 | public DbInfo setDbName(String dbName) { 27 | this.dbName = dbName; 28 | return this; 29 | } 30 | 31 | public Integer dbIndex() { 32 | return dbIndex; 33 | } 34 | 35 | public DbInfo setDbIndex(Integer dbIndex) { 36 | this.dbIndex = dbIndex; 37 | return this; 38 | } 39 | 40 | public Long dbSize() { 41 | return dbSize; 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return RedisFrontUtils.isNotEmpty(dbSize) ? dbName + " [" + dbSize + "]" : dbName; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/LogInfo.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | public class LogInfo { 6 | 7 | private LocalDateTime date; 8 | private String ip; 9 | private String info; 10 | 11 | public String ip() { 12 | return ip; 13 | } 14 | 15 | public LogInfo setIp(String ip) { 16 | this.ip = ip; 17 | return this; 18 | } 19 | 20 | public LocalDateTime date() { 21 | return date; 22 | } 23 | 24 | public LogInfo setDate(LocalDateTime date) { 25 | this.date = date; 26 | return this; 27 | } 28 | 29 | public String info() { 30 | return info; 31 | } 32 | 33 | public LogInfo setInfo(String info) { 34 | this.info = info; 35 | return this; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/MessageInfo.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model; 2 | 3 | 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * ConnectInfo 11 | * 12 | * @author Jin 13 | */ 14 | @Setter 15 | @Getter 16 | public class MessageInfo implements Serializable { 17 | 18 | private String date; 19 | private String channel; 20 | private String message; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/RedisNode.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import org.dromara.redisfront.commons.enums.RedisNodeRole; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | public class RedisNode { 10 | private String uri; 11 | private Integer port; 12 | private RedisNodeRole role; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/entity/ConnectDetailEntity.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.entity; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | import cn.hutool.json.JSONUtil; 5 | import lombok.Data; 6 | import org.dromara.redisfront.commons.enums.ConnectType; 7 | import org.dromara.redisfront.model.context.RedisConnectContext; 8 | 9 | @Data 10 | public class ConnectDetailEntity { 11 | private Integer id; 12 | private String name; 13 | private Integer groupId = -1; 14 | private String host; 15 | private Integer port; 16 | private String username; 17 | private String password; 18 | private Integer enableSsl; 19 | private String connectMode; 20 | private String setting; 21 | private String sslConfig; 22 | private String sshConfig; 23 | 24 | public RedisConnectContext getConnectContext() { 25 | RedisConnectContext redisConnectContext = new RedisConnectContext(); 26 | redisConnectContext.setId(id); 27 | redisConnectContext.setTitle(name); 28 | redisConnectContext.setHost(host); 29 | redisConnectContext.setPort(port); 30 | redisConnectContext.setUsername(username); 31 | redisConnectContext.setPassword(password); 32 | redisConnectContext.setConnectTypeMode(ConnectType.of(connectMode)); 33 | if (StrUtil.isNotEmpty(setting)) { 34 | RedisConnectContext.SettingInfo settingInfo = JSONUtil.toBean(setting, RedisConnectContext.SettingInfo.class); 35 | redisConnectContext.setSetting(settingInfo); 36 | } 37 | if (StrUtil.isNotEmpty(sslConfig)) { 38 | RedisConnectContext.SslInfo sslInfo = JSONUtil.toBean(sslConfig, RedisConnectContext.SslInfo.class); 39 | redisConnectContext.setSslInfo(sslInfo); 40 | } 41 | if (StrUtil.isNotEmpty(sshConfig)) { 42 | RedisConnectContext.SshInfo sshInfo = JSONUtil.toBean(sshConfig, RedisConnectContext.SshInfo.class); 43 | redisConnectContext.setSshInfo(sshInfo); 44 | } 45 | return redisConnectContext; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/entity/ConnectGroupEntity.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.entity; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class ConnectGroupEntity { 7 | private Integer groupId; 8 | private String groupName; 9 | private Integer enableSsh; 10 | private String sshConfig; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/event/RedisFrontEvent.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.event; 2 | 3 | import lombok.Getter; 4 | import org.dromara.quickswing.events.QSEvent; 5 | import org.dromara.redisfront.model.context.RedisConnectContext; 6 | 7 | @Getter 8 | public class RedisFrontEvent extends QSEvent { 9 | private final RedisConnectContext redisConnectContext; 10 | 11 | public RedisFrontEvent(Object source, RedisConnectContext redisConnectContext) { 12 | super(source); 13 | this.redisConnectContext = redisConnectContext; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/table/HashTableModel.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.table; 2 | 3 | import cn.hutool.core.io.unit.DataSizeUtil; 4 | 5 | import javax.swing.table.DefaultTableModel; 6 | import java.util.*; 7 | 8 | /** 9 | * Redis Connection TableModel 10 | */ 11 | public class HashTableModel extends DefaultTableModel { 12 | 13 | private final Class[] columnTypes = new Class[]{ 14 | String.class, String.class, Integer.class, String.class, Integer.class, String.class 15 | }; 16 | private final boolean[] columnEditable = new boolean[]{ 17 | false, false, false, false, false, false 18 | }; 19 | 20 | public HashTableModel(List> dataList) { 21 | var dataVector = new Object[dataList.size()][6]; 22 | for (var i = 0; i < dataList.size(); i++) { 23 | Map.Entry Entry = dataList.get(i); 24 | dataVector[i][0] = Entry.getKey(); 25 | dataVector[i][1] = Entry.getValue(); 26 | dataVector[i][2] = Entry.getKey().length(); 27 | dataVector[i][3] = DataSizeUtil.format(Entry.getKey().getBytes().length); 28 | dataVector[i][4] = Entry.getValue().length(); 29 | dataVector[i][5] = DataSizeUtil.format(Entry.getValue().getBytes().length); 30 | ; 31 | } 32 | this.setDataVector(dataVector, new String[]{"key", "Value", "KeyLength", "KeySize", "ValueLength", "ValueSize"}); 33 | } 34 | 35 | 36 | @Override 37 | public Class getColumnClass(int columnIndex) { 38 | return columnTypes[columnIndex]; 39 | } 40 | 41 | @Override 42 | public boolean isCellEditable(int rowIndex, int columnIndex) { 43 | return columnEditable[columnIndex]; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/table/ListTableModel.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.table; 2 | 3 | import cn.hutool.core.io.unit.DataSizeUtil; 4 | 5 | import javax.swing.table.DefaultTableModel; 6 | import java.util.List; 7 | 8 | /** 9 | * Redis Connection TableModel 10 | */ 11 | public class ListTableModel extends DefaultTableModel { 12 | 13 | private final Class[] columnTypes = new Class[]{ 14 | Integer.class, String.class, Integer.class, String.class 15 | }; 16 | private final boolean[] columnEditable = new boolean[]{ 17 | false, false, false, false 18 | }; 19 | 20 | public ListTableModel(List dataList) { 21 | var dataVector = new Object[dataList.size()][4]; 22 | for (var i = 0; i < dataList.size(); i++) { 23 | dataVector[i][0] = i + 1; 24 | dataVector[i][1] = dataList.get(i); 25 | dataVector[i][2] = dataList.get(i).length(); 26 | dataVector[i][3] = DataSizeUtil.format(dataList.get(i).getBytes().length); 27 | } 28 | this.setDataVector(dataVector, new String[]{"#", "Value", "Length", "Size"}); 29 | } 30 | 31 | 32 | @Override 33 | public Class getColumnClass(int columnIndex) { 34 | return columnTypes[columnIndex]; 35 | } 36 | 37 | @Override 38 | public boolean isCellEditable(int rowIndex, int columnIndex) { 39 | return columnEditable[columnIndex]; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/table/PubSubTableModel.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.table; 2 | 3 | import org.dromara.redisfront.model.MessageInfo; 4 | 5 | import javax.swing.table.DefaultTableModel; 6 | import java.util.List; 7 | 8 | /** 9 | * Redis Connection TableModel 10 | */ 11 | public class PubSubTableModel extends DefaultTableModel { 12 | 13 | private final Class[] columnTypes = new Class[]{ 14 | String.class, String.class, String.class 15 | }; 16 | private final boolean[] columnEditable = new boolean[]{ 17 | false, true, true 18 | }; 19 | 20 | public PubSubTableModel(List dataList) { 21 | var dataVector = new Object[dataList.size()][3]; 22 | for (var i = 0; i < dataList.size(); i++) { 23 | dataVector[i][0] = dataList.get(i).getDate(); 24 | dataVector[i][1] = dataList.get(i).getChannel(); 25 | dataVector[i][2] = dataList.get(i).getMessage(); 26 | } 27 | this.setDataVector(dataVector, new String[]{ 28 | "时间", 29 | "通道", 30 | "消息", 31 | }); 32 | } 33 | 34 | 35 | @Override 36 | public Class getColumnClass(int columnIndex) { 37 | return columnTypes[columnIndex]; 38 | } 39 | 40 | @Override 41 | public boolean isCellEditable(int rowIndex, int columnIndex) { 42 | return columnEditable[columnIndex]; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/table/SetTableModel.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.table; 2 | 3 | import cn.hutool.core.io.unit.DataSizeUtil; 4 | 5 | import javax.swing.table.DefaultTableModel; 6 | import java.util.List; 7 | 8 | /** 9 | * Redis Connection TableModel 10 | */ 11 | public class SetTableModel extends DefaultTableModel { 12 | 13 | private final Class[] columnTypes = new Class[]{ 14 | Integer.class, String.class, Integer.class, String.class 15 | }; 16 | private final boolean[] columnEditable = new boolean[]{ 17 | false, false, false, false 18 | }; 19 | 20 | public SetTableModel(List dataList) { 21 | var dataVector = new Object[dataList.size()][4]; 22 | for (var i = 0; i < dataList.size(); i++) { 23 | dataVector[i][0] = i + 1; 24 | dataVector[i][1] = dataList.get(i); 25 | dataVector[i][2] = dataList.get(i).length(); 26 | dataVector[i][3] = DataSizeUtil.format(dataList.get(i).getBytes().length); 27 | } 28 | this.setDataVector(dataVector, new String[]{"#", "Value", "Length", "Size"}); 29 | } 30 | 31 | 32 | @Override 33 | public Class getColumnClass(int columnIndex) { 34 | return columnTypes[columnIndex]; 35 | } 36 | 37 | @Override 38 | public boolean isCellEditable(int rowIndex, int columnIndex) { 39 | return columnEditable[columnIndex]; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/table/SortedSetTableModel.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.table; 2 | 3 | import cn.hutool.core.io.unit.DataSizeUtil; 4 | import io.lettuce.core.ScoredValue; 5 | 6 | import javax.swing.table.DefaultTableModel; 7 | import java.util.List; 8 | 9 | /** 10 | * Redis Connection TableModel 11 | */ 12 | public class SortedSetTableModel extends DefaultTableModel { 13 | 14 | private final Class[] columnTypes = new Class[]{ 15 | Integer.class, Double.class, String.class, Integer.class, String.class 16 | }; 17 | private final boolean[] columnEditable = new boolean[]{ 18 | false, false, false, false, false 19 | }; 20 | 21 | public SortedSetTableModel(List> dataList) { 22 | var dataVector = new Object[dataList.size()][5]; 23 | for (var i = 0; i < dataList.size(); i++) { 24 | dataVector[i][0] = i + 1; 25 | dataVector[i][1] = dataList.get(i).getScore(); 26 | dataVector[i][2] = dataList.get(i).getValue(); 27 | dataVector[i][3] = dataList.get(i).getValue().length(); 28 | dataVector[i][4] = DataSizeUtil.format(dataList.get(i).getValue().getBytes().length); 29 | } 30 | this.setDataVector(dataVector, new String[]{"#", "Score", "Value", "Length", "Size"}); 31 | } 32 | 33 | 34 | @Override 35 | public Class getColumnClass(int columnIndex) { 36 | return columnTypes[columnIndex]; 37 | } 38 | 39 | @Override 40 | public boolean isCellEditable(int rowIndex, int columnIndex) { 41 | return columnEditable[columnIndex]; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/table/StreamTableModel.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.table; 2 | 3 | import cn.hutool.json.JSONUtil; 4 | import io.lettuce.core.StreamMessage; 5 | 6 | import javax.swing.table.DefaultTableModel; 7 | import java.util.List; 8 | 9 | /** 10 | * Redis Connection TableModel 11 | */ 12 | public class StreamTableModel extends DefaultTableModel { 13 | 14 | private final Class[] columnTypes = new Class[]{ 15 | Integer.class, String.class, String.class 16 | }; 17 | private final boolean[] columnEditable = new boolean[]{ 18 | false, false, false 19 | }; 20 | 21 | public StreamTableModel(List> dataList) { 22 | var dataVector = new Object[dataList.size()][4]; 23 | for (var i = 0; i < dataList.size(); i++) { 24 | dataVector[i][0] = i + 1; 25 | dataVector[i][1] = dataList.get(i).getId(); 26 | dataVector[i][2] = JSONUtil.toJsonStr(dataList.get(i).getBody()) ; 27 | } 28 | this.setDataVector(dataVector, new String[]{"#", "ID","Body"}); 29 | } 30 | 31 | 32 | @Override 33 | public Class getColumnClass(int columnIndex) { 34 | return columnTypes[columnIndex]; 35 | } 36 | 37 | @Override 38 | public boolean isCellEditable(int rowIndex, int columnIndex) { 39 | return columnEditable[columnIndex]; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/turbo/Turbo1.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.turbo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class Turbo1 { 11 | private T t0; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/turbo/Turbo2.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.turbo; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class Turbo2 { 12 | private T1 t1; 13 | private T2 t2; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/turbo/Turbo3.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.turbo; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class Turbo3 { 12 | private T1 t1; 13 | private T2 t2; 14 | private T3 t3; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/turbo/Turbo4.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.turbo; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class Turbo4 { 12 | private T1 t1; 13 | private T2 t2; 14 | private T3 t3; 15 | private T4 t4; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/turbo/Turbo5.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.turbo; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class Turbo5 { 12 | private T1 t1; 13 | private T2 t2; 14 | private T3 t3; 15 | private T4 t4; 16 | private T5 t5; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/model/turbo/Turbo6.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.model.turbo; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class Turbo6 { 12 | private T1 t1; 13 | private T2 t2; 14 | private T3 t3; 15 | private T4 t4; 16 | private T5 t5; 17 | private T6 t6; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/service/RedisHashService.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.service; 2 | 3 | import org.dromara.redisfront.model.context.RedisConnectContext; 4 | import io.lettuce.core.MapScanCursor; 5 | import io.lettuce.core.ScanArgs; 6 | import io.lettuce.core.ScanCursor; 7 | import org.dromara.redisfront.service.impl.RedisHashServiceImpl; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | public interface RedisHashService { 13 | 14 | RedisHashService service = new RedisHashServiceImpl(); 15 | 16 | String hget(RedisConnectContext redisConnectContext, String key, String field); 17 | 18 | Map hgetall(RedisConnectContext redisConnectContext, String key); 19 | 20 | List hkeys(RedisConnectContext redisConnectContext, String key); 21 | 22 | Long hlen(RedisConnectContext redisConnectContext, String key); 23 | 24 | String hmset(RedisConnectContext redisConnectContext, String key, Map map); 25 | 26 | MapScanCursor hscan(RedisConnectContext redisConnectContext, String key, ScanCursor scanCursor, ScanArgs scanArgs); 27 | MapScanCursor hscan(RedisConnectContext redisConnectContext, String key, ScanCursor scanCursor); 28 | 29 | Boolean hset(RedisConnectContext redisConnectContext, String key, String field, String value); 30 | 31 | Long hset(RedisConnectContext redisConnectContext, String key, Map map); 32 | 33 | Long hstrlen(RedisConnectContext redisConnectContext, String key, String field); 34 | 35 | List hvals(RedisConnectContext redisConnectContext, String key); 36 | 37 | Long hdel(RedisConnectContext redisConnectContext, String key, String... fields); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/service/RedisListService.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.service; 2 | 3 | 4 | import org.dromara.redisfront.model.context.RedisConnectContext; 5 | import org.dromara.redisfront.service.impl.RedisListServiceImpl; 6 | 7 | 8 | import java.util.List; 9 | 10 | public interface RedisListService { 11 | 12 | RedisListService service = new RedisListServiceImpl(); 13 | 14 | List lrange(RedisConnectContext redisConnectContext, String key, long start, long stop); 15 | 16 | Long lrem(RedisConnectContext redisConnectContext, String key, long count, String value); 17 | 18 | Long llen(RedisConnectContext redisConnectContext, String key); 19 | 20 | String lpop(RedisConnectContext redisConnectContext, String key); 21 | 22 | List lpop(RedisConnectContext redisConnectContext, String key, long count); 23 | 24 | Long lpush(RedisConnectContext redisConnectContext, String key, String... values); 25 | 26 | String lset(RedisConnectContext redisConnectContext, String key, long index, String value); 27 | 28 | String rpop(RedisConnectContext redisConnectContext, String key); 29 | 30 | List rpop(RedisConnectContext redisConnectContext, String key, long count); 31 | 32 | Long rpush(RedisConnectContext redisConnectContext, String key, String... values); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/service/RedisPubSubService.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.service; 2 | 3 | import org.dromara.redisfront.model.context.RedisConnectContext; 4 | import org.dromara.redisfront.service.impl.RedisPubSubServiceImpl; 5 | 6 | /** 7 | * PubSubService 8 | * 9 | * @author Jin 10 | */ 11 | public interface RedisPubSubService { 12 | RedisPubSubService service = new RedisPubSubServiceImpl(); 13 | 14 | Long publish(RedisConnectContext redisConnectContext, String channel, String message); 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/service/RedisSetService.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.service; 2 | 3 | import org.dromara.redisfront.model.context.RedisConnectContext; 4 | import io.lettuce.core.ScanArgs; 5 | import io.lettuce.core.ScanCursor; 6 | import io.lettuce.core.ValueScanCursor; 7 | import org.dromara.redisfront.service.impl.RedisSetServiceImpl; 8 | 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | public interface RedisSetService { 13 | 14 | RedisSetService service = new RedisSetServiceImpl(); 15 | 16 | Long sadd(RedisConnectContext redisConnectContext, String key, String... members); 17 | 18 | Long scard(RedisConnectContext redisConnectContext, String key); 19 | 20 | Set sdiff(RedisConnectContext redisConnectContext, String... keys); 21 | 22 | 23 | Long sdiffstore(RedisConnectContext redisConnectContext, String destination, String... keys); 24 | 25 | 26 | Set sinter(RedisConnectContext redisConnectContext, String... keys); 27 | 28 | Long sinterstore(RedisConnectContext redisConnectContext, String destination, String... keys); 29 | 30 | Boolean sismember(RedisConnectContext redisConnectContext, String key, String member); 31 | 32 | Set smembers(RedisConnectContext redisConnectContext, String key); 33 | 34 | List smismember(RedisConnectContext redisConnectContext, String key, String... members); 35 | 36 | Boolean smove(RedisConnectContext redisConnectContext, String source, String destination, String member); 37 | 38 | String spop(RedisConnectContext redisConnectContext, String key); 39 | 40 | Set spop(RedisConnectContext redisConnectContext, String key, long count); 41 | 42 | String srandmember(RedisConnectContext redisConnectContext, String key); 43 | 44 | List srandmember(RedisConnectContext redisConnectContext, String key, long count); 45 | 46 | 47 | Long srem(RedisConnectContext redisConnectContext, String key, String... members); 48 | 49 | Set sunion(RedisConnectContext redisConnectContext, String... keys); 50 | 51 | 52 | ValueScanCursor sscan(RedisConnectContext redisConnectContext, String key); 53 | 54 | ValueScanCursor sscan(RedisConnectContext redisConnectContext, String key, ScanCursor scanCursor, ScanArgs scanArgs); 55 | 56 | ValueScanCursor sscan(RedisConnectContext redisConnectContext, String key, ScanCursor scanCursor); 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/service/RedisStreamService.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.service; 2 | 3 | import org.dromara.redisfront.model.context.RedisConnectContext; 4 | import io.lettuce.core.*; 5 | import org.dromara.redisfront.service.impl.RedisStreamServiceImpl; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * RedisStreamService 12 | * 13 | * @author Jin 14 | */ 15 | public interface RedisStreamService { 16 | 17 | RedisStreamService service = new RedisStreamServiceImpl(); 18 | 19 | Long xdel(RedisConnectContext redisConnectContext, String key, String... messageIds); 20 | 21 | Long xack(RedisConnectContext redisConnectContext, String key, String group, String... messageIds); 22 | 23 | String xadd(RedisConnectContext redisConnectContext, String key, Map body); 24 | 25 | String xadd(RedisConnectContext redisConnectContext, String id, String key, Map body); 26 | 27 | List> xrange(RedisConnectContext redisConnectContext, String key, Range range, Limit limit); 28 | 29 | String xadd(RedisConnectContext redisConnectContext, String key, XAddArgs args, Object... keysAndValues); 30 | 31 | String xgroupCreate(RedisConnectContext redisConnectContext, XReadArgs.StreamOffset streamOffset, String group); 32 | 33 | String xgroupCreate(RedisConnectContext redisConnectContext, XReadArgs.StreamOffset streamOffset, String group, XGroupCreateArgs args); 34 | 35 | Long xlen(RedisConnectContext redisConnectContext, String key); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/service/RedisStringService.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.service; 2 | 3 | import org.dromara.redisfront.model.context.RedisConnectContext; 4 | import org.dromara.redisfront.service.impl.RedisStringServiceImpl; 5 | 6 | public interface RedisStringService { 7 | RedisStringService service = new RedisStringServiceImpl(); 8 | 9 | String set(RedisConnectContext redisConnectContext, String key, String value); 10 | 11 | String get(RedisConnectContext redisConnectContext, String key); 12 | 13 | Long strlen(RedisConnectContext redisConnectContext, String key); 14 | 15 | String setex(RedisConnectContext redisConnectContext, String key, long seconds, String value); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/service/RedisZSetService.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.service; 2 | 3 | import org.dromara.redisfront.model.context.RedisConnectContext; 4 | import io.lettuce.core.*; 5 | import org.dromara.redisfront.service.impl.RedisZSetServiceImpl; 6 | 7 | import java.util.List; 8 | 9 | public interface RedisZSetService { 10 | RedisZSetService service = new RedisZSetServiceImpl(); 11 | 12 | Long zadd(RedisConnectContext redisConnectContext, String key, double score, String member); 13 | 14 | Long zadd(RedisConnectContext redisConnectContext, String key, ScoredValue... scoredValues); 15 | 16 | Double zaddincr(RedisConnectContext redisConnectContext, String key, double score, String member); 17 | 18 | Long zcard(RedisConnectContext redisConnectContext, String key); 19 | 20 | Long zrem(RedisConnectContext redisConnectContext, String key, String... members); 21 | List> zrange(RedisConnectContext redisConnectContext, String key, long start, long stop); 22 | 23 | Long zcount(RedisConnectContext redisConnectContext, String key, Range range); 24 | 25 | List zrangebyscore(RedisConnectContext redisConnectContext, String key, Range range, Limit limit); 26 | 27 | List> zrangebyscoreWithScores(RedisConnectContext redisConnectContext, String key, Range range); 28 | 29 | List zrevrangebyscore(RedisConnectContext redisConnectContext, String key, Range range, Limit limit); 30 | 31 | Long zrevrank(RedisConnectContext redisConnectContext, String key, String member); 32 | 33 | ScoredValueScanCursor zscan(RedisConnectContext redisConnectContext, String key); 34 | 35 | ScoredValueScanCursor zscan(RedisConnectContext redisConnectContext, String key, ScanArgs scanArgs); 36 | 37 | ScoredValueScanCursor zscan(RedisConnectContext redisConnectContext, String key, ScanCursor scanCursor, ScanArgs scanArgs); 38 | 39 | ScoredValueScanCursor zscan(RedisConnectContext redisConnectContext, String key, ScanCursor scanCursor); 40 | Double zscore(RedisConnectContext redisConnectContext, String key, String member); 41 | 42 | ScoredValue zpopmin(RedisConnectContext redisConnectContext, String key); 43 | 44 | List> zpopmin(RedisConnectContext redisConnectContext, String key, long count); 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/service/impl/RedisPubSubServiceImpl.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.service.impl; 2 | 3 | import org.dromara.redisfront.commons.utils.RedisFrontUtils; 4 | import org.dromara.redisfront.commons.enums.RedisMode; 5 | import org.dromara.redisfront.commons.lettuce.LettuceUtils; 6 | import org.dromara.redisfront.model.context.RedisConnectContext; 7 | import org.dromara.redisfront.service.RedisPubSubService; 8 | 9 | /** 10 | * PubSubServiceImpl 11 | * 12 | * @author Jin 13 | */ 14 | public class RedisPubSubServiceImpl implements RedisPubSubService { 15 | 16 | @Override 17 | public Long publish(RedisConnectContext redisConnectContext, String channel, String message) { 18 | if (RedisFrontUtils.equal(redisConnectContext.getRedisMode(), RedisMode.CLUSTER)) { 19 | return LettuceUtils.clusterExec(redisConnectContext, clusterCommands -> clusterCommands.publish(channel, message)); 20 | } else { 21 | return LettuceUtils.exec(redisConnectContext, commands -> commands.publish(channel, message)); 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/service/impl/RedisStringServiceImpl.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.service.impl; 2 | 3 | import org.dromara.redisfront.commons.enums.RedisMode; 4 | import org.dromara.redisfront.model.context.RedisConnectContext; 5 | import org.dromara.redisfront.commons.utils.RedisFrontUtils; 6 | import org.dromara.redisfront.commons.lettuce.LettuceUtils; 7 | import org.dromara.redisfront.service.RedisBasicService; 8 | import org.dromara.redisfront.service.RedisStringService; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class RedisStringServiceImpl implements RedisStringService { 13 | 14 | private static final Logger log = LoggerFactory.getLogger(RedisStringServiceImpl.class); 15 | 16 | 17 | @Override 18 | public String set(RedisConnectContext redisConnectContext, String key, String value) { 19 | 20 | if (RedisFrontUtils.equal(redisConnectContext.getRedisMode(), RedisMode.CLUSTER)) { 21 | return LettuceUtils.clusterExec(redisConnectContext, commands -> commands.set(key, value)); 22 | } else { 23 | return LettuceUtils.exec(redisConnectContext, commands -> commands.set(key, value)); 24 | } 25 | } 26 | 27 | @Override 28 | public String get(RedisConnectContext redisConnectContext, String key) { 29 | 30 | if (RedisFrontUtils.equal(redisConnectContext.getRedisMode(), RedisMode.CLUSTER)) { 31 | return LettuceUtils.clusterExec(redisConnectContext, commands -> commands.get(key)); 32 | } else { 33 | return LettuceUtils.exec(redisConnectContext, commands -> commands.get(key)); 34 | } 35 | } 36 | 37 | @Override 38 | public Long strlen(RedisConnectContext redisConnectContext, String key) { 39 | if (RedisFrontUtils.equal(redisConnectContext.getRedisMode(), RedisMode.CLUSTER)) { 40 | return LettuceUtils.clusterExec(redisConnectContext, commands -> commands.strlen(key)); 41 | } else { 42 | return LettuceUtils.exec(redisConnectContext, commands -> commands.strlen(key)); 43 | } 44 | } 45 | 46 | @Override 47 | public String setex(RedisConnectContext redisConnectContext, String key, long seconds, String value) { 48 | if (RedisFrontUtils.equal(redisConnectContext.getRedisMode(), RedisMode.CLUSTER)) { 49 | return LettuceUtils.clusterExec(redisConnectContext, commands -> commands.setex(key, seconds, value)); 50 | } else { 51 | return LettuceUtils.exec(redisConnectContext, commands -> commands.setex(key, seconds, value)); 52 | } 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/chart/RedisClientConnectionsChart.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.chart; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.dromara.redisfront.model.context.RedisConnectContext; 5 | import org.dromara.redisfront.ui.components.monitor.RedisMonitor; 6 | import org.dromara.redisfront.ui.components.monitor.RedisUsageInfo; 7 | import org.dromara.redisfront.ui.widget.RedisFrontWidget; 8 | import org.jfree.chart.ChartFactory; 9 | import org.jfree.chart.JFreeChart; 10 | import org.jfree.data.time.Millisecond; 11 | import org.jfree.data.time.TimeSeries; 12 | import org.jfree.data.time.TimeSeriesCollection; 13 | 14 | @Slf4j 15 | public class RedisClientConnectionsChart extends AbstractRedisChart { 16 | private TimeSeries clientConnectionsSeries; 17 | private final RedisMonitor redisMonitor; 18 | private final RedisFrontWidget owner; 19 | 20 | public RedisClientConnectionsChart(RedisConnectContext redisConnectContext, RedisFrontWidget owner) { 21 | super(redisConnectContext); 22 | this.redisMonitor = new RedisMonitor(owner,redisConnectContext); 23 | this.owner = owner; 24 | this.initializeUI(); 25 | } 26 | 27 | private void initializeUI() { 28 | if (clientConnectionsSeries == null) { 29 | clientConnectionsSeries = new TimeSeries(owner.$tr("RedisClientConnectionsChart.clientConnections.text")); 30 | clientConnectionsSeries.setMaximumItemCount(30); 31 | clientConnectionsSeries.removeAgedItems(false); 32 | } 33 | 34 | TimeSeriesCollection dataset = new TimeSeriesCollection(); 35 | dataset.addSeries(clientConnectionsSeries); 36 | 37 | JFreeChart chart = ChartFactory.createTimeSeriesChart( 38 | "", 39 | "", 40 | owner.$tr("RedisClientConnectionsChart.valueAxisLabel.text"), 41 | dataset, 42 | true, 43 | true, 44 | false 45 | ); 46 | setChart(chart); 47 | } 48 | 49 | @Override 50 | public void rebuildUI() { 51 | this.initializeUI(); 52 | } 53 | 54 | 55 | private void updateData() { 56 | RedisUsageInfo redisUsageInfo = redisMonitor.getUsageInfo(); 57 | Millisecond now = new Millisecond(); 58 | clientConnectionsSeries.addOrUpdate(now, redisUsageInfo.getConnectedClients()); 59 | } 60 | 61 | @Override 62 | protected void updateDataset() { 63 | try { 64 | updateData(); 65 | } catch (Exception e) { 66 | log.error("updateData error", e); 67 | } 68 | } 69 | 70 | @Override 71 | protected void clearDataset() { 72 | clientConnectionsSeries.clear(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/extend/BoldTitleTabbedPaneUI.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.extend; 2 | 3 | import com.formdev.flatlaf.ui.FlatTabbedPaneUI; 4 | 5 | import java.awt.*; 6 | 7 | public class BoldTitleTabbedPaneUI extends FlatTabbedPaneUI { 8 | 9 | @Override 10 | protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected) { 11 | if (isSelected) { 12 | font = font.deriveFont(Font.BOLD); 13 | } 14 | super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected); 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/info/LogInfoData.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.info; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | import java.util.Map; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | public class LogInfoData { 11 | String key; 12 | Map infoData; 13 | } -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/info/LogStatusHolder.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.info; 2 | 3 | public class LogStatusHolder { 4 | private static final ThreadLocal THREAD_LOCAL = new ThreadLocal<>(); 5 | 6 | public static void ignoredLog() { 7 | LogStatusHolder.THREAD_LOCAL.set(true); 8 | } 9 | 10 | public static Boolean getIgnoredLog() { 11 | return LogStatusHolder.THREAD_LOCAL.get(); 12 | } 13 | 14 | public static void clear() { 15 | LogStatusHolder.THREAD_LOCAL.remove(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/monitor/RedisUsageInfo.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.monitor; 2 | 3 | import lombok.Data; 4 | import lombok.ToString; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | @Data 8 | @ToString 9 | public class RedisUsageInfo { 10 | private String cpu; 11 | private String memory; 12 | private NetworkStats network; 13 | private MemoryUsage memoryUsage; 14 | private Integer connectedClients; 15 | private Long commandsProcessed; 16 | 17 | 18 | public record NetworkStats(double inputRate, double outputRate, String formatMessage) { 19 | @Override 20 | public @NotNull String toString() { 21 | return String.format(formatMessage, inputRate / 1024, outputRate / 1024); 22 | } 23 | } 24 | 25 | public record MemoryUsage(double usedMemory, double usedMemoryRss, double fragmentationRatio, String formatMessage) { 26 | @Override 27 | public @NotNull String toString() { 28 | return String.format(formatMessage, usedMemory / 1024 / 1024, usedMemoryRss / 1024 / 1024, fragmentationRatio * 100); 29 | } 30 | } 31 | 32 | public record CpuStats(double systemCpuLoad, double processCpuLoad, String formatMessage) { 33 | @Override 34 | public @NotNull String toString() { 35 | return String.format(formatMessage, systemCpuLoad * 100, processCpuLoad * 100); 36 | } 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/panel/WrapperPanel.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.panel; 2 | 3 | import javax.swing.*; 4 | import javax.swing.border.EmptyBorder; 5 | import java.awt.*; 6 | 7 | public class WrapperPanel extends JPanel { 8 | 9 | public WrapperPanel(JComponent component) { 10 | JPanel contentPanel = new JPanel(); 11 | contentPanel.setLayout(new BorderLayout()); 12 | contentPanel.add(component, BorderLayout.CENTER); 13 | contentPanel.setBackground(UIManager.getColor("Component.background")); 14 | setBorder(new EmptyBorder(8, 8, 7, 8)); 15 | setLayout(new BorderLayout()); 16 | add(contentPanel, BorderLayout.CENTER); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/AbstractRedisDataScanner.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner; 2 | 3 | import org.dromara.redisfront.model.context.RedisConnectContext; 4 | import org.dromara.redisfront.ui.components.scanner.context.RedisScanContext; 5 | import org.dromara.redisfront.ui.components.scanner.context.RedisScanContextManager; 6 | import org.dromara.redisfront.ui.components.scanner.handler.ScanDataRefreshHandler; 7 | import org.dromara.redisfront.ui.components.scanner.model.ScanDataResult; 8 | 9 | import javax.swing.table.TableModel; 10 | import java.util.Collection; 11 | import java.util.LinkedHashMap; 12 | import java.util.Map; 13 | import java.util.ResourceBundle; 14 | 15 | public abstract class AbstractRedisDataScanner implements RedisDataScanner { 16 | protected final RedisConnectContext redisConnectContext; 17 | protected final ResourceBundle tr; 18 | protected final Map> contextMap; 19 | protected final RedisScanContextManager redisScanContextManager = new RedisScanContextManager<>(); 20 | protected final ScanDataRefreshHandler> scanDataRefreshHandler; 21 | 22 | private final ScanDataResult scanDataResult = new ScanDataResult<>(); 23 | 24 | public AbstractRedisDataScanner(RedisConnectContext redisConnectContext, ResourceBundle tr, ScanDataRefreshHandler> scanDataRefreshHandler) { 25 | this.redisConnectContext = redisConnectContext; 26 | this.tr = tr; 27 | this.scanDataRefreshHandler = scanDataRefreshHandler; 28 | this.contextMap = new LinkedHashMap<>(); 29 | } 30 | 31 | protected abstract M createModel(Collection data); 32 | 33 | protected abstract Long getLen(); 34 | 35 | protected void updateState(RedisScanContext scanContext) { 36 | scanDataResult.setData(createModel(scanContext.getKeyList())); 37 | scanDataResult.setLen(getLen()); 38 | scanDataResult.setLoadSize(scanContext.getLoadSize()); 39 | scanDataResult.setDataSize(scanContext.getDataLength()); 40 | scanDataResult.setIsFinished(scanContext.getScanCursor().isFinished()); 41 | } 42 | 43 | @Override 44 | public void refreshUI() { 45 | scanDataRefreshHandler.accept(scanDataResult); 46 | } 47 | 48 | protected RedisScanContext getContext(String key) { 49 | RedisScanContext context = redisScanContextManager.getContext(key); 50 | if (null == context.getLimit()) { 51 | context.setLimit(Long.valueOf(redisConnectContext.getSetting().getLoadKeyNum())); 52 | } 53 | return context; 54 | } 55 | 56 | public void reset(String key) { 57 | redisScanContextManager.reset(key); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/RedisDataScanner.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner; 2 | 3 | public interface RedisDataScanner { 4 | void fetchData(String key); 5 | void refreshUI(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/context/RedisScanContext.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner.context; 2 | 3 | import cn.hutool.core.collection.CollUtil; 4 | import cn.hutool.core.io.unit.DataSizeUtil; 5 | import io.lettuce.core.ScanArgs; 6 | import io.lettuce.core.ScanCursor; 7 | import io.lettuce.core.ScoredValue; 8 | import io.lettuce.core.StreamMessage; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | import org.dromara.redisfront.commons.utils.RedisFrontUtils; 12 | 13 | import java.util.Collection; 14 | import java.util.Collections; 15 | import java.util.Map; 16 | 17 | @Setter 18 | @Getter 19 | public class RedisScanContext { 20 | 21 | @Setter 22 | private ScanCursor scanCursor; 23 | private Long limit; 24 | private String searchKey; 25 | private Collection keys = Collections.emptyList(); 26 | 27 | public ScanCursor getScanCursor() { 28 | if (scanCursor == null) { 29 | scanCursor = ScanCursor.INITIAL; 30 | } 31 | return scanCursor; 32 | } 33 | 34 | public ScanArgs getScanArgs() { 35 | return new ScanArgs() 36 | .match(getSearchKey()) 37 | .limit(limit); 38 | } 39 | 40 | public String getSearchKey() { 41 | return RedisFrontUtils.isNotEmpty(searchKey) ? searchKey : "*"; 42 | } 43 | 44 | public String getLoadSize() { 45 | return String.valueOf(keys.size()); 46 | } 47 | 48 | public String getDataLength() { 49 | Integer sum = keys.stream() 50 | .map(e -> switch (e) { 51 | case String s -> s.getBytes().length; 52 | case Map.Entry entry -> RedisFrontUtils.getByteSize(entry.getValue()); 53 | case StreamMessage message -> RedisFrontUtils.getByteSize(message.getBody()); 54 | case ScoredValue scoredValue -> RedisFrontUtils.getByteSize(scoredValue.getValue()); 55 | case null, default -> 0; 56 | }) 57 | .reduce(Integer::sum) 58 | .orElse(0); 59 | return DataSizeUtil.format(sum); 60 | } 61 | 62 | public Collection getKeyList() { 63 | return keys; 64 | } 65 | 66 | public void setKeyList(Collection keys) { 67 | if (CollUtil.isNotEmpty(keys)) { 68 | if (CollUtil.isNotEmpty(this.keys)) { 69 | this.keys.addAll(keys); 70 | } else { 71 | this.keys = keys; 72 | } 73 | } else { 74 | this.keys = Collections.emptyList(); 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/context/RedisScanContextManager.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner.context; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | public class RedisScanContextManager { 7 | private final Map> contexts = new LinkedHashMap<>(); 8 | 9 | public RedisScanContext getContext(String key) { 10 | return contexts.computeIfAbsent(key, _ -> new RedisScanContext<>()); 11 | } 12 | 13 | public void reset(String key) { 14 | contexts.put(key, new RedisScanContext<>()); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/core/HashRedisDataScanner.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner.core; 2 | 3 | import com.google.common.collect.Lists; 4 | import io.lettuce.core.MapScanCursor; 5 | import org.dromara.redisfront.commons.exception.RedisFrontException; 6 | import org.dromara.redisfront.ui.components.scanner.AbstractRedisDataScanner; 7 | import org.dromara.redisfront.commons.utils.RedisFrontUtils; 8 | import org.dromara.redisfront.model.context.RedisConnectContext; 9 | import org.dromara.redisfront.model.table.HashTableModel; 10 | import org.dromara.redisfront.service.RedisHashService; 11 | import org.dromara.redisfront.ui.components.scanner.handler.ScanDataRefreshHandler; 12 | import org.dromara.redisfront.ui.components.scanner.model.ScanDataResult; 13 | 14 | import java.util.Collection; 15 | import java.util.List; 16 | import java.util.Map; 17 | import java.util.ResourceBundle; 18 | 19 | public class HashRedisDataScanner extends AbstractRedisDataScanner, HashTableModel> { 20 | private final String key; 21 | 22 | public HashRedisDataScanner(RedisConnectContext redisConnectContext, String key, ScanDataRefreshHandler> consumer, ResourceBundle tr) { 23 | super(redisConnectContext, tr, consumer); 24 | this.key = key; 25 | } 26 | 27 | @Override 28 | public void fetchData(String fetchKey) { 29 | var scanContext = getContext(key); 30 | 31 | if (RedisFrontUtils.isNotEmpty(scanContext.getKeyList()) && scanContext.getKeyList().size() >= 1000) { 32 | throw new RedisFrontException(tr.getString("DataViewForm.redisFrontException.message")); 33 | } 34 | 35 | scanContext.setSearchKey(fetchKey); 36 | 37 | MapScanCursor mapScanCursor = RedisHashService.service.hscan(redisConnectContext, key, scanContext.getScanCursor(), scanContext.getScanArgs()); 38 | 39 | scanContext.setScanCursor(mapScanCursor); 40 | 41 | scanContext.setKeyList(Lists.newArrayList(mapScanCursor.getMap().entrySet())); 42 | 43 | updateState(scanContext); 44 | } 45 | 46 | @Override 47 | protected HashTableModel createModel(Collection> data) { 48 | return new HashTableModel((List>) data); 49 | } 50 | 51 | @Override 52 | protected Long getLen() { 53 | return RedisHashService.service.hlen(redisConnectContext, key); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/core/ListRedisDataScanner.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner.core; 2 | 3 | import io.lettuce.core.ScanCursor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.dromara.redisfront.model.context.RedisConnectContext; 7 | import org.dromara.redisfront.model.table.ListTableModel; 8 | import org.dromara.redisfront.service.RedisListService; 9 | import org.dromara.redisfront.ui.components.scanner.AbstractRedisDataScanner; 10 | import org.dromara.redisfront.ui.components.scanner.handler.ScanDataRefreshHandler; 11 | import org.dromara.redisfront.ui.components.scanner.model.ScanDataResult; 12 | 13 | import java.util.Collection; 14 | import java.util.List; 15 | import java.util.ResourceBundle; 16 | 17 | @Setter 18 | @Getter 19 | public class ListRedisDataScanner extends AbstractRedisDataScanner { 20 | 21 | private String key; 22 | 23 | public ListRedisDataScanner(RedisConnectContext redisConnectContext, String key, ScanDataRefreshHandler> scanDataRefreshHandler, ResourceBundle tr) { 24 | super(redisConnectContext, tr, scanDataRefreshHandler); 25 | this.key = key; 26 | } 27 | 28 | 29 | @Override 30 | public void fetchData(String fetchKey) { 31 | var scanContext = getContext(key); 32 | 33 | var start = Long.parseLong(scanContext.getScanCursor().getCursor()); 34 | var stop = start + (scanContext.getLimit() - 1); 35 | var value = RedisListService.service.lrange(redisConnectContext, key, start, stop); 36 | 37 | scanContext.setKeyList(value); 38 | 39 | var nextCursor = start + scanContext.getLimit(); 40 | if (nextCursor >= getLen()) { 41 | scanContext.setScanCursor(new ScanCursor(String.valueOf(getLen()), true)); 42 | } else { 43 | scanContext.setScanCursor(new ScanCursor(String.valueOf(nextCursor), false)); 44 | } 45 | 46 | updateState(scanContext); 47 | } 48 | 49 | @Override 50 | protected ListTableModel createModel(Collection data) { 51 | return new ListTableModel((List) data); 52 | } 53 | 54 | @Override 55 | protected Long getLen() { 56 | return RedisListService.service.llen(redisConnectContext, key); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/core/SetRedisDataScanner.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner.core; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.dromara.redisfront.commons.exception.RedisFrontException; 6 | import org.dromara.redisfront.ui.components.scanner.AbstractRedisDataScanner; 7 | import org.dromara.redisfront.ui.components.scanner.handler.ScanDataRefreshHandler; 8 | import org.dromara.redisfront.ui.components.scanner.model.ScanDataResult; 9 | import org.dromara.redisfront.commons.utils.RedisFrontUtils; 10 | import org.dromara.redisfront.model.context.RedisConnectContext; 11 | import org.dromara.redisfront.model.table.SetTableModel; 12 | import org.dromara.redisfront.service.RedisSetService; 13 | 14 | import java.util.Collection; 15 | import java.util.List; 16 | import java.util.ResourceBundle; 17 | 18 | @Setter 19 | @Getter 20 | public class SetRedisDataScanner extends AbstractRedisDataScanner { 21 | private String key; 22 | 23 | public SetRedisDataScanner(RedisConnectContext redisConnectContext, String key, ScanDataRefreshHandler> scanDataRefreshHandler, ResourceBundle tr) { 24 | super(redisConnectContext, tr, scanDataRefreshHandler); 25 | this.key = key; 26 | } 27 | 28 | 29 | @Override 30 | public void fetchData(String fetchKey) { 31 | 32 | var scanContext = redisScanContextManager.getContext(key); 33 | 34 | if (RedisFrontUtils.isNotEmpty(scanContext.getKeyList()) && scanContext.getKeyList().size() >= 1000) { 35 | throw new RedisFrontException(tr.getString("DataViewForm.redisFrontException.message")); 36 | } 37 | 38 | scanContext.setSearchKey(fetchKey); 39 | 40 | if (null == scanContext.getLimit()) { 41 | scanContext.setLimit(Long.valueOf(redisConnectContext.getSetting().getLoadKeyNum())); 42 | } 43 | 44 | var valueScanCursor = RedisSetService.service.sscan(redisConnectContext, key, scanContext.getScanCursor(), scanContext.getScanArgs()); 45 | scanContext.setScanCursor(valueScanCursor); 46 | 47 | scanContext.setKeyList(valueScanCursor.getValues()); 48 | 49 | updateState(scanContext); 50 | } 51 | 52 | @Override 53 | protected SetTableModel createModel(Collection data) { 54 | return new SetTableModel((List) data); 55 | } 56 | 57 | @Override 58 | protected Long getLen() { 59 | return RedisSetService.service.scard(redisConnectContext, key); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/core/StreamRedisDataScanner.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner.core; 2 | 3 | import io.lettuce.core.Limit; 4 | import io.lettuce.core.Range; 5 | import io.lettuce.core.ScanCursor; 6 | import io.lettuce.core.StreamMessage; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import org.dromara.redisfront.commons.exception.RedisFrontException; 10 | import org.dromara.redisfront.ui.components.scanner.AbstractRedisDataScanner; 11 | import org.dromara.redisfront.ui.components.scanner.handler.ScanDataRefreshHandler; 12 | import org.dromara.redisfront.ui.components.scanner.model.ScanDataResult; 13 | import org.dromara.redisfront.commons.utils.RedisFrontUtils; 14 | import org.dromara.redisfront.model.context.RedisConnectContext; 15 | import org.dromara.redisfront.model.table.StreamTableModel; 16 | import org.dromara.redisfront.service.RedisStreamService; 17 | 18 | import java.util.Collection; 19 | import java.util.List; 20 | import java.util.ResourceBundle; 21 | 22 | @Setter 23 | @Getter 24 | public class StreamRedisDataScanner extends AbstractRedisDataScanner, StreamTableModel> { 25 | 26 | private String key; 27 | private StreamTableModel streamTableModel; 28 | private Long len; 29 | private String dataSize; 30 | private String loadSize; 31 | private Boolean finished; 32 | 33 | public StreamRedisDataScanner(RedisConnectContext redisConnectContext, String key, ScanDataRefreshHandler> scanDataRefreshHandler, ResourceBundle tr) { 34 | super(redisConnectContext, tr, scanDataRefreshHandler); 35 | this.key = key; 36 | } 37 | 38 | @Override 39 | public void fetchData(String fetchKey) { 40 | 41 | var scanContext = getContext(key); 42 | 43 | if (RedisFrontUtils.isNotEmpty(scanContext.getKeyList()) && scanContext.getKeyList().size() >= 1000) { 44 | throw new RedisFrontException(tr.getString("DataViewForm.redisFrontException.message")); 45 | } 46 | 47 | var start = Long.parseLong(scanContext.getScanCursor().getCursor()); 48 | var stop = start + (scanContext.getLimit() - 1); 49 | 50 | var value = RedisStreamService.service.xrange(redisConnectContext, key, Range.unbounded(), Limit.create(start, stop)); 51 | 52 | var nextCursor = start + scanContext.getLimit(); 53 | 54 | if (nextCursor >= len) { 55 | scanContext.setScanCursor(new ScanCursor(String.valueOf(len), true)); 56 | } else { 57 | scanContext.setScanCursor(new ScanCursor(String.valueOf(nextCursor), false)); 58 | } 59 | 60 | scanContext.setKeyList(value); 61 | 62 | updateState(scanContext); 63 | } 64 | 65 | @Override 66 | protected StreamTableModel createModel(Collection> data) { 67 | return new StreamTableModel((List>) data); 68 | } 69 | 70 | @Override 71 | protected Long getLen() { 72 | return RedisStreamService.service.xlen(redisConnectContext, key); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/core/StringRedisDataScanner.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner.core; 2 | 3 | import org.dromara.redisfront.ui.components.scanner.RedisDataScanner; 4 | import org.dromara.redisfront.ui.components.scanner.handler.ScanDataRefreshHandler; 5 | import org.dromara.redisfront.model.context.RedisConnectContext; 6 | import org.dromara.redisfront.model.turbo.Turbo2; 7 | import org.dromara.redisfront.service.RedisStringService; 8 | 9 | public class StringRedisDataScanner implements RedisDataScanner { 10 | private final RedisConnectContext redisConnectContext; 11 | private final ScanDataRefreshHandler> consumer; 12 | private Long strLen; 13 | private String value; 14 | 15 | public StringRedisDataScanner(RedisConnectContext redisConnectContext, ScanDataRefreshHandler> consumer) { 16 | this.redisConnectContext = redisConnectContext; 17 | this.consumer = consumer; 18 | } 19 | 20 | @Override 21 | public void fetchData(String fetchKey) { 22 | strLen = RedisStringService.service.strlen(redisConnectContext, fetchKey); 23 | value = RedisStringService.service.get(redisConnectContext, fetchKey); 24 | } 25 | 26 | @Override 27 | public void refreshUI() { 28 | consumer.accept(new Turbo2<>(strLen, value)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/core/ZSetRedisDataScanner.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner.core; 2 | 3 | import io.lettuce.core.ScoredValue; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.dromara.redisfront.commons.exception.RedisFrontException; 7 | import org.dromara.redisfront.ui.components.scanner.AbstractRedisDataScanner; 8 | import org.dromara.redisfront.ui.components.scanner.handler.ScanDataRefreshHandler; 9 | import org.dromara.redisfront.ui.components.scanner.model.ScanDataResult; 10 | import org.dromara.redisfront.commons.utils.RedisFrontUtils; 11 | import org.dromara.redisfront.model.context.RedisConnectContext; 12 | import org.dromara.redisfront.model.table.SortedSetTableModel; 13 | import org.dromara.redisfront.service.RedisZSetService; 14 | 15 | import java.util.Collection; 16 | import java.util.List; 17 | import java.util.ResourceBundle; 18 | 19 | @Setter 20 | @Getter 21 | public class ZSetRedisDataScanner extends AbstractRedisDataScanner, SortedSetTableModel> { 22 | private String key; 23 | 24 | public ZSetRedisDataScanner(RedisConnectContext redisConnectContext, String key, ScanDataRefreshHandler> scanDataRefreshHandler, ResourceBundle tr) { 25 | super(redisConnectContext, tr, scanDataRefreshHandler); 26 | this.key = key; 27 | } 28 | 29 | 30 | @Override 31 | public void fetchData(String fetchKey) { 32 | 33 | var scanContext = getContext(key); 34 | 35 | if (RedisFrontUtils.isNotEmpty(scanContext.getKeyList()) && scanContext.getKeyList().size() >= 1000) { 36 | throw new RedisFrontException(tr.getString("DataViewForm.redisFrontException.message")); 37 | } 38 | 39 | scanContext.setSearchKey(fetchKey); 40 | 41 | var valueScanCursor = RedisZSetService.service.zscan(redisConnectContext, key, scanContext.getScanCursor(), scanContext.getScanArgs()); 42 | 43 | scanContext.setScanCursor(valueScanCursor); 44 | 45 | scanContext.setScanCursor(valueScanCursor); 46 | 47 | scanContext.setKeyList(valueScanCursor.getValues()); 48 | 49 | updateState(scanContext); 50 | } 51 | 52 | @Override 53 | protected SortedSetTableModel createModel(Collection> data) { 54 | return new SortedSetTableModel((List>) data); 55 | } 56 | 57 | @Override 58 | protected Long getLen() { 59 | return RedisZSetService.service.zcard(redisConnectContext, key); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/handler/ScanDataRefreshHandler.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner.handler; 2 | 3 | import java.util.function.Consumer; 4 | 5 | public interface ScanDataRefreshHandler extends Consumer { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/components/scanner/model/ScanDataResult.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.components.scanner.model; 2 | 3 | import lombok.Data; 4 | 5 | import javax.swing.table.TableModel; 6 | 7 | @Data 8 | public class ScanDataResult { 9 | 10 | private Long len; 11 | 12 | private String dataSize; 13 | 14 | private String loadSize; 15 | 16 | private Boolean isFinished; 17 | 18 | private M data; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/event/AddKeySuccessEvent.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.event; 2 | 3 | import lombok.Getter; 4 | import org.dromara.quickswing.events.QSEvent; 5 | 6 | @Getter 7 | public class AddKeySuccessEvent extends QSEvent { 8 | private final Integer id; 9 | public AddKeySuccessEvent(Object message, Integer id) { 10 | super(message); 11 | this.id = id; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/event/ClickKeyTreeNodeEvent.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.event; 2 | 3 | import lombok.Getter; 4 | import org.dromara.quickswing.events.QSEvent; 5 | 6 | @Getter 7 | public class ClickKeyTreeNodeEvent extends QSEvent { 8 | private final Integer id; 9 | public ClickKeyTreeNodeEvent(Object source, Integer id) { 10 | super(source); 11 | this.id = id; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/event/CommandExecuteEvent.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.event; 2 | 3 | import lombok.Getter; 4 | import org.dromara.quickswing.events.QSEvent; 5 | 6 | @Getter 7 | public class CommandExecuteEvent extends QSEvent { 8 | private final Integer id; 9 | public CommandExecuteEvent(Object message, Integer id) { 10 | super(message); 11 | this.id = id; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/event/DrawerChangeEvent.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.event; 2 | 3 | import org.dromara.quickswing.events.QSEvent; 4 | 5 | public class DrawerChangeEvent extends QSEvent { 6 | public DrawerChangeEvent(Object source) { 7 | super(source); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/event/KeyDeleteSuccessEvent.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.event; 2 | 3 | import lombok.Getter; 4 | import org.dromara.quickswing.events.QSEvent; 5 | 6 | @Getter 7 | public class KeyDeleteSuccessEvent extends QSEvent { 8 | private final Integer id; 9 | public KeyDeleteSuccessEvent(Object source, Integer id) { 10 | super(source); 11 | this.id = id; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/event/OpenRedisConnectEvent.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.event; 2 | 3 | import org.dromara.quickswing.events.QSEvent; 4 | 5 | public class OpenRedisConnectEvent extends QSEvent { 6 | public OpenRedisConnectEvent(Object message) { 7 | super(message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/event/RefreshConnectTreeEvent.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.event; 2 | 3 | import org.dromara.quickswing.events.QSEvent; 4 | 5 | public class RefreshConnectTreeEvent extends QSEvent { 6 | public RefreshConnectTreeEvent(Object message) { 7 | super(message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/handler/ConnectHandler.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.handler; 2 | 3 | import org.dromara.redisfront.model.context.RedisConnectContext; 4 | 5 | import java.util.function.Consumer; 6 | 7 | public interface ConnectHandler extends Consumer { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/handler/DrawerHandler.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.handler; 2 | 3 | import java.util.function.BiConsumer; 4 | 5 | public interface DrawerHandler extends BiConsumer { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/widget/main/fragment/scaffold/PageScaffold.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.widget.main.fragment.scaffold; 2 | 3 | import org.dromara.quickswing.ui.app.page.QSPageItem; 4 | import org.dromara.quickswing.ui.app.page.QSPageScaffold; 5 | import org.dromara.redisfront.ui.widget.RedisFrontWidget; 6 | 7 | public class PageScaffold extends QSPageScaffold> { 8 | public PageScaffold(QSPageItem pageItem) { 9 | super(pageItem); 10 | } 11 | 12 | @Override 13 | public void onChange() { 14 | super.onChange(); 15 | } 16 | 17 | public void onClose() { 18 | super.pageItem.onClose(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/widget/main/fragment/scaffold/report/ReportPageView.form: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 |
61 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/widget/main/fragment/scaffold/terminal/TerminalPageView.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.widget.main.fragment.scaffold.terminal; 2 | 3 | import lombok.Getter; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.dromara.quickswing.ui.app.page.QSPageItem; 6 | import org.dromara.redisfront.model.context.RedisConnectContext; 7 | import org.dromara.redisfront.ui.widget.RedisFrontWidget; 8 | 9 | import javax.swing.*; 10 | 11 | @Slf4j 12 | public class TerminalPageView extends QSPageItem { 13 | @Getter 14 | private final RedisConnectContext redisConnectContext; 15 | @Getter 16 | private final RedisFrontWidget owner; 17 | 18 | private RedisFrontTerminal terminal; 19 | 20 | public TerminalPageView(RedisConnectContext redisConnectContext, RedisFrontWidget owner) { 21 | this.redisConnectContext = redisConnectContext; 22 | this.owner = owner; 23 | this.setupUI(); 24 | } 25 | 26 | @Override 27 | public void onLoad() { 28 | this.terminal = new RedisFrontTerminal(redisConnectContext); 29 | } 30 | 31 | @Override 32 | public void onChange() { 33 | super.onChange(); 34 | } 35 | 36 | @Override 37 | public RedisFrontWidget getApp() { 38 | return owner; 39 | } 40 | 41 | @Override 42 | protected JComponent getContentPanel() { 43 | return terminal; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/widget/main/listener/MouseDraggedListener.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.widget.main.listener; 2 | 3 | import org.dromara.redisfront.ui.widget.RedisFrontWidget; 4 | 5 | import java.awt.*; 6 | import java.awt.event.MouseEvent; 7 | import java.awt.event.MouseListener; 8 | import java.awt.event.MouseMotionListener; 9 | 10 | public class MouseDraggedListener implements MouseListener, MouseMotionListener { 11 | private final RedisFrontWidget owner; 12 | private static int mouseX, mouseY; 13 | 14 | public MouseDraggedListener(RedisFrontWidget owner) { 15 | this.owner = owner; 16 | } 17 | 18 | @Override 19 | public void mousePressed(MouseEvent e) { 20 | mouseX = e.getX(); 21 | mouseY = e.getY(); 22 | owner.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); 23 | } 24 | 25 | @Override 26 | public void mouseDragged(MouseEvent e) { 27 | int newX = owner.getX() + (e.getX() - mouseX); 28 | int newY = owner.getY() + (e.getY() - mouseY); 29 | this.owner.setLocation(newX, newY); 30 | } 31 | 32 | @Override 33 | public void mouseClicked(MouseEvent e) { 34 | 35 | } 36 | 37 | 38 | @Override 39 | public void mouseReleased(MouseEvent e) { 40 | if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0) { 41 | owner.setCursor(Cursor.getDefaultCursor()); 42 | } 43 | } 44 | 45 | @Override 46 | public void mouseEntered(MouseEvent e) { 47 | 48 | } 49 | 50 | @Override 51 | public void mouseExited(MouseEvent e) { 52 | if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0) { 53 | owner.setCursor(Cursor.getDefaultCursor()); 54 | } 55 | } 56 | 57 | 58 | @Override 59 | public void mouseMoved(MouseEvent e) { 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/widget/sidebar/drawer/DrawerAnimationAction.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.widget.sidebar.drawer; 2 | 3 | 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.dromara.quickswing.ui.app.QSAction; 7 | import org.dromara.redisfront.ui.widget.RedisFrontWidget; 8 | import org.jdesktop.core.animation.timing.Animator; 9 | import org.jdesktop.core.animation.timing.TimingTarget; 10 | import org.jdesktop.core.animation.timing.TimingTargetAdapter; 11 | import org.jdesktop.swing.animation.timing.sources.SwingTimerTimingSource; 12 | 13 | import java.awt.event.ActionEvent; 14 | import java.util.function.BiConsumer; 15 | import java.util.function.Consumer; 16 | 17 | import static java.util.concurrent.TimeUnit.MILLISECONDS; 18 | 19 | public class DrawerAnimationAction extends QSAction { 20 | private Animator animator; 21 | @Getter 22 | private boolean drawerOpen = true; 23 | @Setter 24 | private Consumer beforeProcess; 25 | @Setter 26 | private BiConsumer handler; 27 | @Setter 28 | private Consumer afterProcess; 29 | public DrawerAnimationAction(RedisFrontWidget app, BiConsumer handler) { 30 | super(app); 31 | this.handler = handler; 32 | } 33 | 34 | @Override 35 | public void handleAction(ActionEvent e) { 36 | if (animator != null) { 37 | animator.stop(); 38 | } 39 | SwingTimerTimingSource swingTimerTimingSource = new SwingTimerTimingSource(); 40 | swingTimerTimingSource.init(); 41 | animator = new Animator.Builder(swingTimerTimingSource) 42 | .setDebugName("700") 43 | .setDuration(500, MILLISECONDS) 44 | .addTargets(target) 45 | .setDisposeTimingSource(true) 46 | .build(); 47 | animator.start(); 48 | } 49 | 50 | TimingTarget target = new TimingTargetAdapter() { 51 | 52 | public void begin(Animator source) { 53 | if(beforeProcess !=null){ 54 | beforeProcess.accept(drawerOpen); 55 | } 56 | } 57 | 58 | @Override 59 | public void timingEvent(Animator source, double fraction) { 60 | handler.accept(fraction,drawerOpen); 61 | app.revalidate(); 62 | app.repaint(); 63 | } 64 | 65 | @Override 66 | public void end(Animator source) { 67 | if(beforeProcess !=null){ 68 | afterProcess.accept(drawerOpen); 69 | } 70 | drawerOpen = !drawerOpen; 71 | } 72 | 73 | }; 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/widget/sidebar/drawer/DrawerMenuItemEvent.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.widget.sidebar.drawer; 2 | 3 | public interface DrawerMenuItemEvent { 4 | void apply(String key, int[] index); 5 | } -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/widget/sidebar/panel/LogoPanel.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.widget.sidebar.panel; 2 | 3 | import org.dromara.redisfront.commons.resources.Icons; 4 | 5 | import javax.swing.*; 6 | import java.awt.*; 7 | import java.awt.event.MouseAdapter; 8 | import java.awt.event.MouseEvent; 9 | import java.awt.event.MouseListener; 10 | import java.awt.geom.RoundRectangle2D; 11 | 12 | public class LogoPanel extends JPanel { 13 | private static final LogoPanel INSTANCE = new LogoPanel(); 14 | 15 | public static LogoPanel getInstance() { 16 | return INSTANCE; 17 | } 18 | 19 | public LogoPanel() { 20 | this.setOpaque(false); 21 | this.setLayout(new BorderLayout()); 22 | this.setMaximumSize(new Dimension(190, 60)); 23 | this.add(BorderLayout.WEST, new JLabel(Icons.REDIS_ICON_45x45)); 24 | this.add(BorderLayout.CENTER, new JLabel(Icons.LOGO_TEXT_ICON)); 25 | addMouseListener(new MouseAdapter() { 26 | @Override 27 | public void mouseClicked(MouseEvent e) { 28 | if(e.getClickCount() == 2){ 29 | System.gc(); 30 | } 31 | } 32 | }); 33 | JLabel subTitleLabel = new JLabel("Cross-Platform Redis GUI Client"); 34 | subTitleLabel.setVerticalAlignment(JLabel.CENTER); 35 | subTitleLabel.setHorizontalAlignment(JLabel.CENTER); 36 | this.add(BorderLayout.SOUTH, subTitleLabel); 37 | this.setBorder(BorderFactory.createEmptyBorder(3, 10, 2, 10)); 38 | } 39 | 40 | 41 | @Override 42 | protected void paintComponent(Graphics g) { 43 | super.paintComponent(g); 44 | Graphics2D g2d = (Graphics2D) g; 45 | g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 46 | RoundRectangle2D roundRect = new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), 15, 15); 47 | g2d.setColor(getBackground()); 48 | g2d.fill(roundRect); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/widget/sidebar/tree/RedisConnectTreeCellRenderer.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.widget.sidebar.tree; 2 | 3 | import com.formdev.flatlaf.util.SystemInfo; 4 | import org.dromara.redisfront.commons.resources.Icons; 5 | import org.jdesktop.swingx.tree.DefaultXTreeCellRenderer; 6 | 7 | import javax.swing.*; 8 | import java.awt.*; 9 | 10 | public class RedisConnectTreeCellRenderer extends DefaultXTreeCellRenderer { 11 | public RedisConnectTreeCellRenderer() { 12 | this.setTextNonSelectionColor(Color.WHITE); 13 | } 14 | 15 | @Override 16 | public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { 17 | Component c = super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); 18 | if (SystemInfo.isWindows) { 19 | this.setFont(new Font("Microsoft YaHei", Font.PLAIN, 16)); 20 | } 21 | if (value instanceof RedisConnectTreeNode redisConnectTreeNode) { 22 | if (redisConnectTreeNode.getIsGroup()) { 23 | this.setIcon(Icons.FOLDER_ICON_14x14); 24 | } else { 25 | this.setIcon(Icons.LINK_ICON_14x14); 26 | } 27 | } 28 | return c; 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/org/dromara/redisfront/ui/widget/sidebar/tree/RedisConnectTreeNode.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.ui.widget.sidebar.tree; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.experimental.Accessors; 6 | import org.dromara.quickswing.tree.QSTreeNode; 7 | import org.dromara.redisfront.model.entity.ConnectDetailEntity; 8 | import org.dromara.redisfront.model.entity.ConnectGroupEntity; 9 | 10 | import javax.swing.tree.DefaultMutableTreeNode; 11 | import javax.swing.tree.TreeNode; 12 | import java.util.Comparator; 13 | 14 | /** 15 | * NodeInfo 16 | * 17 | * @author Jin 18 | */ 19 | @Getter 20 | @Setter 21 | @Accessors(chain = true) 22 | public class RedisConnectTreeNode extends DefaultMutableTreeNode implements QSTreeNode, Comparator { 23 | 24 | private Boolean isGroup; 25 | private ConnectGroupEntity group; 26 | private ConnectDetailEntity detail; 27 | 28 | public RedisConnectTreeNode(ConnectGroupEntity group) { 29 | this.isGroup = true; 30 | this.group = group; 31 | } 32 | 33 | public RedisConnectTreeNode(ConnectDetailEntity detail) { 34 | this.isGroup = false; 35 | this.detail = detail; 36 | } 37 | 38 | public Integer id() { 39 | if (isGroup) { 40 | return group.getGroupId(); 41 | } 42 | return detail.getId(); 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | if (isGroup) { 48 | return group.getGroupName(); 49 | } 50 | return detail.getName(); 51 | } 52 | 53 | @Override 54 | public int compare(TreeNode o1, TreeNode o2) { 55 | if (o1 instanceof RedisConnectTreeNode o1Node && o2 instanceof RedisConnectTreeNode o2Node) { 56 | return o1Node.id().compareTo(o2Node.id()); 57 | } 58 | return 0; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/resources/icons/CPU.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /src/main/resources/icons/CPU_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /src/main/resources/icons/DataTables.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/icons/RecentlyUsed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/icons/RedisFront.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/src/main/resources/icons/RedisFront.ico -------------------------------------------------------------------------------- /src/main/resources/icons/add.svg: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/icons/add_conn.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/icons/add_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/icons/buildLoadChanges.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/cmd_add.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/cmd_add_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/command.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/command_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/commit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/icons/db_cli2.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 9 | 11 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/icons/db_report2.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 9 | 11 | 13 | 15 | -------------------------------------------------------------------------------- /src/main/resources/icons/delete.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/icons/delete_a.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | -------------------------------------------------------------------------------- /src/main/resources/icons/delete_b.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/icons/delete_b_dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/icons/delete_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/icons/diff.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/icons/download.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/icons/favorite.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/folder.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 9 | -------------------------------------------------------------------------------- /src/main/resources/icons/forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/resources/icons/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/github_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/info.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /src/main/resources/icons/listFiles.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/icons/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dromara/RedisFront/fe63cae3002a5b98a4c620f8b7a1e74b4b6c87b0/src/main/resources/icons/logo.png -------------------------------------------------------------------------------- /src/main/resources/icons/memory.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/memory_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/menu-cut.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/menu-paste.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/icons/mode.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/mode_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/none.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 9 | 11 | 17 | 19 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/resources/icons/none_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 9 | 11 | 17 | 19 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/resources/icons/project.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/icons/refresh.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/icons/refresh_a.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | -------------------------------------------------------------------------------- /src/main/resources/icons/refresh_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/icons/regex.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/icons/regexHovered.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/icons/regexSelected.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/icons/save.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/icons/save_a.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/resources/icons/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/show.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/status_error.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/icons/status_ok.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/icons/test-connect.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/tree_key.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/icons/undo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/wifi.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /src/main/resources/icons/wifi_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /src/main/resources/org/dromara/redisfront/theme/FlatDarkLaf.properties: -------------------------------------------------------------------------------- 1 | RedisFront.main.background=lighten(@background,5%) 2 | RedisFront.nonePanel.background=lighten(@background,5%) 3 | RedisFront.animateButton.background=lighten(@background,1%) 4 | 5 | #---- FlatEditorPane ---- 6 | FlatEditorPane.background=#2b2b2b 7 | FlatEditorPane.caretColor=@foreground 8 | FlatEditorPane.selectionBackground=#214283 9 | FlatEditorPane.currentLineHighlight=#323232 10 | FlatEditorPane.markOccurrencesColor=#52503A 11 | FlatEditorPane.markAllHighlightColor=#32593D 12 | FlatEditorPane.matchedBracketBackground=lighten(#3B514D,3%) 13 | FlatEditorPane.matchedBracketBorderColor=$FlatEditorPane.matchedBracketBackground 14 | FlatEditorPane.style.property=@foreground 15 | FlatEditorPane.style.variable=@foreground 16 | FlatEditorPane.style.variable.background=#00ff0018 17 | FlatEditorPane.style.number=#6897BB 18 | FlatEditorPane.style.color=#6897BB 19 | FlatEditorPane.style.color.background=#ffffff10 20 | FlatEditorPane.style.string=#6A8759 21 | FlatEditorPane.style.function=#CC7832 22 | FlatEditorPane.style.type=#8C8C8C 23 | FlatEditorPane.style.reservedWord=#CC7832 24 | FlatEditorPane.style.literalBoolean=#CC7832 25 | FlatEditorPane.style.operator=#888 26 | FlatEditorPane.style.separator=#888 27 | FlatEditorPane.style.whitespace=@foreground 28 | FlatEditorPane.style.comment=#808080 29 | FlatEditorPane.style.comment.italic=true 30 | FlatEditorPane.gutter.background=$FlatEditorPane.background 31 | FlatEditorPane.gutter.borderColor=$Component.borderColor 32 | FlatEditorPane.gutter.lineNumberColor=@disabledForeground 33 | 34 | # TabbedPane settings 35 | TabbedPane.tabArc=null 36 | TabbedPane.tabSelectionArc=null 37 | TabbedPane.tabSelectionHeight=0 38 | TabbedPane.selectedForeground=lighten(#b30404,30%) 39 | TabbedPane.hoverColor=null 40 | TabbedPane.hoverForeground=lighten(#b30404,20%) 41 | TabbedPane.focusColor=null 42 | 43 | # Separator settings 44 | Separator.stripeIndent=null 45 | Separator.stripeWidth=1 46 | Separator.height=1 47 | 48 | TitlePane.buttonSize=33,33 49 | 50 | ChartPanel.textColor=darken(@disabledForeground,30%) 51 | -------------------------------------------------------------------------------- /src/main/resources/org/dromara/redisfront/theme/FlatLightLaf.properties: -------------------------------------------------------------------------------- 1 | RedisFront.main.background=#b30404 2 | RedisFront.nonePanel.background=lighten(@background,1%) 3 | RedisFront.animateButton.background=@background 4 | 5 | #---- FlatEditorPane ---- 6 | FlatEditorPane.background=#fff 7 | FlatEditorPane.caretColor=@foreground 8 | FlatEditorPane.selectionBackground=#A6D2FF 9 | FlatEditorPane.currentLineHighlight=#fcfaed 10 | FlatEditorPane.markOccurrencesColor=#FCE8F4 11 | FlatEditorPane.markAllHighlightColor=#ffc800 12 | FlatEditorPane.matchedBracketBackground=#93D9D9 13 | FlatEditorPane.matchedBracketBorderColor=$FlatEditorPane.matchedBracketBackground 14 | FlatEditorPane.style.property=@foreground 15 | FlatEditorPane.style.variable=@foreground 16 | FlatEditorPane.style.variable.background=#00cc0018 17 | FlatEditorPane.style.number=#1750EB 18 | FlatEditorPane.style.color=#1750EB 19 | FlatEditorPane.style.color.background=#0000000a 20 | FlatEditorPane.style.string=#067D17 21 | FlatEditorPane.style.function=#871094 22 | FlatEditorPane.style.type=#8C8C8C 23 | FlatEditorPane.style.reservedWord=#871094 24 | FlatEditorPane.style.literalBoolean=#871094 25 | FlatEditorPane.style.operator=#888 26 | FlatEditorPane.style.separator=#888 27 | FlatEditorPane.style.whitespace=@foreground 28 | FlatEditorPane.style.comment=#8C8C8C 29 | FlatEditorPane.style.comment.italic=true 30 | FlatEditorPane.gutter.background=$FlatEditorPane.background 31 | FlatEditorPane.gutter.borderColor=$Component.borderColor 32 | FlatEditorPane.gutter.lineNumberColor=@disabledForeground 33 | 34 | # TabbedPane settings 35 | TabbedPane.tabArc=null 36 | TabbedPane.tabSelectionArc=null 37 | TabbedPane.tabSelectionHeight=0 38 | TabbedPane.selectedForeground=lighten($RedisFront.main.background,5%) 39 | TabbedPane.hoverColor=null 40 | TabbedPane.hoverForeground=lighten($RedisFront.main.background,15%) 41 | TabbedPane.focusColor=null 42 | 43 | 44 | # Separator settings 45 | Separator.stripeIndent=null 46 | Separator.stripeWidth=1 47 | Separator.height=1 48 | 49 | TitlePane.buttonSize=33,33 50 | 51 | ChartPanel.textColor=@foreground 52 | -------------------------------------------------------------------------------- /src/main/resources/svg/actions/colors.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/main/resources/svg/actions/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/svg/actions/execute.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/svg/actions/intentionBulb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/svg/actions/quickfixOffBulb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/svg/actions/suspend.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/svg/close_.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /src/main/resources/svg/dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/main/resources/svg/errorDialog.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/svg/informationDialog.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/svg/light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/main/resources/svg/publish.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/svg/publish_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/svg/redisfront.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 9 | 11 | 17 | 19 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/resources/svg/redisfront_text.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 9 | 13 | 17 | 19 | 23 | 27 | 30 | 33 | 35 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/main/resources/svg/redisfront_text_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 9 | 13 | 17 | 19 | 23 | 27 | 30 | 33 | 35 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/main/resources/svg/subscribe.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/svg/subscribe_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/svg/testBtn.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/svg/unSubscribe.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/svg/unSubscribe_dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/svg/warningDialog.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/test/java/org/dromara/redisfront/commons/utils/DerbyUtilTest.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.utils; 2 | 3 | 4 | public class DerbyUtilTest { 5 | 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/test/java/org/dromara/redisfront/commons/utils/FutureUtilsTest.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.utils; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | public class FutureUtilsTest { 6 | 7 | 8 | @Test 9 | public void test5() throws InterruptedException { 10 | FutureUtils.runAsync(() -> { 11 | try { 12 | Thread.sleep(50); 13 | } catch (InterruptedException e) { 14 | throw new RuntimeException(e); 15 | } 16 | throw new RuntimeException("111111111"); 17 | }, throwable -> System.out.println("捕获到异常:" + throwable.getMessage())); 18 | 19 | Thread.sleep(50); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/dromara/redisfront/commons/utils/TreeTableTest.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.utils; 2 | 3 | import com.formdev.flatlaf.themes.FlatMacLightLaf; 4 | import org.jdesktop.swingx.JXTreeTable; 5 | import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode; 6 | import org.jdesktop.swingx.treetable.DefaultTreeTableModel; 7 | import org.jdesktop.swingx.treetable.TreeTableModel; 8 | 9 | import javax.swing.*; 10 | import java.util.Arrays; 11 | 12 | public class TreeTableTest { 13 | 14 | 15 | static class Bean { 16 | String name; 17 | int age; 18 | 19 | public Bean(String name, int age) { 20 | this.name = name; 21 | this.age = age; 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | public void setName(String name) { 29 | this.name = name; 30 | } 31 | 32 | public int getAge() { 33 | return age; 34 | } 35 | 36 | public void setAge(int age) { 37 | this.age = age; 38 | } 39 | } 40 | 41 | public static void main(String[] args) { 42 | FlatMacLightLaf.setup(); 43 | // 创建树形数据 44 | DefaultMutableTreeTableNode root = new DefaultMutableTreeTableNode(); 45 | DefaultMutableTreeTableNode child1 = new DefaultMutableTreeTableNode(new Bean("小明爸爸", 40)); 46 | root.add(child1); 47 | DefaultMutableTreeTableNode child2 = new DefaultMutableTreeTableNode(new Bean("小明", 10)); 48 | root.add(child2); 49 | DefaultMutableTreeTableNode grandChild = new DefaultMutableTreeTableNode(new Bean("小刚", 33)); 50 | child1.add(grandChild); 51 | 52 | Object[] columnIdentifiers = {"name", "age"}; 53 | 54 | TreeTableModel model = new DefaultTreeTableModel(root, Arrays.stream(columnIdentifiers).toList()) { 55 | @Override 56 | public Object getValueAt(Object node, int column) { 57 | if (node instanceof DefaultMutableTreeTableNode treeNode) { 58 | Object userObject = treeNode.getUserObject(); 59 | if (userObject instanceof Bean bean) { 60 | return switch (column) { 61 | case 0 -> bean.getName(); 62 | case 1 -> bean.getAge(); 63 | default -> throw new IllegalArgumentException("Invalid column index"); 64 | }; 65 | } 66 | } 67 | return null; 68 | } 69 | }; 70 | 71 | JXTreeTable treeTable = new JXTreeTable(model); 72 | 73 | JFrame frame = new JFrame("测试"); 74 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 75 | frame.add(new JScrollPane(treeTable)); 76 | frame.pack(); 77 | frame.setVisible(true); 78 | } 79 | } -------------------------------------------------------------------------------- /src/test/java/org/dromara/redisfront/commons/utils/TreeUtilsTest.java: -------------------------------------------------------------------------------- 1 | package org.dromara.redisfront.commons.utils; 2 | 3 | import org.dromara.redisfront.model.tree.TreeNodeInfo; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import javax.swing.tree.DefaultTreeModel; 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | /** 11 | * TreeUtil 12 | * 13 | * @author Jin 14 | */ 15 | public class TreeUtilsTest { 16 | 17 | @Test 18 | public void test1() { 19 | Set rows = new HashSet<>(); 20 | rows.add("111: 111"); 21 | rows.add("111: 111: 111"); 22 | rows.add("111: 111: 000"); 23 | rows.add("111: 111: BBB"); 24 | // Set treeNodeInfos = TreeUtils.convertTreeNodeInfoSet(TreeUtils.toStringTreeMap(rows, ":"), "",":"); 25 | DefaultTreeModel treeModel = TreeUtils.toTreeModel(rows, ":"); 26 | System.out.println(); 27 | } 28 | 29 | } 30 | --------------------------------------------------------------------------------