summaryrefslogtreecommitdiff
path: root/UI source code/dns-dev-2.0/dns-common
diff options
context:
space:
mode:
Diffstat (limited to 'UI source code/dns-dev-2.0/dns-common')
-rw-r--r--UI source code/dns-dev-2.0/dns-common/pom.xml26
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/AnonymousAccess.java30
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/DataPermission.java47
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Limit.java50
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Query.java87
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousDeleteMapping.java91
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousGetMapping.java90
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPatchMapping.java91
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPostMapping.java91
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPutMapping.java91
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitAspect.java99
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitType.java27
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseDTO.java40
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseEntity.java85
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseMapper.java50
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/AuditorConfig.java45
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElAdminProperties.java37
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElPermissionConfig.java37
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/FileProperties.java60
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RedisConfig.java217
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RsaProperties.java38
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/SwaggerConfig.java148
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadConfigurationException.java98
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadRequestException.java35
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityExistException.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityNotFoundException.java31
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/ApiError.java49
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/GlobalExceptionHandler.java109
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CacheKey.java58
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CallBack.java43
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CloseUtil.java47
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/Constant.java62
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/DateUtil.java160
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ElAdminConstant.java70
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/EncryptUtils.java100
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/FileUtil.java356
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/PageUtil.java63
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/QueryHelp.java208
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RedisUtils.java708
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RequestHolder.java33
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RsaUtils.java198
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SecurityUtils.java95
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SpringContextHolder.java145
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/StringUtils.java264
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ThrowableUtil.java37
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/TranslatorUtil.java66
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ValidationUtil.java45
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeBiEnum.java50
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeEnum.java46
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/DataScopeEnum.java53
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/RequestMethodEnum.java74
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/PageUtils.java145
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/Query.java64
-rw-r--r--UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/R.java40
54 files changed, 5160 insertions, 0 deletions
diff --git a/UI source code/dns-dev-2.0/dns-common/pom.xml b/UI source code/dns-dev-2.0/dns-common/pom.xml
new file mode 100644
index 0000000..33734bb
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/pom.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>dns</artifactId>
+ <groupId>com.example</groupId>
+ <version>2.6</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <properties>
+ <hutool.version>5.3.4</hutool.version>
+ </properties>
+
+ <artifactId>dns-common</artifactId>
+ <name>dns-common</name>
+
+ <dependencies>
+ <!--工具包-->
+ <dependency>
+ <groupId>cn.hutool</groupId>
+ <artifactId>hutool-all</artifactId>
+ <version>${hutool.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/AnonymousAccess.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/AnonymousAccess.java
new file mode 100644
index 0000000..9cffb51
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/AnonymousAccess.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * @author jacky
+ * 用于标记匿名访问方法
+ */
+@Inherited
+@Documented
+@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AnonymousAccess {
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/DataPermission.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/DataPermission.java
new file mode 100644
index 0000000..7fa3e3f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/DataPermission.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * <p>
+ * 用于判断是否过滤数据权限
+ * 1、如果没有用到 @OneToOne 这种关联关系,只需要填写 fieldName [参考:DeptQueryCriteria.class]
+ * 2、如果用到了 @OneToOne ,fieldName 和 joinName 都需要填写,拿UserQueryCriteria.class举例:
+ * 应该是 @DataPermission(joinName = "dept", fieldName = "id")
+ * </p>
+ *
+ * @website https://el-admin.vip
+ * 2020-05-07
+ **/
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DataPermission {
+
+ /**
+ * Entity 中的字段名称
+ */
+ String fieldName() default "";
+
+ /**
+ * Entity 中与部门关联的字段名称
+ */
+ String joinName() default "";
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Limit.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Limit.java
new file mode 100644
index 0000000..ee285de
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Limit.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.annotation;
+
+import com.example.aspect.LimitType;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author jacky
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Limit {
+
+ // 资源名称,用于描述接口功能
+ String name() default "";
+
+ // 资源 key
+ String key() default "";
+
+ // key prefix
+ String prefix() default "";
+
+ // 时间的,单位秒
+ int period();
+
+ // 限制访问次数
+ int count();
+
+ // 限制类型
+ LimitType limitType() default LimitType.CUSTOMER;
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Query.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Query.java
new file mode 100644
index 0000000..e21d60b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/Query.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Query {
+
+ // Dong ZhaoYang 2017/8/7 基本对象的属性名
+ String propName() default "";
+ // Dong ZhaoYang 2017/8/7 查询方式
+ Type type() default Type.EQUAL;
+
+ /**
+ * 连接查询的属性名,如User类中的dept
+ */
+ String joinName() default "";
+
+ /**
+ * 默认左连接
+ */
+ Join join() default Join.LEFT;
+
+ /**
+ * 多字段模糊搜索,仅支持String类型字段,多个用逗号隔开, 如@Query(blurry = "email,username")
+ */
+ String blurry() default "";
+
+ enum Type {
+ // jie 2019/6/4 相等
+ EQUAL
+ // Dong ZhaoYang 2017/8/7 大于等于
+ , GREATER_THAN
+ // Dong ZhaoYang 2017/8/7 小于等于
+ , LESS_THAN
+ // Dong ZhaoYang 2017/8/7 中模糊查询
+ , INNER_LIKE
+ // Dong ZhaoYang 2017/8/7 左模糊查询
+ , LEFT_LIKE
+ // Dong ZhaoYang 2017/8/7 右模糊查询
+ , RIGHT_LIKE
+ // Dong ZhaoYang 2017/8/7 小于
+ , LESS_THAN_NQ
+ // jie 2019/6/4 包含
+ , IN
+ // 不包含
+ , NOT_IN
+ // 不等于
+ ,NOT_EQUAL
+ // between
+ ,BETWEEN
+ // 不为空
+ ,NOT_NULL
+ // 为空
+ ,IS_NULL
+ }
+
+ /**
+ *
+ * 适用于简单连接查询,复杂的请自定义该注解,或者使用sql查询
+ */
+ enum Join {
+ /** jie 2019-6-4 13:18:30 */
+ LEFT, RIGHT, INNER
+ }
+
+}
+
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousDeleteMapping.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousDeleteMapping.java
new file mode 100644
index 0000000..10fbef4
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousDeleteMapping.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed 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 com.example.annotation.rest;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.example.annotation.AnonymousAccess;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Annotation for mapping HTTP {@code DELETE} requests onto specific handler
+ * methods.
+ * 支持匿名访问 DeleteMapping
+ *
+ * @author liaojinlong
+ * @see AnonymousGetMapping
+ * @see AnonymousPostMapping
+ * @see AnonymousPutMapping
+ * @see AnonymousPatchMapping
+ * @see RequestMapping
+ */
+@AnonymousAccess
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@RequestMapping(method = RequestMethod.DELETE)
+public @interface AnonymousDeleteMapping {
+
+ /**
+ * Alias for {@link RequestMapping#name}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String name() default "";
+
+ /**
+ * Alias for {@link RequestMapping#value}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] value() default {};
+
+ /**
+ * Alias for {@link RequestMapping#path}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] path() default {};
+
+ /**
+ * Alias for {@link RequestMapping#params}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] params() default {};
+
+ /**
+ * Alias for {@link RequestMapping#headers}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] headers() default {};
+
+ /**
+ * Alias for {@link RequestMapping#consumes}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] consumes() default {};
+
+ /**
+ * Alias for {@link RequestMapping#produces}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] produces() default {};
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousGetMapping.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousGetMapping.java
new file mode 100644
index 0000000..85d6a78
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousGetMapping.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed 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 com.example.annotation.rest;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.example.annotation.AnonymousAccess;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Annotation for mapping HTTP {@code GET} requests onto specific handler
+ * methods.
+ * <p>
+ * 支持匿名访问 GetMapping
+ *
+ * @author liaojinlong
+ * @see RequestMapping
+ */
+@AnonymousAccess
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@RequestMapping(method = RequestMethod.GET)
+public @interface AnonymousGetMapping {
+
+ /**
+ * Alias for {@link RequestMapping#name}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String name() default "";
+
+ /**
+ * Alias for {@link RequestMapping#value}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] value() default {};
+
+ /**
+ * Alias for {@link RequestMapping#path}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] path() default {};
+
+ /**
+ * Alias for {@link RequestMapping#params}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] params() default {};
+
+ /**
+ * Alias for {@link RequestMapping#headers}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] headers() default {};
+
+ /**
+ * Alias for {@link RequestMapping#consumes}.
+ *
+ * @since 4.3.5
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] consumes() default {};
+
+ /**
+ * Alias for {@link RequestMapping#produces}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] produces() default {};
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPatchMapping.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPatchMapping.java
new file mode 100644
index 0000000..3281a3b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPatchMapping.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed 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 com.example.annotation.rest;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.example.annotation.AnonymousAccess;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Annotation for mapping HTTP {@code PATCH} requests onto specific handler
+ * methods.
+ * * 支持匿名访问 PatchMapping
+ *
+ * @author liaojinlong
+ * @see AnonymousGetMapping
+ * @see AnonymousPostMapping
+ * @see AnonymousPutMapping
+ * @see AnonymousDeleteMapping
+ * @see RequestMapping
+ */
+@AnonymousAccess
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@RequestMapping(method = RequestMethod.PATCH)
+public @interface AnonymousPatchMapping {
+
+ /**
+ * Alias for {@link RequestMapping#name}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String name() default "";
+
+ /**
+ * Alias for {@link RequestMapping#value}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] value() default {};
+
+ /**
+ * Alias for {@link RequestMapping#path}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] path() default {};
+
+ /**
+ * Alias for {@link RequestMapping#params}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] params() default {};
+
+ /**
+ * Alias for {@link RequestMapping#headers}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] headers() default {};
+
+ /**
+ * Alias for {@link RequestMapping#consumes}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] consumes() default {};
+
+ /**
+ * Alias for {@link RequestMapping#produces}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] produces() default {};
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPostMapping.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPostMapping.java
new file mode 100644
index 0000000..977de6c
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPostMapping.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed 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 com.example.annotation.rest;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.example.annotation.AnonymousAccess;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Annotation for mapping HTTP {@code POST} requests onto specific handler
+ * methods.
+ * 支持匿名访问 PostMapping
+ *
+ * @author liaojinlong
+ * @see AnonymousGetMapping
+ * @see AnonymousPostMapping
+ * @see AnonymousPutMapping
+ * @see AnonymousDeleteMapping
+ * @see RequestMapping
+ */
+@AnonymousAccess
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@RequestMapping(method = RequestMethod.POST)
+public @interface AnonymousPostMapping {
+
+ /**
+ * Alias for {@link RequestMapping#name}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String name() default "";
+
+ /**
+ * Alias for {@link RequestMapping#value}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] value() default {};
+
+ /**
+ * Alias for {@link RequestMapping#path}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] path() default {};
+
+ /**
+ * Alias for {@link RequestMapping#params}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] params() default {};
+
+ /**
+ * Alias for {@link RequestMapping#headers}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] headers() default {};
+
+ /**
+ * Alias for {@link RequestMapping#consumes}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] consumes() default {};
+
+ /**
+ * Alias for {@link RequestMapping#produces}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] produces() default {};
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPutMapping.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPutMapping.java
new file mode 100644
index 0000000..6fc00b2
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/annotation/rest/AnonymousPutMapping.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed 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 com.example.annotation.rest;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.example.annotation.AnonymousAccess;
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Annotation for mapping HTTP {@code PUT} requests onto specific handler
+ * methods.
+ * * 支持匿名访问 PutMapping
+ *
+ * @author liaojinlong
+ * @see AnonymousGetMapping
+ * @see AnonymousPostMapping
+ * @see AnonymousPutMapping
+ * @see AnonymousDeleteMapping
+ * @see RequestMapping
+ */
+@AnonymousAccess
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@RequestMapping(method = RequestMethod.PUT)
+public @interface AnonymousPutMapping {
+
+ /**
+ * Alias for {@link RequestMapping#name}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String name() default "";
+
+ /**
+ * Alias for {@link RequestMapping#value}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] value() default {};
+
+ /**
+ * Alias for {@link RequestMapping#path}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] path() default {};
+
+ /**
+ * Alias for {@link RequestMapping#params}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] params() default {};
+
+ /**
+ * Alias for {@link RequestMapping#headers}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] headers() default {};
+
+ /**
+ * Alias for {@link RequestMapping#consumes}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] consumes() default {};
+
+ /**
+ * Alias for {@link RequestMapping#produces}.
+ */
+ @AliasFor(annotation = RequestMapping.class)
+ String[] produces() default {};
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitAspect.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitAspect.java
new file mode 100644
index 0000000..1e1856d
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitAspect.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.aspect;
+
+import com.google.common.collect.ImmutableList;
+import com.example.annotation.Limit;
+import com.example.exception.BadRequestException;
+import com.example.utils.RequestHolder;
+import com.example.utils.StringUtils;
+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.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+import org.springframework.data.redis.core.script.RedisScript;
+import org.springframework.stereotype.Component;
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Method;
+
+/**
+ * @author /
+ */
+@Aspect
+@Component
+public class LimitAspect {
+
+ private final RedisTemplate<Object,Object> redisTemplate;
+ private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class);
+
+ public LimitAspect(RedisTemplate<Object,Object> redisTemplate) {
+ this.redisTemplate = redisTemplate;
+ }
+
+ @Pointcut("@annotation(com.example.annotation.Limit)")
+ public void pointcut() {
+ }
+
+ @Around("pointcut()")
+ public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
+ HttpServletRequest request = RequestHolder.getHttpServletRequest();
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ Method signatureMethod = signature.getMethod();
+ Limit limit = signatureMethod.getAnnotation(Limit.class);
+ LimitType limitType = limit.limitType();
+ String key = limit.key();
+ if (StringUtils.isEmpty(key)) {
+ if (limitType == LimitType.IP) {
+ key = StringUtils.getIp(request);
+ } else {
+ key = signatureMethod.getName();
+ }
+ }
+
+ ImmutableList<Object> keys = ImmutableList.of(StringUtils.join(limit.prefix(), "_", key, "_", request.getRequestURI().replace("/","_")));
+
+ String luaScript = buildLuaScript();
+ RedisScript<Number> redisScript = new DefaultRedisScript<>(luaScript, Number.class);
+ Number count = redisTemplate.execute(redisScript, keys, limit.count(), limit.period());
+ if (null != count && count.intValue() <= limit.count()) {
+ logger.info("第{}次访问key为 {},描述为 [{}] 的接口", count, keys, limit.name());
+ return joinPoint.proceed();
+ } else {
+ throw new BadRequestException("访问次数受限制");
+ }
+ }
+
+ /**
+ * 限流脚本
+ */
+ private String buildLuaScript() {
+ return "local c" +
+ "\nc = redis.call('get',KEYS[1])" +
+ "\nif c and tonumber(c) > tonumber(ARGV[1]) then" +
+ "\nreturn c;" +
+ "\nend" +
+ "\nc = redis.call('incr',KEYS[1])" +
+ "\nif tonumber(c) == 1 then" +
+ "\nredis.call('expire',KEYS[1],ARGV[2])" +
+ "\nend" +
+ "\nreturn c;";
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitType.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitType.java
new file mode 100644
index 0000000..0a6deb6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/aspect/LimitType.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.aspect;
+
+/**
+ * 限流枚举
+ * @author /
+ */
+public enum LimitType {
+ // 默认
+ CUSTOMER,
+ // by ip addr
+ IP
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseDTO.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseDTO.java
new file mode 100644
index 0000000..7802007
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseDTO.java
@@ -0,0 +1,40 @@
+package com.example.base;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.sql.Timestamp;
+
+/**
+ *
+ * 2019年10月24日20:48:53
+ */
+@Getter
+@Setter
+public class BaseDTO implements Serializable {
+
+ private String createBy;
+
+ private String updateBy;
+
+ private Timestamp createTime;
+
+ private Timestamp updateTime;
+
+ @Override
+ public String toString() {
+ ToStringBuilder builder = new ToStringBuilder(this);
+ Field[] fields = this.getClass().getDeclaredFields();
+ try {
+ for (Field f : fields) {
+ f.setAccessible(true);
+ builder.append(f.getName(), f.get(this)).append("\n");
+ }
+ } catch (Exception e) {
+ builder.append("toString builder encounter an error");
+ }
+ return builder.toString();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseEntity.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseEntity.java
new file mode 100644
index 0000000..ba31ddf
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseEntity.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.base;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.hibernate.annotations.CreationTimestamp;
+import org.hibernate.annotations.UpdateTimestamp;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+import javax.persistence.Column;
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.sql.Timestamp;
+
+/**
+ * 通用字段, is_del 根据需求自行添加
+ *
+ * @Date 2019年10月24日20:46:32
+ */
+@Getter
+@Setter
+@MappedSuperclass
+@EntityListeners(AuditingEntityListener.class)
+public class BaseEntity implements Serializable {
+
+ @CreatedBy
+ @Column(name = "create_by", updatable = false)
+ @ApiModelProperty(value = "创建人", hidden = true)
+ private String createBy;
+
+ @LastModifiedBy
+ @Column(name = "update_by")
+ @ApiModelProperty(value = "更新人", hidden = true)
+ private String updateBy;
+
+ @CreationTimestamp
+ @Column(name = "create_time", updatable = false)
+ @ApiModelProperty(value = "创建时间", hidden = true)
+ private Timestamp createTime;
+
+ @UpdateTimestamp
+ @Column(name = "update_time")
+ @ApiModelProperty(value = "更新时间", hidden = true)
+ private Timestamp updateTime;
+
+ /* 分组校验 */
+ public @interface Create {}
+
+ /* 分组校验 */
+ public @interface Update {}
+
+ @Override
+ public String toString() {
+ ToStringBuilder builder = new ToStringBuilder(this);
+ Field[] fields = this.getClass().getDeclaredFields();
+ try {
+ for (Field f : fields) {
+ f.setAccessible(true);
+ builder.append(f.getName(), f.get(this)).append("\n");
+ }
+ } catch (Exception e) {
+ builder.append("toString builder encounter an error");
+ }
+ return builder.toString();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseMapper.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseMapper.java
new file mode 100644
index 0000000..1c2d38a
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/base/BaseMapper.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.base;
+
+import java.util.List;
+
+
+public interface BaseMapper<D, E> {
+
+ /**
+ * DTO转Entity
+ * @param dto /
+ * @return /
+ */
+ E toEntity(D dto);
+
+ /**
+ * Entity转DTO
+ * @param entity /
+ * @return /
+ */
+ D toDto(E entity);
+
+ /**
+ * DTO集合转Entity集合
+ * @param dtoList /
+ * @return /
+ */
+ List <E> toEntity(List<D> dtoList);
+
+ /**
+ * Entity集合转DTO集合
+ * @param entityList /
+ * @return /
+ */
+ List <D> toDto(List<E> entityList);
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/AuditorConfig.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/AuditorConfig.java
new file mode 100644
index 0000000..7d1dcbe
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/AuditorConfig.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.config;
+
+import com.example.utils.SecurityUtils;
+import org.springframework.data.domain.AuditorAware;
+import org.springframework.stereotype.Component;
+import java.util.Optional;
+
+/**
+ * @description : 设置审计
+ * @author : Dong ZhaoYang
+ * : 2019/10/28
+ */
+@Component("auditorAware")
+public class AuditorConfig implements AuditorAware<String> {
+
+ /**
+ * 返回操作员标志信息
+ *
+ * @return /
+ */
+ @Override
+ public Optional<String> getCurrentAuditor() {
+ try {
+ // 这里应根据实际业务情况获取具体信息
+ return Optional.of(SecurityUtils.getCurrentUsername());
+ }catch (Exception ignored){}
+ // 用户定时任务,或者无Token调用的情况
+ return Optional.of("System");
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElAdminProperties.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElAdminProperties.java
new file mode 100644
index 0000000..b7670b3
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElAdminProperties.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * @description
+ * 2021-11-22
+ **/
+@Data
+@Component
+public class ElAdminProperties {
+
+ public static Boolean ipLocal;
+
+ @Value("${ip.local-parsing}")
+ public void setIpLocal(Boolean ipLocal) {
+ ElAdminProperties.ipLocal = ipLocal;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElPermissionConfig.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElPermissionConfig.java
new file mode 100644
index 0000000..7b7c1e7
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/ElPermissionConfig.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.config;
+
+import com.example.utils.SecurityUtils;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.stereotype.Service;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ *
+ */
+@Service(value = "el")
+public class ElPermissionConfig {
+
+ public Boolean check(String ...permissions){
+ // 获取当前用户的所有权限
+ List<String> elPermissions = SecurityUtils.getCurrentUser().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
+ // 判断当前用户的所有权限是否包含接口上定义的权限
+ return elPermissions.contains("admin") || Arrays.stream(permissions).anyMatch(elPermissions::contains);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/FileProperties.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/FileProperties.java
new file mode 100644
index 0000000..a1c3aff
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/FileProperties.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.config;
+
+import lombok.Data;
+import com.example.utils.ElAdminConstant;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ *
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "file")
+public class FileProperties {
+
+ /** 文件大小限制 */
+ private Long maxSize;
+
+ /** 头像大小限制 */
+ private Long avatarMaxSize;
+
+ private ElPath mac;
+
+ private ElPath linux;
+
+ private ElPath windows;
+
+ public ElPath getPath(){
+ String os = System.getProperty("os.name");
+ if(os.toLowerCase().startsWith(ElAdminConstant.WIN)) {
+ return windows;
+ } else if(os.toLowerCase().startsWith(ElAdminConstant.MAC)){
+ return mac;
+ }
+ return linux;
+ }
+
+ @Data
+ public static class ElPath{
+
+ private String path;
+
+ private String avatar;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RedisConfig.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RedisConfig.java
new file mode 100644
index 0000000..d482e83
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RedisConfig.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.config;
+
+import cn.hutool.core.lang.Assert;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.parser.ParserConfig;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cache.Cache;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.interceptor.CacheErrorHandler;
+import org.springframework.cache.interceptor.KeyGenerator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import reactor.util.annotation.Nullable;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ *
+ * 2018-11-24
+ */
+@Slf4j
+@Configuration
+@EnableCaching
+@ConditionalOnClass(RedisOperations.class)
+@EnableConfigurationProperties(RedisProperties.class)
+public class RedisConfig extends CachingConfigurerSupport {
+
+ /**
+ * 设置 redis 数据默认过期时间,默认2小时
+ * 设置@cacheable 序列化方式
+ */
+ @Bean
+ public RedisCacheConfiguration redisCacheConfiguration(){
+ FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
+ RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
+ configuration = configuration.serializeValuesWith(RedisSerializationContext.
+ SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(2));
+ return configuration;
+ }
+
+ @SuppressWarnings("all")
+ @Bean(name = "redisTemplate")
+ @ConditionalOnMissingBean(name = "redisTemplate")
+ public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+ RedisTemplate<Object, Object> template = new RedisTemplate<>();
+ //序列化
+ FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
+ // value值的序列化采用fastJsonRedisSerializer
+ template.setValueSerializer(fastJsonRedisSerializer);
+ template.setHashValueSerializer(fastJsonRedisSerializer);
+ // 全局开启AutoType,这里方便开发,使用全局的方式
+ ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
+ // 建议使用这种方式,小范围指定白名单
+ // ParserConfig.getGlobalInstance().addAccept("com.example.domain");
+ // key的序列化采用StringRedisSerializer
+ template.setKeySerializer(new StringRedisSerializer());
+ template.setHashKeySerializer(new StringRedisSerializer());
+ template.setConnectionFactory(redisConnectionFactory);
+ return template;
+ }
+
+ /**
+ * 自定义缓存key生成策略,默认将使用该策略
+ */
+ @Bean
+ @Override
+ public KeyGenerator keyGenerator() {
+ return (target, method, params) -> {
+ Map<String,Object> container = new HashMap<>(4);
+ Class<?> targetClassClass = target.getClass();
+ // 类地址
+ container.put("class",targetClassClass.toGenericString());
+ // 方法名称
+ container.put("methodName",method.getName());
+ // 包名称
+ container.put("package",targetClassClass.getPackage());
+ // 参数列表
+ for (int i = 0; i < params.length; i++) {
+ container.put(String.valueOf(i),params[i]);
+ }
+ // 转为JSON字符串
+ String jsonString = JSON.toJSONString(container);
+ // 做SHA256 Hash计算,得到一个SHA256摘要作为Key
+ return DigestUtils.sha256Hex(jsonString);
+ };
+ }
+
+ @Bean
+ @Override
+ public CacheErrorHandler errorHandler() {
+ // 异常处理,当Redis发生异常时,打印日志,但是程序正常走
+ log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
+ return new CacheErrorHandler() {
+ @Override
+ public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
+ log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
+ }
+
+ @Override
+ public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
+ log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
+ }
+
+ @Override
+ public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
+ log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
+ }
+
+ @Override
+ public void handleCacheClearError(RuntimeException e, Cache cache) {
+ log.error("Redis occur handleCacheClearError:", e);
+ }
+ };
+ }
+
+}
+
+/**
+ * Value 序列化
+ *
+ * @author /
+ * @param <T>
+ */
+ class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
+
+ private final Class<T> clazz;
+
+ FastJsonRedisSerializer(Class<T> clazz) {
+ super();
+ this.clazz = clazz;
+ }
+
+ @Override
+ public byte[] serialize(T t) {
+ if (t == null) {
+ return new byte[0];
+ }
+ return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
+ }
+
+ @Override
+ public T deserialize(byte[] bytes) {
+ if (bytes == null || bytes.length <= 0) {
+ return null;
+ }
+ String str = new String(bytes, StandardCharsets.UTF_8);
+ return JSON.parseObject(str, clazz);
+ }
+
+}
+
+/**
+ * 重写序列化器
+ *
+ * @author /
+ */
+class StringRedisSerializer implements RedisSerializer<Object> {
+
+ private final Charset charset;
+
+ StringRedisSerializer() {
+ this(StandardCharsets.UTF_8);
+ }
+
+ private StringRedisSerializer(Charset charset) {
+ Assert.notNull(charset, "Charset must not be null!");
+ this.charset = charset;
+ }
+
+ @Override
+ public String deserialize(byte[] bytes) {
+ return (bytes == null ? null : new String(bytes, charset));
+ }
+
+ @Override
+ public @Nullable byte[] serialize(Object object) {
+ String string = JSON.toJSONString(object);
+
+ if (org.apache.commons.lang3.StringUtils.isBlank(string)) {
+ return null;
+ }
+ string = string.replace("\"", "");
+ return string.getBytes(charset);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RsaProperties.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RsaProperties.java
new file mode 100644
index 0000000..7490f71
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/RsaProperties.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.config;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * @website https://el-admin.vip
+ * @description
+ * 2020-05-18
+ **/
+@Data
+@Component
+public class RsaProperties {
+
+ public static String privateKey;
+
+ @Value("${rsa.private_key}")
+ public void setPrivateKey(String privateKey) {
+ RsaProperties.privateKey = privateKey;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/SwaggerConfig.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/SwaggerConfig.java
new file mode 100644
index 0000000..7d0b1c6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/config/SwaggerConfig.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.config;
+
+import com.fasterxml.classmate.TypeResolver;
+import com.google.common.base.Predicates;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.data.domain.Pageable;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.schema.AlternateTypeRule;
+import springfox.documentation.schema.AlternateTypeRuleConvention;
+import springfox.documentation.service.*;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+import java.util.ArrayList;
+import java.util.List;
+import static com.google.common.collect.Lists.newArrayList;
+import static springfox.documentation.schema.AlternateTypeRules.newRule;
+
+/**
+ * api页面 /doc.html
+ *
+ * 2018-11-23
+ */
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+
+ @Value("${jwt.header}")
+ private String tokenHeader;
+
+ @Value("${swagger.enabled}")
+ private Boolean enabled;
+
+ @Bean
+ @SuppressWarnings("all")
+ public Docket createRestApi() {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .enable(enabled)
+ .pathMapping("/")
+ .apiInfo(apiInfo())
+ .select()
+ .paths(Predicates.not(PathSelectors.regex("/error.*")))
+ .paths(PathSelectors.any())
+ .build()
+ //添加登陆认证
+ .securitySchemes(securitySchemes())
+ .securityContexts(securityContexts());
+ }
+
+ private ApiInfo apiInfo() {
+ return new ApiInfoBuilder()
+ .description("一个简单且易上手的 Spring boot 后台管理框架")
+ .title("DNS测绘 接口文档")
+ .version("2.6")
+ .build();
+ }
+
+ private List<SecurityScheme> securitySchemes() {
+ //设置请求头信息
+ List<SecurityScheme> securitySchemes = new ArrayList<>();
+ ApiKey apiKey = new ApiKey(tokenHeader, tokenHeader, "header");
+ securitySchemes.add(apiKey);
+ return securitySchemes;
+ }
+
+ private List<SecurityContext> securityContexts() {
+ //设置需要登录认证的路径
+ List<SecurityContext> securityContexts = new ArrayList<>();
+ // ^(?!auth).*$ 表示所有包含auth的接口不需要使用securitySchemes即不需要带token
+ // ^标识开始 ()里是一子表达式 ?!/auth表示匹配不是/auth的位置,匹配上则添加请求头,注意路径已/开头 .表示任意字符 *表示前面的字符匹配多次 $标识结束
+ securityContexts.add(getContextByPath());
+ return securityContexts;
+ }
+
+ private SecurityContext getContextByPath() {
+ return SecurityContext.builder()
+ .securityReferences(defaultAuth())
+ .forPaths(PathSelectors.regex("^(?!/auth).*$"))
+ .build();
+ }
+
+ private List<SecurityReference> defaultAuth() {
+ List<SecurityReference> securityReferences = new ArrayList<>();
+ AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
+ AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
+ authorizationScopes[0] = authorizationScope;
+ securityReferences.add(new SecurityReference(tokenHeader, authorizationScopes));
+ return securityReferences;
+ }
+}
+
+/**
+ * 将Pageable转换展示在swagger中
+ */
+@Configuration
+class SwaggerDataConfig {
+
+ @Bean
+ public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) {
+ return new AlternateTypeRuleConvention() {
+ @Override
+ public int getOrder() {
+ return Ordered.HIGHEST_PRECEDENCE;
+ }
+
+ @Override
+ public List<AlternateTypeRule> rules() {
+ return newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(Page.class)));
+ }
+ };
+ }
+
+ @ApiModel
+ @Data
+ private static class Page {
+ @ApiModelProperty("页码 (0..N)")
+ private Integer page;
+
+ @ApiModelProperty("每页显示的数目")
+ private Integer size;
+
+ @ApiModelProperty("以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc")
+ private List<String> sort;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadConfigurationException.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadConfigurationException.java
new file mode 100644
index 0000000..0ca41ad
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadConfigurationException.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed 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 com.example.exception;
+
+/**
+ * 统一关于错误配置信息 异常
+ *
+ * @author: liaojinlong
+ * : 2020/6/10 18:06
+ */
+public class BadConfigurationException extends RuntimeException {
+ /**
+ * Constructs a new runtime exception with {@code null} as its
+ * detail message. The cause is not initialized, and may subsequently be
+ * initialized by a call to {@link #initCause}.
+ */
+ public BadConfigurationException() {
+ super();
+ }
+
+ /**
+ * Constructs a new runtime exception with the specified detail message.
+ * The cause is not initialized, and may subsequently be initialized by a
+ * call to {@link #initCause}.
+ *
+ * @param message the detail message. The detail message is saved for
+ * later retrieval by the {@link #getMessage()} method.
+ */
+ public BadConfigurationException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new runtime exception with the specified detail message and
+ * cause. <p>Note that the detail message associated with
+ * {@code cause} is <i>not</i> automatically incorporated in
+ * this runtime exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public BadConfigurationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs a new runtime exception with the specified cause and a
+ * detail message of {@code (cause==null ? null : cause.toString())}
+ * (which typically contains the class and detail message of
+ * {@code cause}). This constructor is useful for runtime exceptions
+ * that are little more than wrappers for other throwables.
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public BadConfigurationException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a new runtime exception with the specified detail
+ * message, cause, suppression enabled or disabled, and writable
+ * stack trace enabled or disabled.
+ *
+ * @param message the detail message.
+ * @param cause the cause. (A {@code null} value is permitted,
+ * and indicates that the cause is nonexistent or unknown.)
+ * @param enableSuppression whether or not suppression is enabled
+ * or disabled
+ * @param writableStackTrace whether or not the stack trace should
+ * be writable
+ * @since 1.7
+ */
+ protected BadConfigurationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadRequestException.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadRequestException.java
new file mode 100644
index 0000000..e8c7474
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/BadRequestException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.exception;
+
+import lombok.Getter;
+import org.springframework.http.HttpStatus;
+import static org.springframework.http.HttpStatus.BAD_REQUEST;
+
+@Getter
+public class BadRequestException extends RuntimeException{
+
+ private Integer status = BAD_REQUEST.value();
+
+ public BadRequestException(String msg){
+ super(msg);
+ }
+
+ public BadRequestException(HttpStatus status,String msg){
+ super(msg);
+ this.status = status.value();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityExistException.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityExistException.java
new file mode 100644
index 0000000..5af387f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityExistException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.exception;
+
+import org.springframework.util.StringUtils;
+
+
+public class EntityExistException extends RuntimeException {
+
+ public EntityExistException(Class clazz, String field, String val) {
+ super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val));
+ }
+
+ private static String generateMessage(String entity, String field, String val) {
+ return StringUtils.capitalize(entity)
+ + " with " + field + " "+ val + " existed";
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityNotFoundException.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityNotFoundException.java
new file mode 100644
index 0000000..cdfd771
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/EntityNotFoundException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.exception;
+
+import org.springframework.util.StringUtils;
+
+
+public class EntityNotFoundException extends RuntimeException {
+
+ public EntityNotFoundException(Class clazz, String field, String val) {
+ super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val));
+ }
+
+ private static String generateMessage(String entity, String field, String val) {
+ return StringUtils.capitalize(entity)
+ + " with " + field + " "+ val + " does not exist";
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/ApiError.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/ApiError.java
new file mode 100644
index 0000000..82ec628
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/ApiError.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.exception.handler;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import java.time.LocalDateTime;
+
+
+@Data
+class ApiError {
+
+ private Integer status = 400;
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime timestamp;
+ private String message;
+
+ private ApiError() {
+ timestamp = LocalDateTime.now();
+ }
+
+ public static ApiError error(String message){
+ ApiError apiError = new ApiError();
+ apiError.setMessage(message);
+ return apiError;
+ }
+
+ public static ApiError error(Integer status, String message){
+ ApiError apiError = new ApiError();
+ apiError.setStatus(status);
+ apiError.setMessage(message);
+ return apiError;
+ }
+}
+
+
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/GlobalExceptionHandler.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/GlobalExceptionHandler.java
new file mode 100644
index 0000000..ba044d1
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/exception/handler/GlobalExceptionHandler.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.exception.handler;
+
+import com.example.exception.BadRequestException;
+import com.example.exception.EntityExistException;
+import com.example.exception.EntityNotFoundException;
+import com.example.utils.ThrowableUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import java.util.Objects;
+import static org.springframework.http.HttpStatus.*;
+
+
+@Slf4j
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+ /**
+ * 处理所有不可知的异常
+ */
+ @ExceptionHandler(Throwable.class)
+ public ResponseEntity<ApiError> handleException(Throwable e){
+ // 打印堆栈信息
+ log.error(ThrowableUtil.getStackTrace(e));
+ return buildResponseEntity(ApiError.error(e.getMessage()));
+ }
+
+ /**
+ * BadCredentialsException
+ */
+ @ExceptionHandler(BadCredentialsException.class)
+ public ResponseEntity<ApiError> badCredentialsException(BadCredentialsException e){
+ // 打印堆栈信息
+ String message = "坏的凭证".equals(e.getMessage()) ? "用户名或密码不正确" : e.getMessage();
+ log.error(message);
+ return buildResponseEntity(ApiError.error(message));
+ }
+
+ /**
+ * 处理自定义异常
+ */
+ @ExceptionHandler(value = BadRequestException.class)
+ public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
+ // 打印堆栈信息
+ log.error(ThrowableUtil.getStackTrace(e));
+ return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage()));
+ }
+
+ /**
+ * 处理 EntityExist
+ */
+ @ExceptionHandler(value = EntityExistException.class)
+ public ResponseEntity<ApiError> entityExistException(EntityExistException e) {
+ // 打印堆栈信息
+ log.error(ThrowableUtil.getStackTrace(e));
+ return buildResponseEntity(ApiError.error(e.getMessage()));
+ }
+
+ /**
+ * 处理 EntityNotFound
+ */
+ @ExceptionHandler(value = EntityNotFoundException.class)
+ public ResponseEntity<ApiError> entityNotFoundException(EntityNotFoundException e) {
+ // 打印堆栈信息
+ log.error(ThrowableUtil.getStackTrace(e));
+ return buildResponseEntity(ApiError.error(NOT_FOUND.value(),e.getMessage()));
+ }
+
+ /**
+ * 处理所有接口数据验证异常
+ */
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public ResponseEntity<ApiError> handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
+ // 打印堆栈信息
+ log.error(ThrowableUtil.getStackTrace(e));
+ String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
+ String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
+ String msg = "不能为空";
+ if(msg.equals(message)){
+ message = str[1] + ":" + message;
+ }
+ return buildResponseEntity(ApiError.error(message));
+ }
+
+ /**
+ * 统一返回
+ */
+ private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
+ return new ResponseEntity<>(apiError, valueOf(apiError.getStatus()));
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CacheKey.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CacheKey.java
new file mode 100644
index 0000000..8e93877
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CacheKey.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed 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 com.example.utils;
+
+/**
+ * @author: liaojinlong
+ * : 2020/6/11 15:49
+ * @apiNote: 关于缓存的Key集合
+ */
+public interface CacheKey {
+
+ /**
+ * 用户
+ */
+ String USER_ID = "user::id:";
+ /**
+ * 数据
+ */
+ String DATA_USER = "data::user:";
+ /**
+ * 菜单
+ */
+ String MENU_ID = "menu::id:";
+ String MENU_USER = "menu::user:";
+ /**
+ * 角色授权
+ */
+ String ROLE_AUTH = "role::auth:";
+ /**
+ * 角色信息
+ */
+ String ROLE_ID = "role::id:";
+ /**
+ * 部门
+ */
+ String DEPT_ID = "dept::id:";
+ /**
+ * 岗位
+ */
+ String JOB_ID = "job::id:";
+ /**
+ * 数据字典
+ */
+ String DICT_NAME = "dict::name:";
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CallBack.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CallBack.java
new file mode 100644
index 0000000..59a7d0b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CallBack.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed 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 com.example.utils;
+
+/**
+ * @author: liaojinlong
+ * : 2020/6/9 17:02
+ * @since: 1.0
+ * @see {@link SpringContextHolder}
+ * 针对某些初始化方法,在SpringContextHolder 初始化前时,<br>
+ * 可提交一个 提交回调任务。<br>
+ * 在SpringContextHolder 初始化后,进行回调使用
+ */
+
+public interface CallBack {
+ /**
+ * 回调执行方法
+ */
+ void executor();
+
+ /**
+ * 本回调任务名称
+ * @return /
+ */
+ default String getCallBackName() {
+ return Thread.currentThread().getId() + ":" + this.getClass().getName();
+ }
+}
+
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CloseUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CloseUtil.java
new file mode 100644
index 0000000..cd515bc
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/CloseUtil.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import java.io.Closeable;
+
+/**
+ *
+ * @website https://el-admin.vip
+ * @description 用于关闭各种连接,缺啥补啥
+ * 2021-03-05
+ **/
+public class CloseUtil {
+
+ public static void close(Closeable closeable) {
+ if (null != closeable) {
+ try {
+ closeable.close();
+ } catch (Exception e) {
+ // 静默关闭
+ }
+ }
+ }
+
+ public static void close(AutoCloseable closeable) {
+ if (null != closeable) {
+ try {
+ closeable.close();
+ } catch (Exception e) {
+ // 静默关闭
+ }
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/Constant.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/Constant.java
new file mode 100644
index 0000000..402403e
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/Constant.java
@@ -0,0 +1,62 @@
+package com.example.utils;
+
+/**
+ * 常量
+ */
+public class Constant {
+ public static final String DOH = "dns-doh";
+
+ public static final String DO53 = "dns-do53";
+
+ public static final String SERVICE = "service";
+
+ public static final String IP = "ip";
+
+ public static final String PORT = "port";
+
+ public static final Integer NONE = 0;
+
+ public static final Integer OPENRDNS = 1;
+
+ public static final Integer FORWARDER = 2;
+
+ public static final Integer FWDRDNS = 3;
+
+ public static final Integer EGRESSRDNS = 4;
+
+ public static final Integer NONSTANDARD = 5;
+
+ public static final String PORT8443 = "8443";
+
+ public static final String PORT443 = "443";
+
+ public static final String PORT53 = "53";
+
+ public static final String DNSTAG = "dns";
+
+ public static final String DOHTAG = "DNS-DoH";
+
+ public static final String DO53TAG = "DNS-Do53";
+
+ public static final String OPENRDNSTAG = "open-rdns";
+
+ public static final String FORWARDERTAG = "forwarder";
+
+ public static final String FWDRDNSTAG = "fwd/rdns";
+
+ public static final String EGRESSRDNSTAG = "egress-dns";
+
+ public static final String NONSTANDARDTAG = "nonstandard";
+
+ public static final String PROTOC_TCP = "tcp";
+
+ public static final String PROTOC_UDP = "udp";
+
+ public static final String IP_IPV4 = "ipv4";
+
+ public static final String IP_IPV6 = "ipv6";
+
+ public static final String POINT = ".";
+
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/DateUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/DateUtil.java
new file mode 100644
index 0000000..57e9408
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/DateUtil.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2019-2020 the original author or authors.
+ *
+ * Licensed 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 com.example.utils;
+
+import java.time.*;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
+
+/**
+ * @author: liaojinlong
+ * : 2020/6/11 16:28
+ * @apiNote: JDK 8 新日期类 格式化与字符串转换 工具类
+ */
+public class DateUtil {
+
+ public static final DateTimeFormatter DFY_MD_HMS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ public static final DateTimeFormatter DFY_MD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+ /**
+ * LocalDateTime 转时间戳
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static Long getTimeStamp(LocalDateTime localDateTime) {
+ return localDateTime.atZone(ZoneId.systemDefault()).toEpochSecond();
+ }
+
+ /**
+ * 时间戳转LocalDateTime
+ *
+ * @param timeStamp /
+ * @return /
+ */
+ public static LocalDateTime fromTimeStamp(Long timeStamp) {
+ return LocalDateTime.ofEpochSecond(timeStamp, 0, OffsetDateTime.now().getOffset());
+ }
+
+ /**
+ * LocalDateTime 转 Date
+ * Jdk8 后 不推荐使用 {@link Date} Date
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static Date toDate(LocalDateTime localDateTime) {
+ return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
+ }
+
+ /**
+ * LocalDate 转 Date
+ * Jdk8 后 不推荐使用 {@link Date} Date
+ *
+ * @param localDate /
+ * @return /
+ */
+ public static Date toDate(LocalDate localDate) {
+ return toDate(localDate.atTime(LocalTime.now(ZoneId.systemDefault())));
+ }
+
+
+ /**
+ * Date转 LocalDateTime
+ * Jdk8 后 不推荐使用 {@link Date} Date
+ *
+ * @param date /
+ * @return /
+ */
+ public static LocalDateTime toLocalDateTime(Date date) {
+ return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
+ }
+
+ /**
+ * 日期 格式化
+ *
+ * @param localDateTime /
+ * @param patten /
+ * @return /
+ */
+ public static String localDateTimeFormat(LocalDateTime localDateTime, String patten) {
+ DateTimeFormatter df = DateTimeFormatter.ofPattern(patten);
+ return df.format(localDateTime);
+ }
+
+ /**
+ * 日期 格式化
+ *
+ * @param localDateTime /
+ * @param df /
+ * @return /
+ */
+ public static String localDateTimeFormat(LocalDateTime localDateTime, DateTimeFormatter df) {
+ return df.format(localDateTime);
+ }
+
+ /**
+ * 日期格式化 yyyy-MM-dd HH:mm:ss
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static String localDateTimeFormatyMdHms(LocalDateTime localDateTime) {
+ return DFY_MD_HMS.format(localDateTime);
+ }
+
+ /**
+ * 日期格式化 yyyy-MM-dd
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public String localDateTimeFormatyMd(LocalDateTime localDateTime) {
+ return DFY_MD.format(localDateTime);
+ }
+
+ /**
+ * 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static LocalDateTime parseLocalDateTimeFormat(String localDateTime, String pattern) {
+ DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
+ return LocalDateTime.from(dateTimeFormatter.parse(localDateTime));
+ }
+
+ /**
+ * 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static LocalDateTime parseLocalDateTimeFormat(String localDateTime, DateTimeFormatter dateTimeFormatter) {
+ return LocalDateTime.from(dateTimeFormatter.parse(localDateTime));
+ }
+
+ /**
+ * 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd HH:mm:ss
+ *
+ * @param localDateTime /
+ * @return /
+ */
+ public static LocalDateTime parseLocalDateTimeFormatyMdHms(String localDateTime) {
+ return LocalDateTime.from(DFY_MD_HMS.parse(localDateTime));
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ElAdminConstant.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ElAdminConstant.java
new file mode 100644
index 0000000..f46ff3b
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ElAdminConstant.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 常用静态常量
+ *
+ *
+ * 2018-12-26
+ */
+public class ElAdminConstant {
+
+ private ElAdminConstant() {
+ throw new IllegalStateException("Utility class");
+ }
+
+ /**
+ * 用于IP定位转换
+ */
+ public static final String REGION = "内网IP|内网IP";
+ /**
+ * win 系统
+ */
+ public static final String WIN = "win";
+
+ /**
+ * mac 系统
+ */
+ public static final String MAC = "mac";
+
+ public static final List<String> openRdnsLabels = Arrays.asList("DNS", "DNS-Do53", "open-rdns");
+
+ public static final List<String> forwarderLabels = Arrays.asList("DNS", "DNS-Do53", "forwarder");
+
+ public static final List<String> fwdRdnsLabels = Arrays.asList("DNS", "DNS-Do53", "fwd/rdns");
+
+ public static final List<String> egressDnsLabels = Arrays.asList("DNS", "DNS-Do53", "egress-dns");
+
+ public static final List<String> nonstandardLabels = Arrays.asList("DNS", "DNS-Do53", "nonstandard");
+
+ public static final List<String> dnsLabels = Arrays.asList("DNS");
+
+ public static final List<String> dohLabels = Arrays.asList("DNS","DNS-DoH");
+
+ public static final List<String> do53Labels = Arrays.asList(new String[]{"DNS","DNS-Do53"});
+
+ /**
+ * 常用接口
+ */
+ public static class Url {
+ // IP归属地查询
+ public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp?ip=%s&json=true";
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/EncryptUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/EncryptUtils.java
new file mode 100644
index 0000000..6ee5a49
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/EncryptUtils.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESKeySpec;
+import javax.crypto.spec.IvParameterSpec;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 加密
+ *
+ * 2018-11-23
+ */
+
+public class EncryptUtils {
+
+ private static final String STR_PARAM = "Passw0rd";
+
+ private static Cipher cipher;
+
+ private static final IvParameterSpec IV = new IvParameterSpec(STR_PARAM.getBytes(StandardCharsets.UTF_8));
+
+ private static DESKeySpec getDesKeySpec(String source) throws Exception {
+ if (source == null || source.length() == 0){
+ return null;
+ }
+ cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
+ String strKey = "Passw0rd";
+ return new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8));
+ }
+
+ /**
+ * 对称加密
+ */
+ public static String desEncrypt(String source) throws Exception {
+ DESKeySpec desKeySpec = getDesKeySpec(source);
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
+ SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey, IV);
+ return byte2hex(
+ cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase();
+ }
+
+ /**
+ * 对称解密
+ */
+ public static String desDecrypt(String source) throws Exception {
+ byte[] src = hex2byte(source.getBytes(StandardCharsets.UTF_8));
+ DESKeySpec desKeySpec = getDesKeySpec(source);
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
+ SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, IV);
+ byte[] retByte = cipher.doFinal(src);
+ return new String(retByte);
+ }
+
+ private static String byte2hex(byte[] inStr) {
+ String stmp;
+ StringBuilder out = new StringBuilder(inStr.length * 2);
+ for (byte b : inStr) {
+ stmp = Integer.toHexString(b & 0xFF);
+ if (stmp.length() == 1) {
+ // 如果是0至F的单位字符串,则添加0
+ out.append("0").append(stmp);
+ } else {
+ out.append(stmp);
+ }
+ }
+ return out.toString();
+ }
+
+ private static byte[] hex2byte(byte[] b) {
+ int size = 2;
+ if ((b.length % size) != 0){
+ throw new IllegalArgumentException("长度不是偶数");
+ }
+ byte[] b2 = new byte[b.length / 2];
+ for (int n = 0; n < b.length; n += size) {
+ String item = new String(b, n, 2);
+ b2[n / 2] = (byte) Integer.parseInt(item, 16);
+ }
+ return b2;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/FileUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/FileUtil.java
new file mode 100644
index 0000000..dc209a9
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/FileUtil.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.poi.excel.BigExcelWriter;
+import cn.hutool.poi.excel.ExcelUtil;
+import com.example.exception.BadRequestException;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.streaming.SXSSFSheet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.security.MessageDigest;
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * File工具类,扩展 hutool 工具包
+ *
+ *
+ * 2018-12-27
+ */
+public class FileUtil extends cn.hutool.core.io.FileUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(FileUtil.class);
+
+ /**
+ * 系统临时目录
+ * <br>
+ * windows 包含路径分割符,但Linux 不包含,
+ * 在windows \\==\ 前提下,
+ * 为安全起见 同意拼装 路径分割符,
+ * <pre>
+ * java.io.tmpdir
+ * windows : C:\Users/xxx\AppData\Local\Temp\
+ * linux: /temp
+ * </pre>
+ */
+ public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;
+ /**
+ * 定义GB的计算常量
+ */
+ private static final int GB = 1024 * 1024 * 1024;
+ /**
+ * 定义MB的计算常量
+ */
+ private static final int MB = 1024 * 1024;
+ /**
+ * 定义KB的计算常量
+ */
+ private static final int KB = 1024;
+
+ /**
+ * 格式化小数
+ */
+ private static final DecimalFormat DF = new DecimalFormat("0.00");
+
+ public static final String IMAGE = "图片";
+ public static final String TXT = "文档";
+ public static final String MUSIC = "音乐";
+ public static final String VIDEO = "视频";
+ public static final String OTHER = "其他";
+
+
+ /**
+ * MultipartFile转File
+ */
+ public static File toFile(MultipartFile multipartFile) {
+ // 获取文件名
+ String fileName = multipartFile.getOriginalFilename();
+ // 获取文件后缀
+ String prefix = "." + getExtensionName(fileName);
+ File file = null;
+ try {
+ // 用uuid作为文件名,防止生成的临时文件重复
+ file = new File(SYS_TEM_DIR + IdUtil.simpleUUID() + prefix);
+ // MultipartFile to File
+ multipartFile.transferTo(file);
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ return file;
+ }
+
+ /**
+ * 获取文件扩展名,不带 .
+ */
+ public static String getExtensionName(String filename) {
+ if ((filename != null) && (filename.length() > 0)) {
+ int dot = filename.lastIndexOf('.');
+ if ((dot > -1) && (dot < (filename.length() - 1))) {
+ return filename.substring(dot + 1);
+ }
+ }
+ return filename;
+ }
+
+ /**
+ * Java文件操作 获取不带扩展名的文件名
+ */
+ public static String getFileNameNoEx(String filename) {
+ if ((filename != null) && (filename.length() > 0)) {
+ int dot = filename.lastIndexOf('.');
+ if ((dot > -1) && (dot < (filename.length()))) {
+ return filename.substring(0, dot);
+ }
+ }
+ return filename;
+ }
+
+ /**
+ * 文件大小转换
+ */
+ public static String getSize(long size) {
+ String resultSize;
+ if (size / GB >= 1) {
+ //如果当前Byte的值大于等于1GB
+ resultSize = DF.format(size / (float) GB) + "GB ";
+ } else if (size / MB >= 1) {
+ //如果当前Byte的值大于等于1MB
+ resultSize = DF.format(size / (float) MB) + "MB ";
+ } else if (size / KB >= 1) {
+ //如果当前Byte的值大于等于1KB
+ resultSize = DF.format(size / (float) KB) + "KB ";
+ } else {
+ resultSize = size + "B ";
+ }
+ return resultSize;
+ }
+
+ /**
+ * inputStream 转 File
+ */
+ static File inputStreamToFile(InputStream ins, String name){
+ File file = new File(SYS_TEM_DIR + name);
+ if (file.exists()) {
+ return file;
+ }
+ OutputStream os = null;
+ try {
+ os = new FileOutputStream(file);
+ int bytesRead;
+ int len = 8192;
+ byte[] buffer = new byte[len];
+ while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
+ os.write(buffer, 0, bytesRead);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ CloseUtil.close(os);
+ CloseUtil.close(ins);
+ }
+ return file;
+ }
+
+ /**
+ * 将文件名解析成文件的上传路径
+ */
+ public static File upload(MultipartFile file, String filePath) {
+ Date date = new Date();
+ SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
+ String name = getFileNameNoEx(file.getOriginalFilename());
+ String suffix = getExtensionName(file.getOriginalFilename());
+ String nowStr = "-" + format.format(date);
+ try {
+ String fileName = name + nowStr + "." + suffix;
+ String path = filePath + fileName;
+ // getCanonicalFile 可解析正确各种路径
+ File dest = new File(path).getCanonicalFile();
+ // 检测是否存在目录
+ if (!dest.getParentFile().exists()) {
+ if (!dest.getParentFile().mkdirs()) {
+ System.out.println("was not successful.");
+ }
+ }
+ // 文件写入
+ file.transferTo(dest);
+ return dest;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ return null;
+ }
+
+ /**
+ * 导出excel
+ */
+ public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
+ String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
+ File file = new File(tempPath);
+ BigExcelWriter writer = ExcelUtil.getBigWriter(file);
+ // 一次性写出内容,使用默认样式,强制输出标题
+ writer.write(list, true);
+ SXSSFSheet sheet = (SXSSFSheet)writer.getSheet();
+ //上面需要强转SXSSFSheet 不然没有trackAllColumnsForAutoSizing方法
+ sheet.trackAllColumnsForAutoSizing();
+ //列宽自适应
+ writer.autoSizeColumnAll();
+ //response为HttpServletResponse对象
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
+ //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
+ response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
+ ServletOutputStream out = response.getOutputStream();
+ // 终止后删除临时文件
+ file.deleteOnExit();
+ writer.flush(out, true);
+ //此处记得关闭输出Servlet流
+ IoUtil.close(out);
+ }
+
+ public static String getFileType(String type) {
+ String documents = "txt doc pdf ppt pps xlsx xls docx";
+ String music = "mp3 wav wma mpa ram ra aac aif m4a";
+ String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
+ String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
+ if (image.contains(type)) {
+ return IMAGE;
+ } else if (documents.contains(type)) {
+ return TXT;
+ } else if (music.contains(type)) {
+ return MUSIC;
+ } else if (video.contains(type)) {
+ return VIDEO;
+ } else {
+ return OTHER;
+ }
+ }
+
+ public static void checkSize(long maxSize, long size) {
+ // 1M
+ int len = 1024 * 1024;
+ if (size > (maxSize * len)) {
+ throw new BadRequestException("文件超出规定大小:" + maxSize + "MB");
+ }
+ }
+
+ /**
+ * 判断两个文件是否相同
+ */
+ public static boolean check(File file1, File file2) {
+ String img1Md5 = getMd5(file1);
+ String img2Md5 = getMd5(file2);
+ if(img1Md5 != null){
+ return img1Md5.equals(img2Md5);
+ }
+ return false;
+ }
+
+ /**
+ * 判断两个文件是否相同
+ */
+ public static boolean check(String file1Md5, String file2Md5) {
+ return file1Md5.equals(file2Md5);
+ }
+
+ private static byte[] getByte(File file) {
+ // 得到文件长度
+ byte[] b = new byte[(int) file.length()];
+ InputStream in = null;
+ try {
+ in = new FileInputStream(file);
+ try {
+ System.out.println(in.read(b));
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return null;
+ } finally {
+ CloseUtil.close(in);
+ }
+ return b;
+ }
+
+ private static String getMd5(byte[] bytes) {
+ // 16进制字符
+ char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ try {
+ MessageDigest mdTemp = MessageDigest.getInstance("MD5");
+ mdTemp.update(bytes);
+ byte[] md = mdTemp.digest();
+ int j = md.length;
+ char[] str = new char[j * 2];
+ int k = 0;
+ // 移位 输出字符串
+ for (byte byte0 : md) {
+ str[k++] = hexDigits[byte0 >>> 4 & 0xf];
+ str[k++] = hexDigits[byte0 & 0xf];
+ }
+ return new String(str);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ return null;
+ }
+
+ /**
+ * 下载文件
+ *
+ * @param request /
+ * @param response /
+ * @param file /
+ */
+ public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) {
+ response.setCharacterEncoding(request.getCharacterEncoding());
+ response.setContentType("application/octet-stream");
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(file);
+ response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
+ IOUtils.copy(fis, response.getOutputStream());
+ response.flushBuffer();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ } finally {
+ if (fis != null) {
+ try {
+ fis.close();
+ if (deleteOnExit) {
+ file.deleteOnExit();
+ }
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+ }
+ }
+
+ public static String getMd5(File file) {
+ return getMd5(getByte(file));
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/PageUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/PageUtil.java
new file mode 100644
index 0000000..5bea120
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/PageUtil.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import org.springframework.data.domain.Page;
+import java.util.*;
+
+/**
+ * 分页工具
+ *
+ * 2018-12-10
+ */
+public class PageUtil extends cn.hutool.core.util.PageUtil {
+
+ /**
+ * List 分页
+ */
+ public static List toPage(int page, int size , List list) {
+ int fromIndex = page * size;
+ int toIndex = page * size + size;
+ if(fromIndex > list.size()){
+ return new ArrayList();
+ } else if(toIndex >= list.size()) {
+ return list.subList(fromIndex,list.size());
+ } else {
+ return list.subList(fromIndex,toIndex);
+ }
+ }
+
+ /**
+ * Page 数据处理,预防redis反序列化报错
+ */
+ public static Map<String,Object> toPage(Page page) {
+ Map<String,Object> map = new LinkedHashMap<>(2);
+ map.put("content",page.getContent());
+ map.put("totalElements",page.getTotalElements());
+ return map;
+ }
+
+ /**
+ * 自定义分页
+ */
+ public static Map<String,Object> toPage(Object object, Object totalElements) {
+ Map<String,Object> map = new LinkedHashMap<>(2);
+ map.put("content",object);
+ map.put("totalElements",totalElements);
+ return map;
+ }
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/QueryHelp.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/QueryHelp.java
new file mode 100644
index 0000000..e9cf239
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/QueryHelp.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.ObjectUtil;
+import lombok.extern.slf4j.Slf4j;
+import com.example.annotation.DataPermission;
+import com.example.annotation.Query;
+import javax.persistence.criteria.*;
+import java.lang.reflect.Field;
+import java.util.*;
+
+/**
+ *
+ * 2019-6-4 14:59:48
+ */
+@Slf4j
+@SuppressWarnings({"unchecked","all"})
+public class QueryHelp {
+
+ public static <R, Q> Predicate getPredicate(Root<R> root, Q query, CriteriaBuilder cb) {
+ List<Predicate> list = new ArrayList<>();
+ if(query == null){
+ return cb.and(list.toArray(new Predicate[0]));
+ }
+ // 数据权限验证
+ DataPermission permission = query.getClass().getAnnotation(DataPermission.class);
+ if(permission != null){
+ // 获取数据权限
+ List<Long> dataScopes = SecurityUtils.getCurrentUserDataScope();
+ if(CollectionUtil.isNotEmpty(dataScopes)){
+ if(StringUtils.isNotBlank(permission.joinName()) && StringUtils.isNotBlank(permission.fieldName())) {
+ Join join = root.join(permission.joinName(), JoinType.LEFT);
+ list.add(getExpression(permission.fieldName(),join, root).in(dataScopes));
+ } else if (StringUtils.isBlank(permission.joinName()) && StringUtils.isNotBlank(permission.fieldName())) {
+ list.add(getExpression(permission.fieldName(),null, root).in(dataScopes));
+ }
+ }
+ }
+ try {
+ List<Field> fields = getAllFields(query.getClass(), new ArrayList<>());
+ for (Field field : fields) {
+ boolean accessible = field.isAccessible();
+ // 设置对象的访问权限,保证对private的属性的访
+ field.setAccessible(true);
+ Query q = field.getAnnotation(Query.class);
+ if (q != null) {
+ String propName = q.propName();
+ String joinName = q.joinName();
+ String blurry = q.blurry();
+ String attributeName = isBlank(propName) ? field.getName() : propName;
+ Class<?> fieldType = field.getType();
+ Object val = field.get(query);
+ if (ObjectUtil.isNull(val) || "".equals(val)) {
+ continue;
+ }
+ Join join = null;
+ // 模糊多字段
+ if (ObjectUtil.isNotEmpty(blurry)) {
+ String[] blurrys = blurry.split(",");
+ List<Predicate> orPredicate = new ArrayList<>();
+ for (String s : blurrys) {
+ orPredicate.add(cb.like(root.get(s)
+ .as(String.class), "%" + val.toString() + "%"));
+ }
+ Predicate[] p = new Predicate[orPredicate.size()];
+ list.add(cb.or(orPredicate.toArray(p)));
+ continue;
+ }
+ if (ObjectUtil.isNotEmpty(joinName)) {
+ String[] joinNames = joinName.split(">");
+ for (String name : joinNames) {
+ switch (q.join()) {
+ case LEFT:
+ if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){
+ join = join.join(name, JoinType.LEFT);
+ } else {
+ join = root.join(name, JoinType.LEFT);
+ }
+ break;
+ case RIGHT:
+ if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){
+ join = join.join(name, JoinType.RIGHT);
+ } else {
+ join = root.join(name, JoinType.RIGHT);
+ }
+ break;
+ case INNER:
+ if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){
+ join = join.join(name, JoinType.INNER);
+ } else {
+ join = root.join(name, JoinType.INNER);
+ }
+ break;
+ default: break;
+ }
+ }
+ }
+ switch (q.type()) {
+ case EQUAL:
+ list.add(cb.equal(getExpression(attributeName,join,root)
+ .as((Class<? extends Comparable>) fieldType),val));
+ break;
+ case GREATER_THAN:
+ list.add(cb.greaterThanOrEqualTo(getExpression(attributeName,join,root)
+ .as((Class<? extends Comparable>) fieldType), (Comparable) val));
+ break;
+ case LESS_THAN:
+ list.add(cb.lessThanOrEqualTo(getExpression(attributeName,join,root)
+ .as((Class<? extends Comparable>) fieldType), (Comparable) val));
+ break;
+ case LESS_THAN_NQ:
+ list.add(cb.lessThan(getExpression(attributeName,join,root)
+ .as((Class<? extends Comparable>) fieldType), (Comparable) val));
+ break;
+ case INNER_LIKE:
+ list.add(cb.like(getExpression(attributeName,join,root)
+ .as(String.class), "%" + val.toString() + "%"));
+ break;
+ case LEFT_LIKE:
+ list.add(cb.like(getExpression(attributeName,join,root)
+ .as(String.class), "%" + val.toString()));
+ break;
+ case RIGHT_LIKE:
+ list.add(cb.like(getExpression(attributeName,join,root)
+ .as(String.class), val.toString() + "%"));
+ break;
+ case IN:
+ if (CollUtil.isNotEmpty((Collection<Object>)val)) {
+ list.add(getExpression(attributeName,join,root).in((Collection<Object>) val));
+ }
+ break;
+ case NOT_IN:
+ if (CollUtil.isNotEmpty((Collection<Object>)val)) {
+ list.add(getExpression(attributeName,join,root).in((Collection<Object>) val).not());
+ }
+ break;
+ case NOT_EQUAL:
+ list.add(cb.notEqual(getExpression(attributeName,join,root), val));
+ break;
+ case NOT_NULL:
+ list.add(cb.isNotNull(getExpression(attributeName,join,root)));
+ break;
+ case IS_NULL:
+ list.add(cb.isNull(getExpression(attributeName,join,root)));
+ break;
+ case BETWEEN:
+ List<Object> between = new ArrayList<>((List<Object>)val);
+ list.add(cb.between(getExpression(attributeName, join, root).as((Class<? extends Comparable>) between.get(0).getClass()),
+ (Comparable) between.get(0), (Comparable) between.get(1)));
+ break;
+ default: break;
+ }
+ }
+ field.setAccessible(accessible);
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ int size = list.size();
+ return cb.and(list.toArray(new Predicate[size]));
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T, R> Expression<T> getExpression(String attributeName, Join join, Root<R> root) {
+ if (ObjectUtil.isNotEmpty(join)) {
+ return join.get(attributeName);
+ } else {
+ return root.get(attributeName);
+ }
+ }
+
+ private static boolean isBlank(final CharSequence cs) {
+ int strLen;
+ if (cs == null || (strLen = cs.length()) == 0) {
+ return true;
+ }
+ for (int i = 0; i < strLen; i++) {
+ if (!Character.isWhitespace(cs.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static List<Field> getAllFields(Class clazz, List<Field> fields) {
+ if (clazz != null) {
+ fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
+ getAllFields(clazz.getSuperclass(), fields);
+ }
+ return fields;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RedisUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RedisUtils.java
new file mode 100644
index 0000000..4de0949
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RedisUtils.java
@@ -0,0 +1,708 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.connection.RedisConnection;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.*;
+import org.springframework.stereotype.Component;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author /
+ */
+@Component
+@SuppressWarnings({"unchecked", "all"})
+public class RedisUtils {
+ private static final Logger log = LoggerFactory.getLogger(RedisUtils.class);
+ private RedisTemplate<Object, Object> redisTemplate;
+ @Value("${jwt.online-key}")
+ private String onlineKey;
+
+ public RedisUtils(RedisTemplate<Object, Object> redisTemplate) {
+ this.redisTemplate = redisTemplate;
+ }
+
+ /**
+ * 指定缓存失效时间
+ *
+ * @param key 键
+ * @param time 时间(秒)
+ */
+ public boolean expire(String key, long time) {
+ try {
+ if (time > 0) {
+ redisTemplate.expire(key, time, TimeUnit.SECONDS);
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 指定缓存失效时间
+ *
+ * @param key 键
+ * @param time 时间(秒)
+ * @param timeUnit 单位
+ */
+ public boolean expire(String key, long time, TimeUnit timeUnit) {
+ try {
+ if (time > 0) {
+ redisTemplate.expire(key, time, timeUnit);
+ }
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 根据 key 获取过期时间
+ *
+ * @param key 键 不能为null
+ * @return 时间(秒) 返回0代表为永久有效
+ */
+ public long getExpire(Object key) {
+ return redisTemplate.getExpire(key, TimeUnit.SECONDS);
+ }
+
+ /**
+ * 查找匹配key
+ *
+ * @param pattern key
+ * @return /
+ */
+ public List<String> scan(String pattern) {
+ ScanOptions options = ScanOptions.scanOptions().match(pattern).build();
+ RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
+ RedisConnection rc = Objects.requireNonNull(factory).getConnection();
+ Cursor<byte[]> cursor = rc.scan(options);
+ List<String> result = new ArrayList<>();
+ while (cursor.hasNext()) {
+ result.add(new String(cursor.next()));
+ }
+ try {
+ RedisConnectionUtils.releaseConnection(rc, factory);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ return result;
+ }
+
+ /**
+ * 分页查询 key
+ *
+ * @param patternKey key
+ * @param page 页码
+ * @param size 每页数目
+ * @return /
+ */
+ public List<String> findKeysForPage(String patternKey, int page, int size) {
+ ScanOptions options = ScanOptions.scanOptions().match(patternKey).build();
+ RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
+ RedisConnection rc = Objects.requireNonNull(factory).getConnection();
+ Cursor<byte[]> cursor = rc.scan(options);
+ List<String> result = new ArrayList<>(size);
+ int tmpIndex = 0;
+ int fromIndex = page * size;
+ int toIndex = page * size + size;
+ while (cursor.hasNext()) {
+ if (tmpIndex >= fromIndex && tmpIndex < toIndex) {
+ result.add(new String(cursor.next()));
+ tmpIndex++;
+ continue;
+ }
+ // 获取到满足条件的数据后,就可以退出了
+ if (tmpIndex >= toIndex) {
+ break;
+ }
+ tmpIndex++;
+ cursor.next();
+ }
+ try {
+ RedisConnectionUtils.releaseConnection(rc, factory);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ return result;
+ }
+
+ /**
+ * 判断key是否存在
+ *
+ * @param key 键
+ * @return true 存在 false不存在
+ */
+ public boolean hasKey(String key) {
+ try {
+ return redisTemplate.hasKey(key);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 删除缓存
+ *
+ * @param key 可以传一个值 或多个
+ */
+ public void del(String... keys) {
+ if (keys != null && keys.length > 0) {
+ if (keys.length == 1) {
+ boolean result = redisTemplate.delete(keys[0]);
+ log.debug("--------------------------------------------");
+ log.debug(new StringBuilder("删除缓存:").append(keys[0]).append(",结果:").append(result).toString());
+ log.debug("--------------------------------------------");
+ } else {
+ Set<Object> keySet = new HashSet<>();
+ for (String key : keys) {
+ keySet.addAll(redisTemplate.keys(key));
+ }
+ long count = redisTemplate.delete(keySet);
+ log.debug("--------------------------------------------");
+ log.debug("成功删除缓存:" + keySet.toString());
+ log.debug("缓存删除数量:" + count + "个");
+ log.debug("--------------------------------------------");
+ }
+ }
+ }
+
+ // ============================String=============================
+
+ /**
+ * 普通缓存获取
+ *
+ * @param key 键
+ * @return 值
+ */
+ public Object get(String key) {
+ return key == null ? null : redisTemplate.opsForValue().get(key);
+ }
+
+ /**
+ * 批量获取
+ *
+ * @param keys
+ * @return
+ */
+ public List<Object> multiGet(List<String> keys) {
+ List list = redisTemplate.opsForValue().multiGet(Sets.newHashSet(keys));
+ List resultList = Lists.newArrayList();
+ Optional.ofNullable(list).ifPresent(e-> list.forEach(ele-> Optional.ofNullable(ele).ifPresent(resultList::add)));
+ return resultList;
+ }
+
+ /**
+ * 普通缓存放入
+ *
+ * @param key 键
+ * @param value 值
+ * @return true成功 false失败
+ */
+ public boolean set(String key, Object value) {
+ try {
+ redisTemplate.opsForValue().set(key, value);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 普通缓存放入并设置时间
+ *
+ * @param key 键
+ * @param value 值
+ * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
+ * @return true成功 false 失败
+ */
+ public boolean set(String key, Object value, long time) {
+ try {
+ if (time > 0) {
+ redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
+ } else {
+ set(key, value);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 普通缓存放入并设置时间
+ *
+ * @param key 键
+ * @param value 值
+ * @param time 时间
+ * @param timeUnit 类型
+ * @return true成功 false 失败
+ */
+ public boolean set(String key, Object value, long time, TimeUnit timeUnit) {
+ try {
+ if (time > 0) {
+ redisTemplate.opsForValue().set(key, value, time, timeUnit);
+ } else {
+ set(key, value);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ // ================================Map=================================
+
+ /**
+ * HashGet
+ *
+ * @param key 键 不能为null
+ * @param item 项 不能为null
+ * @return 值
+ */
+ public Object hget(String key, String item) {
+ return redisTemplate.opsForHash().get(key, item);
+ }
+
+ /**
+ * 获取hashKey对应的所有键值
+ *
+ * @param key 键
+ * @return 对应的多个键值
+ */
+ public Map<Object, Object> hmget(String key) {
+ return redisTemplate.opsForHash().entries(key);
+
+ }
+
+ /**
+ * HashSet
+ *
+ * @param key 键
+ * @param map 对应多个键值
+ * @return true 成功 false 失败
+ */
+ public boolean hmset(String key, Map<String, Object> map) {
+ try {
+ redisTemplate.opsForHash().putAll(key, map);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * HashSet 并设置时间
+ *
+ * @param key 键
+ * @param map 对应多个键值
+ * @param time 时间(秒)
+ * @return true成功 false失败
+ */
+ public boolean hmset(String key, Map<String, Object> map, long time) {
+ try {
+ redisTemplate.opsForHash().putAll(key, map);
+ if (time > 0) {
+ expire(key, time);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 向一张hash表中放入数据,如果不存在将创建
+ *
+ * @param key 键
+ * @param item 项
+ * @param value 值
+ * @return true 成功 false失败
+ */
+ public boolean hset(String key, String item, Object value) {
+ try {
+ redisTemplate.opsForHash().put(key, item, value);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 向一张hash表中放入数据,如果不存在将创建
+ *
+ * @param key 键
+ * @param item 项
+ * @param value 值
+ * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
+ * @return true 成功 false失败
+ */
+ public boolean hset(String key, String item, Object value, long time) {
+ try {
+ redisTemplate.opsForHash().put(key, item, value);
+ if (time > 0) {
+ expire(key, time);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 删除hash表中的值
+ *
+ * @param key 键 不能为null
+ * @param item 项 可以使多个 不能为null
+ */
+ public void hdel(String key, Object... item) {
+ redisTemplate.opsForHash().delete(key, item);
+ }
+
+ /**
+ * 判断hash表中是否有该项的值
+ *
+ * @param key 键 不能为null
+ * @param item 项 不能为null
+ * @return true 存在 false不存在
+ */
+ public boolean hHasKey(String key, String item) {
+ return redisTemplate.opsForHash().hasKey(key, item);
+ }
+
+ /**
+ * hash递增 如果不存在,就会创建一个 并把新增后的值返回
+ *
+ * @param key 键
+ * @param item 项
+ * @param by 要增加几(大于0)
+ * @return
+ */
+ public double hincr(String key, String item, double by) {
+ return redisTemplate.opsForHash().increment(key, item, by);
+ }
+
+ /**
+ * hash递减
+ *
+ * @param key 键
+ * @param item 项
+ * @param by 要减少记(小于0)
+ * @return
+ */
+ public double hdecr(String key, String item, double by) {
+ return redisTemplate.opsForHash().increment(key, item, -by);
+ }
+
+ // ============================set=============================
+
+ /**
+ * 根据key获取Set中的所有值
+ *
+ * @param key 键
+ * @return
+ */
+ public Set<Object> sGet(String key) {
+ try {
+ return redisTemplate.opsForSet().members(key);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * 根据value从一个set中查询,是否存在
+ *
+ * @param key 键
+ * @param value 值
+ * @return true 存在 false不存在
+ */
+ public boolean sHasKey(String key, Object value) {
+ try {
+ return redisTemplate.opsForSet().isMember(key, value);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 将数据放入set缓存
+ *
+ * @param key 键
+ * @param values 值 可以是多个
+ * @return 成功个数
+ */
+ public long sSet(String key, Object... values) {
+ try {
+ return redisTemplate.opsForSet().add(key, values);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ /**
+ * 将set数据放入缓存
+ *
+ * @param key 键
+ * @param time 时间(秒)
+ * @param values 值 可以是多个
+ * @return 成功个数
+ */
+ public long sSetAndTime(String key, long time, Object... values) {
+ try {
+ Long count = redisTemplate.opsForSet().add(key, values);
+ if (time > 0) {
+ expire(key, time);
+ }
+ return count;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ /**
+ * 获取set缓存的长度
+ *
+ * @param key 键
+ * @return
+ */
+ public long sGetSetSize(String key) {
+ try {
+ return redisTemplate.opsForSet().size(key);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ /**
+ * 移除值为value的
+ *
+ * @param key 键
+ * @param values 值 可以是多个
+ * @return 移除的个数
+ */
+ public long setRemove(String key, Object... values) {
+ try {
+ Long count = redisTemplate.opsForSet().remove(key, values);
+ return count;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ // ===============================list=================================
+
+ /**
+ * 获取list缓存的内容
+ *
+ * @param key 键
+ * @param start 开始
+ * @param end 结束 0 到 -1代表所有值
+ * @return
+ */
+ public List<Object> lGet(String key, long start, long end) {
+ try {
+ return redisTemplate.opsForList().range(key, start, end);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * 获取list缓存的长度
+ *
+ * @param key 键
+ * @return
+ */
+ public long lGetListSize(String key) {
+ try {
+ return redisTemplate.opsForList().size(key);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ /**
+ * 通过索引 获取list中的值
+ *
+ * @param key 键
+ * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
+ * @return
+ */
+ public Object lGetIndex(String key, long index) {
+ try {
+ return redisTemplate.opsForList().index(key, index);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ /**
+ * 将list放入缓存
+ *
+ * @param key 键
+ * @param value 值
+ * @return
+ */
+ public boolean lSet(String key, Object value) {
+ try {
+ redisTemplate.opsForList().rightPush(key, value);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 将list放入缓存
+ *
+ * @param key 键
+ * @param value 值
+ * @param time 时间(秒)
+ * @return
+ */
+ public boolean lSet(String key, Object value, long time) {
+ try {
+ redisTemplate.opsForList().rightPush(key, value);
+ if (time > 0) {
+ expire(key, time);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 将list放入缓存
+ *
+ * @param key 键
+ * @param value 值
+ * @return
+ */
+ public boolean lSet(String key, List<Object> value) {
+ try {
+ redisTemplate.opsForList().rightPushAll(key, value);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 将list放入缓存
+ *
+ * @param key 键
+ * @param value 值
+ * @param time 时间(秒)
+ * @return
+ */
+ public boolean lSet(String key, List<Object> value, long time) {
+ try {
+ redisTemplate.opsForList().rightPushAll(key, value);
+ if (time > 0) {
+ expire(key, time);
+ }
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 根据索引修改list中的某条数据
+ *
+ * @param key 键
+ * @param index 索引
+ * @param value 值
+ * @return /
+ */
+ public boolean lUpdateIndex(String key, long index, Object value) {
+ try {
+ redisTemplate.opsForList().set(key, index, value);
+ return true;
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 移除N个值为value
+ *
+ * @param key 键
+ * @param count 移除多少个
+ * @param value 值
+ * @return 移除的个数
+ */
+ public long lRemove(String key, long count, Object value) {
+ try {
+ return redisTemplate.opsForList().remove(key, count, value);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return 0;
+ }
+ }
+
+ /**
+ * @param prefix 前缀
+ * @param ids id
+ */
+ public void delByKeys(String prefix, Set<Long> ids) {
+ Set<Object> keys = new HashSet<>();
+ for (Long id : ids) {
+ keys.addAll(redisTemplate.keys(new StringBuffer(prefix).append(id).toString()));
+ }
+ long count = redisTemplate.delete(keys);
+ // 此处提示可自行删除
+ log.debug("--------------------------------------------");
+ log.debug("成功删除缓存:" + keys.toString());
+ log.debug("缓存删除数量:" + count + "个");
+ log.debug("--------------------------------------------");
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RequestHolder.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RequestHolder.java
new file mode 100644
index 0000000..09764e4
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RequestHolder.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import javax.servlet.http.HttpServletRequest;
+import java.util.Objects;
+
+/**
+ * 获取 HttpServletRequest
+ *
+ * 2018-11-24
+ */
+public class RequestHolder {
+
+ public static HttpServletRequest getHttpServletRequest() {
+ return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RsaUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RsaUtils.java
new file mode 100644
index 0000000..4611a15
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/RsaUtils.java
@@ -0,0 +1,198 @@
+package com.example.utils;
+
+import org.apache.commons.codec.binary.Base64;
+import javax.crypto.Cipher;
+import java.io.ByteArrayOutputStream;
+import java.security.*;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+/**
+ * @author https://www.cnblogs.com/nihaorz/p/10690643.html
+ * @description Rsa 工具类,公钥私钥生成,加解密
+ * 2020-05-18
+ **/
+public class RsaUtils {
+
+ private static final String SRC = "123456";
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("\n");
+ RsaKeyPair keyPair = generateKeyPair();
+ System.out.println("公钥:" + keyPair.getPublicKey());
+ System.out.println("私钥:" + keyPair.getPrivateKey());
+ System.out.println("\n");
+ test1(keyPair);
+ System.out.println("\n");
+ test2(keyPair);
+ System.out.println("\n");
+ }
+
+ /**
+ * 公钥加密私钥解密
+ */
+ private static void test1(RsaKeyPair keyPair) throws Exception {
+ System.out.println("***************** 公钥加密私钥解密开始 *****************");
+ String text1 = encryptByPublicKey(keyPair.getPublicKey(), RsaUtils.SRC);
+ String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1);
+ System.out.println("加密前:" + RsaUtils.SRC);
+ System.out.println("加密后:" + text1);
+ System.out.println("解密后:" + text2);
+ if (RsaUtils.SRC.equals(text2)) {
+ System.out.println("解密字符串和原始字符串一致,解密成功");
+ } else {
+ System.out.println("解密字符串和原始字符串不一致,解密失败");
+ }
+ System.out.println("***************** 公钥加密私钥解密结束 *****************");
+ }
+
+ /**
+ * 私钥加密公钥解密
+ * @throws Exception /
+ */
+ private static void test2(RsaKeyPair keyPair) throws Exception {
+ System.out.println("***************** 私钥加密公钥解密开始 *****************");
+ String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), RsaUtils.SRC);
+ String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1);
+ System.out.println("加密前:" + RsaUtils.SRC);
+ System.out.println("加密后:" + text1);
+ System.out.println("解密后:" + text2);
+ if (RsaUtils.SRC.equals(text2)) {
+ System.out.println("解密字符串和原始字符串一致,解密成功");
+ } else {
+ System.out.println("解密字符串和原始字符串不一致,解密失败");
+ }
+ System.out.println("***************** 私钥加密公钥解密结束 *****************");
+ }
+
+ /**
+ * 公钥解密
+ *
+ * @param publicKeyText 公钥
+ * @param text 待解密的信息
+ * @return /
+ * @throws Exception /
+ */
+ public static String decryptByPublicKey(String publicKeyText, String text) throws Exception {
+ X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.DECRYPT_MODE, publicKey);
+ byte[] result = doLongerCipherFinal(Cipher.DECRYPT_MODE, cipher, Base64.decodeBase64(text));
+ return new String(result);
+ }
+
+ /**
+ * 私钥加密
+ *
+ * @param privateKeyText 私钥
+ * @param text 待加密的信息
+ * @return /
+ * @throws Exception /
+ */
+ public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception {
+ PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+ byte[] result = doLongerCipherFinal(Cipher.ENCRYPT_MODE, cipher, text.getBytes());
+ return Base64.encodeBase64String(result);
+ }
+
+ /**
+ * 私钥解密
+ *
+ * @param privateKeyText 私钥
+ * @param text 待解密的文本
+ * @return /
+ * @throws Exception /
+ */
+ public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {
+ PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.DECRYPT_MODE, privateKey);
+ byte[] result = doLongerCipherFinal(Cipher.DECRYPT_MODE, cipher, Base64.decodeBase64(text));
+ return new String(result);
+ }
+
+ /**
+ * 公钥加密
+ *
+ * @param publicKeyText 公钥
+ * @param text 待加密的文本
+ * @return /
+ */
+ public static String encryptByPublicKey(String publicKeyText, String text) throws Exception {
+ X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+ byte[] result = doLongerCipherFinal(Cipher.ENCRYPT_MODE, cipher, text.getBytes());
+ return Base64.encodeBase64String(result);
+ }
+
+ private static byte[] doLongerCipherFinal(int opMode,Cipher cipher, byte[] source) throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ if (opMode == Cipher.DECRYPT_MODE) {
+ out.write(cipher.doFinal(source));
+ } else {
+ int offset = 0;
+ int totalSize = source.length;
+ while (totalSize - offset > 0) {
+ int size = Math.min(cipher.getOutputSize(0) - 11, totalSize - offset);
+ out.write(cipher.doFinal(source, offset, size));
+ offset += size;
+ }
+ }
+ out.close();
+ return out.toByteArray();
+ }
+
+ /**
+ * 构建RSA密钥对
+ *
+ * @return /
+ * @throws NoSuchAlgorithmException /
+ */
+ public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+ keyPairGenerator.initialize(1024);
+ KeyPair keyPair = keyPairGenerator.generateKeyPair();
+ RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
+ RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
+ String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
+ String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
+ return new RsaKeyPair(publicKeyString, privateKeyString);
+ }
+
+
+ /**
+ * RSA密钥对对象
+ */
+ public static class RsaKeyPair {
+
+ private final String publicKey;
+ private final String privateKey;
+
+ public RsaKeyPair(String publicKey, String privateKey) {
+ this.publicKey = publicKey;
+ this.privateKey = privateKey;
+ }
+
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public String getPrivateKey() {
+ return privateKey;
+ }
+
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SecurityUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SecurityUtils.java
new file mode 100644
index 0000000..e263130
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SecurityUtils.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.example.utils.enums.DataScopeEnum;
+import lombok.extern.slf4j.Slf4j;
+import com.example.exception.BadRequestException;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import java.util.List;
+
+/**
+ * 获取当前登录的用户
+ *
+ * 2019-01-17
+ */
+@Slf4j
+public class SecurityUtils {
+
+ /**
+ * 获取当前登录的用户
+ * @return UserDetails
+ */
+ public static UserDetails getCurrentUser() {
+ UserDetailsService userDetailsService = SpringContextHolder.getBean(UserDetailsService.class);
+ return userDetailsService.loadUserByUsername(getCurrentUsername());
+ }
+
+ /**
+ * 获取系统用户名称
+ *
+ * @return 系统用户名称
+ */
+ public static String getCurrentUsername() {
+ final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (authentication == null) {
+ throw new BadRequestException(HttpStatus.UNAUTHORIZED, "当前登录状态过期");
+ }
+ if (authentication.getPrincipal() instanceof UserDetails) {
+ UserDetails userDetails = (UserDetails) authentication.getPrincipal();
+ return userDetails.getUsername();
+ }
+ throw new BadRequestException(HttpStatus.UNAUTHORIZED, "找不到当前登录的信息");
+ }
+
+ /**
+ * 获取系统用户ID
+ * @return 系统用户ID
+ */
+ public static Long getCurrentUserId() {
+ UserDetails userDetails = getCurrentUser();
+ return new JSONObject(new JSONObject(userDetails).get("user")).get("id", Long.class);
+ }
+
+ /**
+ * 获取当前用户的数据权限
+ * @return /
+ */
+ public static List<Long> getCurrentUserDataScope(){
+ UserDetails userDetails = getCurrentUser();
+ JSONArray array = JSONUtil.parseArray(new JSONObject(userDetails).get("dataScopes"));
+ return JSONUtil.toList(array,Long.class);
+ }
+
+ /**
+ * 获取数据权限级别
+ * @return 级别
+ */
+ public static String getDataScopeType() {
+ List<Long> dataScopes = getCurrentUserDataScope();
+ if(dataScopes.size() != 0){
+ return "";
+ }
+ return DataScopeEnum.ALL.getValue();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SpringContextHolder.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SpringContextHolder.java
new file mode 100644
index 0000000..454b7c8
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/SpringContextHolder.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.core.env.Environment;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Jie
+ * 2019-01-07
+ */
+@Slf4j
+public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
+
+ private static ApplicationContext applicationContext = null;
+ private static final List<CallBack> CALL_BACKS = new ArrayList<>();
+ private static boolean addCallback = true;
+
+ /**
+ * 针对 某些初始化方法,在SpringContextHolder 未初始化时 提交回调方法。
+ * 在SpringContextHolder 初始化后,进行回调使用
+ *
+ * @param callBack 回调函数
+ */
+ public synchronized static void addCallBacks(CallBack callBack) {
+ if (addCallback) {
+ SpringContextHolder.CALL_BACKS.add(callBack);
+ } else {
+ log.warn("CallBack:{} 已无法添加!立即执行", callBack.getCallBackName());
+ callBack.executor();
+ }
+ }
+
+ /**
+ * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T getBean(String name) {
+ assertContextInjected();
+ return (T) applicationContext.getBean(name);
+ }
+
+ /**
+ * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
+ */
+ public static <T> T getBean(Class<T> requiredType) {
+ assertContextInjected();
+ return applicationContext.getBean(requiredType);
+ }
+
+ /**
+ * 获取SpringBoot 配置信息
+ *
+ * @param property 属性key
+ * @param defaultValue 默认值
+ * @param requiredType 返回类型
+ * @return /
+ */
+ public static <T> T getProperties(String property, T defaultValue, Class<T> requiredType) {
+ T result = defaultValue;
+ try {
+ result = getBean(Environment.class).getProperty(property, requiredType);
+ } catch (Exception ignored) {}
+ return result;
+ }
+
+ /**
+ * 获取SpringBoot 配置信息
+ *
+ * @param property 属性key
+ * @return /
+ */
+ public static String getProperties(String property) {
+ return getProperties(property, null, String.class);
+ }
+
+ /**
+ * 获取SpringBoot 配置信息
+ *
+ * @param property 属性key
+ * @param requiredType 返回类型
+ * @return /
+ */
+ public static <T> T getProperties(String property, Class<T> requiredType) {
+ return getProperties(property, null, requiredType);
+ }
+
+ /**
+ * 检查ApplicationContext不为空.
+ */
+ private static void assertContextInjected() {
+ if (applicationContext == null) {
+ throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
+ ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
+ }
+ }
+
+ /**
+ * 清除SpringContextHolder中的ApplicationContext为Null.
+ */
+ private static void clearHolder() {
+ log.debug("清除SpringContextHolder中的ApplicationContext:"
+ + applicationContext);
+ applicationContext = null;
+ }
+
+ @Override
+ public void destroy() {
+ SpringContextHolder.clearHolder();
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ if (SpringContextHolder.applicationContext != null) {
+ log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
+ }
+ SpringContextHolder.applicationContext = applicationContext;
+ if (addCallback) {
+ for (CallBack callBack : SpringContextHolder.CALL_BACKS) {
+ callBack.executor();
+ }
+ CALL_BACKS.clear();
+ }
+ SpringContextHolder.addCallback = false;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/StringUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/StringUtils.java
new file mode 100644
index 0000000..a5fd454
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/StringUtils.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import lombok.extern.slf4j.Slf4j;
+import com.example.config.ElAdminProperties;
+import net.dreamlu.mica.ip2region.core.Ip2regionSearcher;
+import net.dreamlu.mica.ip2region.core.IpInfo;
+import nl.basjes.parse.useragent.UserAgent;
+import nl.basjes.parse.useragent.UserAgentAnalyzer;
+import javax.servlet.http.HttpServletRequest;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.UnknownHostException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Enumeration;
+
+/**
+ *
+ * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
+ */
+@Slf4j
+public class StringUtils extends org.apache.commons.lang3.StringUtils {
+
+ private static final char SEPARATOR = '_';
+ private static final String UNKNOWN = "unknown";
+
+ /**
+ * 注入bean
+ */
+ private final static Ip2regionSearcher IP_SEARCHER = SpringContextHolder.getBean(Ip2regionSearcher.class);
+
+
+ private static final UserAgentAnalyzer USER_AGENT_ANALYZER = UserAgentAnalyzer
+ .newBuilder()
+ .hideMatcherLoadStats()
+ .withCache(10000)
+ .withField(UserAgent.AGENT_NAME_VERSION)
+ .build();
+
+ /**
+ * 驼峰命名法工具
+ *
+ * @return toCamelCase(" hello_world ") == "helloWorld"
+ * toCapitalizeCamelCase("hello_world") == "HelloWorld"
+ * toUnderScoreCase("helloWorld") = "hello_world"
+ */
+ public static String toCamelCase(String s) {
+ if (s == null) {
+ return null;
+ }
+
+ s = s.toLowerCase();
+
+ StringBuilder sb = new StringBuilder(s.length());
+ boolean upperCase = false;
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+
+ if (c == SEPARATOR) {
+ upperCase = true;
+ } else if (upperCase) {
+ sb.append(Character.toUpperCase(c));
+ upperCase = false;
+ } else {
+ sb.append(c);
+ }
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * 驼峰命名法工具
+ *
+ * @return toCamelCase(" hello_world ") == "helloWorld"
+ * toCapitalizeCamelCase("hello_world") == "HelloWorld"
+ * toUnderScoreCase("helloWorld") = "hello_world"
+ */
+ public static String toCapitalizeCamelCase(String s) {
+ if (s == null) {
+ return null;
+ }
+ s = toCamelCase(s);
+ return s.substring(0, 1).toUpperCase() + s.substring(1);
+ }
+
+ /**
+ * 驼峰命名法工具
+ *
+ * @return toCamelCase(" hello_world ") == "helloWorld"
+ * toCapitalizeCamelCase("hello_world") == "HelloWorld"
+ * toUnderScoreCase("helloWorld") = "hello_world"
+ */
+ static String toUnderScoreCase(String s) {
+ if (s == null) {
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ boolean upperCase = false;
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+
+ boolean nextUpperCase = true;
+
+ if (i < (s.length() - 1)) {
+ nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
+ }
+
+ if ((i > 0) && Character.isUpperCase(c)) {
+ if (!upperCase || !nextUpperCase) {
+ sb.append(SEPARATOR);
+ }
+ upperCase = true;
+ } else {
+ upperCase = false;
+ }
+
+ sb.append(Character.toLowerCase(c));
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * 获取ip地址
+ */
+ public static String getIp(HttpServletRequest request) {
+ String ip = request.getHeader("x-forwarded-for");
+ if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
+ ip = request.getHeader("Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
+ ip = request.getHeader("WL-Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
+ ip = request.getRemoteAddr();
+ }
+ String comma = ",";
+ String localhost = "127.0.0.1";
+ if (ip.contains(comma)) {
+ ip = ip.split(",")[0];
+ }
+ if (localhost.equals(ip)) {
+ // 获取本机真正的ip地址
+ try {
+ ip = InetAddress.getLocalHost().getHostAddress();
+ } catch (UnknownHostException e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+ return ip;
+ }
+
+ /**
+ * 根据ip获取详细地址
+ */
+ public static String getCityInfo(String ip) {
+ if (ElAdminProperties.ipLocal) {
+ return getLocalCityInfo(ip);
+ } else {
+ return getHttpCityInfo(ip);
+ }
+ }
+
+ /**
+ * 根据ip获取详细地址
+ */
+ public static String getHttpCityInfo(String ip) {
+ String api = String.format(ElAdminConstant.Url.IP_URL, ip);
+ JSONObject object = JSONUtil.parseObj(HttpUtil.get(api));
+ return object.get("addr", String.class);
+ }
+
+ /**
+ * 根据ip获取详细地址
+ */
+ public static String getLocalCityInfo(String ip) {
+ IpInfo ipInfo = IP_SEARCHER.memorySearch(ip);
+ if(ipInfo != null){
+ return ipInfo.getAddress();
+ }
+ return null;
+
+ }
+
+ public static String getBrowser(HttpServletRequest request) {
+ UserAgent.ImmutableUserAgent userAgent = USER_AGENT_ANALYZER.parse(request.getHeader("User-Agent"));
+ return userAgent.get(UserAgent.AGENT_NAME_VERSION).getValue();
+ }
+
+ /**
+ * 获得当天是周几
+ */
+ public static String getWeekDay() {
+ String[] weekDays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(new Date());
+
+ int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
+ if (w < 0) {
+ w = 0;
+ }
+ return weekDays[w];
+ }
+
+ /**
+ * 获取当前机器的IP
+ *
+ * @return /
+ */
+ public static String getLocalIp() {
+ try {
+ InetAddress candidateAddress = null;
+ // 遍历所有的网络接口
+ for (Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();) {
+ NetworkInterface anInterface = interfaces.nextElement();
+ // 在所有的接口下再遍历IP
+ for (Enumeration<InetAddress> inetAddresses = anInterface.getInetAddresses(); inetAddresses.hasMoreElements();) {
+ InetAddress inetAddr = inetAddresses.nextElement();
+ // 排除loopback类型地址
+ if (!inetAddr.isLoopbackAddress()) {
+ if (inetAddr.isSiteLocalAddress()) {
+ // 如果是site-local地址,就是它了
+ return inetAddr.getHostAddress();
+ } else if (candidateAddress == null) {
+ // site-local类型的地址未被发现,先记录候选地址
+ candidateAddress = inetAddr;
+ }
+ }
+ }
+ }
+ if (candidateAddress != null) {
+ return candidateAddress.getHostAddress();
+ }
+ // 如果没有发现 non-loopback地址.只能用最次选的方案
+ InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
+ if (jdkSuppliedAddress == null) {
+ return "";
+ }
+ return jdkSuppliedAddress.getHostAddress();
+ } catch (Exception e) {
+ return "";
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ThrowableUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ThrowableUtil.java
new file mode 100644
index 0000000..0ea7da7
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ThrowableUtil.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * 异常工具 2019-01-06
+ *
+ */
+public class ThrowableUtil {
+
+ /**
+ * 获取堆栈信息
+ */
+ public static String getStackTrace(Throwable throwable){
+ StringWriter sw = new StringWriter();
+ try (PrintWriter pw = new PrintWriter(sw)) {
+ throwable.printStackTrace(pw);
+ return sw.toString();
+ }
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/TranslatorUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/TranslatorUtil.java
new file mode 100644
index 0000000..7d7087d
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/TranslatorUtil.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import cn.hutool.json.JSONArray;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+
+/**
+ *
+ * 翻译工具类
+ */
+public class TranslatorUtil {
+
+ public static String translate(String word){
+ try {
+ String url = "https://translate.googleapis.com/translate_a/single?" +
+ "client=gtx&" +
+ "sl=en" +
+ "&tl=zh-CN" +
+ "&dt=t&q=" + URLEncoder.encode(word, "UTF-8");
+
+ URL obj = new URL(url);
+ HttpURLConnection con = (HttpURLConnection) obj.openConnection();
+ con.setRequestProperty("User-Agent", "Mozilla/5.0");
+
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(con.getInputStream()));
+ String inputLine;
+ StringBuilder response = new StringBuilder();
+
+ while ((inputLine = in.readLine()) != null) {
+ response.append(inputLine);
+ }
+ in.close();
+ return parseResult(response.toString());
+ }catch (Exception e){
+ return word;
+ }
+ }
+
+ private static String parseResult(String inputJson){
+ JSONArray jsonArray2 = (JSONArray) new JSONArray(inputJson).get(0);
+ StringBuilder result = new StringBuilder();
+ for (Object o : jsonArray2) {
+ result.append(((JSONArray) o).get(0).toString());
+ }
+ return result.toString();
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ValidationUtil.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ValidationUtil.java
new file mode 100644
index 0000000..689ec6f
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/ValidationUtil.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.example.exception.BadRequestException;
+import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator;
+
+/**
+ * 验证工具
+ *
+ * 2018-11-23
+ */
+public class ValidationUtil{
+
+ /**
+ * 验证空
+ */
+ public static void isNull(Object obj, String entity, String parameter , Object value){
+ if(ObjectUtil.isNull(obj)){
+ String msg = entity + " 不存在: "+ parameter +" is "+ value;
+ throw new BadRequestException(msg);
+ }
+ }
+
+ /**
+ * 验证是否为邮箱
+ */
+ public static boolean isEmail(String email) {
+ return new EmailValidator().isValid(email, null);
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeBiEnum.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeBiEnum.java
new file mode 100644
index 0000000..4f0147e
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeBiEnum.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * <p>
+ * 验证码业务场景
+ * </p>
+ *
+ * 2020-05-02
+ */
+@Getter
+@AllArgsConstructor
+public enum CodeBiEnum {
+
+ /* 旧邮箱修改邮箱 */
+ ONE(1, "旧邮箱修改邮箱"),
+
+ /* 通过邮箱修改密码 */
+ TWO(2, "通过邮箱修改密码");
+
+ private final Integer code;
+ private final String description;
+
+ public static CodeBiEnum find(Integer code) {
+ for (CodeBiEnum value : CodeBiEnum.values()) {
+ if (value.getCode().equals(code)) {
+ return value;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeEnum.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeEnum.java
new file mode 100644
index 0000000..17a1b2d
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/CodeEnum.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * <p>
+ * 验证码业务场景对应的 Redis 中的 key
+ * </p>
+ *
+ * 2020-05-02
+ */
+@Getter
+@AllArgsConstructor
+public enum CodeEnum {
+
+ /* 通过手机号码重置邮箱 */
+ PHONE_RESET_EMAIL_CODE("phone_reset_email_code_", "通过手机号码重置邮箱"),
+
+ /* 通过旧邮箱重置邮箱 */
+ EMAIL_RESET_EMAIL_CODE("email_reset_email_code_", "通过旧邮箱重置邮箱"),
+
+ /* 通过手机号码重置密码 */
+ PHONE_RESET_PWD_CODE("phone_reset_pwd_code_", "通过手机号码重置密码"),
+
+ /* 通过邮箱重置密码 */
+ EMAIL_RESET_PWD_CODE("email_reset_pwd_code_", "通过邮箱重置密码");
+
+ private final String key;
+ private final String description;
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/DataScopeEnum.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/DataScopeEnum.java
new file mode 100644
index 0000000..18330f2
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/DataScopeEnum.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * <p>
+ * 数据权限枚举
+ * </p>
+ *
+ * 2020-05-07
+ */
+@Getter
+@AllArgsConstructor
+public enum DataScopeEnum {
+
+ /* 全部的数据权限 */
+ ALL("全部", "全部的数据权限"),
+
+ /* 自己部门的数据权限 */
+ THIS_LEVEL("本级", "自己部门的数据权限"),
+
+ /* 自定义的数据权限 */
+ CUSTOMIZE("自定义", "自定义的数据权限");
+
+ private final String value;
+ private final String description;
+
+ public static DataScopeEnum find(String val) {
+ for (DataScopeEnum dataScopeEnum : DataScopeEnum.values()) {
+ if (dataScopeEnum.getValue().equals(val)) {
+ return dataScopeEnum;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/RequestMethodEnum.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/RequestMethodEnum.java
new file mode 100644
index 0000000..2edd703
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/enums/RequestMethodEnum.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2019-2020 Zheng Jie
+ *
+ * Licensed 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 com.example.utils.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ *
+ * @website https://el-admin.vip
+ * @description
+ * 2020-06-10
+ **/
+@Getter
+@AllArgsConstructor
+public enum RequestMethodEnum {
+
+ /**
+ * 搜寻 @AnonymousGetMapping
+ */
+ GET("GET"),
+
+ /**
+ * 搜寻 @AnonymousPostMapping
+ */
+ POST("POST"),
+
+ /**
+ * 搜寻 @AnonymousPutMapping
+ */
+ PUT("PUT"),
+
+ /**
+ * 搜寻 @AnonymousPatchMapping
+ */
+ PATCH("PATCH"),
+
+ /**
+ * 搜寻 @AnonymousDeleteMapping
+ */
+ DELETE("DELETE"),
+
+ /**
+ * 否则就是所有 Request 接口都放行
+ */
+ ALL("All");
+
+ /**
+ * Request 类型
+ */
+ private final String type;
+
+ public static RequestMethodEnum find(String type) {
+ for (RequestMethodEnum value : RequestMethodEnum.values()) {
+ if (value.getType().equals(type)) {
+ return value;
+ }
+ }
+ return ALL;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/PageUtils.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/PageUtils.java
new file mode 100644
index 0000000..7f02b02
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/PageUtils.java
@@ -0,0 +1,145 @@
+/**
+
+ *
+
+ *
+ *
+ */
+
+package com.example.utils.page;
+
+
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 分页工具类
+ *
+ * @author Mark [email protected]
+ */
+public class PageUtils implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * 总记录数
+ */
+ private int total;
+ /**
+ * 每页记录数
+ */
+ private int size;
+ /**
+ * 总页数
+ */
+ private int pages;
+ /**
+ * 当前页数
+ */
+ private int page;
+ /**
+ * 列表数据
+ */
+ private List<?> list;
+
+ private double totalTime;
+
+ private Object independentIpNum;
+
+ private int resultTotal;
+
+ public int getResultTotal() {
+ return resultTotal;
+ }
+
+ public void setResultTotal(int resultTotal) {
+ this.resultTotal = resultTotal;
+ }
+
+ /**
+ * 分页
+ * @param list 列表数据
+ * @param total 总记录数
+ * @param size 每页记录数
+ * @param page 当前页数
+ */
+ public PageUtils(List<?> list, int total, int size, int page ,double totalTime,int independentIpNum ,int resultTotal) {
+ this.list = list;
+ this.total = total;
+ this.size = size;
+ this.page = page;
+ this.totalTime = totalTime;
+ this.independentIpNum = independentIpNum;
+ this.resultTotal = resultTotal;
+ this.pages = (int)Math.ceil((double)total/size);
+ }
+
+ /**
+ * 分页
+ */
+ public PageUtils(IPage<?> page) {
+ this.list = page.getRecords();
+ this.total = (int)page.getTotal();
+ this.size = (int)page.getSize();
+ this.page = (int)page.getCurrent();
+ this.pages = (int)page.getPages();
+ }
+
+
+ public Object getIndependentIpNum() {
+ return independentIpNum;
+ }
+
+ public void setIndependentIpNum(Object independentIpNum) {
+ this.independentIpNum = independentIpNum;
+ }
+
+ public int getTotal() {
+ return total;
+ }
+
+ public void setTotal(int total) {
+ this.total = total;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public void setSize(int size) {
+ this.size = size;
+ }
+
+ public int getPages() {
+ return pages;
+ }
+
+ public void setPages(int pages) {
+ this.pages = pages;
+ }
+
+ public int getPage() {
+ return page;
+ }
+
+ public double getTotalTime() {
+ return totalTime;
+ }
+
+ public void setTotalTime(double totalTime) {
+ this.totalTime = totalTime;
+ }
+
+ public void setPage(int page) {
+ this.page = page;
+ }
+
+ public List<?> getList() {
+ return list;
+ }
+
+ public void setList(List<?> list) {
+ this.list = list;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/Query.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/Query.java
new file mode 100644
index 0000000..765f2f6
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/Query.java
@@ -0,0 +1,64 @@
+package com.example.utils.page;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+import java.util.Map;
+
+/**
+ * 查询参数
+ */
+public class Query {
+
+ private Class clz;
+
+ public Class<? extends Object> getClz() {
+ return clz;
+ }
+
+ public void setClz(Class clz) {
+ this.clz = clz;
+ }
+
+ public Query(Class clz) {
+ this.clz = clz;
+ }
+
+ public IPage getPage(Map<String, Object> params) {
+ return this.getPage(params, null, false);
+ }
+
+ public IPage getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
+ //分页参数
+ long curPage = 1;
+ long limit = 10;
+
+ if(params.get("page") != null && !"".equals(params.get("page"))){
+ curPage = Long.parseLong((String)params.get("page"));
+ }
+ if(params.get("size") != null && !"".equals(params.get("size"))){
+ limit = Long.parseLong((String)params.get("size"));
+ if(limit == -1){
+ limit = Long.MAX_VALUE;
+ curPage = 0;
+ }
+ }
+
+ //分页对象
+ Page page = new Page(curPage, limit);
+
+ //分页参数
+ params.put("page", page);
+
+
+ // 默认排序
+ if(isAsc) {
+ page.setAsc(defaultOrderField);
+ }else {
+ page.setDesc(defaultOrderField);
+ }
+
+ return page;
+ }
+}
diff --git a/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/R.java b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/R.java
new file mode 100644
index 0000000..92db65a
--- /dev/null
+++ b/UI source code/dns-dev-2.0/dns-common/src/main/java/com/example/utils/page/R.java
@@ -0,0 +1,40 @@
+package com.example.utils.page;
+
+import cn.hutool.core.date.DateUtil;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class R extends HashMap<String, Object> {
+ private static final long serialVersionUID = 1L;
+
+ public R() {
+ put("status", 200);
+ put("message", "success");
+ put("timestamp", new Date());
+ }
+
+ public static R ok(String message) {
+ R r = new R();
+ r.put("message", message);
+ r.put("timestamp", new Date());
+ return r;
+ }
+
+ public static R ok() {
+ return new R();
+ }
+
+ public static R ok(Object data) {
+ R r = new R();
+ r.put("data", data);
+ r.put("timestamp", new Date());
+ return r;
+ }
+
+
+}
+
+