项目初始化
commit
3e27fc399a
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
.idea/
|
||||
youchain-common/target/
|
||||
youchain-generator/target/
|
||||
youchain-logging/target/
|
||||
youchain-system/target/
|
||||
youchain-tongyong/target/
|
||||
youchain-tools/target/
|
||||
application.pid
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, "control" means (i) the power, direct or
|
||||
indirect, to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or
|
||||
translation of a Source form, including but not limited to compiled object code,
|
||||
generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
||||
available under the License, as indicated by a copyright notice that is included
|
||||
in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||
is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative Works
|
||||
shall not include works that remain separable from, or merely link (or bind by
|
||||
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative Works
|
||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||
on behalf of the copyright owner. For the purposes of this definition,
|
||||
"submitted" means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||
the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable (except as stated in this section) patent license to make, have
|
||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||
such license applies only to those patent claims licensable by such Contributor
|
||||
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||
submitted. If You institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||
Contribution incorporated within the Work constitutes direct or contributory
|
||||
patent infringement, then any patent licenses granted to You under this License
|
||||
for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution.
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||
in any medium, with or without modifications, and in Source or Object form,
|
||||
provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of
|
||||
this License; and
|
||||
You must cause any modified files to carry prominent notices stating that You
|
||||
changed the files; and
|
||||
You must retain, in the Source form of any Derivative Works that You distribute,
|
||||
all copyright, patent, trademark, and attribution notices from the Source form
|
||||
of the Work, excluding those notices that do not pertain to any part of the
|
||||
Derivative Works; and
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
||||
Derivative Works that You distribute must include a readable copy of the
|
||||
attribution notices contained within such NOTICE file, excluding those notices
|
||||
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||
following places: within a NOTICE text file distributed as part of the
|
||||
Derivative Works; within the Source form or documentation, if provided along
|
||||
with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents of
|
||||
the NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative Works that
|
||||
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||
provided that such additional attribution notices cannot be construed as
|
||||
modifying the License.
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||
with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions.
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||
any separate license agreement you may have executed with Licensor regarding
|
||||
such Contributions.
|
||||
|
||||
6. Trademarks.
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks,
|
||||
service marks, or product names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
including, without limitation, any warranties or conditions of TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||
solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your exercise of
|
||||
permissions under this License.
|
||||
|
||||
8. Limitation of Liability.
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence),
|
||||
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special, incidental,
|
||||
or consequential damages of any character arising as a result of this License or
|
||||
out of the use or inability to use the Work (including but not limited to
|
||||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||
any and all other commercial damages or losses), even if such Contributor has
|
||||
been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability.
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||
other liability obligations and/or rights consistent with this License. However,
|
||||
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason of your
|
||||
accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets "{}" replaced with your own
|
||||
identifying information. (Don't include the brackets!) The text should be
|
||||
enclosed in the appropriate comment syntax for the file format. We also
|
||||
recommend that a file or class name and description of purpose be included on
|
||||
the same "printed page" as the copyright notice for easier identification within
|
||||
third-party archives.
|
||||
|
||||
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.
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.youchain</groupId>
|
||||
<artifactId>youchain</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>2.6</version>
|
||||
|
||||
<modules>
|
||||
<module>youchain-common</module>
|
||||
<module>youchain-logging</module>
|
||||
<module>youchain-system</module>
|
||||
<module>youchain-tools</module>
|
||||
<module>youchain-generator</module>
|
||||
<module>youchain-tongyong</module>
|
||||
</modules>
|
||||
|
||||
<name>ELADMIN 后台管理</name>
|
||||
<url>https://eladmin.vip</url>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.5.4</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<log4j2.version>2.17.0</log4j2.version>
|
||||
<logback.version>1.2.9</logback.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<log4jdbc.version>1.16</log4jdbc.version>
|
||||
<swagger.version>2.9.2</swagger.version>
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
<druid.version>1.2.8</druid.version>
|
||||
<commons-pool2.version>2.11.1</commons-pool2.version>
|
||||
<mapstruct.version>1.4.2.Final</mapstruct.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!--Spring boot 核心-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--Spring boot Web容器-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
|
||||
</dependency>
|
||||
|
||||
<!--Spring boot 测试-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!--Spring boot 安全框架-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- spring boot 缓存 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--Spring boot Redis-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--spring boot 集成redis所需common-pool2-->
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
<version>${commons-pool2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--监控sql日志-->
|
||||
<dependency>
|
||||
<groupId>org.bgee.log4jdbc-log4j2</groupId>
|
||||
<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
|
||||
<version>${log4jdbc.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Swagger UI 相关 -->
|
||||
<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-spring-boot-starter -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-spring-boot-starter</artifactId>
|
||||
<version>3.0.3</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--Mysql依赖包-->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- druid数据源驱动 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- ip2region IP库 -->
|
||||
<!-- https://mvnrepository.com/artifact/net.dreamlu/mica-ip2region -->
|
||||
<dependency>
|
||||
<groupId>net.dreamlu</groupId>
|
||||
<artifactId>mica-ip2region</artifactId>
|
||||
<version>2.6.3</version>
|
||||
</dependency>
|
||||
|
||||
<!--lombok插件-->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- excel工具 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xerces</groupId>
|
||||
<artifactId>xercesImpl</artifactId>
|
||||
<version>2.12.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- fastjson -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--mapStruct依赖-->
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
<version>${mapstruct.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>${mapstruct.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Java图形验证码 -->
|
||||
<dependency>
|
||||
<groupId>com.github.whvcse</groupId>
|
||||
<artifactId>easy-captcha</artifactId>
|
||||
<version>1.6.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-text</artifactId>
|
||||
<version>1.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 解析客户端操作系统、浏览器信息 -->
|
||||
<dependency>
|
||||
<groupId>nl.basjes.parse.useragent</groupId>
|
||||
<artifactId>yauaa</artifactId>
|
||||
<version>6.11</version>
|
||||
</dependency>
|
||||
|
||||
<!-- fastexcel导出 -->
|
||||
<dependency>
|
||||
<groupId>cn.idev.excel</groupId>
|
||||
<artifactId>fastexcel</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- 打包时跳过测试 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
|
||||
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>public</id>
|
||||
<name>aliyun nexus</name>
|
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</project>
|
||||
|
|
@ -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>youchain</artifactId>
|
||||
<groupId>com.youchain</groupId>
|
||||
<version>2.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
<hutool.version>5.8.21</hutool.version>
|
||||
</properties>
|
||||
|
||||
<artifactId>youchain-common</artifactId>
|
||||
<name>公共模块</name>
|
||||
|
||||
<dependencies>
|
||||
<!--工具包-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -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.youchain.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author jacky
|
||||
* 用于标记匿名访问方法
|
||||
*/
|
||||
@Inherited
|
||||
@Documented
|
||||
@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface AnonymousAccess {
|
||||
|
||||
}
|
||||
|
|
@ -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.youchain.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>
|
||||
* @author Liu Xue
|
||||
* @website https://eladmin.vip
|
||||
* @date 2020-05-07
|
||||
**/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DataPermission {
|
||||
|
||||
/**
|
||||
* Entity 中的字段名称
|
||||
*/
|
||||
String fieldName() default "";
|
||||
|
||||
/**
|
||||
* Entity 中与部门关联的字段名称
|
||||
*/
|
||||
String joinName() default "";
|
||||
}
|
||||
|
|
@ -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.youchain.annotation;
|
||||
|
||||
import com.youchain.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;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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.youchain.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-6-4 13:52:30
|
||||
*/
|
||||
@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 大于
|
||||
, GREATER_THAN_NQ
|
||||
// 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
|
||||
//两个属性 相等
|
||||
,EQUAL_2
|
||||
// 两个属性 大于等于
|
||||
, GREATER_THAN_2
|
||||
// 两个属性 小于等于
|
||||
, LESS_THAN_2
|
||||
// 两个属性 大于等于
|
||||
, GREATER_THAN_NQ_2
|
||||
// 两个属性 小于等于
|
||||
, LESS_THAN_NQ_2
|
||||
// 两个属性 不相等等于
|
||||
, NOT_EQUAL_2
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* 适用于简单连接查询,复杂的请自定义该注解,或者使用sql查询
|
||||
*/
|
||||
enum Join {
|
||||
/** jie 2019-6-4 13:18:30 */
|
||||
LEFT, RIGHT, INNER
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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.youchain.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.youchain.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 {};
|
||||
|
||||
}
|
||||
|
|
@ -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.youchain.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.youchain.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 {};
|
||||
|
||||
}
|
||||
|
|
@ -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.youchain.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.youchain.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 {};
|
||||
|
||||
}
|
||||
|
|
@ -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.youchain.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.youchain.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 {};
|
||||
|
||||
}
|
||||
|
|
@ -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.youchain.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.youchain.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 {};
|
||||
|
||||
}
|
||||
|
|
@ -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.youchain.aspect;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.youchain.utils.RequestHolder;
|
||||
import com.youchain.utils.StringUtils;
|
||||
import com.youchain.annotation.Limit;
|
||||
import com.youchain.exception.BadRequestException;
|
||||
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.youchain.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;";
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.aspect;
|
||||
|
||||
/**
|
||||
* 限流枚举
|
||||
* @author /
|
||||
*/
|
||||
public enum LimitType {
|
||||
// 默认
|
||||
CUSTOMER,
|
||||
// by ip addr
|
||||
IP
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package com.youchain.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;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.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 根据需求自行添加
|
||||
* @author Liu Xue
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.base;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
|
@ -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.youchain.config;
|
||||
|
||||
import com.youchain.utils.SecurityUtils;
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @description : 设置审计
|
||||
* @author : Dong ZhaoYang
|
||||
* @date : 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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @description
|
||||
* @date 2021-11-22
|
||||
**/
|
||||
@Data
|
||||
@Component
|
||||
public class ElAdminProperties {
|
||||
|
||||
public static Boolean ipLocal;
|
||||
|
||||
@Value("${ip.local-parsing}")
|
||||
public void setIpLocal(Boolean ipLocal) {
|
||||
ElAdminProperties.ipLocal = ipLocal;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.config;
|
||||
|
||||
import com.youchain.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;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.config;
|
||||
|
||||
import com.youchain.utils.ElAdminConstant;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* 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.youchain.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;
|
||||
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 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);
|
||||
// fastjson 升级到 1.2.83 后需要指定序列化白名单
|
||||
ParserConfig.getGlobalInstance().addAccept("com.youchain.domain");
|
||||
ParserConfig.getGlobalInstance().addAccept("com.youchain.service.dto");
|
||||
ParserConfig.getGlobalInstance().addAccept("com.youchain");
|
||||
|
||||
|
||||
// 模块内的实体类
|
||||
ParserConfig.getGlobalInstance().addAccept("com.youchain.modules.mnt.domain");
|
||||
ParserConfig.getGlobalInstance().addAccept("com.youchain.modules.quartz.domain");
|
||||
ParserConfig.getGlobalInstance().addAccept("com.youchain.modules.system.domain");
|
||||
// 模块内的 Dto
|
||||
ParserConfig.getGlobalInstance().addAccept("com.youchain.modules.mnt.service.dto");
|
||||
ParserConfig.getGlobalInstance().addAccept("com.youchain.modules.quartz.service.dto");
|
||||
ParserConfig.getGlobalInstance().addAccept("com.youchain.modules.security.service.dto");
|
||||
ParserConfig.getGlobalInstance().addAccept("com.youchain.modules.system.service.dto");
|
||||
// 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<>(8);
|
||||
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>
|
||||
*/
|
||||
@Slf4j
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.youchain.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @website https://eladmin.vip
|
||||
* @description
|
||||
* @date 2020-05-18
|
||||
**/
|
||||
@Data
|
||||
@Component
|
||||
public class RsaProperties {
|
||||
public static String licenseKey;
|
||||
public static String privateKey;
|
||||
|
||||
@Value("${rsa.private_key}")
|
||||
public void setPrivateKey(String privateKey) {
|
||||
RsaProperties.privateKey = privateKey;
|
||||
}
|
||||
|
||||
@Value("${rsa.licenseKey}")
|
||||
public void setLicenseKey(String privateKey) {
|
||||
RsaProperties.licenseKey = privateKey;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* 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.youchain.config;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.fasterxml.classmate.TypeResolver;
|
||||
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.ApiInfo;
|
||||
import springfox.documentation.service.ApiKey;
|
||||
import springfox.documentation.service.AuthorizationScope;
|
||||
import springfox.documentation.service.SecurityReference;
|
||||
import springfox.documentation.service.SecurityScheme;
|
||||
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 springfox.documentation.schema.AlternateTypeRules.newRule;
|
||||
|
||||
/**
|
||||
* api页面 /doc.html
|
||||
* @author Liu Xue
|
||||
* @date 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(PathSelectors.regex("^(?!/error).*"))
|
||||
.paths(PathSelectors.any())
|
||||
.build()
|
||||
//添加登陆认证
|
||||
.securitySchemes(securitySchemes())
|
||||
.securityContexts(securityContexts());
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.description("后台管理")
|
||||
.title("接口文档")
|
||||
.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())
|
||||
.operationSelector(o->o.requestMappingPattern().matches("^(?!/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 CollUtil.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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.exception;
|
||||
|
||||
/**
|
||||
* 统一关于错误配置信息 异常
|
||||
*
|
||||
* @author: liaojinlong
|
||||
* @date: 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.youchain.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-23
|
||||
* 统一异常处理
|
||||
*/
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.youchain.exception;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.youchain.exception;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.exception.handler;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
@Data
|
||||
public class ApiError {
|
||||
|
||||
private Integer status = 400;
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime timestamp;
|
||||
private String message;
|
||||
|
||||
public 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;
|
||||
}
|
||||
|
||||
public static ApiError errorJosn(Integer status, String message){
|
||||
ApiError apiError = new ApiError();
|
||||
apiError.setStatus(status);
|
||||
apiError.setMessage(message);
|
||||
apiError.setTimestamp(LocalDateTime.now());
|
||||
return apiError;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.youchain.exception.handler;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ApiResult {
|
||||
private Object data;//数据
|
||||
private String message;//内容
|
||||
private int status;//编码
|
||||
|
||||
public static ApiResult fail() {
|
||||
|
||||
return result(400, "操作失败!", null);
|
||||
}
|
||||
|
||||
public static ApiResult fail(int code, String msg, Object data) {
|
||||
return result(code, msg, data);
|
||||
}
|
||||
|
||||
public static ApiResult success() {
|
||||
return result(200, "操作成功!", null);
|
||||
}
|
||||
|
||||
public static ApiResult success(Object data) {
|
||||
return result(200, "操作成功!", data);
|
||||
}
|
||||
|
||||
public static ApiResult success(String msg, Object data) {
|
||||
return result(200, msg, data);
|
||||
}
|
||||
|
||||
public static ApiResult success(int status, String msg, Object data) {
|
||||
return result(status, msg, data);
|
||||
}
|
||||
|
||||
public static ApiResult result(int status, String message, Object data) {
|
||||
ApiResult rs = new ApiResult();
|
||||
rs.setStatus(status);
|
||||
rs.setMessage(message);
|
||||
rs.setData(data);
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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.youchain.exception.handler;
|
||||
|
||||
import com.youchain.exception.BadRequestException;
|
||||
import com.youchain.exception.EntityExistException;
|
||||
import com.youchain.exception.EntityNotFoundException;
|
||||
import com.youchain.utils.ThrowableUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import static org.springframework.http.HttpStatus.*;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-23
|
||||
*/
|
||||
@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));
|
||||
ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
|
||||
String message = objectError.getDefaultMessage();
|
||||
if (objectError instanceof FieldError) {
|
||||
message = ((FieldError) objectError).getField() + ": " + message;
|
||||
}
|
||||
return buildResponseEntity(ApiError.error(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一返回
|
||||
*/
|
||||
private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
|
||||
return new ResponseEntity<>(apiError, HttpStatus.valueOf(apiError.getStatus()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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.youchain.utils;
|
||||
|
||||
/**
|
||||
* @author: liaojinlong
|
||||
* @date: 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:";
|
||||
|
||||
String BOM_ACCOUNT_NAME = "bomAccount::id:";
|
||||
}
|
||||
|
|
@ -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.youchain.utils;
|
||||
|
||||
/**
|
||||
* @author: liaojinlong
|
||||
* @date: 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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.youchain.utils;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @website https://eladmin.vip
|
||||
* @description 用于关闭各种连接,缺啥补啥
|
||||
* @date 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) {
|
||||
// 静默关闭
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
package com.youchain.utils;
|
||||
|
||||
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ValueOperations;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class CodeForYmYtil {
|
||||
private static String key_time_type="yyMMdd";
|
||||
public void ce(){
|
||||
new Thread(()->{
|
||||
CodeForYmYtil codeForYmYtil=new CodeForYmYtil();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String code = codeForYmYtil.CodeForYmYtil("ce",5);
|
||||
}
|
||||
}).start();
|
||||
new Thread(()->{
|
||||
CodeForYmYtil codeForYmYtil=new CodeForYmYtil();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String code = codeForYmYtil.CodeForYmYtil("ce",5);
|
||||
}
|
||||
}).start();
|
||||
new Thread(()->{
|
||||
CodeForYmYtil codeForYmYtil=new CodeForYmYtil();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String code = codeForYmYtil.CodeForYmYtil("ce",5);
|
||||
}
|
||||
}).start();
|
||||
new Thread(()->{
|
||||
CodeForYmYtil codeForYmYtil=new CodeForYmYtil();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String code = codeForYmYtil.CodeForYmYtil("ce",5);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
public static synchronized String CodeForYmYtil(String key_code, int len){
|
||||
String code="";
|
||||
String key_time = new SimpleDateFormat(key_time_type).format(Calendar.getInstance().getTime());
|
||||
String key=key_code+key_time;
|
||||
String redisHost = "127.0.0.1";
|
||||
int redisPort = 6379;
|
||||
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisHost, redisPort);
|
||||
LettuceConnectionFactory factory = new LettuceConnectionFactory(config);
|
||||
factory.afterPropertiesSet();
|
||||
RedisTemplate redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(factory);
|
||||
redisTemplate.afterPropertiesSet();
|
||||
|
||||
ValueOperations ops = redisTemplate.opsForValue();
|
||||
String value;
|
||||
// value = ops.get(key).toString();
|
||||
|
||||
if (ops.get(key)==null||ops.get(key).equals("")){
|
||||
ops.set(key, "0");
|
||||
}
|
||||
value = (Integer.valueOf(ops.get(key).toString())+1)+"";
|
||||
ops.set(key, value);
|
||||
while (value.length()<len){
|
||||
value="0"+value;
|
||||
}
|
||||
code=key+value;
|
||||
factory.destroy();
|
||||
return code;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String code = CodeForYmYtil.CodeForYmYtil("pd",5);
|
||||
/* CodeForYmYtil codeForYmYtil=new CodeForYmYtil();
|
||||
codeForYmYtil.ce();*/
|
||||
/*String code = codeForYmYtil.CodeForYmYtil("pt",15);
|
||||
System.out.println(code);*/
|
||||
|
||||
/* String redisHost = "127.0.0.1";
|
||||
int redisPort = 6379;
|
||||
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisHost, redisPort);
|
||||
LettuceConnectionFactory factory = new LettuceConnectionFactory(config);
|
||||
factory.afterPropertiesSet();
|
||||
RedisTemplate redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(factory);
|
||||
redisTemplate.afterPropertiesSet();
|
||||
ValueOperations ops = redisTemplate.opsForValue();
|
||||
|
||||
String value = ops.get("pd")+"";
|
||||
System.out.println(":"+value);
|
||||
factory.destroy();
|
||||
System.out.println("poiuytrew");*/
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* 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.youchain.utils;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author: liaojinlong
|
||||
* @date: 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");
|
||||
|
||||
public static final DateTimeFormatter DFY_MD_HM = DateTimeFormatter.ofPattern("yyyy-MM-dd HH");
|
||||
|
||||
private static SimpleDateFormat ymd = new SimpleDateFormat("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);
|
||||
}
|
||||
|
||||
|
||||
public static Date ymd_date(String fomart) {
|
||||
try {
|
||||
return ymd.parse(fomart);
|
||||
} catch (ParseException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 日期格式化 yyyy-MM-dd
|
||||
*
|
||||
* @param localDateTime /
|
||||
* @return /
|
||||
*/
|
||||
public static String localDateTimeFormatyMd(LocalDateTime localDateTime) {
|
||||
|
||||
return DFY_MD.format(localDateTime);
|
||||
}
|
||||
|
||||
public static String dateYmd(Date date) {
|
||||
return ymd.format(date);
|
||||
}
|
||||
|
||||
//按周天生成批次
|
||||
public static String dateYmdz() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
int year = calendar.get(Calendar.YEAR);
|
||||
int month = calendar.get(Calendar.MONTH) + 1;
|
||||
int day = calendar.get(Calendar.DAY_OF_MONTH);
|
||||
String z="01-07";
|
||||
if(day<=7){
|
||||
z="01-07";
|
||||
}else if(day>7 && day<=14){
|
||||
z="08-14";
|
||||
}else if(day>14 && day<=21){
|
||||
z="15-21";
|
||||
}else if(day>21 && day<=28){
|
||||
z="22-28";
|
||||
}else if(day>28){
|
||||
z="29-31";
|
||||
}
|
||||
return year+"-"+month+"-"+z;
|
||||
}
|
||||
|
||||
public static String formatChageDay(Date date, String type, int value) {
|
||||
Calendar cal = new java.util.GregorianCalendar();
|
||||
cal.setTime(date);
|
||||
if (type.equals("DAY")) {
|
||||
cal.add(Calendar.DATE , value);
|
||||
}
|
||||
if (type.equals("HOUR")) {
|
||||
cal.add(Calendar.HOUR, value);
|
||||
}
|
||||
if (type.equals("MINUTE")) {
|
||||
cal.add(Calendar.MINUTE, value);
|
||||
}
|
||||
if (type.equals("SECOND")) {
|
||||
cal.add(Calendar.SECOND, value);
|
||||
}
|
||||
return ymd.format(cal.getTime());
|
||||
}
|
||||
|
||||
public static Timestamp getBatchTime(int value,Date date) {
|
||||
Calendar cal = new java.util.GregorianCalendar();
|
||||
cal.setTime(date);
|
||||
cal.set(Calendar.HOUR_OF_DAY,8);
|
||||
cal.set(Calendar.MINUTE,30);
|
||||
cal.set(Calendar.MILLISECOND,0);
|
||||
cal.add(Calendar.MINUTE, value);
|
||||
int hour = cal.get(Calendar.HOUR_OF_DAY);
|
||||
int minute = cal.get(Calendar.MINUTE);
|
||||
//11:30-12:30休息
|
||||
if(hour>11||(hour==11&&minute>=30)){
|
||||
cal.add(Calendar.HOUR, 1);
|
||||
}
|
||||
// //17:30-18:30休息
|
||||
// hour = cal.get(Calendar.HOUR_OF_DAY);
|
||||
// if(hour>17||(hour==17&&minute>=30)){
|
||||
// cal.add(Calendar.HOUR, 1);
|
||||
// }
|
||||
return new Timestamp(cal.getTime().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转 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));
|
||||
}
|
||||
|
||||
/**
|
||||
*获取两个字符串计算出小时
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
public static long hoursBetween(String startDateTimeStr,String endDateTimeStr) {
|
||||
// 解析日期时间字符串为 LocalDateTime 对象
|
||||
LocalDateTime startDateTime = LocalDateTime.parse(startDateTimeStr, DFY_MD_HM);
|
||||
LocalDateTime endDateTime = LocalDateTime.parse(endDateTimeStr, DFY_MD_HM);
|
||||
// 计算时间差
|
||||
Duration duration = Duration.between(startDateTime, endDateTime);
|
||||
long hours = duration.toHours(); // 将时间差转换为小时
|
||||
return hours;
|
||||
}
|
||||
|
||||
/**
|
||||
*比较两个日期大小
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
public static int dateComparison (Date date1,Date date2) {
|
||||
int comparison = date1.compareTo(date2);
|
||||
return comparison;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.utils;
|
||||
|
||||
/**
|
||||
* 常用静态常量
|
||||
*
|
||||
* @author Liu Xue
|
||||
* @date 2018-12-26
|
||||
*/
|
||||
public class ElAdminConstant {
|
||||
|
||||
/**
|
||||
* 用于IP定位转换
|
||||
*/
|
||||
public static final String REGION = "内网IP|内网IP";
|
||||
/**
|
||||
* win 系统
|
||||
*/
|
||||
public static final String WIN = "win";
|
||||
|
||||
/**
|
||||
* mac 系统
|
||||
*/
|
||||
public static final String MAC = "mac";
|
||||
|
||||
/**
|
||||
* 常用接口
|
||||
*/
|
||||
public static class Url {
|
||||
// IP归属地查询
|
||||
public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp?ip=%s&json=true";
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.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;
|
||||
|
||||
/**
|
||||
* 加密
|
||||
* @author Liu Xue
|
||||
* @date 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
* 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.youchain.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.youchain.config.FileProperties;
|
||||
import com.youchain.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 工具包
|
||||
*
|
||||
* @author Liu Xue
|
||||
* @date 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 APK = "APK";
|
||||
public static final String ZIP = "ZIP";
|
||||
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 = "-" +SecurityUtils.getCurrentUsername()+ "-" + 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 Exception {
|
||||
log.error("list:"+list.size());
|
||||
if(list.size()>0){
|
||||
if(list.get(0).keySet().size()<=0){
|
||||
throw new BadRequestException("请先保存配置");
|
||||
}
|
||||
}else{
|
||||
throw new BadRequestException("导出数据长度为0");
|
||||
}
|
||||
|
||||
FileProperties properties=SpringContextHolder.getBean(FileProperties.class);
|
||||
String tempPath=properties.getPath().getPath()+"downexcel\\"+IdUtil.fastSimpleUUID() + ".xlsx";
|
||||
File file = new File(tempPath);
|
||||
log.error(tempPath);
|
||||
|
||||
//BigExcelWriter writer = ExcelUtil.getBigWriter(file);
|
||||
MyExcelWriter writer =MyExcelWriter.getBigWriter(file);
|
||||
// 一次性写出内容,使用默认样式,强制输出标题
|
||||
writer.write(list, true);
|
||||
//列宽自适应
|
||||
writer.autoSizeColumnAll();
|
||||
//response为HttpServletResponse对象
|
||||
response.setContentType("application/vnd.ms-excel;charset=utf-8");
|
||||
//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
|
||||
response.setHeader("Content-Disposition","attachment;filename=file.xls");
|
||||
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";
|
||||
String apk = "apk";
|
||||
String zip = "zip rar 7z";
|
||||
if (apk.contains(type)) {
|
||||
return APK;
|
||||
}else if (zip.contains(type)) {
|
||||
return ZIP;
|
||||
}else 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));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.youchain.utils;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import org.apache.commons.compress.utils.IOUtils;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
public class HttpPostUtil {
|
||||
public static String sendPostReq(String api_url, String request){
|
||||
InputStream instr = null;
|
||||
String str = "";
|
||||
try {
|
||||
URL url = new URL(api_url);
|
||||
URLConnection urlCon = url.openConnection();
|
||||
urlCon.setConnectTimeout(3000);
|
||||
byte[] xmlData = request.getBytes();
|
||||
urlCon.setDoOutput(true);
|
||||
urlCon.setDoInput(true);
|
||||
urlCon.setUseCaches(false);
|
||||
urlCon.setRequestProperty("content-Type", "application/json");
|
||||
urlCon.setRequestProperty("charset", "UTF-8");
|
||||
urlCon.setRequestProperty("Content-length", String.valueOf(xmlData.length));
|
||||
DataOutputStream printout = new DataOutputStream(urlCon.getOutputStream());
|
||||
printout.write(xmlData);
|
||||
printout.flush();
|
||||
printout.close();
|
||||
instr = urlCon.getInputStream();
|
||||
byte[] bis = IOUtils.toByteArray(instr);
|
||||
String ResponseString = new String(bis, "UTF-8");
|
||||
if ((ResponseString == null) || ("".equals(ResponseString.trim()))) {
|
||||
System.out.println("返回空");
|
||||
}
|
||||
str = ResponseString;
|
||||
}catch (Exception e){
|
||||
throw new Error(e.getMessage());
|
||||
}
|
||||
/*JSONObject jsonObject=new JSONObject();
|
||||
jsonObject.accumulate("code", "0");
|
||||
jsonObject.accumulate("message", "");
|
||||
jsonObject.accumulate("success", true);
|
||||
jsonObject.accumulate("data", "");
|
||||
str= JSONUtil.toJsonStr(jsonObject.toString());*/
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package com.youchain.utils;
|
||||
|
||||
import cn.hutool.core.exceptions.DependencyException;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.poi.excel.BigExcelWriter;
|
||||
import org.apache.poi.xssf.streaming.SXSSFSheet;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class MyExcelWriter extends BigExcelWriter {
|
||||
public static MyExcelWriter getBigWriter(File file) {
|
||||
try {
|
||||
return new MyExcelWriter(file);
|
||||
} catch (NoClassDefFoundError var1) {
|
||||
throw new DependencyException((Throwable) ObjectUtil.defaultIfNull(var1.getCause(), var1), "You need to add dependency of 'poi-ooxml' to your project, and version >= 4.1.2", new Object[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public MyExcelWriter(File file){
|
||||
super(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigExcelWriter autoSizeColumnAll() {
|
||||
final SXSSFSheet sheet = (SXSSFSheet)this.sheet;
|
||||
sheet.trackAllColumnsForAutoSizing();
|
||||
super.autoSizeColumnAll();
|
||||
for (int i = 0; i <sheet.getRow(sheet.getLastRowNum()).getPhysicalNumberOfCells(); i++) {
|
||||
// 解决自动设置列宽中文失效的问题
|
||||
int colWidth =(sheet.getColumnWidth(i) * 17 / 8);
|
||||
if(colWidth<255*256){
|
||||
sheet.setColumnWidth(i, colWidth < 3000 ? 3000 : colWidth);
|
||||
}else{
|
||||
sheet.setColumnWidth(i,6000 );
|
||||
}
|
||||
|
||||
}
|
||||
sheet.untrackAllColumnsForAutoSizing();
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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.youchain.utils;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 分页工具
|
||||
* @author Liu Xue
|
||||
* @date 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* 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.youchain.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.youchain.annotation.DataPermission;
|
||||
import com.youchain.annotation.Query;
|
||||
import javax.persistence.criteria.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 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 GREATER_THAN_NQ:
|
||||
list.add(cb.greaterThan(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);
|
||||
if(between.size() == 2){
|
||||
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;
|
||||
case GREATER_THAN_2:
|
||||
list.add(cb.greaterThanOrEqualTo(root.get(attributeName), root.get((String)val)));
|
||||
break;
|
||||
case LESS_THAN_2:_THAN_2:
|
||||
list.add(cb.lessThanOrEqualTo(root.get(attributeName), root.get((String)val)));
|
||||
break;
|
||||
case GREATER_THAN_NQ_2:
|
||||
list.add(cb.greaterThan(root.get(attributeName), root.get((String)val)));
|
||||
break;
|
||||
case LESS_THAN_NQ_2:
|
||||
list.add(cb.lessThan(root.get(attributeName), root.get((String)val)));
|
||||
break;
|
||||
case EQUAL_2:
|
||||
list.add(cb.equal(root.get(attributeName), root.get((String)val)));
|
||||
break;
|
||||
case NOT_EQUAL_2:
|
||||
list.add(cb.notEqual(root.get(attributeName), root.get((String)val)));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,741 @@
|
|||
/*
|
||||
* 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.youchain.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.data.redis.serializer.StringRedisSerializer;
|
||||
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;
|
||||
this.redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||
this.redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
this.redisTemplate.setStringSerializer(new StringRedisSerializer());
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定缓存失效时间
|
||||
*
|
||||
* @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) {
|
||||
if (redisTemplate.hasKey(key))
|
||||
keySet.add(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) {
|
||||
try{
|
||||
Object value=redisTemplate.opsForValue().get(key);
|
||||
return value == null ? null :value ;
|
||||
}catch (Exception e){
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Object get(String key,Object def) {
|
||||
try{
|
||||
Object value=redisTemplate.opsForValue().get(key);
|
||||
return value == null ? def :value ;
|
||||
}catch (Exception e){
|
||||
return def;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
public Object hget(String key, String item,Object def) {
|
||||
try {
|
||||
Object value = redisTemplate.opsForHash().get(key, item);
|
||||
return value == null ? def:value;
|
||||
}catch (Exception e){
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取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("--------------------------------------------");
|
||||
}
|
||||
|
||||
public Set<Object> getAllKey(String pattern){
|
||||
return redisTemplate.keys(pattern);
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.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
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-24
|
||||
*/
|
||||
public class RequestHolder {
|
||||
|
||||
public static HttpServletRequest getHttpServletRequest() {
|
||||
return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
package com.youchain.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 工具类,公钥私钥生成,加解密
|
||||
* @date 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.trim()));
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* 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.youchain.utils;
|
||||
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.youchain.exception.BadRequestException;
|
||||
import com.youchain.utils.enums.DataScopeEnum;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 获取当前登录的用户
|
||||
* @author Liu Xue
|
||||
* @date 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();
|
||||
//log.error("-------------------");
|
||||
String str_json=JSONUtil.toJsonStr(userDetails);
|
||||
// log.error(str_json);
|
||||
JSONObject obj=new JSONObject(str_json);
|
||||
JSONArray array=obj.getJSONArray("dataScopes");
|
||||
//JSONArray array = JSONUtil.parseArray(new JSONObject(userDetails).get("dataScopes"));
|
||||
//log.error(array.toString());
|
||||
//log.error(array.size()+"");
|
||||
return JSONUtil.toList(array,Long.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取数据权限级别
|
||||
* @return 级别
|
||||
*/
|
||||
public static String getDataScopeType() {
|
||||
List<Long> dataScopes = getCurrentUserDataScope();
|
||||
if(dataScopes.size() != 0){
|
||||
return "";
|
||||
}
|
||||
return DataScopeEnum.ALL.getValue();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* 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.youchain.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 org.springframework.stereotype.Service;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Jie
|
||||
* @date 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 @Service 的所有 bean 名称
|
||||
* @return /
|
||||
*/
|
||||
public static List<String> getAllServiceBeanName() {
|
||||
return new ArrayList<>(Arrays.asList(applicationContext
|
||||
.getBeanNamesForAnnotation(Service.class)));
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.utils;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.youchain.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;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* 字符串工具类, 继承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 "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.utils;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* 异常工具 2019-01-06
|
||||
* @author Liu Xue
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.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;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* 翻译工具类
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.utils;
|
||||
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.youchain.exception.BadRequestException;
|
||||
|
||||
/**
|
||||
* 验证工具
|
||||
*
|
||||
* @author Liu Xue
|
||||
* @date 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 Validator.isEmail(email);
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.utils.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 验证码业务场景
|
||||
* </p>
|
||||
* @author Liu Xue
|
||||
* @date 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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.youchain.utils.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 验证码业务场景对应的 Redis 中的 key
|
||||
* </p>
|
||||
* @author Liu Xue
|
||||
* @date 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;
|
||||
}
|
||||
|
|
@ -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.youchain.utils.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据权限枚举
|
||||
* </p>
|
||||
* @author Liu Xue
|
||||
* @date 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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.youchain.utils.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @website https://eladmin.vip
|
||||
* @description
|
||||
* @date 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
//
|
||||
// Source code recreated from a .class file by IntelliJ IDEA
|
||||
// (powered by FernFlower decompiler)
|
||||
//
|
||||
|
||||
package org.apache.poi.util;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import javax.xml.stream.XMLEventFactory;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLOutputFactory;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.XMLReader;
|
||||
|
||||
@Internal
|
||||
public final class XMLHelper {
|
||||
static final String FEATURE_LOAD_DTD_GRAMMAR = "http://apache.org/xml/features/nonvalidating/load-dtd-grammar";
|
||||
static final String FEATURE_LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
|
||||
static final String FEATURE_DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
|
||||
static final String FEATURE_PARAMETER_ENTITIES = "http://xml.org/sax/features/external-parameter-entities";
|
||||
static final String FEATURE_EXTERNAL_ENTITIES = "http://xml.org/sax/features/external-general-entities";
|
||||
static final String PROPERTY_ENTITY_EXPANSION_LIMIT = "http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit";
|
||||
static final String PROPERTY_SECURITY_MANAGER = "http://apache.org/xml/properties/security-manager";
|
||||
static final String METHOD_ENTITY_EXPANSION_XERCES = "setEntityExpansionLimit";
|
||||
static final String[] SECURITY_MANAGERS = new String[]{"org.apache.xerces.util.SecurityManager"};
|
||||
private static final Logger LOG = LogManager.getLogger(XMLHelper.class);
|
||||
private static long lastLog;
|
||||
private static final DocumentBuilderFactory documentBuilderFactory = getDocumentBuilderFactory();
|
||||
private static final SAXParserFactory saxFactory = getSaxParserFactory();
|
||||
|
||||
private XMLHelper() {
|
||||
}
|
||||
|
||||
public static DocumentBuilderFactory getDocumentBuilderFactory() {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setExpandEntityReferences(false);
|
||||
factory.setValidating(false);
|
||||
trySet(factory::setFeature, "http://javax.xml.XMLConstants/feature/secure-processing", true);
|
||||
trySet(factory::setAttribute, "http://javax.xml.XMLConstants/property/accessExternalSchema", "");
|
||||
trySet(factory::setAttribute, "http://javax.xml.XMLConstants/property/accessExternalDTD", "");
|
||||
trySet(factory::setFeature, "http://xml.org/sax/features/external-general-entities", false);
|
||||
trySet(factory::setFeature, "http://xml.org/sax/features/external-parameter-entities", false);
|
||||
trySet(factory::setFeature, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
trySet(factory::setFeature, "http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
|
||||
trySet(factory::setFeature, "http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
trySet((n, b) -> {
|
||||
factory.setXIncludeAware(b);
|
||||
}, "XIncludeAware", false);
|
||||
Object manager = getXercesSecurityManager();
|
||||
if (manager == null || !trySet(factory::setAttribute, "http://apache.org/xml/properties/security-manager", manager)) {
|
||||
trySet(factory::setAttribute, "http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit", 1);
|
||||
}
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
public static DocumentBuilder newDocumentBuilder() {
|
||||
try {
|
||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||
documentBuilder.setEntityResolver(XMLHelper::ignoreEntity);
|
||||
documentBuilder.setErrorHandler(new DocHelperErrorHandler());
|
||||
return documentBuilder;
|
||||
} catch (ParserConfigurationException var1) {
|
||||
throw new IllegalStateException("cannot create a DocumentBuilder", var1);
|
||||
}
|
||||
}
|
||||
|
||||
public static SAXParserFactory getSaxParserFactory() {
|
||||
try {
|
||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
factory.setValidating(false);
|
||||
factory.setNamespaceAware(true);
|
||||
trySet(factory::setFeature, "http://javax.xml.XMLConstants/feature/secure-processing", true);
|
||||
trySet(factory::setFeature, "http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
|
||||
trySet(factory::setFeature, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
trySet(factory::setFeature, "http://xml.org/sax/features/external-general-entities", false);
|
||||
trySet(factory::setFeature, "http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
return factory;
|
||||
} catch (Error | RuntimeException var1) {
|
||||
logThrowable(var1, "Failed to create SAXParserFactory", "-");
|
||||
throw var1;
|
||||
} catch (Exception var2) {
|
||||
logThrowable(var2, "Failed to create SAXParserFactory", "-");
|
||||
throw new RuntimeException("Failed to create SAXParserFactory", var2);
|
||||
}
|
||||
}
|
||||
|
||||
public static XMLReader newXMLReader() throws SAXException, ParserConfigurationException {
|
||||
XMLReader xmlReader = saxFactory.newSAXParser().getXMLReader();
|
||||
xmlReader.setEntityResolver(XMLHelper::ignoreEntity);
|
||||
trySet(xmlReader::setFeature, "http://javax.xml.XMLConstants/feature/secure-processing", true);
|
||||
trySet(xmlReader::setFeature, "http://xml.org/sax/features/external-general-entities", false);
|
||||
Object manager = getXercesSecurityManager();
|
||||
if (manager == null || !trySet(xmlReader::setProperty, "http://apache.org/xml/properties/security-manager", manager)) {
|
||||
trySet(xmlReader::setProperty, "http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit", 1);
|
||||
}
|
||||
|
||||
return xmlReader;
|
||||
}
|
||||
|
||||
public static XMLInputFactory newXMLInputFactory() {
|
||||
XMLInputFactory factory = XMLInputFactory.newInstance();
|
||||
trySet(factory::setProperty, "javax.xml.stream.isNamespaceAware", true);
|
||||
trySet(factory::setProperty, "javax.xml.stream.isValidating", false);
|
||||
trySet(factory::setProperty, "javax.xml.stream.supportDTD", false);
|
||||
trySet(factory::setProperty, "javax.xml.stream.isSupportingExternalEntities", false);
|
||||
return factory;
|
||||
}
|
||||
|
||||
public static XMLOutputFactory newXMLOutputFactory() {
|
||||
XMLOutputFactory factory = XMLOutputFactory.newInstance();
|
||||
trySet(factory::setProperty, "javax.xml.stream.isRepairingNamespaces", true);
|
||||
return factory;
|
||||
}
|
||||
|
||||
public static XMLEventFactory newXMLEventFactory() {
|
||||
return XMLEventFactory.newInstance();
|
||||
}
|
||||
|
||||
public static TransformerFactory getTransformerFactory() {
|
||||
TransformerFactory factory = TransformerFactory.newInstance();
|
||||
trySet(factory::setFeature, "http://javax.xml.XMLConstants/feature/secure-processing", true);
|
||||
quietSet(factory::setAttribute, "http://javax.xml.XMLConstants/property/accessExternalDTD", "");
|
||||
trySet(factory::setAttribute, "http://javax.xml.XMLConstants/property/accessExternalStylesheet", "");
|
||||
quietSet(factory::setAttribute, "http://javax.xml.XMLConstants/property/accessExternalSchema", "");
|
||||
return factory;
|
||||
}
|
||||
|
||||
public static Transformer newTransformer() throws TransformerConfigurationException {
|
||||
Transformer serializer = getTransformerFactory().newTransformer();
|
||||
serializer.setOutputProperty("encoding", "UTF-8");
|
||||
serializer.setOutputProperty("indent", "no");
|
||||
serializer.setOutputProperty("method", "xml");
|
||||
return serializer;
|
||||
}
|
||||
|
||||
public static SchemaFactory getSchemaFactory() {
|
||||
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
|
||||
trySet(factory::setFeature, "http://javax.xml.XMLConstants/feature/secure-processing", true);
|
||||
trySet(factory::setProperty, "http://javax.xml.XMLConstants/property/accessExternalDTD", "");
|
||||
trySet(factory::setProperty, "http://javax.xml.XMLConstants/property/accessExternalStylesheet", "");
|
||||
trySet(factory::setProperty, "http://javax.xml.XMLConstants/property/accessExternalSchema", "");
|
||||
return factory;
|
||||
}
|
||||
|
||||
private static Object getXercesSecurityManager() {
|
||||
String[] var0 = SECURITY_MANAGERS;
|
||||
int var1 = var0.length;
|
||||
|
||||
for(int var2 = 0; var2 < var1; ++var2) {
|
||||
String securityManagerClassName = var0[var2];
|
||||
|
||||
try {
|
||||
Object mgr = Class.forName(securityManagerClassName).getDeclaredConstructor().newInstance();
|
||||
Method setLimit = mgr.getClass().getMethod("setEntityExpansionLimit", Integer.TYPE);
|
||||
setLimit.invoke(mgr, 1);
|
||||
return mgr;
|
||||
} catch (ClassNotFoundException var6) {
|
||||
} catch (Throwable var7) {
|
||||
logThrowable(var7, "SAX Feature unsupported", securityManagerClassName);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean trySet(SecurityFeature feature, String name, boolean value) {
|
||||
try {
|
||||
feature.accept(name, value);
|
||||
return true;
|
||||
} catch (Exception var4) {
|
||||
logThrowable(var4, "SAX Feature unsupported", name);
|
||||
} catch (Error var5) {
|
||||
logThrowable(var5, "Cannot set SAX feature because outdated XML parser in classpath", name);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean trySet(SecurityProperty property, String name, Object value) {
|
||||
try {
|
||||
property.accept(name, value);
|
||||
return true;
|
||||
} catch (Exception var4) {
|
||||
logThrowable(var4, "SAX Feature unsupported", name);
|
||||
} catch (Error var5) {
|
||||
logThrowable(var5, "Cannot set SAX feature because outdated XML parser in classpath", name);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean quietSet(SecurityProperty property, String name, Object value) {
|
||||
try {
|
||||
property.accept(name, value);
|
||||
return true;
|
||||
} catch (Error | Exception var4) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void logThrowable(Throwable t, String message, String name) {
|
||||
if (System.currentTimeMillis() > lastLog + TimeUnit.MINUTES.toMillis(5L)) {
|
||||
//LOG.atWarn().withThrowable(t).log("{} [log suppressed for 5 minutes]{}", message, name);
|
||||
lastLog = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static InputSource ignoreEntity(String publicId, String systemId) {
|
||||
return new InputSource(new StringReader(""));
|
||||
}
|
||||
|
||||
private static class DocHelperErrorHandler implements ErrorHandler {
|
||||
private DocHelperErrorHandler() {
|
||||
}
|
||||
|
||||
public void warning(SAXParseException exception) {
|
||||
this.printError(Level.WARN, exception);
|
||||
}
|
||||
|
||||
public void error(SAXParseException exception) {
|
||||
this.printError(Level.ERROR, exception);
|
||||
}
|
||||
|
||||
public void fatalError(SAXParseException exception) throws SAXException {
|
||||
this.printError(Level.FATAL, exception);
|
||||
throw exception;
|
||||
}
|
||||
|
||||
private void printError(Level type, SAXParseException ex) {
|
||||
String systemId = ex.getSystemId();
|
||||
if (systemId != null) {
|
||||
int index = systemId.lastIndexOf(47);
|
||||
if (index != -1) {
|
||||
systemId = systemId.substring(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
String message = (systemId == null ? "" : systemId) + ':' + ex.getLineNumber() + ':' + ex.getColumnNumber() + ':' + ex.getMessage();
|
||||
XMLHelper.LOG.atLevel(type).withThrowable(ex).log(message);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface SecurityProperty {
|
||||
void accept(String var1, Object var2) throws SAXException;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface SecurityFeature {
|
||||
void accept(String var1, boolean var2) throws ParserConfigurationException, SAXException, TransformerException;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package org.apache.poi.xssf.streaming;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.poi.common.usermodel.HyperlinkType;
|
||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
||||
import org.apache.poi.ss.usermodel.DataFormat;
|
||||
import org.apache.poi.ss.usermodel.ExtendedColor;
|
||||
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||
import org.apache.poi.ss.util.AreaReference;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.xssf.usermodel.XSSFCreationHelper;
|
||||
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
||||
|
||||
public class SXSSFCreationHelper implements CreationHelper {
|
||||
private static final Logger LOG = LogManager.getLogger(SXSSFCreationHelper.class);
|
||||
private final SXSSFWorkbook wb;
|
||||
private final XSSFCreationHelper helper;
|
||||
|
||||
@Internal
|
||||
public SXSSFCreationHelper(SXSSFWorkbook workbook) {
|
||||
this.helper = new XSSFCreationHelper(workbook.getXSSFWorkbook());
|
||||
this.wb = workbook;
|
||||
}
|
||||
|
||||
public XSSFRichTextString createRichTextString(String text) {
|
||||
// LOG.atInfo().log("SXSSF doesn't support Rich Text Strings, any formatting information will be lost");
|
||||
return new XSSFRichTextString(text);
|
||||
}
|
||||
|
||||
public SXSSFFormulaEvaluator createFormulaEvaluator() {
|
||||
return new SXSSFFormulaEvaluator(this.wb);
|
||||
}
|
||||
|
||||
public DataFormat createDataFormat() {
|
||||
return this.helper.createDataFormat();
|
||||
}
|
||||
|
||||
public Hyperlink createHyperlink(HyperlinkType type) {
|
||||
return this.helper.createHyperlink(type);
|
||||
}
|
||||
|
||||
public ExtendedColor createExtendedColor() {
|
||||
return this.helper.createExtendedColor();
|
||||
}
|
||||
|
||||
public ClientAnchor createClientAnchor() {
|
||||
return this.helper.createClientAnchor();
|
||||
}
|
||||
|
||||
public AreaReference createAreaReference(String reference) {
|
||||
return new AreaReference(reference, this.wb.getSpreadsheetVersion());
|
||||
}
|
||||
|
||||
public AreaReference createAreaReference(CellReference topLeft, CellReference bottomRight) {
|
||||
return new AreaReference(topLeft, bottomRight, this.wb.getSpreadsheetVersion());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package com.youchain.utils;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
|
||||
public class DateUtilsTest {
|
||||
@Test
|
||||
public void test1() {
|
||||
long l = System.currentTimeMillis() / 1000;
|
||||
LocalDateTime localDateTime = DateUtil.fromTimeStamp(l);
|
||||
System.out.print(DateUtil.localDateTimeFormatyMdHms(localDateTime));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
System.out.println(DateUtil.localDateTimeFormatyMdHms(now));
|
||||
Date date = DateUtil.toDate(now);
|
||||
LocalDateTime localDateTime = DateUtil.toLocalDateTime(date);
|
||||
System.out.println(DateUtil.localDateTimeFormatyMdHms(localDateTime));
|
||||
LocalDateTime localDateTime1 = DateUtil.fromTimeStamp(date.getTime() / 1000);
|
||||
System.out.println(DateUtil.localDateTimeFormatyMdHms(localDateTime1));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.youchain.utils;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class EncryptUtilsTest {
|
||||
|
||||
/**
|
||||
* 对称加密
|
||||
*/
|
||||
@Test
|
||||
public void testDesEncrypt() {
|
||||
try {
|
||||
Assertions.assertEquals("7772841DC6099402", EncryptUtils.desEncrypt("123456"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对称解密
|
||||
*/
|
||||
@Test
|
||||
public void testDesDecrypt() {
|
||||
try {
|
||||
Assertions.assertEquals("123456", EncryptUtils.desDecrypt("7772841DC6099402"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package com.youchain.utils;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class FileUtilTest {
|
||||
|
||||
@Test
|
||||
public void testToFile() {
|
||||
long retval = FileUtil.toFile(new MockMultipartFile("foo", (byte[]) null)).getTotalSpace();
|
||||
assertEquals(500695072768L, retval);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetExtensionName() {
|
||||
Assertions.assertEquals("foo", FileUtil.getExtensionName("foo"));
|
||||
Assertions.assertEquals("exe", FileUtil.getExtensionName("bar.exe"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFileNameNoEx() {
|
||||
Assertions.assertEquals("foo", FileUtil.getFileNameNoEx("foo"));
|
||||
Assertions.assertEquals("bar", FileUtil.getFileNameNoEx("bar.txt"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSize() {
|
||||
Assertions.assertEquals("1000B ", FileUtil.getSize(1000));
|
||||
Assertions.assertEquals("1.00KB ", FileUtil.getSize(1024));
|
||||
Assertions.assertEquals("1.00MB ", FileUtil.getSize(1048576));
|
||||
Assertions.assertEquals("1.00GB ", FileUtil.getSize(1073741824));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package com.youchain.utils;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
public class StringUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testToCamelCase() {
|
||||
assertNull(StringUtils.toCamelCase(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToCapitalizeCamelCase() {
|
||||
assertNull(StringUtils.toCapitalizeCamelCase(null));
|
||||
Assertions.assertEquals("HelloWorld", StringUtils.toCapitalizeCamelCase("hello_world"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToUnderScoreCase() {
|
||||
assertNull(StringUtils.toUnderScoreCase(null));
|
||||
Assertions.assertEquals("hello_world", StringUtils.toUnderScoreCase("helloWorld"));
|
||||
Assertions.assertEquals("\u0000\u0000", StringUtils.toUnderScoreCase("\u0000\u0000"));
|
||||
Assertions.assertEquals("\u0000_a", StringUtils.toUnderScoreCase("\u0000A"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetWeekDay() {
|
||||
SimpleDateFormat simpleDateformat = new SimpleDateFormat("E");
|
||||
Assertions.assertEquals(simpleDateformat.format(new Date()), StringUtils.getWeekDay());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIP() {
|
||||
Assertions.assertEquals("127.0.0.1", StringUtils.getIp(new MockHttpServletRequest()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?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>youchain</artifactId>
|
||||
<groupId>com.youchain</groupId>
|
||||
<version>2.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>youchain-generator</artifactId>
|
||||
<name>代码生成模块</name>
|
||||
|
||||
<properties>
|
||||
<configuration.version>1.10</configuration.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.youchain</groupId>
|
||||
<artifactId>youchain-common</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
|
||||
<!--模板引擎-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/commons-configuration/commons-configuration -->
|
||||
<dependency>
|
||||
<groupId>commons-configuration</groupId>
|
||||
<artifactId>commons-configuration</artifactId>
|
||||
<version>${configuration.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.youchain.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import com.youchain.utils.GenUtil;
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 列的数据信息
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-02
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@Table(name = "code_column_config")
|
||||
public class ColumnInfo implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "column_id")
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "表名")
|
||||
private String tableName;
|
||||
|
||||
@ApiModelProperty(value = "数据库字段名称")
|
||||
private String columnName;
|
||||
|
||||
@ApiModelProperty(value = "数据库字段类型")
|
||||
private String columnType;
|
||||
|
||||
@ApiModelProperty(value = "数据库字段键类型")
|
||||
private String keyType;
|
||||
|
||||
@ApiModelProperty(value = "字段额外的参数")
|
||||
private String extra;
|
||||
|
||||
@ApiModelProperty(value = "数据库字段描述")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty(value = "是否必填")
|
||||
private Boolean notNull;
|
||||
|
||||
@ApiModelProperty(value = "是否在列表显示")
|
||||
private Boolean listShow;
|
||||
|
||||
@ApiModelProperty(value = "是否表单显示")
|
||||
private Boolean formShow;
|
||||
|
||||
@ApiModelProperty(value = "表单类型")
|
||||
private String formType;
|
||||
|
||||
@ApiModelProperty(value = "查询 1:模糊 2:精确")
|
||||
private String queryType;
|
||||
|
||||
@ApiModelProperty(value = "字典名称")
|
||||
private String dictName;
|
||||
|
||||
@ApiModelProperty(value = "日期注解")
|
||||
private String dateAnnotation;
|
||||
|
||||
public ColumnInfo(String tableName, String columnName, Boolean notNull, String columnType, String remark, String keyType, String extra) {
|
||||
this.tableName = tableName;
|
||||
this.columnName = columnName;
|
||||
this.columnType = columnType;
|
||||
this.keyType = keyType;
|
||||
this.extra = extra;
|
||||
this.notNull = notNull;
|
||||
if(GenUtil.PK.equalsIgnoreCase(keyType) && GenUtil.EXTRA.equalsIgnoreCase(extra)){
|
||||
this.notNull = false;
|
||||
}
|
||||
this.remark = remark;
|
||||
this.listShow = true;
|
||||
this.formShow = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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.youchain.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 代码生成配置
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-03
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@Table(name = "code_gen_config")
|
||||
public class GenConfig implements Serializable {
|
||||
|
||||
public GenConfig(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
@Id
|
||||
@Column(name = "config_id")
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "表名")
|
||||
private String tableName;
|
||||
|
||||
@ApiModelProperty(value = "接口名称")
|
||||
private String apiAlias;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "包路径")
|
||||
private String pack;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "模块名")
|
||||
private String moduleName;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "前端文件路径")
|
||||
private String path;
|
||||
|
||||
@ApiModelProperty(value = "前端文件路径")
|
||||
private String apiPath;
|
||||
|
||||
@ApiModelProperty(value = "作者")
|
||||
private String author;
|
||||
|
||||
@ApiModelProperty(value = "表前缀")
|
||||
private String prefix;
|
||||
|
||||
@ApiModelProperty(value = "是否覆盖")
|
||||
private Boolean cover = false;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.youchain.domain.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 表的数据信息
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-02
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TableInfo {
|
||||
|
||||
/** 表名称 */
|
||||
private Object tableName;
|
||||
|
||||
/** 创建日期 */
|
||||
private Object createTime;
|
||||
|
||||
/** 数据库引擎 */
|
||||
private Object engine;
|
||||
|
||||
/** 编码集 */
|
||||
private Object coding;
|
||||
|
||||
/** 备注 */
|
||||
private Object remark;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.youchain.repository;
|
||||
|
||||
import com.youchain.domain.ColumnInfo;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-14
|
||||
*/
|
||||
public interface ColumnInfoRepository extends JpaRepository<ColumnInfo,Long> {
|
||||
|
||||
/**
|
||||
* 查询表信息
|
||||
* @param tableName 表格名
|
||||
* @return 表信息
|
||||
*/
|
||||
List<ColumnInfo> findByTableNameOrderByIdAsc(String tableName);
|
||||
}
|
||||
|
|
@ -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.youchain.repository;
|
||||
|
||||
import com.youchain.domain.GenConfig;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-14
|
||||
*/
|
||||
public interface GenConfigRepository extends JpaRepository<GenConfig,Long> {
|
||||
|
||||
/**
|
||||
* 查询表配置
|
||||
* @param tableName 表名
|
||||
* @return /
|
||||
*/
|
||||
GenConfig findByTableName(String tableName);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.youchain.rest;
|
||||
|
||||
import com.youchain.domain.GenConfig;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.youchain.service.GenConfigService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-14
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/api/genConfig")
|
||||
@Api(tags = "系统:代码生成器配置管理")
|
||||
public class GenConfigController {
|
||||
|
||||
private final GenConfigService genConfigService;
|
||||
|
||||
@ApiOperation("查询")
|
||||
@GetMapping(value = "/{tableName}")
|
||||
public ResponseEntity<Object> queryGenConfig(@PathVariable String tableName){
|
||||
return new ResponseEntity<>(genConfigService.find(tableName), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@ApiOperation("修改")
|
||||
public ResponseEntity<Object> updateGenConfig(@Validated @RequestBody GenConfig genConfig){
|
||||
return new ResponseEntity<>(genConfigService.update(genConfig.getTableName(), genConfig),HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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.youchain.rest;
|
||||
|
||||
import com.youchain.exception.BadRequestException;
|
||||
import com.youchain.utils.PageUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.youchain.domain.ColumnInfo;
|
||||
import com.youchain.service.GenConfigService;
|
||||
import com.youchain.service.GeneratorService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-02
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/api/generator")
|
||||
@Api(tags = "系统:代码生成管理")
|
||||
public class GeneratorController {
|
||||
|
||||
private final GeneratorService generatorService;
|
||||
private final GenConfigService genConfigService;
|
||||
|
||||
@Value("${generator.enabled}")
|
||||
private Boolean generatorEnabled;
|
||||
|
||||
@ApiOperation("查询数据库数据")
|
||||
@GetMapping(value = "/tables/all")
|
||||
public ResponseEntity<Object> queryAllTables(){
|
||||
return new ResponseEntity<>(generatorService.getTables(), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("查询数据库数据")
|
||||
@GetMapping(value = "/tables")
|
||||
public ResponseEntity<Object> queryTables(@RequestParam(defaultValue = "") String name,
|
||||
@RequestParam(defaultValue = "0")Integer page,
|
||||
@RequestParam(defaultValue = "10")Integer size){
|
||||
int[] startEnd = PageUtil.transToStartEnd(page, size);
|
||||
return new ResponseEntity<>(generatorService.getTables(name,startEnd), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("查询字段数据")
|
||||
@GetMapping(value = "/columns")
|
||||
public ResponseEntity<Object> queryColumns(@RequestParam String tableName){
|
||||
List<ColumnInfo> columnInfos = generatorService.getColumns(tableName);
|
||||
return new ResponseEntity<>(PageUtil.toPage(columnInfos,columnInfos.size()), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("保存字段数据")
|
||||
@PutMapping
|
||||
public ResponseEntity<HttpStatus> saveColumn(@RequestBody List<ColumnInfo> columnInfos){
|
||||
generatorService.save(columnInfos);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("同步字段数据")
|
||||
@PostMapping(value = "sync")
|
||||
public ResponseEntity<HttpStatus> syncColumn(@RequestBody List<String> tables){
|
||||
for (String table : tables) {
|
||||
generatorService.sync(generatorService.getColumns(table), generatorService.query(table));
|
||||
}
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("生成代码")
|
||||
@PostMapping(value = "/{tableName}/{type}")
|
||||
public ResponseEntity<Object> generatorCode(@PathVariable String tableName, @PathVariable Integer type, HttpServletRequest request, HttpServletResponse response){
|
||||
if(!generatorEnabled && type == 0){
|
||||
throw new BadRequestException("此环境不允许生成代码,请选择预览或者下载查看!");
|
||||
}
|
||||
switch (type){
|
||||
// 生成代码
|
||||
case 0: generatorService.generator(genConfigService.find(tableName), generatorService.getColumns(tableName));
|
||||
break;
|
||||
// 预览
|
||||
case 1: return generatorService.preview(genConfigService.find(tableName), generatorService.getColumns(tableName));
|
||||
// 打包
|
||||
case 2: generatorService.download(genConfigService.find(tableName), generatorService.getColumns(tableName), request, response);
|
||||
break;
|
||||
default: throw new BadRequestException("没有这个选项");
|
||||
}
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.youchain.service;
|
||||
|
||||
import com.youchain.domain.GenConfig;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-14
|
||||
*/
|
||||
public interface GenConfigService {
|
||||
|
||||
/**
|
||||
* 查询表配置
|
||||
* @param tableName 表名
|
||||
* @return 表配置
|
||||
*/
|
||||
GenConfig find(String tableName);
|
||||
|
||||
/**
|
||||
* 更新表配置
|
||||
* @param tableName 表名
|
||||
* @param genConfig 表配置
|
||||
* @return 表配置
|
||||
*/
|
||||
GenConfig update(String tableName, GenConfig genConfig);
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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.youchain.service;
|
||||
|
||||
import com.youchain.domain.ColumnInfo;
|
||||
import com.youchain.domain.GenConfig;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-02
|
||||
*/
|
||||
public interface GeneratorService {
|
||||
|
||||
/**
|
||||
* 查询数据库元数据
|
||||
* @param name 表名
|
||||
* @param startEnd 分页参数
|
||||
* @return /
|
||||
*/
|
||||
Object getTables(String name, int[] startEnd);
|
||||
|
||||
/**
|
||||
* 得到数据表的元数据
|
||||
* @param name 表名
|
||||
* @return /
|
||||
*/
|
||||
List<ColumnInfo> getColumns(String name);
|
||||
|
||||
/**
|
||||
* 同步表数据
|
||||
* @param columnInfos /
|
||||
* @param columnInfoList /
|
||||
*/
|
||||
void sync(List<ColumnInfo> columnInfos, List<ColumnInfo> columnInfoList);
|
||||
|
||||
/**
|
||||
* 保持数据
|
||||
* @param columnInfos /
|
||||
*/
|
||||
void save(List<ColumnInfo> columnInfos);
|
||||
|
||||
/**
|
||||
* 获取所有table
|
||||
* @return /
|
||||
*/
|
||||
Object getTables();
|
||||
|
||||
/**
|
||||
* 代码生成
|
||||
* @param genConfig 配置信息
|
||||
* @param columns 字段信息
|
||||
*/
|
||||
void generator(GenConfig genConfig, List<ColumnInfo> columns);
|
||||
|
||||
/**
|
||||
* 预览
|
||||
* @param genConfig 配置信息
|
||||
* @param columns 字段信息
|
||||
* @return /
|
||||
*/
|
||||
ResponseEntity<Object> preview(GenConfig genConfig, List<ColumnInfo> columns);
|
||||
|
||||
/**
|
||||
* 打包下载
|
||||
* @param genConfig 配置信息
|
||||
* @param columns 字段信息
|
||||
* @param request /
|
||||
* @param response /
|
||||
*/
|
||||
void download(GenConfig genConfig, List<ColumnInfo> columns, HttpServletRequest request, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 查询数据库的表字段数据数据
|
||||
* @param table /
|
||||
* @return /
|
||||
*/
|
||||
List<ColumnInfo> query(String table);
|
||||
}
|
||||
|
|
@ -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.youchain.service.impl;
|
||||
|
||||
import com.youchain.domain.GenConfig;
|
||||
import com.youchain.repository.GenConfigRepository;
|
||||
import com.youchain.service.GenConfigService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-14
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class GenConfigServiceImpl implements GenConfigService {
|
||||
|
||||
private final GenConfigRepository genConfigRepository;
|
||||
|
||||
@Override
|
||||
public GenConfig find(String tableName) {
|
||||
GenConfig genConfig = genConfigRepository.findByTableName(tableName);
|
||||
if(genConfig == null){
|
||||
return new GenConfig(tableName);
|
||||
}
|
||||
return genConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenConfig update(String tableName, GenConfig genConfig) {
|
||||
String separator = File.separator;
|
||||
String[] paths;
|
||||
String symbol = "\\";
|
||||
if (symbol.equals(separator)) {
|
||||
paths = genConfig.getPath().split("\\\\");
|
||||
} else {
|
||||
paths = genConfig.getPath().split(File.separator);
|
||||
}
|
||||
StringBuilder api = new StringBuilder();
|
||||
for (String path : paths) {
|
||||
api.append(path);
|
||||
api.append(separator);
|
||||
if ("src".equals(path)) {
|
||||
api.append("api");
|
||||
break;
|
||||
}
|
||||
}
|
||||
genConfig.setApiPath(api.toString());
|
||||
return genConfigRepository.save(genConfig);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* 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.youchain.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import com.youchain.domain.ColumnInfo;
|
||||
import com.youchain.domain.GenConfig;
|
||||
import com.youchain.domain.vo.TableInfo;
|
||||
import com.youchain.exception.BadRequestException;
|
||||
import com.youchain.repository.ColumnInfoRepository;
|
||||
import com.youchain.service.GeneratorService;
|
||||
import com.youchain.utils.FileUtil;
|
||||
import com.youchain.utils.GenUtil;
|
||||
import com.youchain.utils.PageUtil;
|
||||
import com.youchain.utils.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.Query;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-02
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class GeneratorServiceImpl implements GeneratorService {
|
||||
private static final Logger log = LoggerFactory.getLogger(GeneratorServiceImpl.class);
|
||||
@PersistenceContext
|
||||
private EntityManager em;
|
||||
|
||||
private final ColumnInfoRepository columnInfoRepository;
|
||||
|
||||
private final String CONFIG_MESSAGE = "请先配置生成器";
|
||||
@Override
|
||||
public Object getTables() {
|
||||
// 使用预编译防止sql注入
|
||||
String sql = "select table_name ,create_time , engine, table_collation, table_comment from information_schema.tables " +
|
||||
"where table_schema = (select database()) " +
|
||||
"order by create_time desc";
|
||||
Query query = em.createNativeQuery(sql);
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTables(String name, int[] startEnd) {
|
||||
// 使用预编译防止sql注入
|
||||
String sql = "select table_name ,create_time , engine, table_collation, table_comment from information_schema.tables " +
|
||||
"where table_schema = (select database()) " +
|
||||
"and table_name like :table order by create_time desc";
|
||||
Query query = em.createNativeQuery(sql);
|
||||
query.setFirstResult(startEnd[0]);
|
||||
query.setMaxResults(startEnd[1] - startEnd[0]);
|
||||
query.setParameter("table", StringUtils.isNotBlank(name) ? ("%" + name + "%") : "%%");
|
||||
List result = query.getResultList();
|
||||
List<TableInfo> tableInfos = new ArrayList<>();
|
||||
for (Object obj : result) {
|
||||
Object[] arr = (Object[]) obj;
|
||||
tableInfos.add(new TableInfo(arr[0], arr[1], arr[2], arr[3], ObjectUtil.isNotEmpty(arr[4]) ? arr[4] : "-"));
|
||||
}
|
||||
String countSql = "select count(1) from information_schema.tables " +
|
||||
"where table_schema = (select database()) and table_name like :table";
|
||||
Query queryCount = em.createNativeQuery(countSql);
|
||||
queryCount.setParameter("table", StringUtils.isNotBlank(name) ? ("%" + name + "%") : "%%");
|
||||
Object totalElements = queryCount.getSingleResult();
|
||||
return PageUtil.toPage(tableInfos, totalElements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ColumnInfo> getColumns(String tableName) {
|
||||
List<ColumnInfo> columnInfos = columnInfoRepository.findByTableNameOrderByIdAsc(tableName);
|
||||
if (CollectionUtil.isNotEmpty(columnInfos)) {
|
||||
return columnInfos;
|
||||
} else {
|
||||
columnInfos = query(tableName);
|
||||
return columnInfoRepository.saveAll(columnInfos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ColumnInfo> query(String tableName) {
|
||||
// 使用预编译防止sql注入
|
||||
String sql = "select column_name, is_nullable, data_type, column_comment, column_key, extra from information_schema.columns " +
|
||||
"where table_name = ? and table_schema = (select database()) order by ordinal_position";
|
||||
Query query = em.createNativeQuery(sql);
|
||||
query.setParameter(1, tableName);
|
||||
List result = query.getResultList();
|
||||
List<ColumnInfo> columnInfos = new ArrayList<>();
|
||||
for (Object obj : result) {
|
||||
Object[] arr = (Object[]) obj;
|
||||
columnInfos.add(
|
||||
new ColumnInfo(
|
||||
tableName,
|
||||
arr[0].toString(),
|
||||
"NO".equals(arr[1]),
|
||||
arr[2].toString(),
|
||||
ObjectUtil.isNotNull(arr[3]) ? arr[3].toString() : null,
|
||||
ObjectUtil.isNotNull(arr[4]) ? arr[4].toString() : null,
|
||||
ObjectUtil.isNotNull(arr[5]) ? arr[5].toString() : null)
|
||||
);
|
||||
}
|
||||
return columnInfos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync(List<ColumnInfo> columnInfos, List<ColumnInfo> columnInfoList) {
|
||||
// 第一种情况,数据库类字段改变或者新增字段
|
||||
for (ColumnInfo columnInfo : columnInfoList) {
|
||||
// 根据字段名称查找
|
||||
List<ColumnInfo> columns = columnInfos.stream().filter(c -> c.getColumnName().equals(columnInfo.getColumnName())).collect(Collectors.toList());
|
||||
// 如果能找到,就修改部分可能被字段
|
||||
if (CollectionUtil.isNotEmpty(columns)) {
|
||||
ColumnInfo column = columns.get(0);
|
||||
column.setColumnType(columnInfo.getColumnType());
|
||||
column.setExtra(columnInfo.getExtra());
|
||||
column.setKeyType(columnInfo.getKeyType());
|
||||
if (StringUtils.isBlank(column.getRemark())) {
|
||||
column.setRemark(columnInfo.getRemark());
|
||||
}
|
||||
columnInfoRepository.save(column);
|
||||
} else {
|
||||
// 如果找不到,则保存新字段信息
|
||||
columnInfoRepository.save(columnInfo);
|
||||
}
|
||||
}
|
||||
// 第二种情况,数据库字段删除了
|
||||
for (ColumnInfo columnInfo : columnInfos) {
|
||||
// 根据字段名称查找
|
||||
List<ColumnInfo> columns = columnInfoList.stream().filter(c -> c.getColumnName().equals(columnInfo.getColumnName())).collect(Collectors.toList());
|
||||
// 如果找不到,就代表字段被删除了,则需要删除该字段
|
||||
if (CollectionUtil.isEmpty(columns)) {
|
||||
columnInfoRepository.delete(columnInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(List<ColumnInfo> columnInfos) {
|
||||
columnInfoRepository.saveAll(columnInfos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generator(GenConfig genConfig, List<ColumnInfo> columns) {
|
||||
if (genConfig.getId() == null) {
|
||||
throw new BadRequestException(CONFIG_MESSAGE);
|
||||
}
|
||||
try {
|
||||
GenUtil.generatorCode(columns, genConfig);
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
throw new BadRequestException("生成失败,请手动处理已生成的文件");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Object> preview(GenConfig genConfig, List<ColumnInfo> columns) {
|
||||
if (genConfig.getId() == null) {
|
||||
throw new BadRequestException(CONFIG_MESSAGE);
|
||||
}
|
||||
List<Map<String, Object>> genList = GenUtil.preview(columns, genConfig);
|
||||
return new ResponseEntity<>(genList, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download(GenConfig genConfig, List<ColumnInfo> columns, HttpServletRequest request, HttpServletResponse response) {
|
||||
if (genConfig.getId() == null) {
|
||||
throw new BadRequestException(CONFIG_MESSAGE);
|
||||
}
|
||||
try {
|
||||
File file = new File(GenUtil.download(columns, genConfig));
|
||||
String zipPath = file.getPath() + ".zip";
|
||||
ZipUtil.zip(file.getPath(), zipPath);
|
||||
FileUtil.downloadFile(request, response, new File(zipPath), true);
|
||||
} catch (IOException e) {
|
||||
throw new BadRequestException("打包失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.youchain.utils;
|
||||
|
||||
import org.apache.commons.configuration.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* sql字段转java
|
||||
*
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-03
|
||||
*/
|
||||
public class ColUtil {
|
||||
private static final Logger log = LoggerFactory.getLogger(ColUtil.class);
|
||||
|
||||
/**
|
||||
* 转换mysql数据类型为java数据类型
|
||||
*
|
||||
* @param type 数据库字段类型
|
||||
* @return String
|
||||
*/
|
||||
static String cloToJava(String type) {
|
||||
Configuration config = getConfig();
|
||||
assert config != null;
|
||||
return config.getString(type, "unknowType");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置信息
|
||||
*/
|
||||
public static PropertiesConfiguration getConfig() {
|
||||
try {
|
||||
return new PropertiesConfiguration("generator.properties");
|
||||
} catch (ConfigurationException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,420 @@
|
|||
/*
|
||||
* 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.youchain.utils;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.template.*;
|
||||
import com.youchain.domain.ColumnInfo;
|
||||
import com.youchain.domain.GenConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 代码生成
|
||||
*
|
||||
* @author Liu Xue
|
||||
* @date 2019-01-02
|
||||
*/
|
||||
@Slf4j
|
||||
@SuppressWarnings({"unchecked", "all"})
|
||||
public class GenUtil {
|
||||
|
||||
private static final String TIMESTAMP = "Timestamp";
|
||||
|
||||
private static final String BIGDECIMAL = "BigDecimal";
|
||||
|
||||
public static final String PK = "PRI";
|
||||
|
||||
public static final String EXTRA = "auto_increment";
|
||||
|
||||
/**
|
||||
* 获取后端代码模板名称
|
||||
*
|
||||
* @return List
|
||||
*/
|
||||
private static List<String> getAdminTemplateNames() {
|
||||
List<String> templateNames = new ArrayList<>();
|
||||
templateNames.add("Entity");
|
||||
templateNames.add("Dto");
|
||||
templateNames.add("Mapper");
|
||||
templateNames.add("Controller");
|
||||
templateNames.add("QueryCriteria");
|
||||
templateNames.add("Service");
|
||||
templateNames.add("ServiceImpl");
|
||||
templateNames.add("Repository");
|
||||
return templateNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取前端代码模板名称
|
||||
*
|
||||
* @return List
|
||||
*/
|
||||
private static List<String> getFrontTemplateNames() {
|
||||
List<String> templateNames = new ArrayList<>();
|
||||
templateNames.add("index");
|
||||
templateNames.add("api");
|
||||
return templateNames;
|
||||
}
|
||||
|
||||
public static List<Map<String, Object>> preview(List<ColumnInfo> columns, GenConfig genConfig) {
|
||||
Map<String, Object> genMap = getGenMap(columns, genConfig);
|
||||
List<Map<String, Object>> genList = new ArrayList<>();
|
||||
// 获取后端模版
|
||||
List<String> templates = getAdminTemplateNames();
|
||||
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
|
||||
for (String templateName : templates) {
|
||||
Map<String, Object> map = new HashMap<>(1);
|
||||
Template template = engine.getTemplate("generator/admin/" + templateName + ".ftl");
|
||||
map.put("content", template.render(genMap));
|
||||
map.put("name", templateName);
|
||||
genList.add(map);
|
||||
}
|
||||
// 获取前端模版
|
||||
templates = getFrontTemplateNames();
|
||||
for (String templateName : templates) {
|
||||
Map<String, Object> map = new HashMap<>(1);
|
||||
Template template = engine.getTemplate("generator/front/" + templateName + ".ftl");
|
||||
map.put(templateName, template.render(genMap));
|
||||
map.put("content", template.render(genMap));
|
||||
map.put("name", templateName);
|
||||
genList.add(map);
|
||||
}
|
||||
return genList;
|
||||
}
|
||||
|
||||
public static String download(List<ColumnInfo> columns, GenConfig genConfig) throws IOException {
|
||||
// 拼接的路径:/tmpeladmin-gen-temp/,这个路径在Linux下需要root用户才有权限创建,非root用户会权限错误而失败,更改为: /tmp/eladmin-gen-temp/
|
||||
// String tempPath =SYS_TEM_DIR + "eladmin-gen-temp" + File.separator + genConfig.getTableName() + File.separator;
|
||||
String tempPath = FileUtil.SYS_TEM_DIR + "eladmin-gen-temp" + File.separator + genConfig.getTableName() + File.separator;
|
||||
Map<String, Object> genMap = getGenMap(columns, genConfig);
|
||||
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
|
||||
// 生成后端代码
|
||||
List<String> templates = getAdminTemplateNames();
|
||||
for (String templateName : templates) {
|
||||
Template template = engine.getTemplate("generator/admin/" + templateName + ".ftl");
|
||||
String filePath = getAdminFilePath(templateName, genConfig, genMap.get("className").toString(), tempPath + "eladmin" + File.separator);
|
||||
assert filePath != null;
|
||||
File file = new File(filePath);
|
||||
// 如果非覆盖生成
|
||||
if (!genConfig.getCover() && FileUtil.exist(file)) {
|
||||
continue;
|
||||
}
|
||||
// 生成代码
|
||||
genFile(file, template, genMap);
|
||||
}
|
||||
// 生成前端代码
|
||||
templates = getFrontTemplateNames();
|
||||
for (String templateName : templates) {
|
||||
Template template = engine.getTemplate("generator/front/" + templateName + ".ftl");
|
||||
String path = tempPath + "eladmin-web" + File.separator;
|
||||
String apiPath = path + "src" + File.separator + "api" + File.separator;
|
||||
String srcPath = path + "src" + File.separator + "views" + File.separator + genMap.get("changeClassName").toString() + File.separator;
|
||||
String filePath = getFrontFilePath(templateName, apiPath, srcPath, genMap.get("changeClassName").toString());
|
||||
assert filePath != null;
|
||||
File file = new File(filePath);
|
||||
// 如果非覆盖生成
|
||||
if (!genConfig.getCover() && FileUtil.exist(file)) {
|
||||
continue;
|
||||
}
|
||||
// 生成代码
|
||||
genFile(file, template, genMap);
|
||||
}
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
public static void generatorCode(List<ColumnInfo> columnInfos, GenConfig genConfig) throws IOException {
|
||||
Map<String, Object> genMap = getGenMap(columnInfos, genConfig);
|
||||
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
|
||||
// 生成后端代码
|
||||
List<String> templates = getAdminTemplateNames();
|
||||
for (String templateName : templates) {
|
||||
Template template = engine.getTemplate("generator/admin/" + templateName + ".ftl");
|
||||
String rootPath = System.getProperty("user.dir");
|
||||
String filePath = getAdminFilePath(templateName, genConfig, genMap.get("className").toString(), rootPath);
|
||||
|
||||
assert filePath != null;
|
||||
File file = new File(filePath);
|
||||
|
||||
// 如果非覆盖生成
|
||||
if (!genConfig.getCover() && FileUtil.exist(file)) {
|
||||
continue;
|
||||
}
|
||||
// 生成代码
|
||||
genFile(file, template, genMap);
|
||||
}
|
||||
|
||||
// 生成前端代码
|
||||
templates = getFrontTemplateNames();
|
||||
for (String templateName : templates) {
|
||||
Template template = engine.getTemplate("generator/front/" + templateName + ".ftl");
|
||||
String filePath = getFrontFilePath(templateName, genConfig.getApiPath(), genConfig.getPath(), genMap.get("changeClassName").toString());
|
||||
|
||||
assert filePath != null;
|
||||
File file = new File(filePath);
|
||||
|
||||
// 如果非覆盖生成
|
||||
if (!genConfig.getCover() && FileUtil.exist(file)) {
|
||||
continue;
|
||||
}
|
||||
// 生成代码
|
||||
genFile(file, template, genMap);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取模版数据
|
||||
private static Map<String, Object> getGenMap(List<ColumnInfo> columnInfos, GenConfig genConfig) {
|
||||
// 存储模版字段数据
|
||||
Map<String, Object> genMap = new HashMap<>(16);
|
||||
// 接口别名
|
||||
genMap.put("apiAlias", genConfig.getApiAlias());
|
||||
// 包名称
|
||||
genMap.put("package", genConfig.getPack());
|
||||
// 模块名称
|
||||
genMap.put("moduleName", genConfig.getModuleName());
|
||||
// 作者
|
||||
genMap.put("author", genConfig.getAuthor());
|
||||
// 创建日期
|
||||
genMap.put("date", LocalDate.now().toString());
|
||||
// 表名
|
||||
genMap.put("tableName", genConfig.getTableName());
|
||||
// 大写开头的类名
|
||||
String className = StringUtils.toCapitalizeCamelCase(genConfig.getTableName());
|
||||
// 小写开头的类名
|
||||
String changeClassName = StringUtils.toCamelCase(genConfig.getTableName());
|
||||
// 判断是否去除表前缀
|
||||
if (StringUtils.isNotEmpty(genConfig.getPrefix())) {
|
||||
className = StringUtils.toCapitalizeCamelCase(StrUtil.removePrefix(genConfig.getTableName(), genConfig.getPrefix()));
|
||||
changeClassName = StringUtils.toCamelCase(StrUtil.removePrefix(genConfig.getTableName(), genConfig.getPrefix()));
|
||||
changeClassName = StringUtils.uncapitalize(changeClassName);
|
||||
}
|
||||
// 保存类名
|
||||
genMap.put("className", className);
|
||||
// 保存小写开头的类名
|
||||
genMap.put("changeClassName", changeClassName);
|
||||
// 存在 Timestamp 字段
|
||||
genMap.put("hasTimestamp", false);
|
||||
// 查询类中存在 Timestamp 字段
|
||||
genMap.put("queryHasTimestamp", false);
|
||||
// 存在 BigDecimal 字段
|
||||
genMap.put("hasBigDecimal", false);
|
||||
// 查询类中存在 BigDecimal 字段
|
||||
genMap.put("queryHasBigDecimal", false);
|
||||
// 是否需要创建查询
|
||||
genMap.put("hasQuery", false);
|
||||
// 自增主键
|
||||
genMap.put("auto", false);
|
||||
// 存在字典
|
||||
genMap.put("hasDict", false);
|
||||
// 存在日期注解
|
||||
genMap.put("hasDateAnnotation", false);
|
||||
// 保存字段信息
|
||||
List<Map<String, Object>> columns = new ArrayList<>();
|
||||
// 保存查询字段的信息
|
||||
List<Map<String, Object>> queryColumns = new ArrayList<>();
|
||||
// 存储字典信息
|
||||
List<String> dicts = new ArrayList<>();
|
||||
// 存储 between 信息
|
||||
List<Map<String, Object>> betweens = new ArrayList<>();
|
||||
// 存储不为空的字段信息
|
||||
List<Map<String, Object>> isNotNullColumns = new ArrayList<>();
|
||||
|
||||
for (ColumnInfo column : columnInfos) {
|
||||
Map<String, Object> listMap = new HashMap<>(16);
|
||||
// 字段描述
|
||||
listMap.put("remark", column.getRemark());
|
||||
// 字段类型
|
||||
listMap.put("columnKey", column.getKeyType());
|
||||
// 主键类型
|
||||
String colType = ColUtil.cloToJava(column.getColumnType());
|
||||
// 小写开头的字段名
|
||||
String changeColumnName = StringUtils.toCamelCase(column.getColumnName());
|
||||
// 大写开头的字段名
|
||||
String capitalColumnName = StringUtils.toCapitalizeCamelCase(column.getColumnName());
|
||||
if (PK.equals(column.getKeyType())) {
|
||||
// 存储主键类型
|
||||
genMap.put("pkColumnType", colType);
|
||||
// 存储小写开头的字段名
|
||||
genMap.put("pkChangeColName", changeColumnName);
|
||||
// 存储大写开头的字段名
|
||||
genMap.put("pkCapitalColName", capitalColumnName);
|
||||
}
|
||||
// 是否存在 Timestamp 类型的字段
|
||||
if (TIMESTAMP.equals(colType)) {
|
||||
genMap.put("hasTimestamp", true);
|
||||
}
|
||||
// 是否存在 BigDecimal 类型的字段
|
||||
if (BIGDECIMAL.equals(colType)) {
|
||||
genMap.put("hasBigDecimal", true);
|
||||
}
|
||||
// 主键是否自增
|
||||
if (EXTRA.equals(column.getExtra())) {
|
||||
genMap.put("auto", true);
|
||||
}
|
||||
// 主键存在字典
|
||||
if (StringUtils.isNotBlank(column.getDictName())) {
|
||||
genMap.put("hasDict", true);
|
||||
if(!dicts.contains(column.getDictName()))
|
||||
dicts.add(column.getDictName());
|
||||
}
|
||||
|
||||
// 存储字段类型
|
||||
listMap.put("columnType", colType);
|
||||
// 存储字原始段名称
|
||||
listMap.put("columnName", column.getColumnName());
|
||||
// 不为空
|
||||
listMap.put("istNotNull", column.getNotNull());
|
||||
// 字段列表显示
|
||||
listMap.put("columnShow", column.getListShow());
|
||||
// 表单显示
|
||||
listMap.put("formShow", column.getFormShow());
|
||||
// 表单组件类型
|
||||
listMap.put("formType", StringUtils.isNotBlank(column.getFormType()) ? column.getFormType() : "Input");
|
||||
// 小写开头的字段名称
|
||||
listMap.put("changeColumnName", changeColumnName);
|
||||
//大写开头的字段名称
|
||||
listMap.put("capitalColumnName", capitalColumnName);
|
||||
// 字典名称
|
||||
listMap.put("dictName", column.getDictName());
|
||||
// 日期注解
|
||||
listMap.put("dateAnnotation", column.getDateAnnotation());
|
||||
if (StringUtils.isNotBlank(column.getDateAnnotation())) {
|
||||
genMap.put("hasDateAnnotation", true);
|
||||
}
|
||||
// 添加非空字段信息
|
||||
if (column.getNotNull()) {
|
||||
isNotNullColumns.add(listMap);
|
||||
}
|
||||
// 判断是否有查询,如有则把查询的字段set进columnQuery
|
||||
if (!StringUtils.isBlank(column.getQueryType())) {
|
||||
// 查询类型
|
||||
listMap.put("queryType", column.getQueryType());
|
||||
// 是否存在查询
|
||||
genMap.put("hasQuery", true);
|
||||
if (TIMESTAMP.equals(colType)) {
|
||||
// 查询中存储 Timestamp 类型
|
||||
genMap.put("queryHasTimestamp", true);
|
||||
}
|
||||
if (BIGDECIMAL.equals(colType)) {
|
||||
// 查询中存储 BigDecimal 类型
|
||||
genMap.put("queryHasBigDecimal", true);
|
||||
}
|
||||
if ("between".equalsIgnoreCase(column.getQueryType())) {
|
||||
betweens.add(listMap);
|
||||
} else {
|
||||
// 添加到查询列表中
|
||||
queryColumns.add(listMap);
|
||||
}
|
||||
}
|
||||
// 添加到字段列表中
|
||||
columns.add(listMap);
|
||||
}
|
||||
// 保存字段列表
|
||||
genMap.put("columns", columns);
|
||||
// 保存查询列表
|
||||
genMap.put("queryColumns", queryColumns);
|
||||
// 保存字段列表
|
||||
genMap.put("dicts", dicts);
|
||||
// 保存查询列表
|
||||
genMap.put("betweens", betweens);
|
||||
// 保存非空字段信息
|
||||
genMap.put("isNotNullColumns", isNotNullColumns);
|
||||
return genMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义后端文件路径以及名称
|
||||
*/
|
||||
private static String getAdminFilePath(String templateName, GenConfig genConfig, String className, String rootPath) {
|
||||
String projectPath = rootPath + File.separator + genConfig.getModuleName();
|
||||
String packagePath = projectPath + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator;
|
||||
if (!ObjectUtils.isEmpty(genConfig.getPack())) {
|
||||
packagePath += genConfig.getPack().replace(".", File.separator) + File.separator;
|
||||
}
|
||||
|
||||
if ("Entity".equals(templateName)) {
|
||||
return packagePath + "domain" + File.separator + className + ".java";
|
||||
}
|
||||
|
||||
if ("Controller".equals(templateName)) {
|
||||
return packagePath + "rest" + File.separator + className + "Controller.java";
|
||||
}
|
||||
|
||||
if ("Service".equals(templateName)) {
|
||||
return packagePath + "service" + File.separator + className + "Service.java";
|
||||
}
|
||||
|
||||
if ("ServiceImpl".equals(templateName)) {
|
||||
return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
|
||||
}
|
||||
|
||||
if ("Dto".equals(templateName)) {
|
||||
return packagePath + "service" + File.separator + "dto" + File.separator + className + "Dto.java";
|
||||
}
|
||||
|
||||
if ("QueryCriteria".equals(templateName)) {
|
||||
return packagePath + "service" + File.separator + "dto" + File.separator + className + "QueryCriteria.java";
|
||||
}
|
||||
|
||||
if ("Mapper".equals(templateName)) {
|
||||
return packagePath + "service" + File.separator + "mapstruct" + File.separator + className + "Mapper.java";
|
||||
}
|
||||
|
||||
if ("Repository".equals(templateName)) {
|
||||
return packagePath + "repository" + File.separator + className + "Repository.java";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义前端文件路径以及名称
|
||||
*/
|
||||
private static String getFrontFilePath(String templateName, String apiPath, String path, String apiName) {
|
||||
|
||||
if ("api".equals(templateName)) {
|
||||
return apiPath + File.separator + apiName + ".js";
|
||||
}
|
||||
|
||||
if ("index".equals(templateName)) {
|
||||
return path + File.separator + "index.vue";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void genFile(File file, Template template, Map<String, Object> map) throws IOException {
|
||||
// 生成目标文件
|
||||
Writer writer = null;
|
||||
try {
|
||||
FileUtil.touch(file);
|
||||
writer = new FileWriter(file);
|
||||
template.render(map, writer);
|
||||
} catch (TemplateException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
assert writer != null;
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?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>youchain</artifactId>
|
||||
<groupId>com.youchain</groupId>
|
||||
<version>2.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>youchain-logging</artifactId>
|
||||
<name>日志模块</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.youchain</groupId>
|
||||
<artifactId>youchain-common</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -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.youchain.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-24
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Log {
|
||||
String value() default "";
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* 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.youchain.aspect;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youchain.utils.RequestHolder;
|
||||
import com.youchain.utils.SecurityUtils;
|
||||
import com.youchain.utils.StringUtils;
|
||||
import com.youchain.utils.ThrowableUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.youchain.domain.Log;
|
||||
import com.youchain.service.LogService;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.*;
|
||||
import org.springframework.security.web.context.HttpRequestResponseHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-24
|
||||
*/
|
||||
@Component
|
||||
@Aspect
|
||||
@Slf4j
|
||||
public class LogAspect {
|
||||
|
||||
private final LogService logService;
|
||||
|
||||
ThreadLocal<Long> currentTime = new ThreadLocal<>();
|
||||
|
||||
public LogAspect(LogService logService) {
|
||||
this.logService = logService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置切入点
|
||||
*/
|
||||
@Pointcut("@annotation(com.youchain.annotation.Log)")
|
||||
public void logPointcut() {
|
||||
// 该方法无方法体,主要为了让同类中其他方法使用此切入点
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置环绕通知,使用在方法logPointcut()上注册的切入点
|
||||
*
|
||||
* @param joinPoint join point for advice
|
||||
*/
|
||||
@Around("logPointcut()")
|
||||
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
Object result;
|
||||
currentTime.set(System.currentTimeMillis());
|
||||
result = joinPoint.proceed();
|
||||
String result_data = handlerResult(result);
|
||||
//log.error("----结束了---"+result_data);
|
||||
Log log_data = new Log("INFO",System.currentTimeMillis() - currentTime.get());
|
||||
currentTime.remove();
|
||||
HttpServletRequest request = RequestHolder.getHttpServletRequest();
|
||||
String url=handlerUrl(request);
|
||||
String parm=handleParm(request);
|
||||
if(parm!=null&&parm.length()>0){
|
||||
url=url+"?"+parm;
|
||||
}
|
||||
|
||||
logService.save(url,result_data,getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request),joinPoint, log_data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private String handleParm( HttpServletRequest request) {
|
||||
if (request == null) {
|
||||
return "request为空";
|
||||
}
|
||||
String parm="";
|
||||
try {
|
||||
parm=request.getQueryString();
|
||||
} catch (Exception e) {
|
||||
parm="parm获取失败";
|
||||
log.error("parm获取失败", e);
|
||||
}
|
||||
return parm;
|
||||
}
|
||||
|
||||
private String handlerUrl( HttpServletRequest request) {
|
||||
if (request == null) {
|
||||
return "request为空";
|
||||
}
|
||||
String url="";
|
||||
try {
|
||||
url=request.getRequestURL().toString();
|
||||
} catch (Exception e) {
|
||||
url="url获取失败";
|
||||
log.error("url获取失败", e);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
private String handlerResult(Object result) {
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
String resultStr;
|
||||
try {
|
||||
if (result instanceof String) {
|
||||
resultStr = (String) result;
|
||||
} else {
|
||||
resultStr = JSONUtil.toJsonStr(result);// 如果返回结果非String类型,转换成JSON格式的字符串
|
||||
}
|
||||
|
||||
if (resultStr.length() > 10000) {
|
||||
resultStr = resultStr.substring(0, 10000);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
resultStr = result.toString();
|
||||
log.error("接口出入参日志打印切面处理返回参数异常", e);
|
||||
}
|
||||
return resultStr;
|
||||
}
|
||||
|
||||
@AfterReturning(returning = "returnValue", pointcut = "logPointcut()")
|
||||
public void doAfterReturning(JoinPoint joinPoint,Object returnValue) throws Throwable {
|
||||
// 处理完请求,返回内容
|
||||
/* log.info("类名:"+joinPoint.getSignature().getDeclaringTypeName()+
|
||||
"、方法名: "+joinPoint.getSignature().getName()+"()、====>@Before:请求参数为:{}", Arrays.toString(joinPoint.getArgs()));
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 配置异常通知
|
||||
*
|
||||
* @param joinPoint join point for advice
|
||||
* @param e exception
|
||||
*/
|
||||
@AfterThrowing(pointcut = "logPointcut()", throwing = "e")
|
||||
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
|
||||
String errDetail=ThrowableUtil.getStackTrace(e)+"";
|
||||
log.error("拦截到异常消息", errDetail);
|
||||
Log log_data = new Log("ERROR",System.currentTimeMillis() - currentTime.get());
|
||||
currentTime.remove();
|
||||
|
||||
log_data.setExceptionDetail(errDetail);
|
||||
HttpServletRequest request = RequestHolder.getHttpServletRequest();
|
||||
|
||||
String url=handlerUrl(request);
|
||||
String parm=handleParm(request);
|
||||
if(parm!=null&&parm.length()>0){
|
||||
url=url+"?"+parm;
|
||||
}
|
||||
logService.save(url,"",getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint)joinPoint, log_data);
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
try {
|
||||
return SecurityUtils.getCurrentUsername();
|
||||
}catch (Exception e){
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.youchain.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-24
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name = "sys_log")
|
||||
@NoArgsConstructor
|
||||
public class Log implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "log_id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
/** 操作用户 */
|
||||
private String username;
|
||||
|
||||
/** 描述 */
|
||||
private String description;
|
||||
|
||||
/** 方法名 */
|
||||
private String method;
|
||||
|
||||
/** 参数 */
|
||||
private String params;
|
||||
|
||||
/** 返回 */
|
||||
private String returnData;
|
||||
|
||||
/** 日志类型 */
|
||||
private String logType;
|
||||
|
||||
/** 请求ip */
|
||||
private String requestIp;
|
||||
|
||||
/** 地址 */
|
||||
private String address;
|
||||
|
||||
/** 浏览器 */
|
||||
private String browser;
|
||||
|
||||
/** 请求耗时 */
|
||||
private Long time;
|
||||
|
||||
/** 异常详细 */
|
||||
private String exceptionDetail;
|
||||
|
||||
/** 创建日期 */
|
||||
@CreationTimestamp
|
||||
private Timestamp createTime;
|
||||
|
||||
public Log(String logType, Long time) {
|
||||
this.logType = logType;
|
||||
this.time = time;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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.youchain.repository;
|
||||
|
||||
import com.youchain.domain.Log;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-24
|
||||
*/
|
||||
@Repository
|
||||
public interface LogRepository extends JpaRepository<Log,Long>, JpaSpecificationExecutor<Log> {
|
||||
|
||||
/**
|
||||
* 根据日志类型删除信息
|
||||
* @param logType 日志类型
|
||||
*/
|
||||
@Modifying
|
||||
@Query(value = "delete from sys_log where log_type = ?1", nativeQuery = true)
|
||||
void deleteByLogType(String logType);
|
||||
}
|
||||
|
|
@ -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.youchain.rest;
|
||||
|
||||
import com.youchain.utils.SecurityUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.youchain.annotation.Log;
|
||||
import com.youchain.service.LogService;
|
||||
import com.youchain.service.dto.LogQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-24
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/api/logs")
|
||||
@Api(tags = "系统:日志管理")
|
||||
public class LogController {
|
||||
|
||||
private final LogService logService;
|
||||
|
||||
@Log("导出数据")
|
||||
@ApiOperation("导出数据")
|
||||
@GetMapping(value = "/download")
|
||||
@PreAuthorize("@el.check()")
|
||||
public void exportLog(HttpServletResponse response, LogQueryCriteria criteria) throws Exception {
|
||||
criteria.setLogType("INFO");
|
||||
logService.download(logService.queryAll(criteria), response);
|
||||
}
|
||||
|
||||
@Log("导出错误数据")
|
||||
@ApiOperation("导出错误数据")
|
||||
@GetMapping(value = "/error/download")
|
||||
@PreAuthorize("@el.check()")
|
||||
public void exportErrorLog(HttpServletResponse response, LogQueryCriteria criteria) throws Exception {
|
||||
criteria.setLogType("ERROR");
|
||||
logService.download(logService.queryAll(criteria), response);
|
||||
}
|
||||
@GetMapping
|
||||
@ApiOperation("日志查询")
|
||||
@PreAuthorize("@el.check()")
|
||||
public ResponseEntity<Object> queryLog(LogQueryCriteria criteria, Pageable pageable){
|
||||
criteria.setLogType("INFO");
|
||||
return new ResponseEntity<>(logService.queryAll(criteria,pageable), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/user")
|
||||
@ApiOperation("用户日志查询")
|
||||
public ResponseEntity<Object> queryUserLog(LogQueryCriteria criteria, Pageable pageable){
|
||||
criteria.setLogType("INFO");
|
||||
criteria.setUsername(SecurityUtils.getCurrentUsername());
|
||||
return new ResponseEntity<>(logService.queryAllByUser(criteria,pageable), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/error")
|
||||
@ApiOperation("错误日志查询")
|
||||
@PreAuthorize("@el.check()")
|
||||
public ResponseEntity<Object> queryErrorLog(LogQueryCriteria criteria, Pageable pageable){
|
||||
criteria.setLogType("ERROR");
|
||||
return new ResponseEntity<>(logService.queryAll(criteria,pageable), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/error/{id}")
|
||||
@ApiOperation("日志异常详情查询")
|
||||
@PreAuthorize("@el.check()")
|
||||
public ResponseEntity<Object> queryErrorLogDetail(@PathVariable Long id){
|
||||
return new ResponseEntity<>(logService.findByErrDetail(id), HttpStatus.OK);
|
||||
}
|
||||
@DeleteMapping(value = "/del/error")
|
||||
@Log("删除所有ERROR日志")
|
||||
@ApiOperation("删除所有ERROR日志")
|
||||
@PreAuthorize("@el.check()")
|
||||
public ResponseEntity<Object> delAllErrorLog(){
|
||||
logService.delAllByError();
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@DeleteMapping(value = "/del/info")
|
||||
@Log("删除所有INFO日志")
|
||||
@ApiOperation("删除所有INFO日志")
|
||||
@PreAuthorize("@el.check()")
|
||||
public ResponseEntity<Object> delAllInfoLog(){
|
||||
logService.delAllByInfo();
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.service;
|
||||
|
||||
import com.youchain.service.dto.LogQueryCriteria;
|
||||
import com.youchain.domain.Log;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-24
|
||||
*/
|
||||
public interface LogService {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param criteria 查询条件
|
||||
* @param pageable 分页参数
|
||||
* @return /
|
||||
*/
|
||||
Object queryAll(LogQueryCriteria criteria, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 查询全部数据
|
||||
* @param criteria 查询条件
|
||||
* @return /
|
||||
*/
|
||||
List<Log> queryAll(LogQueryCriteria criteria);
|
||||
|
||||
/**
|
||||
* 查询用户日志
|
||||
* @param criteria 查询条件
|
||||
* @param pageable 分页参数
|
||||
* @return -
|
||||
*/
|
||||
Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 保存日志数据
|
||||
* @param username 用户
|
||||
* @param browser 浏览器
|
||||
* @param ip 请求IP
|
||||
* @param joinPoint /
|
||||
* @param log 日志实体
|
||||
*/
|
||||
|
||||
void save(String url,String returnValue,String username, String browser, String ip, JoinPoint joinPoint, Log log);
|
||||
|
||||
|
||||
void saveLog(Log log);
|
||||
/**
|
||||
* 查询异常详情
|
||||
* @param id 日志ID
|
||||
* @return Object
|
||||
*/
|
||||
Object findByErrDetail(Long id);
|
||||
|
||||
/**
|
||||
* 导出日志
|
||||
* @param logs 待导出的数据
|
||||
* @param response /
|
||||
* @throws Exception /
|
||||
*/
|
||||
void download(List<Log> logs, HttpServletResponse response) throws Exception, Exception;
|
||||
|
||||
/**
|
||||
* 删除所有错误日志
|
||||
*/
|
||||
void delAllByError();
|
||||
|
||||
/**
|
||||
* 删除所有INFO日志
|
||||
*/
|
||||
void delAllByInfo();
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.youchain.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-5-22
|
||||
*/
|
||||
@Data
|
||||
public class LogErrorDTO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String username;
|
||||
|
||||
private String description;
|
||||
|
||||
private String method;
|
||||
|
||||
private String returnData;
|
||||
|
||||
private String params;
|
||||
|
||||
private String browser;
|
||||
|
||||
private String requestIp;
|
||||
|
||||
private String address;
|
||||
|
||||
private Timestamp createTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.youchain.service.dto;
|
||||
|
||||
import com.youchain.annotation.Query;
|
||||
import lombok.Data;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 日志查询类
|
||||
* @author Liu Xue
|
||||
* @date 2019-6-4 09:23:07
|
||||
*/
|
||||
@Data
|
||||
public class LogQueryCriteria {
|
||||
|
||||
@Query(blurry = "username,description,address,requestIp,method,params")
|
||||
private String blurry;
|
||||
|
||||
@Query
|
||||
private String username;
|
||||
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private String method;
|
||||
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private String description;
|
||||
|
||||
@Query(type = Query.Type.GREATER_THAN)
|
||||
private Long time;
|
||||
|
||||
@Query
|
||||
private String logType;
|
||||
|
||||
@Query(type = Query.Type.BETWEEN)
|
||||
private List<Timestamp> createTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.youchain.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-5-22
|
||||
*/
|
||||
@Data
|
||||
public class LogSmallDTO implements Serializable {
|
||||
|
||||
private String description;
|
||||
|
||||
private String requestIp;
|
||||
|
||||
private String returnData;
|
||||
|
||||
private Long time;
|
||||
|
||||
private String address;
|
||||
|
||||
private String browser;
|
||||
|
||||
private Timestamp createTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* 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.youchain.service.impl;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youchain.domain.Log;
|
||||
import com.youchain.repository.LogRepository;
|
||||
import com.youchain.service.LogService;
|
||||
import com.youchain.service.dto.LogQueryCriteria;
|
||||
import com.youchain.service.mapstruct.LogSmallMapper;
|
||||
import com.youchain.utils.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.youchain.service.mapstruct.LogErrorMapper;
|
||||
import com.youchain.utils.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2018-11-24
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class LogServiceImpl implements LogService {
|
||||
private final LogRepository logRepository;
|
||||
private final LogErrorMapper logErrorMapper;
|
||||
private final LogSmallMapper logSmallMapper;
|
||||
|
||||
@Override
|
||||
public Object queryAll(LogQueryCriteria criteria, Pageable pageable) {
|
||||
Page<Log> page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable);
|
||||
String status = "ERROR";
|
||||
if (status.equals(criteria.getLogType())) {
|
||||
return PageUtil.toPage(page.map(logErrorMapper::toDto));
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Log> queryAll(LogQueryCriteria criteria) {
|
||||
return logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable) {
|
||||
Page<Log> page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable);
|
||||
return PageUtil.toPage(page.map(logSmallMapper::toDto));
|
||||
}
|
||||
@Async
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void save(String url,String returnValue,String username, String browser, String ip, JoinPoint joinPoint, Log log_data) {
|
||||
if (log_data == null) {
|
||||
throw new IllegalArgumentException("Log 不能为 null!");
|
||||
}
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
com.youchain.annotation.Log aopLog = method.getAnnotation(com.youchain.annotation.Log.class);
|
||||
|
||||
// 方法路径
|
||||
String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
|
||||
|
||||
// 描述
|
||||
log_data.setDescription(aopLog.value());
|
||||
|
||||
log_data.setRequestIp(ip);
|
||||
log_data.setAddress(StringUtils.getCityInfo(log_data.getRequestIp()));
|
||||
log_data.setMethod(url+"---"+methodName);
|
||||
log_data.setUsername(username);
|
||||
log_data.setParams(getParameter(method, joinPoint.getArgs()));
|
||||
// 记录登录用户,隐藏密码信息
|
||||
if(signature.getName().equals("login") && StringUtils.isNotEmpty(log_data.getParams())){
|
||||
JSONObject obj = JSONUtil.parseObj(log_data.getParams());
|
||||
log_data.setUsername(obj.getStr("username", ""));
|
||||
log_data.setParams(JSONUtil.toJsonStr(Dict.create().set("username", log_data.getUsername())));
|
||||
}
|
||||
log_data.setBrowser(browser);
|
||||
log_data.setReturnData(returnValue);
|
||||
logRepository.save(log_data);
|
||||
}
|
||||
|
||||
@Async
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveLog(Log log_data) {
|
||||
if (log_data == null) {
|
||||
throw new IllegalArgumentException("Log 不能为 null!");
|
||||
}
|
||||
logRepository.save(log_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据方法和传入的参数获取请求参数
|
||||
*/
|
||||
private String getParameter(Method method, Object[] args) {
|
||||
List<Object> argList = new ArrayList<>();
|
||||
Parameter[] parameters = method.getParameters();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
//将RequestBody注解修饰的参数作为请求参数
|
||||
RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
|
||||
if (requestBody != null) {
|
||||
argList.add(args[i]);
|
||||
}
|
||||
//将RequestParam注解修饰的参数作为请求参数
|
||||
RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
|
||||
if (requestParam != null) {
|
||||
Map<String, Object> map = new HashMap<>(2);
|
||||
String key = parameters[i].getName();
|
||||
if (!StringUtils.isEmpty(requestParam.value())) {
|
||||
key = requestParam.value();
|
||||
}
|
||||
map.put(key, args[i]);
|
||||
argList.add(map);
|
||||
}
|
||||
}
|
||||
if (argList.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
return argList.size() == 1 ? JSONUtil.toJsonStr(argList.get(0)) : JSONUtil.toJsonStr(argList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object findByErrDetail(Long id) {
|
||||
Log log = logRepository.findById(id).orElseGet(Log::new);
|
||||
ValidationUtil.isNull(log.getId(), "Log", "id", id);
|
||||
String details = log.getExceptionDetail();
|
||||
return Dict.create().set("exception", details+"");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void download(List<Log> logs, HttpServletResponse response) throws Exception {
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
for (Log log : logs) {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("用户名", log.getUsername());
|
||||
map.put("IP", log.getRequestIp());
|
||||
map.put("IP来源", log.getAddress());
|
||||
map.put("描述", log.getDescription());
|
||||
map.put("浏览器", log.getBrowser());
|
||||
map.put("请求耗时/毫秒", log.getTime());
|
||||
map.put("异常详情", log.getExceptionDetail()+"");
|
||||
map.put("创建日期", log.getCreateTime());
|
||||
list.add(map);
|
||||
}
|
||||
FileUtil.downloadExcel(list, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delAllByError() {
|
||||
logRepository.deleteByLogType("ERROR");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void delAllByInfo() {
|
||||
logRepository.deleteByLogType("INFO");
|
||||
}
|
||||
}
|
||||
|
|
@ -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.youchain.service.mapstruct;
|
||||
|
||||
import com.youchain.base.BaseMapper;
|
||||
import com.youchain.domain.Log;
|
||||
import com.youchain.service.dto.LogErrorDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-5-22
|
||||
*/
|
||||
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface LogErrorMapper extends BaseMapper<LogErrorDTO, Log> {
|
||||
|
||||
}
|
||||
|
|
@ -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.youchain.service.mapstruct;
|
||||
|
||||
import com.youchain.base.BaseMapper;
|
||||
import com.youchain.domain.Log;
|
||||
import com.youchain.service.dto.LogSmallDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
/**
|
||||
* @author Liu Xue
|
||||
* @date 2019-5-22
|
||||
*/
|
||||
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface LogSmallMapper extends BaseMapper<LogSmallDTO, Log> {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
#2023-11-3 AGV场景表
|
||||
CREATE TABLE `base_agv_scene` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`dept_id` bigint(20) DEFAULT NULL COMMENT '仓库ID',
|
||||
`code` varchar(20) NOT NULL COMMENT '代码',
|
||||
`name` varchar(20) NOT NULL COMMENT '名称',
|
||||
`remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '备注',
|
||||
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
|
||||
`update_by` varchar(255) DEFAULT NULL COMMENT '修改人',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='AGV场景表';
|
||||
|
||||
ALTER TABLE `base_area` ADD COLUMN `agv_scene_id` bigint(20) DEFAULT NULL COMMENT 'avg场景id';
|
||||
ALTER TABLE `base_item` ADD COLUMN `agv_scene_id` bigint(20) DEFAULT NULL COMMENT 'avg场景id';
|
||||
#物料类型字典
|
||||
INSERT INTO `sys_dict` (`dict_id`, `name`, `description`, `create_by`, `update_by`, `create_time`, `update_time`) VALUES (21, 'item_type', '货物类型', 'admin', 'admin', '2023-11-03 11:49:03', '2023-11-03 11:49:03');
|
||||
INSERT INTO `sys_dict_detail` (`detail_id`, `dict_id`, `label`, `value`, `dict_sort`, `create_by`, `update_by`, `create_time`, `update_time`) VALUES (69, 21, '前桶', 'QT', 1, 'admin', 'admin', '2023-11-03 11:49:34', '2023-11-03 11:49:34');
|
||||
INSERT INTO `sys_dict_detail` (`detail_id`, `dict_id`, `label`, `value`, `dict_sort`, `create_by`, `update_by`, `create_time`, `update_time`) VALUES (69, 21, '后桶', 'HT', 2, 'admin', 'admin', '2023-11-03 11:49:34', '2023-11-03 11:49:34');
|
||||
INSERT INTO `sys_dict_detail` (`detail_id`, `dict_id`, `label`, `value`, `dict_sort`, `create_by`, `update_by`, `create_time`, `update_time`) VALUES (70, 21, '门封', 'MF', 3, 'admin', 'admin', '2023-11-03 13:39:13', '2023-11-03 13:39:13');
|
||||
INSERT INTO `sys_dict_detail` (`detail_id`, `dict_id`, `label`, `value`, `dict_sort`, `create_by`, `update_by`, `create_time`, `update_time`) VALUES (71, 21, '小件', 'XJ', 4, 'admin', 'admin', '2023-11-03 13:39:24', '2023-11-03 13:39:24');
|
||||
INSERT INTO `sys_dict_detail` (`detail_id`, `dict_id`, `label`, `value`, `dict_sort`, `create_by`, `update_by`, `create_time`, `update_time`) VALUES (72, 21, 'ZCZ', '轴承座', 5, 'admin', 'admin', '2023-11-03 13:39:39', '2023-11-03 13:39:39');
|
||||
|
||||
#入库点位
|
||||
ALTER table data_asn_detail add point_id bigint(20) DEFAULT NULL COMMENT '点位序号';
|
||||
|
||||
#按钮盒
|
||||
alter table base_box add `IP` varchar(50) DEFAULT NULL COMMENT 'IP' ;
|
||||
alter table base_box add `lamp_status` varchar(50) DEFAULT '0' COMMENT '指示灯状态';
|
||||
alter table base_box add `lamp_code` varchar(50) DEFAULT NULL COMMENT '按钮盒编号';
|
||||
|
||||
#指示灯日志
|
||||
CREATE TABLE `sys_lamp_log` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`ip` varchar(50) DEFAULT NULL COMMENT 'ip',
|
||||
`button_box` varchar(50) DEFAULT NULL COMMENT '所属按钮盒',
|
||||
`button_code` varchar(50) DEFAULT NULL COMMENT '按钮编码',
|
||||
`operation_type` varchar(50) DEFAULT NULL COMMENT '操作类型',
|
||||
`request_content` varchar(255) DEFAULT NULL COMMENT '请求内容',
|
||||
`return_content` varchar(255) DEFAULT NULL COMMENT '返回内容',
|
||||
`return_state` varchar(50) DEFAULT NULL COMMENT '返回状态',
|
||||
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
|
||||
`update_by` varchar(255) DEFAULT NULL COMMENT '修改人',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='指示灯日志';
|
||||
|
||||
#轴承座物料类型变更
|
||||
update base_item it set it.good_type='ZC' where good_type='ZCZ';
|
||||
|
||||
|
||||
#data_agv_task 增加 是否扫描字段
|
||||
alter table data_agv_task add `be_scan` int(11) DEFAULT NULL COMMENT '是否扫描' ;
|
||||
update data_agv_task set be_scan=0 where be_scan is null ;
|
||||
|
||||
#机械臂点位物料编码
|
||||
ALTER table base_point add item_code VARCHAR(50) COMMENT '点位物料编码';
|
||||
|
||||
#点位排,用于门封解锁
|
||||
alter table base_point add rows int(11) DEFAULT NULL COMMENT '层' ;
|
||||
alter table base_point add col int(11) DEFAULT NULL COMMENT '列' ;
|
||||
alter table base_point add line int(11) DEFAULT NULL COMMENT '排' ;
|
||||
|
||||
update base_point set rows=0,col=0,line=0 where rows is null;
|
||||
#轴承座机械臂表通信配置表
|
||||
CREATE TABLE `base_zcjxb` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`modbus_tcp_task_finish` tinyint(1) DEFAULT '0' COMMENT 'Modbus-tcp的任务是否启用',
|
||||
`modbus_tcp_point` varchar(255) DEFAULT NULL COMMENT 'Modbus-tcp对应的地标点',
|
||||
`modbus_tcp_item` varchar(255) DEFAULT NULL COMMENT 'Modbus-tcp对应的物料',
|
||||
`modbus_tcp_slave_id` int(11) DEFAULT NULL COMMENT '从机ID',
|
||||
`task_off_on_a` tinyint(1) DEFAULT '0' COMMENT 'a车点位是否有任务',
|
||||
`task_off_on_b` tinyint(1) DEFAULT '0' COMMENT 'b车点位是否有任务',
|
||||
`code` int(11) DEFAULT NULL COMMENT '机械臂机台号',
|
||||
`ip` varchar(100) NOT NULL COMMENT 'ip地址',
|
||||
`port` int(11) NOT NULL COMMENT '端口号',
|
||||
`communication_type` varchar(255) DEFAULT NULL COMMENT '通信类型',
|
||||
`address` int(11) DEFAULT NULL COMMENT '地址',
|
||||
`data_length` int(11) DEFAULT NULL COMMENT '数据长度',
|
||||
`offset_a1` int(11) DEFAULT NULL COMMENT '偏移量-A返回空车',
|
||||
`offset_b1` int(11) DEFAULT NULL COMMENT '偏移量-B返回空车',
|
||||
`offset_a2` int(11) DEFAULT NULL COMMENT '偏移量-A叫料',
|
||||
`offset_b2` int(11) DEFAULT NULL COMMENT '偏移量-B叫料',
|
||||
`offset_a3` int(11) DEFAULT NULL COMMENT '偏移量-A车有料',
|
||||
`offset_b3` int(11) DEFAULT NULL COMMENT '偏移量-B车有料',
|
||||
`point_a1` varchar(255) DEFAULT NULL COMMENT 'A车的地标点',
|
||||
`point_b1` varchar(255) DEFAULT NULL COMMENT 'B车的地标点',
|
||||
`item_a1` varchar(255) DEFAULT NULL COMMENT 'A车的物料',
|
||||
`item_b1` varchar(255) DEFAULT NULL COMMENT 'B车的物料',
|
||||
`enabled` tinyint(1) DEFAULT '0' COMMENT '是否启用',
|
||||
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
|
||||
`update_by` varchar(255) DEFAULT NULL COMMENT '更新人',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=62 DEFAULT CHARSET=utf8 COMMENT='机械臂';
|
||||
|
||||
# 添加一个机械臂正在执行的任务名称
|
||||
ALTER TABLE `base_zcjxb` ADD COLUMN task_name varchar(255) DEFAULT NULL COMMENT '任务名称';
|
||||
|
||||
# 库区管理
|
||||
alter TABLE base_area add column working_station varchar(50) DEFAULT NULL COMMENT '所属工位';
|
||||
alter TABLE base_area add column point_id bigint(20) DEFAULT NULL COMMENT '缓存库位';
|
||||
alter TABLE base_area add column bexb tinyint(1) DEFAULT '0' COMMENT'线边接收';
|
||||
alter TABLE base_area add column besh tinyint(1) DEFAULT '0' COMMENT'收货仓库';
|
||||
alter TABLE base_area add column bezz tinyint(1) DEFAULT '0' COMMENT'制造库位耗用';
|
||||
|
||||
# 生产顺序计划表
|
||||
CREATE TABLE `base_production_plan` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`dept_id` bigint(20) DEFAULT NULL COMMENT '仓库ID',
|
||||
`enabled` bit(1) DEFAULT b'0' COMMENT '状态:1启用、0禁用',
|
||||
`big_item_id` bigint(20) DEFAULT NULL COMMENT '完成品番',
|
||||
`working_station` varchar(50) DEFAULT NULL COMMENT '工位',
|
||||
`No` int(7) DEFAULT NULL COMMENT 'No',
|
||||
`machine_no` int(7) DEFAULT NULL COMMENT '机号',
|
||||
`import_date` datetime DEFAULT NULL COMMENT '导入日期',
|
||||
`planned_date` datetime DEFAULT NULL COMMENT '计划日期',
|
||||
`downline_date` datetime DEFAULT NULL COMMENT '下线日期',
|
||||
`take_up_time` datetime DEFAULT NULL COMMENT '耗用时间',
|
||||
`IDNO` varchar(50) DEFAULT NULL COMMENT 'IDNO',
|
||||
`monthly_no` varchar(255) DEFAULT NULL COMMENT '月度序号',
|
||||
`project_no` varchar(255) DEFAULT NULL COMMENT '计划单号',
|
||||
`make_line` varchar(255) DEFAULT NULL COMMENT '制造线',
|
||||
`order_no` bigint(20) DEFAULT NULL COMMENT '序号',
|
||||
`bom_list_id` bigint(20) DEFAULT NULL COMMENT '工位清单',
|
||||
`sh_area_id` bigint(20) DEFAULT NULL COMMENT '收货仓库',
|
||||
`rk_area_id` bigint(20) DEFAULT NULL COMMENT '入库库区',
|
||||
`off_line_part_id` bigint(20) DEFAULT NULL COMMENT '下线零件ID',
|
||||
`pick_plan_id` bigint(20) DEFAULT NULL COMMENT '备货计划ID',
|
||||
`type` varchar(255) DEFAULT NULL COMMENT '出库类型',
|
||||
`part_variety` varchar(255) DEFAULT NULL COMMENT '部品种类',
|
||||
`statue` varchar(255) DEFAULT NULL COMMENT '耗用状态',
|
||||
`auto_production_id` bigint(20) DEFAULT NULL COMMENT '所属自动计划',
|
||||
`description` varchar(255) DEFAULT NULL COMMENT '描述',
|
||||
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
|
||||
`update_by` varchar(255) DEFAULT NULL COMMENT '更新人',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改日期',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE KEY `bpp_key` (`working_station`,`IDNO`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='生产顺序计划';
|
||||
|
||||
# 部品品番 添加库位字段
|
||||
ALTER table base_item add point_id bigint(20) DEFAULT NULL COMMENT '库位';
|
||||
|
||||
# 收货管理表
|
||||
CREATE TABLE `data_asn` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`code` varchar(20) CHARACTER SET utf8 NOT NULL COMMENT '单号',
|
||||
`area_id` bigint(20) DEFAULT NULL COMMENT '库区',
|
||||
`status` varchar(255) DEFAULT NULL COMMENT '状态',
|
||||
`cus_code` varchar(255) DEFAULT NULL COMMENT '客户订单号',
|
||||
`related_bill1` varchar(255) DEFAULT NULL COMMENT '相关单号1',
|
||||
`related_bill2` varchar(255) DEFAULT NULL COMMENT '相关单号2',
|
||||
`related_bill3` varchar(255) DEFAULT NULL COMMENT '相关单号3',
|
||||
`order_date`datetime DEFAULT NULL DEFAULT NULL COMMENT '订单日期',
|
||||
`estimate_date`datetime DEFAULT NULL COMMENT '预计到货日期',
|
||||
`received_date`datetime DEFAULT NULL COMMENT '收货日期',
|
||||
`from_name` varchar(255) DEFAULT NULL COMMENT '发货方',
|
||||
`from_address` varchar(255) DEFAULT NULL COMMENT '发货地址',
|
||||
`from_man` varchar(255) DEFAULT NULL COMMENT '发货联系人',
|
||||
`from_tel` varchar(255) DEFAULT NULL COMMENT '发货电话',
|
||||
`order_quantity` double DEFAULT '0' COMMENT '订单数量',
|
||||
`received_quantity` double DEFAULT '0' COMMENT '收货数量',
|
||||
`putaway_quantity` double DEFAULT '0' COMMENT '上架数量',
|
||||
`vehicle` varchar(255) DEFAULT NULL COMMENT '车牌号',
|
||||
`bill_type_id` varchar(255) DEFAULT NULL COMMENT '单据类型',
|
||||
`dept_id` bigint(20) DEFAULT NULL COMMENT '仓库ID',
|
||||
`description` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
|
||||
`update_by` varchar(255) DEFAULT NULL COMMENT '修改人',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE KEY `code` (`code`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='收货管理';
|
||||
# 出库添加关联主表的字段
|
||||
ALTER table data_pick_detail add pick_ticket bigint(20) DEFAULT NULL COMMENT '出库管理主表';
|
||||
# 出库管理
|
||||
CREATE TABLE `data_pick_ticket` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`area` bigint(20) DEFAULT NULL COMMENT '出库库区',
|
||||
`sh_area` bigint(20) DEFAULT NULL COMMENT '收货库区',
|
||||
`code` varchar(20) NOT NULL COMMENT '单号',
|
||||
`status` varchar(255) DEFAULT NULL COMMENT '状态',
|
||||
`cus_code` varchar(20) DEFAULT NULL COMMENT '客户订单号',
|
||||
`related_bill1` varchar(255) DEFAULT NULL COMMENT '相关单号1',
|
||||
`related_bill2` varchar(255) DEFAULT NULL COMMENT '相关单号2',
|
||||
`related_bill3` varchar(255) DEFAULT NULL COMMENT '相关单号3',
|
||||
`order_date` datetime DEFAULT NULL COMMENT '订单日期',
|
||||
`ship_date` datetime DEFAULT NULL COMMENT '发货日期',
|
||||
`fh_by` varchar(255) DEFAULT NULL COMMENT '发货人',
|
||||
`received_date` datetime DEFAULT NULL COMMENT '到达日期',
|
||||
`sl_by` varchar(255) DEFAULT NULL COMMENT '接收人',
|
||||
`sl_qty` double DEFAULT '0' COMMENT '收料数量',
|
||||
`tl_date` time DEFAULT NULL COMMENT '投料日期',
|
||||
`tl_by` varchar(255) DEFAULT NULL COMMENT '投料人',
|
||||
`tl_qty` double DEFAULT '0' COMMENT '投料数量',
|
||||
`ship_to_name` varchar(255) DEFAULT NULL COMMENT '收货方',
|
||||
`ship_address` varchar(255) DEFAULT NULL COMMENT '收货地址',
|
||||
`ship_man` varchar(255) DEFAULT NULL COMMENT '收货联系人',
|
||||
`ship_tel` varchar(255) DEFAULT NULL COMMENT '收货电话',
|
||||
`order_quantity` double DEFAULT '0' COMMENT '订单数量',
|
||||
`allocated_quantity` double DEFAULT '0' COMMENT '出单数量',
|
||||
`picked_quantity` double DEFAULT '0' COMMENT '拣货数量',
|
||||
`shipped_quantity` double DEFAULT '0' COMMENT '发运数量',
|
||||
`xb_qty` double DEFAULT '0' COMMENT '线边数量',
|
||||
`zt_qty` double DEFAULT '0' COMMENT '在途数量',
|
||||
`xq_qty` double DEFAULT '0' COMMENT '需求数量',
|
||||
`bh_qty` double DEFAULT '0' COMMENT '备货数量',
|
||||
`vehicle` varchar(255) DEFAULT NULL COMMENT '车牌号',
|
||||
`bill_type` bigint(20) DEFAULT NULL COMMENT '单据类型',
|
||||
`bp_type` bigint(20) DEFAULT NULL COMMENT '部品种类',
|
||||
`dept_id` bigint(20) DEFAULT NULL COMMENT '仓库ID',
|
||||
`description` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
|
||||
`update_by` varchar(255) DEFAULT NULL COMMENT '修改人',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
UNIQUE KEY `dpt` (`code`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='出库管理';
|
||||
|
||||
# 新政字段
|
||||
ALTER table data_pick_detail add `point_id` bigint(20) DEFAULT NULL COMMENT '点位';
|
||||
# xppRecord增加状态字段
|
||||
ALTER table `data_xpp_record` add `status` varchar(255) DEFAULT NULL COMMENT '状态';
|
||||
ALTER TABLE `data_xpp_record` MODIFY COLUMN `nrs` INT(11);
|
||||
# inventory 加字段
|
||||
ALTER table `data_inventory` add `area_id` bigint(20) DEFAULT NULL COMMENT '库区';
|
||||
ALTER table `data_inventory` add `zzkw` bigint(20) DEFAULT NULL COMMENT '制造库位';
|
||||
# InventoryLog
|
||||
ALTER table `data_inventory_log` add `area_id` bigint(20) DEFAULT NULL COMMENT '库区';
|
||||
ALTER table `data_inventory_log` add `zzkw` bigint(20) DEFAULT NULL COMMENT '制造库位';
|
||||
ALTER table `data_inventory_log` add `zckw` bigint(20) DEFAULT NULL COMMENT '暂存库位';
|
||||
# Task
|
||||
ALTER table `data_task` add `area_id` bigint(20) DEFAULT NULL COMMENT '库区';
|
||||
ALTER table `data_task` add `zzkw` bigint(20) DEFAULT NULL COMMENT '制造库位';
|
||||
# sys_dept 表添加代码字段
|
||||
ALTER table `sys_dept` add `code` varchar(255) DEFAULT NULL COMMENT '代码';
|
||||
# 备货页面需要加的字段
|
||||
ALTER table data_pick_ticket add `pure_req_qty` double DEFAULT '0' COMMENT '纯需求数量';
|
||||
ALTER table data_pick_ticket add `prep_re` double DEFAULT '0' COMMENT '备货需求数量';
|
||||
ALTER table data_pick_ticket add `out_order_date` datetime DEFAULT NULL COMMENT '出单日期';
|
||||
ALTER table data_pick_ticket add `stocking_date` datetime DEFAULT NULL COMMENT '备货日期';
|
||||
# 出库单明细
|
||||
ALTER table data_pick_detail add `xq_qty` double DEFAULT '0' COMMENT '需求数量';
|
||||
ALTER table data_pick_detail add `pure_req_qty` double DEFAULT '0' COMMENT '纯需求数量';
|
||||
ALTER table data_pick_detail add `xb_qty` double DEFAULT '0' COMMENT '线边数量';
|
||||
ALTER table data_pick_detail add `y_stk_demand_qty` double DEFAULT '0' COMMENT '原备货需求数量';
|
||||
ALTER table data_pick_detail add `y_req_qty` double DEFAULT '0' COMMENT '原纯需求数';
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
<?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>youchain</artifactId>
|
||||
<groupId>com.youchain</groupId>
|
||||
<version>2.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>youchain-system</artifactId>
|
||||
<name>核心模块</name>
|
||||
|
||||
<properties>
|
||||
<jjwt.version>0.11.2</jjwt.version>
|
||||
<!-- oshi监控需要指定jna版本, 问题详见 https://github.com/oshi/oshi/issues/1040 -->
|
||||
<jna.version>5.8.0</jna.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!--jlibmodbus-->
|
||||
<dependency>
|
||||
<groupId>com.intelligt.modbus</groupId>
|
||||
<artifactId>jlibmodbus</artifactId>
|
||||
<version>1.2.9.7</version>
|
||||
</dependency>
|
||||
<!-- 代码生成模块 -->
|
||||
<dependency>
|
||||
<groupId>com.youchain</groupId>
|
||||
<artifactId>youchain-generator</artifactId>
|
||||
<version>2.6</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.youchain</groupId>
|
||||
<artifactId>youchain-common</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--积木模块引用
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.jimureport</groupId>
|
||||
<artifactId>jimureport-spring-boot-starter</artifactId>
|
||||
<version>1.6.6</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>poi-ooxml-schemas</artifactId>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<!-- 通用模块 -->
|
||||
<dependency>
|
||||
<groupId>com.youchain</groupId>
|
||||
<artifactId>youchain-tongyong</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
|
||||
<!-- tools 模块包含了 common 和 logging 模块 -->
|
||||
<dependency>
|
||||
<groupId>com.youchain</groupId>
|
||||
<artifactId>youchain-tools</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring boot websocket -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- quartz -->
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
<artifactId>quartz</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- linux的管理 -->
|
||||
<dependency>
|
||||
<groupId>ch.ethz.ganymed</groupId>
|
||||
<artifactId>ganymed-ssh2</artifactId>
|
||||
<version>build210</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
<version>0.1.55</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>6.1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.youchain</groupId>
|
||||
<artifactId>youchain-logging</artifactId>
|
||||
<version>2.6</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- jwt -->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.1.42.Final</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<!-- 打包 -->
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<!-- 跳过单元测试 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.youchain;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.youchain.annotation.rest.AnonymousGetMapping;
|
||||
import com.youchain.modules.license.AGxServerInfos;
|
||||
import com.youchain.modules.license.LicenseValidate;
|
||||
import com.youchain.modules.license.LinuxServerInfos;
|
||||
import com.youchain.modules.license.WindowsServerInfos;
|
||||
import com.youchain.utils.SpringContextHolder;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
|
||||
import org.springframework.boot.context.ApplicationPidFileWriter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 开启审计功能 -> @EnableJpaAuditing
|
||||
*
|
||||
* @author Liu Xue
|
||||
* @date 2018/11/15 9:20:19
|
||||
*/
|
||||
@EnableAsync
|
||||
@RestController
|
||||
@Api(hidden = true)
|
||||
@SpringBootApplication
|
||||
@EnableTransactionManagement
|
||||
@EnableAutoConfiguration(exclude={MongoAutoConfiguration.class})
|
||||
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
|
||||
@Slf4j
|
||||
public class AppRun {
|
||||
//@SpringBootApplication(scanBasePackages = {"org.jeecg.modules.jmreport","me.zhengjie"})
|
||||
public static void main(String[] args) {
|
||||
SpringApplication springApplication = new SpringApplication(AppRun.class);
|
||||
// 监控应用的PID,启动时可指定PID路径:--spring.pid.file=/home/eladmin/app.pid
|
||||
// 或者在 application.yml 添加文件路径,方便 kill,kill `cat /home/eladmin/app.pid`
|
||||
springApplication.addListeners(new ApplicationPidFileWriter());
|
||||
springApplication.run(args);
|
||||
|
||||
log.error(JSONUtil.toJsonStr(LicenseValidate.getDeviceInfo()));
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpringContextHolder springContextHolder() {
|
||||
return new SpringContextHolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 访问首页提示
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
@AnonymousGetMapping("/")
|
||||
public String index() {
|
||||
return "Backend service started successfully";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package com.youchain.DuplicateSubmission;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DuplicateSubmission {
|
||||
|
||||
int value() default 5;
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package com.youchain.DuplicateSubmission;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
import com.youchain.exception.BadRequestException;
|
||||
import com.youchain.utils.RedisUtils;
|
||||
import com.youchain.utils.RequestHolder;
|
||||
import com.youchain.utils.SpringContextHolder;
|
||||
import com.youchain.utils.StringUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class DuplicateSubmissionAspect {
|
||||
|
||||
// @Around("@annotation(com.example.demo.LogExecutionTime)")表示该环绕通知仅在使用@LogExecutionTime注解的方法上执行
|
||||
@Around("@annotation(duplicateSubmission)")
|
||||
public Object logExecutionTime(ProceedingJoinPoint joinPoint,DuplicateSubmission duplicateSubmission) throws Throwable {
|
||||
|
||||
int value = duplicateSubmission.value();
|
||||
|
||||
|
||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = signature.getMethod();
|
||||
String parm1=getParameter(method, joinPoint.getArgs());
|
||||
HttpServletRequest request = RequestHolder.getHttpServletRequest();
|
||||
String parm=handleParm(request);
|
||||
String url=handlerUrl(request);
|
||||
RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class);
|
||||
String key=url+"-"+parm1+"-"+parm;
|
||||
if(redisUtils.hasKey(key)){
|
||||
throw new BadRequestException("操作过快,请稍后重试");
|
||||
}
|
||||
redisUtils.set(key,"",value);
|
||||
// 执行目标方法
|
||||
Object result = joinPoint.proceed();
|
||||
System.out.println("请求参数为:"+key);
|
||||
|
||||
redisUtils.del(key);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private String handleParm( HttpServletRequest request) {
|
||||
if (request == null) {
|
||||
return "";
|
||||
}
|
||||
String parm="";
|
||||
try {
|
||||
parm=request.getQueryString();
|
||||
} catch (Exception e) {
|
||||
parm="";
|
||||
System.out.println("parm获取失败");
|
||||
}
|
||||
if(parm==null||parm.isEmpty()){
|
||||
parm="";
|
||||
}
|
||||
return parm;
|
||||
}
|
||||
|
||||
private String getParameter(Method method, Object[] args) {
|
||||
List<Object> argList = new ArrayList<>();
|
||||
Parameter[] parameters = method.getParameters();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
// 过滤掉不能序列化的类型: MultiPartFile
|
||||
if (args[i] instanceof MultipartFile) {
|
||||
continue;
|
||||
}
|
||||
//将RequestBody注解修饰的参数作为请求参数
|
||||
RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
|
||||
if (requestBody != null) {
|
||||
argList.add(args[i]);
|
||||
}
|
||||
//将RequestParam注解修饰的参数作为请求参数
|
||||
RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
|
||||
if (requestParam != null) {
|
||||
Map<String, Object> map = new HashMap<>(2);
|
||||
String key = parameters[i].getName();
|
||||
if (!StringUtils.isEmpty(requestParam.value())) {
|
||||
key = requestParam.value();
|
||||
}
|
||||
map.put(key, args[i]);
|
||||
argList.add(map);
|
||||
}
|
||||
}
|
||||
if (argList.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
return argList.size() == 1 ? JSON.toJSONString(argList.get(0)) : JSON.toJSONString(argList);
|
||||
}
|
||||
|
||||
private String handlerUrl( HttpServletRequest request) {
|
||||
if (request == null) {
|
||||
return "";
|
||||
}
|
||||
String url="";
|
||||
try {
|
||||
url=request.getRequestURL().toString();
|
||||
} catch (Exception e) {
|
||||
url="";
|
||||
}
|
||||
if(url==null||url.isEmpty()){
|
||||
url="";
|
||||
}
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package com.youchain.Netty;
|
||||
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class HexTools {
|
||||
|
||||
//十六进制字符转十进制
|
||||
public static int covert(String content){
|
||||
int number=0;
|
||||
String [] HighLetter = {"A","B","C","D","E","F"};
|
||||
Map<String,Integer> map = new HashMap<>();
|
||||
for(int i = 0;i <= 9;i++){
|
||||
map.put(i+"",i);
|
||||
}
|
||||
for(int j= 10;j<HighLetter.length+10;j++){
|
||||
map.put(HighLetter[j-10],j);
|
||||
}
|
||||
String[]str = new String[content.length()];
|
||||
for(int i = 0; i < str.length; i++){
|
||||
str[i] = content.substring(i,i+1);
|
||||
}
|
||||
for(int i = 0; i < str.length; i++){
|
||||
number += map.get(str[i])*Math.pow(16,str.length-1-i);
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
public static byte[] hexString2Bytes(String src) {
|
||||
int l = src.length() / 2;
|
||||
byte[] ret = new byte[l];
|
||||
for (int i = 0; i < l; i++) {
|
||||
ret[i] = (byte) Integer
|
||||
.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package com.youchain.Netty;
|
||||
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
@Slf4j
|
||||
public class MessageDecodeHandler extends ByteToMessageDecoder {
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> out) throws Exception {
|
||||
/* ByteBuf frame = in.retainedDuplicate();
|
||||
final String content = frame.toString(CharsetUtil.UTF_8);
|
||||
log.error("content:"+content);
|
||||
list.add(content);
|
||||
in.skipBytes(in.readableBytes());*/
|
||||
|
||||
|
||||
String HEXES = "0123456789ABCDEF";
|
||||
byte[] req = new byte[in.readableBytes()];
|
||||
in.readBytes(req);
|
||||
final StringBuilder hex = new StringBuilder(2 * req.length);
|
||||
|
||||
for (int i = 0; i < req.length; i++) {
|
||||
byte b = req[i];
|
||||
hex.append(HEXES.charAt((b & 0xF0) >> 4))
|
||||
.append(HEXES.charAt((b & 0x0F)));
|
||||
}
|
||||
out.add(hex.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.youchain.Netty;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
public class MessageEncodeHandler extends MessageToByteEncoder<String> {
|
||||
// 数据分割符
|
||||
String delimiter;
|
||||
|
||||
public MessageEncodeHandler(String delimiter) {
|
||||
this.delimiter = delimiter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext channelHandlerContext, String message, ByteBuf out) throws Exception {
|
||||
out.writeBytes((message + delimiter).getBytes(CharsetUtil.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package com.youchain.Netty;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public class NettyConfig {
|
||||
final NettyProperties nettyProperties;
|
||||
|
||||
public NettyConfig(NettyProperties nettyProperties) {
|
||||
this.nettyProperties = nettyProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* boss线程池-进行客户端连接
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public NioEventLoopGroup boosGroup() {
|
||||
return new NioEventLoopGroup(nettyProperties.getBoss());
|
||||
}
|
||||
|
||||
/**
|
||||
* worker线程池-进行业务处理
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public NioEventLoopGroup workerGroup() {
|
||||
return new NioEventLoopGroup(nettyProperties.getWorker());
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务端启动器,监听客户端连接
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public ServerBootstrap serverBootstrap() {
|
||||
ServerBootstrap serverBootstrap = new ServerBootstrap()
|
||||
// 指定使用的线程组
|
||||
.group(boosGroup(), workerGroup())
|
||||
// 指定使用的通道
|
||||
.channel(NioServerSocketChannel.class)
|
||||
// 指定连接超时时间
|
||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, nettyProperties.getTimeout())
|
||||
// 指定worker处理器
|
||||
.childHandler(new NettyServerHandler());
|
||||
return serverBootstrap;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue