项目初始化

main
huojin\hj 2025-07-25 11:22:48 +08:00
commit 3e27fc399a
1200 changed files with 99767 additions and 0 deletions

9
.gitignore vendored 100644
View File

@ -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

191
LICENSE 100644
View File

@ -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.

1
README.md 100644
View File

@ -0,0 +1 @@
新框架基础模板-后端

253
pom.xml 100644
View File

@ -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>

View File

@ -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>

View File

@ -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 {
}

View File

@ -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 "";
}

View File

@ -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;
}

View File

@ -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;
/**
* Userdept
*/
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
}
}

View File

@ -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 {};
}

View File

@ -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 {};
}

View File

@ -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 {};
}

View File

@ -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 {};
}

View File

@ -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 {};
}

View File

@ -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;";
}
}

View File

@ -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
}

View File

@ -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 2019102420: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();
}
}

View File

@ -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 2019102420: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();
}
}

View File

@ -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> {
/**
* DTOEntity
* @param dto /
* @return /
*/
E toEntity(D dto);
/**
* EntityDTO
* @param entity /
* @return /
*/
D toDto(E entity);
/**
* DTOEntity
* @param dtoList /
* @return /
*/
List <E> toEntity(List<D> dtoList);
/**
* EntityDTO
* @param entityList /
* @return /
*/
List <D> toDto(List<E> entityList);
}

View File

@ -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");
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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 handleCacheGetErrorkey -> [{}]", key, e);
}
@Override
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
log.error("Redis occur handleCachePutErrorkey -> [{}]value -> [{}]", key, value, e);
}
@Override
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheEvictErrorkey -> [{}]", 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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
/**
* Pageableswagger
*/
@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;
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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";
}
}

View File

@ -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";
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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()));
}
}

View File

@ -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:";
}

View File

@ -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();
}
}

View File

@ -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) {
// 静默关闭
}
}
}
}

View File

@ -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");*/
}
}

View File

@ -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);
//1130-1230休息
if(hour>11||(hour==11&&minute>=30)){
cal.add(Calendar.HOUR, 1);
}
// //1730-1830休息
// 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;
}
}

View File

@ -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";
}
}

View File

@ -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;
}
}

View File

@ -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 = "其他";
/**
* MultipartFileFile
*/
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));
}
}

View 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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 () time0 time0
* @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=============================
/**
* keySet
*
* @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;
}
}
/**
* valueset,
*
* @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;
}
}
/**
* Nvalue
*
* @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);
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}
/**
* applicationContextBean, .
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
assertContextInjected();
return (T) applicationContext.getBean(name);
}
/**
* applicationContextBean, .
*/
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.");
}
}
/**
* SpringContextHolderApplicationContextNull.
*/
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)));
}
}

View File

@ -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 "";
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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));
}
}

View File

@ -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();
}
}
}

View File

@ -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));
}
}

View File

@ -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()));
}
}

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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("打包失败");
}
}
}

View File

@ -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;
/**
* sqljava
*
* @author Liu Xue
* @date 2019-01-03
*/
public class ColUtil {
private static final Logger log = LoggerFactory.getLogger(ColUtil.class);
/**
* mysqljava
*
* @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;
}
}

View File

@ -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();
}
}
}

View File

@ -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>

View File

@ -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 "";
}

View File

@ -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 "";
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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");
}
}

View File

@ -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> {
}

View File

@ -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> {
}

View File

@ -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 '原纯需求数';

View File

@ -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>

View File

@ -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 添加文件路径,方便 killkill `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";
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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));
}
}

View File

@ -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