From 6b7e0bfa3300a5745e0b8f94bd7b04ad62b448a4 Mon Sep 17 00:00:00 2001
From: yuchao1990 <757143422@qq.com>
Date: Sun, 28 Jun 2020 08:57:10 +0800
Subject: [PATCH] =?UTF-8?q?=E6=89=A9=E5=B1=95=E9=A1=B9=E7=9B=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
modbus-server/pom.xml | 73 +++
.../SarnathModbusServerApplication.java | 30 ++
.../modbusserver/dtuutils/BitConverter.java | 420 ++++++++++++++++++
.../modbusserver/dtuutils/DTUServer.java | 48 ++
.../dtuutils/DTUServerHandler.java | 137 ++++++
modbus-server/src/main/resources/banner.txt | 8 +
.../src/main/resources/bootstrap.yml | 24 +
modbus-server/src/main/resources/logback.xml | 74 +++
pom.xml | 27 +-
ruoyi-api/ruoyi-api-system/pom.xml | 8 +-
.../ruoyi/common/core/utils/BitConverter.java | 380 ++++++++++++++++
.../gateway/RuoYiGatewayApplication.java | 6 +-
ruoyi-modules/ruoyi-system/pom.xml | 30 +-
.../system/controller/SysUserController.java | 1 +
ruoyi-visual/hystrix-dashboard/pom.xml | 67 +++
.../HystrixDashBoardApplication.java | 22 +
.../src/main/resources/banner.txt | 8 +
.../src/main/resources/bootstrap.yml | 24 +
ruoyi-visual/pom.xml | 1 +
19 files changed, 1353 insertions(+), 35 deletions(-)
create mode 100644 modbus-server/pom.xml
create mode 100644 modbus-server/src/main/java/com/sarnath/modbusserver/SarnathModbusServerApplication.java
create mode 100644 modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/BitConverter.java
create mode 100644 modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/DTUServer.java
create mode 100644 modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/DTUServerHandler.java
create mode 100644 modbus-server/src/main/resources/banner.txt
create mode 100644 modbus-server/src/main/resources/bootstrap.yml
create mode 100644 modbus-server/src/main/resources/logback.xml
create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/BitConverter.java
create mode 100644 ruoyi-visual/hystrix-dashboard/pom.xml
create mode 100644 ruoyi-visual/hystrix-dashboard/src/main/java/com/sarnath/hystrix/dashboard/HystrixDashBoardApplication.java
create mode 100644 ruoyi-visual/hystrix-dashboard/src/main/resources/banner.txt
create mode 100644 ruoyi-visual/hystrix-dashboard/src/main/resources/bootstrap.yml
diff --git a/modbus-server/pom.xml b/modbus-server/pom.xml
new file mode 100644
index 00000000..ea4e34fb
--- /dev/null
+++ b/modbus-server/pom.xml
@@ -0,0 +1,73 @@
+
+
+
+ ruoyi
+ com.ruoyi
+ 2.0.0
+
+ 4.0.0
+
+ modbus-server
+
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-sentinel
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ io.springfox
+ springfox-swagger-ui
+ ${swagger.fox.version}
+
+
+
+ com.ruoyi
+ ruoyi-common-swagger
+
+
+
+ io.netty
+ netty-all
+ 4.1.50.Final
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+
+
+
+
+
diff --git a/modbus-server/src/main/java/com/sarnath/modbusserver/SarnathModbusServerApplication.java b/modbus-server/src/main/java/com/sarnath/modbusserver/SarnathModbusServerApplication.java
new file mode 100644
index 00000000..1b3b4d0b
--- /dev/null
+++ b/modbus-server/src/main/java/com/sarnath/modbusserver/SarnathModbusServerApplication.java
@@ -0,0 +1,30 @@
+package com.sarnath.modbusserver;
+
+import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
+import com.sarnath.modbusserver.dtuutils.DTUServer;
+import org.springframework.boot.SpringApplication;
+import org.springframework.cloud.client.SpringCloudApplication;
+
+@EnableCustomSwagger2
+@SpringCloudApplication
+public class SarnathModbusServerApplication
+{
+ public static void main(String[] args)
+ {
+ SpringApplication.run(SarnathModbusServerApplication.class, args);
+
+
+ new Thread(()->{
+ DTUServer.Start();
+ }).start();
+ System.out.println("(♥◠‿◠)ノ゙ Modbus服务端模块启动成功 ლ(´ڡ`ლ)゙ \n" +
+ "____.___._________ \n" +
+ "\\__ | |\\_ ___ \\ \n" +
+ " / | |/ \\ \\/ \n" +
+ " \\____ |\\ \\____\n" +
+ " / ______| \\______ /\n" +
+ " \\/ \\/ ");
+
+
+ }
+}
diff --git a/modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/BitConverter.java b/modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/BitConverter.java
new file mode 100644
index 00000000..b11a6474
--- /dev/null
+++ b/modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/BitConverter.java
@@ -0,0 +1,420 @@
+package com.sarnath.modbusserver.dtuutils;
+
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+
+/**
+ * 数字转字节数组工具类
+ */
+public class BitConverter {
+
+ /**
+ * 以字节数组的形式返回指定的布尔值
+ * @param data 一个布尔值
+ * @return 长度为 1 的字节数组
+ */
+ public static byte[] getBytes(boolean data) {
+ byte[] bytes = new byte[1];
+ bytes[0] = (byte) (data ? 1 : 0);
+ return bytes;
+ }
+
+ /**
+ * 以字节数组的形式返回指定的 16 位有符号整数值
+ * @param data 要转换的数字
+ * @return 长度为 2 的字节数组
+ */
+ public static byte[] getBytes(short data) {
+ byte[] bytes = new byte[2];
+ if (isLittleEndian()) {
+ bytes[0] = (byte) (data & 0xff);
+ bytes[1] = (byte) ((data & 0xff00) >> 8);
+ } else {
+ bytes[1] = (byte) (data & 0xff);
+ bytes[0] = (byte) ((data & 0xff00) >> 8);
+ }
+ return bytes;
+ }
+
+ /**
+ * 以字节数组的形式返回指定的 Unicode 字符值
+ * @param data 要转换的字符
+ * @return 长度为 2 的字节数组
+ */
+ public static byte[] getBytes(char data) {
+ byte[] bytes = new byte[2];
+ if (isLittleEndian()) {
+ bytes[0] = (byte) (data);
+ bytes[1] = (byte) (data >> 8);
+ } else {
+ bytes[1] = (byte) (data);
+ bytes[0] = (byte) (data >> 8);
+ }
+ return bytes;
+ }
+
+ /**
+ * 以字节数组的形式返回指定的 32 位有符号整数值
+ * @param data 要转换的数字
+ * @return 长度为 4 的字节数组
+ */
+ public static byte[] getBytes(int data) {
+ byte[] bytes = new byte[4];
+ if (isLittleEndian()) {
+ bytes[0] = (byte) (data & 0xff);
+ bytes[1] = (byte) ((data & 0xff00) >> 8);
+ bytes[2] = (byte) ((data & 0xff0000) >> 16);
+ bytes[3] = (byte) ((data & 0xff000000) >> 24);
+ } else {
+ bytes[3] = (byte) (data & 0xff);
+ bytes[2] = (byte) ((data & 0xff00) >> 8);
+ bytes[1] = (byte) ((data & 0xff0000) >> 16);
+ bytes[0] = (byte) ((data & 0xff000000) >> 24);
+ }
+ return bytes;
+ }
+
+ /**
+ * 以字节数组的形式返回指定的 64 位有符号整数值
+ * @param data 要转换的数字
+ * @return 长度为 8 的字节数组
+ */
+ public static byte[] getBytes(long data) {
+ byte[] bytes = new byte[8];
+ if (isLittleEndian()) {
+ bytes[0] = (byte) (data & 0xff);
+ bytes[1] = (byte) ((data >> 8) & 0xff);
+ bytes[2] = (byte) ((data >> 16) & 0xff);
+ bytes[3] = (byte) ((data >> 24) & 0xff);
+ bytes[4] = (byte) ((data >> 32) & 0xff);
+ bytes[5] = (byte) ((data >> 40) & 0xff);
+ bytes[6] = (byte) ((data >> 48) & 0xff);
+ bytes[7] = (byte) ((data >> 56) & 0xff);
+ } else {
+ bytes[7] = (byte) (data & 0xff);
+ bytes[6] = (byte) ((data >> 8) & 0xff);
+ bytes[5] = (byte) ((data >> 16) & 0xff);
+ bytes[4] = (byte) ((data >> 24) & 0xff);
+ bytes[3] = (byte) ((data >> 32) & 0xff);
+ bytes[2] = (byte) ((data >> 40) & 0xff);
+ bytes[1] = (byte) ((data >> 48) & 0xff);
+ bytes[0] = (byte) ((data >> 56) & 0xff);
+ }
+ return bytes;
+ }
+
+ /**
+ * 以字节数组的形式返回指定的单精度浮点值
+ * @param data 要转换的数字
+ * @return 长度为 4 的字节数组
+ */
+ public static byte[] getBytes(float data) {
+ return getBytes(Float.floatToIntBits(data));
+ }
+
+ /**
+ * 以字节数组的形式返回指定的双精度浮点值
+ * @param data 要转换的数字
+ * @return 长度为 8 的字节数组
+ */
+ public static byte[] getBytes(double data) {
+ return getBytes(Double.doubleToLongBits(data));
+ }
+
+ /**
+ * 将指定字符串中的所有字符编码为一个字节序列
+ * @param data 包含要编码的字符的字符串
+ * @return 一个字节数组,包含对指定的字符集进行编码的结果
+ */
+ public static byte[] getBytes(String data) {
+ return data.getBytes(Charset.forName("UTF-8"));
+ }
+
+ /**
+ * 将指定字符串中的所有字符编码为一个字节序列
+ * @param data 包含要编码的字符的字符串
+ * @param charsetName 字符集编码
+ * @return 一个字节数组,包含对指定的字符集进行编码的结果
+ */
+ public static byte[] getBytes(String data, String charsetName) {
+ return data.getBytes(Charset.forName(charsetName));
+ }
+
+ /**
+ * 返回由字节数组转换来的布尔值
+ * @param bytes 字节数组
+ * @return 布尔值
+ */
+ public static boolean toBoolean(byte[] bytes) {
+ return bytes[0] == 0 ? false : true;
+ }
+
+ /**
+ * 返回由字节数组中的指定的一个字节转换来的布尔值
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 布尔值
+ */
+ public static boolean toBoolean(byte[] bytes, int startIndex) {
+ return toBoolean(copyFrom(bytes, startIndex, 1));
+ }
+
+ /**
+ * 返回由字节数组转换来的 16 位有符号整数
+ * @param bytes 字节数组
+ * @return 由两个字节构成的 16 位有符号整数
+ */
+ public static short toShort(byte[] bytes) {
+ if (isLittleEndian()) {
+ return (short) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
+ } else {
+ return (short) ((0xff & bytes[1]) | (0xff00 & (bytes[0] << 8)));
+ }
+ }
+
+ /**
+ * 无符号short整数转换为2字节的byte数组
+ *
+ * @param s
+ * short整数
+ * @return byte数组
+ */
+ public static byte[] unsignedShortToByte2(int s) {
+ byte[] targets = new byte[2];
+ targets[0] = (byte) (s >> 8 & 0xFF);
+ targets[1] = (byte) (s & 0xFF);
+ return targets;
+ }
+
+ /**
+ * byte数组转换为无符号short整数
+ *
+ * @param bytes
+ * byte数组
+ * @return short整数
+ */
+ public static int byte2ToUnsignedShort(byte[] bytes) {
+ return byte2ToUnsignedShort(bytes, 0);
+ }
+
+ /**
+ * byte数组转换为无符号short整数
+ *
+ * @param bytes
+ * byte数组
+ * @param off
+ * 开始位置
+ * @return short整数
+ */
+ public static int byte2ToUnsignedShort(byte[] bytes, int off) {
+ int high = bytes[off];
+ int low = bytes[off + 1];
+ return (high << 8 & 0xFF00) | (low & 0xFF);
+ }
+
+ /**
+ * 返回由字节数组中的指定的两个字节转换来的 16 位有符号整数
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由两个字节构成的 16 位有符号整数
+ */
+ public static short toShort(byte[] bytes, int startIndex) {
+ return toShort(copyFrom(bytes, startIndex, 2));
+ }
+
+ /**
+ * 返回由字节数组转换来的 Unicode 字符
+ * @param bytes 字节数组
+ * @return 由两个字节构成的字符
+ */
+ public static char toChar(byte[] bytes) {
+ if (isLittleEndian()) {
+ return (char) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
+ } else {
+ return (char) ((0xff & bytes[1]) | (0xff00 & (bytes[0] << 8)));
+ }
+ }
+
+ /**
+ * 返回由字节数组中的指定的两个字节转换来的 Unicode 字符
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由两个字节构成的字符
+ */
+ public static char toChar(byte[] bytes, int startIndex) {
+ return toChar(copyFrom(bytes, startIndex, 2));
+ }
+
+ /**
+ * 返回由字节数组转换来的 32 位有符号整数
+ * @param bytes 字节数组
+ * @return 由四个字节构成的 32 位有符号整数
+ */
+ public static int toInt(byte[] bytes) {
+ if (isLittleEndian()) {
+ return (0xff & bytes[0])
+ | (0xff00 & (bytes[1] << 8))
+ | (0xff0000 & (bytes[2] << 16))
+ | (0xff000000 & (bytes[3] << 24));
+ } else {
+ return (0xff & bytes[3])
+ | (0xff00 & (bytes[2] << 8))
+ | (0xff0000 & (bytes[1] << 16))
+ | (0xff000000 & (bytes[0] << 24));
+ }
+ }
+
+ /**
+ * 返回由字节数组中的指定的四个字节转换来的 32 位有符号整数
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由四个字节构成的 32 位有符号整数
+ */
+ public static int toInt(byte[] bytes, int startIndex) {
+ return toInt(copyFrom(bytes, startIndex, 4));
+ }
+
+ /**
+ * 返回由字节数组转换来的 64 位有符号整数
+ * @param bytes 字节数组
+ * @return 由八个字节构成的 64 位有符号整数
+ */
+ public static long toLong(byte[] bytes) {
+ if (isLittleEndian()) {
+ return (0xffL & (long) bytes[0])
+ | (0xff00L & ((long) bytes[1] << 8))
+ | (0xff0000L & ((long) bytes[2] << 16))
+ | (0xff000000L & ((long) bytes[3] << 24))
+ | (0xff00000000L & ((long) bytes[4] << 32))
+ | (0xff0000000000L & ((long) bytes[5] << 40))
+ | (0xff000000000000L & ((long) bytes[6] << 48))
+ | (0xff00000000000000L & ((long) bytes[7] << 56));
+ } else {
+ return (0xffL & (long) bytes[7])
+ | (0xff00L & ((long) bytes[6] << 8))
+ | (0xff0000L & ((long) bytes[5] << 16))
+ | (0xff000000L & ((long) bytes[4] << 24))
+ | (0xff00000000L & ((long) bytes[3] << 32))
+ | (0xff0000000000L & ((long) bytes[2] << 40))
+ | (0xff000000000000L & ((long) bytes[1] << 48))
+ | (0xff00000000000000L & ((long) bytes[0] << 56));
+ }
+ }
+
+ /**
+ * 返回由字节数组中的指定的八个字节转换来的 64 位有符号整数
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由八个字节构成的 64 位有符号整数
+ */
+ public static long toLong(byte[] bytes, int startIndex) {
+ return toLong(copyFrom(bytes, startIndex, 8));
+ }
+
+ /**
+ * 返回由字节数组转换来的单精度浮点数
+ * @param bytes 字节数组
+ * @return 由四个字节构成的单精度浮点数
+ */
+ public static float toFloat(byte[] bytes) {
+ return Float.intBitsToFloat(toInt(bytes));
+ }
+
+ /**
+ * 返回由字节数组中的指定的四个字节转换来的单精度浮点数
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由四个字节构成的单精度浮点数
+ */
+ public static float toFloat(byte[] bytes, int startIndex) {
+ return Float.intBitsToFloat(toInt(copyFrom(bytes, startIndex, 4)));
+ }
+
+ /**
+ * 返回由字节数组转换来的双精度浮点数
+ * @param bytes 字节数组
+ * @return 由八个字节构成的双精度浮点数
+ */
+ public static double toDouble(byte[] bytes) {
+ return Double.longBitsToDouble(toLong(bytes));
+ }
+
+ /**
+ * 返回由字节数组中的指定的八个字节转换来的双精度浮点数
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由八个字节构成的双精度浮点数
+ */
+ public static double toDouble(byte[] bytes, int startIndex) {
+ return Double.longBitsToDouble(toLong(copyFrom(bytes, startIndex, 8)));
+ }
+
+ /**
+ * 返回由字节数组转换来的字符串
+ * @param bytes 字节数组
+ * @return 字符串
+ */
+ public static String toString(byte[] bytes) {
+ return new String(bytes, Charset.forName("UTF-8"));
+ }
+
+ /**
+ * 返回由字节数组转换来的字符串
+ * @param bytes 字节数组
+ * @param charsetName 字符集编码
+ * @return 字符串
+ */
+ public static String toString(byte[] bytes, String charsetName) {
+ return new String(bytes, Charset.forName(charsetName));
+ }
+
+ /**
+ * 以字符串表示形式返回字节数组的内容
+ * @param bytes 字节数组
+ * @return 字符串形式的 bytes
+ */
+ public static String toHexString(byte[] bytes) {
+ if (bytes == null)
+ return "null";
+ int iMax = bytes.length - 1;
+ if (iMax == -1)
+ return "[]";
+ StringBuilder b = new StringBuilder();
+ b.append('[');
+ for (int i = 0; ; i++) {
+ b.append(String.format("%02x", bytes[i] & 0xFF));
+ if (i == iMax)
+ return b.append(']').toString();
+ b.append(", ");
+ }
+ }
+
+
+ // --------------------------------------------------------------------------------------------
+
+
+ /**
+ * 数组拷贝。
+ * @param src 字节数组。
+ * @param off 起始下标。
+ * @param len 拷贝长度。
+ * @return 指定长度的字节数组。
+ */
+ public static byte[] copyFrom(byte[] src, int off, int len) {
+ // return Arrays.copyOfRange(src, off, off + len);
+ byte[] bits = new byte[len];
+ for (int i = off, j = 0; i < src.length && j < len; i++, j++) {
+ bits[j] = src[i];
+ }
+ return bits;
+ }
+
+ /**
+ * 判断 CPU Endian 是否为 Little
+ * @return 判断结果
+ */
+ private static boolean isLittleEndian() {
+ return ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
+ }
+}
+
diff --git a/modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/DTUServer.java b/modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/DTUServer.java
new file mode 100644
index 00000000..54b17160
--- /dev/null
+++ b/modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/DTUServer.java
@@ -0,0 +1,48 @@
+package com.sarnath.modbusserver.dtuutils;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.logging.LogLevel;
+import io.netty.handler.logging.LoggingHandler;
+
+public class DTUServer {
+
+ static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
+ public static void Start()
+ {
+ //主工作线程组,设置为1个线程
+ EventLoopGroup bossGroup = new NioEventLoopGroup(1);
+ //工作线程组,默认为内核数*2的线程数
+ EventLoopGroup workerGroup = new NioEventLoopGroup();
+ try {
+ ServerBootstrap b = new ServerBootstrap();
+ b.group(bossGroup, workerGroup)
+ .channel(NioServerSocketChannel.class)
+ .option(ChannelOption.SO_BACKLOG, 100)
+ .childHandler(new ChannelInitializer() {
+ @Override
+ public void initChannel(SocketChannel ch) throws Exception {
+ ChannelPipeline p = ch.pipeline();
+ p.addLast(new LoggingHandler(LogLevel.INFO));
+ p.addLast(new DTUServerHandler());
+ }
+ });
+
+
+ // Start the server.
+ ChannelFuture f = b.bind(PORT).sync();
+ // Wait until the server socket is closed.
+ f.channel().closeFuture().sync();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ // Shut down all event loops to terminate all threads.
+ bossGroup.shutdownGracefully();
+ workerGroup.shutdownGracefully();
+ }
+ }
+
+}
diff --git a/modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/DTUServerHandler.java b/modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/DTUServerHandler.java
new file mode 100644
index 00000000..6735424e
--- /dev/null
+++ b/modbus-server/src/main/java/com/sarnath/modbusserver/dtuutils/DTUServerHandler.java
@@ -0,0 +1,137 @@
+package com.sarnath.modbusserver.dtuutils;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.net.InetSocketAddress;
+
+public class DTUServerHandler extends ChannelInboundHandlerAdapter {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DTUServerHandler.class);
+
+ private byte[] cBuf = new byte[0];
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg) {
+ InetSocketAddress ipSocket = (InetSocketAddress )ctx.channel().remoteAddress();
+ String addr = ipSocket.getAddress().getHostAddress();
+ int port = ipSocket.getPort();
+ LOG.info("通道读取,对方位于" + addr + ":" + port);
+ ByteBuf buffer = (ByteBuf)msg;
+ if (buffer != null)
+ {
+ //string msg = BitConverter.ToString(buffer.Array);
+ //LogUtil.Info(msg);
+ // 读取长度
+ int len = buffer.readableBytes();
+ byte[] curBuf = new byte[len];
+ buffer.readBytes(curBuf,0,len);
+ //System.arraycopy(buffer.array(), buffer.arrayOffset(), curBuf, 0, len);
+ String tempMsg = BitConverter.toHexString(curBuf);
+ LOG.info("xxxxxxxxx:"+tempMsg);
+ //
+ Unpacking(curBuf);
+ }
+ }
+
+ ///
+ /// 递归处理当前包
+ ///
+ ///
+ private void Unpacking(byte[] curBuf)
+ {
+ // 读取长度
+ int len = curBuf.length;
+ // 定义拼接数据包
+ byte[] revBuf = new byte[len + cBuf.length];
+ // 拼接 缓存数据包
+ System.arraycopy(cBuf, 0, revBuf, 0, cBuf.length);
+ // 拼接 新接收数据包
+ System.arraycopy(curBuf, 0, revBuf, cBuf.length, len);
+ // 使用完重置缓存包
+ cBuf = new byte[0];
+ // 包长判断
+ if (len >= 4)
+ {
+ String tempMsg = BitConverter.toHexString(revBuf);
+ LOG.info("xxxxxxxxx:"+tempMsg);
+
+ String tempMsg2 = BitConverter.toHexString(BitConverter.copyFrom(revBuf, 2, 2));
+ LOG.info("xxxxxxxxx2:"+tempMsg2);
+ LOG.info("xxxxxxxxx2:"+BitConverter.toHexString(BitConverter.getBytes((short) 6)));
+ //2 3 位为整包长度
+ short packageLen = BitConverter.toShort(BitConverter.copyFrom(revBuf, 2, 2));
+ LOG.info("packageLen:"+packageLen);
+ if (packageLen==0)
+ {
+ return;
+ }
+ if (packageLen > revBuf.length)
+ {
+ // 缓存断包 等待下一个数据包
+ LOG.info("缓存断包!");
+ cBuf = revBuf;
+ }
+ else
+ {
+ // 根据长度 拆包
+ byte[] comBuf = new byte[packageLen];
+ System.arraycopy(revBuf, 0, comBuf, 0, packageLen);
+ // 业务处理
+ DoSomeThing(comBuf);
+ //// 重置缓存包
+ //cBuf = new byte[0];
+ int remLen = revBuf.length - packageLen;
+ if (remLen>0)
+ {
+ LOG.info("粘包处理!");
+ // 重置当前处理包
+ curBuf = new byte[remLen];
+ System.arraycopy(revBuf, packageLen, curBuf, 0, remLen);
+ // 递归处理剩余数据包
+ Unpacking(curBuf);
+ }
+ }
+ }
+ else
+ {
+ // 缓存断包 等待下一个数据包
+ LOG.info("缓存断包!");
+ cBuf = revBuf;
+ }
+ }
+ @Override
+ public void channelReadComplete(ChannelHandlerContext ctx) {
+ ctx.flush();
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+ // Close the connection when an exception is raised.
+ cause.printStackTrace();
+ ctx.close();
+ }
+
+ private void DoSomeThing(byte[] comBuf)
+ {
+ String msg = BitConverter.toHexString(comBuf);
+ LOG.info("DoSomeThing:"+msg);
+
+ //int dataLen = BitConverter.ToInt16(comBuf, 2) - 14;
+ //byte[] DataByte = new byte[dataLen];
+ //Array.ConstrainedCopy(comBuf, 14, DataByte, 0, dataLen);
+
+ //// 0 1 头
+ //// 2 3 长度
+ //// 4 5 厂站号
+ //int stationId = BitConverter.ToInt16(comBuf, 4);
+ //// 6 7 通道号
+ //int channelId = BitConverter.ToInt16(comBuf, 6);
+ //int startAddress = BitConverter.ToInt16(comBuf, 11);
+ //int type = Convert.ToInt16(comBuf[9]);
+ //LogUtil.Info("场站号:" + stationId.ToString() + ", 通道号:" + channelId.ToString() + ", 起始地址:" + startAddress+",type:"+ type);
+ //LogUtil.Info(stationId+":"+string.Join("-", GetRaw(DataByte)));
+ }
+}
diff --git a/modbus-server/src/main/resources/banner.txt b/modbus-server/src/main/resources/banner.txt
new file mode 100644
index 00000000..d8ac9257
--- /dev/null
+++ b/modbus-server/src/main/resources/banner.txt
@@ -0,0 +1,8 @@
+Spring Boot Version: ${spring-boot.version}
+Spring Application Name: ${spring.application.name}
+ _____ .______. _________
+ / \ ____ __| _/\_ |__ __ __ ______ / _____/ ______________ __ ___________
+ / \ / \ / _ \ / __ | | __ \| | \/ ___/ ______ \_____ \_/ __ \_ __ \ \/ // __ \_ __ \
+/ Y ( <_> ) /_/ | | \_\ \ | /\___ \ /_____/ / \ ___/| | \/\ /\ ___/| | \/
+\____|__ /\____/\____ | |___ /____//____ > /_______ /\___ >__| \_/ \___ >__|
+ \/ \/ \/ \/ \/ \/ \/
diff --git a/modbus-server/src/main/resources/bootstrap.yml b/modbus-server/src/main/resources/bootstrap.yml
new file mode 100644
index 00000000..9f339a22
--- /dev/null
+++ b/modbus-server/src/main/resources/bootstrap.yml
@@ -0,0 +1,24 @@
+# Tomcat
+server:
+ port: 8710
+
+# Spring
+spring:
+ application:
+ # 应用名称
+ name: modbus-server
+ profiles:
+ # 环境配置
+ active: dev
+ cloud:
+ nacos:
+ discovery:
+ # 服务注册地址
+ server-addr: 127.0.0.1:8848
+ config:
+ # 配置中心地址
+ server-addr: 127.0.0.1:8848
+ # 配置文件格式
+ file-extension: yml
+ # 共享配置
+ shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
diff --git a/modbus-server/src/main/resources/logback.xml b/modbus-server/src/main/resources/logback.xml
new file mode 100644
index 00000000..351b5e57
--- /dev/null
+++ b/modbus-server/src/main/resources/logback.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+ :ss} %-5level ${springAppName:-} %thread %logger %msg%n"/>
+
+
+
+
+ ${log.pattern}
+
+
+
+
+
+ ${log.path}/info.log
+
+
+
+ ${log.path}/info.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ INFO
+
+ ACCEPT
+
+ DENY
+
+
+
+
+ ${log.path}/error.log
+
+
+
+ ${log.path}/error.%d{yyyy-MM-dd}.log
+
+ 60
+
+
+ ${log.pattern}
+
+
+
+ ERROR
+
+ ACCEPT
+
+ DENY
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index ac7bbabe..b0eeaecc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -71,21 +71,21 @@
pom
import
-
+
de.codecentric
spring-boot-admin-starter-client
${spring-boot-admin.version}
-
+
org.mybatis.spring.boot
mybatis-spring-boot-starter
${spring-boot.mybatis}
-
+
io.swagger
@@ -146,7 +146,7 @@
fastjson
${fastjson.version}
-
+
org.apache.commons
@@ -160,49 +160,49 @@
ruoyi-common-core
${ruoyi.version}
-
+
com.ruoyi
ruoyi-common-swagger
${ruoyi.version}
-
+
com.ruoyi
ruoyi-common-security
${ruoyi.version}
-
+
com.ruoyi
ruoyi-common-datascope
${ruoyi.version}
-
+
com.ruoyi
ruoyi-common-log
${ruoyi.version}
-
+
com.ruoyi
ruoyi-common-redis
${ruoyi.version}
-
+
com.ruoyi
ruoyi-api-system
${ruoyi.version}
-
+
@@ -213,11 +213,12 @@
ruoyi-modules
ruoyi-api
ruoyi-common
+ modbus-server
pom
-
+
@@ -234,4 +235,4 @@
-
\ No newline at end of file
+
diff --git a/ruoyi-api/ruoyi-api-system/pom.xml b/ruoyi-api/ruoyi-api-system/pom.xml
index 6f9997c9..0b1973d3 100644
--- a/ruoyi-api/ruoyi-api-system/pom.xml
+++ b/ruoyi-api/ruoyi-api-system/pom.xml
@@ -8,7 +8,7 @@
2.0.0
4.0.0
-
+
ruoyi-api-system
@@ -16,13 +16,13 @@
-
+
com.ruoyi
ruoyi-common-core
-
+
-
\ No newline at end of file
+
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/BitConverter.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/BitConverter.java
new file mode 100644
index 00000000..5b4397b0
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/BitConverter.java
@@ -0,0 +1,380 @@
+package com.ruoyi.common.core.utils;
+
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+
+/**
+ * 数字转字节数组工具类
+ */
+public class BitConverter {
+
+ /**
+ * 以字节数组的形式返回指定的布尔值
+ * @param data 一个布尔值
+ * @return 长度为 1 的字节数组
+ */
+ public static byte[] getBytes(boolean data) {
+ byte[] bytes = new byte[1];
+ bytes[0] = (byte) (data ? 1 : 0);
+ return bytes;
+ }
+
+ /**
+ * 以字节数组的形式返回指定的 16 位有符号整数值
+ * @param data 要转换的数字
+ * @return 长度为 2 的字节数组
+ */
+ public static byte[] getBytes(short data) {
+ byte[] bytes = new byte[2];
+ if (isLittleEndian()) {
+ bytes[0] = (byte) (data & 0xff);
+ bytes[1] = (byte) ((data & 0xff00) >> 8);
+ } else {
+ bytes[1] = (byte) (data & 0xff);
+ bytes[0] = (byte) ((data & 0xff00) >> 8);
+ }
+ return bytes;
+ }
+
+ /**
+ * 以字节数组的形式返回指定的 Unicode 字符值
+ * @param data 要转换的字符
+ * @return 长度为 2 的字节数组
+ */
+ public static byte[] getBytes(char data) {
+ byte[] bytes = new byte[2];
+ if (isLittleEndian()) {
+ bytes[0] = (byte) (data);
+ bytes[1] = (byte) (data >> 8);
+ } else {
+ bytes[1] = (byte) (data);
+ bytes[0] = (byte) (data >> 8);
+ }
+ return bytes;
+ }
+
+ /**
+ * 以字节数组的形式返回指定的 32 位有符号整数值
+ * @param data 要转换的数字
+ * @return 长度为 4 的字节数组
+ */
+ public static byte[] getBytes(int data) {
+ byte[] bytes = new byte[4];
+ if (isLittleEndian()) {
+ bytes[0] = (byte) (data & 0xff);
+ bytes[1] = (byte) ((data & 0xff00) >> 8);
+ bytes[2] = (byte) ((data & 0xff0000) >> 16);
+ bytes[3] = (byte) ((data & 0xff000000) >> 24);
+ } else {
+ bytes[3] = (byte) (data & 0xff);
+ bytes[2] = (byte) ((data & 0xff00) >> 8);
+ bytes[1] = (byte) ((data & 0xff0000) >> 16);
+ bytes[0] = (byte) ((data & 0xff000000) >> 24);
+ }
+ return bytes;
+ }
+
+ /**
+ * 以字节数组的形式返回指定的 64 位有符号整数值
+ * @param data 要转换的数字
+ * @return 长度为 8 的字节数组
+ */
+ public static byte[] getBytes(long data) {
+ byte[] bytes = new byte[8];
+ if (isLittleEndian()) {
+ bytes[0] = (byte) (data & 0xff);
+ bytes[1] = (byte) ((data >> 8) & 0xff);
+ bytes[2] = (byte) ((data >> 16) & 0xff);
+ bytes[3] = (byte) ((data >> 24) & 0xff);
+ bytes[4] = (byte) ((data >> 32) & 0xff);
+ bytes[5] = (byte) ((data >> 40) & 0xff);
+ bytes[6] = (byte) ((data >> 48) & 0xff);
+ bytes[7] = (byte) ((data >> 56) & 0xff);
+ } else {
+ bytes[7] = (byte) (data & 0xff);
+ bytes[6] = (byte) ((data >> 8) & 0xff);
+ bytes[5] = (byte) ((data >> 16) & 0xff);
+ bytes[4] = (byte) ((data >> 24) & 0xff);
+ bytes[3] = (byte) ((data >> 32) & 0xff);
+ bytes[2] = (byte) ((data >> 40) & 0xff);
+ bytes[1] = (byte) ((data >> 48) & 0xff);
+ bytes[0] = (byte) ((data >> 56) & 0xff);
+ }
+ return bytes;
+ }
+
+ /**
+ * 以字节数组的形式返回指定的单精度浮点值
+ * @param data 要转换的数字
+ * @return 长度为 4 的字节数组
+ */
+ public static byte[] getBytes(float data) {
+ return getBytes(Float.floatToIntBits(data));
+ }
+
+ /**
+ * 以字节数组的形式返回指定的双精度浮点值
+ * @param data 要转换的数字
+ * @return 长度为 8 的字节数组
+ */
+ public static byte[] getBytes(double data) {
+ return getBytes(Double.doubleToLongBits(data));
+ }
+
+ /**
+ * 将指定字符串中的所有字符编码为一个字节序列
+ * @param data 包含要编码的字符的字符串
+ * @return 一个字节数组,包含对指定的字符集进行编码的结果
+ */
+ public static byte[] getBytes(String data) {
+ return data.getBytes(Charset.forName("UTF-8"));
+ }
+
+ /**
+ * 将指定字符串中的所有字符编码为一个字节序列
+ * @param data 包含要编码的字符的字符串
+ * @param charsetName 字符集编码
+ * @return 一个字节数组,包含对指定的字符集进行编码的结果
+ */
+ public static byte[] getBytes(String data, String charsetName) {
+ return data.getBytes(Charset.forName(charsetName));
+ }
+
+ /**
+ * 返回由字节数组转换来的布尔值
+ * @param bytes 字节数组
+ * @return 布尔值
+ */
+ public static boolean toBoolean(byte[] bytes) {
+ return bytes[0] == 0 ? false : true;
+ }
+
+ /**
+ * 返回由字节数组中的指定的一个字节转换来的布尔值
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 布尔值
+ */
+ public static boolean toBoolean(byte[] bytes, int startIndex) {
+ return toBoolean(copyFrom(bytes, startIndex, 1));
+ }
+
+ /**
+ * 返回由字节数组转换来的 16 位有符号整数
+ * @param bytes 字节数组
+ * @return 由两个字节构成的 16 位有符号整数
+ */
+ public static short toShort(byte[] bytes) {
+ if (isLittleEndian()) {
+ return (short) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
+ } else {
+ return (short) ((0xff & bytes[1]) | (0xff00 & (bytes[0] << 8)));
+ }
+ }
+
+ /**
+ * 返回由字节数组中的指定的两个字节转换来的 16 位有符号整数
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由两个字节构成的 16 位有符号整数
+ */
+ public static short toShort(byte[] bytes, int startIndex) {
+ return toShort(copyFrom(bytes, startIndex, 2));
+ }
+
+ /**
+ * 返回由字节数组转换来的 Unicode 字符
+ * @param bytes 字节数组
+ * @return 由两个字节构成的字符
+ */
+ public static char toChar(byte[] bytes) {
+ if (isLittleEndian()) {
+ return (char) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
+ } else {
+ return (char) ((0xff & bytes[1]) | (0xff00 & (bytes[0] << 8)));
+ }
+ }
+
+ /**
+ * 返回由字节数组中的指定的两个字节转换来的 Unicode 字符
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由两个字节构成的字符
+ */
+ public static char toChar(byte[] bytes, int startIndex) {
+ return toChar(copyFrom(bytes, startIndex, 2));
+ }
+
+ /**
+ * 返回由字节数组转换来的 32 位有符号整数
+ * @param bytes 字节数组
+ * @return 由四个字节构成的 32 位有符号整数
+ */
+ public static int toInt(byte[] bytes) {
+ if (isLittleEndian()) {
+ return (0xff & bytes[0])
+ | (0xff00 & (bytes[1] << 8))
+ | (0xff0000 & (bytes[2] << 16))
+ | (0xff000000 & (bytes[3] << 24));
+ } else {
+ return (0xff & bytes[3])
+ | (0xff00 & (bytes[2] << 8))
+ | (0xff0000 & (bytes[1] << 16))
+ | (0xff000000 & (bytes[0] << 24));
+ }
+ }
+
+ /**
+ * 返回由字节数组中的指定的四个字节转换来的 32 位有符号整数
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由四个字节构成的 32 位有符号整数
+ */
+ public static int toInt(byte[] bytes, int startIndex) {
+ return toInt(copyFrom(bytes, startIndex, 4));
+ }
+
+ /**
+ * 返回由字节数组转换来的 64 位有符号整数
+ * @param bytes 字节数组
+ * @return 由八个字节构成的 64 位有符号整数
+ */
+ public static long toLong(byte[] bytes) {
+ if (isLittleEndian()) {
+ return (0xffL & (long) bytes[0])
+ | (0xff00L & ((long) bytes[1] << 8))
+ | (0xff0000L & ((long) bytes[2] << 16))
+ | (0xff000000L & ((long) bytes[3] << 24))
+ | (0xff00000000L & ((long) bytes[4] << 32))
+ | (0xff0000000000L & ((long) bytes[5] << 40))
+ | (0xff000000000000L & ((long) bytes[6] << 48))
+ | (0xff00000000000000L & ((long) bytes[7] << 56));
+ } else {
+ return (0xffL & (long) bytes[7])
+ | (0xff00L & ((long) bytes[6] << 8))
+ | (0xff0000L & ((long) bytes[5] << 16))
+ | (0xff000000L & ((long) bytes[4] << 24))
+ | (0xff00000000L & ((long) bytes[3] << 32))
+ | (0xff0000000000L & ((long) bytes[2] << 40))
+ | (0xff000000000000L & ((long) bytes[1] << 48))
+ | (0xff00000000000000L & ((long) bytes[0] << 56));
+ }
+ }
+
+ /**
+ * 返回由字节数组中的指定的八个字节转换来的 64 位有符号整数
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由八个字节构成的 64 位有符号整数
+ */
+ public static long toLong(byte[] bytes, int startIndex) {
+ return toLong(copyFrom(bytes, startIndex, 8));
+ }
+
+ /**
+ * 返回由字节数组转换来的单精度浮点数
+ * @param bytes 字节数组
+ * @return 由四个字节构成的单精度浮点数
+ */
+ public static float toFloat(byte[] bytes) {
+ return Float.intBitsToFloat(toInt(bytes));
+ }
+
+ /**
+ * 返回由字节数组中的指定的四个字节转换来的单精度浮点数
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由四个字节构成的单精度浮点数
+ */
+ public static float toFloat(byte[] bytes, int startIndex) {
+ return Float.intBitsToFloat(toInt(copyFrom(bytes, startIndex, 4)));
+ }
+
+ /**
+ * 返回由字节数组转换来的双精度浮点数
+ * @param bytes 字节数组
+ * @return 由八个字节构成的双精度浮点数
+ */
+ public static double toDouble(byte[] bytes) {
+ return Double.longBitsToDouble(toLong(bytes));
+ }
+
+ /**
+ * 返回由字节数组中的指定的八个字节转换来的双精度浮点数
+ * @param bytes 字节数组
+ * @param startIndex 起始下标
+ * @return 由八个字节构成的双精度浮点数
+ */
+ public static double toDouble(byte[] bytes, int startIndex) {
+ return Double.longBitsToDouble(toLong(copyFrom(bytes, startIndex, 8)));
+ }
+
+ /**
+ * 返回由字节数组转换来的字符串
+ * @param bytes 字节数组
+ * @return 字符串
+ */
+ public static String toString(byte[] bytes) {
+ return new String(bytes, Charset.forName("UTF-8"));
+ }
+
+ /**
+ * 返回由字节数组转换来的字符串
+ * @param bytes 字节数组
+ * @param charsetName 字符集编码
+ * @return 字符串
+ */
+ public static String toString(byte[] bytes, String charsetName) {
+ return new String(bytes, Charset.forName(charsetName));
+ }
+
+ /**
+ * 以字符串表示形式返回字节数组的内容
+ * @param bytes 字节数组
+ * @return 字符串形式的 bytes
+ */
+ public static String toHexString(byte[] bytes) {
+ if (bytes == null)
+ return "null";
+ int iMax = bytes.length - 1;
+ if (iMax == -1)
+ return "[]";
+ StringBuilder b = new StringBuilder();
+ b.append('[');
+ for (int i = 0; ; i++) {
+ b.append(String.format("%02x", bytes[i] & 0xFF));
+ if (i == iMax)
+ return b.append(']').toString();
+ b.append(", ");
+ }
+ }
+
+
+ // --------------------------------------------------------------------------------------------
+
+
+ /**
+ * 数组拷贝。
+ * @param src 字节数组。
+ * @param off 起始下标。
+ * @param len 拷贝长度。
+ * @return 指定长度的字节数组。
+ */
+ private static byte[] copyFrom(byte[] src, int off, int len) {
+ // return Arrays.copyOfRange(src, off, off + len);
+ byte[] bits = new byte[len];
+ for (int i = off, j = 0; i < src.length && j < len; i++, j++) {
+ bits[j] = src[i];
+ }
+ return bits;
+ }
+
+ /**
+ * 判断 CPU Endian 是否为 Little
+ * @return 判断结果
+ */
+ private static boolean isLittleEndian() {
+ return ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
+ }
+}
+
diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/RuoYiGatewayApplication.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/RuoYiGatewayApplication.java
index d1f6ec14..0533aaf4 100644
--- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/RuoYiGatewayApplication.java
+++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/RuoYiGatewayApplication.java
@@ -7,11 +7,11 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* 网关启动程序
- *
+ *
* @author ruoyi
*/
@EnableDiscoveryClient
-@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })// 关闭自动配置功能
public class RuoYiGatewayApplication
{
public static void main(String[] args)
@@ -28,4 +28,4 @@ public class RuoYiGatewayApplication
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
-}
\ No newline at end of file
+}
diff --git a/ruoyi-modules/ruoyi-system/pom.xml b/ruoyi-modules/ruoyi-system/pom.xml
index bddafc43..d30bf4c3 100644
--- a/ruoyi-modules/ruoyi-system/pom.xml
+++ b/ruoyi-modules/ruoyi-system/pom.xml
@@ -8,76 +8,76 @@
2.0.0
4.0.0
-
+
ruoyi-modules-system
ruoyi-modules-system系统模块
-
+
-
+
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
-
+
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
-
+
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
-
+
org.springframework.boot
spring-boot-starter-web
-
+
io.springfox
springfox-swagger-ui
${swagger.fox.version}
-
+
mysql
mysql-connector-java
-
+
com.ruoyi
ruoyi-common-security
-
+
com.ruoyi
ruoyi-common-datascope
-
+
com.ruoyi
ruoyi-common-log
-
+
com.ruoyi
ruoyi-common-swagger
-
+
com.ruoyi
@@ -101,5 +101,5 @@
-
-
\ No newline at end of file
+
+
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java
index a8509575..b412abaa 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java
@@ -4,6 +4,7 @@ import java.io.IOException;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletResponse;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
diff --git a/ruoyi-visual/hystrix-dashboard/pom.xml b/ruoyi-visual/hystrix-dashboard/pom.xml
new file mode 100644
index 00000000..0043d868
--- /dev/null
+++ b/ruoyi-visual/hystrix-dashboard/pom.xml
@@ -0,0 +1,67 @@
+
+
+
+ ruoyi-visual
+ com.ruoyi
+ 2.0.0
+
+ 4.0.0
+
+ hystrix-dashboard
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-sentinel
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ com.netflix.hystrix
+ hystrix-javanica
+ RELEASE
+
+
+ org.springframework.cloud
+ spring-cloud-netflix-hystrix-dashboard
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+
+
+
+
+
+
diff --git a/ruoyi-visual/hystrix-dashboard/src/main/java/com/sarnath/hystrix/dashboard/HystrixDashBoardApplication.java b/ruoyi-visual/hystrix-dashboard/src/main/java/com/sarnath/hystrix/dashboard/HystrixDashBoardApplication.java
new file mode 100644
index 00000000..04077552
--- /dev/null
+++ b/ruoyi-visual/hystrix-dashboard/src/main/java/com/sarnath/hystrix/dashboard/HystrixDashBoardApplication.java
@@ -0,0 +1,22 @@
+package com.sarnath.hystrix.dashboard;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.cloud.client.SpringCloudApplication;
+import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
+
+@EnableHystrixDashboard
+@SpringCloudApplication
+public class HystrixDashBoardApplication {
+ public static void main(String[] args)
+ {
+ SpringApplication.run(HystrixDashBoardApplication.class, args);
+ System.out.println("(♥◠‿◠)ノ゙ hystrix-dashboard服务模块启动成功 ლ(´ڡ`ლ)゙ \n" +
+ "____.___._________ \n" +
+ "\\__ | |\\_ ___ \\ \n" +
+ " / | |/ \\ \\/ \n" +
+ " \\____ |\\ \\____\n" +
+ " / ______| \\______ /\n" +
+ " \\/ \\/ ");
+
+ }
+}
diff --git a/ruoyi-visual/hystrix-dashboard/src/main/resources/banner.txt b/ruoyi-visual/hystrix-dashboard/src/main/resources/banner.txt
new file mode 100644
index 00000000..71027b75
--- /dev/null
+++ b/ruoyi-visual/hystrix-dashboard/src/main/resources/banner.txt
@@ -0,0 +1,8 @@
+Spring Boot Version: ${spring-boot.version}
+Spring Application Name: ${spring.application.name}
+.__ __ .__ .___ .__ ___. .___
+| |__ ___.__. _______/ |________|__|__ ___ __| _/____ _____| |__\_ |__ _________ _______ __| _/
+| | < | |/ ___/\ __\_ __ \ \ \/ / ______ / __ |\__ \ / ___/ | \| __ \ / _ \__ \\_ __ \/ __ |
+| Y \___ |\___ \ | | | | \/ |> < /_____/ / /_/ | / __ \_\___ \| Y \ \_\ ( <_> ) __ \| | \/ /_/ |
+|___| / ____/____ > |__| |__| |__/__/\_ \ \____ |(____ /____ >___| /___ /\____(____ /__| \____ |
+ \/\/ \/ \/ \/ \/ \/ \/ \/ \/ \/
diff --git a/ruoyi-visual/hystrix-dashboard/src/main/resources/bootstrap.yml b/ruoyi-visual/hystrix-dashboard/src/main/resources/bootstrap.yml
new file mode 100644
index 00000000..11cda9a1
--- /dev/null
+++ b/ruoyi-visual/hystrix-dashboard/src/main/resources/bootstrap.yml
@@ -0,0 +1,24 @@
+# Tomcat
+server:
+ port: 8100
+
+# Spring
+spring:
+ application:
+ # 应用名称
+ name: hystrix-dashboard
+ profiles:
+ # 环境配置
+ active: dev
+ cloud:
+ nacos:
+ discovery:
+ # 服务注册地址
+ server-addr: 127.0.0.1:8848
+ config:
+ # 配置中心地址
+ server-addr: 127.0.0.1:8848
+ # 配置文件格式
+ file-extension: yml
+ # 共享配置
+ shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
diff --git a/ruoyi-visual/pom.xml b/ruoyi-visual/pom.xml
index d2838a92..68365f5c 100644
--- a/ruoyi-visual/pom.xml
+++ b/ruoyi-visual/pom.xml
@@ -10,6 +10,7 @@
ruoyi-monitor
+ hystrix-dashboard
ruoyi-visual