You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by qi...@apache.org on 2022/08/03 12:30:42 UTC

[iotdb-web-workbench] 08/29: Add GH actions Support till version 13 Fixed all licensing for RAT Plugin Minor Update in Readme and License

This is an automated email from the ASF dual-hosted git repository.

qiaojialin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb-web-workbench.git

commit 63a507fcbb5456941ddce2c6807a54729fac667c
Author: Julian Feinauer <j....@pragmaticminds.de>
AuthorDate: Sat Sep 11 10:54:52 2021 +0200

    Add GH actions
    Support till version 13
    Fixed all licensing for RAT Plugin
    Minor Update in Readme and License
---
 .github/workflows/default.yml                      |   55 +
 NOTICE                                             |    5 +-
 README.md                                          |    1 +
 README_zh.md                                       |   19 +-
 backend/.drone.yml                                 |   68 +
 backend/Dockerfile                                 |   24 +
 README.md => backend/README.md                     |   37 +-
 backend/build.gradle                               |   66 +
 backend/build.sh                                   |   20 +
 README.md => backend/doc/config.md                 |   28 +-
 backend/doc/deploy.md                              |   65 +
 backend/doc/intro.md                               |   55 +
 README.md => backend/doc/log.md                    |   10 +-
 backend/doc/maven.md                               |   46 +
 backend/doc/note.md                                |   74 +
 README.md => backend/doc/promise.md                |    9 +-
 README.md => backend/doc/release.md                |    8 +-
 README.md => backend/doc/rest.md                   |   11 +-
 README.md => backend/doc/rule.md                   |   17 +-
 backend/doc/swagger.md                             |   51 +
 backend/doc/validate.md                            |   68 +
 backend/gradlew                                    |  188 ++
 backend/pom.xml                                    |  239 +++
 backend/settings.gradle                            |   20 +
 .../org/apache/iotdb/admin/AdminApplication.java   |   39 +
 .../iotdb/admin/aop/BaseExceptionAdvice.java       |   44 +
 .../apache/iotdb/admin/aop/ParamValidAspect.java   |   78 +
 .../admin/common/exception/BaseException.java      |   43 +
 .../iotdb/admin/common/exception/ErrorCode.java    |  286 +++
 .../admin/common/utils/AuthenticationUtils.java    |   49 +
 .../apache/iotdb/admin/config/FilterConfig.java    |   46 +
 .../iotdb/admin/config/MybatisPlusConfig.java      |   51 +
 .../apache/iotdb/admin/config/SecurityConfig.java  |   49 +
 .../apache/iotdb/admin/config/SwaggerConfig.java   |   79 +
 .../iotdb/admin/config/ValidatorConfiguration.java |   41 +
 .../admin/controller/ConnectionController.java     |  125 ++
 .../iotdb/admin/controller/HealthController.java   |   51 +
 .../iotdb/admin/controller/IotDBController.java    |  867 +++++++++
 .../iotdb/admin/controller/QueryController.java    |  133 ++
 .../iotdb/admin/controller/UserController.java     |  121 ++
 .../java/org/apache/iotdb/admin/demo/JDBC.java     |  159 ++
 .../org/apache/iotdb/admin/demo/NativeAPI.java     |  123 ++
 .../org/apache/iotdb/admin/filter/TokenFilter.java |   57 +
 .../iotdb/admin/mapper/ConnectionMapper.java       |   29 +
 .../apache/iotdb/admin/mapper/DeviceMapper.java    |   28 +
 .../org/apache/iotdb/admin/mapper/GroupMapper.java |   28 +
 .../iotdb/admin/mapper/MeasurementMapper.java      |   29 +
 .../org/apache/iotdb/admin/mapper/QueryMapper.java |   29 +
 .../org/apache/iotdb/admin/mapper/UserMapper.java  |   29 +
 .../iotdb/admin/model/dto/ConnectionDTO.java       |   53 +
 .../org/apache/iotdb/admin/model/dto/CountDTO.java |   33 +
 .../apache/iotdb/admin/model/dto/DeviceDTO.java    |   36 +
 .../iotdb/admin/model/dto/DeviceInfoDTO.java       |   41 +
 .../org/apache/iotdb/admin/model/dto/GroupDTO.java |   41 +
 .../apache/iotdb/admin/model/dto/IotDBRole.java    |   39 +
 .../apache/iotdb/admin/model/dto/IotDBUser.java    |   45 +
 .../apache/iotdb/admin/model/dto/IotDBUserDTO.java |   31 +
 .../iotdb/admin/model/dto/MeasurementDTO.java      |   37 +
 .../iotdb/admin/model/dto/PrivilegeInfoDTO.java    |   40 +
 .../org/apache/iotdb/admin/model/dto/QueryDTO.java |   35 +
 .../apache/iotdb/admin/model/dto/SearchDTO.java    |   36 +
 .../apache/iotdb/admin/model/dto/Timeseries.java   |   42 +
 .../iotdb/admin/model/entity/Connection.java       |   65 +
 .../apache/iotdb/admin/model/entity/Device.java    |   54 +
 .../iotdb/admin/model/entity/Measurement.java      |   43 +
 .../org/apache/iotdb/admin/model/entity/Query.java |   42 +
 .../iotdb/admin/model/entity/StorageGroup.java     |   54 +
 .../org/apache/iotdb/admin/model/entity/User.java  |   49 +
 .../org/apache/iotdb/admin/model/vo/BaseVO.java    |   58 +
 .../org/apache/iotdb/admin/model/vo/ConnVO.java    |   38 +
 .../apache/iotdb/admin/model/vo/ConnectionVO.java  |   40 +
 .../apache/iotdb/admin/model/vo/DeviceInfo.java    |   34 +
 .../apache/iotdb/admin/model/vo/DeviceInfoVO.java  |   33 +
 .../org/apache/iotdb/admin/model/vo/DeviceVO.java  |   33 +
 .../apache/iotdb/admin/model/vo/GroupInfoVO.java   |   37 +
 .../org/apache/iotdb/admin/model/vo/GroupVO.java   |   36 +
 .../apache/iotdb/admin/model/vo/IotDBUserVO.java   |   34 +
 .../apache/iotdb/admin/model/vo/MeasurementVO.java |   34 +
 .../iotdb/admin/model/vo/MeasuremtnInfoVO.java     |   33 +
 .../org/apache/iotdb/admin/model/vo/PathVO.java    |   32 +
 .../apache/iotdb/admin/model/vo/PrivilegeInfo.java |   39 +
 .../org/apache/iotdb/admin/model/vo/QueryVO.java   |   31 +
 .../org/apache/iotdb/admin/model/vo/RecordVO.java  |   33 +
 .../iotdb/admin/model/vo/RoleWithPrivilegesVO.java |   34 +
 .../apache/iotdb/admin/model/vo/SqlResultVO.java   |   37 +
 .../iotdb/admin/model/vo/StorageGroupVO.java       |   31 +
 .../iotdb/admin/service/ConnectionService.java     |   41 +
 .../apache/iotdb/admin/service/DeviceService.java  |   43 +
 .../apache/iotdb/admin/service/GroupService.java   |   44 +
 .../apache/iotdb/admin/service/IotDBService.java   |   96 +
 .../iotdb/admin/service/MeasurementService.java    |   36 +
 .../apache/iotdb/admin/service/QueryService.java   |   39 +
 .../apache/iotdb/admin/service/UserService.java    |   32 +
 .../admin/service/impl/ConnectionServiceImpl.java  |  128 ++
 .../admin/service/impl/DeviceServiceImpl.java      |  144 ++
 .../iotdb/admin/service/impl/GroupServiceImpl.java |  157 ++
 .../iotdb/admin/service/impl/IotDBServiceImpl.java | 1857 ++++++++++++++++++++
 .../admin/service/impl/MeasurementServiceImpl.java |  142 ++
 .../iotdb/admin/service/impl/QueryServiceImpl.java |  109 ++
 .../iotdb/admin/service/impl/UserServiceImpl.java  |   85 +
 backend/src/main/resources/META-INF/app.properties |   20 +
 .../src/main/resources/application-dev.properties  |   30 +
 .../src/main/resources/application-prod.properties |   30 +
 .../src/main/resources/application-test.properties |   26 +
 backend/src/main/resources/application.properties  |   21 +
 backend/src/main/resources/log4j2-prod.xml         |  120 ++
 backend/src/main/resources/log4j2.xml              |  120 ++
 .../test/java/org/apache/iotdb/admin/DemoJDBC.java |   41 +
 .../admin/controller/ConnectionControllerTest.java |  118 ++
 .../admin/controller/IotDBControllerTest.java      |  380 ++++
 .../admin/controller/QueryControllerTest.java      |  134 ++
 .../iotdb/admin/controller/TestSystemInfo.java     |   47 +
 112 files changed, 9275 insertions(+), 25 deletions(-)

diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml
new file mode 100644
index 0000000..d0b7938
--- /dev/null
+++ b/.github/workflows/default.yml
@@ -0,0 +1,55 @@
+# This workflow will build a Java project with Maven
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Main Mac and Linux
+
+on:
+  push:
+    branches:
+      - master
+      - 'rel/*'
+      - Vector
+    paths-ignore:
+      - 'docs/**'
+  pull_request:
+    branches:
+      - master
+      - 'rel/*'
+      - cluster_new
+      - Vector
+    paths-ignore:
+      - 'docs/**'
+  # allow manually run the action:
+  workflow_dispatch:
+
+env:
+  MAVEN_OPTS: -Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false -Dmaven.wagon.http.retryHandler.class=standard -Dmaven.wagon.http.retryHandler.count=3
+
+jobs:
+  unix:
+    strategy:
+      fail-fast: false
+      max-parallel: 20
+      matrix:
+        java: [ 8, 11, 13 ]
+        os: [ ubuntu-latest, macos-latest ]
+    runs-on: ${{ matrix.os}}
+
+    steps:
+      - uses: actions/checkout@v2
+      - name: Set up JDK ${{ matrix.java }}
+        uses: actions/setup-java@v1
+        with:
+          java-version: ${{ matrix.java }}
+      - name: Cache Maven packages
+        uses: actions/cache@v2
+        with:
+          path: ~/.m2
+          key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+          restore-keys: ${{ runner.os }}-m2-
+      - name: Check Apache Rat
+        run: cd backend && mvn -B apache-rat:check -P site -P code-coverage
+      - name: IT/UT Test
+        shell: bash
+        # we do not compile client-cpp for saving time, it is tested in client.yml
+        run:  cd backend && mvn -B clean post-integration-test -Dtest.port.closed=true -P '!testcontainer'
diff --git a/NOTICE b/NOTICE
index e983e45..3b945c0 100644
--- a/NOTICE
+++ b/NOTICE
@@ -21,4 +21,7 @@ Apache Commons Collections
 Copyright 2001-2019 The Apache Software Foundation
 
 This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
\ No newline at end of file
+The Apache Software Foundation (http://www.apache.org/).
+
+============================================================================
+
diff --git a/README.md b/README.md
index 06ee6a0..adf58fc 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,7 @@
     under the License.
 
 -->
+
 [English](./README.md) | [中文](./README_ZH.md)
 
 # Overview
diff --git a/README_zh.md b/README_zh.md
index 06ee6a0..9f1cb6d 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -18,9 +18,22 @@
     under the License.
 
 -->
-[English](./README.md) | [中文](./README_ZH.md)
 
-# Overview
+[English](./README.md) | [中文](./README_zh.md)
+
+# IoTDB-Workbench
+
+IotDB-Workbench是IotDB的可视化管理工具,可对IotDB的数据进行增删改查、权限控制等,简化IotDB的使用及学习成本。
+在我们心中IotDB是最棒的时序数据库之一,我们将一直不遗余力地推动国产时序数据库IotDB的应用和发展,为本土开源能力的提高、开源生态的发展,贡献自己的力量,欢迎大家加入IotDB Admin的开发及维护,期待你的加入:
+
+![微信](backend/doc/image/wechat.png)
+
+## 后端服务运行
+
+[后端服务设计及运行说明](backend/README.md)
+
+## 前端服务运行
+
+[前端服务运行说明](frontend/README.md)
 
-This code repo is a web based workbench for [Apache IoTDB](https://iotdb.apache.org)
 
diff --git a/backend/.drone.yml b/backend/.drone.yml
new file mode 100644
index 0000000..9307f0d
--- /dev/null
+++ b/backend/.drone.yml
@@ -0,0 +1,68 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+---
+kind: pipeline
+name: deploy-testing-environment-preview.1.0
+git_image: hub.d.cisdigital.cn/drone/git
+platform:
+  os: linux
+  arch: amd64
+
+steps:
+  - name: tag
+    image: hub.segma.tech/drone/drone-tag:v1.1
+    environment:
+      TAG_FILE: .tags
+
+  - name: build
+    image: hub.segma.tech/drone/maven-plugin:3.6.1-jdk-8-alpine
+    commands:
+      - mvn clean package -D maven.test.skip=true
+
+  - name: docker
+    image: hub.segma.tech/drone/plugins/docker:19.03.8
+    environment:
+      PLUGIN_DEBUG: true
+    settings:
+      dockerfile: ./Dockerfile
+      username:
+        from_secret: docker_username
+      password:
+        from_secret: docker_password
+      repo: hub.d.cisdigital.cn/iot-dacoo/iotdb
+      registry: hub.d.cisdigital.cn
+      insecure: true
+
+  - name: deploy
+    image: hub.d.cisdigital.cn/drone/drone-paas-plugin:latest
+    settings:
+      application_id: 62
+      application_cluster: dev_paas
+      application_deployment_id: 725
+      application_deployment_replicas: 1
+      application_deployment_image: hub.d.cisdigital.cn/iot-dacoo/iotdb
+      server_url: http://drone-paas-server.kube-drone:8080
+      
+trigger:
+  branch:
+    - master
+    - dev
+  event:
+    - push
\ No newline at end of file
diff --git a/backend/Dockerfile b/backend/Dockerfile
new file mode 100644
index 0000000..f6e39cc
--- /dev/null
+++ b/backend/Dockerfile
@@ -0,0 +1,24 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+FROM hub.segma.tech/library/java:8-jre-centos7-apollo
+
+COPY target/service-1.0.0.jar /app/app.jar
+
+ENTRYPOINT ["java", "-jar", "/app/app.jar"]
diff --git a/README.md b/backend/README.md
similarity index 58%
copy from README.md
copy to backend/README.md
index 06ee6a0..63d3d6e 100644
--- a/README.md
+++ b/backend/README.md
@@ -18,9 +18,40 @@
     under the License.
 
 -->
-[English](./README.md) | [中文](./README_ZH.md)
 
-# Overview
+# 后端服务设计及运行说明
 
-This code repo is a web based workbench for [Apache IoTDB](https://iotdb.apache.org)
+[IoTDB-Workbench快速入门](doc/intro.md)
 
+## Building the Backend
+
+The backend can be built using maven by using
+
+```
+mvn clean install
+```
+
+## 开发环境搭建
+
+[Maven配置](doc/maven.md)
+
+[日志如何配置](doc/log.md)
+
+[接口文档配置](doc/swagger.md)
+
+[统一参数验证](doc/validate.md)
+
+[常用实践约定](doc/promise.md)
+
+[接口规范](doc/rest.md)
+
+[代码规范checkstyle](doc/rule.md)
+
+[代码规范和注释](doc/note.md)
+
+## 线上部署
+
+[项目部署](doc/deploy.md)
+
+## 发布日志
+[release-note](doc/release.md)
diff --git a/backend/build.gradle b/backend/build.gradle
new file mode 100644
index 0000000..8b92fc3
--- /dev/null
+++ b/backend/build.gradle
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+apply plugin: 'java'
+apply plugin: 'maven'
+
+group = 'cn.cisdigital.demo'
+version = '1.0.0'
+
+description = """demo项目"""
+
+sourceCompatibility = 1.5
+targetCompatibility = 1.5
+tasks.withType(JavaCompile) {
+	options.encoding = 'UTF-8'
+}
+
+
+
+repositories {
+        
+     maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
+     maven { url "http://10.73.1.87:8088/nexus/content/groups/public/" }
+     maven { url "http://repo.maven.apache.org/maven2" }
+}
+dependencies {
+    compile(group: 'org.springframework.boot', name: 'spring-boot-starter-web', version:'2.3.3.RELEASE') {
+exclude(module: 'spring-boot-starter-logging')
+    }
+    compile(group: 'mysql', name: 'mysql-connector-java', version:'5.1.47') {
+exclude(module: 'protobuf-java')
+    }
+    compile group: 'org.springframework.boot', name: 'spring-boot-starter-log4j2', version:'2.3.3.RELEASE'
+    compile group: 'org.projectlombok', name: 'lombok', version:'1.18.12'
+    compile group: 'com.alibaba', name: 'druid-spring-boot-starter', version:'1.1.17'
+    compile group: 'com.baomidou', name: 'mybatis-plus-boot-starter', version:'3.4.0'
+    compile group: 'com.alibaba', name: 'fastjson', version:'1.2.73'
+    compile group: 'org.apache.commons', name: 'commons-lang3', version:'3.11'
+    compile group: 'com.ctrip.framework.apollo', name: 'apollo-client', version:'1.2.0'
+    compile group: 'io.springfox', name: 'springfox-swagger2', version:'2.7.0'
+    compile group: 'io.springfox', name: 'springfox-swagger-ui', version:'2.7.0'
+    compile group: 'cn.cisdigital', name: 'exception-component', version:'1.0.0'
+    compile group: 'com.dianping.cat', name: 'cat-client', version:'3.0.0'
+    compile group: 'org.hibernate.validator', name: 'hibernate-validator', version:'6.0.9.Final'
+    compile group: 'org.aspectj', name: 'aspectjweaver', version:'1.9.6'
+    testCompile(group: 'org.springframework.boot', name: 'spring-boot-starter-test', version:'2.3.3.RELEASE') {
+exclude(module: 'junit-vintage-engine')
+    }
+    testCompile group: 'junit', name: 'junit', version:'4.13'
+}
diff --git a/backend/build.sh b/backend/build.sh
new file mode 100755
index 0000000..40fdd9a
--- /dev/null
+++ b/backend/build.sh
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+#!/usr/bin/env bash
\ No newline at end of file
diff --git a/README.md b/backend/doc/config.md
similarity index 54%
copy from README.md
copy to backend/doc/config.md
index 06ee6a0..bd1b453 100644
--- a/README.md
+++ b/backend/doc/config.md
@@ -18,9 +18,31 @@
     under the License.
 
 -->
-[English](./README.md) | [中文](./README_ZH.md)
 
-# Overview
+# 配置中心 Apollo
 
-This code repo is a web based workbench for [Apache IoTDB](https://iotdb.apache.org)
+##接入步骤
+1. 添加依赖 ,在pom.xml 中添加依赖,如不需要apolo,可以去掉该依赖
 
+```xml
+<dependency>
+  <groupId>com.ctrip.framework.apollo</groupId>
+  <artifactId>apollo-client</artifactId>
+  <version>1.2.0</version>
+</dependency>
+```
+
+版本号请使用1.2.0,服务器版本xxx
+
+2. 在application.properties文件中增加必要配置
+
+```properties
+    #配置中心服务地址
+    apollo.meta=http://192.168.1.241:8081
+    #开启配置中心
+    apollo.bootstrap.enabled=true
+    # 采用配置的形式注入命名空间application
+    apollo.bootstrap.namespaces=application
+```
+
+3. 编写读取配置的类。参考bean包下面的TestBean类。
diff --git a/backend/doc/deploy.md b/backend/doc/deploy.md
new file mode 100644
index 0000000..c608a17
--- /dev/null
+++ b/backend/doc/deploy.md
@@ -0,0 +1,65 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+# 部署流程
+
+## 后端部署
+
+1 通过backend/src/main/resources/application-xxx.properties文件配置项目,注意修改数据源的路径。
+
+![](image/配置文件.PNG)
+
+2 打包
+
+![](image/打包.png)
+
+3 打包之后,将jar包上传到指定服务器并运行。  
+
+首先请确定服务器上安装了sqlite3(一般Linux系统自带sqlite3,如果没有请安装)。  
+通过如下命令将jar包挂载到后台运行:  
+nohup java -jar xxx.jar >/dev/null 2>&1 &
+
+至此后端部署完成。
+
+## 前端结合后端部署
+
+1 在服务器安装nginx服务器,命令如下:
+
+yum install -y nginx
+
+2 安装完成后,配置nginx的配置文件,可通过nginx -t 获取配置文件路径:
+
+![](image/nginx配置文件位置.png)
+
+3 vim xxx.conf编辑nginx配置
+
+配置信息如下:
+
+![](image/nginx配置文件.png)
+
+黄框内容为监听端口号配置;  
+红框内容以“/”映射前端资源文件,请指定为你的dist文件路径;  
+绿框以“/api”映射后台服务地址,与application-xxx.properties文件中配置的端口号和上下文根保持一致;  
+如果你需要多个服务则需配置多个server
+
+4 保存配置后,命令行输入nginx启动nginx
+
+浏览器调用服务器ip地址,端口号为黄框里指定的端口号,请求到服务器资源则部署成功。
diff --git a/backend/doc/intro.md b/backend/doc/intro.md
new file mode 100644
index 0000000..b57f038
--- /dev/null
+++ b/backend/doc/intro.md
@@ -0,0 +1,55 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+# IoTDB-Workbench快速入门
+
+该项目IoTDB-Workbench,为IoTDB的可视化监控程序。
+
+## 支持的环境
+
+目前支持的开发环境如下:
+
+- Java 1.8
+- Maven 3.3.9 或以上
+- Gradle
+- 推荐IntelliJ IDEA 2017或以上
+
+## 目录结构说明
+
+- doc : 文档目录,一些帮助文档
+- src : 源码文件
+- Dockerfile : docker镜像打包文件
+- pom.xml : Maven Pom文件
+- README.md : 帮助文件目录
+
+## 使用的公用库
+
+由于是开源软件,使用的所有库都应该是maven公有仓库能找的,满足轻量、稳定2个特性。
+
+## 快速启动
+
+项目提供maven、gradle两种构建工具,以maven为例启动项目:  
+首先通过IntelliJ IDEA打开本项目,右键点击pom.xml,点击Add as Maven Project导入项目相关依赖。
+![](image/pom.PNG)  
+导入完成后启动AdminApplication项目,如果未报错并出现如下界面则代表项目运行成功。  
+![](image/启动成功.PNG)  
+本系统默认登录用户为root,密码为123456。  
+具体部署步骤请参考[部署文档](deploy.md)
\ No newline at end of file
diff --git a/README.md b/backend/doc/log.md
similarity index 61%
copy from README.md
copy to backend/doc/log.md
index 06ee6a0..536f83b 100644
--- a/README.md
+++ b/backend/doc/log.md
@@ -18,9 +18,13 @@
     under the License.
 
 -->
-[English](./README.md) | [中文](./README_ZH.md)
 
-# Overview
+# 日志配置
 
-This code repo is a web based workbench for [Apache IoTDB](https://iotdb.apache.org)
+日志使用的是log4j,日志配置文件在src/main/resources/log4j2.xml中,log4j2.xml中默认路径写的是:
 
+<property name="log.home">/data/applogs/app-test</property>
+
+window系统请更改路径。
+
+默认我们已经配置好了日志,如果启动的时候报`ERROR Unable to create file /data/applogs/app/projectservicedemo_debug.log java.io.IOException: Could not create directory /data/applogs/app`的错误,那么可能你没有/data目录的权限,这时候你需要换一个目录。
diff --git a/backend/doc/maven.md b/backend/doc/maven.md
new file mode 100644
index 0000000..6b03b5a
--- /dev/null
+++ b/backend/doc/maven.md
@@ -0,0 +1,46 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+# Maven 仓库配置
+
+本文介绍如何配置Maven仓库
+
+## Maven 安装
+
+无论你是mac电脑还是window电脑,都可以到Maven官网直接下载[Maven 3.8.2](https://dlcdn.apache.org/maven/maven-3/3.8.2/binaries/apache-maven-3.8.2-bin.tar.gz)
+
+然后找一个目录解压,路径最好不要有中文,然后在Idea中引用该Maven。在下图中找到"Maven Setting"
+
+![](image/maven配置.jpg)
+
+然后按照如下内容进行配置
+
+![](image/maven详细配置.jpg)
+
+## Maven 配置
+
+Maven也请使用jdk 1.8,在Idea的Build Tools->Maven->Runner中设置JRE为1.8。
+
+尝试执行右边的Maven Projects窗口中的Lifecycle中的compile命令,看是否编译成功,如失败可以添加`-X`参数,查看错误原因。
+
+如果出现编译错误:Error:java: 无效的目标发行版: 11
+
+请到 Build,Execution,Deployment->Compiler->Java Compiler设置 Per-module btyecode为1.8,默认可能为11。
diff --git a/backend/doc/note.md b/backend/doc/note.md
new file mode 100644
index 0000000..16f74b0
--- /dev/null
+++ b/backend/doc/note.md
@@ -0,0 +1,74 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+# Controller格式
+
+```java
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.xxx;
+
+import org.apache.iotdb.xxx;
+import org.apache.iotdb.rpc.xxx;
+import org.apache.iotdb.service.rpc.xxx;
+
+import org.apache.thrift.xxx;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Map;
+```
+
+排列整齐 不同层级之间用空格分开
+
+## 注释
+
+注释使用英文注释
diff --git a/README.md b/backend/doc/promise.md
similarity index 79%
copy from README.md
copy to backend/doc/promise.md
index 06ee6a0..1f9c2ad 100644
--- a/README.md
+++ b/backend/doc/promise.md
@@ -18,9 +18,12 @@
     under the License.
 
 -->
-[English](./README.md) | [中文](./README_ZH.md)
 
-# Overview
+# 常用实践约定
 
-This code repo is a web based workbench for [Apache IoTDB](https://iotdb.apache.org)
+本章讨论常用默认的IoTDB-Workbench约定
+
+## 理论约定
+
+1. 随着SpringBoot的流行,我们现在更多采用基于注解式的配置从而替换掉了基于XML的配置。
 
diff --git a/README.md b/backend/doc/release.md
similarity index 84%
copy from README.md
copy to backend/doc/release.md
index 06ee6a0..0e4c436 100644
--- a/README.md
+++ b/backend/doc/release.md
@@ -18,9 +18,11 @@
     under the License.
 
 -->
-[English](./README.md) | [中文](./README_ZH.md)
 
-# Overview
+# 发布日志
 
-This code repo is a web based workbench for [Apache IoTDB](https://iotdb.apache.org)
+## 1.0.0
+
+1. xxx
+2. xxx
 
diff --git a/README.md b/backend/doc/rest.md
similarity index 79%
copy from README.md
copy to backend/doc/rest.md
index 06ee6a0..0b25e53 100644
--- a/README.md
+++ b/backend/doc/rest.md
@@ -18,9 +18,14 @@
     under the License.
 
 -->
-[English](./README.md) | [中文](./README_ZH.md)
 
-# Overview
+# 接口规范
 
-This code repo is a web based workbench for [Apache IoTDB](https://iotdb.apache.org)
+有时候,会犯一些错误,例如直接会定义如下的一些接口:
 
+- /user/delete
+- /user/add
+- /user/update
+- /user/select
+
+这样的接口太数据库化,读起来虽然比较容易
diff --git a/README.md b/backend/doc/rule.md
similarity index 51%
copy from README.md
copy to backend/doc/rule.md
index 06ee6a0..31b6225 100644
--- a/README.md
+++ b/backend/doc/rule.md
@@ -18,9 +18,20 @@
     under the License.
 
 -->
-[English](./README.md) | [中文](./README_ZH.md)
 
-# Overview
+# 阿里巴巴java规范checkstyle
 
-This code repo is a web based workbench for [Apache IoTDB](https://iotdb.apache.org)
+我们使用阿里巴巴java规范泰山版(1.6.0)
 
+需使用idea(版本2018.3+)安装插件,自动检查代码规范,具体操作步骤如下:
+
+1、Mac:IntelliJ IDEA -> Preferences -> Plugins -> Installed plugins from Disk -> 选择doc目录下的code-guidelines进行安装
+   Windows:File -> Settings -> Plugins -> Installed plugins from Disk -> 选择doc目录下的code-guidelines进行安装
+
+2、重启idea
+
+##在线安装java规范checkstyle
+1、Mac:IntelliJ IDEA -> Preferences -> Plugins -> Browse repositories -> 搜索Alibaba Java Coding Guidelines -> 直接install进行在线安装
+   Windows:File -> Settings -> Plugins -> Marketplace -> 搜索Alibaba Java Coding Guidelines -> 直接install进行在线安装
+
+2、重启idea
\ No newline at end of file
diff --git a/backend/doc/swagger.md b/backend/doc/swagger.md
new file mode 100644
index 0000000..37e9b0d
--- /dev/null
+++ b/backend/doc/swagger.md
@@ -0,0 +1,51 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+# swagger的使用
+
+swagger在前后端联调开发中,启动非常重要的作用,如下:
+
+1. 保持接口和文档的一致性
+2. 使注释更为丰富
+
+
+
+1、框架依赖中已包含swagger接口组件。
+```xml
+<dependency>
+    <groupId>io.springfox</groupId>
+    <artifactId>springfox-swagger2</artifactId>
+    <version>2.7.0</version>
+</dependency>
+<dependency>
+    <groupId>io.springfox</groupId>
+    <artifactId>springfox-swagger-ui</artifactId>
+    <version>2.7.0</version>
+</dependency>
+```
+
+## 网页地址
+
+你可以通过http://localhost:8080/swagger-ui.html这个地址获得接口信息。
+
+## 生产环境、测试环境、开发环境配置
+
+在生产环境中需要把swagger去掉,请参考配置类Swagger2Config中的@Profile({"dev", "test"})注解。(当前配置表示加载在dev和test文件使用,只在开发环境和测试环境的时候加载该类)
\ No newline at end of file
diff --git a/backend/doc/validate.md b/backend/doc/validate.md
new file mode 100644
index 0000000..ceb0f5b
--- /dev/null
+++ b/backend/doc/validate.md
@@ -0,0 +1,68 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+# 参数验证
+
+参数验证一般有很多种方法:
+
+1. 直接写在controller中,有时候,特别是新人,98%会忘记写参数验证
+2. 切面,注解形式的参数验证
+
+我们认为第2种方式会好于第一种方式,所以我们使用了成熟的hibernat验证框架对参数进行验证
+
+## hibernat参数验证配置
+
+在开发中经常需要写一些字段校验的代码,比如字段非空,字段长度限制,邮箱格式验证等等,写这些与业务逻辑关系不大的代码有几个麻烦:
+
+1. 验证代码繁琐,重复劳动
+2. 方法内代码显得冗长
+3. 每次要看哪些参数验证是否完整,需要去翻阅验证逻辑代码
+hibernate validator(官方文档)提供了一套比较完善、便捷的验证实现方式。
+
+spring-boot-starter-web包里面有hibernate-validator包,不需要引用hibernate validator依赖。
+
+## 校验框架的使用方式
+
+接入步骤:
+
+1、引入依赖
+
+```xml
+<dependency>
+    <groupId>org.hibernate.validator</groupId>
+    <artifactId>hibernate-validator</artifactId>
+    <version>6.0.9.Final</version>
+</dependency>
+```
+
+2、在需要校验的类上的属性上加上相关注解
+
+如DemoUser中name上加@NotNull和@Length注解
+
+3、进行aop配置,创建ParamValidAspect切面配置(可选)。
+
+
+## 注意事项:
+
+>如果不接入ParamValidAspect切面配置,校验框架会自动抛出Spring的参数校验的异常;如果使用了自定义切面配置,
+可以在doAround方法中对相关的参数校验做特殊的处理。本项目中对参数校验进行了统一的特殊处理(切面配置),返回与
+异常主见中的异常保持一致的错误状态码。建议以该项目的方式进行切面配置,从而遵循异常状态码规范。
+
diff --git a/backend/gradlew b/backend/gradlew
new file mode 100755
index 0000000..f4f9798
--- /dev/null
+++ b/backend/gradlew
@@ -0,0 +1,188 @@
+#!/usr/bin/env sh
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=`expr $i + 1`
+    done
+    case $i in
+        0) set -- ;;
+        1) set -- "$args0" ;;
+        2) set -- "$args0" "$args1" ;;
+        3) set -- "$args0" "$args1" "$args2" ;;
+        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/backend/pom.xml b/backend/pom.xml
new file mode 100644
index 0000000..6413aba
--- /dev/null
+++ b/backend/pom.xml
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.springframework.boot</groupId>
+    <artifactId>spring-boot-starter-parent</artifactId>
+    <version>2.3.3.RELEASE</version>
+    <relativePath/> <!-- lookup parent from repository -->
+  </parent>
+  <groupId>org.apache.iotdb.admin</groupId>
+  <artifactId>workbench</artifactId>
+  <version>1.0.0</version>
+  <packaging>jar</packaging>
+  <name>IoTDB Workbench</name>
+  <description>Apache IoTDB Workbench开源项目</description>
+
+  <properties>
+    <!-- 对应java 1.8,如果编译错误,可能需要调整 -->
+    <java.version>1.8</java.version>
+    <skipTests>true</skipTests>
+  </properties>
+
+
+  <dependencies>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.springframework.boot</groupId>
+          <artifactId>spring-boot-starter-logging</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-log4j2</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-security</artifactId>
+    </dependency>
+
+    <!--sqlite驱动-->
+    <dependency>
+      <groupId>org.xerial</groupId>
+      <artifactId>sqlite-jdbc</artifactId>
+      <version>3.34.0</version>
+    </dependency>
+
+    <!--jwt-->
+    <dependency>
+      <groupId>com.auth0</groupId>
+      <artifactId>java-jwt</artifactId>
+      <version>3.4.0</version>
+    </dependency>
+
+    <!-- get set方法自动生成 -->
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <optional>true</optional>
+    </dependency>
+
+    <!-- mybatis-plus -->
+    <dependency>
+      <groupId>com.baomidou</groupId>
+      <artifactId>mybatis-plus-boot-starter</artifactId>
+      <version>3.4.0</version>
+    </dependency>
+    <!-- 数据库结束 -->
+
+    <!-- 常用工具库 -->
+    <dependency>
+      <groupId>com.alibaba</groupId>
+      <artifactId>fastjson</artifactId>
+      <version>1.2.73</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <version>3.11</version>
+    </dependency>
+    <!-- 常用工具库结束 -->
+
+
+    <!-- spring单元测试 -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.junit.vintage</groupId>
+          <artifactId>junit-vintage-engine</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <!-- spring单元测试结束 -->
+
+    <!-- swagger 组件,用于自动生成api接口文档 -->
+    <dependency>
+      <groupId>io.springfox</groupId>
+      <artifactId>springfox-swagger2</artifactId>
+      <version>2.7.0</version>
+    </dependency>
+    <dependency>
+      <groupId>io.springfox</groupId>
+      <artifactId>springfox-swagger-ui</artifactId>
+      <version>2.7.0</version>
+    </dependency>
+    <!-- swagger 组件结束-->
+
+    <!-- 校验框架-->
+    <dependency>
+      <groupId>org.hibernate.validator</groupId>
+      <artifactId>hibernate-validator</artifactId>
+      <version>6.0.9.Final</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.aspectj</groupId>
+      <artifactId>aspectjweaver</artifactId>
+      <version>1.9.6</version>
+    </dependency>
+    <!-- 校验框架结束-->
+
+    <dependency>
+      <groupId>org.apache.iotdb</groupId>
+      <artifactId>iotdb-session</artifactId>
+      <version>0.12.0</version>
+      <exclusions>
+        <exclusion>
+          <artifactId>logback-classic</artifactId>
+          <groupId>ch.qos.logback</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.iotdb</groupId>
+      <artifactId>iotdb-jdbc</artifactId>
+      <version>0.12.0</version>
+      <exclusions>
+        <exclusion>
+          <artifactId>logback-classic</artifactId>
+          <groupId>ch.qos.logback</groupId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+        <version>2.5.3</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>repackage</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <!--https://blog.csdn.net/eguid/article/details/78291497-->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.8.1</version>
+        <configuration>
+          <verbose>true</verbose>
+          <fork>true</fork>
+          <executable>${JAVA_HOME}/bin/javac</executable>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.rat</groupId>
+        <artifactId>apache-rat-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>license-check</id>
+            <phase>verify</phase>
+            <goals>
+              <goal>check</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+    </plugins>
+
+  </build>
+
+  <repositories>
+    <repository>
+      <id>central</id>
+      <name>Central Repository</name>
+      <url>https://repo.maven.apache.org/maven2</url>
+      <releases>
+        <enabled>true</enabled>
+      </releases>
+      <snapshots>
+        <enabled>true</enabled>
+      </snapshots>
+    </repository>
+  </repositories>
+</project>
diff --git a/backend/settings.gradle b/backend/settings.gradle
new file mode 100644
index 0000000..c9e1192
--- /dev/null
+++ b/backend/settings.gradle
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+rootProject.name = 'service'
diff --git a/backend/src/main/java/org/apache/iotdb/admin/AdminApplication.java b/backend/src/main/java/org/apache/iotdb/admin/AdminApplication.java
new file mode 100644
index 0000000..55adaf8
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/AdminApplication.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+
+/**
+ * 后端代码启动类
+ * 1. MapperScan需要配置为mapper所在的包,自动扫描mapper,MapperScan是用于数据库组件自动扫描使用的。
+ */
+@SpringBootApplication
+@MapperScan("org.apache.iotdb.admin.mapper")
+@EnableWebSecurity
+public class AdminApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(AdminApplication.class, args);
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/aop/BaseExceptionAdvice.java b/backend/src/main/java/org/apache/iotdb/admin/aop/BaseExceptionAdvice.java
new file mode 100644
index 0000000..da38b49
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/aop/BaseExceptionAdvice.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.aop;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.model.vo.BaseVO;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * 通用异常处理拦截器
+ */
+@Slf4j
+@ControllerAdvice
+public class BaseExceptionAdvice {
+
+    @ExceptionHandler(BaseException.class)
+    @ResponseBody
+    public BaseVO handleBaseException(BaseException e) {
+        log.error("调用接口异常", e);
+        BaseVO result = new BaseVO(e.getErrorCode(), e.getMessage(), null);
+        return result;
+    }
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/aop/ParamValidAspect.java b/backend/src/main/java/org/apache/iotdb/admin/aop/ParamValidAspect.java
new file mode 100644
index 0000000..5b9cb07
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/aop/ParamValidAspect.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.aop;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Path;
+import javax.validation.Validator;
+import java.util.Set;
+
+/**
+ * 参数验证
+ */
+@Aspect
+@Slf4j
+@Component
+public class ParamValidAspect {
+
+    @Autowired
+    private Validator validator;
+
+
+    /**
+     * 定义校验包的未知
+     */
+    @Pointcut("execution(* org.apache.iotdb.admin.controller..*.*(..))")
+    public void pointcut() {
+    }
+
+    /**
+     * 处理参数校验错误的具体方法,抛出异常组件中的异常,遵循异常规范
+     */
+    @Around("pointcut()")
+    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
+        Object[] args = pjp.getArgs();
+        for (Object arg : args) {
+            if (arg != null) {
+                Set<ConstraintViolation<Object>> constraintViolations = validator.validate(arg);
+                if (constraintViolations.size() > 0) {
+                    for (ConstraintViolation<Object> constraintViolation : constraintViolations) {
+                        Path property = constraintViolation.getPropertyPath();
+                        String name = property.iterator().next().getName();
+                        //打印具体异常信息,对应校验框架注解中的message
+                        log.error("[" + name + "]" + constraintViolation.getMessage());
+                        throw new BaseException(ErrorCode.WRONG_PARAM, "参数错误:" + constraintViolation.getMessage());
+                    }
+                }
+            }
+        }
+        return pjp.proceed();
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/common/exception/BaseException.java b/backend/src/main/java/org/apache/iotdb/admin/common/exception/BaseException.java
new file mode 100644
index 0000000..41eaa70
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/common/exception/BaseException.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.common.exception;
+
+/**
+ * 异常类
+ */
+public class BaseException extends Exception {
+
+    private String errorCode;
+    private String message;
+
+    public BaseException(String errorCode, String message) {
+        this.errorCode = errorCode;
+        this.message = message;
+    }
+
+    public String getErrorCode() {
+        return errorCode;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/common/exception/ErrorCode.java b/backend/src/main/java/org/apache/iotdb/admin/common/exception/ErrorCode.java
new file mode 100644
index 0000000..1fa47da
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/common/exception/ErrorCode.java
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.common.exception;
+
+/**
+ * 错误码类
+ */
+public class ErrorCode {
+
+    // 连接相关
+    public static final String ALIAS_REPEAT = "CONN-0001";
+    public static final String ALIAS_REPEAT_MSG = "别名重复";
+
+    public static final String INSERT_CONN_FAIL = "CONN-0002";
+    public static final String INSERT_CONN_FAIL_MSG = "添加或更新连接失败";
+
+    public static final String DELETE_CONN_FAIL = "CONN-0003";
+    public static final String DELETE_CONN_FAIL_MSG = "删除连接失败";
+
+    public static final String NO_CONN = "CONN-0004";
+    public static final String NO_CONN_MSG = "连接不存在";
+
+    public static final String GET_CONN_FAIL = "CONN-0005";
+    public static final String GET_CONN_FAIL_MSG = "获取连接失败";
+
+    public static final String CHECK_FAIL = "CONN-0006";
+    public static final String CHECK_FAIL_MSG = "没有权限或连接不存在";
+
+    public static final String TEST_CONN_FAIL = "CONN-0007";
+    public static final String TEST_CONN_FAIL_MSG = "连接不可达或连接超时";
+
+    public static final String TEST_CONN_WRONG = "CONN-0008";
+    public static final String TEST_CONN_WRONG_MSG = "连接失败,主机输入不合法";
+
+    public static final String TIME_OUT = "CONN-0009";
+    public static final String TIME_OUT_MSG = "连接超时";
+
+    public static final String TEST_CONN_FAIL_PWD = "CONN-0010";
+    public static final String TEST_CONN_FAIL_PWD_MSG = "连接失败,用户名或密码错误";
+
+    // 登录相关
+    public static final String LOGIN_FAIL_USER = "USER-0001";
+    public static final String LOGIN_FAIL_USER_MSG = "登录失败,用户不存在";
+
+    public static final String USER_EXIST = "USER-0002";
+    public static final String USER_EXIST_MSG = "用户已存在";
+
+    public static final String LOGIN_FAIL_PWD = "USER-0003";
+    public static final String LOGIN_FAIL_PWD_MSG = "登录失败,密码错误";
+
+    public static final String INSERT_USER_FAIL = "USER-0004";
+    public static final String INSERT_USER_FAIL_MSG = "插入失败";
+
+    public static final String WRONG_USER_PARAM = "USER-0005";
+    public static final String WRONG_USER_PARAM_MSG = "请输入合法的用户名和密码";
+
+    public static final String DELETE_USER_FAIL = "USER-0006";
+    public static final String DELETE_USER_FAIL_MSG = "删除用户失败";
+
+    public static final String NO_USER = "USER-0007";
+    public static final String NO_USER_MSG = "用户未指定";
+
+    public static final String USER_AUTH_FAIL = "USER-0008";
+    public static final String USER_AUTH_FAIL_MSG = "用户不一致,不能进行操作";
+
+    public static final String TOKEN_ERR = "USER-0009";
+    public static final String TOKEN_ERR_MSG = "请登录或token失效";
+
+    public static final String GET_TOKEN_FAIL = "USER-0010";
+    public static final String GET_TOKEN_FAIL_MSG = "获取token失败";
+
+    public static final String SET_JWT_FAIL = "USER-0011";
+    public static final String SET_JWT_FAIL_MSG = "JWT编解码失败";
+
+    // iotDB相关
+    public static final String INSERT_TS_FAIL = "IOTDB-0001";
+    public static final String INSERT_TS_FAIL_MSG = "插入时间序列失败";
+
+    public static final String DELETE_TS_FAIL = "IOTDB-0002";
+    public static final String DELETE_TS_FAIL_MSG = "删除时间序列失败";
+
+    public static final String DB_BOOL_WRONG = "IOTDB-0003";
+    public static final String DB_BOOL_WRONG_MSG = "Boolean值输入错误,0为false,1为true";
+
+    public static final String DB_DATATYPE_WRONG = "IOTDB-0004";
+    public static final String DB_DATATYPE_WRONG_MSG = "TSDataType类型传入错误";
+
+    public static final String GET_DBCONN_FAIL = "IOTDB-005";
+    public static final String GET_DBCONN_FAIL_MSG = "获取数据库连接失败";
+
+    public static final String GET_SESSION_FAIL = "IOTDB-0006";
+    public static final String GET_SESSION_FAIL_MSG = "获取session失败";
+
+    public static final String CLOSE_DBCONN_FAIL = "IOTDB-0007";
+    public static final String CLOSE_DBCONN_FAIL_MSG = "关闭连接失败";
+
+    public static final String SQL_EP = "IOTDB-0008";
+    public static final String SQL_EP_MSG = "没有权限或sql异常";
+
+    public static final String QUERY_FAIL = "IOTDB-0009";
+    public static final String QUERY_FAIL_MSG = "sql查询失败";
+
+    public static final String SQL_PARAM_WRONG = "IOTDB-0010";
+    public static final String SQL_PARAM_WRONG_MSG = "sql参数不合法";
+
+    public static final String WRONG_DB_PARAM = "IOTDB-0011";
+    public static final String WRONG_DB_PARAM_MSG = "输入参数不合法";
+
+    public static final String GET_USER_FAIL = "IOTDB-0012";
+    public static final String GET_USER_FAIL_MSG = "获取用户信息失败";
+
+    public static final String GET_SQL_ONE_VALUE_FAIL = "IOTDB-0013";
+    public static final String GET_SQL_ONE_VALUE_FAIL_MSG = "获取值失败";
+
+    public static final String SET_TTL_FAIL = "IOTDB-0014";
+    public static final String SET_TTL_FAIL_MSG = "设置存活时间失败";
+
+    public static final String DEL_TTL_FAIL = "IOTDB-0015";
+    public static final String DEL_TTL_FAIL_MSG = "删除存活时间失败";
+
+    public static final String GET_SQL_ONE_COLUMN_FAIL = "IOTDB-0016";
+    public static final String GET_SQL_ONE_COLUMN_FAIL_MSG = "获取列表失败";
+
+    public static final String GET_SQL_SET_FAIL = "IOTDB-0017";
+    public static final String GET_SQL_SET_FAIL_MSG = "获取列表集合失败";
+
+    public static final String INSERT_DEV_FAIL = "IOTDB-0018";
+    public static final String INSERT_DEV_FAIL_MSG = "插入实体失败";
+
+    public static final String GET_MSM_FAIL = "IOTDB-0019";
+    public static final String GET_MSM_FAIL_MSG = "获取物理量数据信息失败";
+
+    public static final String NO_SUCH_FIELD = "IOTDB-0020";
+    public static final String NO_SUCH_FIELD_MSG = "返回集没此属性";
+
+    public static final String GET_LAST_VALUE_FAIL = "IOTDB-0021";
+    public static final String GET_LAST_VALUE_FAIL_MSG = "获取物理量最新值失败";
+
+    public static final String SET_GROUP_FAIL = "IOTDB-0022";
+    public static final String SET_GROUP_FAIL_MSG = "创建存储组失败";
+
+    public static final String DELETE_GROUP_FAIL = "IOTDB-0023";
+    public static final String DELETE_GROUP_FAIL_MSG = "删除存储组失败";
+
+    public static final String DELETE_DB_USER_FAIL = "IOTDB-0024";
+    public static final String DELETE_DB_USER_FAIL_MSG = "删除数据库用户失败";
+
+    public static final String DELETE_DB_ROLE_FAIL = "IOTDB-0025";
+    public static final String DELETE_DB_ROLE_FAIL_MSG = "删除数据库角色失败";
+
+    public static final String SET_DB_USER_FAIL = "IOTDB-0026";
+    public static final String SET_DB_USER_FAIL_MSG = "创建数据库用户失败";
+
+    public static final String SET_DB_ROLE_FAIL = "IOTDB-0027";
+    public static final String SET_DB_ROLE_FAIL_MSG = "创建数据库角色或对应权限时失败";
+
+    public static final String NO_TYPE = "IOTDB-0028";
+    public static final String NO_TYPE_MSG = "粒度类型不存在";
+
+    public static final String PRIV_ROOT_FAIL = "IOTDB-0029";
+    public static final String PRIV_ROOT_FAIL_MSG = "根路径权限操作失败";
+
+    public static final String PRIV_GROUP_FAIL = "IOTDB-0030";
+    public static final String PRIV_GROUP_FAIL_MSG = "组路径权限操作失败";
+
+    public static final String PRIV_DEVICE_FAIL = "IOTDB-0031";
+    public static final String PRIV_DEVICE_FAIL_MSG = "实体路径权限操作失败";
+
+    public static final String PRIV_TIMESERIES_FAIL = "IOTDB-0032";
+    public static final String PRIV_TIMESERIES_FAIL_MSG = "物理量路径权限操作失败";
+
+    public static final String GET_RECORD_FAIL = "IOTDB-0033";
+    public static final String GET_RECORD_FAIL_MSG = "获取物理量记录失败";
+
+    public static final String NO_SQL = "IOTDB-0034";
+    public static final String NO_SQL_MSG = "没有sql执行语句";
+
+    public static final String UPDATE_GROUP_INFO_FAIL = "IOTDB-0035";
+    public static final String UPDATE_GROUP_INFO_FAIL_MSG = "更新组信息失败";
+
+    public static final String NO_GROUP_INFO = "IOTDB-0036";
+    public static final String NO_GROUP_INFO_MSG = "不存在存储组信息";
+
+    public static final String NO_GROUP = "IOTDB-0037";
+    public static final String NO_GROUP_MSG = "不存在存储组";
+
+    public static final String NO_DEVICE_INFO = "IOTDB-0038";
+    public static final String NO_DEVICE_INFO_MSG = "不存在设备信息";
+
+    public static final String UPDATE_PWD_FAIL = "IOTDB-0039";
+    public static final String UPDATE_PWD_FAIL_MSG = "修改账号密码失败";
+
+    public static final String NO_QUERY = "IOTDB-0040";
+    public static final String NO_QUERY_MSG = "不存在此查询";
+
+    public static final String NO_ALL_NUM_SEARCH = "IOTDB-0041";
+    public static final String NO_ALL_NUM_SEARCH_MSG = "不支持纯数字查询";
+
+    public static final String NO_PRI_SET_TTL = "IOTDB-0042";
+    public static final String NO_PRI_SET_TTL_MSG = "没有权限设置存活时间";
+
+    public static final String NO_PRI_CREATE_TIMESERIES = "IOTDB-0043";
+    public static final String NO_PRI_CREATE_TIMESERIES_MSG = "没有权限创建物理量";
+
+    public static final String NO_PRI_READ_TIMESERIES = "IOTDB-0044";
+    public static final String NO_PRI_READ_TIMESERIES_MSG = "没有权限查看物理量";
+
+    public static final String NO_PRI_DELETE_TIMESERIES = "IOTDB-0045";
+    public static final String NO_PRI_DELETE_TIMESERIES_MSG = "没有权限删除物理量";
+
+    public static final String CONN_REFUSED = "IOTDB-0046";
+    public static final String CONN_REFUSED_MSG = "连接错误,检查输入";
+
+    public static final String WRONG_USER = "IOTDB-0047";
+    public static final String WRONG_USER_MSG = "连接用户名或密码错误";
+
+    public static final String NO_PRI_SET_GROUP = "IOTDB-0048";
+    public static final String NO_PRI_SET_GROUP_MSG = "没有权限操作存储组";
+
+    public static final String NO_PRI_DELETE_GROUP = "IOTDB-0048";
+    public static final String NO_PRI_DELETE_GROUP_MSG = "没有权限删除存储组";
+
+    public static final String NO_SUPPORT_SQL = "IOTDB-0049";
+    public static final String NO_SUPPORT_SQL_MSG = "不支持此sql执行";
+
+    public static final String TTL_WRONG = "IOTDB-0050";
+    public static final String TTL_WRONG_MSG = "存活时间必须大于等于0";
+
+    public static final String NO_PRI_TIMESERIES_DATA = "IOTDB-0051";
+    public static final String NO_PRI_TIMESERIES_DATA_MSG = "没有权限查看测点数据";
+
+    public static final String NO_SUP_CONTAIN_ROOT = "IOTDB-0052";
+    public static final String NO_SUP_CONTAIN_ROOT_MSG = "不支持包含\"root\"的输入";
+
+    // 存储组表相关
+    public static final String INSERT_GROUP_INFO_FAIL = "GROUP-0001";
+    public static final String INSERT_GROUP_INFO_FAIL_MSG = "插入存储组信息失败";
+
+    public static final String DELETE_GROUP_INFO_FAIL = "GROUP-0002";
+    public static final String DELETE_GROUP_INFO_FAIL_MSG = "删除存储组信息失败";
+
+    // 实体表相关
+    public static final String DELETE_DEVICE_INFO_FAIL = "DEV-0001";
+    public static final String DELETE_DEVICE_INFO_FAIL_MSG = "删除实体信息失败";
+
+    public static final String SET_DEVICE_INFO_FAIL = "DEV-0002";
+    public static final String SET_DEVICE_INFO_FAIL_MSG = "插入实体信息失败";
+
+    // 物理量表相关
+    public static final String DELETE_MEASUREMENT_INFO_FAIL = "MEASU-0001";
+    public static final String DELETE_MEASUREMENT_INFO_FAIL_MSG = "删除物理量信息失败";
+
+    public static final String SET_MEASUREMENT_INFO_FAIL = "MEASU-0002";
+    public static final String SET_MEASUREMENT_INFO_FAIL_MSG = "插入物理量信息失败";
+
+    public static final String GET_MSM_DES_FAIL = "MEASU-0003";
+    public static final String GET_MSM_DES_FAIL_MSG = "获取物理量描述信息失败";
+
+    // 查询表相关
+    public static final String QUERY_EXIST = "QUERY-0001";
+    public static final String QUERY_EXIST_MSG = "脚本名已存在";
+
+    public static final String QUERY_NOT_EXIST = "QUERY-0002";
+    public static final String QUERY_NOT_EXIST_MSG = "脚本不存在";
+
+
+    // 参数校验相关
+    public static final String WRONG_PARAM = "PARAM-0001";
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/common/utils/AuthenticationUtils.java b/backend/src/main/java/org/apache/iotdb/admin/common/utils/AuthenticationUtils.java
new file mode 100644
index 0000000..efe1f84
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/common/utils/AuthenticationUtils.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.common.utils;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 校验工具类
+ */
+public class AuthenticationUtils {
+
+    public static void userAuthentication(Integer userId, HttpServletRequest request) throws BaseException {
+        if (userId == null) {
+            throw new BaseException(ErrorCode.NO_USER, ErrorCode.NO_USER_MSG);
+        }
+        DecodedJWT authorization = JWT.decode(request.getHeader("Authorization"));
+        Integer tokenUserId = authorization.getClaim("userId").asInt();
+        if (!tokenUserId.equals(userId)) {
+            throw new BaseException(ErrorCode.USER_AUTH_FAIL, ErrorCode.USER_AUTH_FAIL_MSG);
+        }
+    }
+
+    public static Integer getUserId(HttpServletRequest request) {
+        DecodedJWT authentication = JWT.decode(request.getHeader("Authorization"));
+        return authentication.getClaim("userId").asInt();
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/config/FilterConfig.java b/backend/src/main/java/org/apache/iotdb/admin/config/FilterConfig.java
new file mode 100644
index 0000000..50dafeb
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/config/FilterConfig.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.config;
+
+import org.apache.iotdb.admin.filter.TokenFilter;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 拦截器配置类
+ */
+@Component
+public class FilterConfig implements WebMvcConfigurer {
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        InterceptorRegistration interceptorRegistration = registry.addInterceptor(new TokenFilter());
+        List<String> paths = new ArrayList();
+        paths.add("/servers/**");
+        paths.add("/get");
+        interceptorRegistration.addPathPatterns(paths);
+    }
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/config/MybatisPlusConfig.java b/backend/src/main/java/org/apache/iotdb/admin/config/MybatisPlusConfig.java
new file mode 100644
index 0000000..becedc1
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/config/MybatisPlusConfig.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 该类是Mybatis-Plus的配置类,mybatis以插件的形式来实现特定功能
+ */
+@Configuration
+public class MybatisPlusConfig {
+
+    /**
+     * 分页插件配置,对相关数据库进行拦截并分页
+     *
+     * @return 分页拦截器
+     */
+    @Bean
+    public MybatisPlusInterceptor paginationInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        // 使用不同的数据库,可以更改DbType.MYSQL的类型
+        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
+        // 每页最多100条,可以更改,但不建议太大
+        paginationInnerInterceptor.setMaxLimit(100L);
+        interceptor.addInnerInterceptor(paginationInnerInterceptor);
+        return interceptor;
+    }
+
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/config/SecurityConfig.java b/backend/src/main/java/org/apache/iotdb/admin/config/SecurityConfig.java
new file mode 100644
index 0000000..bf93858
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/config/SecurityConfig.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+
+/**
+ * 加密算法配置类 hash算法
+ */
+@Configuration
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        http.authorizeRequests()
+            .antMatchers("/**")
+            .permitAll()
+            .anyRequest()
+            .authenticated()
+            .and().csrf().disable();
+    }
+
+    @Bean
+    public BCryptPasswordEncoder bCryptPasswordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/config/SwaggerConfig.java b/backend/src/main/java/org/apache/iotdb/admin/config/SwaggerConfig.java
new file mode 100644
index 0000000..45a0374
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/config/SwaggerConfig.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.ParameterBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.schema.ModelRef;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Parameter;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * swagger配置类
+ */
+@Configuration
+@EnableSwagger2
+@Profile({"dev", "test"})
+public class SwaggerConfig {
+
+    @Bean
+    public Docket createRestApi() {
+        return new Docket(DocumentationType.SWAGGER_2)
+            .apiInfo(apiinfo())
+            .enable(true)
+            .globalOperationParameters(jwtToken())
+            .select()
+            .apis(RequestHandlerSelectors.basePackage("org.apache.iotdb.admin.controller"))
+            .paths(PathSelectors.any())
+            .build();
+    }
+
+    private ApiInfo apiinfo() {
+        return new ApiInfoBuilder()
+            .title("IOTDB接口文档")
+            .description("iotDB层级关系 存储组 -> 实体(设备) -> 测点(时间序列)")
+            .build();
+    }
+
+    private List<Parameter> jwtToken() {
+
+        ParameterBuilder tokenPar = new ParameterBuilder();
+        List<Parameter> pars = new ArrayList<>();
+        tokenPar.name("Authorization")
+            .description("jwt令牌")
+            .modelRef(new ModelRef("string"))
+            .parameterType("header")
+            .required(false);
+        pars.add(tokenPar.build());
+        return pars;
+    }
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/config/ValidatorConfiguration.java b/backend/src/main/java/org/apache/iotdb/admin/config/ValidatorConfiguration.java
new file mode 100644
index 0000000..ff63d55
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/config/ValidatorConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.config;
+
+import org.hibernate.validator.HibernateValidator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+
+/**
+ * 校验框架配置类
+ */
+@Configuration
+public class ValidatorConfiguration {
+
+    @Bean("validator")
+    public Validator getValidatorFactory() {
+        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory();
+        return validatorFactory.getValidator();
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/controller/ConnectionController.java b/backend/src/main/java/org/apache/iotdb/admin/controller/ConnectionController.java
new file mode 100644
index 0000000..71dbdd3
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/controller/ConnectionController.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.apache.iotdb.admin.common.utils.AuthenticationUtils;
+import org.apache.iotdb.admin.model.dto.ConnectionDTO;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.apache.iotdb.admin.model.vo.BaseVO;
+import org.apache.iotdb.admin.model.vo.ConnVO;
+import org.apache.iotdb.admin.model.vo.ConnectionVO;
+import org.apache.iotdb.admin.service.ConnectionService;
+import org.apache.iotdb.session.Session;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.List;
+
+@RestController
+@Api(value = "连接相关接口")
+public class ConnectionController {
+
+    @Autowired
+    private ConnectionService connectionService;
+
+    @PostMapping("/servers")
+    @ApiOperation("保存或更新连接")
+    public BaseVO saveOrUpdateConnection(@RequestBody Connection connection, HttpServletRequest request) throws BaseException {
+        AuthenticationUtils.userAuthentication(connection.getUserId(), request);
+        if (connection.getId() != null) {
+            connectionService.update(connection);
+            return BaseVO.success("更新成功", null);
+        }
+        connectionService.insert(connection);
+
+        return BaseVO.success("保存成功", null);
+    }
+
+    @DeleteMapping("/servers/{serverId}")
+    @ApiOperation("删除连接")
+    public BaseVO deleteConnection(@PathVariable("serverId") Integer serverId, HttpServletRequest request) throws BaseException {
+        Integer userId = AuthenticationUtils.getUserId(request);
+        connectionService.check(serverId, userId);
+        connectionService.deleteById(serverId, userId);
+        return BaseVO.success("删除成功", null);
+    }
+
+    @GetMapping("/servers/{serverId}")
+    @ApiOperation("获取连接具体配置")
+    public BaseVO<Connection> getConnection(@PathVariable("serverId") Integer serverId, HttpServletRequest request) throws BaseException {
+        Integer userId = AuthenticationUtils.getUserId(request);
+        connectionService.check(serverId, userId);
+        return BaseVO.success("获取成功", connectionService.getById(serverId));
+    }
+
+    @GetMapping("/servers")
+    @ApiOperation("获取所有连接")
+    public BaseVO<ConnectionVO> getAllConnections(@RequestParam("userId") Integer userId, HttpServletRequest request) throws BaseException {
+        AuthenticationUtils.userAuthentication(userId, request);
+        List<ConnVO> connVOs = connectionService.getAllConnections(userId);
+        ConnectionVO connectionVO = new ConnectionVO(connVOs, userId, null);
+        return BaseVO.success("获取成功", connectionVO);
+    }
+
+    @PostMapping("/test")
+    @ApiOperation("连通性测试")
+    public BaseVO testConnection(@RequestBody ConnectionDTO conn) throws BaseException {
+        Socket socket = null;
+        try {
+            socket = new Socket();
+            socket.connect(new InetSocketAddress(conn.getHost(), conn.getPort()), 5000);
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.TEST_CONN_FAIL, ErrorCode.TEST_CONN_FAIL_MSG);
+        } finally {
+            try {
+                if (socket != null) {
+                    socket.close();
+                }
+            } catch (Exception e) {
+                throw new BaseException(ErrorCode.TEST_CONN_FAIL, ErrorCode.TEST_CONN_FAIL_MSG);
+            }
+        }
+        Session session = null;
+        try {
+            session = new Session(conn.getHost(), conn.getPort(), conn.getUsername(), conn.getPassword());
+            session.open();
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.TEST_CONN_FAIL_PWD, ErrorCode.TEST_CONN_FAIL_PWD_MSG);
+        } finally {
+            try {
+                if (session != null) {
+                    session.close();
+                }
+            } catch (Exception e) {
+                throw new BaseException(ErrorCode.TEST_CONN_FAIL_PWD, ErrorCode.TEST_CONN_FAIL_PWD_MSG);
+            }
+        }
+        return BaseVO.success("连通成功", null);
+    }
+
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/controller/HealthController.java b/backend/src/main/java/org/apache/iotdb/admin/controller/HealthController.java
new file mode 100644
index 0000000..62efb35
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/controller/HealthController.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.controller;
+
+import java.io.IOException;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+/**
+ * 运维平台通过存活、就绪探针表示应用是否存活,就绪。这个类大家最好不好删除,url地址也不要改变
+ */
+@Controller
+public class HealthController {
+
+    /**
+     * 存活探针,运维平台会每格一段时间,请求一下这个接口,如果这个接口返回200,那么表示存活,
+     * 如果多次返回500,则表示这个程序已经死了,会重启这个程序。
+     */
+    @GetMapping(value = "/healthz/liveness")
+    public void liveness(HttpServletResponse response) throws IOException, BaseException {
+        response.setStatus(HttpServletResponse.SC_OK);
+    }
+
+    /**
+     * 就绪探针,运维平台会每格一段时间,请求一下这个接口,如果这个接口返回200,那么表示程序已经可用,
+     * 如果多次返回500,则表示这个程序未启动成功,会重启这个程序。
+     */
+    @GetMapping(value = "/healthz/readiness")
+    public void readiness(HttpServletResponse response) throws IOException {
+        response.setStatus(HttpServletResponse.SC_OK);
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/controller/IotDBController.java b/backend/src/main/java/org/apache/iotdb/admin/controller/IotDBController.java
new file mode 100644
index 0000000..8153022
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/controller/IotDBController.java
@@ -0,0 +1,867 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.apache.iotdb.admin.common.utils.AuthenticationUtils;
+import org.apache.iotdb.admin.model.dto.*;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.apache.iotdb.admin.model.entity.Device;
+import org.apache.iotdb.admin.model.entity.StorageGroup;
+import org.apache.iotdb.admin.model.vo.*;
+import org.apache.iotdb.admin.service.*;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@RestController
+@Api(value = "iotdb操作相关接口")
+@RequestMapping("/servers/{serverId}")
+public class IotDBController {
+
+    @Autowired
+    private ConnectionService connectionService;
+
+    @Autowired
+    private IotDBService iotDBService;
+
+    @Autowired
+    private GroupService groupService;
+
+    @Autowired
+    private DeviceService deviceService;
+
+    @Autowired
+    private MeasurementService measurementService;
+
+
+    @GetMapping("/storageGroups/info")
+    @ApiOperation("获得存储组信息列表")
+    public BaseVO<List<GroupInfoVO>> getAllStorageGroupsInfo(@PathVariable("serverId") Integer serverId, HttpServletRequest request) throws BaseException {
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        List<String> groupNames = iotDBService.getAllStorageGroups(connection);
+        List<GroupInfoVO> groupInfoList = new ArrayList<>();
+        if (groupNames == null || groupNames.size() == 0) {
+            return BaseVO.success("获取成功", groupInfoList);
+        }
+        String host = connection.getHost();
+        List<Integer> deviceCounts = iotDBService.getDevicesCount(connection, groupNames);
+        List<String> descriptions = groupService.getGroupDescription(host, groupNames);
+        for (int i = 0; i < groupNames.size(); i++) {
+            GroupInfoVO groupInfoVO = new GroupInfoVO();
+            groupInfoVO.setGroupName(groupNames.get(i).replaceFirst("root.", ""));
+            groupInfoVO.setDeviceCount(deviceCounts.get(i));
+            groupInfoVO.setDescription(descriptions.get(i));
+            groupInfoList.add(groupInfoVO);
+        }
+        return BaseVO.success("获取成功", groupInfoList);
+    }
+
+    @GetMapping("/storageGroups")
+    @ApiOperation("获得存储组列表")
+    public BaseVO<List<StorageGroupVO>> getAllStorageGroups(@PathVariable("serverId") Integer serverId, HttpServletRequest request) throws BaseException {
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        List<StorageGroupVO> storageGroupVOList = new ArrayList<>();
+        List<String> groupNames = iotDBService.getAllStorageGroups(connection);
+        if (groupNames == null || groupNames.size() == 0) {
+            return BaseVO.success("获取成功", storageGroupVOList);
+        }
+        String host = connection.getHost();
+        for (String groupName : groupNames) {
+            StorageGroupVO storageGroupVO = new StorageGroupVO();
+            Integer id = groupService.getGroupId(host, groupName);
+            storageGroupVO.setGroupId(id);
+            groupName = groupName.replaceFirst("root.", "");
+            storageGroupVO.setGroupName(groupName);
+            storageGroupVOList.add(storageGroupVO);
+        }
+        return BaseVO.success("获取成功", storageGroupVOList);
+    }
+
+    @PostMapping("/storageGroups")
+    @ApiOperation("新增或修改存储组")
+    public BaseVO saveStorageGroup(@PathVariable("serverId") Integer serverId,
+        @RequestBody GroupDTO groupDTO,
+        HttpServletRequest request) throws BaseException {
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        String groupName = groupDTO.getGroupName();
+        String checkName = groupName.toLowerCase();
+        if (checkName.contains("root")) {
+            throw new BaseException(ErrorCode.NO_SUP_CONTAIN_ROOT, ErrorCode.NO_SUP_CONTAIN_ROOT_MSG);
+        }
+        groupName = "root." + groupName;
+        Long ttl = groupDTO.getTtl();
+        String ttlUnit = groupDTO.getTtlUnit();
+        Integer groupId = groupDTO.getGroupId();
+        groupDTO.setGroupName(groupName);
+
+        List<String> groupNames = iotDBService.getAllStorageGroups(connection);
+        if (groupId == null) {
+            if (!groupNames.contains(groupDTO.getGroupName())) {
+                iotDBService.saveStorageGroup(connection, groupName);
+            }
+            groupService.setStorageGroupInfo(connection, groupDTO);
+        } else {
+            groupService.updateStorageGroupInfo(connection, groupDTO);
+        }
+        if (ttl != null && ttlUnit != null) {
+            if (ttl >= 0) {
+                Long times = switchTime(ttlUnit);
+                iotDBService.saveGroupTtl(connection, groupName, ttl * times);
+            } else {
+                throw new BaseException(ErrorCode.TTL_WRONG, ErrorCode.TTL_WRONG_MSG);
+            }
+        } else {
+            if (ttl == null && ttlUnit == null) {
+                iotDBService.cancelGroupTtl(connection, groupName);
+            } else {
+                throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+            }
+        }
+        return BaseVO.success("新增或更新成功", null);
+    }
+
+    @DeleteMapping("/storageGroups/{groupName}")
+    @ApiOperation("删除存储组")
+    public BaseVO deleteStorageGroup(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        HttpServletRequest request) throws BaseException {
+        if (groupName == null || !groupName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        String host = connection.getHost();
+        iotDBService.deleteStorageGroup(connection, groupName);
+        groupService.deleteGroupInfo(host, groupName);
+        deviceService.deleteDeviceInfo(host, groupName);
+        measurementService.deleteMeasurementInfo(host, groupName);
+        return BaseVO.success("删除成功", null);
+    }
+
+    @GetMapping("/storageGroups/{groupName}")
+    @ApiOperation("存储组详情获取")
+    public BaseVO<GroupVO> getStorageGroup(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        HttpServletRequest request) throws BaseException {
+        if (groupName == null || !groupName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        String host = connection.getHost();
+        StorageGroup group = groupService.getGroupInfo(host, groupName);
+        String ttl = iotDBService.getGroupTTL(connection, groupName);
+        String ttlUnit;
+        GroupVO groupVO = new GroupVO();
+        if (ttl != null && !"null".equalsIgnoreCase(ttl)) {
+            Long totalTime = Long.valueOf(ttl);
+            ttlUnit = getTTL(totalTime);
+            Long times = switchTime(ttlUnit);
+            ttl = String.valueOf(totalTime / times);
+            groupVO.setTtl(ttl);
+            groupVO.setTtiUnit(ttlUnit);
+        } else {
+            groupVO.setTtl(null);
+        }
+        if (group != null) {
+            groupVO.setCreator(group.getCreator());
+            groupVO.setDescription(group.getDescription());
+            Date date = new Date(group.getCreateTime());
+            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+            String createTime = simpleDateFormat.format(date);
+            groupVO.setCreateTime(createTime);
+        }
+        groupVO.setGroupName(groupName.replaceFirst("root.", ""));
+        groupVO.setAlias(connection.getAlias());
+        return BaseVO.success("获取成功", groupVO);
+    }
+
+    @GetMapping("/storageGroups/{groupName}/devices/info")
+    @ApiOperation("获取指定存储组下的实体(设备)信息列表")
+    public BaseVO<DeviceInfoVO> getDevicesInfoByGroupName(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        @RequestParam("pageSize") Integer pageSize,
+        @RequestParam("pageNum") Integer pageNum,
+        @RequestParam(value = "keyword", required = false) String keyword,
+        HttpServletRequest request) throws BaseException {
+        if (groupName == null || !groupName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        if (pageSize == null || pageNum == null) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        CountDTO countDTO = iotDBService.getDevicesByGroup(connection, groupName, pageSize, pageNum, keyword);
+        List<String> deviceNames = countDTO.getObjects();
+        DeviceInfoVO deviceInfoVO = new DeviceInfoVO();
+        Integer totalPage = countDTO.getTotalPage();
+        Integer totalCount = countDTO.getTotalCount();
+        deviceInfoVO.setTotalCount(totalCount);
+        deviceInfoVO.setTotalPage(totalPage);
+        List<Integer> lines = iotDBService.getTimeseriesCount(connection, deviceNames);
+        List<Device> devices = deviceService.getDevices(connection.getHost(), deviceNames);
+        List<DeviceInfo> deviceInfos = new ArrayList<>();
+        if (deviceNames != null) {
+            for (int i = 0; i < deviceNames.size(); i++) {
+                String deviceName = deviceNames.get(i);
+                if (groupName.equals(deviceName)) {
+                    continue;
+                }
+                DeviceInfo deviceInfo = new DeviceInfo();
+                deviceInfo.setDeviceName(deviceName.replaceFirst(groupName + ".", ""));
+                deviceInfo.setLine(lines.get(i));
+                if (devices.get(i) != null) {
+                    deviceInfo.setDeviceId(devices.get(i).getId());
+                    deviceInfo.setCreator(devices.get(i).getCreator());
+                    deviceInfo.setDescription(devices.get(i).getDescription());
+                }
+                deviceInfos.add(deviceInfo);
+            }
+        }
+        deviceInfoVO.setDeviceInfos(deviceInfos);
+        return BaseVO.success("获取成功", deviceInfoVO);
+    }
+
+    @GetMapping("/storageGroups/{groupName}/devices")
+    @ApiOperation("获取指定存储组下的实体(设备)列表")
+    public BaseVO<List<String>> getDevicesByGroupName(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        HttpServletRequest request) throws BaseException {
+        if (groupName == null || !groupName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        List<String> deviceNamesStr = iotDBService.getDevices(connection, groupName);
+        List<String> deviceNames = new ArrayList<>();
+        for (String s : deviceNamesStr) {
+            String deviceName;
+            if (groupName.equals(s)) {
+                continue;
+            } else {
+                deviceName = s.replaceFirst(groupName + ".", "");
+            }
+            deviceNames.add(deviceName);
+        }
+        return BaseVO.success("获取成功", deviceNames);
+    }
+
+    @PostMapping("/storageGroups/{groupName}/devices")
+    @ApiOperation("新增或编辑实体(设备)")
+    public BaseVO<List<String>> saveOrUpdateDevice(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        @RequestBody DeviceInfoDTO deviceInfoDTO,
+        HttpServletRequest request) throws BaseException {
+        if (groupName == null || !groupName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        if (deviceInfoDTO.getDeviceDTOList() == null || deviceInfoDTO.getDeviceDTOList().size() == 0) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        deviceInfoDTO.setDeviceName(groupName + "." + deviceInfoDTO.getDeviceName());
+        for (DeviceDTO deviceDTO : deviceInfoDTO.getDeviceDTOList()) {
+            deviceDTO.setTimeseries(deviceInfoDTO.getDeviceName() + "." + deviceDTO.getTimeseries());
+        }
+        String host = connection.getHost();
+        iotDBService.createDeviceWithMeasurements(connection, deviceInfoDTO);
+        if (deviceInfoDTO.getDeviceId() == null) {
+            deviceService.setDeviceInfo(connection, deviceInfoDTO);
+            measurementService.setMeasurementsInfo(host, deviceInfoDTO);
+        } else {
+            deviceService.updateDeviceInfo(deviceInfoDTO);
+            measurementService.updateMeasurementsInfo(host, deviceInfoDTO);
+        }
+        return BaseVO.success("新增或更新成功", null);
+    }
+
+
+    @DeleteMapping("/storageGroups/{groupName}/devices/{deviceName}")
+    @ApiOperation("删除实体(设备)")
+    public BaseVO deleteDevice(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        @PathVariable("deviceName") String deviceName,
+        HttpServletRequest request) throws BaseException {
+        if (groupName == null || !groupName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        if (deviceName == null || !deviceName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        deviceName = groupName + "." + deviceName;
+        String host = connection.getHost();
+        iotDBService.deleteTimeseriesByDevice(connection, deviceName);
+        deviceService.deleteDeviceInfoByDeviceName(host, deviceName);
+        measurementService.deleteMeasurementInfoByDeviceName(host, deviceName);
+        return BaseVO.success("删除成功", null);
+    }
+
+    @GetMapping("/storageGroups/{groupName}/devices/{deviceName}")
+    @ApiOperation("获取实体(设备)详情")
+    public BaseVO<DeviceVO> getDeviceInfo(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        @PathVariable("deviceName") String deviceName,
+        HttpServletRequest request) throws BaseException {
+        if (deviceName == null || !deviceName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        deviceName = groupName + "." + deviceName;
+        String host = connection.getHost();
+        DeviceVO deviceVO = deviceService.getDevice(host, deviceName);
+        return BaseVO.success("获取成功", deviceVO);
+    }
+
+    @GetMapping("/storageGroups/{groupName}/devices/{deviceName}/info")
+    @ApiOperation("获取指定实体(设备)下的物理量列表详情")
+    public BaseVO<MeasuremtnInfoVO> getMeasurementsByDeviceName(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        @PathVariable("deviceName") String deviceName,
+        @RequestParam("pageSize") Integer pageSize,
+        @RequestParam("pageNum") Integer pageNum,
+        @RequestParam(value = "keyword", required = false) String keyword,
+        HttpServletRequest request) throws BaseException {
+        if (groupName == null || !groupName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        if (deviceName == null || !deviceName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        deviceName = groupName + "." + deviceName;
+        CountDTO countDTO = iotDBService.getMeasurementsByDevice(connection, deviceName, pageSize, pageNum, keyword);
+        List<MeasurementDTO> measurementDTOList = countDTO.getObjects();
+        List<MeasurementVO> measurementVOList = new ArrayList<>();
+        String host = connection.getHost();
+        if (measurementDTOList != null) {
+            for (MeasurementDTO measurementDTO : measurementDTOList) {
+                MeasurementVO measurementVO = new MeasurementVO();
+                BeanUtils.copyProperties(measurementDTO, measurementVO);
+                if (measurementVO.getTimeseries() != null) {
+                    measurementVO.setTimeseries(measurementVO.getTimeseries().replaceFirst(deviceName + ".", ""));
+                }
+                String description = measurementService.getDescription(host, measurementDTO.getTimeseries());
+                String newValue = iotDBService.getLastMeasurementValue(connection, measurementDTO.getTimeseries());
+                measurementVO.setNewValue(newValue);
+                measurementVO.setDescription(description);
+                measurementVOList.add(measurementVO);
+            }
+        }
+        MeasuremtnInfoVO measuremtnInfoVO = new MeasuremtnInfoVO();
+        measuremtnInfoVO.setTotalCount(countDTO.getTotalCount());
+        measuremtnInfoVO.setTotalPage(countDTO.getTotalPage());
+        measuremtnInfoVO.setMeasurementVOList(measurementVOList);
+        return BaseVO.success("获取成功", measuremtnInfoVO);
+    }
+
+    @GetMapping("/storageGroups/{groupName}/devices/{deviceName}/timeseries/{timeseriesName}")
+    @ApiOperation("获取指定物理量的最新两百条数据记录")
+    public BaseVO<RecordVO> getMeasurementInfo(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        @PathVariable("deviceName") String deviceName,
+        @PathVariable("timeseriesName") String timeseriesName,
+        HttpServletRequest request) throws BaseException {
+        if (groupName == null || !groupName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        if (deviceName == null || !deviceName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        deviceName = groupName + "." + deviceName;
+        RecordVO recordVO = iotDBService.getRecords(connection, deviceName, timeseriesName);
+        return BaseVO.success("获取成功", recordVO);
+    }
+
+    @PostMapping("/storageGroups/{groupName}/devices/{deviceName}/timeseries")
+    @ApiOperation("创建时间序列  (未使用)")
+    public BaseVO insertTimeseries(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        @PathVariable("deviceName") String deviceName,
+        @RequestBody Timeseries timeseries,
+        HttpServletRequest request) throws BaseException {
+        if (deviceName == null || !deviceName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        deviceName = groupName + "." + deviceName;
+        iotDBService.insertTimeseries(connection, deviceName, timeseries);
+        return BaseVO.success("创建成功", null);
+    }
+
+    @GetMapping("/storageGroups/{groupName}/devices/{deviceName}/timeseries/info")
+    @ApiOperation("指定设备下的所有物理量  (未使用)")
+    public BaseVO<SqlResultVO> showTimeseries(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        @PathVariable("deviceName") String deviceName,
+        HttpServletRequest request) throws BaseException {
+        if (deviceName == null || !deviceName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        deviceName = groupName + "." + deviceName;
+        SqlResultVO resultVO = iotDBService.showTimeseries(connection, deviceName);
+        return BaseVO.success("获取成功", resultVO);
+    }
+
+    @GetMapping("/storageGroups/{groupName}/devices/{deviceName}/timeseries")
+    @ApiOperation("指定设备下的物理量列表")
+    public BaseVO<List<String>> getTimeseries(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        @PathVariable("deviceName") String deviceName,
+        HttpServletRequest request) throws BaseException {
+        if (deviceName == null || !deviceName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        deviceName = groupName + "." + deviceName;
+        List<String> timeseriesStr = iotDBService.getTimeseries(connection, deviceName);
+        List<String> timeseries = new ArrayList<>();
+        for (String s : timeseriesStr) {
+            timeseries.add(s.replaceFirst(deviceName + ".", ""));
+        }
+        return BaseVO.success("获取成功", timeseries);
+    }
+
+    @DeleteMapping("/storageGroups/{groupName}/devices/{deviceName}/timeseries/{timeseriesName}")
+    @ApiOperation("删除物理量")
+    public BaseVO deleteTimeseries(@PathVariable("serverId") Integer serverId,
+        @PathVariable("groupName") String groupName,
+        @PathVariable("deviceName") String deviceName,
+        @PathVariable("timeseriesName") String timeseriesName,
+        HttpServletRequest request) throws BaseException {
+        if (timeseriesName == null || !timeseriesName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        groupName = "root." + groupName;
+        deviceName = groupName + "." + deviceName;
+        timeseriesName = deviceName + "." + timeseriesName;
+        iotDBService.deleteTimeseries(connection, timeseriesName);
+        String host = connection.getHost();
+        measurementService.deleteMeasurementInfo(host, timeseriesName);
+        return BaseVO.success("删除成功", null);
+    }
+
+    @GetMapping("/users")
+    @ApiOperation("获取数据库用户列表")
+    public BaseVO<List<String>> getIotDBUserList(@PathVariable("serverId") Integer serverId, HttpServletRequest request) throws BaseException {
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        List<String> users = iotDBService.getIotDBUserList(connection);
+        String username = connection.getUsername();
+        if (users == null) {
+            users = new ArrayList<>();
+            users.add(username);
+            return BaseVO.success("获取成功", users);
+        }
+        // 前端需要将当前用户处于列表第一位
+        List<String> newUsers = new ArrayList<>();
+        newUsers.add(username);
+        for (String user : users) {
+            if (username.equalsIgnoreCase(user)) {
+                continue;
+            }
+            newUsers.add(user);
+        }
+        return BaseVO.success("获取成功", newUsers);
+    }
+
+    @GetMapping("/roles")
+    @ApiOperation("获取数据库角色列表   (未使用)")
+    public BaseVO<List<String>> getIotDBRoleList(@PathVariable("serverId") Integer serverId, HttpServletRequest request) throws BaseException {
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        List<String> roles = iotDBService.getIotDBRoleList(connection);
+        return BaseVO.success("获取成功", roles);
+    }
+
+    @GetMapping("/users/{userName}")
+    @ApiOperation("获取数据源用户的具体信息或其他用户的权限信息")
+    public BaseVO<IotDBUserVO> getIotDBUser(@PathVariable("serverId") Integer serverId,
+        @PathVariable("userName") String userName,
+        HttpServletRequest request) throws BaseException {
+        if (userName == null || !userName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        IotDBUserVO iotDBUserVO = iotDBService.getIotDBUser(connection, userName);
+        return BaseVO.success("获取成功", iotDBUserVO);
+    }
+
+    @PostMapping("/users/{userName}")
+    @ApiOperation("数据库用户赋权")
+    public BaseVO setUserPrivileges(@PathVariable("serverId") Integer serverId,
+        @PathVariable("userName") String userName,
+        @RequestBody PrivilegeInfoDTO privilegeInfoDTO,
+        HttpServletRequest request) throws BaseException {
+        if (userName == null || !userName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        if (privilegeInfoDTO == null) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        Integer type = privilegeInfoDTO.getType();
+        if (type != null && (type > 3 || type < 0)) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+//        Integer delType = pathCheckAndGetDelType(privilegeInfoDTO);
+        pathCheck(privilegeInfoDTO);
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        iotDBService.setUserPrivileges(connection, userName, privilegeInfoDTO);
+        return BaseVO.success("操作成功", null);
+    }
+
+    private void pathCheck(PrivilegeInfoDTO privilegeInfoDTO) throws BaseException {
+        Integer type = privilegeInfoDTO.getType();
+        List<String> groupPaths = privilegeInfoDTO.getGroupPaths();
+        List<String> devicePaths = privilegeInfoDTO.getDevicePaths();
+        List<String> timeseriesPaths = privilegeInfoDTO.getTimeseriesPaths();
+        List<String> delDevicePaths = privilegeInfoDTO.getDelDevicePaths();
+        List<String> delGroupPaths = privilegeInfoDTO.getDelGroupPaths();
+        List<String> delTimeseriesPaths = privilegeInfoDTO.getDelTimeseriesPaths();
+        if (type == null) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        switch (type) {
+            case 0:
+                if (groupPaths != null && groupPaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                if (devicePaths != null && devicePaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                if (timeseriesPaths != null && timeseriesPaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                if (delDevicePaths != null && delDevicePaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                if (delGroupPaths != null && delGroupPaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                if (delTimeseriesPaths != null && delTimeseriesPaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                break;
+            case 1:
+                if (devicePaths != null && devicePaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                if (timeseriesPaths != null && timeseriesPaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                if (delDevicePaths != null && delDevicePaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                if (delTimeseriesPaths != null && delTimeseriesPaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                break;
+            case 2:
+                if (groupPaths != null && groupPaths.size() > 0) {
+                    if (groupPaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (devicePaths == null || devicePaths.size() == 0) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                }
+                if (devicePaths != null && devicePaths.size() > 0) {
+                    if (groupPaths == null || groupPaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                }
+                if (timeseriesPaths != null && timeseriesPaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                if (delGroupPaths != null && delGroupPaths.size() > 0) {
+                    if (delGroupPaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (delDevicePaths == null || delDevicePaths.size() == 0) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                }
+                if (delDevicePaths != null && delDevicePaths.size() > 0) {
+                    if (delGroupPaths == null || delGroupPaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                }
+                if (delTimeseriesPaths != null && delTimeseriesPaths.size() > 0) {
+                    throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                }
+                break;
+            case 3:
+                if (groupPaths != null && groupPaths.size() > 0) {
+                    if (groupPaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (devicePaths == null || devicePaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (timeseriesPaths == null || timeseriesPaths.size() == 0) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                }
+                if (devicePaths != null && devicePaths.size() > 0) {
+                    if (devicePaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (groupPaths == null || groupPaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (timeseriesPaths == null || timeseriesPaths.size() == 0) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                }
+                if (timeseriesPaths != null && timeseriesPaths.size() > 0) {
+                    if (groupPaths == null || groupPaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (devicePaths == null || devicePaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                }
+                if (delGroupPaths != null && delGroupPaths.size() > 0) {
+                    if (delGroupPaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (delDevicePaths == null || delDevicePaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (delTimeseriesPaths == null || delTimeseriesPaths.size() == 0) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                }
+                if (delDevicePaths != null && delDevicePaths.size() > 0) {
+                    if (delDevicePaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (delGroupPaths == null || delGroupPaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (delTimeseriesPaths == null || delTimeseriesPaths.size() == 0) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                }
+                if (delTimeseriesPaths != null && delTimeseriesPaths.size() > 0) {
+                    if (delGroupPaths == null || delGroupPaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                    if (delDevicePaths == null || delDevicePaths.size() != 1) {
+                        throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+                    }
+                }
+                break;
+            default:
+                throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+//        if (delTimeseriesPaths != null && delTimeseriesPaths.size() > 0) {
+//            if (delGroupPaths == null || delGroupPaths.size() != 1) {
+//                throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+//            }
+//            if (delDevicePaths == null || delDevicePaths.size() != 1) {
+//                throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+//            }
+//            return 3;
+//        }
+//        if (delDevicePaths != null && delDevicePaths.size() > 0) {
+//            if (delGroupPaths == null || delGroupPaths.size() != 1) {
+//                throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+//            }
+//            return 2;
+//        }
+//        if (delGroupPaths != null && delGroupPaths.size() > 0) {
+//            return 1;
+//        }
+//        return 0;
+    }
+
+    @PostMapping("/users/pwd")
+    @ApiOperation("改变用户密码")
+    public BaseVO updatePassword(@PathVariable("serverId") Integer serverId,
+        @RequestBody IotDBUser iotDBUser,
+        HttpServletRequest request) throws BaseException {
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        iotDBService.updatePwd(connection, iotDBUser);
+        return BaseVO.success("修改成功", null);
+    }
+
+    @DeleteMapping("/users/{userName}")
+    @ApiOperation("删除数据库用户")
+    public BaseVO deleteIotDBUser(@PathVariable("serverId") Integer serverId,
+        @PathVariable("userName") String userName,
+        HttpServletRequest request) throws BaseException {
+        if (userName == null || !userName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        iotDBService.deleteIotDBUser(connection, userName);
+        return BaseVO.success("删除成功", null);
+    }
+
+    @DeleteMapping("/roles/{roleName}")
+    @ApiOperation("删除数据库角色  (未使用)")
+    public BaseVO deleteIotDBRole(@PathVariable("serverId") Integer serverId,
+        @PathVariable("roleName") String roleName,
+        HttpServletRequest request) throws BaseException {
+        if (roleName == null || roleName.matches("^[^ ]+$")) {
+            throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        iotDBService.deleteIotDBRole(connection, roleName);
+        return BaseVO.success("删除成功", null);
+    }
+
+    @PostMapping("/users")
+    @ApiOperation("创建数据库用户")
+    public BaseVO setIotDBUser(@PathVariable("serverId") Integer serverId,
+        @RequestBody IotDBUser iotDBUser,
+        HttpServletRequest request) throws BaseException {
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        iotDBService.setIotDBUser(connection, iotDBUser);
+        return BaseVO.success("创建成功", null);
+    }
+
+    @PostMapping("/roles")
+    @ApiOperation("创建数据角色   (未使用)")
+    public BaseVO setIotDBUser(@PathVariable("serverId") Integer serverId,
+        @RequestBody IotDBRole iotDBRole,
+        HttpServletRequest request) throws BaseException {
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        iotDBService.setIotDBRole(connection, iotDBRole);
+        return BaseVO.success("创建成功", null);
+    }
+
+    private void check(HttpServletRequest request, Integer serverId) throws BaseException {
+        Integer userId = AuthenticationUtils.getUserId(request);
+        connectionService.check(serverId, userId);
+    }
+
+
+    private Long switchTime(String ttlUnit) throws BaseException {
+        Long time = 0L;
+        switch (ttlUnit) {
+            case "second":
+                time = 1000L;
+                break;
+            case "minute":
+                time = 60 * 1000L;
+                break;
+            case "hour":
+                time = 60 * 60 * 1000L;
+                break;
+            case "day":
+                time = 24 * 60 * 60 * 1000L;
+                break;
+            case "week":
+                time = 7 * 24 * 60 * 60 * 1000L;
+                break;
+            case "month":
+                time = 30 * 24 * 60 * 60 * 1000L;
+                break;
+            case "year":
+                time = 12 * 30 * 24 * 60 * 60 * 1000L;
+                break;
+            default:
+                throw new BaseException(ErrorCode.WRONG_DB_PARAM, ErrorCode.WRONG_DB_PARAM_MSG);
+        }
+        return time;
+    }
+
+    private String getTTL(Long time) {
+        long yearTime = 31104000000L;
+        long monthTime = 2592000000L;
+        long weekTime = 604800000L;
+        long dayTime = 86400000L;
+        long hourTime = 3600000L;
+        long minuteTime = 60000L;
+        long secondTime = 1000L;
+        if (time == 0) {
+            return "milliSecond";
+        }
+        if ((time / yearTime != 0) && (time % yearTime == 0)) {
+            return "year";
+        }
+        if ((time / monthTime != 0) && (time % monthTime == 0)) {
+            return "month";
+        }
+        if ((time / weekTime != 0) && (time % weekTime == 0)) {
+            return "week";
+        }
+        if ((time / dayTime != 0) && (time % dayTime == 0)) {
+            return "day";
+        }
+        if ((time / hourTime != 0) && (time % hourTime == 0)) {
+            return "hour";
+        }
+        if ((time / minuteTime != 0) && (time % minuteTime == 0)) {
+            return "minute";
+        }
+        if ((time / secondTime != 0) && (time % secondTime == 0)) {
+            return "second";
+        }
+        return null;
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/controller/QueryController.java b/backend/src/main/java/org/apache/iotdb/admin/controller/QueryController.java
new file mode 100644
index 0000000..88ec329
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/controller/QueryController.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.apache.iotdb.admin.common.utils.AuthenticationUtils;
+import org.apache.iotdb.admin.model.dto.SearchDTO;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.apache.iotdb.admin.model.entity.Query;
+import org.apache.iotdb.admin.model.vo.BaseVO;
+import org.apache.iotdb.admin.model.vo.QueryVO;
+import org.apache.iotdb.admin.model.vo.SqlResultVO;
+import org.apache.iotdb.admin.service.ConnectionService;
+import org.apache.iotdb.admin.service.IotDBService;
+import org.apache.iotdb.admin.service.QueryService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+@RestController
+@Api(value = "查询相关接口")
+@RequestMapping("/servers/{serverId}")
+public class QueryController {
+
+    @Autowired
+    private ConnectionService connectionService;
+
+    @Autowired
+    private IotDBService iotDBService;
+
+    @Autowired
+    private QueryService queryService;
+
+    @PostMapping("/querySql")
+    @ApiOperation("用于查询器查询")
+    public BaseVO<List<SqlResultVO>> query(@PathVariable("serverId") Integer serverId,
+        @RequestBody SearchDTO searchDTO,
+        HttpServletRequest request) throws BaseException {
+        List<String> sqls = searchDTO.getSqls();
+        if (sqls == null || sqls.size() == 0) {
+            throw new BaseException(ErrorCode.NO_SQL, ErrorCode.NO_SQL_MSG);
+        }
+        check(request, serverId);
+        Connection connection = connectionService.getById(serverId);
+        Long timestamp = searchDTO.getTimestamp();
+        List<SqlResultVO> sqlResultVOList = iotDBService.queryAll(connection, sqls, timestamp);
+        return BaseVO.success("查询成功", sqlResultVOList);
+    }
+
+    @PostMapping("/query")
+    @ApiOperation("用于查询脚本保存或编辑")
+    public BaseVO saveQuery(@PathVariable("serverId") Integer serverId,
+        @RequestBody Query query,
+        HttpServletRequest request) throws BaseException {
+        String sqls = query.getSqls();
+        if (sqls == null || "".equals(sqls)) {
+            throw new BaseException(ErrorCode.NO_SQL, ErrorCode.NO_SQL_MSG);
+        }
+        check(request, serverId);
+        if (query.getId() != null) {
+            queryService.update(serverId, query);
+            return BaseVO.success("更新成功", null);
+        }
+        queryService.save(serverId, query);
+        return BaseVO.success("保存成功", null);
+    }
+
+    @GetMapping("/query")
+    @ApiOperation("获取脚本列表")
+    public BaseVO<List<QueryVO>> getQueries(@PathVariable("serverId") Integer serverId,
+        HttpServletRequest request) throws BaseException {
+        check(request, serverId);
+        List<QueryVO> queryVOList = queryService.getQueryList(serverId);
+        return BaseVO.success("获取成功", queryVOList);
+    }
+
+    @DeleteMapping("/query/{queryId}")
+    @ApiOperation("删除脚本")
+    public BaseVO deleteQuery(@PathVariable("serverId") Integer serverId,
+        @PathVariable("queryId") Integer queryId,
+        HttpServletRequest request) throws BaseException {
+        check(request, serverId);
+        queryService.deleteQuery(queryId);
+        return BaseVO.success("删除成功", null);
+    }
+
+    @GetMapping("/query/{queryId}")
+    @ApiOperation("获取指定脚本")
+    public BaseVO<Query> getQuery(@PathVariable("serverId") Integer serverId,
+        @PathVariable("queryId") Integer queryId,
+        HttpServletRequest request) throws BaseException {
+        check(request, serverId);
+        Query query = queryService.getQuery(queryId);
+        return BaseVO.success("获取成功", query);
+    }
+
+    @GetMapping("/stop")
+    @ApiOperation("用于查询终止")
+    public BaseVO query(@PathVariable("serverId") Integer serverId, @RequestParam("timestamp") Long timestamp, HttpServletRequest request)
+        throws BaseException {
+        check(request, serverId);
+        iotDBService.stopQuery(serverId, timestamp);
+        return BaseVO.success("停止成功", null);
+    }
+
+    public void check(HttpServletRequest request, Integer serverId) throws BaseException {
+        Integer userId = AuthenticationUtils.getUserId(request);
+        connectionService.check(serverId, userId);
+    }
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/controller/UserController.java b/backend/src/main/java/org/apache/iotdb/admin/controller/UserController.java
new file mode 100644
index 0000000..8fbbc3d
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/controller/UserController.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.controller;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.apache.iotdb.admin.common.utils.AuthenticationUtils;
+import org.apache.iotdb.admin.model.entity.User;
+import org.apache.iotdb.admin.model.vo.BaseVO;
+import org.apache.iotdb.admin.model.vo.ConnVO;
+import org.apache.iotdb.admin.model.vo.ConnectionVO;
+import org.apache.iotdb.admin.service.ConnectionService;
+import org.apache.iotdb.admin.service.UserService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.net.InetAddress;
+import java.util.Calendar;
+import java.util.List;
+
+@RestController
+@Api(value = "登录相关接口")
+public class UserController {
+
+    @Autowired
+    private UserService userService;
+
+    @Autowired
+    private ConnectionService connectionService;
+
+    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
+
+    @PostMapping("/login")
+    @ApiOperation("登录")
+    public BaseVO<ConnectionVO> login(@RequestParam("name") String name, @RequestParam("password") String password, HttpServletResponse response)
+        throws BaseException {
+        if (name == null || password == null || name.length() < 4 || password.length() < 4) {
+            throw new BaseException(ErrorCode.WRONG_USER_PARAM, ErrorCode.WRONG_USER_PARAM_MSG);
+        }
+        User user = userService.login(name, password);
+        int userId = user.getId();
+        List<ConnVO> connVOs = connectionService.getAllConnections(userId);
+        ConnectionVO connectionVO = new ConnectionVO(connVOs, userId, name);
+        response.addHeader("Authorization", getToken(user));
+        return BaseVO.success("登录成功", connectionVO);
+    }
+
+    @PostMapping("/save")
+    @ApiOperation("创建用户  (未使用)")
+    public BaseVO save(@RequestBody User user) throws BaseException {
+        userService.insert(user);
+        return BaseVO.success("保存成功", null);
+    }
+
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除用户  (未使用)")
+    public BaseVO delete(@RequestParam("userId") Integer userId, HttpServletRequest request) throws BaseException {
+        AuthenticationUtils.userAuthentication(userId, request);
+        userService.delete(userId);
+        return BaseVO.success("删除成功", null);
+    }
+
+    @GetMapping("/get")
+    @ApiOperation("二次登录获取用户信息")
+    public BaseVO<User> getUser(HttpServletRequest request) {
+        String authorization = request.getHeader("Authorization");
+        DecodedJWT decode = JWT.decode(authorization);
+        User user = new User();
+        if (decode != null) {
+            Integer userId = decode.getClaim("userId").asInt();
+            String name = decode.getClaim("name").asString();
+            user.setId(userId);
+            user.setName(name);
+        }
+        return BaseVO.success("获取成功", user);
+    }
+
+    private String getToken(User user) throws BaseException {
+        Calendar instance = Calendar.getInstance();
+        try {
+            instance.add(Calendar.HOUR, 24);
+            String token = JWT.create()
+                .withClaim("userId", user.getId())
+                .withClaim("name", user.getName())
+                .withExpiresAt(instance.getTime())
+                .sign(Algorithm.HMAC256("IOTDB:" + InetAddress.getLocalHost().getHostAddress()));
+            logger.info(user.getName() + "登录成功");
+            return token;
+        } catch (Exception e) {
+            logger.info(e.getMessage());
+            throw new BaseException(ErrorCode.GET_TOKEN_FAIL, ErrorCode.GET_TOKEN_FAIL_MSG);
+        }
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/demo/JDBC.java b/backend/src/main/java/org/apache/iotdb/admin/demo/JDBC.java
new file mode 100644
index 0000000..3cb100a
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/demo/JDBC.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.demo;
+
+
+import java.sql.*;
+
+/**
+ * JDBC demo代码
+ */
+public class JDBC {
+
+    public static void main(String[] args) throws SQLException {
+        Connection connection = getConnection();
+        if (connection == null) {
+            System.out.println("get connection defeat");
+            return;
+        }
+        Statement statement = connection.createStatement();
+        //创建存储组
+        try {
+            statement.execute("SET STORAGE GROUP TO root.demo");
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        //展示存储组
+        statement.execute("SHOW STORAGE GROUP");
+        outputResult(statement.getResultSet());
+        //创建时间序列
+        //不同的数据类型有不同的编码方式. 这里以INT32作为例子
+        try {
+            statement.execute("CREATE TIMESERIES root.demo.s0 WITH DATATYPE=INT32,ENCODING=RLE;");
+        } catch (SQLException e) {
+            System.out.println(e.getMessage());
+        }
+        //展示时间序列
+        statement.execute("SHOW TIMESERIES root.demo");
+        outputResult(statement.getResultSet());
+        //展示设备
+        statement.execute("SHOW DEVICES");
+        outputResult(statement.getResultSet());
+        //计算时间序列个数
+        statement.execute("COUNT TIMESERIES root");
+        outputResult(statement.getResultSet());
+        //计算给定级别的nodes个数
+        statement.execute("COUNT NODES root LEVEL=3");
+        outputResult(statement.getResultSet());
+        //计算时间序列以级别3分组的个数
+        statement.execute("COUNT TIMESERIES root GROUP BY LEVEL=3");
+        outputResult(statement.getResultSet());
+
+        //批量执行插入语句
+        statement.addBatch("insert into root.demo(timestamp,s0) values(1,1);");
+        statement.addBatch("insert into root.demo(timestamp,s0) values(1,1);");
+        statement.addBatch("insert into root.demo(timestamp,s0) values(2,15);");
+        statement.addBatch("insert into root.demo(timestamp,s0) values(2,17);");
+        statement.addBatch("insert into root.demo(timestamp,s0) values(4,12);");
+        statement.executeBatch();
+        statement.clearBatch();
+
+        //查询语句
+        String sql = "select * from root.demo";
+        ResultSet resultSet = statement.executeQuery(sql);
+        System.out.println("sql: " + sql);
+        outputResult(resultSet);
+
+        //精确的查询语句
+        sql = "select s0 from root.demo where time = 4;";
+        resultSet = statement.executeQuery(sql);
+        System.out.println("sql: " + sql);
+        outputResult(resultSet);
+
+        //时间范围查询
+        sql = "select s0 from root.demo where time >= 2 and time < 5;";
+        resultSet = statement.executeQuery(sql);
+        System.out.println("sql: " + sql);
+        outputResult(resultSet);
+
+        //聚合查询
+        sql = "select count(s0) from root.demo;";
+        resultSet = statement.executeQuery(sql);
+        System.out.println("sql: " + sql);
+        outputResult(resultSet);
+
+        //删除时间序列
+        statement.execute("delete timeseries root.demo.s0");
+
+        //关闭连接
+        statement.close();
+        connection.close();
+    }
+
+
+    public static Connection getConnection() {
+        // JDBC driver name and database URL
+        String driver = "org.apache.iotdb.jdbc.IoTDBDriver";
+        String url = "jdbc:iotdb://127.0.0.1:6667/";
+
+        // Database credentials
+        String username = "root";
+        String password = "root";
+
+        Connection connection = null;
+        try {
+            Class.forName(driver);
+            connection = DriverManager.getConnection(url, username, password);
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        return connection;
+    }
+
+
+    /**
+     * This is an example of outputting the results in the ResultSet
+     */
+    private static void outputResult(ResultSet resultSet) throws SQLException {
+        if (resultSet != null) {
+            System.out.println("--------------------------");
+            final ResultSetMetaData metaData = resultSet.getMetaData();
+            final int columnCount = metaData.getColumnCount();
+            for (int i = 0; i < columnCount; i++) {
+                System.out.print(metaData.getColumnLabel(i + 1) + " ");
+            }
+            System.out.println();
+            while (resultSet.next()) {
+                for (int i = 1; ; i++) {
+                    System.out.print(resultSet.getString(i));
+                    if (i < columnCount) {
+                        System.out.print(", ");
+                    } else {
+                        System.out.println();
+                        break;
+                    }
+                }
+            }
+            System.out.println("--------------------------\n");
+        }
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/demo/NativeAPI.java b/backend/src/main/java/org/apache/iotdb/admin/demo/NativeAPI.java
new file mode 100644
index 0000000..11259c1
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/demo/NativeAPI.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.demo;
+
+import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.rpc.StatementExecutionException;
+import org.apache.iotdb.session.Session;
+import org.apache.iotdb.session.SessionDataSet;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+import org.apache.iotdb.tsfile.read.common.Field;
+import org.apache.iotdb.tsfile.read.common.RowRecord;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 原生api demo代码
+ */
+public class NativeAPI {
+
+    public static void main(String[] args) throws IoTDBConnectionException, StatementExecutionException {
+        //建立连接
+        Session session = new Session("localhost", 6667, "root", "root");
+        session.open();
+//        SessionPool sessionPool = new SessionPool("localhost", 6667,"root","root",3);
+//        sessionPool.insertRecord();
+        //创建存储组
+        session.setStorageGroup("root.fyx");
+        //创建时间序列
+        /**
+         *   path:层级路径
+         *  TSDataType数据类型:六种                 支持编码方式
+         *          boolean              PLAIN,RLE
+         *          int32                PLAIN,RLE,TS_2DIFF,GORILLA
+         *          int64                PLAIN,RLE,TS_2DIFF,GORILLA
+         *          float                PLAIN,RLE,TS_2DIFF,GORILLA
+         *          double               PLAIN,RLE,TS_2DIFF,GORILLA
+         *          text(字符串)         PLAIN
+         *
+         *  TSEncoding编码方式:
+         *        PLAIN编码:不编码 压缩效率高 空间存储效率低
+         *       二阶差分编码(TS_2DIFF):适合单调序列数据 不适合编码波动较大的数据
+         *       游程编码(RLE):比较适合整数值连续出现的序列
+         *       GORILLA编码:无损编码,它比较适合编码前后值比较接近的数值序列
+         *       定频数据编码(REGULAR):仅适用于整型 允许数据缺失
+         *
+         *  CompressionType压缩方式:
+         *        UMCOMPRESSED
+         *        SNAPPY
+         *        LZ4
+         *        GZIP
+         *        SDT
+         *        PAA
+         *        PLA
+         */
+        session.createTimeseries("root.fyx.cq.dev.temp", TSDataType.FLOAT, TSEncoding.RLE, CompressionType.SNAPPY, null, null, null, null);
+        //创建多个时间序列
+//        session.createMultiTimeseries();
+        //插入数据
+        List<String> measurements = new ArrayList<>();
+        List<TSDataType> types = new ArrayList<>();
+        measurements.add("temp");
+        types.add(TSDataType.FLOAT);
+        for (long time = 0; time < 10; time++) {
+            List<Object> values = new ArrayList<>();
+            values.add(time * 6.6f);
+            //如果不加type,服务器会做类型推断,会有额外耗时
+            session.insertRecord("root.fyx.cq.dev", time, measurements, types, values);
+        }
+        //执行非查询语句的sql
+        session.executeNonQueryStatement("insert into root.fyx.cq.dev(timestamp,temp) values(now(),66.66)");
+        //执行查询语句的sql
+        SessionDataSet sessionDataSet = session.executeQueryStatement("select * from root.fyx.cq.dev");
+        //数据处理
+        int fetchSize = sessionDataSet.getFetchSize();
+        List<String> columnNames = sessionDataSet.getColumnNames();
+        List<TSDataType> columnTypes = sessionDataSet.getColumnTypes();
+        System.out.println(columnNames);
+        System.out.println(columnTypes);
+        if (fetchSize > 0) {
+            while (sessionDataSet.hasNext()) {
+                RowRecord next = sessionDataSet.next();
+                List<Field> fields = next.getFields();
+                // 查询结果第一个为时间戳
+                long timestamp = next.getTimestamp();
+                System.out.print(timestamp + "\t");
+                for (int i = 0; i < fields.size(); i++) {
+                    Field field = fields.get(i);
+                    // 这里的需要按照类型获取
+                    System.out.print(field.getObjectValue(field.getDataType()));
+                }
+                System.out.println();
+            }
+        }
+        sessionDataSet.closeOperationHandle();
+        //删除时间序列
+        session.deleteTimeseries("root.fyx.cq.dev.temp");
+        //删除存储组
+        session.deleteStorageGroup("root.fyx");
+        session.close();
+    }
+
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/filter/TokenFilter.java b/backend/src/main/java/org/apache/iotdb/admin/filter/TokenFilter.java
new file mode 100644
index 0000000..59be4fa
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/filter/TokenFilter.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.filter;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.JWTVerifier;
+import com.auth0.jwt.algorithms.Algorithm;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * 拦截器
+ */
+public class TokenFilter implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws BaseException {
+        JWTVerifier jwtVerifier;
+        try {
+            jwtVerifier = JWT.require(Algorithm.HMAC256("IOTDB:" + InetAddress.getLocalHost().getHostAddress())).build();
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+            throw new BaseException(ErrorCode.SET_JWT_FAIL, ErrorCode.SET_JWT_FAIL_MSG);
+        }
+        try {
+            String authorization = request.getHeader("Authorization");
+            jwtVerifier.verify(authorization);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new BaseException(ErrorCode.TOKEN_ERR, ErrorCode.TOKEN_ERR_MSG);
+        }
+        return true;
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/mapper/ConnectionMapper.java b/backend/src/main/java/org/apache/iotdb/admin/mapper/ConnectionMapper.java
new file mode 100644
index 0000000..a9db0bb
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/mapper/ConnectionMapper.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.springframework.stereotype.Component;
+
+@Component
+public interface ConnectionMapper extends BaseMapper<Connection> {
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/mapper/DeviceMapper.java b/backend/src/main/java/org/apache/iotdb/admin/mapper/DeviceMapper.java
new file mode 100644
index 0000000..b870411
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/mapper/DeviceMapper.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.iotdb.admin.model.entity.Device;
+import org.springframework.stereotype.Component;
+
+@Component
+public interface DeviceMapper extends BaseMapper<Device> {
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/mapper/GroupMapper.java b/backend/src/main/java/org/apache/iotdb/admin/mapper/GroupMapper.java
new file mode 100644
index 0000000..5752ff6
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/mapper/GroupMapper.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.iotdb.admin.model.entity.StorageGroup;
+import org.springframework.stereotype.Component;
+
+@Component
+public interface GroupMapper extends BaseMapper<StorageGroup> {
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/mapper/MeasurementMapper.java b/backend/src/main/java/org/apache/iotdb/admin/mapper/MeasurementMapper.java
new file mode 100644
index 0000000..be3a017
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/mapper/MeasurementMapper.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.iotdb.admin.model.entity.Measurement;
+import org.springframework.stereotype.Component;
+
+@Component
+public interface MeasurementMapper extends BaseMapper<Measurement> {
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/mapper/QueryMapper.java b/backend/src/main/java/org/apache/iotdb/admin/mapper/QueryMapper.java
new file mode 100644
index 0000000..d0c8858
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/mapper/QueryMapper.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.iotdb.admin.model.entity.Query;
+import org.springframework.stereotype.Component;
+
+@Component
+public interface QueryMapper extends BaseMapper<Query> {
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/mapper/UserMapper.java b/backend/src/main/java/org/apache/iotdb/admin/mapper/UserMapper.java
new file mode 100644
index 0000000..55889c2
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/mapper/UserMapper.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.iotdb.admin.model.entity.User;
+import org.springframework.stereotype.Component;
+
+@Component
+public interface UserMapper extends BaseMapper<User> {
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/ConnectionDTO.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/ConnectionDTO.java
new file mode 100644
index 0000000..a87dac6
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/ConnectionDTO.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+import org.hibernate.validator.constraints.Range;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.io.Serializable;
+
+@Data
+public class ConnectionDTO implements Serializable {
+
+    @NotBlank(message = "主机地址不能为空或为null")
+    @Pattern(regexp = "^((2(5[0-5]{1}|[0-4]\\d{1})|[0-1]?\\d{1,2})(\\.(2(5[0-5]{1}|[0-4]\\d{1})|[0-1]?\\d{1,2})){3})|(localhost)$", message = "主机号输入不合法")
+    private String host;
+
+    @NotNull(message = "端口号不能为null")
+    @Range(min = 0, max = 65535, message = "端口号输入不合法")
+    private Integer port;
+
+    @NotBlank(message = "用户名不能为空或为null")
+    @Length(min = 4, message = "长度必须大于等于4")
+    @Pattern(regexp = "^[^ ]+$", message = "用户名不能包含空格")
+    private String username;
+
+    @NotBlank(message = "密码不能为空或为null")
+    @Length(min = 4, message = "长度必须大于等于4")
+    @Pattern(regexp = "^[^ ]+$", message = "密码不能包含空格")
+    private String password;
+
+}
+
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/CountDTO.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/CountDTO.java
new file mode 100644
index 0000000..c04efa3
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/CountDTO.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class CountDTO<T> implements Serializable {
+
+    private List<T> objects;
+    private Integer totalCount;
+    private Integer totalPage;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/DeviceDTO.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/DeviceDTO.java
new file mode 100644
index 0000000..5050673
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/DeviceDTO.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class DeviceDTO implements Serializable {
+
+    private String timeseries;
+
+    private String dataType;
+
+    private String encoding;
+
+    private String description;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/DeviceInfoDTO.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/DeviceInfoDTO.java
new file mode 100644
index 0000000..3733e54
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/DeviceInfoDTO.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class DeviceInfoDTO implements Serializable {
+
+    private List<DeviceDTO> deviceDTOList;
+
+    @NotNull(message = "设备名不能为null")
+    @Pattern(regexp = "^[^ ]+$", message = "不能包含空格")
+    private String deviceName;
+
+    private String description;
+
+    private Integer deviceId;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/GroupDTO.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/GroupDTO.java
new file mode 100644
index 0000000..5aa6070
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/GroupDTO.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.io.Serializable;
+
+@Data
+public class GroupDTO implements Serializable {
+
+    @NotNull(message = "存储组名不能为null")
+    @Pattern(regexp = "^[^ ]+$", message = "不能包含空格")
+    private String groupName;
+    private String description;
+    private Long ttl;
+    private String ttlUnit;
+    private Integer groupId;
+
+}
+
+
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/IotDBRole.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/IotDBRole.java
new file mode 100644
index 0000000..6d2ba60
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/IotDBRole.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 传输role信息类
+ */
+@Data
+public class IotDBRole implements Serializable {
+
+    @Length(min = 4, message = "长度必须大于等于4")
+    private String roleName;
+
+    private List<String> privileges;
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/IotDBUser.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/IotDBUser.java
new file mode 100644
index 0000000..767ad92
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/IotDBUser.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.Pattern;
+import java.io.Serializable;
+
+/**
+ * 传输User信息类
+ */
+@Data
+public class IotDBUser implements Serializable {
+
+    @Length(min = 4, message = "长度必须大于等于4")
+    @Pattern(regexp = "^[^ ]+$", message = "不能包含空格")
+    private String userName;
+
+    @Length(min = 4, message = "长度必须大于等于4")
+    @Pattern(regexp = "^[^ ]+$", message = "不能包含空格")
+    private String password;
+
+//    private List<String> privileges;
+//
+//    private List<String> roles;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/IotDBUserDTO.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/IotDBUserDTO.java
new file mode 100644
index 0000000..562fc62
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/IotDBUserDTO.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class IotDBUserDTO implements Serializable {
+
+    private List<PrivilegeInfoDTO> privilegesInfos;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/MeasurementDTO.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/MeasurementDTO.java
new file mode 100644
index 0000000..b9e6fc7
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/MeasurementDTO.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class MeasurementDTO implements Serializable {
+
+    private String timeseries;
+    private String alias;
+    private String storagegroup;
+    private String dataType;
+    private String encoding;
+    private String compression;
+    private String tags;
+    private String attributes;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/PrivilegeInfoDTO.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/PrivilegeInfoDTO.java
new file mode 100644
index 0000000..69488b6
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/PrivilegeInfoDTO.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class PrivilegeInfoDTO implements Serializable {
+
+    // 0 1 2 3 对应 root、storageGroup、device、timeseries
+    private Integer type;
+    private List<String> groupPaths;
+    private List<String> devicePaths;
+    private List<String> timeseriesPaths;
+    private List<String> privileges;
+    private List<String> cancelPrivileges;
+    private List<String> delGroupPaths;
+    private List<String> delDevicePaths;
+    private List<String> delTimeseriesPaths;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/QueryDTO.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/QueryDTO.java
new file mode 100644
index 0000000..ca8a86a
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/QueryDTO.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+@Data
+public class QueryDTO implements Serializable {
+
+
+    @NotNull(message = "未指定脚本名")
+    private String queryName;
+
+    private String sqls;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/SearchDTO.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/SearchDTO.java
new file mode 100644
index 0000000..4d0c8ba
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/SearchDTO.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class SearchDTO implements Serializable {
+
+    private List<String> sqls;
+
+    @NotNull(message = "不能为null")
+    private Long timestamp;
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/dto/Timeseries.java b/backend/src/main/java/org/apache/iotdb/admin/model/dto/Timeseries.java
new file mode 100644
index 0000000..ecf72cf
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/dto/Timeseries.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 传输时间序列信息的类
+ */
+@Data
+public class Timeseries implements Serializable {
+
+    private List<String> measurements = new ArrayList<>();
+
+    private List<String> types = new ArrayList<>();
+
+    private long time;
+
+    private List<String> values;
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/entity/Connection.java b/backend/src/main/java/org/apache/iotdb/admin/model/entity/Connection.java
new file mode 100644
index 0000000..6672db9
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/entity/Connection.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+import org.hibernate.validator.constraints.Range;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.io.Serializable;
+
+@Data
+public class Connection implements Serializable {
+
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    @NotBlank(message = "主机地址不能为空或为null")
+    @Pattern(regexp = "^((2(5[0-5]{1}|[0-4]\\d{1})|[0-1]?\\d{1,2})(\\.(2(5[0-5]{1}|[0-4]\\d{1})|[0-1]?\\d{1,2})){3})|(localhost)$", message = "主机号输入不合法")
+    private String host;
+
+    @NotNull(message = "端口号不能为null")
+    @Range(min = 0, max = 65535, message = "端口号输入不合法")
+    private Integer port;
+
+    @NotBlank(message = "用户名不能为空或为null")
+    @Length(min = 4, message = "长度必须大于等于4")
+    @Pattern(regexp = "^[^ ]+$", message = "用户名不能包含空格")
+    private String username;
+
+    @NotBlank(message = "密码不能为空或为null")
+    @Length(min = 4, message = "长度必须大于等于4")
+    @Pattern(regexp = "^[^ ]+$", message = "密码不能包含空格")
+    private String password;
+
+    @NotBlank(message = "连接名不能为空或为null")
+    @Length(min = 3, max = 100, message = "连接名长度必须在3-100之间")
+    @Pattern(regexp = "^[^ ]+$", message = "连接名不能包含空格")
+    private String alias;
+
+    @NotNull(message = "用户id不能为null")
+    private Integer userId;
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/entity/Device.java b/backend/src/main/java/org/apache/iotdb/admin/model/entity/Device.java
new file mode 100644
index 0000000..8d0abc4
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/entity/Device.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.io.Serializable;
+
+@Data
+public class Device implements Serializable {
+
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    @NotNull(message = "未指定所属主机")
+    private String host;
+
+    private String description;
+
+    @NotBlank
+    @Length(min = 4, message = "创建者名长度必须大于等于4")
+    @Pattern(regexp = "^[^ ]+$", message = "创建者名不能包含空格")
+    private String creator;
+
+    @NotNull(message = "未指定创建时间")
+    private Long createTime;
+
+    @NotBlank
+    @Pattern(regexp = "^[^ ]+$", message = "设备名不能包含空格")
+    private String deviceName;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/entity/Measurement.java b/backend/src/main/java/org/apache/iotdb/admin/model/entity/Measurement.java
new file mode 100644
index 0000000..c6178a6
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/entity/Measurement.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.entity;
+
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+@Data
+public class Measurement implements Serializable {
+
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    @NotNull(message = "未指定所属主机")
+    private String host;
+
+    @NotNull(message = "未指定测点名")
+    private String measurementName;
+
+    private String description;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/entity/Query.java b/backend/src/main/java/org/apache/iotdb/admin/model/entity/Query.java
new file mode 100644
index 0000000..0d98620
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/entity/Query.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+@Data
+public class Query implements Serializable {
+
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    @NotNull(message = "未指定所属连接id")
+    private Integer connectionId;
+
+    @NotNull(message = "未指定脚本名")
+    private String queryName;
+
+    private String sqls;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/entity/StorageGroup.java b/backend/src/main/java/org/apache/iotdb/admin/model/entity/StorageGroup.java
new file mode 100644
index 0000000..51e9e0e
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/entity/StorageGroup.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import java.io.Serializable;
+
+@Data
+public class StorageGroup implements Serializable {
+
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    @NotNull(message = "未指定所属主机")
+    private String host;
+
+    private String description;
+
+    @NotBlank
+    @Length(min = 4, message = "创建者名长度必须大于等于4")
+    @Pattern(regexp = "^[^ ]+$", message = "创建者名不能包含空格")
+    private String creator;
+
+    @NotNull(message = "未指定创建时间")
+    private Long createTime;
+
+    @NotBlank
+    private String groupName;
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/entity/User.java b/backend/src/main/java/org/apache/iotdb/admin/model/entity/User.java
new file mode 100644
index 0000000..9df52b7
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/entity/User.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Null;
+import javax.validation.constraints.Pattern;
+import java.io.Serializable;
+
+@Data
+public class User implements Serializable {
+
+    @Null
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+    @NotBlank
+    @Length(min = 4, message = "长度必须大于等于4")
+    @Pattern(regexp = "^[^ ]+$", message = "不能包含空格")
+    private String name;
+
+    @NotBlank
+    @Length(min = 6, message = "长度必须大于等于6")
+    @Pattern(regexp = "^[^ ]+$", message = "不能包含空格")
+    private String password;
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/BaseVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/BaseVO.java
new file mode 100644
index 0000000..07f1179
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/BaseVO.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+/**
+ * 返回信息类
+ */
+@Data
+public class BaseVO<T> {
+
+    /**
+     * 0 表示成功 其他表示错误类型
+     */
+    private String code;
+
+    /**
+     * 定义出错时候用户可读的信息
+     */
+    private String message;
+
+    /**
+     * 这是一个返回数据的通用类型模板
+     */
+    private T data;
+
+    public BaseVO() {
+    }
+
+    public BaseVO(String code, String message, T data) {
+        this.code = code;
+        this.message = message;
+        this.data = data;
+    }
+
+    public static <T> BaseVO<T> success(String message, T data) {
+        return new BaseVO<>("0", message, data);
+    }
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/ConnVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/ConnVO.java
new file mode 100644
index 0000000..da2e511
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/ConnVO.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 展示别名及serverId
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ConnVO implements Serializable {
+
+    private Integer id;
+    private String alias;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/ConnectionVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/ConnectionVO.java
new file mode 100644
index 0000000..dbc50ce
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/ConnectionVO.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 展示用户的连接列表
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ConnectionVO implements Serializable {
+
+    List<ConnVO> aliasList;
+    Integer userId;
+    String name;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/DeviceInfo.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/DeviceInfo.java
new file mode 100644
index 0000000..60a5a21
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/DeviceInfo.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class DeviceInfo implements Serializable {
+
+    private String deviceName;
+    private String description;
+    private String creator;
+    private Integer line;
+    private Integer deviceId;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/DeviceInfoVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/DeviceInfoVO.java
new file mode 100644
index 0000000..88f47bd
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/DeviceInfoVO.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class DeviceInfoVO implements Serializable {
+
+    private List<DeviceInfo> deviceInfos;
+    private Integer totalCount;
+    private Integer totalPage;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/DeviceVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/DeviceVO.java
new file mode 100644
index 0000000..de0fec7
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/DeviceVO.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class DeviceVO implements Serializable {
+
+    private String description;
+    private String creator;
+    private String time;
+    private Integer deviceId;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/GroupInfoVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/GroupInfoVO.java
new file mode 100644
index 0000000..5a3b320
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/GroupInfoVO.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class GroupInfoVO implements Serializable {
+
+    private String groupName;
+    private Integer deviceCount;
+    private String description;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/GroupVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/GroupVO.java
new file mode 100644
index 0000000..efbf29c
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/GroupVO.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class GroupVO implements Serializable {
+
+    private String groupName;
+    private String alias;
+    private String description;
+    private String creator;
+    private String createTime;
+    private String ttl;
+    private String ttiUnit;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/IotDBUserVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/IotDBUserVO.java
new file mode 100644
index 0000000..f5976ad
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/IotDBUserVO.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class IotDBUserVO implements Serializable {
+
+    private String userName;
+    private String password;
+    private List<PrivilegeInfo> privilegesInfo;
+//    private List<RoleWithPrivilegesVO> roleWithPrivileges;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/MeasurementVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/MeasurementVO.java
new file mode 100644
index 0000000..3e7574d
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/MeasurementVO.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class MeasurementVO implements Serializable {
+
+    private String timeseries;
+    private String dataType;
+    private String encoding;
+    private String description;
+    private String newValue;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/MeasuremtnInfoVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/MeasuremtnInfoVO.java
new file mode 100644
index 0000000..35334dc
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/MeasuremtnInfoVO.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class MeasuremtnInfoVO implements Serializable {
+
+    private List<MeasurementVO> measurementVOList;
+    private Integer totalCount;
+    private Integer totalPage;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/PathVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/PathVO.java
new file mode 100644
index 0000000..0c9884e
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/PathVO.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class PathVO implements Serializable {
+
+    private String groupName;
+    private String deviceName;
+    private String timeseriesName;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/PrivilegeInfo.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/PrivilegeInfo.java
new file mode 100644
index 0000000..f1fc85a
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/PrivilegeInfo.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class PrivilegeInfo implements Serializable {
+
+    // 0 1 2 3 对应 root、storageGroup、device、timeseries
+    private Integer type;
+    private List<String> groupPaths;
+    private List<String> devicePaths;
+    private List<String> timeseriesPaths;
+    private List<String> privileges;
+    private List<String> allTimeseriesPaths;
+    private List<String> allDevicePaths;
+    private List<String> allGroupPaths;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/QueryVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/QueryVO.java
new file mode 100644
index 0000000..51d6ddc
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/QueryVO.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class QueryVO implements Serializable {
+
+    private Integer id;
+    private String queryName;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/RecordVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/RecordVO.java
new file mode 100644
index 0000000..6b34ee1
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/RecordVO.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class RecordVO implements Serializable {
+
+    private List<Date> timeList;
+    private List<Long> valueList;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/RoleWithPrivilegesVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/RoleWithPrivilegesVO.java
new file mode 100644
index 0000000..21ecfd7
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/RoleWithPrivilegesVO.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 角色及其对应权限
+ */
+@Data
+public class RoleWithPrivilegesVO implements Serializable {
+
+    private String role;
+    private String privilege;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/SqlResultVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/SqlResultVO.java
new file mode 100644
index 0000000..c810248
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/SqlResultVO.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * sql查询的元数据列表和数据列表
+ */
+@Data
+public class SqlResultVO implements Serializable {
+
+    private List<String> metaDataList;
+    private List<List<String>> valueList;
+    private String queryTime;
+    private Long line;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/model/vo/StorageGroupVO.java b/backend/src/main/java/org/apache/iotdb/admin/model/vo/StorageGroupVO.java
new file mode 100644
index 0000000..f6876a6
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/model/vo/StorageGroupVO.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class StorageGroupVO implements Serializable {
+
+    private String groupName;
+    private Integer groupId;
+}
\ No newline at end of file
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/ConnectionService.java b/backend/src/main/java/org/apache/iotdb/admin/service/ConnectionService.java
new file mode 100644
index 0000000..5b63a64
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/ConnectionService.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service;
+
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.apache.iotdb.admin.model.vo.ConnVO;
+
+import java.util.List;
+
+public interface ConnectionService {
+
+    List<ConnVO> getAllConnections(Integer id);
+
+    void insert(Connection connection) throws BaseException;
+
+    void deleteById(Integer serverId, Integer userId) throws BaseException;
+
+    Connection getById(Integer serverId) throws BaseException;
+
+    void check(Integer serverId, Integer userId) throws BaseException;
+
+    void update(Connection connection) throws BaseException;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/DeviceService.java b/backend/src/main/java/org/apache/iotdb/admin/service/DeviceService.java
new file mode 100644
index 0000000..5d9d202
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/DeviceService.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service;
+
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.model.dto.DeviceInfoDTO;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.apache.iotdb.admin.model.entity.Device;
+import org.apache.iotdb.admin.model.vo.DeviceVO;
+
+import java.util.List;
+
+public interface DeviceService {
+
+    List<Device> getDevices(String host, List<String> deviceNames);
+
+    void deleteDeviceInfo(String host, String groupName) throws BaseException;
+
+    void deleteDeviceInfoByDeviceName(String host, String deviceName) throws BaseException;
+
+    void setDeviceInfo(Connection connection, DeviceInfoDTO deviceInfoDTO) throws BaseException;
+
+    DeviceVO getDevice(String host, String deviceName);
+
+    void updateDeviceInfo(DeviceInfoDTO deviceInfoDTO) throws BaseException;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/GroupService.java b/backend/src/main/java/org/apache/iotdb/admin/service/GroupService.java
new file mode 100644
index 0000000..1155d55
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/GroupService.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service;
+
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.model.dto.GroupDTO;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.apache.iotdb.admin.model.entity.StorageGroup;
+
+import java.util.List;
+
+public interface GroupService {
+
+    List<String> getGroupDescription(String host, List<String> groupNames) throws BaseException;
+
+    void setStorageGroupInfo(Connection connection, GroupDTO groupDTO) throws BaseException;
+
+    boolean isExist(String host, String groupName);
+
+    void deleteGroupInfo(String host, String groupName) throws BaseException;
+
+    StorageGroup getGroupInfo(String host, String groupName);
+
+    void updateStorageGroupInfo(Connection connection, GroupDTO groupDTO) throws BaseException;
+
+    Integer getGroupId(String host, String groupName);
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/IotDBService.java b/backend/src/main/java/org/apache/iotdb/admin/service/IotDBService.java
new file mode 100644
index 0000000..82c15a3
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/IotDBService.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service;
+
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.model.dto.*;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.apache.iotdb.admin.model.vo.IotDBUserVO;
+import org.apache.iotdb.admin.model.vo.RecordVO;
+import org.apache.iotdb.admin.model.vo.SqlResultVO;
+
+import java.util.List;
+
+public interface IotDBService {
+
+    List<String> getAllStorageGroups(Connection connection) throws BaseException;
+
+    void saveStorageGroup(Connection connection, String groupName) throws BaseException;
+
+    void deleteStorageGroup(Connection connection, String groupName) throws BaseException;
+
+    CountDTO getDevicesByGroup(Connection connection, String groupName, Integer pageSize, Integer pageNum, String keyword) throws BaseException;
+
+    CountDTO getMeasurementsByDevice(Connection connection, String deviceName, Integer pageSize, Integer pageNum, String keyword) throws BaseException;
+
+    List<String> getIotDBUserList(Connection connection) throws BaseException;
+
+    List<String> getIotDBRoleList(Connection connection) throws BaseException;
+
+    IotDBUserVO getIotDBUser(Connection connection, String userName) throws BaseException;
+
+    void deleteIotDBUser(Connection connection, String userName) throws BaseException;
+
+    void deleteIotDBRole(Connection connection, String roleName) throws BaseException;
+
+    void setIotDBUser(Connection connection, IotDBUser iotDBUserVO) throws BaseException;
+
+    void setIotDBRole(Connection connection, IotDBRole iotDBRole) throws BaseException;
+
+    void insertTimeseries(Connection connection, String deviceName, Timeseries timeseries) throws BaseException;
+
+    void deleteTimeseries(Connection connection, String timeseriesName) throws BaseException;
+
+    SqlResultVO showTimeseries(Connection connection, String deviceName) throws BaseException;
+
+    List<Integer> getDevicesCount(Connection connection, List<String> groupNames) throws BaseException;
+
+    void saveGroupTtl(Connection connection, String groupName, long l) throws BaseException;
+
+    void cancelGroupTtl(Connection connection, String groupName) throws BaseException;
+
+    Integer getDeviceCount(Connection connection, String groupName) throws BaseException;
+
+    List<Integer> getTimeseriesCount(Connection connection, List<String> deviceNames) throws BaseException;
+
+    void deleteTimeseriesByDevice(Connection connection, String deviceName) throws BaseException;
+
+    void createDeviceWithMeasurements(Connection connection, DeviceInfoDTO deviceInfoDTO) throws BaseException;
+
+    Integer getMeasurementsCount(Connection connection, String deviceName) throws BaseException;
+
+    String getLastMeasurementValue(Connection connection, String timeseries) throws BaseException;
+
+    String getGroupTTL(Connection connection, String groupName) throws BaseException;
+
+    List<String> getDevices(Connection connection, String groupName) throws BaseException;
+
+    List<String> getTimeseries(Connection connection, String deviceName) throws BaseException;
+
+    void setUserPrivileges(Connection connection, String userName, PrivilegeInfoDTO privilegeInfoDTO) throws BaseException;
+
+    RecordVO getRecords(Connection connection, String deviceName, String timeseriesName) throws BaseException;
+
+    List<SqlResultVO> queryAll(Connection connection, List<String> sqls, Long timestamp) throws BaseException;
+
+    void updatePwd(Connection connection, IotDBUser iotDBUser) throws BaseException;
+
+    void stopQuery(Integer serverId, Long timestamp) throws BaseException;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/MeasurementService.java b/backend/src/main/java/org/apache/iotdb/admin/service/MeasurementService.java
new file mode 100644
index 0000000..64240db
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/MeasurementService.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service;
+
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.model.dto.DeviceInfoDTO;
+
+public interface MeasurementService {
+
+    void deleteMeasurementInfo(String host, String groupName) throws BaseException;
+
+    void deleteMeasurementInfoByDeviceName(String host, String deviceName) throws BaseException;
+
+    void setMeasurementsInfo(String host, DeviceInfoDTO deviceInfoDTO) throws BaseException;
+
+    String getDescription(String host, String timeseries) throws BaseException;
+
+    void updateMeasurementsInfo(String host, DeviceInfoDTO deviceInfoDTO) throws BaseException;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/QueryService.java b/backend/src/main/java/org/apache/iotdb/admin/service/QueryService.java
new file mode 100644
index 0000000..613966f
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/QueryService.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service;
+
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.model.entity.Query;
+import org.apache.iotdb.admin.model.vo.QueryVO;
+
+import java.util.List;
+
+public interface QueryService {
+
+    void save(Integer serverId, Query query) throws BaseException;
+
+    void update(Integer serverId, Query query) throws BaseException;
+
+    List<QueryVO> getQueryList(Integer serverId);
+
+    void deleteQuery(Integer queryId) throws BaseException;
+
+    Query getQuery(Integer queryId) throws BaseException;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/UserService.java b/backend/src/main/java/org/apache/iotdb/admin/service/UserService.java
new file mode 100644
index 0000000..d263646
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/UserService.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service;
+
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.model.entity.User;
+
+public interface UserService {
+
+    User login(String name, String password) throws BaseException;
+
+    void insert(User user) throws BaseException;
+
+    void delete(Integer userId) throws BaseException;
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/impl/ConnectionServiceImpl.java b/backend/src/main/java/org/apache/iotdb/admin/service/impl/ConnectionServiceImpl.java
new file mode 100644
index 0000000..40dedbc
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/impl/ConnectionServiceImpl.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.apache.iotdb.admin.mapper.ConnectionMapper;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.apache.iotdb.admin.model.vo.ConnVO;
+import org.apache.iotdb.admin.service.ConnectionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class ConnectionServiceImpl extends ServiceImpl<ConnectionMapper, Connection> implements ConnectionService {
+
+    @Autowired
+    private ConnectionMapper connectionMapper;
+
+    @Override
+    public List<ConnVO> getAllConnections(Integer userId) {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("user_id", userId);
+        List<Connection> connections = connectionMapper.selectList(queryWrapper);
+        List<ConnVO> ConnVOs = new ArrayList();
+        for (Connection connection : connections) {
+            ConnVOs.add(new ConnVO(connection.getId(), connection.getAlias()));
+        }
+        return ConnVOs;
+    }
+
+    @Override
+    public void insert(Connection connection) throws BaseException {
+        String alias = connection.getAlias();
+        Integer userId = connection.getUserId();
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("user_id", userId);
+        queryWrapper.eq("alias", alias);
+        Connection existConnection = connectionMapper.selectOne(queryWrapper);
+        // 别名唯一
+        if (existConnection != null) {
+            throw new BaseException(ErrorCode.ALIAS_REPEAT, ErrorCode.ALIAS_REPEAT_MSG);
+        }
+        if ("127.0.0.1".equals(connection.getHost())) {
+            connection.setHost("localhost");
+        }
+        int flag = connectionMapper.insert(connection);
+        if (flag <= 0) {
+            throw new BaseException(ErrorCode.INSERT_CONN_FAIL, ErrorCode.INSERT_CONN_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public void deleteById(Integer serverId, Integer userId) throws BaseException {
+        try {
+            connectionMapper.deleteById(serverId);
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.DELETE_CONN_FAIL, ErrorCode.DELETE_CONN_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public Connection getById(Integer serverId) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("id", serverId);
+        try {
+            Connection connection = connectionMapper.selectOne(queryWrapper);
+            if (connection == null) {
+                throw new BaseException(ErrorCode.NO_CONN, ErrorCode.NO_CONN_MSG);
+            }
+            return connection;
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.GET_CONN_FAIL, ErrorCode.GET_CONN_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public void check(Integer serverId, Integer userId) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("id", serverId);
+        queryWrapper.eq("user_id", userId);
+        Connection connection = connectionMapper.selectOne(queryWrapper);
+        if (connection == null) {
+            throw new BaseException(ErrorCode.CHECK_FAIL, ErrorCode.CHECK_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public void update(Connection connection) throws BaseException {
+        String alias = connection.getAlias();
+        Integer userId = connection.getUserId();
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("user_id", userId);
+        queryWrapper.eq("alias", alias);
+        Connection existConnection = connectionMapper.selectOne(queryWrapper);
+        // 别名唯一
+        if (existConnection != null && !connection.getId().equals(existConnection.getId())) {
+            throw new BaseException(ErrorCode.ALIAS_REPEAT, ErrorCode.ALIAS_REPEAT_MSG);
+        }
+        int flag = connectionMapper.updateById(connection);
+        if (flag <= 0) {
+            throw new BaseException(ErrorCode.INSERT_CONN_FAIL, ErrorCode.INSERT_CONN_FAIL_MSG);
+        }
+    }
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/impl/DeviceServiceImpl.java b/backend/src/main/java/org/apache/iotdb/admin/service/impl/DeviceServiceImpl.java
new file mode 100644
index 0000000..d507d91
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/impl/DeviceServiceImpl.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.apache.iotdb.admin.mapper.DeviceMapper;
+import org.apache.iotdb.admin.model.dto.DeviceInfoDTO;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.apache.iotdb.admin.model.entity.Device;
+import org.apache.iotdb.admin.model.vo.DeviceVO;
+import org.apache.iotdb.admin.service.DeviceService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@Service
+public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService {
+
+
+    @Autowired
+    private DeviceMapper deviceMapper;
+
+    @Override
+    public List<Device> getDevices(String host, List<String> deviceNames) {
+        List<Device> devices = new ArrayList<>();
+        for (String deviceName : deviceNames) {
+            QueryWrapper queryWrapper = new QueryWrapper();
+            queryWrapper.eq("host", host);
+            queryWrapper.eq("device_name", deviceName);
+            Device device = deviceMapper.selectOne(queryWrapper);
+            devices.add(device);
+        }
+        return devices;
+    }
+
+    @Override
+    public void deleteDeviceInfo(String host, String groupName) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", host);
+        queryWrapper.like("device_name", groupName);
+        try {
+            deviceMapper.delete(queryWrapper);
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.DELETE_DEVICE_INFO_FAIL, ErrorCode.DELETE_DEVICE_INFO_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public void deleteDeviceInfoByDeviceName(String host, String deviceName) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", host);
+        queryWrapper.eq("device_name", deviceName);
+        try {
+            deviceMapper.delete(queryWrapper);
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.DELETE_DEVICE_INFO_FAIL, ErrorCode.DELETE_DEVICE_INFO_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public void setDeviceInfo(Connection connection, DeviceInfoDTO deviceInfoDTO) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", connection.getHost());
+        queryWrapper.eq("device_name", deviceInfoDTO.getDeviceName());
+        Device existDevice = deviceMapper.selectOne(queryWrapper);
+        if (existDevice == null) {
+            Device device = new Device();
+            device.setCreator(connection.getUsername());
+            device.setDeviceName(deviceInfoDTO.getDeviceName());
+            device.setCreateTime(System.currentTimeMillis());
+            device.setHost(connection.getHost());
+            device.setDescription(deviceInfoDTO.getDescription());
+            int flag = deviceMapper.insert(device);
+            if (flag <= 0) {
+                throw new BaseException(ErrorCode.SET_DEVICE_INFO_FAIL, ErrorCode.SET_DEVICE_INFO_FAIL_MSG);
+            }
+            return;
+        }
+        existDevice.setDescription(deviceInfoDTO.getDescription());
+        int flag = deviceMapper.updateById(existDevice);
+        if (flag <= 0) {
+            throw new BaseException(ErrorCode.SET_DEVICE_INFO_FAIL, ErrorCode.SET_DEVICE_INFO_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public DeviceVO getDevice(String host, String deviceName) {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", host);
+        queryWrapper.eq("device_name", deviceName);
+        Device device = deviceMapper.selectOne(queryWrapper);
+        // 非系统创建的设备没有设备信息
+        DeviceVO deviceVO = new DeviceVO();
+        if (device != null) {
+            deviceVO.setCreator(device.getCreator());
+            deviceVO.setDescription(device.getDescription());
+            deviceVO.setDeviceId(device.getId());
+            Long createTime = device.getCreateTime();
+            Date date = new Date(createTime);
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+            String time = sdf.format(date);
+            deviceVO.setTime(time);
+            return deviceVO;
+        }
+        return deviceVO;
+    }
+
+    @Override
+    public void updateDeviceInfo(DeviceInfoDTO deviceInfoDTO) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("id", deviceInfoDTO.getDeviceId());
+        Device existDevice = deviceMapper.selectOne(queryWrapper);
+        if (existDevice != null) {
+            existDevice.setDescription(deviceInfoDTO.getDescription());
+            deviceMapper.updateById(existDevice);
+            return;
+        }
+        throw new BaseException(ErrorCode.NO_DEVICE_INFO, ErrorCode.NO_DEVICE_INFO_MSG);
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/impl/GroupServiceImpl.java b/backend/src/main/java/org/apache/iotdb/admin/service/impl/GroupServiceImpl.java
new file mode 100644
index 0000000..7ae2122
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/impl/GroupServiceImpl.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.apache.iotdb.admin.mapper.GroupMapper;
+import org.apache.iotdb.admin.model.dto.GroupDTO;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.apache.iotdb.admin.model.entity.StorageGroup;
+import org.apache.iotdb.admin.service.GroupService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class GroupServiceImpl extends ServiceImpl<GroupMapper, StorageGroup> implements GroupService {
+
+
+    @Autowired
+    private GroupMapper groupMapper;
+
+    @Override
+    public List<String> getGroupDescription(String host, List<String> groupNames) throws BaseException {
+        List<String> descriptions = new ArrayList<>();
+        for (String groupName : groupNames) {
+            descriptions.add(getDescription(host, groupName));
+        }
+        return descriptions;
+    }
+
+    @Override
+    public void setStorageGroupInfo(Connection connection, GroupDTO groupDTO) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        String host = connection.getHost();
+        String groupName = groupDTO.getGroupName();
+        String description = groupDTO.getDescription();
+        if ("127.0.0.1".equals(host)) {
+            host = "localhost";
+        }
+        queryWrapper.eq("host", host);
+        queryWrapper.eq("group_name", groupName);
+        StorageGroup storageGroup = groupMapper.selectOne(queryWrapper);
+        if (storageGroup != null) {
+            storageGroup.setDescription(description);
+            int flag = groupMapper.updateById(storageGroup);
+            if (flag <= 0) {
+                throw new BaseException(ErrorCode.INSERT_GROUP_INFO_FAIL, ErrorCode.INSERT_GROUP_INFO_FAIL_MSG);
+            }
+            return;
+        }
+        String username = connection.getUsername();
+        StorageGroup group = new StorageGroup();
+        group.setCreateTime(System.currentTimeMillis());
+        group.setCreator(username);
+        group.setGroupName(groupName);
+        group.setDescription(description);
+        group.setHost(host);
+        int flag = groupMapper.insert(group);
+        if (flag <= 0) {
+            throw new BaseException(ErrorCode.INSERT_GROUP_INFO_FAIL, ErrorCode.INSERT_GROUP_INFO_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public boolean isExist(String host, String groupName) {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", host);
+        queryWrapper.eq("group_name", groupName);
+        StorageGroup group = groupMapper.selectOne(queryWrapper);
+        if (group != null) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void deleteGroupInfo(String host, String groupName) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", host);
+        queryWrapper.eq("group_name", groupName);
+        try {
+            groupMapper.delete(queryWrapper);
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.DELETE_GROUP_INFO_FAIL, ErrorCode.DELETE_GROUP_INFO_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public StorageGroup getGroupInfo(String host, String groupName) {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", host);
+        queryWrapper.eq("group_name", groupName);
+        return groupMapper.selectOne(queryWrapper);
+    }
+
+    @Override
+    public void updateStorageGroupInfo(Connection connection, GroupDTO groupDTO) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", connection.getHost());
+        queryWrapper.eq("group_name", groupDTO.getGroupName());
+        StorageGroup storageGroup = groupMapper.selectOne(queryWrapper);
+        if (storageGroup != null) {
+            storageGroup.setDescription(groupDTO.getDescription());
+            int flag = groupMapper.updateById(storageGroup);
+            if (flag <= 0) {
+                throw new BaseException(ErrorCode.UPDATE_GROUP_INFO_FAIL, ErrorCode.UPDATE_GROUP_INFO_FAIL_MSG);
+            }
+            return;
+        }
+        throw new BaseException(ErrorCode.NO_GROUP_INFO, ErrorCode.NO_GROUP_INFO_MSG);
+    }
+
+    @Override
+    public Integer getGroupId(String host, String groupName) {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", host);
+        queryWrapper.eq("group_name", groupName);
+        StorageGroup group = groupMapper.selectOne(queryWrapper);
+        if (group != null) {
+            return group.getId();
+        }
+        return null;
+    }
+
+    private String getDescription(String host, String groupName) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", host);
+        queryWrapper.eq("group_name", groupName);
+        StorageGroup storageGroup = groupMapper.selectOne(queryWrapper);
+        if (storageGroup != null) {
+            return storageGroup.getDescription();
+        }
+        return null;
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/impl/IotDBServiceImpl.java b/backend/src/main/java/org/apache/iotdb/admin/service/impl/IotDBServiceImpl.java
new file mode 100644
index 0000000..5a69eac
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/impl/IotDBServiceImpl.java
@@ -0,0 +1,1857 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service.impl;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.apache.iotdb.admin.model.dto.*;
+import org.apache.iotdb.admin.model.entity.Connection;
+import org.apache.iotdb.admin.model.vo.*;
+import org.apache.iotdb.admin.service.IotDBService;
+import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.rpc.StatementExecutionException;
+import org.apache.iotdb.session.pool.SessionDataSetWrapper;
+import org.apache.iotdb.session.pool.SessionPool;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+import org.apache.iotdb.tsfile.read.common.RowRecord;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.lang.reflect.Field;
+import java.sql.*;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.*;
+import java.util.concurrent.*;
+
+@Service
+public class IotDBServiceImpl implements IotDBService {
+
+    private static final Logger logger = LoggerFactory.getLogger(IotDBServiceImpl.class);
+
+    private static final HashMap<String, Boolean> SPECIAL_PRIVILEGES = new HashMap();
+
+    private static final String NO_NEED_PRIVILEGES = "SET_STORAGE_GROUP";
+
+    private static final List<String> PRIVILEGES = new ArrayList<>();
+
+    private static final HashMap<String, Boolean> QUERY_STOP = new HashMap<>();
+
+    static {
+        SPECIAL_PRIVILEGES.put("CREATE_TIMESERIES", true);
+        SPECIAL_PRIVILEGES.put("INSERT_TIMESERIES", true);
+        SPECIAL_PRIVILEGES.put("READ_TIMESERIES", true);
+        SPECIAL_PRIVILEGES.put("DELETE_TIMESERIES", true);
+    }
+
+    static {
+        PRIVILEGES.add("SET_STORAGE_GROUP");
+        PRIVILEGES.add("CREATE_TIMESERIES");
+        PRIVILEGES.add("INSERT_TIMESERIES");
+        PRIVILEGES.add("READ_TIMESERIES");
+        PRIVILEGES.add("DELETE_TIMESERIES");
+        PRIVILEGES.add("CREATE_USER");
+        PRIVILEGES.add("DELETE_USER");
+        PRIVILEGES.add("MODIFY_PASSWORD");
+        PRIVILEGES.add("LIST_USER");
+        PRIVILEGES.add("GRANT_USER_PRIVILEGE");
+        PRIVILEGES.add("REVOKE_USER_PRIVILEGE");
+        PRIVILEGES.add("CREATE_FUNCTION");
+        PRIVILEGES.add("DROP_FUNCTION");
+        PRIVILEGES.add("CREATE_TRIGGER");
+        PRIVILEGES.add("DROP_TRIGGER");
+        PRIVILEGES.add("START_TRIGGER");
+        PRIVILEGES.add("STOP_TRIGGER");
+    }
+
+
+    @Override
+    public List<String> getAllStorageGroups(Connection connection) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "show storage group";
+        List<String> users = executeQueryOneColumn(sessionPool, sql);
+        sessionPool.close();
+        return users;
+    }
+
+    @Override
+    public void saveStorageGroup(Connection connection, String groupName) throws BaseException {
+        paramValid(groupName);
+        SessionPool sessionPool = getSessionPool(connection);
+        try {
+            sessionPool.setStorageGroup(groupName);
+        } catch (StatementExecutionException e) {
+            // 300为存储组重复或者其前/后路径上已经有存储组了
+            if (e.getStatusCode() == 602) {
+                throw new BaseException(ErrorCode.NO_PRI_SET_GROUP, ErrorCode.NO_PRI_SET_GROUP_MSG);
+            }
+            if (e.getStatusCode() == 300) {
+                throw new BaseException(ErrorCode.SET_GROUP_FAIL, ErrorCode.SET_GROUP_FAIL_MSG);
+            }
+            logger.error(e.getMessage());
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.SET_GROUP_FAIL, ErrorCode.SET_GROUP_FAIL_MSG);
+        } finally {
+            if (sessionPool != null) {
+                sessionPool.close();
+            }
+        }
+    }
+
+    @Override
+    public void deleteStorageGroup(Connection connection, String groupName) throws BaseException {
+        paramValid(groupName);
+        SessionPool sessionPool = getSessionPool(connection);
+        try {
+            sessionPool.deleteStorageGroup(groupName);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            if (e.getStatusCode() == 602) {
+                throw new BaseException(ErrorCode.NO_PRI_DELETE_GROUP, ErrorCode.NO_PRI_DELETE_GROUP_MSG);
+            }
+            throw new BaseException(ErrorCode.DELETE_GROUP_FAIL, ErrorCode.DELETE_GROUP_FAIL_MSG);
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.DELETE_GROUP_FAIL, ErrorCode.DELETE_GROUP_FAIL_MSG);
+        } finally {
+            if (sessionPool != null) {
+                sessionPool.close();
+            }
+        }
+    }
+
+    @Override
+    public CountDTO getDevicesByGroup(Connection connection, String groupName, Integer pageSize, Integer pageNum, String keyword) throws BaseException {
+        paramValid(groupName);
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "show devices " + groupName;
+        SessionDataSetWrapper sessionDataSetWrapper = null;
+        try {
+            sessionDataSetWrapper = sessionPool.executeQueryStatement(sql);
+            int batchSize = sessionDataSetWrapper.getBatchSize();
+            List<String> values = new ArrayList<>();
+            int count = 0;
+            if (batchSize > 0) {
+                while (sessionDataSetWrapper.hasNext()) {
+                    RowRecord rowRecord = sessionDataSetWrapper.next();
+                    List<org.apache.iotdb.tsfile.read.common.Field> fields = rowRecord.getFields();
+                    if (keyword != null || "".equals(keyword)) {
+                        String deviceName = fields.get(0).toString();
+                        deviceName = StringUtils.removeStart(deviceName, groupName + ".");
+                        if (deviceName.contains(keyword)) {
+                            count++;
+                        } else {
+                            continue;
+                        }
+                        if (count >= pageSize * (pageNum - 1) + 1 && count <= pageSize * pageNum) {
+                            values.add(fields.get(0).toString());
+                        }
+                    } else {
+                        count++;
+                        if (count >= pageSize * (pageNum - 1) + 1 && count <= pageSize * pageNum) {
+                            values.add(fields.get(0).toString());
+                        }
+                    }
+                }
+            }
+            CountDTO countDTO = new CountDTO();
+            countDTO.setObjects(values);
+            countDTO.setTotalCount(count);
+            Integer totalPage = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
+            countDTO.setTotalPage(totalPage);
+            return countDTO;
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_SQL_ONE_COLUMN_FAIL, ErrorCode.GET_SQL_ONE_COLUMN_FAIL_MSG);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_SQL_ONE_COLUMN_FAIL, ErrorCode.GET_SQL_ONE_COLUMN_FAIL_MSG);
+        } finally {
+            if (sessionDataSetWrapper != null) {
+                sessionDataSetWrapper.close();
+            }
+            if (sessionPool != null) {
+                sessionPool.close();
+            }
+        }
+    }
+
+    @Override
+    public CountDTO getMeasurementsByDevice(Connection connection, String deviceName, Integer pageSize, Integer pageNum, String keyword) throws BaseException {
+        paramValid(deviceName);
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "show timeseries " + deviceName;
+        SessionDataSetWrapper sessionDataSetWrapper = null;
+        try {
+            sessionDataSetWrapper = sessionPool.executeQueryStatement(sql);
+            List<MeasurementDTO> results = new ArrayList<>();
+            int batchSize = sessionDataSetWrapper.getBatchSize();
+            int count = 0;
+            if (batchSize > 0) {
+                while (sessionDataSetWrapper.hasNext()) {
+                    RowRecord rowRecord = sessionDataSetWrapper.next();
+                    List<org.apache.iotdb.tsfile.read.common.Field> fields = rowRecord.getFields();
+                    if (keyword != null || "".equals(keyword)) {
+                        String measurementName = fields.get(0).toString();
+                        measurementName = StringUtils.removeStart(measurementName, deviceName + ".");
+                        if (measurementName.contains(keyword)) {
+                            count++;
+                        } else {
+                            continue;
+                        }
+                        if (count >= pageSize * (pageNum - 1) + 1 && count <= pageSize * pageNum) {
+                            MeasurementDTO t = new MeasurementDTO();
+                            List<String> columnNames = sessionDataSetWrapper.getColumnNames();
+                            for (int i = 0; i < fields.size(); i++) {
+                                Field field = MeasurementDTO.class.getDeclaredField(columnNames.get(i).replaceAll(" ", ""));
+                                field.setAccessible(true);
+                                field.set(t, fields.get(i).toString());
+                            }
+                            results.add(t);
+                        }
+                    } else {
+                        count++;
+                        if (count >= pageSize * (pageNum - 1) + 1 && count <= pageSize * pageNum) {
+                            MeasurementDTO t = new MeasurementDTO();
+                            List<String> columnNames = sessionDataSetWrapper.getColumnNames();
+                            for (int i = 0; i < fields.size(); i++) {
+                                Field field = MeasurementDTO.class.getDeclaredField(columnNames.get(i).replaceAll(" ", ""));
+                                field.setAccessible(true);
+                                field.set(t, fields.get(i).toString());
+                            }
+                            results.add(t);
+                        }
+                    }
+                }
+            }
+            CountDTO countDTO = new CountDTO();
+            countDTO.setObjects(results);
+            countDTO.setTotalCount(count);
+            Integer totalPage = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
+            countDTO.setTotalPage(totalPage);
+            return countDTO;
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_MSM_FAIL, ErrorCode.GET_MSM_FAIL_MSG);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_MSM_FAIL, ErrorCode.GET_MSM_FAIL_MSG);
+        } catch (Exception e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_MSM_FAIL, ErrorCode.GET_MSM_FAIL_MSG);
+        } finally {
+            if (sessionDataSetWrapper != null) {
+                sessionDataSetWrapper.close();
+            }
+        }
+    }
+
+    @Override
+    public List<String> getIotDBUserList(Connection connection) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "list user";
+        List<String> users = executeQueryOneColumn(sessionPool, sql);
+        sessionPool.close();
+        return users;
+    }
+
+    @Override
+    public List<String> getIotDBRoleList(Connection connection) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "list role";
+        List<String> roles = executeQueryOneColumn(sessionPool, sql);
+        sessionPool.close();
+        return roles;
+    }
+
+    @Override
+    public IotDBUserVO getIotDBUser(Connection connection, String userName) throws BaseException {
+        paramValid(userName);
+        IotDBUserVO iotDBUserVO = new IotDBUserVO();
+        iotDBUserVO.setUserName(userName);
+        if (userName.equals(connection.getUsername())) {
+            iotDBUserVO.setPassword(connection.getPassword());
+        } else {
+            iotDBUserVO.setPassword(null);
+        }
+        if ("root".equalsIgnoreCase(userName)) {
+            List<PrivilegeInfo> privilegeInfos = new ArrayList<>();
+            PrivilegeInfo privilegeInfo = new PrivilegeInfo();
+            privilegeInfo.setType(0);
+            privilegeInfo.setPrivileges(PRIVILEGES);
+            privilegeInfos.add(privilegeInfo);
+            iotDBUserVO.setPrivilegesInfo(privilegeInfos);
+            return iotDBUserVO;
+        }
+        SessionPool sessionpool = getSessionPool(connection);
+        String sql = "list user privileges " + userName;
+        try {
+            SessionDataSetWrapper sessionDataSetWrapper = sessionpool.executeQueryStatement(sql);
+            int batchSize = sessionDataSetWrapper.getBatchSize();
+            if (batchSize > 0) {
+                List<String> privileges = new ArrayList<>();
+                while (sessionDataSetWrapper.hasNext()) {
+                    RowRecord next = sessionDataSetWrapper.next();
+                    List<org.apache.iotdb.tsfile.read.common.Field> fields = next.getFields();
+                    for (int i = 0; i < fields.size(); i++) {
+                        org.apache.iotdb.tsfile.read.common.Field field = fields.get(i);
+                        if (i == 0) {
+                            if (field != null && field.toString().length() > 0) {
+                                break;
+                            }
+                            continue;
+                        }
+                        privileges.add(field.toString());
+                    }
+                }
+                // privileges String内容形式 "path : 权限1 权限2 权限3"
+                // 组装成权限信息集合
+                List<PrivilegeInfo> privilegeInfos = new ArrayList<>();
+                if (privileges != null && privileges.size() > 0) {
+                    privilegeInfos = privilegesStrSwitchToObject(sessionpool, privileges);
+                }
+                iotDBUserVO.setPrivilegesInfo(privilegeInfos);
+            }
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.GET_USER_FAIL, ErrorCode.GET_USER_FAIL_MSG);
+        } finally {
+            if (sessionpool != null) {
+                sessionpool.close();
+            }
+        }
+        return iotDBUserVO;
+    }
+
+    @Override
+    public void deleteIotDBUser(Connection connection, String userName) throws BaseException {
+        paramValid(userName);
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "drop user " + userName;
+        try {
+            sessionPool.executeNonQueryStatement(sql);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.DELETE_DB_USER_FAIL, ErrorCode.DELETE_DB_USER_FAIL_MSG);
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.DELETE_DB_USER_FAIL, ErrorCode.DELETE_DB_USER_FAIL_MSG);
+        } finally {
+            if (sessionPool != null) {
+                sessionPool.close();
+            }
+        }
+    }
+
+    @Override
+    public void deleteIotDBRole(Connection connection, String roleName) throws BaseException {
+        paramValid(roleName);
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "drop role " + roleName;
+        try {
+            sessionPool.executeNonQueryStatement(sql);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.DELETE_DB_ROLE_FAIL, ErrorCode.DELETE_DB_ROLE_FAIL_MSG);
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.DELETE_DB_ROLE_FAIL, ErrorCode.DELETE_DB_ROLE_FAIL_MSG);
+        } finally {
+            if (sessionPool != null) {
+                sessionPool.close();
+            }
+        }
+    }
+
+    @Override
+    public void setIotDBUser(Connection connection, IotDBUser iotDBUser) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String userName = iotDBUser.getUserName();
+        String password = iotDBUser.getPassword();
+        String sql = "create user " + userName + " '" + password + "'";
+        try {
+            sessionPool.executeNonQueryStatement(sql);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.SET_DB_USER_FAIL, ErrorCode.SET_DB_USER_FAIL_MSG);
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.SET_DB_USER_FAIL, ErrorCode.SET_DB_USER_FAIL_MSG);
+        } finally {
+            if (sessionPool != null) {
+                sessionPool.close();
+            }
+        }
+//        // 用户角色
+//        for (String role : iotDBUser.getRoles()) {
+//            paramValid(role);
+//            sql = "grant " + role + " to " + userName;
+//            customExecute(conn, sql);
+//        }
+//        // 用户授权
+//        List<String> privileges = iotDBUser.getPrivileges();
+//        for (String privilege : privileges) {
+//            sql = handlerPrivilegeStrToSql(privilege, userName, null);
+//            if (sql != null) {
+//                customExecute(conn, sql);
+//            }
+//        }
+    }
+
+    @Override
+    public void setIotDBRole(Connection connection, IotDBRole iotDBRole) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String roleName = iotDBRole.getRoleName();
+        String sql = "create role " + roleName;
+        try {
+            sessionPool.executeNonQueryStatement(sql);
+            List<String> privileges = iotDBRole.getPrivileges();
+            for (String privilege : privileges) {
+                sql = handlerPrivilegeStrToSql(privilege, null, roleName);
+                if (sql != null) {
+                    sessionPool.executeNonQueryStatement(sql);
+                }
+            }
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.SET_DB_ROLE_FAIL, ErrorCode.SET_DB_ROLE_FAIL_MSG);
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.SET_DB_ROLE_FAIL, ErrorCode.SET_DB_ROLE_FAIL_MSG);
+        } finally {
+            if (sessionPool != null) {
+                sessionPool.close();
+            }
+        }
+    }
+
+//    @Override
+//    public SqlResultVO query(Connection connection, String sql) throws BaseException {
+//        java.sql.Connection conn = getConnection(connection);
+//        SqlResultVO sqlResultVO = sqlQuery(conn, sql);
+//        closeConnection(conn);
+//        return sqlResultVO;
+//    }
+
+    @Override
+    public void insertTimeseries(Connection connection, String deviceName, Timeseries timeseries) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        try {
+            List<TSDataType> types = handleTypeStr(timeseries.getTypes());
+            List<Object> values = handleValueStr(timeseries.getValues(), types);
+            sessionPool.insertRecord(deviceName, timeseries.getTime(), timeseries.getMeasurements(), types, values);
+        } catch (IoTDBConnectionException e) {
+            throw new BaseException(ErrorCode.INSERT_TS_FAIL, ErrorCode.INSERT_TS_FAIL_MSG);
+        } catch (StatementExecutionException e) {
+            throw new BaseException(ErrorCode.INSERT_TS_FAIL, ErrorCode.INSERT_TS_FAIL_MSG);
+        } finally {
+            if (sessionPool != null) {
+                sessionPool.close();
+            }
+        }
+
+    }
+
+    @Override
+    public void deleteTimeseries(Connection connection, String timeseriesName) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        try {
+            sessionPool.deleteTimeseries(timeseriesName);
+        } catch (IoTDBConnectionException e) {
+            throw new BaseException(ErrorCode.DELETE_TS_FAIL, ErrorCode.DELETE_TS_FAIL_MSG);
+        } catch (StatementExecutionException e) {
+            if (e.getStatusCode() == 602) {
+                throw new BaseException(ErrorCode.NO_PRI_DELETE_TIMESERIES, ErrorCode.NO_PRI_DELETE_TIMESERIES_MSG);
+            }
+            throw new BaseException(ErrorCode.DELETE_TS_FAIL, ErrorCode.DELETE_TS_FAIL_MSG);
+        } finally {
+            if (sessionPool != null) {
+                sessionPool.close();
+            }
+        }
+    }
+
+    @Override
+    public SqlResultVO showTimeseries(Connection connection, String deviceName) throws BaseException {
+        paramValid(deviceName);
+        java.sql.Connection conn = getConnection(connection);
+        String sql = "show timeseries " + deviceName;
+        SqlResultVO resultVO = sqlQuery(conn, sql);
+        closeConnection(conn);
+        return resultVO;
+    }
+
+    @Override
+    public List<Integer> getDevicesCount(Connection connection, List<String> groupNames) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        List<Integer> devicesCount = new ArrayList<>();
+        for (String groupName : groupNames) {
+            String sql = "count devices " + groupName;
+            String value = executeQueryOneValue(sessionPool, sql);
+            if (value == null) {
+                devicesCount.add(0);
+                continue;
+            }
+            Integer count = Integer.valueOf(value);
+            devicesCount.add(count);
+        }
+        sessionPool.close();
+        return devicesCount;
+    }
+
+    @Override
+    public void saveGroupTtl(Connection connection, String groupName, long l) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "set ttl to " + groupName + " " + l;
+        try {
+            sessionPool.executeNonQueryStatement(sql);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            if (e.getStatusCode() == 602) {
+                throw new BaseException(ErrorCode.NO_PRI_SET_TTL, ErrorCode.NO_PRI_SET_TTL_MSG);
+            }
+            throw new BaseException(ErrorCode.SET_TTL_FAIL, ErrorCode.SET_TTL_FAIL_MSG);
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.SET_TTL_FAIL, ErrorCode.SET_TTL_FAIL_MSG);
+        } finally {
+            sessionPool.close();
+        }
+    }
+
+    @Override
+    public void cancelGroupTtl(Connection connection, String groupName) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "unset ttl to " + groupName;
+        try {
+            sessionPool.executeNonQueryStatement(sql);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+        } finally {
+            sessionPool.close();
+        }
+    }
+
+    @Override
+    public Integer getDeviceCount(Connection connection, String groupName) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "count devices " + groupName;
+        String value = executeQueryOneValue(sessionPool, sql);
+        if (value == null) {
+            return 0;
+        }
+        Integer count = Integer.valueOf(value);
+        return count;
+    }
+
+    @Override
+    public List<Integer> getTimeseriesCount(Connection connection, List<String> deviceNames) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        List<Integer> lines = new ArrayList<>();
+        for (String deviceName : deviceNames) {
+            String sql = "count timeseries " + deviceName;
+            String value = executeQueryOneValue(sessionPool, sql);
+            if (value == null) {
+                lines.add(0);
+                continue;
+            }
+            Integer count = Integer.valueOf(value);
+            lines.add(count);
+        }
+        sessionPool.close();
+        return lines;
+    }
+
+    @Override
+    public void deleteTimeseriesByDevice(Connection connection, String deviceName) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "delete timeseries " + deviceName + ".*";
+        try {
+            sessionPool.executeNonQueryStatement(sql);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            if (e.getStatusCode() == 602) {
+                throw new BaseException(ErrorCode.NO_PRI_DELETE_TIMESERIES, ErrorCode.NO_PRI_DELETE_TIMESERIES_MSG);
+            }
+            throw new BaseException(ErrorCode.DELETE_TS_FAIL, ErrorCode.DELETE_TS_FAIL_MSG);
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.DELETE_TS_FAIL, ErrorCode.DELETE_TS_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public void createDeviceWithMeasurements(Connection connection, DeviceInfoDTO deviceInfoDTO) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        List<String> typesStr = new ArrayList<>();
+        List<String> encodingsStr = new ArrayList<>();
+        List<String> measurements = new ArrayList<>();
+        for (DeviceDTO deviceDTO : deviceInfoDTO.getDeviceDTOList()) {
+            typesStr.add(deviceDTO.getDataType());
+            encodingsStr.add(deviceDTO.getEncoding());
+            measurements.add(deviceDTO.getTimeseries());
+        }
+        List<TSDataType> types = handleTypeStr(typesStr);
+        List<TSEncoding> encodings = handleEncodingStr(encodingsStr);
+        List<CompressionType> compressionTypes = new ArrayList<>();
+        for (int i = 0; i < types.size(); i++) {
+            compressionTypes.add(CompressionType.SNAPPY);
+        }
+        try {
+            sessionPool.createMultiTimeseries(measurements, types, encodings, compressionTypes, null, null, null, null);
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.INSERT_DEV_FAIL, ErrorCode.INSERT_DEV_FAIL_MSG);
+        } catch (StatementExecutionException e) {
+            if (e.getMessage().contains("No permissions")) {
+                throw new BaseException(ErrorCode.NO_PRI_CREATE_TIMESERIES, ErrorCode.NO_PRI_CREATE_TIMESERIES_MSG);
+            }
+            if (!e.getMessage().contains("PathAlreadyExistException")) {
+                logger.error(e.getMessage());
+                throw new BaseException(ErrorCode.INSERT_DEV_FAIL, ErrorCode.INSERT_DEV_FAIL_MSG);
+            }
+        } finally {
+            if (sessionPool != null) {
+                sessionPool.close();
+            }
+        }
+    }
+
+    @Override
+    public Integer getMeasurementsCount(Connection connection, String deviceName) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "count timeseries " + deviceName;
+        String valueStr = executeQueryOneValue(sessionPool, sql);
+        return Integer.valueOf(valueStr);
+    }
+
+    @Override
+    public String getLastMeasurementValue(Connection connection, String timeseries) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        int index = timeseries.lastIndexOf(".");
+        String sql = "select last_value(" + timeseries.substring(index + 1) + ") from " + timeseries.substring(0, index);
+        String value;
+        try {
+            value = executeQueryOneValue(sessionPool, sql);
+        } finally {
+            sessionPool.close();
+        }
+        return value;
+    }
+
+    @Override
+    public String getGroupTTL(Connection connection, String groupName) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "show ttl on " + groupName;
+        String queryField = "ttl";
+        String ttl = executeQueryOneLine(sessionPool, sql, queryField);
+        return ttl;
+    }
+
+    @Override
+    public List<String> getDevices(Connection connection, String groupName) throws BaseException {
+        paramValid(groupName);
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "show devices " + groupName;
+        List<String> devicesName = executeQueryOneColumn(sessionPool, sql);
+        return devicesName;
+    }
+
+    @Override
+    public List<String> getTimeseries(Connection connection, String deviceName) throws BaseException {
+        paramValid(deviceName);
+        SessionPool sessionPool = getSessionPool(connection);
+        String sql = "show timeseries " + deviceName;
+        SqlResultVO sqlResultVO = executeQuery(sessionPool, sql, true);
+        List<String> metaDataList = sqlResultVO.getMetaDataList();
+        int index = -1;
+        if (metaDataList != null) {
+            for (int i = 0; i < metaDataList.size(); i++) {
+                if ("timeseries".equalsIgnoreCase(metaDataList.get(i))) {
+                    index = i;
+                    break;
+                }
+            }
+        }
+        if (index == -1) {
+            throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG);
+        }
+        List<List<String>> valueList = sqlResultVO.getValueList();
+        List<String> timeseries = new ArrayList<>();
+        for (List<String> list : valueList) {
+            timeseries.add(list.get(index));
+        }
+        return timeseries;
+    }
+
+    @Override
+    public void setUserPrivileges(Connection connection, String userName, PrivilegeInfoDTO privilegeInfoDTO) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        // 授权
+        List<String> privileges = privilegeInfoDTO.getPrivileges();
+        if (notNullAndNotZero(privileges)) {
+            grantOrRevoke("grant", privileges, userName, privilegeInfoDTO, sessionPool);
+        }
+        // 取消授权
+        List<String> cancelPrivileges = privilegeInfoDTO.getCancelPrivileges();
+        if (notNullAndNotZero(cancelPrivileges)) {
+            grantOrRevoke("revoke", cancelPrivileges, userName, privilegeInfoDTO, sessionPool);
+        }
+        cancelPathPrivileges(userName, privilegeInfoDTO, sessionPool);
+        sessionPool.close();
+    }
+
+    private void cancelPathPrivileges(String userName, PrivilegeInfoDTO privilegeInfoDTO, SessionPool sessionPool) {
+        Integer type = privilegeInfoDTO.getType();
+        List<String> delDevicePaths = privilegeInfoDTO.getDelDevicePaths();
+        List<String> delGroupPaths = privilegeInfoDTO.getDelGroupPaths();
+        List<String> delTimeseriesPaths = privilegeInfoDTO.getDelTimeseriesPaths();
+        switch (type) {
+            case 1:
+                if (notNullAndNotZero(delGroupPaths)) {
+                    Set<String> privileges = SPECIAL_PRIVILEGES.keySet();
+                    for (String delGroupPath : delGroupPaths) {
+                        for (String privilegesStr : privileges) {
+                            String sql = "revoke user " + userName + " privileges '" + privilegesStr + "' on root."
+                                + delGroupPath;
+                            try {
+                                sessionPool.executeNonQueryStatement(sql);
+                            } catch (StatementExecutionException e) {
+                                logger.error(e.getMessage());
+                            } catch (IoTDBConnectionException e) {
+                                logger.error(e.getMessage());
+                            }
+                        }
+                    }
+                }
+                break;
+            case 2:
+                if (notNullAndNotZero(delDevicePaths)) {
+                    Set<String> privileges = SPECIAL_PRIVILEGES.keySet();
+                    String onlyGroupPath = delGroupPaths.get(0);
+                    for (String delDevicePath : delDevicePaths) {
+                        for (String privilegesStr : privileges) {
+                            String sql = "revoke user " + userName + " privileges '" + privilegesStr + "' on root."
+                                + onlyGroupPath + "." + delDevicePath;
+                            try {
+                                sessionPool.executeNonQueryStatement(sql);
+                            } catch (StatementExecutionException e) {
+                                logger.error(e.getMessage());
+                            } catch (IoTDBConnectionException e) {
+                                logger.error(e.getMessage());
+                            }
+                        }
+                    }
+                }
+                break;
+            case 3:
+                if (notNullAndNotZero(delTimeseriesPaths)) {
+                    Set<String> privileges = SPECIAL_PRIVILEGES.keySet();
+                    String onlyGroupPath = delGroupPaths.get(0);
+                    String onlyDevicePath = delDevicePaths.get(0);
+                    for (String delTimeseriesPath : delTimeseriesPaths) {
+                        for (String privilegesStr : privileges) {
+                            String sql = "revoke user " + userName + " privileges '" + privilegesStr + "' on root."
+                                + onlyGroupPath + "." + onlyDevicePath + "." + delTimeseriesPath;
+                            try {
+                                sessionPool.executeNonQueryStatement(sql);
+                            } catch (StatementExecutionException e) {
+                                logger.error(e.getMessage());
+                            } catch (IoTDBConnectionException e) {
+                                logger.error(e.getMessage());
+                            }
+                        }
+                    }
+                }
+                break;
+        }
+    }
+
+    @Override
+    public RecordVO getRecords(Connection connection, String deviceName, String timeseriesName) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        RecordVO recordVO = new RecordVO();
+        List<Date> timeList = new ArrayList<>();
+        List<Long> valueList = new ArrayList<>();
+        String sql = "select time," + timeseriesName + " from " + deviceName + " order by time desc limit 200 offset 0";
+        try {
+            SessionDataSetWrapper sessionDataSetWrapper = sessionPool.executeQueryStatement(sql);
+            int batchSize = sessionDataSetWrapper.getBatchSize();
+            if (batchSize > 0) {
+                while (sessionDataSetWrapper.hasNext()) {
+                    RowRecord next = sessionDataSetWrapper.next();
+                    Date date = new Date(next.getTimestamp());
+                    timeList.add(date);
+                    List<org.apache.iotdb.tsfile.read.common.Field> fields = next.getFields();
+                    Long value = Long.valueOf(fields.get(0).toString());
+                    valueList.add(value);
+                }
+            }
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_RECORD_FAIL, ErrorCode.GET_RECORD_FAIL_MSG);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_RECORD_FAIL, ErrorCode.GET_RECORD_FAIL_MSG);
+        }
+        recordVO.setTimeList(timeList);
+        recordVO.setValueList(valueList);
+        return recordVO;
+    }
+
+    @Override
+    public List<SqlResultVO> queryAll(Connection connection, List<String> sqls, Long timestamp) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        List<SqlResultVO> results;
+        String id_plus_timestamp;
+        try {
+            results = new ArrayList<>();
+            Integer id = connection.getId();
+            id_plus_timestamp = id + ":" + timestamp;
+            QUERY_STOP.put(id_plus_timestamp, true);
+            for (String sql : sqls) {
+                int firstSpaceIndex = sql.indexOf(" ");
+                String judge = sql.substring(0, firstSpaceIndex);
+                if ("show".equalsIgnoreCase(judge) || "count".equalsIgnoreCase(judge) || "list".equalsIgnoreCase(judge)) {
+                    SqlResultVO sqlResultVO = executeQuery(sessionPool, sql, false, id_plus_timestamp, false);
+                    results.add(sqlResultVO);
+                    continue;
+                }
+                if ("select".equalsIgnoreCase(judge)) {
+                    SqlResultVO sqlResultVO = executeQuery(sessionPool, sql, false, id_plus_timestamp, true);
+                    results.add(sqlResultVO);
+                    continue;
+                }
+                try {
+                    if (QUERY_STOP.get(id_plus_timestamp)) {
+                        String sqlCheck = sql.toLowerCase();
+                        if (sqlCheck != null && sqlCheck.contains("insert")) {
+                            String s = sqlCheck;
+                            String[] split = s.split("\\.");
+                            if (split.length <= 2) {
+                                throw new BaseException(ErrorCode.NO_SUPPORT_SQL, ErrorCode.NO_SUPPORT_SQL_MSG);
+                            }
+                        }
+                        if (sqlCheck != null && sqlCheck.contains("create timeseries")) {
+                            String s = sqlCheck;
+                            String[] split = s.split("\\.");
+                            if (split.length <= 3) {
+                                throw new BaseException(ErrorCode.NO_SUPPORT_SQL, ErrorCode.NO_SUPPORT_SQL_MSG);
+                            }
+                        }
+                        long start = System.currentTimeMillis();
+                        sessionPool.executeNonQueryStatement(sql);
+                        long end = System.currentTimeMillis();
+                        double time = (end - start + 0.0d) / 1000;
+                        String queryTime = time + "s";
+                        SqlResultVO sqlResultVO = new SqlResultVO();
+                        sqlResultVO.setQueryTime(queryTime);
+                        sqlResultVO.setLine(0L);
+                        results.add(sqlResultVO);
+                    }
+                } catch (StatementExecutionException e) {
+                    logger.error(e.getMessage());
+                    throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG + ":" + sql + "执行出错,错误信息[" + e.getMessage() + "]");
+                } catch (IoTDBConnectionException e) {
+                    logger.error(e.getMessage());
+                    throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG + ":" + sql + "执行出错,错误信息[" + e.getMessage() + "]");
+                }
+            }
+        } finally {
+            if (sessionPool != null) {
+                sessionPool.close();
+            }
+        }
+        QUERY_STOP.remove(id_plus_timestamp);
+        return results;
+    }
+
+    @Override
+    public void updatePwd(Connection connection, IotDBUser iotDBUser) throws BaseException {
+        SessionPool sessionPool = getSessionPool(connection);
+        String userName = iotDBUser.getUserName();
+        String newPWD = iotDBUser.getPassword();
+        String sql = "alter user " + userName + " set password '" + newPWD + "'";
+        try {
+            sessionPool.executeNonQueryStatement(sql);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.UPDATE_PWD_FAIL, ErrorCode.UPDATE_PWD_FAIL_MSG);
+        } catch (IoTDBConnectionException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void stopQuery(Integer serverId, Long timestamp) throws BaseException {
+        String notStopKey = serverId + ":" + timestamp;
+        if (QUERY_STOP.containsKey(notStopKey)) {
+            QUERY_STOP.put(notStopKey, false);
+            return;
+        }
+        throw new BaseException(ErrorCode.NO_QUERY, ErrorCode.NO_QUERY_MSG);
+    }
+
+
+    private void grantOrRevoke(String word, List<String> privileges, String userName, PrivilegeInfoDTO privilegesInfo, SessionPool sessionPool)
+        throws BaseException {
+        Integer type = privilegesInfo.getType();
+//        String privilegesStr = String.join("','", privileges); 一起存会有bug
+        for (String privilegesStr : privileges) {
+            if (type == 0) {
+                String sql = word + " user " + userName + " privileges '" + privilegesStr + "' on root";
+                try {
+                    sessionPool.executeNonQueryStatement(sql);
+                } catch (StatementExecutionException e) {
+                    logger.error(e.getMessage());
+                } catch (IoTDBConnectionException e) {
+                    logger.error(e.getMessage());
+                }
+                continue;
+            }
+            if (type == 1) {
+                List<String> groupPaths = privilegesInfo.getGroupPaths();
+                if (notNullAndNotZero(groupPaths)) {
+                    for (String groupPath : groupPaths) {
+                        String sql = word + " user " + userName + " privileges '" + privilegesStr + "' on root."
+                            + groupPath;
+                        try {
+                            sessionPool.executeNonQueryStatement(sql);
+                        } catch (StatementExecutionException e) {
+                            logger.error(e.getMessage());
+                        } catch (IoTDBConnectionException e) {
+                            logger.error(e.getMessage());
+                        }
+                    }
+                }
+                continue;
+            }
+            if (type == 2) {
+                List<String> groupPaths = privilegesInfo.getGroupPaths();
+                List<String> devicePaths = privilegesInfo.getDevicePaths();
+                if (notNullAndNotZero(groupPaths) && groupPaths.size() == 1 && notNullAndNotZero(devicePaths)) {
+                    String onlyGroupPath = groupPaths.get(0);
+                    for (String devicePath : devicePaths) {
+                        String sql = word + " user " + userName + " privileges '" + privilegesStr + "' on root."
+                            + onlyGroupPath + "." + devicePath;
+                        try {
+                            sessionPool.executeNonQueryStatement(sql);
+                        } catch (StatementExecutionException e) {
+                            logger.error(e.getMessage());
+                        } catch (IoTDBConnectionException e) {
+                            logger.error(e.getMessage());
+                        }
+                    }
+                }
+                continue;
+            }
+            if (type == 3) {
+                List<String> groupPaths = privilegesInfo.getGroupPaths();
+                List<String> devicePaths = privilegesInfo.getDevicePaths();
+                List<String> timeseriesPaths = privilegesInfo.getTimeseriesPaths();
+                if (notNullAndNotZero(groupPaths) && groupPaths.size() == 1 && notNullAndNotZero(devicePaths)
+                    && devicePaths.size() == 1 && notNullAndNotZero(timeseriesPaths)) {
+                    String onlyGroupPath = groupPaths.get(0);
+                    String onlyDevicePath = devicePaths.get(0);
+                    for (String timeseriesPath : timeseriesPaths) {
+                        String sql = word + " user " + userName + " privileges '" + privilegesStr + "' on root."
+                            + onlyGroupPath + "." + onlyDevicePath + "." + timeseriesPath;
+                        try {
+                            sessionPool.executeNonQueryStatement(sql);
+                        } catch (StatementExecutionException e) {
+                            logger.error(e.getMessage());
+                        } catch (IoTDBConnectionException e) {
+                            logger.error(e.getMessage());
+                        }
+                    }
+                }
+                continue;
+            }
+            throw new BaseException(ErrorCode.NO_TYPE, ErrorCode.NO_TYPE_MSG);
+        }
+    }
+
+
+    /**
+     * 判断集合不为空且长度大于0
+     */
+    private boolean notNullAndNotZero(List list) {
+        if (list != null && list.size() > 0) {
+            return true;
+        }
+        return false;
+    }
+
+    private String executeQueryOneLine(SessionPool sessionPool, String sql, String queryField) throws BaseException {
+        try {
+            SessionDataSetWrapper sessionDataSetWrapper = sessionPool.executeQueryStatement(sql);
+            List<String> columnNames = sessionDataSetWrapper.getColumnNames();
+            int index = -1;
+            for (int i = 0; i < columnNames.size(); i++) {
+                if (queryField.equals(columnNames.get(i))) {
+                    index = i;
+                }
+            }
+            if (index == -1) {
+                throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG);
+            }
+            int batchSize = sessionDataSetWrapper.getBatchSize();
+            if (batchSize > 0) {
+                if (sessionDataSetWrapper.hasNext()) {
+                    RowRecord rowRecord = sessionDataSetWrapper.next();
+                    return rowRecord.getFields().get(index).toString();
+                }
+            }
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG);
+        }
+        throw new BaseException(ErrorCode.NO_GROUP, ErrorCode.NO_GROUP_MSG);
+    }
+
+    private SqlResultVO executeQuery(SessionPool sessionPool, String sql, Boolean closePool) throws BaseException {
+        SqlResultVO sqlResultVO = new SqlResultVO();
+        List<List<String>> valuelist = new ArrayList<>();
+        try {
+            SessionDataSetWrapper sessionDataSetWrapper = sessionPool.executeQueryStatement(sql);
+            long start = System.currentTimeMillis();
+            List<String> columnNames = sessionDataSetWrapper.getColumnNames();
+            sqlResultVO.setMetaDataList(columnNames);
+            int batchSize = sessionDataSetWrapper.getBatchSize();
+            // 记录行数
+            long count = 0;
+            if (batchSize > 0) {
+                while (sessionDataSetWrapper.hasNext()) {
+                    List<String> strList = new ArrayList<>();
+                    RowRecord rowRecord = sessionDataSetWrapper.next();
+                    count++;
+                    for (org.apache.iotdb.tsfile.read.common.Field field : rowRecord.getFields()) {
+                        strList.add(field.toString());
+                    }
+                    valuelist.add(strList);
+                }
+                long end = System.currentTimeMillis();
+                double time = (end - start + 0.0d) / 1000;
+                String queryTime = time + "s";
+                sqlResultVO.setQueryTime(queryTime);
+                sqlResultVO.setLine(count);
+            }
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG);
+        } finally {
+            if (sessionPool != null && closePool) {
+                sessionPool.close();
+            }
+        }
+        sqlResultVO.setValueList(valuelist);
+        return sqlResultVO;
+    }
+
+    private SqlResultVO executeQuery(SessionPool sessionPool, String sql, Boolean closePool, String notStopKey, boolean timeFlag) throws BaseException {
+        SqlResultVO sqlResultVO = new SqlResultVO();
+        List<List<String>> valuelist = new ArrayList<>();
+        try {
+            SessionDataSetWrapper sessionDataSetWrapper = sessionPool.executeQueryStatement(sql);
+            long start = System.currentTimeMillis();
+            List<String> columnNames = sessionDataSetWrapper.getColumnNames();
+            sqlResultVO.setMetaDataList(columnNames);
+            int batchSize = sessionDataSetWrapper.getBatchSize();
+            // 记录行数
+            long count = 0;
+            if (batchSize > 0) {
+                while (sessionDataSetWrapper.hasNext() && QUERY_STOP.get(notStopKey)) {
+                    List<String> strList = new ArrayList<>();
+                    RowRecord rowRecord = sessionDataSetWrapper.next();
+                    if (timeFlag) {
+                        long timestamp = rowRecord.getTimestamp();
+                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+                        Date date = new Date(timestamp);
+                        String timeStr = simpleDateFormat.format(date);
+                        strList.add(timeStr);
+                    }
+                    count++;
+                    for (org.apache.iotdb.tsfile.read.common.Field field : rowRecord.getFields()) {
+                        strList.add(field.toString());
+                    }
+                    valuelist.add(strList);
+                }
+                long end = System.currentTimeMillis();
+                double time = (end - start + 0.0d) / 1000;
+                String queryTime = time + "s";
+                sqlResultVO.setQueryTime(queryTime);
+                sqlResultVO.setLine(count);
+            }
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            if (e.getStatusCode() == 602) {
+                throw new BaseException(ErrorCode.NO_PRI_TIMESERIES_DATA, ErrorCode.NO_PRI_TIMESERIES_DATA_MSG);
+            }
+            throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG);
+        } finally {
+            if (sessionPool != null && closePool) {
+                sessionPool.close();
+            }
+        }
+        sqlResultVO.setValueList(valuelist);
+        return sqlResultVO;
+    }
+
+
+    private <T> CountDTO executeQuery(Class<T> clazz, SessionPool sessionPool, String sql, Integer pageSize, Integer pageNum, String keyword)
+        throws BaseException {
+        SessionDataSetWrapper sessionDataSetWrapper = null;
+        try {
+            sessionDataSetWrapper = sessionPool.executeQueryStatement(sql);
+            List<T> results = new ArrayList<>();
+            int batchSize = sessionDataSetWrapper.getBatchSize();
+            int count = 0;
+            if (batchSize > 0) {
+                while (sessionDataSetWrapper.hasNext()) {
+                    RowRecord rowRecord = sessionDataSetWrapper.next();
+                    count++;
+                    if (count >= pageSize * (pageNum - 1) + 1 && count <= pageSize * pageNum) {
+                        T t = clazz.newInstance();
+                        List<org.apache.iotdb.tsfile.read.common.Field> fields = rowRecord.getFields();
+                        List<String> columnNames = sessionDataSetWrapper.getColumnNames();
+                        for (int i = 0; i < fields.size(); i++) {
+                            Field field = clazz.getDeclaredField(columnNames.get(i).replaceAll(" ", ""));
+                            field.setAccessible(true);
+                            field.set(t, fields.get(i).toString());
+                        }
+                        results.add(t);
+                    }
+                }
+            }
+            CountDTO countDTO = new CountDTO();
+            countDTO.setObjects(results);
+            countDTO.setTotalCount(count);
+            Integer totalPage = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
+            countDTO.setTotalPage(totalPage);
+            return countDTO;
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_MSM_FAIL, ErrorCode.GET_MSM_FAIL_MSG);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_MSM_FAIL, ErrorCode.GET_MSM_FAIL_MSG);
+        } catch (Exception e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_MSM_FAIL, ErrorCode.GET_MSM_FAIL_MSG);
+        } finally {
+            if (sessionDataSetWrapper != null) {
+                sessionDataSetWrapper.close();
+            }
+        }
+    }
+
+    private String executeQueryOneValue(SessionPool sessionPool, String sql) throws BaseException {
+        SessionDataSetWrapper sessionDataSetWrapper = null;
+        try {
+            sessionDataSetWrapper = sessionPool.executeQueryStatement(sql);
+            int batchSize = sessionDataSetWrapper.getBatchSize();
+            String value = null;
+            if (batchSize > 0) {
+                while (sessionDataSetWrapper.hasNext()) {
+                    RowRecord rowRecord = sessionDataSetWrapper.next();
+                    List<org.apache.iotdb.tsfile.read.common.Field> fields = rowRecord.getFields();
+                    value = fields.get(0).toString();
+                    break;
+                }
+            }
+            return value;
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_SQL_ONE_VALUE_FAIL, ErrorCode.GET_SQL_ONE_VALUE_FAIL_MSG);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            if (e.getStatusCode() == 602 && sql != null && sql.contains("select")) {
+                throw new BaseException(ErrorCode.NO_PRI_READ_TIMESERIES, ErrorCode.NO_PRI_READ_TIMESERIES_MSG);
+            }
+            throw new BaseException(ErrorCode.GET_SQL_ONE_VALUE_FAIL, ErrorCode.GET_SQL_ONE_VALUE_FAIL_MSG);
+        } finally {
+            if (sessionDataSetWrapper != null) {
+                sessionDataSetWrapper.close();
+            }
+        }
+    }
+
+    private CountDTO executeQueryOneColumn(SessionPool sessionPool, String sql, Integer pageSize, Integer pageNum) throws BaseException {
+        SessionDataSetWrapper sessionDataSetWrapper = null;
+        try {
+            sessionDataSetWrapper = sessionPool.executeQueryStatement(sql);
+            int batchSize = sessionDataSetWrapper.getBatchSize();
+            List<String> values = new ArrayList<>();
+            int count = 0;
+            if (batchSize > 0) {
+                while (sessionDataSetWrapper.hasNext()) {
+                    RowRecord rowRecord = sessionDataSetWrapper.next();
+                    count++;
+                    if (count >= pageSize * (pageNum - 1) + 1 && count <= pageSize * pageNum) {
+                        List<org.apache.iotdb.tsfile.read.common.Field> fields = rowRecord.getFields();
+                        values.add(fields.get(0).toString());
+                    }
+                }
+            }
+            CountDTO countDTO = new CountDTO();
+            countDTO.setObjects(values);
+            countDTO.setTotalCount(count);
+            Integer totalPage = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
+            countDTO.setTotalPage(totalPage);
+            return countDTO;
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_SQL_ONE_COLUMN_FAIL, ErrorCode.GET_SQL_ONE_COLUMN_FAIL_MSG);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_SQL_ONE_COLUMN_FAIL, ErrorCode.GET_SQL_ONE_COLUMN_FAIL_MSG);
+        } finally {
+            if (sessionDataSetWrapper != null) {
+                sessionDataSetWrapper.close();
+            }
+        }
+    }
+
+    private List<String> executeQueryOneColumn(SessionPool sessionPool, String sql) throws BaseException {
+        SessionDataSetWrapper sessionDataSetWrapper = null;
+        try {
+            Callable call = () -> sessionPool.executeQueryStatement(sql);
+            ExecutorService service = Executors.newFixedThreadPool(1);
+            Future submit = service.submit(call);
+            sessionDataSetWrapper = (SessionDataSetWrapper) submit.get(60, TimeUnit.SECONDS);
+            int batchSize = sessionDataSetWrapper.getBatchSize();
+            List<String> values = new ArrayList<>();
+            if (batchSize > 0) {
+                while (sessionDataSetWrapper.hasNext()) {
+                    RowRecord rowRecord = sessionDataSetWrapper.next();
+                    List<org.apache.iotdb.tsfile.read.common.Field> fields = rowRecord.getFields();
+                    values.add(fields.get(0).toString());
+                }
+            }
+            return values;
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_SQL_ONE_COLUMN_FAIL, ErrorCode.GET_SQL_ONE_COLUMN_FAIL_MSG);
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_SQL_ONE_COLUMN_FAIL, ErrorCode.GET_SQL_ONE_COLUMN_FAIL_MSG);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+            throw new BaseException(ErrorCode.TIME_OUT, ErrorCode.TIME_OUT_MSG);
+        } catch (ExecutionException e) {
+            e.printStackTrace();
+            if (e.getMessage().contains("600")) {
+                throw new BaseException(ErrorCode.WRONG_USER, ErrorCode.WRONG_USER_MSG);
+            }
+            throw new BaseException(ErrorCode.CONN_REFUSED, ErrorCode.CONN_REFUSED_MSG);
+        } catch (TimeoutException e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.TIME_OUT, ErrorCode.TIME_OUT_MSG);
+        } finally {
+            if (sessionDataSetWrapper != null) {
+                sessionDataSetWrapper.close();
+            }
+        }
+    }
+
+
+    private List<PrivilegeInfo> privilegesStrSwitchToObject(SessionPool sessionPool, List<String> privileges) throws BaseException {
+        List<PrivilegeInfo> results = new ArrayList<>();
+        List<String> pathStr = new ArrayList<>();
+        List<List<String>> privilegeStr = new ArrayList<>();
+        HashMap<String, Boolean> rootPrivileges = new HashMap();
+        // 遍历集合 将路径和权限集合分别装 过程中 将root相关内容处理
+        for (int i = 0; i < privileges.size(); i++) {
+            String[] split = privileges.get(i).split(":");
+            String[] s = split[1].trim().split(" ");
+            String path = split[0].trim();
+            //为root特殊处理
+            if ("root".equals(path)) {
+                for (String s1 : s) {
+                    if (rootPrivileges.containsKey(s1)) {
+                        continue;
+                    }
+                    rootPrivileges.put(s1, true);
+                }
+                continue;
+            }
+            List<String> list = new ArrayList<>();
+            pathStr.add(path);
+            // 其他粒度下 只需要存储SPECIAL_PRIVILEGES四种权限
+            for (String s1 : s) {
+                if (SPECIAL_PRIVILEGES.containsKey(s1)) {
+                    list.add(s1);
+                    continue;
+                }
+                // 除了root这一层级 其他此权限不生效 不添加进root权限集合
+                if (NO_NEED_PRIVILEGES.equals(s1)) {
+                    continue;
+                }
+                if (rootPrivileges.containsKey(s1)) {
+                    continue;
+                }
+                rootPrivileges.put(s1, true);
+            }
+            privilegeStr.add(list);
+        }
+        // 先处理root 生成对象
+        Set<String> strings = rootPrivileges.keySet();
+        List<String> rootPrivilege = Arrays.asList(strings.toArray(new String[0]));
+        if (rootPrivilege != null && rootPrivilege.size() > 0) {
+            PrivilegeInfo privilegeInfo = new PrivilegeInfo();
+            privilegeInfo.setType(0);
+            privilegeInfo.setPrivileges(rootPrivilege);
+            results.add(privilegeInfo);
+        }
+        // 处理非root  String存储形式 "权限1 权限2 权限3.." List存储相同并集下的path路径
+        Map<String, List<String>> privilegeOne = new HashMap<>();
+        Map<String, List<String>> privilegeTwo = new HashMap<>();
+        Map<String, List<String>> privilegeThree = new HashMap<>();
+        for (int i = 0; i < pathStr.size(); i++) {
+            String s = pathStr.get(i);
+            List<String> list = privilegeStr.get(i);
+            String str = String.join(" ", list);
+            // 通过路径获取所属粒度
+            int type = findType(sessionPool, s);
+            if (type == 1) {
+                // 判断相同的权限集合 放入同一list
+                if (privilegeOne.containsKey(str)) {
+                    List<String> typeList = privilegeOne.get(str);
+                    typeList.add(s);
+                    continue;
+                }
+                ArrayList<String> newStr = new ArrayList();
+                newStr.add(s);
+                privilegeOne.put(str, newStr);
+                continue;
+            }
+            if (type == 2) {
+                // 判断相同的权限集合 放入同一list
+                if (privilegeTwo.containsKey(str)) {
+                    List<String> typeList = privilegeTwo.get(str);
+                    // 相同粒度 同一范围下做前缀判断 相同则为一个并集
+                    int existEnd = typeList.get(0).lastIndexOf(".");
+                    int end = s.lastIndexOf(".");
+                    if (typeList.get(0).substring(0, existEnd).equals(s.substring(0, end))) {
+                        typeList.add(s);
+                        continue;
+                    }
+                }
+                ArrayList<String> newStr = new ArrayList();
+                newStr.add(s);
+                privilegeTwo.put(str, newStr);
+                continue;
+            }
+            if (type == 3) {
+                if (privilegeThree.containsKey(str)) {
+                    List<String> typeList = privilegeThree.get(str);
+                    int existEnd = typeList.get(0).lastIndexOf(".");
+                    int end = s.lastIndexOf(".");
+                    if (typeList.get(0).substring(0, existEnd).equals(s.substring(0, end))) {
+                        typeList.add(s);
+                        continue;
+                    }
+                }
+                ArrayList<String> newStr = new ArrayList();
+                newStr.add(s);
+                privilegeThree.put(str, newStr);
+            }
+        }
+        Set<String> oneKeys = privilegeOne.keySet();
+        Set<String> twoKeys = privilegeTwo.keySet();
+        Set<String> threeKeys = privilegeThree.keySet();
+        // 封装成PrivilegeInfo返回 字符串处理
+        for (String oneKey : oneKeys) {
+            PrivilegeInfo oneInfo = new PrivilegeInfo();
+            List<String> groupPath = new ArrayList<>();
+            List<String> list = privilegeOne.get(oneKey);
+            for (String s : list) {
+                String groupName = s.replaceFirst("root.", "");
+                groupPath.add(groupName);
+            }
+            List<String> privilegesOne = Arrays.asList(oneKey.split(" "));
+            String sql = "show storage group";
+            List<String> allGroupPathsStr = executeQueryOneColumn(sessionPool, sql);
+            List<String> allGroupPaths = new ArrayList<>();
+            for (String s : allGroupPathsStr) {
+                String field = s.replaceFirst("root.", "");
+                allGroupPaths.add(field);
+            }
+            // 展示数据
+            oneInfo.setType(1);
+            oneInfo.setPrivileges(privilegesOne);
+            // allxxx内容为前端编辑修改时需要的数据
+            oneInfo.setGroupPaths(groupPath);
+            oneInfo.setAllGroupPaths(allGroupPaths);
+            results.add(oneInfo);
+        }
+        for (String twoKey : twoKeys) {
+            PrivilegeInfo twoInfo = new PrivilegeInfo();
+            List<String> groupPath = new ArrayList<>();
+            List<String> devicePath = new ArrayList<>();
+            List<String> list = privilegeTwo.get(twoKey);
+            // 得到 组名、设备名、测点名  便于后续字符串操作
+            PathVO pathVO = splitPathToPathVO(sessionPool, list.get(0));
+            groupPath.add(pathVO.getGroupName());
+            for (String s : list) {
+                String deviceName = s.replaceFirst("root." + pathVO.getGroupName() + ".", "");
+                devicePath.add(deviceName);
+            }
+            List<String> privilegesTwo = Arrays.asList(twoKey.split(" "));
+            String sql = "show storage group";
+            List<String> allGroupPathsStr = executeQueryOneColumn(sessionPool, sql);
+            List<String> allGroupPaths = new ArrayList<>();
+            for (String s : allGroupPathsStr) {
+                String field = s.replaceFirst("root.", "");
+                allGroupPaths.add(field);
+            }
+            int end = list.get(0).lastIndexOf(".");
+            sql = "show devices " + list.get(0).substring(0, end) + ".*";
+            List<String> allDevicePathsStr = executeQueryOneColumn(sessionPool, sql);
+            List<String> allDevicePaths = new ArrayList<>();
+            for (String s : allDevicePathsStr) {
+                String field = s.replaceFirst(list.get(0).substring(0, end) + ".", "");
+                allDevicePaths.add(field);
+            }
+            // 展示数据
+            twoInfo.setType(2);
+            twoInfo.setPrivileges(privilegesTwo);
+            twoInfo.setGroupPaths(groupPath);
+            twoInfo.setDevicePaths(devicePath);
+            // allxxx内容为前端编辑修改时需要的数据
+            twoInfo.setAllGroupPaths(allGroupPaths);
+            twoInfo.setAllDevicePaths(allDevicePaths);
+            results.add(twoInfo);
+        }
+        for (String threeKey : threeKeys) {
+            PrivilegeInfo threeInfo = new PrivilegeInfo();
+            List<String> groupPath = new ArrayList<>();
+            List<String> devicePath = new ArrayList<>();
+            List<String> timeseriesPath = new ArrayList<>();
+            List<String> list = privilegeThree.get(threeKey);
+            // 得到 组名、设备名、测点名  便于后续字符串操作
+            PathVO pathVO = splitPathToPathVO(sessionPool, list.get(0));
+            groupPath.add(pathVO.getGroupName());
+            devicePath.add(pathVO.getDeviceName());
+            for (String s : list) {
+                String timeseriesName = s.replaceFirst("root." + pathVO.getGroupName() + "." + pathVO.getDeviceName() + ".", "");
+                timeseriesPath.add(timeseriesName);
+            }
+            List<String> privilegesOne = Arrays.asList(threeKey.split(" "));
+            String sql = "show storage group";
+            List<String> allGroupPathsStr = executeQueryOneColumn(sessionPool, sql);
+            List<String> allGroupPaths = new ArrayList<>();
+            for (String s : allGroupPathsStr) {
+                String field = s.replaceFirst("root.", "");
+                allGroupPaths.add(field);
+            }
+            sql = "show devices root." + pathVO.getGroupName() + ".*";
+            List<String> allDevicePathsStr = executeQueryOneColumn(sessionPool, sql);
+            List<String> allDevicePaths = new ArrayList<>();
+            for (String s : allDevicePathsStr) {
+                String deviceName = s.replaceFirst("root." + pathVO.getGroupName() + ".", "");
+                allDevicePaths.add(deviceName);
+            }
+            int end = list.get(0).lastIndexOf(".");
+            sql = "show timeseries " + list.get(0).substring(0, end) + ".*";
+            List<String> allTimeseriesPathsStr = executeQueryOneColumn(sessionPool, sql);
+            List<String> allTimeseriesPaths = new ArrayList<>();
+            for (String s : allTimeseriesPathsStr) {
+                String field = s.replaceFirst(list.get(0).substring(0, end) + ".", "");
+                allTimeseriesPaths.add(field);
+            }
+            // 展示数据
+            threeInfo.setType(3);
+            threeInfo.setPrivileges(privilegesOne);
+            threeInfo.setGroupPaths(groupPath);
+            threeInfo.setDevicePaths(devicePath);
+            threeInfo.setTimeseriesPaths(timeseriesPath);
+            // allxxx内容为前端编辑修改时需要的数据
+            threeInfo.setAllGroupPaths(allGroupPaths);
+            threeInfo.setAllDevicePaths(allDevicePaths);
+            threeInfo.setAllTimeseriesPaths(allTimeseriesPaths);
+            results.add(threeInfo);
+        }
+        return results;
+    }
+
+    private PathVO splitPathToPathVO(SessionPool sessionPool, String s) throws BaseException {
+        PathVO pathVO = new PathVO();
+        while (!"root".equals(s)) {
+            String sql = "count devices " + s;
+            Integer isDevice = Integer.valueOf(executeQueryOneValue(sessionPool, sql));
+            sql = "count storage group " + s;
+            Integer isGroup = Integer.valueOf(executeQueryOneValue(sessionPool, sql));
+            // 为测点
+            if (isDevice == 0 && isGroup == 0) {
+                int mid = s.lastIndexOf(".");
+                String timeseriesName = s.substring(mid + 1);
+                pathVO.setTimeseriesName(timeseriesName);
+                s = s.substring(0, mid);
+                continue;
+            }
+            // 既是存储组也是实体
+            if (isDevice == 1 && isGroup == 1) {
+                String deviceName = s.replaceFirst("root.", "");
+                String groupName = s.replaceFirst("root.", "");
+                pathVO.setGroupName(groupName);
+                pathVO.setDeviceName(deviceName);
+                break;
+            }
+            // 是存储组 判断是否还为实体
+            if (isDevice > 1 && isGroup == 1) {
+                sql = "show devices " + s;
+                List<String> list = executeQueryOneColumn(sessionPool, sql);
+                if (list.contains(s)) {
+                    String deviceName = s.replaceFirst("root.", "");
+                    String groupName = s.replaceFirst("root.", "");
+                    pathVO.setGroupName(groupName);
+                    pathVO.setDeviceName(deviceName);
+                    break;
+                }
+                String groupName = s.replaceFirst("root.", "");
+                pathVO.setGroupName(groupName);
+            }
+            // 为存储组
+            if (isDevice == 0 && isGroup == 1) {
+                String groupName = s.replaceFirst("root.", "");
+                pathVO.setGroupName(groupName);
+                break;
+            }
+            // 实体 实体之下还可以有实体 需要遍历有多少层级
+            if (isDevice >= 1 && isGroup == 0) {
+                String oldS = s;
+                while (true) {
+                    int mid = s.lastIndexOf(".");
+                    s = s.substring(0, mid);
+                    sql = "count storage group " + s;
+                    isGroup = Integer.valueOf(executeQueryOneValue(sessionPool, sql));
+                    if (isGroup > 0) {
+                        String deviceName = oldS.replaceFirst(s + ".", "");
+                        String groupName = s.replaceFirst("root.", "");
+                        pathVO.setGroupName(groupName);
+                        pathVO.setDeviceName(deviceName);
+                        break;
+                    }
+                }
+                break;
+            }
+        }
+        return pathVO;
+    }
+
+    private int findType(SessionPool sessionPool, String s) throws BaseException {
+        // 主要用于判断s路径是否已经不存在 iotdb存在已删除路径的权限还会展示出来的问题
+        String sql = "count timeseries " + s;
+        SessionDataSetWrapper sessionDataSetWrapper = null;
+        try {
+            sessionDataSetWrapper = sessionPool.executeQueryStatement(sql);
+        } catch (IoTDBConnectionException e) {
+            logger.error(e.getMessage());
+            return -1;
+        } catch (StatementExecutionException e) {
+            logger.error(e.getMessage());
+            return -1;
+        } finally {
+            if (sessionDataSetWrapper != null) {
+                sessionDataSetWrapper.close();
+            }
+        }
+        sql = "count storage group " + s;
+        Integer isGroup = Integer.valueOf(executeQueryOneValue(sessionPool, sql));
+        if (isGroup == 1) {
+            return 1;
+        }
+        // 无效路径 既不是root 也不是存储组 不展示到页面
+        if (isGroup > 1) {
+            return -1;
+        }
+        sql = "count devices " + s;
+        Integer isDevices = Integer.valueOf(executeQueryOneValue(sessionPool, sql));
+        if (isDevices == 1) {
+            return 2;
+        }
+        return 3;
+    }
+
+    private List<TSEncoding> handleEncodingStr(List<String> encoding) {
+        List<TSEncoding> list = new ArrayList<>();
+        for (String s : encoding) {
+            switch (s) {
+                case "PLAIN":
+                    list.add(TSEncoding.PLAIN);
+                    break;
+                case "PLAIN_DICTIONARY":
+                    list.add(TSEncoding.PLAIN_DICTIONARY);
+                    break;
+                case "RLE":
+                    list.add(TSEncoding.RLE);
+                    break;
+                case "DIFF":
+                    list.add(TSEncoding.DIFF);
+                    break;
+                case "TS_2DIFF":
+                    list.add(TSEncoding.TS_2DIFF);
+                    break;
+                case "BITMAP":
+                    list.add(TSEncoding.BITMAP);
+                    break;
+                case "GORILLA_V1":
+                    list.add(TSEncoding.GORILLA_V1);
+                    break;
+                case "REGULAR":
+                    list.add(TSEncoding.REGULAR);
+                    break;
+                case "GORILLA":
+                    list.add(TSEncoding.GORILLA);
+                    break;
+            }
+        }
+        return list;
+    }
+
+    private List<Object> handleValueStr(List<String> values, List<TSDataType> types) throws BaseException {
+        List<Object> list = new ArrayList<>();
+        for (int i = 0; i < types.size(); i++) {
+            TSDataType type = types.get(i);
+            if (type == TSDataType.BOOLEAN) {
+                Integer booleanNum = Integer.valueOf(values.get(i));
+                Boolean flag = null;
+                if (booleanNum == 0) {
+                    flag = false;
+                }
+                if (booleanNum == 1) {
+                    flag = true;
+                }
+                if (flag != null) {
+                    list.add(flag);
+                    continue;
+                }
+                throw new BaseException(ErrorCode.DB_BOOL_WRONG, ErrorCode.DB_BOOL_WRONG_MSG);
+            }
+            if (type == TSDataType.INT32 || type == TSDataType.INT64) {
+                Integer intNum = Integer.valueOf(values.get(i));
+                list.add(intNum);
+                continue;
+            }
+            if (type == TSDataType.FLOAT) {
+                Float floatNum = Float.valueOf(values.get(i));
+                list.add(floatNum);
+                continue;
+            }
+            if (type == TSDataType.DOUBLE) {
+                Double doubleNum = Double.valueOf(values.get(i));
+                list.add(doubleNum);
+                continue;
+            }
+            list.add(values.get(i));
+        }
+        return list;
+    }
+
+    private List<TSDataType> handleTypeStr(List<String> types) throws BaseException {
+        List<TSDataType> list = new ArrayList<>();
+        for (String type : types) {
+            TSDataType tsDataType;
+            switch (type) {
+                case "BOOLEAN":
+                    tsDataType = TSDataType.BOOLEAN;
+                    break;
+                case "INT32":
+                    tsDataType = TSDataType.INT32;
+                    break;
+                case "INT64":
+                    tsDataType = TSDataType.INT64;
+                    break;
+                case "FLOAT":
+                    tsDataType = TSDataType.FLOAT;
+                    break;
+                case "DOUBLE":
+                    tsDataType = TSDataType.DOUBLE;
+                    break;
+                case "TEXT":
+                    tsDataType = TSDataType.TEXT;
+                    break;
+                default:
+                    throw new BaseException(ErrorCode.DB_DATATYPE_WRONG, ErrorCode.DB_DATATYPE_WRONG_MSG);
+            }
+            list.add(tsDataType);
+        }
+        return list;
+    }
+
+
+    public static java.sql.Connection getConnection(Connection connection) throws BaseException {
+        String driver = "org.apache.iotdb.jdbc.IoTDBDriver";
+        String url = "jdbc:iotdb://" + connection.getHost() + ":" + connection.getPort() + "/";
+        String username = connection.getUsername();
+        String password = connection.getPassword();
+        java.sql.Connection conn;
+        try {
+            Class.forName(driver);
+            conn = DriverManager.getConnection(url, username, password);
+        } catch (ClassNotFoundException e) {
+            throw new BaseException(ErrorCode.GET_DBCONN_FAIL, ErrorCode.GET_DBCONN_FAIL_MSG);
+        } catch (SQLException e) {
+            throw new BaseException(ErrorCode.GET_DBCONN_FAIL, ErrorCode.GET_DBCONN_FAIL_MSG);
+        }
+        return conn;
+    }
+
+    public static SessionPool getSessionPool(Connection connection) throws BaseException {
+        String host = connection.getHost();
+        Integer port = connection.getPort();
+        String username = connection.getUsername();
+        String password = connection.getPassword();
+        SessionPool sessionPool = null;
+        try {
+            sessionPool = new SessionPool(host, port, username, password, 3);
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.GET_SESSION_FAIL, ErrorCode.GET_SESSION_FAIL_MSG);
+        }
+        return sessionPool;
+    }
+//    public static SessionPool getSession(Connection connection) throws BaseException {
+//        if(sessionPool == null){
+//            host = connection.getHost();
+//            port = connection.getPort();
+//            username = connection.getUsername();
+//            password = connection.getPassword();
+//            sessionPool = new SessionPool(host,port,username,password,3);
+//            return sessionPool;
+//        }
+//        if(host == connection.getHost() && port.equals(connection.getPort()) && username == connection.getUsername() && password == connection.getPassword()){
+//            return sessionPool;
+//        }
+//        sessionPool.close();
+//        host = connection.getHost();
+//        port = connection.getPort();
+//        username = connection.getUsername();
+//        password = connection.getPassword();
+//        sessionPool = new SessionPool(host,port,username,password,3);
+//        return sessionPool;
+//    }
+
+    private void closeConnection(java.sql.Connection conn) throws BaseException {
+        try {
+            if (conn != null) {
+                conn.close();
+            }
+        } catch (SQLException e) {
+            throw new BaseException(ErrorCode.CLOSE_DBCONN_FAIL, ErrorCode.CLOSE_DBCONN_FAIL_MSG);
+        }
+    }
+
+    private String handlerPrivilegeStrToSql(String privilege, String userName, String roleName) {
+        int i = privilege.indexOf(":");
+        String path = privilege.substring(0, i).trim();
+        String[] privileges = privilege.substring(i + 1).trim().split(" ");
+        int len = privileges.length;
+        if (len == 0) {
+            return null;
+        }
+        StringBuilder str = new StringBuilder();
+        if (userName != null) {
+            str.append("grant user " + userName + " privileges ");
+        } else {
+            str.append("grant role " + roleName + " privileges ");
+        }
+        for (int j = 0; i < len - 1; j++) {
+            str.append("'" + privileges[j] + "',");
+        }
+        str.append("'" + privileges[len - 1] + "' on " + path);
+        return str.toString();
+    }
+
+
+    private SqlResultVO sqlQuery(java.sql.Connection conn, String sql) throws BaseException {
+        PreparedStatement statement = null;
+        ResultSet resultSet = null;
+        try {
+            statement = conn.prepareStatement(sql);
+            resultSet = statement.executeQuery();
+            ResultSetMetaData metaData = resultSet.getMetaData();
+            int columnCount = metaData.getColumnCount();
+            SqlResultVO sqlResultVO = new SqlResultVO();
+            List<String> metaDataList = new ArrayList<>();
+            for (int i = 0; i < columnCount; i++) {
+                metaDataList.add(metaData.getColumnLabel(i + 1));
+            }
+            sqlResultVO.setMetaDataList(metaDataList);
+            List<List<String>> valuelist = new ArrayList<>();
+            while (resultSet.next()) {
+                List<String> strList = new ArrayList<>();
+                for (int i = 0; i < columnCount; i++) {
+                    strList.add(resultSet.getString(i + 1));
+                }
+                valuelist.add(strList);
+            }
+            sqlResultVO.setValueList(valuelist);
+            return sqlResultVO;
+        } catch (SQLException e) {
+            throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG);
+        } finally {
+            if (resultSet != null) {
+                try {
+                    resultSet.close();
+                } catch (SQLException e) {
+                    throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG);
+                }
+            }
+            if (statement != null) {
+                try {
+                    statement.close();
+                } catch (SQLException e) {
+                    throw new BaseException(ErrorCode.SQL_EP, ErrorCode.SQL_EP_MSG);
+                }
+            }
+            closeConnection(conn);
+        }
+    }
+
+    /**
+     * 防止sql注入对参数进行校验不能有空格
+     *
+     * @param field 拼接sql的字段
+     */
+    private void paramValid(String field) throws BaseException {
+        if (field != null) {
+            if (!field.matches("^[^ ]+$")) {
+                throw new BaseException(ErrorCode.SQL_PARAM_WRONG, ErrorCode.SQL_PARAM_WRONG_MSG);
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/impl/MeasurementServiceImpl.java b/backend/src/main/java/org/apache/iotdb/admin/service/impl/MeasurementServiceImpl.java
new file mode 100644
index 0000000..52a6f65
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/impl/MeasurementServiceImpl.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.apache.iotdb.admin.mapper.MeasurementMapper;
+import org.apache.iotdb.admin.model.dto.DeviceDTO;
+import org.apache.iotdb.admin.model.dto.DeviceInfoDTO;
+import org.apache.iotdb.admin.model.entity.Measurement;
+import org.apache.iotdb.admin.service.MeasurementService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class MeasurementServiceImpl extends ServiceImpl<MeasurementMapper, Measurement> implements MeasurementService {
+
+    @Autowired
+    private MeasurementMapper measurementMapper;
+
+    private static final Logger logger = LoggerFactory.getLogger(IotDBServiceImpl.class);
+
+    @Override
+    public void deleteMeasurementInfo(String host, String groupName) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", host);
+        queryWrapper.like("measurement_name", groupName);
+        try {
+            measurementMapper.delete(queryWrapper);
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.DELETE_MEASUREMENT_INFO_FAIL, ErrorCode.DELETE_MEASUREMENT_INFO_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public void deleteMeasurementInfoByDeviceName(String host, String deviceName) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", host);
+        queryWrapper.like("measurement_name", deviceName);
+        try {
+            measurementMapper.delete(queryWrapper);
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.DELETE_MEASUREMENT_INFO_FAIL, ErrorCode.DELETE_MEASUREMENT_INFO_FAIL_MSG);
+        }
+    }
+
+    @Override
+    public void setMeasurementsInfo(String host, DeviceInfoDTO deviceInfoDTO) throws BaseException {
+        List<String> descriptions = new ArrayList<>();
+        List<String> measurements = new ArrayList<>();
+        for (DeviceDTO deviceDTO : deviceInfoDTO.getDeviceDTOList()) {
+            descriptions.add(deviceDTO.getDescription());
+            measurements.add(deviceDTO.getTimeseries());
+        }
+        for (int i = 0; i < measurements.size(); i++) {
+            Measurement mea = new Measurement();
+            mea.setDescription(descriptions.get(i));
+            mea.setMeasurementName(measurements.get(i));
+            mea.setHost(host);
+            int flag = measurementMapper.insert(mea);
+            if (flag <= 0) {
+                throw new BaseException(ErrorCode.SET_MEASUREMENT_INFO_FAIL, ErrorCode.SET_MEASUREMENT_INFO_FAIL_MSG);
+            }
+        }
+    }
+
+    @Override
+    public String getDescription(String host, String timeseries) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("host", host);
+        queryWrapper.eq("measurement_name", timeseries);
+        Measurement measurement = null;
+        try {
+            measurement = measurementMapper.selectOne(queryWrapper);
+        } catch (Exception e) {
+            logger.error(e.getMessage());
+            throw new BaseException(ErrorCode.GET_MSM_DES_FAIL, ErrorCode.GET_MSM_DES_FAIL_MSG);
+        }
+        if (measurement != null) {
+            return measurement.getDescription();
+        }
+        return null;
+    }
+
+    @Override
+    public void updateMeasurementsInfo(String host, DeviceInfoDTO deviceInfoDTO) throws BaseException {
+        List<String> descriptions = new ArrayList<>();
+        List<String> measurements = new ArrayList<>();
+        for (DeviceDTO deviceDTO : deviceInfoDTO.getDeviceDTOList()) {
+            descriptions.add(deviceDTO.getDescription());
+            measurements.add(deviceDTO.getTimeseries());
+        }
+        for (int i = 0; i < measurements.size(); i++) {
+            QueryWrapper queryWrapper = new QueryWrapper();
+            queryWrapper.eq("host", host);
+            queryWrapper.eq("measurement_name", measurements.get(i));
+            Measurement existMeasurement = measurementMapper.selectOne(queryWrapper);
+            // 未创建的测点
+            if (existMeasurement == null) {
+                Measurement mea = new Measurement();
+                mea.setDescription(descriptions.get(i));
+                mea.setMeasurementName(measurements.get(i));
+                mea.setHost(host);
+                int flag = measurementMapper.insert(mea);
+                if (flag <= 0) {
+                    throw new BaseException(ErrorCode.SET_MEASUREMENT_INFO_FAIL, ErrorCode.SET_MEASUREMENT_INFO_FAIL_MSG);
+                }
+                continue;
+            }
+            // 已创建的测点更新描述
+            existMeasurement.setDescription(descriptions.get(i));
+            int flag = measurementMapper.updateById(existMeasurement);
+            if (flag <= 0) {
+                throw new BaseException(ErrorCode.SET_MEASUREMENT_INFO_FAIL, ErrorCode.SET_MEASUREMENT_INFO_FAIL_MSG);
+            }
+        }
+    }
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/impl/QueryServiceImpl.java b/backend/src/main/java/org/apache/iotdb/admin/service/impl/QueryServiceImpl.java
new file mode 100644
index 0000000..76dd6ae
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/impl/QueryServiceImpl.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.apache.iotdb.admin.mapper.QueryMapper;
+import org.apache.iotdb.admin.model.entity.Query;
+import org.apache.iotdb.admin.model.vo.QueryVO;
+import org.apache.iotdb.admin.service.QueryService;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class QueryServiceImpl extends ServiceImpl<QueryMapper, Query> implements QueryService {
+
+    @Autowired
+    private QueryMapper queryMapper;
+
+    @Override
+    public void save(Integer serverId, Query inputQuery) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("connection_id", serverId);
+        queryWrapper.eq("query_name", inputQuery.getQueryName());
+        Query query = queryMapper.selectOne(queryWrapper);
+        if (query == null) {
+            Query newQuery = new Query();
+            newQuery.setConnectionId(serverId);
+            newQuery.setQueryName(inputQuery.getQueryName());
+            newQuery.setSqls(inputQuery.getSqls());
+            queryMapper.insert(newQuery);
+            return;
+        }
+        throw new BaseException(ErrorCode.QUERY_EXIST, ErrorCode.QUERY_EXIST_MSG);
+    }
+
+    @Override
+    public void update(Integer serverId, Query inputQuery) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("id", inputQuery.getId());
+        Query query = queryMapper.selectOne(queryWrapper);
+        if (query != null) {
+            query.setQueryName(inputQuery.getQueryName());
+            query.setSqls(inputQuery.getSqls());
+            queryMapper.updateById(query);
+            return;
+        }
+        throw new BaseException(ErrorCode.QUERY_EXIST, ErrorCode.QUERY_EXIST_MSG);
+    }
+
+    @Override
+    public List<QueryVO> getQueryList(Integer serverId) {
+        QueryWrapper<Query> queryWrapper = new QueryWrapper();
+        queryWrapper.eq("connection_id", serverId);
+        List<Query> queries = queryMapper.selectList(queryWrapper);
+        List<QueryVO> queryVOList = new ArrayList<>();
+        for (Query query : queries) {
+            QueryVO queryVO = new QueryVO();
+            BeanUtils.copyProperties(query, queryVO);
+            queryVOList.add(queryVO);
+        }
+        return queryVOList;
+    }
+
+    @Override
+    public void deleteQuery(Integer queryId) throws BaseException {
+        QueryWrapper<Query> queryWrapper = new QueryWrapper();
+        queryWrapper.eq("id", queryId);
+        int flag = queryMapper.delete(queryWrapper);
+        if (flag <= 0) {
+            throw new BaseException(ErrorCode.QUERY_NOT_EXIST, ErrorCode.QUERY_NOT_EXIST_MSG);
+        }
+    }
+
+    @Override
+    public Query getQuery(Integer queryId) throws BaseException {
+        QueryWrapper<Query> queryWrapper = new QueryWrapper();
+        queryWrapper.eq("id", queryId);
+        Query query = queryMapper.selectOne(queryWrapper);
+        if (query == null) {
+            throw new BaseException(ErrorCode.QUERY_NOT_EXIST, ErrorCode.QUERY_NOT_EXIST_MSG);
+        }
+        return query;
+    }
+
+}
diff --git a/backend/src/main/java/org/apache/iotdb/admin/service/impl/UserServiceImpl.java b/backend/src/main/java/org/apache/iotdb/admin/service/impl/UserServiceImpl.java
new file mode 100644
index 0000000..8610c39
--- /dev/null
+++ b/backend/src/main/java/org/apache/iotdb/admin/service/impl/UserServiceImpl.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.apache.iotdb.admin.common.exception.BaseException;
+import org.apache.iotdb.admin.common.exception.ErrorCode;
+import org.apache.iotdb.admin.mapper.UserMapper;
+import org.apache.iotdb.admin.model.entity.User;
+import org.apache.iotdb.admin.service.UserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+
+@Service
+public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
+
+
+    @Autowired
+    private UserMapper userMapper;
+
+    @Autowired
+    private BCryptPasswordEncoder bCryptPasswordEncoder;
+
+    @Override
+    public User login(String name, String password) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("name", name);
+        User user = userMapper.selectOne(queryWrapper);
+        if (user != null) {
+            if (!bCryptPasswordEncoder.matches(password, user.getPassword())) {
+                throw new BaseException(ErrorCode.LOGIN_FAIL_PWD, ErrorCode.LOGIN_FAIL_PWD_MSG);
+            }
+            return user;
+        } else {
+            throw new BaseException(ErrorCode.LOGIN_FAIL_USER, ErrorCode.LOGIN_FAIL_USER_MSG);
+        }
+    }
+
+    @Override
+    public void insert(User user) throws BaseException {
+        QueryWrapper queryWrapper = new QueryWrapper();
+        queryWrapper.eq("name", user.getName());
+        User existUser = userMapper.selectOne(queryWrapper);
+        if (existUser == null) {
+            user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
+            try {
+                userMapper.insert(user);
+            } catch (Exception e) {
+                throw new BaseException(ErrorCode.INSERT_USER_FAIL, ErrorCode.INSERT_USER_FAIL_MSG);
+            }
+        } else {
+            throw new BaseException(ErrorCode.USER_EXIST, ErrorCode.USER_EXIST_MSG);
+        }
+    }
+
+    @Override
+    public void delete(Integer userId) throws BaseException {
+        try {
+            userMapper.deleteById(userId);
+        } catch (Exception e) {
+            throw new BaseException(ErrorCode.DELETE_USER_FAIL, ErrorCode.DELETE_USER_FAIL_MSG);
+        }
+    }
+
+
+}
diff --git a/backend/src/main/resources/META-INF/app.properties b/backend/src/main/resources/META-INF/app.properties
new file mode 100644
index 0000000..ca3692a
--- /dev/null
+++ b/backend/src/main/resources/META-INF/app.properties
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+app.name=test
\ No newline at end of file
diff --git a/backend/src/main/resources/application-dev.properties b/backend/src/main/resources/application-dev.properties
new file mode 100644
index 0000000..4a14685
--- /dev/null
+++ b/backend/src/main/resources/application-dev.properties
@@ -0,0 +1,30 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# 指定日志配置文件的位置
+logging.config=classpath:log4j2.xml
+
+# 配置端口号和上下文根
+server.port=8080
+server.servlet.context-path=/api
+
+# 指定数据源和连接驱动
+# 如下配置数据源的方式会导致项目重新打包后数据丢失,仅为了开发时方便测试,实际部署项目时请参考application-prod.properties文件配置
+spring.datasource.url=jdbc:sqlite::resource:sqlite/iotdb.db
+spring.datasource.driver-class-name=org.sqlite.JDBC
\ No newline at end of file
diff --git a/backend/src/main/resources/application-prod.properties b/backend/src/main/resources/application-prod.properties
new file mode 100644
index 0000000..b6b57f8
--- /dev/null
+++ b/backend/src/main/resources/application-prod.properties
@@ -0,0 +1,30 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# 指定日志配置文件的位置
+logging.config=classpath:log4j2-prod.xml
+
+# 配置端口号和上下文根
+server.port=8081
+server.servlet.context-path=/api
+
+# 指定数据源和连接驱动
+# 请将backend/src/main/resources/sqlite下的iotdb.db文件复制一份到你的服务器上,并将以下路径修改为你的iotdb.db文件路径
+spring.datasource.url=jdbc:sqlite:/usr/local/iotdb/data/iotdb1.db
+spring.datasource.driver-class-name=org.sqlite.JDBC
\ No newline at end of file
diff --git a/backend/src/main/resources/application-test.properties b/backend/src/main/resources/application-test.properties
new file mode 100644
index 0000000..2d959b0
--- /dev/null
+++ b/backend/src/main/resources/application-test.properties
@@ -0,0 +1,26 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+logging.config=classpath:log4j2.xml
+
+server.port=8079
+server.servlet.context-path=/api
+
+spring.datasource.url=jdbc:sqlite:/usr/local/iotdb/data/iotdb.db
+spring.datasource.driver-class-name=org.sqlite.JDBC
\ No newline at end of file
diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties
new file mode 100644
index 0000000..5aa2fca
--- /dev/null
+++ b/backend/src/main/resources/application.properties
@@ -0,0 +1,21 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# 指定配置文件。dev、prod、test分别表示开发、生产、测试环境
+spring.profiles.active=dev
\ No newline at end of file
diff --git a/backend/src/main/resources/log4j2-prod.xml b/backend/src/main/resources/log4j2-prod.xml
new file mode 100644
index 0000000..3a0f519
--- /dev/null
+++ b/backend/src/main/resources/log4j2-prod.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<configuration status="ERROR">
+
+    <Properties>
+        <!--应用名-->
+        <property name="app">IoTDB-Workbench</property>
+        <property name="log.root.level">INFO</property>
+        <property name="log.home">/data/applogs/app-prod</property>
+        <property name="log.default.pattern">%-d{yyyy-MM-dd HH:mm:ss.SSS} [%p] [${app}] %l %m%n</property>
+        <property name="log.stats.pattern">%m%n</property>
+    </Properties>
+
+    <appenders>
+        <Console name="STDOUT" target="SYSTEM_OUT">
+            <PatternLayout>
+                <Pattern>${log.default.pattern}</Pattern>
+            </PatternLayout>
+        </Console>
+
+        <RollingFile name="ROLLING_DEBUG" fileName="${log.home}/${app}_debug.log"
+                     filePattern="${log.home}/debug.log.%i">
+            <PatternLayout>
+                <Pattern>${log.default.pattern}</Pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="100 MB" />
+            </Policies>
+            <DefaultRolloverStrategy max="10"/>
+            <!--<DirectWriteRolloverStrategy maxFiles="10"/>-->
+            <Filters>
+                <ThresholdFilter level="DEBUG" onMatch="ACCEPT"/>
+            </Filters>
+        </RollingFile>
+
+        <RollingFile name="ROLLING_INFO" fileName="${log.home}/${app}_info.log"
+                     filePattern="${log.home}/info.log.%i">
+            <PatternLayout>
+                <Pattern>${log.default.pattern}</Pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="100 MB" />
+            </Policies>
+            <DefaultRolloverStrategy max="10"/>
+            <Filters>
+                <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
+                <ThresholdFilter level="INFO" onMatch="ACCEPT"/>
+            </Filters>
+        </RollingFile>
+
+        <RollingFile name="ROLLING_WARN" fileName="${log.home}/${app}_warn.log"
+                     filePattern="${log.home}/warn.log.%i">
+            <PatternLayout>
+                <Pattern>${log.default.pattern}</Pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="100 MB" />
+            </Policies>
+            <DefaultRolloverStrategy max="10"/>
+            <Filters>
+                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
+                <ThresholdFilter level="WARN" onMatch="ACCEPT"/>
+            </Filters>
+        </RollingFile>
+
+        <RollingFile name="ROLLING_ERROR" fileName="${log.home}/${app}_error.log"
+                     filePattern="${log.home}/error.log.%i">
+            <PatternLayout>
+                <Pattern>${log.default.pattern}</Pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="100 MB" />
+            </Policies>
+            <DefaultRolloverStrategy max="10"/>
+            <!--<DirectWriteRolloverStrategy maxFiles="10"/>-->
+            <Filters>
+                <ThresholdFilter level="ERROR" onMatch="ACCEPT"/>
+            </Filters>
+        </RollingFile>
+
+
+
+    </appenders>
+
+    <loggers>
+        <!--level日志级别: ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF -->
+        <Root level="${log.root.level}">
+            <AppenderRef ref="STDOUT"/>
+            <AppenderRef ref="ROLLING_INFO"/>
+            <AppenderRef ref="ROLLING_WARN"/>
+            <AppenderRef ref="ROLLING_ERROR"/>
+            <!--<AppenderRef ref="ROLLING_DEBUG"/>-->
+        </Root>
+
+
+        <!--<logger name="com.alibaba" level="ERROR"/>-->
+        <!--<logger name="org" level="ERROR"/>-->
+
+    </loggers>
+
+</configuration>
+
diff --git a/backend/src/main/resources/log4j2.xml b/backend/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..21772ee
--- /dev/null
+++ b/backend/src/main/resources/log4j2.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+
+<configuration status="ERROR">
+
+    <Properties>
+        <!--应用名-->
+        <property name="app">IoTDB-Workbench</property>
+        <property name="log.root.level">INFO</property>
+        <property name="log.home">/data/applogs/app-test</property>
+        <property name="log.default.pattern">%-d{yyyy-MM-dd HH:mm:ss.SSS} [%p] [${app}] %l %m%n</property>
+        <property name="log.stats.pattern">%m%n</property>
+    </Properties>
+
+    <appenders>
+        <Console name="STDOUT" target="SYSTEM_OUT">
+            <PatternLayout>
+                <Pattern>${log.default.pattern}</Pattern>
+            </PatternLayout>
+        </Console>
+
+        <RollingFile name="ROLLING_DEBUG" fileName="${log.home}/${app}_debug.log"
+                     filePattern="${log.home}/debug.log.%i">
+            <PatternLayout>
+                <Pattern>${log.default.pattern}</Pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="100 MB" />
+            </Policies>
+            <DefaultRolloverStrategy max="10"/>
+            <!--<DirectWriteRolloverStrategy maxFiles="10"/>-->
+            <Filters>
+                <ThresholdFilter level="DEBUG" onMatch="ACCEPT"/>
+            </Filters>
+        </RollingFile>
+
+        <RollingFile name="ROLLING_INFO" fileName="${log.home}/${app}_info.log"
+                     filePattern="${log.home}/info.log.%i">
+            <PatternLayout>
+                <Pattern>${log.default.pattern}</Pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="100 MB" />
+            </Policies>
+            <DefaultRolloverStrategy max="10"/>
+            <Filters>
+                <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
+                <ThresholdFilter level="INFO" onMatch="ACCEPT"/>
+            </Filters>
+        </RollingFile>
+
+        <RollingFile name="ROLLING_WARN" fileName="${log.home}/${app}_warn.log"
+                     filePattern="${log.home}/warn.log.%i">
+            <PatternLayout>
+                <Pattern>${log.default.pattern}</Pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="100 MB" />
+            </Policies>
+            <DefaultRolloverStrategy max="10"/>
+            <Filters>
+                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
+                <ThresholdFilter level="WARN" onMatch="ACCEPT"/>
+            </Filters>
+        </RollingFile>
+
+        <RollingFile name="ROLLING_ERROR" fileName="${log.home}/${app}_error.log"
+                     filePattern="${log.home}/error.log.%i">
+            <PatternLayout>
+                <Pattern>${log.default.pattern}</Pattern>
+            </PatternLayout>
+            <Policies>
+                <SizeBasedTriggeringPolicy size="100 MB" />
+            </Policies>
+            <DefaultRolloverStrategy max="10"/>
+            <!--<DirectWriteRolloverStrategy maxFiles="10"/>-->
+            <Filters>
+                <ThresholdFilter level="ERROR" onMatch="ACCEPT"/>
+            </Filters>
+        </RollingFile>
+
+
+
+    </appenders>
+
+    <loggers>
+        <!--level日志级别: ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF -->
+        <Root level="${log.root.level}">
+            <AppenderRef ref="STDOUT"/>
+            <AppenderRef ref="ROLLING_INFO"/>
+            <AppenderRef ref="ROLLING_WARN"/>
+            <AppenderRef ref="ROLLING_ERROR"/>
+            <!--<AppenderRef ref="ROLLING_DEBUG"/>-->
+        </Root>
+
+
+        <!--<logger name="com.alibaba" level="ERROR"/>-->
+        <!--<logger name="org" level="ERROR"/>-->
+
+    </loggers>
+
+</configuration>
+
diff --git a/backend/src/test/java/org/apache/iotdb/admin/DemoJDBC.java b/backend/src/test/java/org/apache/iotdb/admin/DemoJDBC.java
new file mode 100644
index 0000000..dcf0780
--- /dev/null
+++ b/backend/src/test/java/org/apache/iotdb/admin/DemoJDBC.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * ${DESCRIPTION}
+ *
+ * @author fanli
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class DemoJDBC {
+
+
+    @Test
+    public void testSelect() {
+
+    }
+}
diff --git a/backend/src/test/java/org/apache/iotdb/admin/controller/ConnectionControllerTest.java b/backend/src/test/java/org/apache/iotdb/admin/controller/ConnectionControllerTest.java
new file mode 100644
index 0000000..df531d9
--- /dev/null
+++ b/backend/src/test/java/org/apache/iotdb/admin/controller/ConnectionControllerTest.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.controller;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.Rollback;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.RequestBuilder;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.context.WebApplicationContext;
+
+import java.net.InetAddress;
+import java.util.Calendar;
+
+@SpringBootTest
+class ConnectionControllerTest {
+
+    private MockMvc mvc;
+
+    @Autowired
+    private WebApplicationContext wac;
+
+    private String token = getToken();
+
+    @Transactional
+    @Rollback
+    @Test
+    void saveOrUpdateConnection() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .post("http://127.0.0.1:8080/api/servers")
+            .contextPath("/api")
+            .content("{\n" +
+                "  \"alias\": \"tttt\",\n" +
+                "  \"host\": \"localhost\",\n" +
+                "  \"password\": \"root\",\n" +
+                "  \"port\": 6667,\n" +
+                "  \"userId\": 1,\n" +
+                "  \"username\": \"root\"\n" +
+                "}")
+            .header("Authorization", token)
+            .header("Content-Type", "application/json");
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Transactional
+    @Rollback
+    @Test
+    void deleteConnection() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .delete("http://127.0.0.1:8080/api/servers/1")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Test
+    void getConnection() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Test
+    void getAllConnections() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers")
+            .contextPath("/api")
+            .param("userId", "1")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    private String getToken() {
+        Calendar instance = Calendar.getInstance();
+        try {
+            instance.add(Calendar.HOUR, 24);
+            String token = JWT.create()
+                .withClaim("userId", 1)
+                .withClaim("name", "root")
+                .withExpiresAt(instance.getTime())
+                .sign(Algorithm.HMAC256("IOTDB:" + InetAddress.getLocalHost().getHostAddress()));
+            return token;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/backend/src/test/java/org/apache/iotdb/admin/controller/IotDBControllerTest.java b/backend/src/test/java/org/apache/iotdb/admin/controller/IotDBControllerTest.java
new file mode 100644
index 0000000..d724a47
--- /dev/null
+++ b/backend/src/test/java/org/apache/iotdb/admin/controller/IotDBControllerTest.java
@@ -0,0 +1,380 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.admin.controller;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.RequestBuilder;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import java.net.InetAddress;
+import java.util.Calendar;
+
+@SpringBootTest
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+class IotDBControllerTest {
+
+    private MockMvc mvc;
+    @Autowired
+    private WebApplicationContext wac;
+
+
+    private String token = getToken();
+
+    private String getToken() {
+        Calendar instance = Calendar.getInstance();
+        try {
+            instance.add(Calendar.HOUR, 24);
+            String token = JWT.create()
+                .withClaim("userId", 1)
+                .withClaim("name", "root")
+                .withExpiresAt(instance.getTime())
+                .sign(Algorithm.HMAC256("IOTDB:" + InetAddress.getLocalHost().getHostAddress()));
+            return token;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    @Order(1)
+    @Test
+    void saveStorageGroup() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .post("http://127.0.0.1:8080/api/servers/1/storageGroups")
+            .contextPath("/api")
+            .content("{\n" +
+                "  \"description\": \"a group\",\n" +
+                "  \"groupName\": \"group1\",\n" +
+                "  \"ttl\": 1,\n" +
+                "  \"ttlUnit\": \"day\"\n" +
+                "}")
+            .header("Authorization", token)
+            .header("Content-Type", "application/json");
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+        request = MockMvcRequestBuilders
+            .post("http://127.0.0.1:8080/api/servers/1/storageGroups")
+            .contextPath("/api")
+            .content("{\n" +
+                "  \"description\": \"a group2\",\n" +
+                "  \"groupName\": \"group2\",\n" +
+                "  \"ttl\": 2,\n" +
+                "  \"ttlUnit\": \"day\"\n" +
+                "}")
+            .header("Authorization", token)
+            .header("Content-Type", "application/json");
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(2)
+    @Test
+    void getAllStorageGroupsInfo() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1/storageGroups/info")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(3)
+    @Test
+    void getAllStorageGroups() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1/storageGroups")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(4)
+    @Test
+    void getStorageGroup() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1/storageGroups/group1")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(5)
+    @Test
+    void deleteStorageGroup() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .delete("http://127.0.0.1:8080/api/servers/1/storageGroups/group2")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(6)
+    @Test
+    void saveOrUpdateDevice() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .post("http://127.0.0.1:8080/api/servers/1/storageGroups/group1/devices")
+            .contextPath("/api")
+            .content("{\n" +
+                "  \"description\": \"a device1\",\n" +
+                "  \"deviceDTOList\": [\n" +
+                "    {\n" +
+                "      \"dataType\": \"INT64\",\n" +
+                "      \"description\": \"a dev1\",\n" +
+                "      \"encoding\": \"PLAIN\",\n" +
+                "      \"timeseries\": \"s1\"\n" +
+                "    }\n" +
+                "  ],\n" +
+                "  \"deviceName\": \"dev1\"\n" +
+                "}")
+            .header("Authorization", token)
+            .header("Content-Type", "application/json");
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+        request = MockMvcRequestBuilders
+            .post("http://127.0.0.1:8080/api/servers/1/storageGroups/group1/devices")
+            .contextPath("/api")
+            .content("{\n" +
+                "  \"description\": \"a device1\",\n" +
+                "  \"deviceDTOList\": [\n" +
+                "    {\n" +
+                "      \"dataType\": \"INT64\",\n" +
+                "      \"description\": \"a dev1\",\n" +
+                "      \"encoding\": \"PLAIN\",\n" +
+                "      \"timeseries\": \"s1\"\n" +
+                "    }\n" +
+                "  ],\n" +
+                "  \"deviceName\": \"dev2\"\n" +
+                "}")
+            .header("Authorization", token)
+            .header("Content-Type", "application/json");
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(7)
+    @Test
+    void getDeviceInfo() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1/storageGroups/group1/devices/dev1")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(8)
+    @Test
+    void getDevicesInfoByGroupName() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1/storageGroups/group1/devices/info")
+            .param("pageSize", "10")
+            .param("pageNum", "1")
+            .param("keyword", "d")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(9)
+    @Test
+    void getDevicesByGroupName() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1/storageGroups/group1/devices")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(10)
+    @Test
+    void deleteDevice() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .delete("http://127.0.0.1:8080/api/servers/1/storageGroups/group1/devices/dev2")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(11)
+    @Test
+    void getMeasurementsByDeviceName() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1/storageGroups/group1/devices/dev1/info")
+            .param("pageSize", "10")
+            .param("pageNum", "1")
+            .param("keyword", "s")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(12)
+    @Test
+    void getMeasurementInfo() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1/storageGroups/group1/devices/dev1")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(13)
+    @Test
+    void getTimeseries() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1/storageGroups/group1/devices/dev1/timeseries")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(14)
+    @Test
+    void deleteTimeseries() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .delete("http://127.0.0.1:8080/api/servers/1/storageGroups/group1/devices/dev1/timeseries/s1")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(15)
+    @Test
+    void setIotDBUser() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .post("http://127.0.0.1:8080/api/servers/1/users")
+            .contextPath("/api")
+            .content("{\n" +
+                "  \"password\": \"1234\",\n" +
+                "  \"userName\": \"lisi\"\n" +
+                "}")
+            .header("Authorization", token)
+            .header("Content-Type", "application/json");
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(16)
+    @Test
+    void getIotDBUserList() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1/users")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(17)
+    @Test
+    void setUserPrivileges() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .post("http://127.0.0.1:8080/api/servers/1/users/lisi")
+            .contextPath("/api")
+            .content("{\n" +
+                "  \"cancelPrivileges\": [],\n" +
+                "  \"delDevicePaths\": [],\n" +
+                "  \"delGroupPaths\": [],\n" +
+                "  \"delTimeseriesPaths\": [],\n" +
+                "  \"devicePaths\": [],\n" +
+                "  \"groupPaths\": [\n" +
+                "    \"group1\"\n" +
+                "  ],\n" +
+                "  \"privileges\": [\n" +
+                "    \"CREATE_TIMESERIES\"\n" +
+                "  ],\n" +
+                "  \"timeseriesPaths\": [],\n" +
+                "  \"type\": 1\n" +
+                "}")
+            .header("Authorization", token)
+            .header("Content-Type", "application/json");
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(18)
+    @Test
+    void getIotDBUser() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .get("http://127.0.0.1:8080/api/servers/1/users/lisi")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(19)
+    @Test
+    void updatePassword() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .post("http://127.0.0.1:8080/api/servers/1/users/pwd")
+            .contextPath("/api")
+            .content("{\n" +
+                "  \"password\": \"2222\",\n" +
+                "  \"userName\": \"lisi\"\n" +
+                "}")
+            .header("Authorization", token)
+            .header("Content-Type", "application/json");
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(20)
+    @Test
+    void deleteIotDBUser() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .delete("http://127.0.0.1:8080/api/servers/1/users/lisi")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @Order(21)
+    @Test
+    void deleteStorageGroup2() throws Exception {
+        mvc = MockMvcBuilders.webAppContextSetup(wac).build();
+        RequestBuilder request = MockMvcRequestBuilders
+            .delete("http://127.0.0.1:8080/api/servers/1/storageGroups/group1")
+            .contextPath("/api")
+            .header("Authorization", token);
+        mvc.perform(request).andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+}
\ No newline at end of file
diff --git a/backend/src/test/java/org/apache/iotdb/admin/controller/QueryControllerTest.java b/backend/src/test/java/org/apache/iotdb/admin/controller/QueryControllerTest.java
new file mode 100644
index 0000000..cc06ff8
--- /dev/null
+++ b/backend/src/test/java/org/apache/iotdb/admin/controller/QueryControllerTest.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
... 179 lines suppressed ...