Commit d3208434 by T

第一次提交

parents
### IDEA ###
.idea/*
*.iml
*/target/*
*/*.iml
\ No newline at end of file
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 2018 Elune
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.
\ No newline at end of file
<h1 style="text-align: center">el-admin 后台管理系统</h1>
<div style="text-align: center">
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/elunez/eladmin/blob/master/LICENSE)
[![star](https://gitee.com/elunez/eladmin/badge/star.svg?theme=white)](https://gitee.com/elunez/eladmin)
[![GitHub stars](https://img.shields.io/github/stars/elunez/eladmin.svg?style=social&label=Stars)](https://github.com/elunez/eladmin)
[![GitHub forks](https://img.shields.io/github/forks/elunez/eladmin.svg?style=social&label=Fork)](https://github.com/elunez/eladmin)
</div>
#### 项目简介
eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前后端分离的后台管理系统, 权限控制的方式为RBAC,项目支持数据字典与数据权限管理,支持一键生成前后端代码,支持前端菜单动态路由
**开发文档** [https://docs.auauz.net/](https://docs.auauz.net)
**体验地址** [https://auauz.net/](https://auauz.net/)
**账号密码** ```admin/123456```(默认密码都是123456)
#### 项目源码
| | 后端源码 | 前端源码 |
|--- |--- | --- |
| github | https://github.com/elunez/eladmin | https://github.com/elunez/eladmin-web |
| 码云 | https://gitee.com/elunez/eladmin | https://gitee.com/elunez/eladmin-web |
#### 系统功能
- 用户管理:提供用户的相关配置,新增用户后,默认密码为123456
- 角色管理:对权限与菜单进行分配,可根据部门设置角色的数据权限
- 菜单管理:已实现菜单动态路由,后端可配置化,支持多级菜单
- 部门管理:可配置系统组织架构,树形表格展示
- 岗位管理:配置各个部门的职位
- 字典管理:应广大码友的要求加入字典管理,可维护常用一些固定的数据,如:状态,性别等
- 操作日志:记录用户操作的日志
- 异常日志:记录异常日志,方便开发人员定位错误
- 系统缓存:使用jedis将缓存操作可视化,并提供对redis的基本操作,可根据需求自行扩展
- SQL监控:采用druid 监控数据库访问性能,默认用户名admin,密码123456
- 定时任务:整合Quartz做定时任务,加入任务日志,任务运行情况一目了然
- 代码生成:高灵活度一键生成前后端代码,减少百分之80左右的工作任务
- 邮件工具:配合富文本,发送html格式的邮件
- 免费图床:使用sm.ms图床,用作公共图片上传使用
- 七牛云存储:可同步七牛云存储的数据到系统,无需登录七牛云直接操作云数据
- 支付宝支付:整合了支付宝支付并且提供了测试账号,可自行测试
#### 项目结构
项目采用按功能分模块开发方式,将通用的配置放在公共模块,```system```模块为系统核心模块也是项目入口模块,```logging``` 模块为系统的日志模块,```tools``` 为第三方工具模块,包含了图床、邮件、七牛云、支付宝,```generator``` 为系统的代码生成模块
- eladmin-common 公共模块
- annotation 为系统自定义注解
- aspect 自定义注解的切面
- base 提供了Entity、DTO基类和mapstruct的通用mapper
- config 自定义权限实现、redis配置、swagger配置
- exception 项目统一异常的处理
- utils 系统通用工具类
- eladmin-system 系统核心模块(系统启动入口)
- config 配置跨域与静态资源,与数据权限
- thread 线程池相关
- modules 系统相关模块(登录授权、系统监控、定时任务等)
- eladmin-logging 系统日志模块
- eladmin-tools 系统第三方工具模块
- eladmin-generator 系统代码生成模块
#### 系统预览
<table>
<tr>
<td><img src="https://i.loli.net/2019/05/18/5cdf77fa8144d68788.png"/></td>
<td><img src="https://i.loli.net/2019/05/18/5cdf7763993e361778.png"/></td>
</tr>
<tr>
<td><img src="https://i.loli.net/2019/05/18/5cdf7763971d453615.png"/></td>
<td><img src="https://i.loli.net/2019/05/18/5cdf77632e85a60423.png"/></td>
</tr>
<tr>
<td><img src="https://i.loli.net/2019/05/18/5cdf77632b4b090165.png"/></td>
<td><img src="https://i.loli.net/2019/05/18/5cdf77639929277783.png"/></td>
</tr>
<tr>
<td><img src="https://i.loli.net/2019/05/18/5cdf78969adc389599.png"/></td>
</tr>
</table>
#### 项目捐赠
项目的发展离不开你的支持,请作者喝杯咖啡吧!ps:辣条也行 ☕! [Donate](https://docs.auauz.net/#/jz)
#### 反馈交流
- QQ交流群:891137268
<?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>eladmin</artifactId>
<groupId>me.zhengjie</groupId>
<version>2.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eladmin-common</artifactId>
<name>公共模块</name>
</project>
\ No newline at end of file
package me.zhengjie.annotation;
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 AnonymousAccess {
}
package me.zhengjie.annotation;
import me.zhengjie.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;
}
package me.zhengjie.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Zheng Jie
* @date 2019-6-4 13:52:30
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Query {
// Dong ZhaoYang 2017/8/7 基本对象的属性名
String propName() default "";
// Dong ZhaoYang 2017/8/7 查询方式
Type type() default Type.EQUAL;
/**
* 连接查询的属性名,如User类中的dept
*/
String joinName() default "";
/**
* 默认左连接
*/
Join join() default Join.LEFT;
/**
* 多字段模糊搜索,仅支持String类型字段,多个用逗号隔开, 如@Query(blurry = "email,username")
*/
String blurry() default "";
String[] orPropNames() default {};
String orPropVal() default "";
enum Type {
// jie 2019/6/4 相等
EQUAL
// Dong ZhaoYang 2017/8/7 大于等于
, GREATER_THAN
// Dong ZhaoYang 2017/8/7 小于等于
, LESS_THAN
// Dong ZhaoYang 2017/8/7 中模糊查询
, INNER_LIKE
// Dong ZhaoYang 2017/8/7 左模糊查询
, LEFT_LIKE
// Dong ZhaoYang 2017/8/7 右模糊查询
, RIGHT_LIKE
// Dong ZhaoYang 2017/8/7 小于
, LESS_THAN_NQ
// jie 2019/6/4 包含
, IN
// huang 2020/7/76 或者
, OR
// huang 2020/7/16 相等或者等于null
, CONTAINS_NULL
}
/**
* @author Zheng Jie
* 适用于简单连接查询,复杂的请自定义该注解,或者使用sql查询
*/
enum Join {
/** jie 2019-6-4 13:18:30 左连接 */
LEFT
/** jie 2019-6-4 13:18:30 右连接 */
, RIGHT
}
}
package me.zhengjie.aspect;
import com.google.common.collect.ImmutableList;
import me.zhengjie.annotation.Limit;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.utils.RequestHolder;
import me.zhengjie.utils.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
@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(me.zhengjie.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().replaceAll("/","_")));
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;";
}
}
package me.zhengjie.aspect;
/**
* 限流枚举
* @author /
*/
public enum LimitType {
// 默认
CUSTOMER,
// by ip addr
IP;
}
package me.zhengjie.base;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @Date 2019年10月24日20:48:53
*/
@Getter
@Setter
public class BaseDTO implements Serializable {
private Boolean isDelete;
private Timestamp createTime;
private Timestamp updateTime;
}
package me.zhengjie.base;
import lombok.*;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.sql.Timestamp;
import java.lang.reflect.Field;
/**
* @author Zheng Jie
* @Date 2019年10月24日20:46:32
*/
@Getter
@Setter
@MappedSuperclass
public class BaseEntity implements Serializable {
// 删除标识
@Column(name = "is_delete", columnDefinition = "bit default 0")
private Boolean isDelete = false;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
@Column(name = "update_time")
@UpdateTimestamp
private Timestamp updateTime;
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();
}
}
package me.zhengjie.base;
import java.util.List;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
public interface BaseMapper<D, E> {
/**
* DTO转Entity
*/
E toEntity(D dto);
/**
* Entity转DTO
*/
D toDto(E entity);
/**
* DTO集合转Entity集合
*/
List <E> toEntity(List<D> dtoList);
/**
* Entity集合转DTO集合
*/
List <D> toDto(List<E> entityList);
}
package me.zhengjie.config;
import me.zhengjie.utils.SecurityUtils;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Service(value = "el")
public class ElPermissionConfig {
public Boolean check(String ...permissions){
// 如果是匿名访问的,就放行
String anonymous = "anonymous";
if(Arrays.asList(permissions).contains(anonymous)){
return true;
}
// 获取当前用户的所有权限
List<String> elPermissions = SecurityUtils.getUserDetails().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
// 判断当前用户的所有权限是否包含接口上定义的权限
return elPermissions.contains("admin") || Arrays.stream(permissions).anyMatch(elPermissions::contains);
}
}
package me.zhengjie.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 me.zhengjie.utils.StringUtils;
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 java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2018-11-24
*/
@Slf4j
@Configuration
@EnableCaching
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig extends CachingConfigurerSupport {
/**
* 设置 redis 数据默认过期时间,默认6小时
* 设置@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(6));
return configuration;
}
@Bean(name = "redisTemplate")
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//序列化
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
// value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
// 全局开启AutoType,这里方便开发,使用全局的方式
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
// 建议使用这种方式,小范围指定白名单
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.domain");
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.service.dto");
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.service.dto");
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.domain");
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.quartz.domain");
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.monitor.domain");
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.security.security");
// 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<>();
Class<?> targetClassClass = target.getClass();
// 类地址
container.put("class",targetClassClass.toGenericString());
// 方法名称
container.put("methodName",method.getName());
// 包名称
container.put("package",targetClassClass.getPackage());
// 参数列表
for (int i = 0; i < params.length; i++) {
container.put(String.valueOf(i),params[i]);
}
// 转为JSON字符串
String jsonString = JSON.toJSONString(container);
// 做SHA256 Hash计算,得到一个SHA256摘要作为Key
return DigestUtils.sha256Hex(jsonString);
};
}
@Bean
@Override
public CacheErrorHandler errorHandler() {
// 异常处理,当Redis发生异常时,打印日志,但是程序正常走
log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
return new CacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
}
@Override
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
}
@Override
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
}
@Override
public void handleCacheClearError(RuntimeException e, Cache cache) {
log.error("Redis occur handleCacheClearError:", e);
}
};
}
}
/**
* Value 序列化
*
* @author /
* @param <T>
*/
class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
private 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 byte[] serialize(Object object) {
String string = JSON.toJSONString(object);
if (StringUtils.isBlank(string)) {
return null;
}
string = string.replace("\"", "");
return string.getBytes(charset);
}
}
package me.zhengjie.config;
import com.fasterxml.classmate.TypeResolver;
import com.google.common.base.Predicates;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.data.domain.Pageable;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.schema.AlternateTypeRule;
import springfox.documentation.schema.AlternateTypeRuleConvention;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
import static springfox.documentation.schema.AlternateTypeRules.newRule;
/**
* api页面 /swagger-ui.html
* @author Zheng Jie
* @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() {
ParameterBuilder ticketPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
ticketPar.name(tokenHeader).description("token")
.modelRef(new ModelRef("string"))
.parameterType("header")
.defaultValue("Bearer ")
.required(true)
.build();
pars.add(ticketPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.enable(enabled)
.apiInfo(apiInfo())
.select()
.paths(Predicates.not(PathSelectors.regex("/error.*")))
.build()
.globalOperationParameters(pars);
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("eladmin 接口文档")
.version("2.3")
.build();
}
}
/**
* 将Pageable转换展示在swagger中
*/
@Configuration
class SwaggerDataConfig {
@Bean
public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) {
return new AlternateTypeRuleConvention() {
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
@Override
public List<AlternateTypeRule> rules() {
return newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(Page.class)));
}
};
}
@ApiModel
@Data
private static class Page {
@ApiModelProperty("页码 (0..N)")
private Integer page;
@ApiModelProperty("每页显示的数目")
private Integer size;
@ApiModelProperty("以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc")
private List<String> sort;
}
}
package me.zhengjie.exception;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
/**
* @author Zheng Jie
* @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();
}
}
package me.zhengjie.exception;
import org.springframework.util.StringUtils;
/**
* @author Zheng Jie
* @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";
}
}
\ No newline at end of file
package me.zhengjie.exception;
import org.springframework.util.StringUtils;
/**
* @author Zheng Jie
* @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";
}
}
\ No newline at end of file
package me.zhengjie.exception.handler;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Data
class ApiError {
private Integer status = 400;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime timestamp;
private String message;
private ApiError() {
timestamp = LocalDateTime.now();
}
public static ApiError error(String message){
ApiError apiError = new ApiError();
apiError.setMessage(message);
return apiError;
}
public static ApiError error(Integer status, String message){
ApiError apiError = new ApiError();
apiError.setStatus(status);
apiError.setMessage(message);
return apiError;
}
}
package me.zhengjie.exception.handler;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.exception.EntityExistException;
import me.zhengjie.exception.EntityNotFoundException;
import me.zhengjie.utils.ThrowableUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.Objects;
import static org.springframework.http.HttpStatus.*;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理所有不可知的异常
*/
@ExceptionHandler(Throwable.class)
public ResponseEntity handleException(Throwable e){
// 打印堆栈信息
log.error(ThrowableUtil.getStackTrace(e));
return buildResponseEntity(ApiError.error(e.getMessage()));
}
/**
* 处理 接口无权访问异常AccessDeniedException
*/
@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity handleAccessDeniedException(AccessDeniedException e){
// 打印堆栈信息
log.error(ThrowableUtil.getStackTrace(e));
return buildResponseEntity(ApiError.error(FORBIDDEN.value(),e.getMessage()));
}
/**
* 处理自定义异常
*/
@ExceptionHandler(value = BadRequestException.class)
public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
// 打印堆栈信息
log.error(ThrowableUtil.getStackTrace(e));
return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage()));
}
/**
* 处理 EntityExist
*/
@ExceptionHandler(value = EntityExistException.class)
public ResponseEntity<ApiError> entityExistException(EntityExistException e) {
// 打印堆栈信息
log.error(ThrowableUtil.getStackTrace(e));
return buildResponseEntity(ApiError.error(e.getMessage()));
}
/**
* 处理 EntityNotFound
*/
@ExceptionHandler(value = EntityNotFoundException.class)
public ResponseEntity<ApiError> entityNotFoundException(EntityNotFoundException e) {
// 打印堆栈信息
log.error(ThrowableUtil.getStackTrace(e));
return buildResponseEntity(ApiError.error(NOT_FOUND.value(),e.getMessage()));
}
/**
* 处理所有接口数据验证异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ApiError> handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
// 打印堆栈信息
log.error(ThrowableUtil.getStackTrace(e));
String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
if("不能为空".equals(message)){
message = str[1] + ":" + message;
}
return buildResponseEntity(ApiError.error(message));
}
/**
* 统一返回
*/
private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
return new ResponseEntity<>(apiError, HttpStatus.valueOf(apiError.getStatus()));
}
}
package me.zhengjie.utils;
/**
* 常用静态常量
* @author Zheng Jie
* @date 2018-12-26
*/
public class ElAdminConstant {
public static final String RESET_PASS = "重置密码";
public static final String RESET_MAIL = "重置邮箱";
/**
* 用于IP定位转换
*/
static final String REGION = "内网IP|内网IP";
/**
* 常用接口
*/
public static class Url{
public static final String SM_MS_URL = "https://sm.ms/api/upload";
}
}
package me.zhengjie.utils;
import org.springframework.util.DigestUtils;
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 Zheng Jie
* @date 2018-11-23
*/
public class EncryptUtils {
private static String strKey = "Passw0rd", strParam = "Passw0rd";
/**
* 对称加密
*/
public static String desEncrypt(String source) throws Exception {
if (source == null || source.length() == 0){
return null;
}
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
DESKeySpec desKeySpec = new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
IvParameterSpec iv = new IvParameterSpec(strParam.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
return byte2hex(
cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase();
}
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) {
if ((b.length % 2) != 0){
throw new IllegalArgumentException("长度不是偶数");
}
byte[] b2 = new byte[b.length / 2];
for (int n = 0; n < b.length; n += 2) {
String item = new String(b, n, 2);
b2[n / 2] = (byte) Integer.parseInt(item, 16);
}
return b2;
}
/**
* 对称解密
*/
public static String desDecrypt(String source) throws Exception {
if (source == null || source.length() == 0){
return null;
}
byte[] src = hex2byte(source.getBytes());
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
DESKeySpec desKeySpec = new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
IvParameterSpec iv = new IvParameterSpec(strParam.getBytes(StandardCharsets.UTF_8));
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
byte[] retByte = cipher.doFinal(src);
return new String(retByte);
}
/**
* 密码加密
*/
public static String encryptPassword(String password){
return DigestUtils.md5DigestAsHex(password.getBytes());
}
}
package me.zhengjie.utils;
import cn.hutool.core.codec.Base64;
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 me.zhengjie.exception.BadRequestException;
import org.springframework.web.multipart.MultipartFile;
import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletOutputStream;
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 Zheng Jie
* @date 2018-12-27
*/
public class FileUtil extends cn.hutool.core.io.FileUtil {
/**
* 定义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");
/**
* MultipartFile转File
*/
public static File toFile(MultipartFile multipartFile){
// 获取文件名
String fileName = multipartFile.getOriginalFilename();
// 获取文件后缀
String prefix="."+getExtensionName(fileName);
File file = null;
try {
// 用uuid作为文件名,防止生成的临时文件重复
file = File.createTempFile(IdUtil.simpleUUID(), prefix);
// MultipartFile to File
multipartFile.transferTo(file);
} catch (IOException e) {
e.printStackTrace();
}
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) throws Exception{
File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name);
if (file.exists()) {
return file;
}
OutputStream os = new FileOutputStream(file);
int bytesRead;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
return file;
}
/**
* 将文件名解析成文件的上传路径
*/
public static File upload(MultipartFile file, String filePath) {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
String name = getFileNameNoEx(file.getOriginalFilename());
String suffix = getExtensionName(file.getOriginalFilename());
String nowStr = "-" + format.format(date);
try {
String fileName = name + nowStr + "." + suffix;
String path = filePath + fileName;
// getCanonicalFile 可解析正确各种路径
File dest = new File(path).getCanonicalFile();
// 检测是否存在目录
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
// 文件写入
file.transferTo(dest);
return dest;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String fileToBase64(File file) throws Exception {
FileInputStream inputFile = new FileInputStream(file);
String base64;
byte[] buffer = new byte[(int)file.length()];
inputFile.read(buffer);
inputFile.close();
base64=Base64.encode(buffer);
return base64.replaceAll("[\\s*\t\n\r]", "");
}
/**
* 导出excel
*/
public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
String tempPath =System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx";
File file = new File(tempPath);
BigExcelWriter writer= ExcelUtil.getBigWriter(file);
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(list, true);
//response为HttpServletResponse对象
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
response.setHeader("Content-Disposition","attachment;filename=file.xlsx");
ServletOutputStream out=response.getOutputStream();
// 终止后删除临时文件
file.deleteOnExit();
writer.flush(out, true);
//此处记得关闭输出Servlet流
IoUtil.close(out);
}
public static String getFileType(String type) {
String documents = "txt doc pdf ppt pps xlsx xls docx";
String music = "mp3 wav wma mpa ram ra aac aif m4a";
String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
if(image.contains(type)){
return "图片";
} else if(documents.contains(type)){
return "文档";
} else if(music.contains(type)){
return "音乐";
} else if(video.contains(type)){
return "视频";
} else {
return "其他";
}
}
public static String getFileTypeByMimeType(String type) {
String mimeType = new MimetypesFileTypeMap().getContentType("." + type);
return mimeType.split("/")[0];
}
public static void checkSize(long maxSize, long size) {
if(size > (maxSize * 1024 * 1024)){
throw new BadRequestException("文件超出规定大小");
}
}
/**
* 判断两个文件是否相同
*/
public static boolean check(File file1, File file2) {
String img1Md5 = getMd5(file1);
String img2Md5 = getMd5(file2);
return img1Md5.equals(img2Md5);
}
/**
* 判断两个文件是否相同
*/
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()];
try {
InputStream in = new FileInputStream(file);
try {
in.read(b);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
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) {
e.printStackTrace();
}
return null;
}
public static String getMd5(File file) {
return getMd5(getByte(file));
}
}
package me.zhengjie.utils;
import org.springframework.data.domain.Page;
import java.util.*;
/**
* 分页工具
* @author Zheng Jie
* @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;
}
}
package me.zhengjie.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.Query;
import javax.persistence.criteria.*;
import java.lang.reflect.Field;
import java.util.*;
/**
* @author Zheng Jie
* @date 2019-6-4 14:59:48
*/
@Slf4j
public class QueryHelp {
@SuppressWarnings("unchecked")
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]));
}
try {
List<Field> fields = getAllFields(query.getClass(), new ArrayList<>());
for (Field field : fields) {
boolean accessible = field.isAccessible();
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)){
join = join.join(name, JoinType.LEFT);
} else {
join = root.join(name, JoinType.LEFT);
}
break;
case RIGHT:
if(ObjectUtil.isNotNull(join)){
join = join.join(name, JoinType.RIGHT);
} else {
join = root.join(name, JoinType.RIGHT);
}
break;
default: break;
}
}
}
switch (q.type()) {
case EQUAL:
list.add(cb.equal(getExpression(attributeName,join,root)
.as((Class<? extends Comparable>) fieldType),val));
break;
case GREATER_THAN:
list.add(cb.greaterThanOrEqualTo(getExpression(attributeName,join,root)
.as((Class<? extends Comparable>) fieldType), (Comparable) val));
break;
case LESS_THAN:
list.add(cb.lessThanOrEqualTo(getExpression(attributeName,join,root)
.as((Class<? extends Comparable>) fieldType), (Comparable) val));
break;
case LESS_THAN_NQ:
list.add(cb.lessThan(getExpression(attributeName,join,root)
.as((Class<? extends Comparable>) fieldType), (Comparable) val));
break;
case INNER_LIKE:
list.add(cb.like(getExpression(attributeName,join,root)
.as(String.class), "%" + val.toString() + "%"));
break;
case LEFT_LIKE:
list.add(cb.like(getExpression(attributeName,join,root)
.as(String.class), "%" + val.toString()));
break;
case RIGHT_LIKE:
list.add(cb.like(getExpression(attributeName,join,root)
.as(String.class), val.toString() + "%"));
case IN:
if (CollUtil.isNotEmpty((Collection<Long>)val)) {
list.add(getExpression(attributeName,join,root).in((Collection<Long>) val));
}
break;
case OR:
if (Boolean.valueOf(q.orPropVal())) {
Predicate[] pArrays = (Predicate[]) Arrays.asList(q.orPropNames()).stream().map(
prop -> cb
.equal(getExpression(prop, null, root).as(String.class),
q.orPropVal())).toArray();
cb.or(pArrays);
}
break;
case CONTAINS_NULL:
List<Predicate> orPredicate = new ArrayList<>();
orPredicate.add(cb.equal(getExpression(attributeName,join,root)
.as((Class<? extends Comparable>) fieldType),val));
orPredicate.add(cb.isNull(getExpression(attributeName,join,root)));
Predicate[] p = new Predicate[orPredicate.size()];
list.add(cb.or(orPredicate.toArray(p)));
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;
}
private static List<Field> getAllFields(Class clazz, List<Field> fields) {
if (clazz != null) {
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
getAllFields(clazz.getSuperclass(), fields);
}
return fields;
}
}
package me.zhengjie.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 Zheng Jie
* @date 2018-11-24
*/
public class RequestHolder {
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
}
}
package me.zhengjie.utils;
import cn.hutool.json.JSONObject;
import me.zhengjie.exception.BadRequestException;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.userdetails.UserDetails;
/**
* 获取当前登录的用户
* @author Zheng Jie
* @date 2019-01-17
*/
public class SecurityUtils {
public static UserDetails getUserDetails() {
UserDetails userDetails;
try {
userDetails = (UserDetails) org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication().getPrincipal();
} catch (Exception e) {
throw new BadRequestException(HttpStatus.UNAUTHORIZED, "登录状态过期");
}
return userDetails;
}
/**
* 获取系统用户名称
* @return 系统用户名称
*/
public static String getUsername(){
Object obj = getUserDetails();
return new JSONObject(obj).get("username", String.class);
}
/**
* 获取系统用户id
* @return 系统用户id
*/
public static String getUserId(){
Object obj = getUserDetails();
return new JSONObject(obj).get("id", String.class);
}
}
package me.zhengjie.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;
/**
* @author Jie
* @date 2019-01-07
*/
@Slf4j
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
private static ApplicationContext applicationContext = null;
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
assertContextInjected();
return (T) applicationContext.getBean(name);
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(Class<T> requiredType) {
assertContextInjected();
return applicationContext.getBean(requiredType);
}
/**
* 检查ApplicationContext不为空.
*/
private static void assertContextInjected() {
if (applicationContext == null) {
throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
}
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
private static void clearHolder() {
log.debug("清除SpringContextHolder中的ApplicationContext:"
+ applicationContext);
applicationContext = null;
}
@Override
public void destroy(){
SpringContextHolder.clearHolder();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringContextHolder.applicationContext != null) {
log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
}
SpringContextHolder.applicationContext = applicationContext;
}
}
package me.zhengjie.utils;
import cn.hutool.core.io.resource.ClassPathResource;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.UserAgent;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.Date;
/**
* 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
*/
public class StringUtils extends org.apache.commons.lang3.StringUtils {
private static final char SEPARATOR = '_';
/**
* 驼峰命名法工具
*
* @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();
}
if (ip.contains(",")) {
ip = ip.split(",")[0];
}
if ("127.0.0.1".equals(ip)) {
// 获取本机真正的ip地址
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
return ip;
}
/**
* 根据ip获取详细地址
*/
public static String getCityInfo(String ip) {
try {
String path = "ip2region/ip2region.db";
String name = "ip2region.db";
DbConfig config = new DbConfig();
File file = FileUtil.inputStreamToFile(new ClassPathResource(path).getStream(), name);
DbSearcher searcher = new DbSearcher(config, file.getPath());
Method method;
method = searcher.getClass().getMethod("btreeSearch", String.class);
DataBlock dataBlock;
dataBlock = (DataBlock) method.invoke(searcher, ip);
String address = dataBlock.getRegion().replace("0|","");
if(address.charAt(address.length()-1) == '|'){
address = address.substring(0,address.length() - 1);
}
return address.equals(ElAdminConstant.REGION)?"内网IP":address;
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public static String getBrowser(HttpServletRequest request){
UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
Browser browser = userAgent.getBrowser();
return browser.getName();
}
/**
* 获得当天是周几
*/
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];
}
}
\ No newline at end of file
package me.zhengjie.utils;
import me.zhengjie.exception.BadRequestException;
import org.hibernate.exception.ConstraintViolationException;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* 异常工具 2019-01-06
* @author Zheng Jie
*/
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();
}
}
public static void throwForeignKeyException(Throwable e, String msg){
Throwable t = e.getCause();
while ((t != null) && !(t instanceof ConstraintViolationException)) {
t = t.getCause();
}
if (t != null) {
throw new BadRequestException(msg);
}
assert false;
throw new BadRequestException("删除失败:" + t.getMessage());
}
}
package me.zhengjie.utils;
import cn.hutool.json.JSONArray;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
public class TranslatorUtil {
public static String translate(String word){
try {
String url = "https://translate.googleapis.com/translate_a/single?" +
"client=gtx&" +
"sl=en" +
"&tl=zh-CN" +
"&dt=t&q=" + URLEncoder.encode(word, "UTF-8");
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestProperty("User-Agent", "Mozilla/5.0");
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return parseResult(response.toString());
}catch (Exception e){
return word;
}
}
private static String parseResult(String inputJson){
JSONArray jsonArray2 = (JSONArray) new JSONArray(inputJson).get(0);
StringBuilder result = new StringBuilder();
for (Object o : jsonArray2) {
result.append(((JSONArray) o).get(0).toString());
}
return result.toString();
}
}
package me.zhengjie.utils;
import cn.hutool.core.util.ObjectUtil;
import me.zhengjie.exception.BadRequestException;
/**
* 验证工具
* @author Zheng Jie
* @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 string) {
if (string == null){
return false;
}
String regEx1 = "^([a-z0-9A-Z]+[-|.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
return string.matches(regEx1);
}
}
package me.zhengjie.utils;
import org.junit.Test;
import static org.junit.Assert.*;
import static me.zhengjie.utils.EncryptUtils.*;
public class EncryptUtilsTest {
/**
* 对称加密
*/
@Test
public void testDesEncrypt() {
try {
assertEquals("7772841DC6099402", desEncrypt("123456"));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 对称解密
*/
@Test
public void testDesDecrypt() {
try {
assertEquals("123456", desDecrypt("7772841DC6099402"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
package me.zhengjie.utils;
import org.junit.Test;
import org.springframework.mock.web.MockMultipartFile;
import static org.junit.Assert.*;
import static me.zhengjie.utils.FileUtil.*;
public class FileUtilTest {
@Test
public void testToFile() {
long retval = toFile(new MockMultipartFile("foo", (byte[]) null)).getTotalSpace();
assertEquals(500695072768L, retval);
}
@Test
public void testGetExtensionName() {
assertEquals("foo", getExtensionName("foo"));
assertEquals("exe", getExtensionName("bar.exe"));
}
@Test
public void testGetFileNameNoEx() {
assertEquals("foo", getFileNameNoEx("foo"));
assertEquals("bar", getFileNameNoEx("bar.txt"));
}
@Test
public void testGetSize() {
assertEquals("1000B ", getSize(1000));
assertEquals("1.00KB ", getSize(1024));
assertEquals("1.00MB ", getSize(1048576));
assertEquals("1.00GB ", getSize(1073741824));
}
}
package me.zhengjie.utils;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;
import static me.zhengjie.utils.StringUtils.*;
import static org.junit.Assert.*;
public class StringUtilsTest {
@Test
public void testToCamelCase() {
assertNull(toCamelCase(null));
}
@Test
public void testToCapitalizeCamelCase() {
assertNull(StringUtils.toCapitalizeCamelCase(null));
assertEquals("HelloWorld", toCapitalizeCamelCase("hello_world"));
}
@Test
public void testToUnderScoreCase() {
assertNull(StringUtils.toUnderScoreCase(null));
assertEquals("hello_world", toUnderScoreCase("helloWorld"));
assertEquals("\u0000\u0000", toUnderScoreCase("\u0000\u0000"));
assertEquals("\u0000_a", toUnderScoreCase("\u0000A"));
}
@Test
public void testGetWeekDay() {
SimpleDateFormat simpleDateformat = new SimpleDateFormat("E");
assertEquals(simpleDateformat.format(new Date()), getWeekDay());
}
@Test
public void testGetIP() {
assertEquals("127.0.0.1", getIp(new MockHttpServletRequest()));
}
}
\ No newline at end of file
<?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>eladmin</artifactId>
<groupId>me.zhengjie</groupId>
<version>2.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eladmin-generator</artifactId>
<name>代码生成模块</name>
<properties>
<configuration.version>1.9</configuration.version>
</properties>
<dependencies>
<dependency>
<groupId>me.zhengjie</groupId>
<artifactId>eladmin-common</artifactId>
<version>2.3</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>
\ No newline at end of file
package me.zhengjie.domain;
import lombok.Data;
import javax.persistence.*;
/**
* 代码生成配置
* @author Zheng Jie
* @date 2019-01-03
*/
@Data
@Entity
@Table(name = "gen_config")
public class GenConfig {
@Id
private Long id;
// 包路径
private String pack;
// 模块名
@Column(name = "module_name")
private String moduleName;
// 前端文件路径
private String path;
// 前端文件路径
@Column(name = "api_path")
private String apiPath;
// 作者
private String author;
// 表前缀
private String prefix;
// 是否覆盖
private Boolean cover;
}
package me.zhengjie.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 列的数据信息
* @author Zheng Jie
* @date 2019-01-02
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ColumnInfo {
// 数据库字段名称
private Object columnName;
// 允许空值
private Object isNullable;
// 数据库字段类型
private Object columnType;
// 数据库字段注释
private Object columnComment;
// 数据库字段键类型
private Object columnKey;
// 额外的参数
private Object extra;
// 查询 1:模糊 2:精确
private String columnQuery;
// 是否在列表显示
private String columnShow;
}
package me.zhengjie.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 表的数据信息
* @author Zheng Jie
* @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;
}
package me.zhengjie.repository;
import me.zhengjie.domain.GenConfig;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author Zheng Jie
* @date 2019-01-14
*/
public interface GenConfigRepository extends JpaRepository<GenConfig,Long> {
}
package me.zhengjie.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.domain.GenConfig;
import me.zhengjie.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 Zheng Jie
* @date 2019-01-14
*/
@RestController
@RequestMapping("/api/genConfig")
@Api(tags = "系统:代码生成器配置管理")
public class GenConfigController {
private final GenConfigService genConfigService;
public GenConfigController(GenConfigService genConfigService) {
this.genConfigService = genConfigService;
}
@ApiOperation("查询")
@GetMapping
public ResponseEntity get(){
return new ResponseEntity<>(genConfigService.find(), HttpStatus.OK);
}
@ApiOperation("修改")
@PutMapping
public ResponseEntity emailConfig(@Validated @RequestBody GenConfig genConfig){
return new ResponseEntity<>(genConfigService.update(genConfig),HttpStatus.OK);
}
}
package me.zhengjie.rest;
import cn.hutool.core.util.PageUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.domain.vo.ColumnInfo;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.service.GenConfigService;
import me.zhengjie.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 java.util.List;
/**
* @author Zheng Jie
* @date 2019-01-02
*/
@RestController
@RequestMapping("/api/generator")
@Api(tags = "系统:代码生成管理")
public class GeneratorController {
private final GeneratorService generatorService;
private final GenConfigService genConfigService;
@Value("${generator.enabled}")
private Boolean generatorEnabled;
public GeneratorController(GeneratorService generatorService, GenConfigService genConfigService) {
this.generatorService = generatorService;
this.genConfigService = genConfigService;
}
@ApiOperation("查询数据库元数据")
@GetMapping(value = "/tables")
public ResponseEntity getTables(@RequestParam(defaultValue = "") String name,
@RequestParam(defaultValue = "0")Integer page,
@RequestParam(defaultValue = "10")Integer size){
int[] startEnd = PageUtil.transToStartEnd(page+1, size);
return new ResponseEntity<>(generatorService.getTables(name,startEnd), HttpStatus.OK);
}
@ApiOperation("查询表内元数据")
@GetMapping(value = "/columns")
public ResponseEntity getTables(@RequestParam String tableName){
return new ResponseEntity<>(generatorService.getColumns(tableName), HttpStatus.OK);
}
@ApiOperation("生成代码")
@PostMapping
public ResponseEntity generator(@RequestBody List<ColumnInfo> columnInfos, @RequestParam String tableName){
if(!generatorEnabled){
throw new BadRequestException("此环境不允许生成代码!");
}
generatorService.generator(columnInfos,genConfigService.find(),tableName);
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.service;
import me.zhengjie.domain.GenConfig;
/**
* @author Zheng Jie
* @date 2019-01-14
*/
public interface GenConfigService {
GenConfig find();
GenConfig update(GenConfig genConfig);
}
package me.zhengjie.service;
import me.zhengjie.domain.GenConfig;
import me.zhengjie.domain.vo.ColumnInfo;
import java.util.List;
/**
* @author Zheng Jie
* @date 2019-01-02
*/
public interface GeneratorService {
/**
* 查询数据库元数据
* @param name 表名
* @param startEnd 分页参数
* @return /
*/
Object getTables(String name, int[] startEnd);
/**
* 得到数据表的元数据
* @param name 表名
* @return /
*/
Object getColumns(String name);
/**
* 生成代码
* @param columnInfos 表字段数据
* @param genConfig 代码生成配置
* @param tableName 表名
*/
void generator(List<ColumnInfo> columnInfos, GenConfig genConfig, String tableName);
}
package me.zhengjie.service.impl;
import me.zhengjie.domain.GenConfig;
import me.zhengjie.repository.GenConfigRepository;
import me.zhengjie.service.GenConfigService;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.Optional;
/**
* @author Zheng Jie
* @date 2019-01-14
*/
@Service
@CacheConfig(cacheNames = "genConfig")
public class GenConfigServiceImpl implements GenConfigService {
private final GenConfigRepository genConfigRepository;
public GenConfigServiceImpl(GenConfigRepository genConfigRepository) {
this.genConfigRepository = genConfigRepository;
}
@Override
@Cacheable(key = "'1'")
public GenConfig find() {
Optional<GenConfig> genConfig = genConfigRepository.findById(1L);
return genConfig.orElseGet(GenConfig::new);
}
@Override
@CacheEvict(allEntries = true)
public GenConfig update(GenConfig genConfig) {
genConfig.setId(1L);
// 自动设置Api路径,注释掉前需要同步取消前端的注释
String separator = File.separator;
String[] paths;
if (separator.equals("\\")) {
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 (path.equals("src")) {
api.append("api");
break;
}
}
genConfig.setApiPath(api.toString());
return genConfigRepository.save(genConfig);
}
}
package me.zhengjie.service.impl;
import cn.hutool.core.util.ObjectUtil;
import me.zhengjie.domain.GenConfig;
import me.zhengjie.domain.vo.ColumnInfo;
import me.zhengjie.domain.vo.TableInfo;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.service.GeneratorService;
import me.zhengjie.utils.GenUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.StringUtils;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author Zheng Jie
* @date 2019-01-02
*/
@Service
public class GeneratorServiceImpl implements GeneratorService {
@PersistenceContext
private EntityManager em;
@Override
@SuppressWarnings("all")
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 ? order by create_time desc";
Query query = em.createNativeQuery(sql);
query.setFirstResult(startEnd[0]);
query.setMaxResults(startEnd[1]-startEnd[0]);
query.setParameter(1, 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] : "-"));
}
Query query1 = em.createNativeQuery("SELECT COUNT(*) from information_schema.tables where table_schema = (select database())");
Object totalElements = query1.getSingleResult();
return PageUtil.toPage(tableInfos,totalElements);
}
@Override
@SuppressWarnings("all")
public Object getColumns(String name) {
// 使用预编译防止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, StringUtils.isNotBlank(name) ? name : null);
List result = query.getResultList();
List<ColumnInfo> columnInfos = new ArrayList<>();
for (Object obj : result) {
Object[] arr = (Object[]) obj;
columnInfos.add(new ColumnInfo(arr[0],arr[1],arr[2],arr[3],arr[4],arr[5],null,"true"));
}
return PageUtil.toPage(columnInfos,columnInfos.size());
}
@Override
public void generator(List<ColumnInfo> columnInfos, GenConfig genConfig, String tableName) {
if(genConfig.getId() == null){
throw new BadRequestException("请先配置生成器");
}
try {
GenUtil.generatorCode(columnInfos,genConfig,tableName);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
package me.zhengjie.utils;
import org.apache.commons.configuration.*;
/**
* sql字段转java
*
* @author Zheng Jie
* @date 2019-01-03
*/
public class ColUtil {
/**
* 转换mysql数据类型为java数据类型
* @param type 数据库字段类型
* @return String
*/
static String cloToJava(String type){
Configuration config = getConfig();
assert config != null;
return config.getString(type,"unknowType");
}
/**
* 获取配置信息
*/
public static PropertiesConfiguration getConfig() {
try {
return new PropertiesConfiguration("generator.properties" );
} catch (ConfigurationException e) {
e.printStackTrace();
}
return null;
}
}
package me.zhengjie.utils;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.template.*;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.domain.GenConfig;
import me.zhengjie.domain.vo.ColumnInfo;
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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 代码生成
* @author Zheng Jie
* @date 2019-01-02
*/
@Slf4j
public class GenUtil {
private static final String TIMESTAMP = "Timestamp";
private static final String BIGDECIMAL = "BigDecimal";
private static final String PK = "PRI";
private 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("Repository");
templateNames.add("Service");
templateNames.add("ServiceImpl");
templateNames.add("QueryCriteria");
templateNames.add("Controller");
return templateNames;
}
/**
* 获取前端代码模板名称
* @return List
*/
private static List<String> getFrontTemplateNames() {
List<String> templateNames = new ArrayList<>();
templateNames.add("api");
templateNames.add("index");
templateNames.add("eForm");
return templateNames;
}
/**
* 生成代码
* @param columnInfos 表元数据
* @param genConfig 生成代码的参数配置,如包路径,作者
*/
public static void generatorCode(List<ColumnInfo> columnInfos, GenConfig genConfig, String tableName) throws IOException {
Map<String,Object> map = new HashMap<>();
map.put("package",genConfig.getPack());
map.put("moduleName",genConfig.getModuleName());
map.put("author",genConfig.getAuthor());
map.put("date", LocalDate.now().toString());
map.put("tableName",tableName);
String className = StringUtils.toCapitalizeCamelCase(tableName);
String changeClassName = StringUtils.toCamelCase(tableName);
// 判断是否去除表前缀
if (StringUtils.isNotEmpty(genConfig.getPrefix())) {
className = StringUtils.toCapitalizeCamelCase(StrUtil.removePrefix(tableName,genConfig.getPrefix()));
changeClassName = StringUtils.toCamelCase(StrUtil.removePrefix(tableName,genConfig.getPrefix()));
}
map.put("className", className);
map.put("upperCaseClassName", className.toUpperCase());
map.put("changeClassName", changeClassName);
map.put("hasTimestamp",false);
map.put("queryHasTimestamp",false);
map.put("queryHasBigDecimal",false);
map.put("hasBigDecimal",false);
map.put("hasQuery",false);
map.put("auto",false);
List<Map<String,Object>> columns = new ArrayList<>();
List<Map<String,Object>> queryColumns = new ArrayList<>();
for (ColumnInfo column : columnInfos) {
Map<String,Object> listMap = new HashMap<>();
listMap.put("columnComment",column.getColumnComment());
listMap.put("columnKey",column.getColumnKey());
String colType = ColUtil.cloToJava(column.getColumnType().toString());
String changeColumnName = StringUtils.toCamelCase(column.getColumnName().toString());
String capitalColumnName = StringUtils.toCapitalizeCamelCase(column.getColumnName().toString());
if(PK.equals(column.getColumnKey())){
map.put("pkColumnType",colType);
map.put("pkChangeColName",changeColumnName);
map.put("pkCapitalColName",capitalColumnName);
}
if(TIMESTAMP.equals(colType)){
map.put("hasTimestamp",true);
}
if(BIGDECIMAL.equals(colType)){
map.put("hasBigDecimal",true);
}
if(EXTRA.equals(column.getExtra())){
map.put("auto",true);
}
listMap.put("columnType",colType);
listMap.put("columnName",column.getColumnName());
listMap.put("isNullable",column.getIsNullable());
listMap.put("columnShow",column.getColumnShow());
listMap.put("changeColumnName",changeColumnName);
listMap.put("capitalColumnName",capitalColumnName);
// 判断是否有查询,如有则把查询的字段set进columnQuery
if(!StringUtils.isBlank(column.getColumnQuery())){
listMap.put("columnQuery",column.getColumnQuery());
map.put("hasQuery",true);
if(TIMESTAMP.equals(colType)){
map.put("queryHasTimestamp",true);
}
if(BIGDECIMAL.equals(colType)){
map.put("queryHasBigDecimal",true);
}
queryColumns.add(listMap);
}
columns.add(listMap);
}
map.put("columns",columns);
map.put("queryColumns",queryColumns);
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,className);
assert filePath != null;
File file = new File(filePath);
// 如果非覆盖生成
if(!genConfig.getCover() && FileUtil.exist(file)){
continue;
}
// 生成代码
genFile(file, template, map);
}
// 生成前端代码
templates = getFrontTemplateNames();
for (String templateName : templates) {
Template template = engine.getTemplate("generator/front/"+templateName+".ftl");
String filePath = getFrontFilePath(templateName,genConfig,map.get("changeClassName").toString());
assert filePath != null;
File file = new File(filePath);
// 如果非覆盖生成
if(!genConfig.getCover() && FileUtil.exist(file)){
continue;
}
// 生成代码
genFile(file, template, map);
}
}
/**
* 定义后端文件路径以及名称
*/
private static String getAdminFilePath(String templateName, GenConfig genConfig, String className) {
String projectPath = System.getProperty("user.dir") + 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 + "mapper" + 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, GenConfig genConfig, String apiName) {
String path = genConfig.getPath();
if ("api".equals(templateName)) {
return genConfig.getApiPath() + File.separator + apiName + ".js";
}
if ("index".equals(templateName)) {
return path + File.separator + "index.vue";
}
if ("eForm".equals(templateName)) {
return path + File.separator + File.separator + "form.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();
}
}
}
<?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>eladmin</artifactId>
<groupId>me.zhengjie</groupId>
<version>2.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eladmin-logging</artifactId>
<name>日志模块</name>
<dependencies>
<dependency>
<groupId>me.zhengjie</groupId>
<artifactId>eladmin-common</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package me.zhengjie.aop.log;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Zheng Jie
* @date 2018-11-24
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
String value() default "";
}
package me.zhengjie.aspect;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.domain.Log;
import me.zhengjie.service.LogService;
import me.zhengjie.utils.RequestHolder;
import me.zhengjie.utils.SecurityUtils;
import me.zhengjie.utils.StringUtils;
import me.zhengjie.utils.ThrowableUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* @author Zheng Jie
* @date 2018-11-24
*/
@Component
@Aspect
@Slf4j
public class LogAspect {
private final LogService logService;
private long currentTime = 0L;
public LogAspect(LogService logService) {
this.logService = logService;
}
/**
* 配置切入点
*/
@Pointcut("@annotation(me.zhengjie.aop.log.Log)")
public void logPointcut() {
// 该方法无方法体,主要为了让同类中其他方法使用此切入点
}
/**
* 配置环绕通知,使用在方法logPointcut()上注册的切入点
*
* @param joinPoint join point for advice
*/
@Around("logPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object result;
currentTime = System.currentTimeMillis();
result = joinPoint.proceed();
Log log = new Log("INFO",System.currentTimeMillis() - currentTime);
HttpServletRequest request = RequestHolder.getHttpServletRequest();
logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request),joinPoint, log);
return result;
}
/**
* 配置异常通知
*
* @param joinPoint join point for advice
* @param e exception
*/
@AfterThrowing(pointcut = "logPointcut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
Log log = new Log("ERROR",System.currentTimeMillis() - currentTime);
log.setExceptionDetail(ThrowableUtil.getStackTrace(e).getBytes().toString());
HttpServletRequest request = RequestHolder.getHttpServletRequest();
logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint)joinPoint, log);
}
public String getUsername() {
try {
return SecurityUtils.getUsername();
}catch (Exception e){
return "";
}
}
}
package me.zhengjie.domain;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2018-11-24
*/
@Entity
@Data
@Table(name = "base_jp_log")
@NoArgsConstructor
public class Log implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 操作用户
private String username;
// 描述
private String description;
// 方法名
private String method;
// 参数
private String params;
// 日志类型
@Column(name = "log_type")
private String logType;
// 请求ip
@Column(name = "request_ip")
private String requestIp;
@Column(name = "address")
private String address;
private String browser;
// 请求耗时
private Long time;
// 异常详细
@Column(name = "exception_detail")
private String exceptionDetail;
// 创建日期
@CreationTimestamp
@Column(name = "create_time")
private Timestamp createTime;
public Log(String logType, Long time) {
this.logType = logType;
this.time = time;
}
}
package me.zhengjie.repository;
import me.zhengjie.domain.Log;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
/**
* @author Zheng Jie
* @date 2018-11-24
*/
@Repository
public interface LogRepository extends JpaRepository<Log,Long>, JpaSpecificationExecutor<Log> {
/**
* 获取一个时间段的IP记录
*/
@Query(value = "select count(*) FROM (select request_ip FROM base_jp_log where create_time between ?1 and ?2 GROUP BY request_ip) as s",nativeQuery = true)
Long findIp(String date1, String date2);
@Query(value = "select l FROM base_jp_log l where l.id = ?1",nativeQuery = true)
Log findExceptionById(Long id);
}
package me.zhengjie.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.service.LogService;
import me.zhengjie.service.dto.LogQueryCriteria;
import me.zhengjie.utils.SecurityUtils;
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.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Zheng Jie
* @date 2018-11-24
*/
@RestController
@RequestMapping("/api/logs")
@Api(tags = "监控:日志管理")
public class LogController {
private final LogService logService;
public LogController(LogService logService) {
this.logService = logService;
}
@Log("导出数据")
@ApiOperation("导出数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check()")
public void download(HttpServletResponse response, LogQueryCriteria criteria) throws IOException {
logService.download(logService.queryAll(criteria), response);
}
@GetMapping
@ApiOperation("日志查询")
@PreAuthorize("@el.check()")
public ResponseEntity getLogs(LogQueryCriteria criteria, Pageable pageable){
criteria.setLogType("INFO");
return new ResponseEntity<>(logService.queryAll(criteria,pageable), HttpStatus.OK);
}
@GetMapping(value = "/user")
@ApiOperation("用户日志查询")
public ResponseEntity getUserLogs(LogQueryCriteria criteria, Pageable pageable){
criteria.setLogType("INFO");
criteria.setBlurry(SecurityUtils.getUsername());
return new ResponseEntity<>(logService.queryAllByUser(criteria,pageable), HttpStatus.OK);
}
@GetMapping(value = "/error")
@ApiOperation("错误日志查询")
@PreAuthorize("@el.check()")
public ResponseEntity getErrorLogs(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 getErrorLogs(@PathVariable Long id){
return new ResponseEntity<>(logService.findByErrDetail(id), HttpStatus.OK);
}
}
package me.zhengjie.service;
import me.zhengjie.domain.Log;
import me.zhengjie.service.dto.LogQueryCriteria;
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 Zheng Jie
* @date 2018-11-24
*/
public interface LogService {
Object queryAll(LogQueryCriteria criteria, Pageable pageable);
List<Log> queryAll(LogQueryCriteria criteria);
Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable);
@Async
void save(String username, String browser, String ip, ProceedingJoinPoint joinPoint, Log log);
/**
* 查询异常详情
* @param id 日志ID
* @return Object
*/
Object findByErrDetail(Long id);
void download(List<Log> queryAll, HttpServletResponse response) throws IOException;
}
package me.zhengjie.service.dto;
import lombok.Data;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-5-22
*/
@Data
public class LogErrorDTO implements Serializable {
private Long id;
// 操作用户
private String username;
// 描述
private String description;
// 方法名
private String method;
// 参数
private String params;
private String browser;
// 请求ip
private String requestIp;
private String address;
// 创建日期
private Timestamp createTime;
}
\ No newline at end of file
package me.zhengjie.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
import java.sql.Timestamp;
/**
* 日志查询类
* @author Zheng Jie
* @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 logType;
@Query(type = Query.Type.GREATER_THAN,propName = "createTime")
private Timestamp startTime;
@Query(type = Query.Type.LESS_THAN,propName = "createTime")
private Timestamp endTime;
}
package me.zhengjie.service.dto;
import lombok.Data;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-5-22
*/
@Data
public class LogSmallDTO implements Serializable {
// 描述
private String description;
// 请求ip
private String requestIp;
// 请求耗时
private Long time;
private String address;
private String browser;
// 创建日期
private Timestamp createTime;
}
package me.zhengjie.service.impl;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import me.zhengjie.domain.Log;
import me.zhengjie.repository.LogRepository;
import me.zhengjie.service.LogService;
import me.zhengjie.service.dto.LogQueryCriteria;
import me.zhengjie.service.mapper.LogErrorMapper;
import me.zhengjie.service.mapper.LogSmallMapper;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.StringUtils;
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.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2018-11-24
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class LogServiceImpl implements LogService {
private final LogRepository logRepository;
private final LogErrorMapper logErrorMapper;
private final LogSmallMapper logSmallMapper;
public LogServiceImpl(LogRepository logRepository, LogErrorMapper logErrorMapper, LogSmallMapper logSmallMapper) {
this.logRepository = logRepository;
this.logErrorMapper = logErrorMapper;
this.logSmallMapper = logSmallMapper;
}
@Override
public Object queryAll(LogQueryCriteria criteria, Pageable pageable){
Page<Log> page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)),pageable);
if ("ERROR".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));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void save(String username, String browser, String ip, ProceedingJoinPoint joinPoint, Log log){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
me.zhengjie.aop.log.Log aopLog = method.getAnnotation(me.zhengjie.aop.log.Log.class);
// 方法路径
String methodName = joinPoint.getTarget().getClass().getName()+"."+signature.getName()+"()";
StringBuilder params = new StringBuilder("{");
//参数值
Object[] argValues = joinPoint.getArgs();
//参数名称
String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
if(argValues != null){
for (int i = 0; i < argValues.length; i++) {
params.append(" ").append(argNames[i]).append(": ").append(argValues[i]);
}
}
// 描述
if (log != null) {
log.setDescription(aopLog.value());
}
assert log != null;
log.setRequestIp(ip);
String LOGINPATH = "login";
if(LOGINPATH.equals(signature.getName())){
try {
assert argValues != null;
username = new JSONObject(argValues[0]).get("username").toString();
}catch (Exception e){
e.printStackTrace();
}
}
log.setAddress(StringUtils.getCityInfo(log.getRequestIp()));
log.setMethod(methodName);
log.setUsername(username);
// log.setParams(params.toString() + " }");
log.setBrowser(browser);
logRepository.save(log);
}
@Override
public Object findByErrDetail(Long id) {
byte[] details = logRepository.findExceptionById(id).getExceptionDetail().getBytes();
return Dict.create().set("exception",new String(ObjectUtil.isNotNull(details) ? details : "".getBytes()));
}
@Override
public void download(List<Log> logs, HttpServletResponse response) throws IOException {
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("异常详情", new String(ObjectUtil.isNotNull(log.getExceptionDetail()) ? log.getExceptionDetail() : "".getBytes()));
map.put("创建日期", log.getCreateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
package me.zhengjie.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.domain.Log;
import me.zhengjie.service.dto.LogErrorDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2019-5-22
*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface LogErrorMapper extends BaseMapper<LogErrorDTO, Log> {
}
\ No newline at end of file
package me.zhengjie.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.domain.Log;
import me.zhengjie.service.dto.LogSmallDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2019-5-22
*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface LogSmallMapper extends BaseMapper<LogSmallDTO, Log> {
}
\ No newline at end of file
<?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>eladmin</artifactId>
<groupId>me.zhengjie</groupId>
<version>2.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<artifactId>eladmin-system</artifactId>
<name>核心模块</name>
<properties>
<jjwt.version>0.9.1</jjwt.version>
<junmp.version>1.0.0</junmp.version>
</properties>
<repositories>
<repository>
<id>junmp-public</id>
<name>junmp-public</name>
<url>http://maven.sothing.top/repository/junmp-public/</url>
</repository>
</repositories>
<dependencyManagement>
<dependencies>
<!--整合spring cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--整合spring cloud alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>me.zhengjie</groupId>
<artifactId>eladmin-generator</artifactId>
<version>2.3</version>
<exclusions>
<exclusion>
<groupId>me.zhengjie</groupId>
<artifactId>eladmin-common</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>me.zhengjie</groupId>
<artifactId>eladmin-tools</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>com.junmp.kernel</groupId>
<artifactId>junmp-jwt-starter</artifactId>
<version>${junmp.version}</version>
</dependency>
<dependency>
<groupId>com.zl</groupId>
<artifactId>jwzhjar</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.junmp</groupId>
<artifactId>jsonxml</artifactId>
<version>10</version>
</dependency>
<dependency>
<groupId>com.junmp</groupId>
<artifactId>http-sdk</artifactId>
<version>10</version>
</dependency>
<!-- sqlserver依赖 -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<scope>runtime</scope>
</dependency>
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.1</version>
</dependency>
<!-- jwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<!-- quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
</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>
package me.zhengjie;
import me.zhengjie.utils.SpringContextHolder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* @author Zheng Jie
* @date 2018/11/15 9:20:19
*/
@EnableAsync
@SpringBootApplication
@EnableTransactionManagement
@EnableDiscoveryClient
public class AppRun extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(AppRun.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(AppRun.class);
}
}
package me.zhengjie.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.file.Paths;
/**
* WebMvcConfigurer
*
* @author Zheng Jie
* @date 2018-11-30
*/
@Configuration
@EnableWebMvc
public class ConfigurerAdapter implements WebMvcConfigurer {
@Value("${file.path}")
private String path;
@Value("${file.avatar}")
private String avatar;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(true)
.allowedHeaders("*")
.allowedOrigins("*")
.allowedMethods("GET","POST","PUT","DELETE");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String avatarUtl = Paths.get(avatar).normalize().toUri().toASCIIString();
String pathUtl = Paths.get(path).normalize().toUri().toASCIIString();
registry.addResourceHandler("/avatar/**").addResourceLocations(avatarUtl).setCachePeriod(0);
registry.addResourceHandler("/file/**").addResourceLocations(pathUtl).setCachePeriod(0);
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0);
}
}
package me.zhengjie.config;
import me.zhengjie.modules.system.domain.BaseJpOrganization;
import me.zhengjie.modules.system.domain.Dept;
import me.zhengjie.modules.system.service.BaseJpOrganizationService;
import me.zhengjie.modules.system.service.DeptService;
import me.zhengjie.modules.system.service.RoleService;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.*;
import me.zhengjie.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
/**
* 数据权限配置
* @author Zheng Jie
* @date 2019-4-1
*/
@Component
public class DataScope {
private final String[] scopeType = {"全部","本级","自定义"};
private final UserService userService;
private final RoleService roleService;
private final DeptService deptService;
private final BaseJpOrganizationService organizationService;
public DataScope(UserService userService, RoleService roleService, DeptService deptService,
BaseJpOrganizationService organizationService) {
this.userService = userService;
this.roleService = roleService;
this.deptService = deptService;
this.organizationService = organizationService;
}
public Set<Long> getDeptIds() {
UserDTO user = userService.findByName(SecurityUtils.getUsername());
// 用于存储部门id
Set<Long> deptIds = new HashSet<>();
// 查询用户角色
List<RoleSmallDTO> roleSet = roleService.findByUsers_Id(user.getId());
for (RoleSmallDTO role : roleSet) {
if (scopeType[0].equals(role.getDataScope())) {
return new HashSet<>() ;
}
// 存储本级的数据权限
if (scopeType[1].equals(role.getDataScope())) {
deptIds.add(user.getDept().getId());
}
// 存储自定义的数据权限
if (scopeType[2].equals(role.getDataScope())) {
Set<Dept> depts = deptService.findByRoleIds(role.getId());
for (Dept dept : depts) {
deptIds.add(dept.getId());
List<Dept> deptChildren = deptService.findByPid(dept.getId());
if (deptChildren != null && deptChildren.size() != 0) {
deptIds.addAll(getDeptChildren(deptChildren));
}
}
}
}
return deptIds;
}
public List<Long> getDeptChildren(List<Dept> deptList) {
List<Long> list = new ArrayList<>();
deptList.forEach(dept -> {
if (dept!=null && dept.getEnabled()){
List<Dept> depts = deptService.findByPid(dept.getId());
if(deptList.size() != 0){
list.addAll(getDeptChildren(depts));
}
list.add(dept.getId());
}
}
);
return list;
}
public Set<String> getOrgChildren1(List<BaseJpOrganization> orgList) {
Set<String> ids = new HashSet<>();
for (BaseJpOrganization org : orgList) {
for (BaseJpOrganization it : orgList) {
if (it.getParentId().equals(org.getId())) {
// if (org.getChildren() == null) {
// org.setChildren(new ArrayList<>());
// }
// org.getChildren().add(it);
ids.add(it.getId());
}
}
}
List<String> allIds = orgList.stream().map(node -> node.getId()).collect(Collectors.toList());
return ids;
}
public List<String> getOrgChildren(List<BaseJpOrganization> orgList) {
List<String> list = new ArrayList<>();
orgList.forEach(org -> {
if (org != null) {
// List<BaseJpOrganization> baseJpOrganizations = organizationService.findByPid(org.getId());
List<BaseJpOrganization> baseJpOrganizations = org.getChildren();
if(orgList.size() != 0) {
list.addAll(getOrgChildren(baseJpOrganizations));
}
list.add(org.getId());
}
}
);
return list;
}
}
package me.zhengjie.config.thread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 异步任务线程池装配类
* @author https://juejin.im/entry/5abb8f6951882555677e9da2
* @date 2019年10月31日15:06:18
*/
@Slf4j
@Configuration
public class AsyncTaskExecutePool implements AsyncConfigurer {
//注入配置类
private final AsyncTaskProperties config;
public AsyncTaskExecutePool(AsyncTaskProperties config) {
this.config = config;
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程池大小
executor.setCorePoolSize(config.getCorePoolSize());
//最大线程数
executor.setMaxPoolSize(config.getMaxPoolSize());
//队列容量
executor.setQueueCapacity(config.getQueueCapacity());
//活跃时间
executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
//线程名字前缀
executor.setThreadNamePrefix("el-async-");
// setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
// CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (throwable, method, objects) -> {
log.error("===="+throwable.getMessage()+"====", throwable);
log.error("exception method:"+method.getName());
};
}
}
package me.zhengjie.config.thread;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 线程池配置属性类
* @author https://juejin.im/entry/5abb8f6951882555677e9da2
* @date 2019年10月31日14:58:18
*/
@Data
@Component
@ConfigurationProperties(prefix = "task.pool")
public class AsyncTaskProperties {
private int corePoolSize;
private int maxPoolSize;
private int keepAliveSeconds;
private int queueCapacity;
}
package me.zhengjie.config.thread;
import org.springframework.stereotype.Component;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 自定义线程名称
* @author Zheng Jie
* @date 2019年10月31日17:49:55
*/
@Component
public class TheadFactoryName implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
public TheadFactoryName() {
this("el-pool");
}
private TheadFactoryName(String name){
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
//此时namePrefix就是 name + 第几个用这个工厂创建线程池的
this.namePrefix = name +
poolNumber.getAndIncrement();
}
@Override
public Thread newThread(Runnable r) {
//此时线程的名字 就是 namePrefix + -thread- + 这个线程池中第几个执行的线程
Thread t = new Thread(group, r,
namePrefix + "-thread-"+threadNumber.getAndIncrement(),
0);
if (t.isDaemon()) {
t.setDaemon(false);
}
if (t.getPriority() != Thread.NORM_PRIORITY) {
t.setPriority(Thread.NORM_PRIORITY);
}
return t;
}
}
package me.zhengjie.config.thread;
import me.zhengjie.utils.SpringContextHolder;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 用于获取自定义线程池
* @author Zheng Jie
* @date 2019年10月31日18:16:47
*/
public class ThreadPoolExecutorUtil {
public static ThreadPoolExecutor getPoll(){
AsyncTaskProperties properties = SpringContextHolder.getBean(AsyncTaskProperties.class);
return new ThreadPoolExecutor(
properties.getCorePoolSize(),
properties.getMaxPoolSize(),
properties.getKeepAliveSeconds(),
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(properties.getQueueCapacity()),
new TheadFactoryName()
);
}
}
package me.zhengjie.modules.monitor.config;
import me.zhengjie.modules.monitor.service.VisitsService;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 初始化站点统计
* @author Zheng Jie
*/
@Component
public class VisitsInitialization implements ApplicationRunner {
private final VisitsService visitsService;
public VisitsInitialization(VisitsService visitsService) {
this.visitsService = visitsService;
}
@Override
public void run(ApplicationArguments args){
System.out.println("--------------- 初始化站点统计,如果存在今日统计则跳过 ---------------");
visitsService.save();
System.out.println("--------------- 初始化站点统计完成 ---------------");
}
}
\ No newline at end of file
package me.zhengjie.modules.monitor.domain;
import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* pv 与 ip 统计
*
* @author Zheng Jie
* @date 2018-12-13
*/
@Entity
@Data
@Table(name = "visits")
public class Visits implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String date;
@Column(name = "pv_counts")
private Long pvCounts;
@Column(name = "ip_counts")
private Long ipCounts;
@CreationTimestamp
@Column(name = "create_time")
private Timestamp createTime;
@Column(name = "week_day")
private String weekDay;
}
package me.zhengjie.modules.monitor.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* @author Zheng Jie
* @date 2018-12-10
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RedisVo implements Serializable {
@NotBlank
private String key;
@NotBlank
private String value;
}
package me.zhengjie.modules.monitor.repository;
import me.zhengjie.modules.monitor.domain.Visits;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* @author Zheng Jie
* @date 2018-12-13
*/
@Repository
public interface VisitsRepository extends JpaRepository<Visits,Long> {
/**
* findByDate
* @param date 日期
* @return Visits
*/
Visits findByDate(String date);
/**
* 获得一个时间段的记录
* @param date1 日期1
* @param date2 日期2
* @return List
*/
@Query(value = "select * FROM visits where create_time between ?1 and ?2",nativeQuery = true)
List<Visits> findAllVisits(String date1, String date2);
}
package me.zhengjie.modules.monitor.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.annotation.Limit;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* 接口限流测试类
*/
@RestController
@RequestMapping("/api/limit")
@Api(tags = "系统:限流测试管理")
public class LimitController {
private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger();
/**
* 测试限流注解,下面配置说明该接口 60秒内最多只能访问 10次,保存到redis的键名为 limit_test,
*/
@GetMapping
@PreAuthorize("@el.check('anonymous')")
@ApiOperation("测试")
@Limit(key = "test", period = 60, count = 10, name = "testLimit", prefix = "limit")
public int testLimit() {
return ATOMIC_INTEGER.incrementAndGet();
}
}
package me.zhengjie.modules.monitor.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.modules.monitor.domain.vo.RedisVo;
import me.zhengjie.modules.monitor.service.RedisService;
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 Zheng Jie
* @date 2018-12-10
*/
@RestController
@RequestMapping("/api/redis")
@Api(tags = "系统:Redis缓存管理")
public class RedisController {
private final RedisService redisService;
public RedisController(RedisService redisService) {
this.redisService = redisService;
}
@Log("查询Redis缓存")
@GetMapping
@ApiOperation("查询Redis缓存")
@PreAuthorize("@el.check('redis:list')")
public ResponseEntity getRedis(String key, Pageable pageable){
return new ResponseEntity<>(redisService.findByKey(key,pageable), HttpStatus.OK);
}
@Log("导出数据")
@ApiOperation("导出数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('redis:list')")
public void download(HttpServletResponse response, String key) throws IOException {
redisService.download(redisService.findByKey(key), response);
}
@Log("删除Redis缓存")
@DeleteMapping
@ApiOperation("删除Redis缓存")
@PreAuthorize("@el.check('redis:del')")
public ResponseEntity delete(@RequestBody RedisVo resources){
redisService.delete(resources.getKey());
return new ResponseEntity(HttpStatus.OK);
}
@Log("清空Redis缓存")
@DeleteMapping(value = "/all")
@ApiOperation("清空Redis缓存")
@PreAuthorize("@el.check('redis:del')")
public ResponseEntity deleteAll(){
redisService.deleteAll();
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.modules.monitor.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.modules.monitor.service.VisitsService;
import me.zhengjie.utils.RequestHolder;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Zheng Jie
* @date 2018-12-13
*/
@RestController
@RequestMapping("/api/visits")
@Api(tags = "系统:访问记录管理")
public class VisitsController {
private final VisitsService visitsService;
public VisitsController(VisitsService visitsService) {
this.visitsService = visitsService;
}
@PostMapping
@ApiOperation("创建访问记录")
public ResponseEntity create(){
visitsService.count(RequestHolder.getHttpServletRequest());
return new ResponseEntity(HttpStatus.CREATED);
}
@GetMapping
@ApiOperation("查询")
public ResponseEntity get(){
return new ResponseEntity<>(visitsService.get(),HttpStatus.OK);
}
@GetMapping(value = "/chartData")
@ApiOperation("查询图表数据")
public ResponseEntity getChartData(){
return new ResponseEntity<>(visitsService.getChartData(),HttpStatus.OK);
}
}
package me.zhengjie.modules.monitor.service;
import me.zhengjie.modules.monitor.domain.vo.RedisVo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* 可自行扩展
* @author Zheng Jie
* @date 2018-12-10
*/
public interface RedisService {
/**
* findById
* @param key 键
* @return /
*/
Page findByKey(String key, Pageable pageable);
/**
* findById
* @param key 键
* @return /
*/
List<RedisVo> findByKey(String key);
/**
* 查询验证码的值
* @param key 键
* @return /
*/
String getCodeVal(String key);
/**
* 保存验证码
* @param key 键
* @param val 值
*/
void saveCode(String key, Object val);
/**
* 保存钉钉的登录token
* @param key
* @param val
*/
void saveAccessToken(String key, Object val);
/**
* delete
* @param key 键
*/
void delete(String key);
/**
* 清空缓存
*/
void deleteAll();
/**
*
* @param redisVos /
* @param response /
*/
void download(List<RedisVo> redisVos, HttpServletResponse response) throws IOException;
}
package me.zhengjie.modules.monitor.service;
import org.springframework.scheduling.annotation.Async;
import javax.servlet.http.HttpServletRequest;
/**
* @author Zheng Jie
* @date 2018-12-13
*/
public interface VisitsService {
/**
* 提供给定时任务,每天0点执行
*/
void save();
/**
* 新增记录
* @param request /
*/
@Async
void count(HttpServletRequest request);
/**
* 获取数据
* @return /
*/
Object get();
/**
* getChartData
* @return /
*/
Object getChartData();
}
package me.zhengjie.modules.monitor.service.impl;
import cn.hutool.core.util.ObjectUtil;
import me.zhengjie.modules.monitor.domain.vo.RedisVo;
import me.zhengjie.modules.monitor.service.RedisService;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2018-12-10
*/
@Service
@SuppressWarnings({"unchecked","all"})
public class RedisServiceImpl implements RedisService {
private final RedisTemplate redisTemplate;
@Value("${loginCode.expiration}")
private Long expiration;
@Value("${jwt.online}")
private String onlineKey;
@Value("${jwt.codeKey}")
private String codeKey;
public RedisServiceImpl(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public Page<RedisVo> findByKey(String key, Pageable pageable){
List<RedisVo> redisVos = findByKey(key);
return new PageImpl<RedisVo>(
PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(),redisVos),
pageable,
redisVos.size());
}
@Override
public List<RedisVo> findByKey(String key) {
List<RedisVo> redisVos = new ArrayList<>();
if(!"*".equals(key)){
key = "*" + key + "*";
}
Set<String> keys = redisTemplate.keys(key);
for (String s : keys) {
// 过滤掉权限的缓存
if (s.contains("role::loadPermissionByUser") || s.contains("user::loadUserByUsername") || s.contains(onlineKey) || s.contains(codeKey)) {
continue;
}
RedisVo redisVo = new RedisVo(s, Objects.requireNonNull(redisTemplate.opsForValue().get(s)).toString());
redisVos.add(redisVo);
}
return redisVos;
}
@Override
public void delete(String key) {
redisTemplate.delete(key);
}
@Override
public void deleteAll() {
Set<String> keys = redisTemplate.keys( "*");
redisTemplate.delete(keys.stream().filter(s -> !s.contains(onlineKey)).filter(s -> !s.contains(codeKey)).collect(Collectors.toList()));
}
@Override
public String getCodeVal(String key) {
try {
return Objects.requireNonNull(redisTemplate.opsForValue().get(key)).toString();
}catch (Exception e){
return "";
}
}
@Override
public void saveCode(String key, Object val) {
redisTemplate.opsForValue().set(key,val);
redisTemplate.expire(key, expiration, TimeUnit.MINUTES);
}
@Override
public void saveAccessToken(String key, Object val) {
redisTemplate.opsForValue().set(key,val);
redisTemplate.expire(key,7200000, TimeUnit.MINUTES);
}
@Override
public void download(List<RedisVo> redisVos, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (RedisVo redisVo : redisVos) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("key", redisVo.getKey());
map.put("value", redisVo.getValue());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
package me.zhengjie.modules.monitor.service.impl;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.monitor.domain.Visits;
import me.zhengjie.modules.monitor.repository.VisitsRepository;
import me.zhengjie.modules.monitor.service.VisitsService;
import me.zhengjie.repository.LogRepository;
import me.zhengjie.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2018-12-13
*/
@Slf4j
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class VisitsServiceImpl implements VisitsService {
private final VisitsRepository visitsRepository;
private final LogRepository logRepository;
public VisitsServiceImpl(VisitsRepository visitsRepository, LogRepository logRepository) {
this.visitsRepository = visitsRepository;
this.logRepository = logRepository;
}
@Override
public void save() {
LocalDate localDate = LocalDate.now();
Visits visits = visitsRepository.findByDate(localDate.toString());
if(visits == null){
visits = new Visits();
visits.setWeekDay(StringUtils.getWeekDay());
visits.setPvCounts(1L);
visits.setIpCounts(1L);
visits.setDate(localDate.toString());
visitsRepository.save(visits);
}
}
@Override
public void count(HttpServletRequest request) {
LocalDate localDate = LocalDate.now();
Visits visits = visitsRepository.findByDate(localDate.toString());
visits.setPvCounts(visits.getPvCounts()+1);
long ipCounts = logRepository.findIp(localDate.toString(), localDate.plusDays(1).toString());
visits.setIpCounts(ipCounts);
visitsRepository.save(visits);
}
@Override
public Object get() {
Map<String,Object> map = new HashMap<>();
LocalDate localDate = LocalDate.now();
Visits visits = visitsRepository.findByDate(localDate.toString());
List<Visits> list = visitsRepository.findAllVisits(localDate.minusDays(6).toString(),localDate.plusDays(1).toString());
long recentVisits = 0, recentIp = 0;
for (Visits data : list) {
recentVisits += data.getPvCounts();
recentIp += data.getIpCounts();
}
map.put("newVisits",visits.getPvCounts());
map.put("newIp",visits.getIpCounts());
map.put("recentVisits",recentVisits);
map.put("recentIp",recentIp);
return map;
}
@Override
public Object getChartData() {
Map<String,Object> map = new HashMap<>();
LocalDate localDate = LocalDate.now();
List<Visits> list = visitsRepository.findAllVisits(localDate.minusDays(6).toString(),localDate.plusDays(1).toString());
map.put("weekDays",list.stream().map(Visits::getWeekDay).collect(Collectors.toList()));
map.put("visitsData",list.stream().map(Visits::getPvCounts).collect(Collectors.toList()));
map.put("ipData",list.stream().map(Visits::getIpCounts).collect(Collectors.toList()));
return map;
}
}
package me.zhengjie.modules.oauth.domain;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
@Getter
@Setter
@Entity
@Table(name = "jp_gun")
public class JpGun implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "gun_name")
private String gunName;
@Column(name = "epc")
private String epc;
@Column(name = "status")
private String status;
@Column(name = "create_time")
private Date createTime;
@Column(name = "person_name")
private String personName;
@Column(name = "g_count")
private Integer gCount;
}
package me.zhengjie.modules.oauth.domain;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.io.Serializable;
@Getter
@Setter
@Entity
@Table(name = "jp_module")
public class JpModule implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "name")
private String name;
@Column(name = "pid")
private Long pid;
@Column(name = "pname")
private String pname;
}
package me.zhengjie.modules.oauth.domain;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.io.Serializable;
@Getter
@Setter
@Entity
@Table(name = "jp_module_materiel")
public class JpModuleMateriel implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@OneToOne
@JoinColumn(name = "module_id")
private JpModule jpModule;
@Column(name = "materiel_name")
private String materielName;
@Column(name = "g_count")
private Integer gCount;
@Column(name = "location")
private String location;
}
package me.zhengjie.modules.oauth.repository;
import me.zhengjie.modules.oauth.domain.JpGun;
import me.zhengjie.modules.oauth.service.dto.JpGunPieDTO;
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.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Map;
public interface JpGunRepository extends JpaRepository<JpGun, String>, JpaSpecificationExecutor<JpGun> {
JpGun findByEpc(String epc);
@Modifying
@Transactional
@Query(value = "update jp_gun set status = ?2 , create_time = ?3 where epc = ?1",nativeQuery = true)
void updateStatus(String epc, String status, Date createTime);
@Query(value = "select * from jp_gun s1 where s1.status is not null order by s1.create_time desc",nativeQuery = true)
List<JpGun> findAll();
@Query(value = "SELECT s1.gun_name AS name,count(s1.id) AS value FROM jp_gun s1 WHERE s1.status is not null And datediff(day, s1.create_time,getdate())=0 GROUP BY s1.gun_name",nativeQuery = true)
List<Map<String, Integer>> getPie();
@Query(value ="SELECT count(*) AS lyCount FROM jp_gun s1 WHERE datediff(day, s1.create_time,getdate())=0",nativeQuery = true)
Map<String, Integer> getLyCount();
@Query(value ="SELECT count(*) AS inCount FROM jp_gun s1 WHERE datediff(day, s1.create_time,getdate())=0 AND status = '入库'",nativeQuery = true)
Map<String, Integer> getInCount();
@Query(value ="SELECT count(*) AS unReturnCount FROM jp_gun s1 WHERE status = '出库'",nativeQuery = true)
Map<String, Integer> getUnReturnCount();
@Query(value = "SELECT s1.gun_name AS name, count(s1.id) as value FROM jp_gun s1 WHERE s1.status='出库' GROUP BY s1.gun_name",nativeQuery = true)
List<Map<String, Integer>> getUnReturn();
}
package me.zhengjie.modules.oauth.repository;
import me.zhengjie.modules.oauth.domain.JpModuleMateriel;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface JpModuleMaterielRepository extends JpaRepository<JpModuleMateriel, String>, JpaSpecificationExecutor<JpModuleMateriel> {
}
package me.zhengjie.modules.oauth.rest;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2020-05-27 13:55
* 作者:ningzp@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Slf4j
@RestController
@RequestMapping("/anno")
@Api(value = "用户授权认证", tags = "登录接口")
public class OauthController {
// @Autowired
// private ValidateCodeService validateCodeService;
//
//
// @Autowired
// private TokenUtil tokenUtil;
//
//
//
// /**
// * 验证验证码
// *
// * @param key 验证码唯一uuid key
// * @param code 验证码
// * @return
// * @throws BizException
// */
// @ApiOperation(value = "验证验证码", notes = "验证验证码")
// @GetMapping(value = "/check")
// public ApiRes<Boolean> check(@RequestParam(value = "key") String key, @RequestParam(value = "code") String code) throws BizException {
// return this.validateCodeService.check(key, code);
// }
//
//
// /**
// * 生成验证码
// *
// * @param key 键
// */
// @ApiOperation(value = "验证码", notes = "验证码")
// @GetMapping(value = "/captcha", produces = "image/png")
// public void captcha(@RequestParam(value = "key") String key, HttpServletResponse response) throws IOException {
// this.validateCodeService.create(key, response);
// }
//
// /**
// * 验证token
// *
// * @param token
// * @return
// * @throws Exception
// */
// @ApiOperation(value = "验证token", notes = "验证token")
// @GetMapping(value = "/verify")
// public ApiRes<ApiAuthInfo> verify(@RequestParam(value = "token") String token) throws BizException {
// return ApiRes.success(tokenUtil.getApiAuthInfo(token));
// }
}
package me.zhengjie.modules.oauth.service;
import me.zhengjie.modules.oauth.domain.JpGun;
import me.zhengjie.modules.oauth.service.dto.JpGunPieDTO;
import me.zhengjie.modules.oauth.service.dto.JpGunQueryCriteria;
import org.springframework.data.domain.Pageable;
import java.util.List;
import java.util.Map;
public interface JpGunService {
JpGun findByEpc(String epc);
void updateStatus(String epc, String status);
Object queryAll();
List<Map<String, Integer>> getPie();
List<Map<String, Integer>> getUnReturn();
Map<String, Integer> getLyCount();
Map<String, Integer> getInCount();
Map<String, Integer> getUnReturnCount();
}
package me.zhengjie.modules.oauth.service;
import me.zhengjie.modules.oauth.service.dto.JpModuleMaterielCriteria;
import org.springframework.data.domain.Pageable;
public interface JpModuleMaterielService {
Object queryAll(JpModuleMaterielCriteria jpModuleMaterielCriteria, Pageable pageable);
}
package me.zhengjie.modules.oauth.service.dto;
import lombok.Data;
import java.io.Serializable;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2020/8/25 6:38 下午
* 作者:ningzp@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Data
public class CalSignDto implements Serializable {
/**
* 应用秘钥
*/
private String appKey;
/**
* 内容
*/
private String content;
}
package me.zhengjie.modules.oauth.service.dto;
import lombok.Data;
import java.util.Date;
@Data
public class GunDto {
private Long id;
private String gunName;
private String epc;
private String status;
private Date createTime;
private String personName;
}
package me.zhengjie.modules.oauth.service.dto;
import lombok.Data;
import net.bytebuddy.description.field.FieldDescription;
@Data
public class GunStatisticsDTO {
private Integer lyCount;
private Integer returnCount;
private Integer unReturnCount;
}
package me.zhengjie.modules.oauth.service.dto;
import lombok.Data;
import java.util.List;
@Data
public class JpGunDTO {
private List<String> list;
private String state;
}
package me.zhengjie.modules.oauth.service.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class JpGunPieDTO implements Serializable {
private String gunName;
private Integer gCount;
}
package me.zhengjie.modules.oauth.service.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import me.zhengjie.annotation.Query;
@Data
@NoArgsConstructor
public class JpGunQueryCriteria {
private String name;
private String status;
}
package me.zhengjie.modules.oauth.service.dto;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
public class JpModuleDTO implements Serializable {
private Long id;
private String name;
private Long pid;
private String pname;
}
package me.zhengjie.modules.oauth.service.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class JpModuleMaterielCriteria {
private String moduleName;
}
package me.zhengjie.modules.oauth.service.dto;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import me.zhengjie.modules.oauth.domain.JpModule;
import java.io.Serializable;
@Getter
@Setter
public class JpModuleMaterielDTO implements Serializable {
private Long id;
private JpModule jpModule;
private String materielName;
private Integer gCount;
private String location;
}
package me.zhengjie.modules.oauth.service.dto;
import lombok.Data;
@Data
public class OrgDetailDto {
private String name;
private String parentId;
private String code;
}
package me.zhengjie.modules.oauth.service.dto;
import lombok.Data;
import java.io.Serializable;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2020/8/25 11:27 上午
* 作者:ningzp@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Data
public class OrgDto implements Serializable {
private String orgNo;
}
package me.zhengjie.modules.oauth.service.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.io.Serializable;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2020/8/25 6:24 下午
* 作者:ningzp@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Data
public class TokenInfoDto implements Serializable {
@JsonProperty("access_token")
private String token;
@JsonProperty("expiration_time")
private String expiration;
}
package me.zhengjie.modules.oauth.service.impl;
import me.zhengjie.modules.oauth.domain.JpGun;
import me.zhengjie.modules.oauth.repository.JpGunRepository;
import me.zhengjie.modules.oauth.service.JpGunService;
import me.zhengjie.modules.oauth.service.dto.JpGunPieDTO;
import me.zhengjie.modules.oauth.service.mapper.JpGunMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class JpGunServiceImpl implements JpGunService {
private JpGunRepository jpGunRepository;
private JpGunMapper jpGunMapper;
public JpGunServiceImpl(JpGunRepository jpGunRepository, JpGunMapper jpGunMapper) {
this.jpGunRepository = jpGunRepository;
this.jpGunMapper = jpGunMapper;
}
@Override
public JpGun findByEpc(String epc) {
return jpGunRepository.findByEpc(epc);
}
@Override
public void updateStatus(String epc, String status) {
jpGunRepository.updateStatus(epc, status, new Date());
}
@Override
public Object queryAll() {
return jpGunRepository.findAll();
}
@Override
public List<Map<String, Integer>> getPie() {
return jpGunRepository.getPie();
}
@Override
public List<Map<String, Integer>> getUnReturn() {
return jpGunRepository.getUnReturn();
}
@Override
public Map<String, Integer> getLyCount() {
return jpGunRepository.getLyCount();
}
@Override
public Map<String, Integer> getInCount() {
return jpGunRepository.getInCount();
}
@Override
public Map<String, Integer> getUnReturnCount() {
return jpGunRepository.getUnReturnCount();
}
}
package me.zhengjie.modules.oauth.service.impl;
import me.zhengjie.modules.oauth.domain.JpGun;
import me.zhengjie.modules.oauth.domain.JpModuleMateriel;
import me.zhengjie.modules.oauth.repository.JpModuleMaterielRepository;
import me.zhengjie.modules.oauth.service.JpModuleMaterielService;
import me.zhengjie.modules.oauth.service.dto.JpModuleMaterielCriteria;
import me.zhengjie.modules.oauth.service.mapper.JpModuleMaterielMapper;
import me.zhengjie.modules.system.service.dto.UserDTO;
import me.zhengjie.modules.util.BeanPlusUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class JpModuleMaterielServiceImpl implements JpModuleMaterielService {
private JpModuleMaterielRepository jpModuleMaterielRepository;
private JpModuleMaterielMapper jpModuleMaterielMapper;
public JpModuleMaterielServiceImpl(JpModuleMaterielRepository jpModuleMaterielRepository, JpModuleMaterielMapper jpModuleMaterielMapper) {
this.jpModuleMaterielRepository = jpModuleMaterielRepository;
this.jpModuleMaterielMapper = jpModuleMaterielMapper;
}
@Override
public Object queryAll(JpModuleMaterielCriteria criteria, Pageable pageable) {
Page<JpModuleMateriel> page = jpModuleMaterielRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
return PageUtil.toPage(page.map(item -> jpModuleMaterielMapper.toDto(item)));
}
}
package me.zhengjie.modules.oauth.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.oauth.domain.JpGun;
import me.zhengjie.modules.oauth.service.dto.GunDto;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface JpGunMapper extends BaseMapper<GunDto, JpGun> {
}
package me.zhengjie.modules.oauth.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.oauth.domain.JpModule;
import me.zhengjie.modules.oauth.service.dto.JpModuleDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface JpModuleMapper extends BaseMapper<JpModuleDTO, JpModule> {
}
package me.zhengjie.modules.oauth.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.oauth.domain.JpModuleMateriel;
import me.zhengjie.modules.oauth.service.dto.JpModuleMaterielDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
@Mapper(componentModel = "spring",uses = {JpModuleMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface JpModuleMaterielMapper extends BaseMapper<JpModuleMaterielDTO, JpModuleMateriel> {
}
package me.zhengjie.modules.oauth.util;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.crypto.symmetric.DESede;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* <pre>
*
* 描述:与上海金币对接的加解密工具类
* 版本:1.0.0
* 日期:2020/7/14 4:13 下午
* 作者:ningzp@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Slf4j
public class AuthUtil {
/**
* 初始的IV
*/
private final static byte[] IV = new byte[]{0x08, 0x07, 0x09, 0x01, 0x09, 0x06, 0x01, 0x08};
/**
* 默认长度
*/
private final static int DEFAULT_MD5_KEY_LEN = 32;
/**
* 解密数据
*
* @param mwText 密文内容
* @param key 秘钥
*/
public static byte[] decode(String mwText, String key) {
try {
DESede deSede = new DESede(Mode.CBC, Padding.ZeroPadding, CardUtil.hex2byte(key), IV);
return deSede.decrypt(mwText);
} catch (Exception ex) {
throw new RuntimeException(String.format("解密失败>>%s", ex.getMessage()));
}
}
/**
* 加密
*
* @param plainText 明文内容
* @param key 秘钥
*/
public static String encode(String plainText, String key) {
try {
DESede deSede = new DESede(Mode.CBC, Padding.ZeroPadding, CardUtil.hex2byte(key), IV);
//加密
byte[] bytes = deSede.encrypt(plainText);
return CardUtil.byte2hex(bytes).toUpperCase();
} catch (Exception ex) {
throw new RuntimeException(String.format("加密失败>>", ex.getMessage()));
}
}
/**
* 计算给定内容的MD5值并返序
*
* @param text
*/
public static String getMd5Key(String text) {
String key = stringToMD5(text);
if (StringUtils.isNotEmpty(key) && key.length() == DEFAULT_MD5_KEY_LEN) {
StringBuilder sb = new StringBuilder();
sb.append(key).append(key.substring(0, 16));
return sb.reverse().toString();
} else {
throw new RuntimeException("秘钥生成失败");
}
}
/**
* 计算MD5值
*
* @param plainText
*/
private static String stringToMD5(String plainText) {
try {
byte[] secretBytes = null;
secretBytes = MessageDigest.getInstance("md5").digest(plainText.getBytes());
return CardUtil.byte2hex(secretBytes).toUpperCase();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("算法不支持");
}
}
/**
* 检查签名
*
* @param timestamp 时间戳
* @param appKey 应用秘钥
* @param appSecret 加密秘钥
* @param sign 签名值
* @param version 版本号
*/
public static boolean checkSign(String timestamp, String appKey, String appSecret, String version, String sign) {
StringBuilder builder = new StringBuilder();
builder.append(timestamp).append(appKey).append(version);
String newSign = DigestUtil.hmac(HmacAlgorithm.HmacSHA256, appSecret.getBytes()).digestHex(builder.toString());
if (StringUtils.equalsIgnoreCase(sign, newSign)) {
return true;
} else {
return false;
}
}
/**
* 计算签名值
* 通过appKey从DB中查询对应的秘钥appSecret
*
* @param appSecret 加密秘钥
* @param content 计算内容
*/
public static String calSign(String appSecret, String content) {
return DigestUtil.hmac(HmacAlgorithm.HmacSHA256, appSecret.getBytes()).digestHex(content);
}
}
package me.zhengjie.modules.oauth.util;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
/**
* <pre>
*
* 描述:Hex之间转化接口
* 版本:1.0.0
* 日期:2020/8/25 10:55 上午
* 作者:ningzp@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
public class CardUtil {
public static String toHexString(byte[] in) {
StringBuilder out = new StringBuilder(2 * in.length);
for (int i = 0; i < in.length; i++) {
out.append(String.format("%02x", (in[i] & 0xFF)));
}
return out.toString().toUpperCase();
}
/**
* hex 转成 byte[]
* <p>
* 例如:hex2byte("21d153ef") = 0x21, 0xd1, 0x53, 0xef
*
* @param str
* @return
*/
public static final byte[] hex2byte(String str) {
byte[] ret = null;
if (StringUtils.isBlank(str)) {
return ret;
}
str = StringUtils.deleteWhitespace(str);
if (str.toCharArray().length % 2 != 0) {
str = "0" + str; // 如果是奇数位
}
char[] arr = str.toCharArray();
ret = new byte[str.length() / 2];
int length = str.length();
for (int i = 0, j = 0, l = length; i < l; i++, j++) {
StringBuffer swap = new StringBuffer().append(arr[i++]).append(arr[i]);
int byteInt = Integer.parseInt(swap.toString(), 16) & 0xFF;
ret[j] = new Integer(byteInt).byteValue();
}
return ret;
}
/**
* byte数组转换为ASCII形式字符串 例如:byte2hex(0x21, 0xd1, 0x53, 0xef) = "21d153ef"
*
* @param bytes
* @return
*/
public static final String byte2hex(byte[] bytes) {
if (ArrayUtils.isEmpty(bytes)) {
return StringUtils.EMPTY;
}
StringBuffer ret = new StringBuffer();
int bytesLength = bytes.length;
for (int i = 0; i < bytesLength; i++) {
byte b = bytes[i];
String hexString = (Integer.toHexString(b & 0XFF));
if (hexString.length() == 1) {
ret.append("0");
}
ret.append(hexString);
}
return ret.toString().toUpperCase();
}
}
package me.zhengjie.modules.quartz.config;
import me.zhengjie.modules.quartz.domain.QuartzJob;
import me.zhengjie.modules.quartz.repository.QuartzJobRepository;
import me.zhengjie.modules.quartz.utils.QuartzManage;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author Zheng Jie
* @date 2019-01-07
*/
@Component
public class JobRunner implements ApplicationRunner {
private final QuartzJobRepository quartzJobRepository;
private final QuartzManage quartzManage;
public JobRunner(QuartzJobRepository quartzJobRepository, QuartzManage quartzManage) {
this.quartzJobRepository = quartzJobRepository;
this.quartzManage = quartzManage;
}
/**
* 项目启动时重新激活启用的定时任务
* @param applicationArguments /
*/
@Override
public void run(ApplicationArguments applicationArguments){
System.out.println("--------------------注入定时任务---------------------");
List<QuartzJob> quartzJobs = quartzJobRepository.findByIsPauseIsFalse();
quartzJobs.forEach(quartzManage::addJob);
System.out.println("--------------------定时任务注入完成---------------------");
}
}
package me.zhengjie.modules.quartz.config;
import org.quartz.Scheduler;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;
/**
* 定时任务配置
* @author /
* @date 2019-01-07
*/
@Configuration
public class QuartzConfig {
/**
* 解决Job中注入Spring Bean为null的问题
*/
@Component("quartzJobFactory")
public static class QuartzJobFactory extends AdaptableJobFactory {
private final AutowireCapableBeanFactory capableBeanFactory;
public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) {
this.capableBeanFactory = capableBeanFactory;
}
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
/**
* 注入scheduler到spring
* @param quartzJobFactory /
* @return Scheduler
* @throws Exception /
*/
@Bean(name = "scheduler")
public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception {
SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();
factoryBean.setJobFactory(quartzJobFactory);
factoryBean.afterPropertiesSet();
Scheduler scheduler=factoryBean.getScheduler();
scheduler.start();
return scheduler;
}
}
package me.zhengjie.modules.quartz.domain;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-01-07
*/
@Getter
@Setter
@Entity
@Table(name = "quartz_job")
public class QuartzJob implements Serializable {
public static final String JOB_KEY = "JOB_KEY";
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = {Update.class})
private Long id;
// 定时器名称
@Column(name = "job_name")
private String jobName;
// Bean名称
@Column(name = "bean_name")
@NotBlank
private String beanName;
// 方法名称
@Column(name = "method_name")
@NotBlank
private String methodName;
// 参数
@Column(name = "params")
private String params;
// cron表达式
@Column(name = "cron_expression")
@NotBlank
private String cronExpression;
// 状态
@Column(name = "is_pause")
private Boolean isPause = false;
// 备注
@Column(name = "remark")
@NotBlank
private String remark;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
public @interface Update {}
}
\ No newline at end of file
package me.zhengjie.modules.quartz.domain;
import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-01-07
*/
@Entity
@Data
@Table(name = "quartz_log")
public class QuartzLog implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;
// 任务名称
@Column(name = "job_name")
private String jobName;
// Bean名称
@Column(name = "baen_name")
private String beanName;
// 方法名称
@Column(name = "method_name")
private String methodName;
// 参数
@Column(name = "params")
private String params;
// cron表达式
@Column(name = "cron_expression")
private String cronExpression;
// 状态
@Column(name = "is_success")
private Boolean isSuccess;
// 异常详细
@Column(name = "exception_detail",columnDefinition = "text")
private String exceptionDetail;
// 耗时(毫秒)
private Long time;
// 创建日期
@CreationTimestamp
@Column(name = "create_time")
private Timestamp createTime;
}
package me.zhengjie.modules.quartz.repository;
import me.zhengjie.modules.quartz.domain.QuartzJob;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
/**
* @author Zheng Jie
* @date 2019-01-07
*/
public interface QuartzJobRepository extends JpaRepository<QuartzJob,Long>, JpaSpecificationExecutor<QuartzJob> {
/**
* 查询启用的任务
* @return List
*/
List<QuartzJob> findByIsPauseIsFalse();
}
package me.zhengjie.modules.quartz.repository;
import me.zhengjie.modules.quartz.domain.QuartzLog;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author Zheng Jie
* @date 2019-01-07
*/
public interface QuartzLogRepository extends JpaRepository<QuartzLog,Long>, JpaSpecificationExecutor<QuartzLog> {
}
package me.zhengjie.modules.quartz.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.aop.log.Log;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.quartz.domain.QuartzJob;
import me.zhengjie.modules.quartz.service.QuartzJobService;
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Zheng Jie
* @date 2019-01-07
*/
@Slf4j
@RestController
@Api(tags = "系统:定时任务管理")
@RequestMapping("/api/jobs")
public class QuartzJobController {
private static final String ENTITY_NAME = "quartzJob";
private final QuartzJobService quartzJobService;
public QuartzJobController(QuartzJobService quartzJobService) {
this.quartzJobService = quartzJobService;
}
@Log("查询定时任务")
@ApiOperation("查询定时任务")
@GetMapping
@PreAuthorize("@el.check('timing:list')")
public ResponseEntity getJobs(JobQueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(quartzJobService.queryAll(criteria,pageable), HttpStatus.OK);
}
@Log("导出任务数据")
@ApiOperation("导出任务数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('timing:list')")
public void download(HttpServletResponse response, JobQueryCriteria criteria) throws IOException {
quartzJobService.download(quartzJobService.queryAll(criteria), response);
}
@Log("导出日志数据")
@ApiOperation("导出日志数据")
@GetMapping(value = "/download/log")
@PreAuthorize("@el.check('timing:list')")
public void downloadLog(HttpServletResponse response, JobQueryCriteria criteria) throws IOException {
quartzJobService.downloadLog(quartzJobService.queryAllLog(criteria), response);
}
@ApiOperation("查询任务执行日志")
@GetMapping(value = "/logs")
@PreAuthorize("@el.check('timing:list')")
public ResponseEntity getJobLogs(JobQueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(quartzJobService.queryAllLog(criteria,pageable), HttpStatus.OK);
}
@Log("新增定时任务")
@ApiOperation("新增定时任务")
@PostMapping
@PreAuthorize("@el.check('timing:add')")
public ResponseEntity create(@Validated @RequestBody QuartzJob resources){
if (resources.getId() != null) {
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
}
return new ResponseEntity<>(quartzJobService.create(resources),HttpStatus.CREATED);
}
@Log("修改定时任务")
@ApiOperation("修改定时任务")
@PutMapping
@PreAuthorize("@el.check('timing:edit')")
public ResponseEntity update(@Validated(QuartzJob.Update.class) @RequestBody QuartzJob resources){
quartzJobService.update(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("更改定时任务状态")
@ApiOperation("更改定时任务状态")
@PutMapping(value = "/{id}")
@PreAuthorize("@el.check('timing:edit')")
public ResponseEntity updateIsPause(@PathVariable Long id){
quartzJobService.updateIsPause(quartzJobService.findById(id));
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("执行定时任务")
@ApiOperation("执行定时任务")
@PutMapping(value = "/exec/{id}")
@PreAuthorize("@el.check('timing:edit')")
public ResponseEntity execution(@PathVariable Long id){
quartzJobService.execution(quartzJobService.findById(id));
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("删除定时任务")
@ApiOperation("删除定时任务")
@DeleteMapping(value = "/{id}")
@PreAuthorize("@el.check('timing:del')")
public ResponseEntity delete(@PathVariable Long id){
quartzJobService.delete(quartzJobService.findById(id));
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.modules.quartz.service;
import me.zhengjie.modules.quartz.domain.QuartzJob;
import me.zhengjie.modules.quartz.domain.QuartzLog;
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria;
import org.springframework.data.domain.Pageable;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @author Zheng Jie
* @date 2019-01-07
*/
public interface QuartzJobService {
Object queryAll(JobQueryCriteria criteria, Pageable pageable);
List<QuartzJob> queryAll(JobQueryCriteria criteria);
Object queryAllLog(JobQueryCriteria criteria, Pageable pageable);
List<QuartzLog> queryAllLog(JobQueryCriteria criteria);
QuartzJob create(QuartzJob resources);
void update(QuartzJob resources);
void delete(QuartzJob quartzJob);
QuartzJob findById(Long id);
/**
* 更改定时任务状态
* @param quartzJob /
*/
void updateIsPause(QuartzJob quartzJob);
/**
* 立即执行定时任务
* @param quartzJob /
*/
void execution(QuartzJob quartzJob);
void download(List<QuartzJob> queryAll, HttpServletResponse response) throws IOException;
void downloadLog(List<QuartzLog> queryAllLog, HttpServletResponse response) throws IOException;
}
package me.zhengjie.modules.quartz.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-6-4 10:33:02
*/
@Data
public class JobQueryCriteria {
@Query(type = Query.Type.INNER_LIKE)
private String jobName;
@Query
private Boolean isSuccess;
@Query(type = Query.Type.GREATER_THAN,propName = "createTime")
private Timestamp startTime;
@Query(type = Query.Type.LESS_THAN,propName = "createTime")
private Timestamp endTime;
}
package me.zhengjie.modules.quartz.service.impl;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.quartz.domain.QuartzJob;
import me.zhengjie.modules.quartz.domain.QuartzLog;
import me.zhengjie.modules.quartz.repository.QuartzJobRepository;
import me.zhengjie.modules.quartz.repository.QuartzLogRepository;
import me.zhengjie.modules.quartz.service.QuartzJobService;
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria;
import me.zhengjie.modules.quartz.utils.QuartzManage;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import org.quartz.CronExpression;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2019-01-07
*/
@Service(value = "quartzJobService")
@CacheConfig(cacheNames = "quartzJob")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class QuartzJobServiceImpl implements QuartzJobService {
private final QuartzJobRepository quartzJobRepository;
private final QuartzLogRepository quartzLogRepository;
private final QuartzManage quartzManage;
public QuartzJobServiceImpl(QuartzJobRepository quartzJobRepository, QuartzLogRepository quartzLogRepository, QuartzManage quartzManage) {
this.quartzJobRepository = quartzJobRepository;
this.quartzLogRepository = quartzLogRepository;
this.quartzManage = quartzManage;
}
@Override
@Cacheable
public Object queryAll(JobQueryCriteria criteria, Pageable pageable){
return PageUtil.toPage(quartzJobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable));
}
@Override
public Object queryAllLog(JobQueryCriteria criteria, Pageable pageable){
return PageUtil.toPage(quartzLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable));
}
@Override
public List<QuartzJob> queryAll(JobQueryCriteria criteria) {
return quartzJobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
}
@Override
public List<QuartzLog> queryAllLog(JobQueryCriteria criteria) {
return quartzLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
}
@Override
@Cacheable(key = "#p0")
public QuartzJob findById(Long id) {
QuartzJob quartzJob = quartzJobRepository.findById(id).orElseGet(QuartzJob::new);
ValidationUtil.isNull(quartzJob.getId(),"QuartzJob","id",id);
return quartzJob;
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public QuartzJob create(QuartzJob resources) {
if (!CronExpression.isValidExpression(resources.getCronExpression())){
throw new BadRequestException("cron表达式格式错误");
}
resources = quartzJobRepository.save(resources);
quartzManage.addJob(resources);
return resources;
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(QuartzJob resources) {
if(resources.getId().equals(1L)){
throw new BadRequestException("该任务不可操作");
}
if (!CronExpression.isValidExpression(resources.getCronExpression())){
throw new BadRequestException("cron表达式格式错误");
}
resources = quartzJobRepository.save(resources);
quartzManage.updateJobCron(resources);
}
@Override
@CacheEvict(allEntries = true)
public void updateIsPause(QuartzJob quartzJob) {
if(quartzJob.getId().equals(1L)){
throw new BadRequestException("该任务不可操作");
}
if (quartzJob.getIsPause()) {
quartzManage.resumeJob(quartzJob);
quartzJob.setIsPause(false);
} else {
quartzManage.pauseJob(quartzJob);
quartzJob.setIsPause(true);
}
quartzJobRepository.save(quartzJob);
}
@Override
public void execution(QuartzJob quartzJob) {
if(quartzJob.getId().equals(1L)){
throw new BadRequestException("该任务不可操作");
}
quartzManage.runAJobNow(quartzJob);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(QuartzJob quartzJob) {
if(quartzJob.getId().equals(1L)){
throw new BadRequestException("该任务不可操作");
}
quartzManage.deleteJob(quartzJob);
quartzJobRepository.delete(quartzJob);
}
@Override
public void download(List<QuartzJob> quartzJobs, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (QuartzJob quartzJob : quartzJobs) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("任务名称", quartzJob.getJobName());
map.put("Bean名称", quartzJob.getBeanName());
map.put("执行方法", quartzJob.getMethodName());
map.put("参数", quartzJob.getParams());
map.put("表达式", quartzJob.getCronExpression());
map.put("状态", quartzJob.getIsPause() ? "暂停中" : "运行中");
map.put("描述", quartzJob.getRemark());
map.put("创建日期", quartzJob.getCreateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
@Override
public void downloadLog(List<QuartzLog> queryAllLog, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (QuartzLog quartzLog : queryAllLog) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("任务名称", quartzLog.getJobName());
map.put("Bean名称", quartzLog.getBeanName());
map.put("执行方法", quartzLog.getMethodName());
map.put("参数", quartzLog.getParams());
map.put("表达式", quartzLog.getCronExpression());
map.put("异常详情", quartzLog.getExceptionDetail());
map.put("耗时/毫秒", quartzLog.getTime());
map.put("状态", quartzLog.getIsSuccess() ? "成功" : "失败");
map.put("创建日期", quartzLog.getCreateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
package me.zhengjie.modules.quartz.task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 测试用
* @author Zheng Jie
* @date 2019-01-08
*/
@Slf4j
@Component
public class TestTask {
public void run(){
log.info("执行成功");
}
public void run1(String str){
log.info("执行成功,参数为: {}" + str);
}
}
package me.zhengjie.modules.quartz.task;
import me.zhengjie.modules.monitor.service.VisitsService;
import org.springframework.stereotype.Component;
/**
* @author Zheng Jie
* @date 2018-12-25
*/
@Component
public class VisitsTask {
private final VisitsService visitsService;
public VisitsTask(VisitsService visitsService) {
this.visitsService = visitsService;
}
public void run(){
visitsService.save();
}
}
package me.zhengjie.modules.quartz.utils;
import me.zhengjie.config.thread.TheadFactoryName;
import me.zhengjie.config.thread.ThreadPoolExecutorUtil;
import me.zhengjie.modules.quartz.domain.QuartzJob;
import me.zhengjie.modules.quartz.domain.QuartzLog;
import me.zhengjie.modules.quartz.repository.QuartzLogRepository;
import me.zhengjie.modules.quartz.service.QuartzJobService;
import me.zhengjie.utils.SpringContextHolder;
import me.zhengjie.utils.ThrowableUtil;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.concurrent.*;
/**
* 参考人人开源,https://gitee.com/renrenio/renren-security
* @author /
* @date 2019-01-07
*/
@Async
public class ExecutionJob extends QuartzJobBean {
private Logger logger = LoggerFactory.getLogger(this.getClass());
// 该处仅供参考
private final static ThreadPoolExecutor executor = ThreadPoolExecutorUtil.getPoll();
@Override
@SuppressWarnings("unchecked")
protected void executeInternal(JobExecutionContext context) {
QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY);
// 获取spring bean
QuartzLogRepository quartzLogRepository = SpringContextHolder.getBean(QuartzLogRepository.class);
QuartzJobService quartzJobService = SpringContextHolder.getBean(QuartzJobService.class);
QuartzLog log = new QuartzLog();
log.setJobName(quartzJob.getJobName());
log.setBeanName(quartzJob.getBeanName());
log.setMethodName(quartzJob.getMethodName());
log.setParams(quartzJob.getParams());
long startTime = System.currentTimeMillis();
log.setCronExpression(quartzJob.getCronExpression());
try {
// 执行任务
logger.info("任务准备执行,任务名称:{}", quartzJob.getJobName());
QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),
quartzJob.getParams());
Future<?> future = executor.submit(task);
future.get();
long times = System.currentTimeMillis() - startTime;
log.setTime(times);
// 任务状态
log.setIsSuccess(true);
logger.info("任务执行完毕,任务名称:{} 总共耗时:{} 毫秒", quartzJob.getJobName(), times);
} catch (Exception e) {
logger.error("任务执行失败,任务名称:{}" + quartzJob.getJobName(), e);
long times = System.currentTimeMillis() - startTime;
log.setTime(times);
// 任务状态 0:成功 1:失败
log.setIsSuccess(false);
log.setExceptionDetail(ThrowableUtil.getStackTrace(e));
quartzJob.setIsPause(false);
//更新状态
quartzJobService.updateIsPause(quartzJob);
} finally {
quartzLogRepository.save(log);
}
}
}
package me.zhengjie.modules.quartz.utils;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.quartz.domain.QuartzJob;
import org.quartz.*;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import static org.quartz.TriggerBuilder.newTrigger;
/**
* @author Zheng Jie
* @date 2019-01-07
*/
@Slf4j
@Component
public class QuartzManage {
private static final String JOB_NAME = "TASK_";
@Resource(name = "scheduler")
private Scheduler scheduler;
public void addJob(QuartzJob quartzJob){
try {
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(ExecutionJob.class).
withIdentity(JOB_NAME + quartzJob.getId()).build();
//通过触发器名和cron 表达式创建 Trigger
Trigger cronTrigger = newTrigger()
.withIdentity(JOB_NAME + quartzJob.getId())
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression()))
.build();
cronTrigger.getJobDataMap().put(QuartzJob.JOB_KEY, quartzJob);
//重置启动时间
((CronTriggerImpl)cronTrigger).setStartTime(new Date());
//执行定时任务
scheduler.scheduleJob(jobDetail,cronTrigger);
// 暂停任务
if (quartzJob.getIsPause()) {
pauseJob(quartzJob);
}
} catch (Exception e){
log.error("创建定时任务失败", e);
throw new BadRequestException("创建定时任务失败");
}
}
/**
* 更新job cron表达式
* @param quartzJob /
*/
public void updateJobCron(QuartzJob quartzJob){
try {
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 如果不存在则创建一个定时任务
if(trigger == null){
addJob(quartzJob);
trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
}
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression());
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
//重置启动时间
((CronTriggerImpl)trigger).setStartTime(new Date());
trigger.getJobDataMap().put(QuartzJob.JOB_KEY,quartzJob);
scheduler.rescheduleJob(triggerKey, trigger);
// 暂停任务
if (quartzJob.getIsPause()) {
pauseJob(quartzJob);
}
} catch (Exception e){
log.error("更新定时任务失败", e);
throw new BadRequestException("更新定时任务失败");
}
}
/**
* 删除一个job
* @param quartzJob /
*/
public void deleteJob(QuartzJob quartzJob){
try {
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.pauseJob(jobKey);
scheduler.deleteJob(jobKey);
} catch (Exception e){
log.error("删除定时任务失败", e);
throw new BadRequestException("删除定时任务失败");
}
}
/**
* 恢复一个job
* @param quartzJob /
*/
public void resumeJob(QuartzJob quartzJob){
try {
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 如果不存在则创建一个定时任务
if(trigger == null)
addJob(quartzJob);
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.resumeJob(jobKey);
} catch (Exception e){
log.error("恢复定时任务失败", e);
throw new BadRequestException("恢复定时任务失败");
}
}
/**
* 立即执行job
* @param quartzJob /
*/
public void runAJobNow(QuartzJob quartzJob){
try {
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 如果不存在则创建一个定时任务
if(trigger == null)
addJob(quartzJob);
JobDataMap dataMap = new JobDataMap();
dataMap.put(QuartzJob.JOB_KEY, quartzJob);
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.triggerJob(jobKey,dataMap);
} catch (Exception e){
log.error("定时任务执行失败", e);
throw new BadRequestException("定时任务执行失败");
}
}
/**
* 暂停一个job
* @param quartzJob /
*/
public void pauseJob(QuartzJob quartzJob){
try {
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.pauseJob(jobKey);
} catch (Exception e){
log.error("定时任务暂停失败", e);
throw new BadRequestException("定时任务暂停失败");
}
}
}
package me.zhengjie.modules.quartz.utils;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.utils.SpringContextHolder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
/**
* 执行定时任务
* @author /
*/
@Slf4j
public class QuartzRunnable implements Callable {
private Object target;
private Method method;
private String params;
QuartzRunnable(String beanName, String methodName, String params)
throws NoSuchMethodException, SecurityException {
this.target = SpringContextHolder.getBean(beanName);
this.params = params;
if (StringUtils.isNotBlank(params)) {
this.method = target.getClass().getDeclaredMethod(methodName, String.class);
} else {
this.method = target.getClass().getDeclaredMethod(methodName);
}
}
@Override
public Object call() throws Exception {
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotBlank(params)) {
method.invoke(target, params);
} else {
method.invoke(target);
}
return null;
}
}
package me.zhengjie.modules.security.config;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.config.ElPermissionConfig;
import me.zhengjie.modules.security.security.JwtAuthenticationEntryPoint;
import me.zhengjie.modules.security.security.JwtAuthorizationTokenFilter;
import me.zhengjie.modules.security.service.JwtUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final JwtAuthenticationEntryPoint unauthorizedHandler;
private final JwtUserDetailsService jwtUserDetailsService;
private final ApplicationContext applicationContext;
// 自定义基于JWT的安全过滤器
private final JwtAuthorizationTokenFilter authenticationTokenFilter;
@Value("${jwt.header}")
private String tokenHeader;
public SecurityConfig(JwtAuthenticationEntryPoint unauthorizedHandler, JwtUserDetailsService jwtUserDetailsService, JwtAuthorizationTokenFilter authenticationTokenFilter, ApplicationContext applicationContext) {
this.unauthorizedHandler = unauthorizedHandler;
this.jwtUserDetailsService = jwtUserDetailsService;
this.authenticationTokenFilter = authenticationTokenFilter;
this.applicationContext = applicationContext;
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(jwtUserDetailsService)
.passwordEncoder(passwordEncoderBean());
}
@Bean
GrantedAuthorityDefaults grantedAuthorityDefaults() {
// Remove the ROLE_ prefix
return new GrantedAuthorityDefaults("");
}
@Bean
public PasswordEncoder passwordEncoderBean() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// 搜寻 匿名标记 url: PreAuthorize("hasAnyRole('anonymous')") 和 PreAuthorize("@el.check('anonymous')") 和 AnonymousAccess
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();
Set<String> anonymousUrls = new HashSet<>();
for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
HandlerMethod handlerMethod = infoEntry.getValue();
AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class);
if (null != preAuthorize && preAuthorize.value().toLowerCase().contains("anonymous")) {
anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
} else if (null != anonymousAccess && null == preAuthorize) {
anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
}
}
httpSecurity
// 禁用 CSRF
.csrf().disable()
// 授权异常
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 不创建会话
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
.antMatchers(
HttpMethod.GET,
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js"
).anonymous()
.antMatchers().permitAll()
// swagger start
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/swagger-resources/**").permitAll()
.antMatchers("/webjars/**").permitAll()
.antMatchers("/*/api-docs").permitAll()
.antMatchers("/get_org_token").permitAll()
.antMatchers("/mock/cal_sign").permitAll()
.antMatchers("/getOrgs").permitAll()
.antMatchers("/zzdApi/getUserInfo").permitAll()
.antMatchers("/getGunName").permitAll()
.antMatchers("/getAllList").permitAll()
.antMatchers("/getSixModule").permitAll()
.antMatchers("/getGunPie").permitAll()
.antMatchers("/getGunInAndOut").permitAll()
.antMatchers("/getGunUnReturn").permitAll()
// swagger end
// 文件
.antMatchers("/avatar/**").permitAll()
.antMatchers("/file/**").permitAll()
// 放行OPTIONS请求
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/druid/**").permitAll()
// 自定义匿名访问所有url放行 : 允许 匿名和带权限以及登录用户访问
.antMatchers(anonymousUrls.toArray(new String[0])).permitAll()
// 所有请求都需要认证
.anyRequest().authenticated()
// 防止iframe 造成跨域
.and().headers().frameOptions().disable();
httpSecurity
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
}
package me.zhengjie.modules.security.rest;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.wf.captcha.ArithmeticCaptcha;
import com.wf.captcha.SpecCaptcha;
import com.zl.jwzh.yun.Qxrz;
import com.zl.jwzh.yun.comm.MyHelp;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.aop.log.Log;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.monitor.service.RedisService;
import me.zhengjie.modules.security.security.*;
import me.zhengjie.modules.security.service.OnlineUserService;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.UserDTO;
import me.zhengjie.modules.system.service.dto.UserSmallDTO;
import me.zhengjie.utils.EncryptUtils;
import me.zhengjie.modules.security.utils.JwtTokenUtil;
import me.zhengjie.utils.SecurityUtils;
import me.zhengjie.utils.StringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2018-11-23
* 授权、根据token获取用户详细信息
*/
@Slf4j
@RestController
@CrossOrigin
@RequestMapping("/auth")
@Api(tags = "系统:系统授权接口")
public class AuthenticationController {
@Value("${jwt.codeKey}")
private String codeKey;
@Value("${jwt.expiration}")
private Long expiration;
private final JwtTokenUtil jwtTokenUtil;
private final RedisService redisService;
private final UserService userService;
private final UserDetailsService userDetailsService;
private final OnlineUserService onlineUserService;
public AuthenticationController(JwtTokenUtil jwtTokenUtil, RedisService redisService,UserService userService, @Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService, OnlineUserService onlineUserService) {
this.jwtTokenUtil = jwtTokenUtil;
this.redisService = redisService;
this.userService = userService;
this.userDetailsService = userDetailsService;
this.onlineUserService = onlineUserService;
}
@Log("用户登录")
@ApiOperation("登录授权")
@AnonymousAccess
@PostMapping(value = "/login")
public ResponseEntity login(@Validated @RequestBody AuthUser authUser, HttpServletRequest request){
// 查询验证码
String code = redisService.getCodeVal(authUser.getUuid());
// 清除验证码
redisService.delete(authUser.getUuid());
if (!authUser.getCode().equalsIgnoreCase(code)) {
throw new BadRequestException("验证码错误");
}
final JwtUser jwtUser = (JwtUser) userDetailsService.loadUserByUsername(authUser.getUsername());
String ip = request.getRemoteAddr();
String errCount = redisService.getCodeVal(authUser.getUsername() + ip);
if (errCount != "" && Integer.parseInt(errCount) == 3){
throw new AccountExpiredException("在当前IP下该账号的访问被禁止, 请在30分钟后重试!");
}
if(!jwtUser.getPassword().equals(authUser.getPassword())){
if (errCount.isEmpty()) {
redisService.saveCode(authUser.getUsername() + ip, 1);
} else {
redisService.saveCode(authUser.getUsername() + ip, Integer.parseInt(errCount) + 1);
}
throw new AccountExpiredException("密码错误");
}
if(!jwtUser.isEnabled()){
throw new AccountExpiredException("账号已停用,请联系管理员");
}
// token过期了再刷token
boolean online = onlineUserService.getAll(null).stream().map(OnlineUser::getUserName).collect(Collectors.toList()).contains(authUser.getUsername());
if(online) {
List<OnlineUser> onlineUserList = onlineUserService.getAll(null).stream().filter(s->s.getUserName().equals(authUser.getUsername())).collect(Collectors.toList());
return ResponseEntity.ok(new AuthInfo( onlineUserList.get(0).getExpireTime(), onlineUserList.get(0).getToken() , jwtUser));
} else {
// 生成令牌
final String token = jwtTokenUtil.generateToken(jwtUser);
Long expireTime = new Date().getTime() + expiration;
// 保存在线信息
onlineUserService.save(jwtUser, token, expireTime, request);
userService.updateToken(jwtUser.getUsername(), token);
// 返回 token
return ResponseEntity.ok(new AuthInfo(expireTime,token, jwtUser));
}
}
@ApiOperation("刷新token")
@AnonymousAccess
@PostMapping(value = "/refreshToken")
public ResponseEntity refreshToken(@RequestParam("userName") String userName, HttpServletRequest request){
final JwtUser jwtUser = (JwtUser) userDetailsService.loadUserByUsername(userName);
// token过期了再刷token
boolean online = onlineUserService.getAll(null).stream().map(OnlineUser::getUserName).collect(Collectors.toList()).contains(userName);
if(online) {
List<OnlineUser> onlineUserList = onlineUserService.getAll(null).stream().filter(s->s.getUserName().equals(userName)).collect(Collectors.toList());
return ResponseEntity.ok(new AuthInfo( onlineUserList.get(0).getExpireTime(), onlineUserList.get(0).getToken() , jwtUser));
} else {
final String token = jwtTokenUtil.generateToken(jwtUser);
Long expireTime = new Date().getTime() + expiration;
onlineUserService.save(jwtUser, token,expireTime, request);
return ResponseEntity.ok(new AuthInfo(expireTime, token, jwtUser));
}
}
@ApiOperation("获取用户信息")
@AnonymousAccess
@PostMapping(value = "/userLogin")
public ResponseEntity userLogin(@Validated @RequestBody AuthUser authUser){
UserSmallDTO userSmallDTO = userService.findByUsername(authUser.getUsername());
if(!userSmallDTO.getPassword().equals(EncryptUtils.encryptPassword(authUser.getPassword()))){
throw new AccountExpiredException("密码错误");
}
if(!userSmallDTO.getEnabled()){
throw new AccountExpiredException("账号已停用,请联系管理员");
}
return ResponseEntity.ok(userSmallDTO);
}
@ApiOperation("获取用户信息")
@GetMapping(value = "/info")
public ResponseEntity getUserInfo(){
JwtUser jwtUser = (JwtUser)userDetailsService.loadUserByUsername(SecurityUtils.getUsername());
return ResponseEntity.ok(jwtUser);
}
@ApiOperation("获取验证码")
@AnonymousAccess
@GetMapping(value = "/code")
public ImgResult getCode(){
// 算术类型 https://gitee.com/whvse/EasyCaptcha
// ArithmeticCaptcha captcha = new ArithmeticCaptcha(111, 36);
// 几位数运算,默认是两位
// captcha.setLen(2);
// 获取运算的结果:5
SpecCaptcha captcha = new SpecCaptcha(111, 36,4);
String result = captcha.text();
String uuid = codeKey + IdUtil.simpleUUID();
redisService.saveCode(uuid,result);
return new ImgResult(captcha.toBase64(),uuid);
}
@ApiOperation("退出登录")
@AnonymousAccess
@DeleteMapping(value = "/logout")
public ResponseEntity logout(HttpServletRequest request){
// onlineUserService.logout(jwtTokenUtil.getToken(request));
return new ResponseEntity(HttpStatus.OK);
}
@Log("警综平台免登")
@ApiOperation("警综平台免登")
@AnonymousAccess
@GetMapping(value = "/pkiLogin")
public String pkiLogin(String zjipst_sfzh, String zjipst_rz, Model model,HttpServletRequest request , HttpServletResponse resp) {
try {
Qxrz ser = new Qxrz(); //警综验证接口
Map<String, Object> map = ser.verificationToMap(zjipst_rz);
if (map != null && map.size() > 0) {
String type = MyHelp.OtoS(map.get("TYPE")); //返回结果类型
String description = MyHelp.OtoS(map.get("DESCRIPTION")); //返回结果类型描述
Map<String, String> returnMsg = (Map<String, String>) map.get("RETURNMSG");
if (!"10000".equals(type)) {
model.addAttribute("error", "返回结果类型:"+ type + ";返回结果描述:" +description);
return "407";
} else {
zjipst_sfzh = returnMsg.get("SFZH");
UserDTO userDTO = userService.findBySfzh(zjipst_sfzh);
if (userDTO == null) {
model.addAttribute("error", "用户未在平台注册");
return "407";
}
final JwtUser jwtUser = (JwtUser) userDetailsService.loadUserByUsername(userDTO.getUsername());
final String token = jwtTokenUtil.generateToken(jwtUser);
Long expireTime = new Date().getTime() + expiration;
// 保存在线信息
onlineUserService.save(jwtUser, token, expireTime, request);
userService.updateToken(jwtUser.getUsername(), token);
resp.sendRedirect("http://41.190.20.132:99/#/login?redirect=%2Fdashboard&token=" + token );
}
} else {
model.addAttribute("error", "警综未正常返回数据");
return "407";
}
} catch (Exception e) {
e.printStackTrace();
}
return "407";
}
}
package me.zhengjie.modules.security.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.modules.security.service.OnlineUserService;
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;
@RestController
@RequestMapping("/auth/online")
@Api(tags = "系统:在线用户管理")
public class OnlineController {
private final OnlineUserService onlineUserService;
public OnlineController(OnlineUserService onlineUserService) {
this.onlineUserService = onlineUserService;
}
@ApiOperation("查询在线用户")
@GetMapping
@PreAuthorize("@el.check()")
public ResponseEntity getAll(String filter, Pageable pageable){
return new ResponseEntity<>(onlineUserService.getAll(filter, pageable),HttpStatus.OK);
}
@Log("导出数据")
@ApiOperation("导出数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check()")
public void download(HttpServletResponse response, String filter) throws IOException {
onlineUserService.download(onlineUserService.getAll(filter), response);
}
@ApiOperation("踢出用户")
@DeleteMapping(value = "/{key}")
@PreAuthorize("@el.check()")
public ResponseEntity delete(@PathVariable String key) throws Exception {
onlineUserService.kickOut(key);
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.modules.security.security;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.io.Serializable;
/**
* @author Zheng Jie
* @date 2018-11-23
* 返回token
*/
@Getter
@AllArgsConstructor
public class AuthInfo implements Serializable {
private final Long expireTime;
private final String token;
private final JwtUser user;
}
package me.zhengjie.modules.security.security;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotBlank;
/**
* @author Zheng Jie
* @date 2018-11-30
*/
@Getter
@Setter
public class AuthUser {
@NotBlank
private String username;
@NotBlank
private String password;
private String code;
private String uuid = "";
@Override
public String toString() {
return "{username=" + username + ", password= ******}";
}
}
package me.zhengjie.modules.security.security;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author Zheng Jie
* @date 2019-6-5 17:29:57
*/
@Data
@AllArgsConstructor
public class ImgResult {
private String img;
private String uuid;
}
package me.zhengjie.modules.security.security;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
private static final long serialVersionUID = -8970718410437077606L;
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
// 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
}
}
package me.zhengjie.modules.security.security;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.security.utils.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@Component
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
@Value("${jwt.online}")
private String onlineKey;
private final UserDetailsService userDetailsService;
private final JwtTokenUtil jwtTokenUtil;
private final RedisTemplate redisTemplate;
public JwtAuthorizationTokenFilter(@Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, RedisTemplate redisTemplate) {
this.userDetailsService = userDetailsService;
this.jwtTokenUtil = jwtTokenUtil;
this.redisTemplate = redisTemplate;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String authToken = jwtTokenUtil.getToken(request);
OnlineUser onlineUser = null;
try {
onlineUser = (OnlineUser)redisTemplate.opsForValue().get(onlineKey + authToken);
} catch (Exception e) {
log.error(e.getMessage());
}
if (onlineUser != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// It is not compelling necessary to load the use details from the database. You could also store the information
// in the token and read it from it. It's up to you ;)
JwtUser userDetails = (JwtUser)this.userDetailsService.loadUserByUsername(onlineUser.getUserName());
// For simple validation it is completely sufficient to just check the token integrity. You don't have to call
// the database compellingly. Again it's up to you ;)
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
}
package me.zhengjie.modules.security.security;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import me.zhengjie.modules.system.domain.BaseJpPoliceman;
import me.zhengjie.modules.system.service.dto.BaseJpOrganizationSmallDTO;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Getter
public class JwtUser implements UserDetails {
//@JsonIgnore
private final String id;
private final String username;
@JsonIgnore
private final String password;
private final String avatar;
private final String email;
private final String phone;
@JsonIgnore
private final String dept;
@JsonIgnore
private final String job;
private final List<Long> roleIds;
private final BaseJpOrganizationSmallDTO baseJpOrganization;
private final BaseJpPoliceman policeman;
private final String nickName;
@JsonIgnore
private final Collection<GrantedAuthority> authorities;
private final boolean enabled;
private Timestamp createTime;
@JsonIgnore
private final Date lastPasswordResetDate;
public JwtUser(String id, String username, String password, String avatar,
String email, String phone, List<Long> roleIds, String dept, String job, BaseJpOrganizationSmallDTO baseJpOrganization,
String nickName, Collection<GrantedAuthority> authorities, boolean enabled,
Timestamp createTime, Date lastPasswordResetDate, BaseJpPoliceman policeman) {
this.id = id;
this.username = username;
this.password = password;
this.avatar = avatar;
this.email = email;
this.phone = phone;
this.roleIds = roleIds;
this.dept = dept;
this.job = job;
this.baseJpOrganization = baseJpOrganization;
this.nickName = nickName;
this.authorities = authorities;
this.enabled = enabled;
this.createTime = createTime;
this.lastPasswordResetDate = lastPasswordResetDate;
this.policeman = policeman;
}
@JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
}
@JsonIgnore
@Override
public boolean isAccountNonLocked() {
return true;
}
@JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@JsonIgnore
@Override
public String getPassword() {
return password;
}
@Override
public boolean isEnabled() {
return enabled;
}
public Collection getRoles() {
return authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet());
}
}
package me.zhengjie.modules.security.security;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @author Zheng Jie
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OnlineUser {
private String userName;
private String job;
private String browser;
private String ip;
private String address;
private String key;
private String token;
private Date loginTime;
private Long expireTime;
}
package me.zhengjie.modules.security.service;
import me.zhengjie.modules.system.domain.Menu;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.modules.system.repository.RoleRepository;
import me.zhengjie.modules.system.service.dto.UserDTO;
import me.zhengjie.utils.StringUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@CacheConfig(cacheNames = "role")
public class JwtPermissionService {
private final RoleRepository roleRepository;
public JwtPermissionService(RoleRepository roleRepository) {
this.roleRepository = roleRepository;
}
/**
* key的名称如有修改,请同步修改 UserServiceImpl 中的 update 方法
* @param user 用户信息
* @return Collection
*/
@Cacheable(key = "'loadPermissionByUser:' + #p0.username")
public Collection<GrantedAuthority> mapToGrantedAuthorities(UserDTO user) {
System.out.println("--------------------loadPermissionByUser:" + user.getUsername() + "---------------------");
Set<Role> roles = roleRepository.findByUsers_Id(user.getId());
Set<String> permissions = roles.stream().filter(role -> StringUtils.isNotBlank(role.getPermission())).map(Role::getPermission).collect(Collectors.toSet());
permissions.addAll(
roles.stream().flatMap(role -> role.getMenus().stream())
.filter(menu -> StringUtils.isNotBlank(menu.getPermission()))
.map(Menu::getPermission).collect(Collectors.toSet())
);
return permissions.stream().map(permission -> new SimpleGrantedAuthority(permission))
.collect(Collectors.toList());
}
}
package me.zhengjie.modules.security.service;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.security.security.JwtUser;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.*;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2018-11-22
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class JwtUserDetailsService implements UserDetailsService {
private final UserService userService;
private final JwtPermissionService permissionService;
public JwtUserDetailsService(UserService userService, JwtPermissionService permissionService) {
this.userService = userService;
this.permissionService = permissionService;
}
@Override
public UserDetails loadUserByUsername(String username){
UserDTO user = userService.findByName(username);
if (user == null) {
throw new BadRequestException("账号不存在");
} else {
return createJwtUser(user);
}
}
public UserDetails createJwtUser(UserDTO user) {
return new JwtUser(
user.getId(),
user.getUsername(),
user.getPassword(),
user.getAvatar(),
user.getEmail(),
user.getPhone(),
user.getRoles().stream().map(roleSmallDTO -> roleSmallDTO.getId()).collect(Collectors.toList()),
Optional.ofNullable(user.getDept()).map(DeptSmallDTO::getName).orElse(null),
Optional.ofNullable(user.getJob()).map(JobSmallDTO::getName).orElse(null),
user.getBaseJpOrganization(),
user.getNickName(),
permissionService.mapToGrantedAuthorities(user),
user.getEnabled(),
user.getCreateTime(),
user.getLastPasswordResetTime(),
user.getPoliceman()
);
}
}
package me.zhengjie.modules.security.service;
import me.zhengjie.modules.security.security.JwtUser;
import me.zhengjie.modules.security.security.OnlineUser;
import me.zhengjie.utils.EncryptUtils;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* @author Zheng Jie
* @Date 2019年10月26日21:56:27
*/
@Service
@SuppressWarnings({"unchecked","all"})
public class OnlineUserService {
@Value("${jwt.expiration}")
private Long expiration;
@Value("${jwt.online}")
private String onlineKey;
private final RedisTemplate redisTemplate;
public OnlineUserService(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void save(JwtUser jwtUser, String token, Long expireTime, HttpServletRequest request){
String job = jwtUser.getDept() + "/" + jwtUser.getJob();
String ip = StringUtils.getIp(request);
String browser = StringUtils.getBrowser(request);
String address = StringUtils.getCityInfo(ip);
OnlineUser onlineUser = null;
try {
onlineUser = new OnlineUser(jwtUser.getUsername(), job, browser , ip, address, EncryptUtils.desEncrypt(token), token, new Date(), expireTime);
} catch (Exception e) {
e.printStackTrace();
}
redisTemplate.opsForValue().set(onlineKey + token, onlineUser);
redisTemplate.expire(onlineKey + token,expiration, TimeUnit.MILLISECONDS);
}
public Page<OnlineUser> getAll(String filter, Pageable pageable){
List<OnlineUser> onlineUsers = getAll(filter);
return new PageImpl<OnlineUser>(
PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(),onlineUsers),
pageable,
onlineUsers.size());
}
public List<OnlineUser> getAll(String filter){
List<String> keys = new ArrayList<>(redisTemplate.keys(onlineKey + "*"));
Collections.reverse(keys);
List<OnlineUser> onlineUsers = new ArrayList<>();
for (String key : keys) {
OnlineUser onlineUser = (OnlineUser) redisTemplate.opsForValue().get(key);
if(StringUtils.isNotBlank(filter)){
if(onlineUser.toString().contains(filter)){
onlineUsers.add(onlineUser);
}
} else {
onlineUsers.add(onlineUser);
}
}
Collections.sort(onlineUsers, (o1, o2) -> {
return o2.getLoginTime().compareTo(o1.getLoginTime());
});
return onlineUsers;
}
public void kickOut(String val) throws Exception {
String key = onlineKey + EncryptUtils.desDecrypt(val);
redisTemplate.delete(key);
}
public void logout(String token) {
String key = onlineKey + token;
redisTemplate.delete(key);
}
public void download(List<OnlineUser> all, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (OnlineUser user : all) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("用户名", user.getUserName());
map.put("岗位", user.getJob());
map.put("登录IP", user.getIp());
map.put("登录地点", user.getAddress());
map.put("浏览器", user.getBrowser());
map.put("登录日期", user.getLoginTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
package me.zhengjie.modules.security.utils;
import io.jsonwebtoken.*;
import io.jsonwebtoken.impl.DefaultClock;
import me.zhengjie.modules.security.security.JwtUser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@Component
public class JwtTokenUtil implements Serializable {
private static final long serialVersionUID = -3301605591108950415L;
private Clock clock = DefaultClock.INSTANCE;
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
@Value("${jwt.header}")
private String tokenHeader;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
private Date getIssuedAtDateFromToken(String token) {
return getClaimFromToken(token, Claims::getIssuedAt);
}
private Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(clock.now());
}
private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
return (lastPasswordReset != null && created.before(lastPasswordReset));
}
private Boolean ignoreTokenExpiration(String token) {
// here you specify tokens, for that the expiration is ignored
return false;
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
}
private String doGenerateToken(Map<String, Object> claims, String subject) {
final Date createdDate = clock.now();
final Date expirationDate = calculateExpirationDate(createdDate);
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(createdDate)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) {
final Date created = getIssuedAtDateFromToken(token);
return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset)
&& (!isTokenExpired(token) || ignoreTokenExpiration(token));
}
public String refreshToken(String token) {
final Date createdDate = clock.now();
final Date expirationDate = calculateExpirationDate(createdDate);
final Claims claims = getAllClaimsFromToken(token);
claims.setIssuedAt(createdDate);
claims.setExpiration(expirationDate);
return Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
public String getToken(HttpServletRequest request){
final String requestHeader = request.getHeader(tokenHeader);
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
return requestHeader.substring(7);
}
return null;
}
public Boolean validateToken(String token, UserDetails userDetails) {
JwtUser user = (JwtUser) userDetails;
final Date created = getIssuedAtDateFromToken(token);
final Date expiration = getExpirationDateFromToken(token);
// 如果token存在,且token创建日期 > 最后修改密码的日期 则代表token有效
return (!isTokenExpired(token)
&& !isCreatedBeforeLastPasswordReset(created, user.getLastPasswordResetDate())
);
}
private Date calculateExpirationDate(Date createdDate) {
return new Date(createdDate.getTime() + expiration);
}
}
package me.zhengjie.modules.system.domain;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.*;
@Entity
@Getter
@Setter
@Table(name="base_jp_organization")
public class BaseJpOrganization implements Serializable {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name= "system-uuid", strategy = "uuid")
@Column(name="id",length = 32)
@NotNull(groups = Update.class)
private String id;
@Column(name = "name",nullable = false)
@NotBlank
private String name;
@Column(name = "code",nullable = false)
@NotBlank
private String code;
@Column(name = "create_time")
private Date createTime;
@Column(name = "update_time")
private Date updateTime;
@Column(name = "find_code")
private String findCode;
@Column(name = "area_name")
private String areaName;
@Column(name = "state")
private int state;
@Column(name = "parent_id")
private String parentId;
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
@JoinColumn(name="parent_id")
private List<BaseJpOrganization> children = new ArrayList<BaseJpOrganization>();
@Column(name="show")
private String show;
@Column(name="d_name")
private String dName;
/**
* 经度
*/
@Column(name="longitude")
private String longitude;
/**
* 纬度
*/
@Column(name="latitude")
private String latitude;
public @interface Update {}
}
package me.zhengjie.modules.system.domain;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2021/8/6 15:27
* 作者:huangqy@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Entity
@Getter
@Setter
@Table(name="base_jp_policeman")
public class BaseJpPoliceman implements Serializable {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name= "system-uuid", strategy = "uuid")
@Column(name="id",length = 36)
@NotNull(groups = BaseJpPoliceman.Update.class)
private String id;
@Column(name = "police_code")
private String policeCode;
@Column(name = "name")
private String name;
public @interface Update {}
}
package me.zhengjie.modules.system.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2019-03-25
*/
@Entity
@Getter
@Setter
@Table(name="dept")
public class Dept implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@NotNull(groups = Update.class)
private Long id;
@Column(name = "name",nullable = false)
@NotBlank
private String name;
@NotNull
private Boolean enabled;
@Column(name = "pid",nullable = false)
@NotNull
private Long pid;
@JsonIgnore
@ManyToMany(mappedBy = "depts")
private Set<Role> roles;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
public @interface Update {}
}
\ No newline at end of file
package me.zhengjie.modules.system.domain;
import lombok.Getter;
import lombok.Setter;
import me.zhengjie.base.BaseEntity;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
@Entity
@Getter
@Setter
@Table(name="dict")
public class Dict implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@NotNull(groups = Update.class)
private Long id;
@Column(name = "name",nullable = false,unique = true)
@NotBlank
private String name;
@Column(name = "remark")
private String remark;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
@OneToMany(mappedBy = "dict",cascade={CascadeType.PERSIST,CascadeType.REMOVE})
private List<DictDetail> dictDetails;
public @interface Update {}
}
\ No newline at end of file
package me.zhengjie.modules.system.domain;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
@Entity
@Getter
@Setter
@Table(name="dict_detail")
public class DictDetail implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@NotNull(groups = Update.class)
private Long id;
// 字典标签
@Column(name = "label",nullable = false)
private String label;
// 字典值
@Column(name = "value",nullable = false)
private String value;
// 排序
@Column(name = "sort")
private String sort = "999";
// 字典id
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name = "dict_id")
private Dict dict;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
public @interface Update {}
}
\ No newline at end of file
package me.zhengjie.modules.system.domain;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-03-29
*/
@Entity
@Getter
@Setter
@Table(name="job")
public class Job implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@NotNull(groups = Update.class)
private Long id;
@Column(name = "name",nullable = false)
@NotBlank
private String name;
@Column(unique = true)
@NotNull
private Long sort;
@Column(name = "enabled",nullable = false)
@NotNull
private Boolean enabled;
@OneToOne
@JoinColumn(name = "dept_id")
private Dept dept;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
public @interface Update {}
}
\ No newline at end of file
package me.zhengjie.modules.system.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import me.zhengjie.modules.system.service.entity.TreeEntity;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Objects;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2018-12-17
*/
@Entity
@Getter
@Setter
@Table(name = "menu")
public class Menu extends TreeEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = {Update.class})
private Long id;
@NotBlank
private String name;
@Column(unique = true)
private Long sort = 999L;
@Column(name = "path")
private String path;
private String component;
// 类型
@Column(name = "type")
private Integer type;
// 权限
@Column(name = "permission")
private String permission;
@Column(unique = true,name = "component_name")
private String componentName;
private String icon;
@Column(columnDefinition = "bit(1) default 0")
private Boolean cache;
@Column(columnDefinition = "bit(1) default 0")
private Boolean hidden;
// 上级菜单ID
@Column(name = "pid",nullable = false)
private Long pid;
// 是否为外链 true/false
@Column(name = "i_frame")
private Boolean iFrame;
@ManyToMany(mappedBy = "menus")
@JsonIgnore
private Set<Role> roles;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
public @interface Update {}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Menu menu = (Menu) o;
return Objects.equals(id, menu.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
package me.zhengjie.modules.system.domain;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
@Entity
@Getter
@Setter
@Table(name="base_jp_process")
public class Process implements Serializable {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name= "system-uuid", strategy = "uuid")
@Column(name="id",length = 32)
@NotNull(groups = Process.Update.class)
private String id;
@Column(name = "name",nullable = false)
@NotBlank
private String name;
@Column(name = "code",nullable = false)
@NotBlank
private String code;
@Column(name = "description",nullable = false)
@NotBlank
private String description;
@Column(name = "publish_status")
@NotNull
private Boolean publishStatus;
@Column(name = "process_xml", columnDefinition = "text")
private String processXml;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
@Column(name = "update_time")
private Date updateTime;
// @Column(name = "org_id")
// private String orgId;
@OneToOne
@JoinColumn(name = "org_id")
private BaseJpOrganization baseJpOrganization;
public @interface Update {}
}
package me.zhengjie.modules.system.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Objects;
import java.util.Set;
/**
* 角色
* @author Zheng Jie
* @date 2018-11-22
*/
@Entity
@Table(name = "role")
@Getter
@Setter
public class Role implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull(groups = {Update.class})
private Long id;
@Column(nullable = false)
@NotBlank
private String name;
// 数据权限类型 全部 、 本级 、 自定义
@Column(name = "data_scope")
private String dataScope = "本级";
// 数值越小,级别越大
@Column(name = "level")
private Integer level = 3;
@Column
private String remark;
// 权限
@Column(name = "permission")
private String permission;
@JsonIgnore
@ManyToMany(mappedBy = "roles")
private Set<User> users;
@ManyToMany
@JoinTable(name = "roles_menus", joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "menu_id",referencedColumnName = "id")})
private Set<Menu> menus;
@ManyToMany
@JoinTable(name = "roles_depts", joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "dept_id",referencedColumnName = "id")})
private Set<Dept> depts;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
public @interface Update {}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Role role = (Role) o;
return Objects.equals(id, role.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
package me.zhengjie.modules.system.domain;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2018-11-22
*/
@Entity
@Getter
@Setter
@Table(name="common_jp_user")
public class User implements Serializable {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name= "system-uuid", strategy = "uuid")
@Column(name="id",length = 32)
@NotNull(groups = Update.class)
private String id;
@NotBlank
@Column(unique = true)
private String username;
@OneToOne
@JoinColumn(name = "avatar_id")
private UserAvatar userAvatar;
private String email;
@NotBlank
private String phone;
@NotNull
private Boolean enabled;
private String password;
private String token;
@JoinColumn(name = "nick_name")
private String nickName;
@OneToOne
@JoinColumn(name = "organization_id")
private BaseJpOrganization baseJpOrganization;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
@Column(name = "last_password_reset_time")
private Date lastPasswordResetTime;
@ManyToMany
@JoinTable(name = "users_roles", joinColumns = {@JoinColumn(name = "user_id",referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "id")})
private Set<Role> roles;
@OneToOne
@JoinColumn(name = "job_id")
private Job job;
@OneToOne
@JoinColumn(name = "dept_id")
private Dept dept;
@OneToOne
@JoinColumn(name = "police_id")
private BaseJpPoliceman policeman;
private String sfzh;
public @interface Update {}
}
package me.zhengjie.modules.system.domain;
import cn.hutool.core.util.ObjectUtil;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import me.zhengjie.base.BaseEntity;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019年9月7日 16:16:59
*/
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "user_avatar")
public class UserAvatar implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String realName;
private String path;
private String size;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
public UserAvatar(UserAvatar userAvatar,String realName, String path, String size) {
this.id = ObjectUtil.isNotEmpty(userAvatar) ? userAvatar.getId() : null;
this.realName = realName;
this.path = path;
this.size = size;
}
}
package me.zhengjie.modules.system.domain.vo;
import lombok.Data;
import java.util.List;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2022/8/31 13:48
* 作者:huangqy@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Data
public class GaodeRes {
private String status;
private List<GeoCodes> geocodes;
}
package me.zhengjie.modules.system.domain.vo;
import lombok.Data;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2022/8/31 13:50
* 作者:huangqy@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Data
public class GeoCodes {
private String location;
}
package me.zhengjie.modules.system.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.io.Serializable;
/**
* @author Zheng Jie
* @date 2018-12-20
*/
@Data
@AllArgsConstructor
public class MenuMetaVo implements Serializable {
private String title;
private String icon;
private Boolean noCache;
}
package me.zhengjie.modules.system.domain.vo;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 构建前端路由时用到
* @author Zheng Jie
* @date 2018-12-20
*/
@Data
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class MenuVo implements Serializable {
private String name;
private String path;
private Boolean hidden;
private String redirect;
private String component;
private Boolean alwaysShow;
private MenuMetaVo meta;
private List<MenuVo> children;
}
package me.zhengjie.modules.system.domain.vo;
import lombok.Data;
/**
* 修改密码的 Vo 类
* @author Zheng Jie
* @date 2019年7月11日13:59:49
*/
@Data
public class UserPassVo {
private String oldPass;
private String newPass;
}
package me.zhengjie.modules.system.repository;
import me.zhengjie.modules.system.domain.BaseJpOrganization;
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.transaction.annotation.Transactional;
import java.util.List;
public interface BaseJpOrganizationRepository extends JpaRepository<BaseJpOrganization, String>, JpaSpecificationExecutor<BaseJpOrganization> {
@Query(value = "SELECT * FROM base_jp_organization s1 WHERE s1.parent_id = ?1",nativeQuery = true)
List<BaseJpOrganization> findByPid(String id);
@Query(value = "SELECT * FROM base_jp_organization s1 WHERE longitude is null",nativeQuery = true)
List<BaseJpOrganization> queryAll();
@Query(value = "SELECT * FROM base_jp_organization s1 WHERE s1.code = ?1",nativeQuery = true)
BaseJpOrganization findByCode(String code);
@Modifying
@Transactional
@Query(value = "update base_jp_organization set longitude = ?2, latitude = ?3 WHERE code = ?1",nativeQuery = true)
void updateJWD(String code, String longitude, String latitude);
@Modifying
@Transactional
@Query(value = "update base_jp_organization set show = ?2 where id = ?1",nativeQuery = true)
void updateShowPurse(String id, String show);
}
package me.zhengjie.modules.system.repository;
import me.zhengjie.modules.system.domain.Dept;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2019-03-25
*/
public interface DeptRepository extends JpaRepository<Dept, Long>, JpaSpecificationExecutor<Dept> {
List<Dept> findByPid(Long id);
@Query(value = "select name from dept where id = ?1",nativeQuery = true)
String findNameById(Long id);
Set<Dept> findByRoles_Id(Long id);
}
\ No newline at end of file
package me.zhengjie.modules.system.repository;
import me.zhengjie.modules.system.domain.DictDetail;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
public interface DictDetailRepository extends JpaRepository<DictDetail, Long>, JpaSpecificationExecutor<DictDetail> {
}
\ No newline at end of file
package me.zhengjie.modules.system.repository;
import me.zhengjie.modules.system.domain.Dict;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
public interface DictRepository extends JpaRepository<Dict, Long>, JpaSpecificationExecutor<Dict> {
}
\ No newline at end of file
package me.zhengjie.modules.system.repository;
import me.zhengjie.modules.system.domain.Job;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author Zheng Jie
* @date 2019-03-29
*/
public interface JobRepository extends JpaRepository<Job, Long>, JpaSpecificationExecutor<Job> {
}
\ No newline at end of file
package me.zhengjie.modules.system.repository;
import me.zhengjie.modules.system.domain.Menu;
import me.zhengjie.modules.system.service.dto.MenuDTO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import java.util.LinkedHashSet;
import java.util.List;
/**
* @author Zheng Jie
* @date 2018-12-17
*/
public interface MenuRepository extends JpaRepository<Menu, Long>, JpaSpecificationExecutor<Menu> {
Menu findByName(String name);
Menu findByComponentName(String name);
List<Menu> findByPid(long pid);
LinkedHashSet<Menu> findByRoles_IdAndTypeIsNotInOrderBySortAsc(Long id, Integer type);
/**
* 查询顶级菜单
* @return /
*/
@Query(value = "SELECT m.* FROM menu m WHERE " +
"m.pid = 0",nativeQuery = true)
List<Menu> findByPidIsZero();
}
package me.zhengjie.modules.system.repository;
import me.zhengjie.modules.system.domain.Process;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
public interface ProcessRepository extends JpaRepository<Process, String>, JpaSpecificationExecutor<Process> {
@Query(value = "select * from base_jp_process where orgId = ?1 or orgId is null",nativeQuery = true)
Page<Process> findAllByOrgId(String orgId, Pageable pageable);
}
package me.zhengjie.modules.system.repository;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.modules.system.service.dto.RoleSmallDTO;
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 java.util.List;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2018-12-03
*/
public interface RoleRepository extends JpaRepository<Role, Long>, JpaSpecificationExecutor<Role> {
Role findByName(String name);
Set<Role> findByUsers_Id(String id);
@Modifying
@Query(value = "delete from roles_menus where menu_id = ?1",nativeQuery = true)
void untiedMenu(Long id);
@Query(value = "select * from role s1 where s1.level >= ?1",nativeQuery = true)
List<Role> findByLevel(Integer level);
}
package me.zhengjie.modules.system.repository;
import me.zhengjie.modules.system.domain.UserAvatar;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author Zheng Jie
* @date 2018-11-22
*/
public interface UserAvatarRepository extends JpaRepository<UserAvatar, Long>, JpaSpecificationExecutor<UserAvatar> {
}
package me.zhengjie.modules.system.repository;
import me.zhengjie.modules.system.domain.User;
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 java.util.Date;
import java.util.List;
/**
* @author Zheng Jie
* @date 2018-11-22
*/
public interface UserRepository extends JpaRepository<User, String>, JpaSpecificationExecutor<User> {
User findByUsername(String username);
User findByEmail(String email);
User findBySfzh(String sfzh);
@Query(value="SELECT * FROM common_jp_user WHERE organization_id = ?1",nativeQuery = true)
List<User> queryByOrganizationId(String organizationId);
@Query(value="select * from common_jp_user s1 where username=?1 ",nativeQuery = true)
User queryByUsername(String username);
@Modifying
@Query(value = "update common_jp_user set password = ?2 , last_password_reset_time = ?3 where username = ?1",nativeQuery = true)
void updatePass(String username, String pass, Date lastPasswordResetTime);
@Modifying
@Query(value = "update common_jp_user set email = ?2 where username = ?1",nativeQuery = true)
void updateEmail(String username, String email);
@Modifying
@Query(value = "update common_jp_user set token = ?2 where username = ?1",nativeQuery = true)
void updateToken(String username, String token);
}
package me.zhengjie.modules.system.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.config.DataScope;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.domain.Dept;
import me.zhengjie.modules.system.service.DeptService;
import me.zhengjie.modules.system.service.dto.DeptDTO;
import me.zhengjie.modules.system.service.dto.DeptQueryCriteria;
import me.zhengjie.utils.ThrowableUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @author Zheng Jie
* @date 2019-03-25
*/
@RestController
@Api(tags = "系统:部门管理")
@RequestMapping("/api/dept")
public class DeptController {
private final DeptService deptService;
private final DataScope dataScope;
private static final String ENTITY_NAME = "dept";
public DeptController(DeptService deptService, DataScope dataScope) {
this.deptService = deptService;
this.dataScope = dataScope;
}
@Log("导出部门数据")
@ApiOperation("导出部门数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('dept:list')")
public void download(HttpServletResponse response, DeptQueryCriteria criteria) throws IOException {
deptService.download(deptService.queryAll(criteria), response);
}
@Log("查询部门")
@ApiOperation("查询部门")
@GetMapping
@PreAuthorize("@el.check('user:list','dept:list')")
public ResponseEntity getDepts(DeptQueryCriteria criteria){
// 数据权限
criteria.setIds(dataScope.getDeptIds());
List<DeptDTO> deptDTOS = deptService.queryAll(criteria);
return new ResponseEntity<>(deptService.buildTree(deptDTOS),HttpStatus.OK);
}
@Log("新增部门")
@ApiOperation("新增部门")
@PostMapping
@PreAuthorize("@el.check('dept:add')")
public ResponseEntity create(@Validated @RequestBody Dept resources){
if (resources.getId() != null) {
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
}
return new ResponseEntity<>(deptService.create(resources),HttpStatus.CREATED);
}
@Log("修改部门")
@ApiOperation("修改部门")
@PutMapping
@PreAuthorize("@el.check('dept:edit')")
public ResponseEntity update(@Validated(Dept.Update.class) @RequestBody Dept resources){
deptService.update(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("删除部门")
@ApiOperation("删除部门")
@DeleteMapping(value = "/{id}")
@PreAuthorize("@el.check('dept:del')")
public ResponseEntity delete(@PathVariable Long id){
try {
deptService.delete(id);
}catch (Throwable e){
ThrowableUtil.throwForeignKeyException(e, "该部门存在岗位或者角色关联,请取消关联后再试");
}
return new ResponseEntity(HttpStatus.OK);
}
}
\ No newline at end of file
package me.zhengjie.modules.system.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.domain.Dict;
import me.zhengjie.modules.system.service.DictService;
import me.zhengjie.modules.system.service.dto.DictQueryCriteria;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
@Api(tags = "系统:字典管理")
@RestController
@RequestMapping("/api/dict")
public class DictController {
private final DictService dictService;
private static final String ENTITY_NAME = "dict";
public DictController(DictService dictService) {
this.dictService = dictService;
}
@Log("导出字典数据")
@ApiOperation("导出字典数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('dict:list')")
public void download(HttpServletResponse response, DictQueryCriteria criteria) throws IOException {
dictService.download(dictService.queryAll(criteria), response);
}
@Log("查询字典")
@ApiOperation("查询字典")
@GetMapping
@PreAuthorize("@el.check('dict:list')")
public ResponseEntity getDicts(DictQueryCriteria resources, Pageable pageable){
return new ResponseEntity<>(dictService.queryAll(resources,pageable),HttpStatus.OK);
}
@Log("新增字典")
@ApiOperation("新增字典")
@PostMapping
@PreAuthorize("@el.check('dict:add')")
public ResponseEntity create(@Validated @RequestBody Dict resources){
if (resources.getId() != null) {
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
}
return new ResponseEntity<>(dictService.create(resources),HttpStatus.CREATED);
}
@Log("修改字典")
@ApiOperation("修改字典")
@PutMapping
@PreAuthorize("@el.check('dict:edit')")
public ResponseEntity update(@Validated(Dict.Update.class) @RequestBody Dict resources){
dictService.update(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("删除字典")
@ApiOperation("删除字典")
@DeleteMapping(value = "/{id}")
@PreAuthorize("@el.check('dict:del')")
public ResponseEntity delete(@PathVariable Long id){
dictService.delete(id);
return new ResponseEntity(HttpStatus.OK);
}
}
\ No newline at end of file
package me.zhengjie.modules.system.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.domain.DictDetail;
import me.zhengjie.modules.system.service.DictDetailService;
import me.zhengjie.modules.system.service.dto.DictDetailQueryCriteria;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
@RestController
@Api(tags = "系统:字典详情管理")
@RequestMapping("/api/dictDetail")
public class DictDetailController {
private final DictDetailService dictDetailService;
private static final String ENTITY_NAME = "dictDetail";
public DictDetailController(DictDetailService dictDetailService) {
this.dictDetailService = dictDetailService;
}
@ApiOperation("查询字典详情")
@GetMapping
public ResponseEntity getDictDetails(DictDetailQueryCriteria criteria,
@PageableDefault(sort = {"sort"}, direction = Sort.Direction.ASC) Pageable pageable){
return new ResponseEntity<>(dictDetailService.queryAll(criteria,pageable),HttpStatus.OK);
}
@Log("查询多个字典详情")
@ApiOperation("查询多个字典详情")
@GetMapping(value = "/map")
public ResponseEntity getDictDetailMaps(DictDetailQueryCriteria criteria,
@PageableDefault(sort = {"sort"}, direction = Sort.Direction.ASC) Pageable pageable){
String[] names = criteria.getDictName().split(",");
Map<String,Object> map = new HashMap<>(names.length);
for (String name : names) {
criteria.setDictName(name);
map.put(name,dictDetailService.queryAll(criteria,pageable).get("content"));
}
return new ResponseEntity<>(map,HttpStatus.OK);
}
@Log("新增字典详情")
@ApiOperation("新增字典详情")
@PostMapping
@PreAuthorize("@el.check('dict:add')")
public ResponseEntity create(@Validated @RequestBody DictDetail resources){
if (resources.getId() != null) {
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
}
return new ResponseEntity<>(dictDetailService.create(resources),HttpStatus.CREATED);
}
@Log("修改字典详情")
@ApiOperation("修改字典详情")
@PutMapping
@PreAuthorize("@el.check('dict:edit')")
public ResponseEntity update(@Validated(DictDetail.Update.class) @RequestBody DictDetail resources){
dictDetailService.update(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("删除字典详情")
@ApiOperation("删除字典详情")
@DeleteMapping(value = "/{id}")
@PreAuthorize("@el.check('dict:del')")
public ResponseEntity delete(@PathVariable Long id){
dictDetailService.delete(id);
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.modules.system.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.config.DataScope;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.domain.Job;
import me.zhengjie.modules.system.service.JobService;
import me.zhengjie.modules.system.service.dto.JobQueryCriteria;
import me.zhengjie.utils.ThrowableUtil;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Zheng Jie
* @date 2019-03-29
*/
@Api(tags = "系统:岗位管理")
@RestController
@RequestMapping("/api/job")
public class JobController {
private final JobService jobService;
private final DataScope dataScope;
private static final String ENTITY_NAME = "job";
public JobController(JobService jobService, DataScope dataScope) {
this.jobService = jobService;
this.dataScope = dataScope;
}
@Log("导出岗位数据")
@ApiOperation("导出岗位数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('job:list')")
public void download(HttpServletResponse response, JobQueryCriteria criteria) throws IOException {
jobService.download(jobService.queryAll(criteria), response);
}
@Log("查询岗位")
@ApiOperation("查询岗位")
@GetMapping
@PreAuthorize("@el.check('job:list','user:list')")
public ResponseEntity getJobs(JobQueryCriteria criteria,
Pageable pageable){
// 数据权限
criteria.setDeptIds(dataScope.getDeptIds());
return new ResponseEntity<>(jobService.queryAll(criteria, pageable),HttpStatus.OK);
}
@Log("新增岗位")
@ApiOperation("新增岗位")
@PostMapping
@PreAuthorize("@el.check('job:add')")
public ResponseEntity create(@Validated @RequestBody Job resources){
if (resources.getId() != null) {
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
}
return new ResponseEntity<>(jobService.create(resources),HttpStatus.CREATED);
}
@Log("修改岗位")
@ApiOperation("修改岗位")
@PutMapping
@PreAuthorize("@el.check('job:edit')")
public ResponseEntity update(@Validated(Job.Update.class) @RequestBody Job resources){
jobService.update(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("删除岗位")
@ApiOperation("删除岗位")
@DeleteMapping(value = "/{id}")
@PreAuthorize("@el.check('job:del')")
public ResponseEntity delete(@PathVariable Long id){
try {
jobService.delete(id);
}catch (Throwable e){
ThrowableUtil.throwForeignKeyException(e, "该岗位存在用户关联,请取消关联后再试");
}
return new ResponseEntity(HttpStatus.OK);
}
}
\ No newline at end of file
package me.zhengjie.modules.system.rest;
import cn.hutool.core.collection.CollectionUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.aop.log.Log;
import me.zhengjie.modules.system.domain.Menu;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.service.MenuService;
import me.zhengjie.modules.system.service.RoleService;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.MenuDTO;
import me.zhengjie.modules.system.service.dto.MenuQueryCriteria;
import me.zhengjie.modules.system.service.dto.UserDTO;
import me.zhengjie.modules.system.service.dto.UserSmallDTO;
import me.zhengjie.modules.system.service.mapper.MenuMapper;
import me.zhengjie.utils.SecurityUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2018-12-03
*/
@Api(tags = "系统:菜单管理")
@RestController
@RequestMapping("/api/menus")
@SuppressWarnings("unchecked")
public class MenuController {
private final MenuService menuService;
private final UserService userService;
private final RoleService roleService;
private final MenuMapper menuMapper;
private static final String ENTITY_NAME = "menu";
public MenuController(MenuService menuService, UserService userService, RoleService roleService, MenuMapper menuMapper) {
this.menuService = menuService;
this.userService = userService;
this.roleService = roleService;
this.menuMapper = menuMapper;
}
@Log("导出菜单数据")
@ApiOperation("导出菜单数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('menu:list')")
public void download(HttpServletResponse response, MenuQueryCriteria criteria) throws IOException {
menuService.download(menuService.queryAll(criteria), response);
}
@ApiOperation("获取前端所需菜单")
@GetMapping(value = "/build")
public ResponseEntity buildMenus(){
// UserDTO user = userService.findByName(SecurityUtils.getUsername());
UserSmallDTO user = userService.findByUsername(SecurityUtils.getUsername());
List<MenuDTO> menuDTOList = menuService.findByRoles(roleService.findByUsers_Id(user.getId()), user.getBaseJpOrganization().getCode(), user.getBaseJpOrganization().getShow());
List<MenuDTO> menuDTOS = (List<MenuDTO>) menuService.buildTree(menuDTOList).get("content");
return new ResponseEntity<>(menuService.buildMenus(menuDTOS),HttpStatus.OK);
}
@ApiOperation("返回全部的菜单")
@GetMapping(value = "/tree")
@PreAuthorize("@el.check('menu:list','roles:list')")
public ResponseEntity getMenuTree(){
return new ResponseEntity<>(menuService.genMenuTree(),HttpStatus.OK);
}
@ApiOperation("返回全部的菜单")
@GetMapping(value = "/lazy")
@PreAuthorize("@el.check('menu:list','roles:list')")
public ResponseEntity<Object> query(@RequestParam Long pid){
return new ResponseEntity<>(menuService.getMenus(pid),HttpStatus.OK);
}
@ApiOperation("根据菜单ID返回所有子节点ID,包含自身ID")
@GetMapping(value = "/child")
@PreAuthorize("@el.check('menu:list','roles:list')")
public ResponseEntity<Object> child(@RequestParam Long id){
Set<Menu> menuSet = new HashSet<>();
List<MenuDTO> menuList = menuService.getMenus(id);
menuSet.add(menuService.findOne(id));
menuSet = menuService.getChildMenus(menuMapper.toEntity(menuList), menuSet);
Set<Long> ids = menuSet.stream().map(Menu::getId).collect(Collectors.toSet());
return new ResponseEntity<>(ids,HttpStatus.OK);
}
@Log("查询菜单")
@ApiOperation("查询菜单")
@GetMapping
@PreAuthorize("@el.check('menu:list')")
public ResponseEntity getMenus(MenuQueryCriteria criteria){
List<MenuDTO> menuDTOList = menuService.queryAll(criteria);
return new ResponseEntity<>(menuService.buildTree(menuDTOList),HttpStatus.OK);
}
@ApiOperation("查询菜单:根据ID获取同级与上级数据")
@PostMapping("/superior")
@PreAuthorize("@el.check('menu:list')")
public ResponseEntity<Object> getSuperior(@RequestBody List<Long> ids) {
Set<MenuDTO> menuDtos = new LinkedHashSet<>();
if(CollectionUtil.isNotEmpty(ids)){
for (Long id : ids) {
MenuDTO menuDto = menuService.findById(id);
menuDtos.addAll(menuService.getSuperior(menuDto, new ArrayList<>()));
}
return new ResponseEntity<>(menuService.buildTree(new ArrayList<>(menuDtos)),HttpStatus.OK);
}
return new ResponseEntity<>(menuService.getMenus(null),HttpStatus.OK);
}
@Log("新增菜单")
@ApiOperation("新增菜单")
@PostMapping
@PreAuthorize("@el.check('menu:add')")
public ResponseEntity create(@Validated @RequestBody Menu resources){
if (resources.getId() != null) {
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
}
return new ResponseEntity<>(menuService.create(resources),HttpStatus.CREATED);
}
@Log("修改菜单")
@ApiOperation("修改菜单")
@PutMapping
@PreAuthorize("@el.check('menu:edit')")
public ResponseEntity update(@Validated(Menu.Update.class) @RequestBody Menu resources){
menuService.update(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("删除菜单")
@ApiOperation("删除菜单")
@DeleteMapping(value = "/{id}")
@PreAuthorize("@el.check('menu:del')")
public ResponseEntity delete(@PathVariable Long id){
List<Menu> menuList = menuService.findByPid(id);
Set<Menu> menuSet = new HashSet<>();
menuSet.add(menuService.findOne(id));
menuSet = menuService.getDeleteMenus(menuList, menuSet);
menuService.delete(menuSet);
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.modules.system.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.modules.system.domain.BaseJpOrganization;
import me.zhengjie.modules.system.service.BaseJpOrganizationService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2021/3/11 15:31
* 作者:huangqy@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Api(tags = "组织机构管理采购管理")
@RestController
@RequestMapping("/api/org")
public class OrganizationController {
private BaseJpOrganizationService baseJpOrganizationService;
public OrganizationController(BaseJpOrganizationService baseJpOrganizationService) {
this.baseJpOrganizationService = baseJpOrganizationService;
}
@ApiOperation("获取单个流程")
@PostMapping(value = "/showPurse")
public ResponseEntity showPurse(@RequestBody BaseJpOrganization dto) {
this.baseJpOrganizationService.showPurse(dto.getId(), dto.getShow());
return new ResponseEntity(HttpStatus.OK);
}
@AnonymousAccess
@PostMapping(value = "/updateOrgJWD")
public ResponseEntity updateOrg() {
this.baseJpOrganizationService.updateOrgJWD();
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.modules.system.rest;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.modules.system.domain.Process;
import me.zhengjie.modules.system.service.ProcessService;
import me.zhengjie.modules.system.service.dto.ProcessDTO;
import me.zhengjie.modules.system.service.dto.ProcessQueryCriteria;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.nio.charset.Charset;
import java.util.*;
@RestController
@Api(tags = "系统:流程管理")
@RequestMapping("/api/process")
public class ProcessController {
private final ProcessService processService;
public ProcessController(ProcessService processService) {
this.processService = processService;
}
@ApiOperation("获取单个流程图")
@GetMapping(value = "getProcessXml/{id}")
public ResponseEntity getProcessXml(@PathVariable String id){
String result;
ProcessDTO processDTO = processService.findById(id);
if (ObjectUtil.isNull(processDTO.getProcessXml()) || processDTO.getProcessXml().isEmpty()) {
Map<String,Object> map = new HashMap<>();
map.put("id", processDTO.getId());
map.put("name", processDTO.getName());
map.put("description", processDTO.getDescription());
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
Template template = engine.getTemplate("generator/processXml.ftl");
result= template.render(map);
} else {
result = processDTO.getProcessXml();
}
MultiValueMap<String, String> stringMultiValueMap = new LinkedMultiValueMap<>();
stringMultiValueMap.add("Content-Type", "text/xml;charset=UTF-8");
return new ResponseEntity(result, stringMultiValueMap, HttpStatus.OK);
}
@ApiOperation("获取单个流程")
@GetMapping(value = "/{id}")
public ResponseEntity getProcess(@PathVariable String id) {
return new ResponseEntity(processService.findById(id), HttpStatus.OK);
}
@Log("查询流程列表")
@ApiOperation("查询流程列表")
@GetMapping
public ResponseEntity getProcesses(ProcessQueryCriteria criteria, Pageable pageable) {
return new ResponseEntity<>(processService.queryAll(criteria, pageable), HttpStatus.OK);
}
@Log("新增流程")
@ApiOperation("新增流程")
@PostMapping
public ResponseEntity create(@Validated @RequestBody Process resources) {
return new ResponseEntity<>(processService.create(resources), HttpStatus.CREATED);
}
@Log("修改流程")
@ApiOperation("修改流程")
@PutMapping
public ResponseEntity update(@Validated @RequestBody Process resources) {
processService.update(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("删除流程")
@ApiOperation("删除流程")
@DeleteMapping(value = "/{id}")
public ResponseEntity delete(@PathVariable String id){
processService.delete(id);
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.modules.system.rest;
import cn.hutool.core.lang.Dict;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.service.RoleService;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.RoleDTO;
import me.zhengjie.modules.system.service.dto.RoleQueryCriteria;
import me.zhengjie.modules.system.service.dto.RoleSmallDTO;
import me.zhengjie.utils.SecurityUtils;
import me.zhengjie.utils.ThrowableUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2018-12-03
*/
@Api(tags = "系统:角色管理")
@RestController
@RequestMapping("/api/roles")
public class RoleController {
private final RoleService roleService;
@Autowired
private UserService userService;
private static final String ENTITY_NAME = "role";
public RoleController(RoleService roleService) {
this.roleService = roleService;
}
@ApiOperation("获取单个role")
@GetMapping(value = "/{id}")
@PreAuthorize("@el.check('roles:list')")
public ResponseEntity getRoles(@PathVariable Long id){
return new ResponseEntity<>(roleService.findById(id), HttpStatus.OK);
}
@Log("导出角色数据")
@ApiOperation("导出角色数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('role:list')")
public void download(HttpServletResponse response, RoleQueryCriteria criteria) throws IOException {
roleService.download(roleService.queryAll(criteria), response);
}
@ApiOperation("返回全部的角色")
@GetMapping(value = "/all")
@PreAuthorize("@el.check('roles:list','user:add','user:edit')")
public ResponseEntity getAll(){
String username = SecurityUtils.getUsername();
Optional<RoleSmallDTO> roleSmallDTO = userService.findByName(username).getRoles().
stream().filter(Objects::nonNull).min(Comparator.comparingInt(RoleSmallDTO::getLevel));
return new ResponseEntity<>(roleService.findByLevel(roleSmallDTO.get().getLevel()),HttpStatus.OK);
}
@Log("查询角色")
@ApiOperation("查询角色")
@GetMapping
@PreAuthorize("@el.check('roles:list')")
public ResponseEntity getRoles(RoleQueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(roleService.queryAll(criteria,pageable),HttpStatus.OK);
}
@ApiOperation("获取用户级别")
@GetMapping(value = "/level")
public ResponseEntity getLevel(){
List<Integer> levels = roleService.findByUsers_Id(SecurityUtils.getUserId()).stream().map(RoleSmallDTO::getLevel).collect(Collectors.toList());
return new ResponseEntity<>(Dict.create().set("level", Collections.min(levels)),HttpStatus.OK);
}
@Log("新增角色")
@ApiOperation("新增角色")
@PostMapping
@PreAuthorize("@el.check('roles:add')")
public ResponseEntity create(@Validated @RequestBody Role resources){
if (resources.getId() != null) {
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
}
return new ResponseEntity<>(roleService.create(resources),HttpStatus.CREATED);
}
@Log("修改角色")
@ApiOperation("修改角色")
@PutMapping
@PreAuthorize("@el.check('roles:edit')")
public ResponseEntity update(@Validated(Role.Update.class) @RequestBody Role resources){
roleService.update(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("修改角色菜单")
@ApiOperation("修改角色菜单")
@PutMapping(value = "/menu")
@PreAuthorize("@el.check('roles:edit')")
public ResponseEntity updateMenu(@RequestBody Role resources){
RoleDTO role = roleService.findById(resources.getId());
roleService.updateMenu(resources,role);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@Log("删除角色")
@ApiOperation("删除角色")
@DeleteMapping(value = "/{id}")
@PreAuthorize("@el.check('roles:del')")
public ResponseEntity delete(@PathVariable Long id){
try {
roleService.delete(id);
}catch (Throwable e){
ThrowableUtil.throwForeignKeyException(e, "该角色存在用户关联,请取消关联后再试");
}
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.modules.system.rest;
import com.zl.jwzh.yun.Qxrz;
import com.zl.jwzh.yun.comm.MyHelp;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.aop.log.Log;
import me.zhengjie.config.DataScope;
import me.zhengjie.domain.VerificationCode;
import me.zhengjie.modules.monitor.service.RedisService;
import me.zhengjie.modules.security.service.OnlineUserService;
import me.zhengjie.modules.security.utils.JwtTokenUtil;
import me.zhengjie.modules.system.domain.BaseJpOrganization;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.domain.vo.UserPassVo;
import me.zhengjie.modules.system.service.BaseJpOrganizationService;
import me.zhengjie.modules.system.service.DeptService;
import me.zhengjie.modules.system.service.RoleService;
import me.zhengjie.modules.system.service.dto.RoleSmallDTO;
import me.zhengjie.modules.system.service.dto.UserDTO;
import me.zhengjie.modules.system.service.dto.UserQueryCriteria;
import me.zhengjie.modules.system.service.dto.UserSmallDTO;
import me.zhengjie.service.VerificationCodeService;
import me.zhengjie.utils.*;
import me.zhengjie.modules.system.service.UserService;
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.security.core.userdetails.UserDetails;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Api(tags = "系统:用户管理")
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
private final DataScope dataScope;
private final DeptService deptService;
private final BaseJpOrganizationService orgService;
private final RoleService roleService;
private final VerificationCodeService verificationCodeService;
private final RedisService redisService;
private final JwtTokenUtil jwtTokenUtil;
private final OnlineUserService onlineUserService;
public UserController(UserService userService, DataScope dataScope, DeptService deptService,
BaseJpOrganizationService orgService,RoleService roleService,
VerificationCodeService verificationCodeService, RedisService redisService,
JwtTokenUtil jwtTokenUtil, OnlineUserService onlineUserService) {
this.userService = userService;
this.dataScope = dataScope;
this.deptService = deptService;
this.orgService = orgService;
this.roleService = roleService;
this.verificationCodeService = verificationCodeService;
this.redisService = redisService;
this.jwtTokenUtil = jwtTokenUtil;
this.onlineUserService = onlineUserService;
}
@Log("导出用户数据")
@ApiOperation("导出用户数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('user:list')")
public void download(HttpServletResponse response, UserQueryCriteria criteria) throws IOException {
userService.download(userService.queryAll(criteria), response);
}
@Log("查询用户")
@ApiOperation("查询用户")
@GetMapping
@PreAuthorize("@el.check('user:list')")
public ResponseEntity getUsers(UserQueryCriteria criteria, Pageable pageable){
Integer currentLevel = Collections.min(roleService.findByUsers_Id(SecurityUtils.getUserId()).stream().map(RoleSmallDTO::getLevel).collect(Collectors.toList()));
return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK);
}
@ApiOperation("过滤掉等级比他高用户分页列表")
@GetMapping(value = "/getPageUser")
public ResponseEntity getPageUsers(UserQueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(userService.queryPageUser(criteria, pageable), HttpStatus.OK);
}
public static Set<String> getNodeIds(List<BaseJpOrganization> orgList, String parentId, Set<String> ids) {
for (BaseJpOrganization org : orgList) {
//遍历出父id等于参数的id,add进子节点集合
if (org.getParentId().equals(parentId)) {
//递归遍历下一级
ids.add(org.getId());
getNodeIds(orgList, org.getId(), ids);
}
}
return ids;
}
@Log("查询组织机构下用户")
@ApiOperation("查询组织机构下用户")
@AnonymousAccess
@GetMapping(value = "/all")
public ResponseEntity getUsers(UserQueryCriteria criteria){
return new ResponseEntity<>(userService.findByOrganizationId(criteria.getOrganizationId()),HttpStatus.OK);
}
@Log("新增用户")
@ApiOperation("新增用户")
@PostMapping
@PreAuthorize("@el.check('user:add')")
public ResponseEntity create(@Validated @RequestBody User resources){
checkLevel(resources);
return new ResponseEntity<>(userService.create(resources),HttpStatus.CREATED);
}
@Log("修改用户")
@ApiOperation("修改用户")
@PutMapping
@PreAuthorize("@el.check('user:edit')")
public ResponseEntity update(@Validated(User.Update.class) @RequestBody User resources){
checkLevel(resources);
userService.update(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@Log("删除用户")
@ApiOperation("删除用户")
@DeleteMapping(value = "/{id}")
@PreAuthorize("@el.check('user:del')")
public ResponseEntity delete(@PathVariable String id){
Integer currentLevel = Collections.min(roleService.findByUsers_Id(SecurityUtils.getUserId()).stream().map(RoleSmallDTO::getLevel).collect(Collectors.toList()));
Integer optLevel = Collections.min(roleService.findByUsers_Id(id).stream().map(RoleSmallDTO::getLevel).collect(Collectors.toList()));
if (currentLevel > optLevel) {
throw new BadRequestException("角色权限不足");
}
userService.delete(id);
return new ResponseEntity(HttpStatus.OK);
}
@ApiOperation("修改密码")
@PostMapping(value = "/updatePass")
public ResponseEntity updatePass(@RequestBody UserPassVo user, HttpServletRequest request){
UserDetails userDetails = SecurityUtils.getUserDetails();
if(!userDetails.getPassword().equals(EncryptUtils.encryptPassword(user.getOldPass()))){
throw new BadRequestException("修改失败,旧密码错误");
}
if(userDetails.getPassword().equals(EncryptUtils.encryptPassword(user.getNewPass()))){
throw new BadRequestException("新密码不能与旧密码相同");
}
userService.updatePass(userDetails.getUsername(),EncryptUtils.encryptPassword(user.getNewPass()));
redisService.delete("user::loadUserByUsername:" + userDetails.getUsername());
onlineUserService.logout(jwtTokenUtil.getToken(request));
return new ResponseEntity(HttpStatus.OK);
}
@ApiOperation("重置密码")
@PostMapping(value = "/resetPass")
public ResponseEntity resetPass(@RequestBody User user,HttpServletRequest request){
UserDTO userDTO = userService.findById(user.getId());
UserSmallDTO userSmallDTO = userService.findByUsername(userDTO.getUsername());
userService.updatePass(userDTO.getUsername(),EncryptUtils.encryptPassword("123456"));
redisService.delete("online-token" + userSmallDTO.getToken());
redisService.delete("user::loadUserByUsername:" + userDTO.getUsername());
return new ResponseEntity(HttpStatus.OK);
}
@ApiOperation("修改头像")
@PostMapping(value = "/updateAvatar")
public ResponseEntity updateAvatar(@RequestParam MultipartFile file){
userService.updateAvatar(file);
return new ResponseEntity(HttpStatus.OK);
}
@Log("修改邮箱")
@ApiOperation("修改邮箱")
@PostMapping(value = "/updateEmail/{code}")
public ResponseEntity updateEmail(@PathVariable String code,@RequestBody User user){
UserDetails userDetails = SecurityUtils.getUserDetails();
if(!userDetails.getPassword().equals(EncryptUtils.encryptPassword(user.getPassword()))){
throw new BadRequestException("密码错误");
}
VerificationCode verificationCode = new VerificationCode(code, ElAdminConstant.RESET_MAIL,"email",user.getEmail());
verificationCodeService.validated(verificationCode);
userService.updateEmail(userDetails.getUsername(),user.getEmail());
return new ResponseEntity(HttpStatus.OK);
}
/**
* 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误
* @param resources /
*/
private void checkLevel(User resources) {
Integer currentLevel = Collections.min(roleService.findByUsers_Id(SecurityUtils.getUserId()).stream().map(RoleSmallDTO::getLevel).collect(Collectors.toList()));
Integer optLevel = roleService.findByRoles(resources.getRoles());
if (currentLevel > optLevel) {
throw new BadRequestException("角色权限不足");
}
}
}
package me.zhengjie.modules.system.service;
import me.zhengjie.modules.oauth.service.dto.OrgDetailDto;
import me.zhengjie.modules.system.domain.BaseJpOrganization;
import me.zhengjie.modules.system.service.dto.BaseJpOrganizationDTO;
import java.util.List;
import java.util.Set;
public interface BaseJpOrganizationService {
List<BaseJpOrganization> findByPid(String parentId);
List<BaseJpOrganization> queryAll();
BaseJpOrganization findById(String id);
BaseJpOrganization findByCode(String code);
void showPurse(String id, String show);
void updateOrgJWD();
}
package me.zhengjie.modules.system.service;
import me.zhengjie.modules.system.domain.Dept;
import me.zhengjie.modules.system.service.dto.DeptDTO;
import me.zhengjie.modules.system.service.dto.DeptQueryCriteria;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2019-03-25
*/
public interface DeptService {
List<DeptDTO> queryAll(DeptQueryCriteria criteria);
DeptDTO findById(Long id);
DeptDTO create(Dept resources);
void update(Dept resources);
void delete(Long id);
Object buildTree(List<DeptDTO> deptDTOS);
List<Dept> findByPid(long pid);
Set<Dept> findByRoleIds(Long id);
void download(List<DeptDTO> queryAll, HttpServletResponse response) throws IOException;
}
\ No newline at end of file
package me.zhengjie.modules.system.service;
import me.zhengjie.modules.system.domain.DictDetail;
import me.zhengjie.modules.system.service.dto.DictDetailDTO;
import me.zhengjie.modules.system.service.dto.DictDetailQueryCriteria;
import org.springframework.data.domain.Pageable;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
public interface DictDetailService {
DictDetailDTO findById(Long id);
DictDetailDTO create(DictDetail resources);
void update(DictDetail resources);
void delete(Long id);
Map queryAll(DictDetailQueryCriteria criteria, Pageable pageable);
}
\ No newline at end of file
package me.zhengjie.modules.system.service;
import me.zhengjie.modules.system.domain.Dict;
import me.zhengjie.modules.system.service.dto.DictDTO;
import me.zhengjie.modules.system.service.dto.DictQueryCriteria;
import org.springframework.data.domain.Pageable;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
public interface DictService {
Map<String,Object> queryAll(DictQueryCriteria dict, Pageable pageable);
List<DictDTO> queryAll(DictQueryCriteria dict);
DictDTO findById(Long id);
DictDTO create(Dict resources);
void update(Dict resources);
void delete(Long id);
void download(List<DictDTO> queryAll, HttpServletResponse response) throws IOException;
}
\ No newline at end of file
package me.zhengjie.modules.system.service;
import me.zhengjie.modules.system.domain.Job;
import me.zhengjie.modules.system.service.dto.JobDTO;
import me.zhengjie.modules.system.service.dto.JobQueryCriteria;
import org.springframework.data.domain.Pageable;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2019-03-29
*/
public interface JobService {
JobDTO findById(Long id);
JobDTO create(Job resources);
void update(Job resources);
void delete(Long id);
Map<String,Object> queryAll(JobQueryCriteria criteria, Pageable pageable);
List<JobDTO> queryAll(JobQueryCriteria criteria);
void download(List<JobDTO> queryAll, HttpServletResponse response) throws IOException;
}
\ No newline at end of file
package me.zhengjie.modules.system.service;
import me.zhengjie.modules.system.domain.Menu;
import me.zhengjie.modules.system.service.dto.MenuDTO;
import me.zhengjie.modules.system.service.dto.MenuQueryCriteria;
import me.zhengjie.modules.system.service.dto.RoleSmallDTO;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2018-12-17
*/
public interface MenuService {
List<MenuDTO> queryAll(MenuQueryCriteria criteria);
MenuDTO findById(long id);
MenuDTO create(Menu resources);
void update(Menu resources);
Set<Menu> getDeleteMenus(List<Menu> menuList, Set<Menu> menuSet);
Object getMenuTree(List<Menu> menus);
Object genMenuTree();
/**
* 懒加载菜单数据
* @param pid /
* @return /
*/
List<MenuDTO> getMenus(Long pid);
/**
* 获取所有子节点,包含自身ID
* @param menuList /
* @param menuSet /
* @return /
*/
Set<Menu> getChildMenus(List<Menu> menuList, Set<Menu> menuSet);
/**
* 根据ID获取同级与上级数据
* @param menuDto /
* @param objects /
* @return /
*/
List<MenuDTO> getSuperior(MenuDTO menuDto, List<Menu> objects);
List<Menu> findByPid(long pid);
Map<String,Object> buildTree(List<MenuDTO> menuDTOS);
// List<MenuDTO> findByRoles(List<RoleSmallDTO> roles);
List<MenuDTO> findByRoles(List<RoleSmallDTO> roles, String code, String show);
Object buildMenus(List<MenuDTO> byRoles);
Menu findOne(Long id);
void delete(Set<Menu> menuSet);
void download(List<MenuDTO> queryAll, HttpServletResponse response) throws IOException;
}
package me.zhengjie.modules.system.service;
import me.zhengjie.modules.system.domain.Process;
import me.zhengjie.modules.system.service.dto.ProcessDTO;
import me.zhengjie.modules.system.service.dto.ProcessQueryCriteria;
import org.springframework.data.domain.Pageable;
public interface ProcessService {
ProcessDTO create(Process resources);
ProcessDTO findById(String id);
Object queryAll(ProcessQueryCriteria criteria, Pageable pageable);
void update(Process resources);
void delete(String id);
}
package me.zhengjie.modules.system.service;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.modules.system.service.dto.RoleDTO;
import me.zhengjie.modules.system.service.dto.RoleQueryCriteria;
import me.zhengjie.modules.system.service.dto.RoleSmallDTO;
import org.springframework.data.domain.Pageable;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2018-12-03
*/
public interface RoleService {
RoleDTO findById(long id);
RoleDTO create(Role resources);
void update(Role resources);
void delete(Long id);
List<RoleSmallDTO> findByUsers_Id(String id);
Integer findByRoles(Set<Role> roles);
void updateMenu(Role resources, RoleDTO roleDTO);
void untiedMenu(Long id);
Object queryAll(Pageable pageable);
Object queryAll(RoleQueryCriteria criteria, Pageable pageable);
List<RoleDTO> queryAll(RoleQueryCriteria criteria);
void download(List<RoleDTO> queryAll, HttpServletResponse response) throws IOException;
List<RoleSmallDTO> findByLevel(Integer level);
}
package me.zhengjie.modules.system.service;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.modules.system.service.dto.UserDTO;
import me.zhengjie.modules.system.service.dto.UserQueryCriteria;
import me.zhengjie.modules.system.service.dto.UserSmallDTO;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
public interface UserService {
UserDTO findById(String id);
UserDTO findBySfzh(String sfzh);
UserDTO create(User resources);
void update(User resources);
void delete(String id);
User queryByUsername(String username);
UserDTO findByName(String userName);
UserSmallDTO findByUsername(String userName);
List<UserDTO> findByOrganizationId(String organizationId);
void updatePass(String username, String encryptPassword);
void updateAvatar(MultipartFile file);
void updateEmail(String username, String email);
void updateToken(String username, String token);
Object queryAll(UserQueryCriteria criteria, Pageable pageable);
Object queryPageUser(UserQueryCriteria criteria, Pageable pageable);
List<UserDTO> queryAll(UserQueryCriteria criteria);
void download(List<UserDTO> queryAll, HttpServletResponse response) throws IOException;
}
package me.zhengjie.modules.system.service.dto;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;
@Getter
@Setter
public class BaseJpOrganizationDTO implements Serializable {
private String id;
private String parentId;
private List<BaseJpOrganizationDTO> children;
/**
* 初始化子类
*/
public void initChildren() {
if (getChildren() == null) {
this.setChildren(Lists.newArrayList());
}
}
}
package me.zhengjie.modules.system.service.dto;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
public class BaseJpOrganizationSmallDTO implements Serializable {
private String id;
private String name;
private String code;
private String findCode;
private String show;
private String dName;
private String longitude;
private String latitude;
}
package me.zhengjie.modules.system.service.dto;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Column;
import java.io.Serializable;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2021/8/19 17:22
* 作者:huangqy@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Getter
@Setter
public class BaseJpPolicemanDTO implements Serializable {
private String id;
private String policeCode;
private String name;
}
package me.zhengjie.modules.system.service.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;
/**
* @author Zheng Jie
* @date 2019-03-25
*/
@Getter
@Setter
public class DeptDTO implements Serializable {
// ID
private Long id;
// 名称
private String name;
@NotNull
private Boolean enabled;
// 上级部门
private Long pid;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<DeptDTO> children;
private Timestamp createTime;
public String getLabel() {
return name;
}
}
\ No newline at end of file
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
import java.sql.Timestamp;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2019-03-25
*/
@Data
public class DeptQueryCriteria{
@Query(type = Query.Type.IN, propName="id")
private Set<Long> ids;
@Query(type = Query.Type.INNER_LIKE)
private String name;
@Query
private Boolean enabled;
@Query
private Long pid;
@Query(type = Query.Type.GREATER_THAN,propName = "createTime")
private Timestamp startTime;
@Query(type = Query.Type.LESS_THAN,propName = "createTime")
private Timestamp endTime;
}
\ No newline at end of file
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author Zheng Jie
* @date 2019-6-10 16:32:18
*/
@Data
public class DeptSmallDTO implements Serializable {
private Long id;
private String name;
}
\ No newline at end of file
package me.zhengjie.modules.system.service.dto;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
@Getter
@Setter
public class DictDTO implements Serializable {
private Long id;
private String name;
private String remark;
private List<DictDetailDTO> dictDetails;
private Timestamp createTime;
}
package me.zhengjie.modules.system.service.dto;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
@Getter
@Setter
public class DictDetailDTO implements Serializable {
private Long id;
private String label;
private String value;
private String sort;
private Timestamp createTime;
}
\ No newline at end of file
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
@Data
public class DictDetailQueryCriteria {
@Query(type = Query.Type.INNER_LIKE)
private String label;
@Query(propName = "name",joinName = "dict")
private String dictName;
}
\ No newline at end of file
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
/**
* 公共查询类
*/
@Data
public class DictQueryCriteria {
// 多字段模糊
@Query(blurry = "name,remark")
private String blurry;
}
package me.zhengjie.modules.system.service.dto;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-03-29
*/
@Getter
@Setter
@NoArgsConstructor
public class JobDTO implements Serializable {
private Long id;
private Long sort;
private String name;
private Boolean enabled;
private DeptDTO dept;
private String deptSuperiorName;
private Timestamp createTime;
public JobDTO(String name, Boolean enabled) {
this.name = name;
this.enabled = enabled;
}
}
\ No newline at end of file
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import me.zhengjie.annotation.Query;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2019-6-4 14:49:34
*/
@Data
@NoArgsConstructor
public class JobQueryCriteria {
@Query(type = Query.Type.INNER_LIKE)
private String name;
@Query
private Boolean enabled;
@Query(propName = "id", joinName = "dept")
private Long deptId;
@Query(propName = "id", joinName = "dept", type = Query.Type.IN)
private Set<Long> deptIds;
@Query(type = Query.Type.GREATER_THAN,propName = "createTime")
private Timestamp startTime;
@Query(type = Query.Type.LESS_THAN,propName = "createTime")
private Timestamp endTime;
}
\ No newline at end of file
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author Zheng Jie
* @date 2019-6-10 16:32:18
*/
@Data
@NoArgsConstructor
public class JobSmallDTO implements Serializable {
private Long id;
private String name;
}
\ No newline at end of file
package me.zhengjie.modules.system.service.dto;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;
/**
* @author Zheng Jie
* @date 2018-12-17
*/
@Getter
@Setter
public class MenuDTO implements Serializable {
private Long id;
private Integer type;
private String permission;
private String name;
private Long sort;
private String path;
private String component;
private Long pid;
private Boolean iFrame;
private Boolean cache;
private Boolean hidden;
private String componentName;
private String icon;
private List<MenuDTO> children;
private Timestamp createTime;
}
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
import java.sql.Timestamp;
/**
* 公共查询类
*/
@Data
public class MenuQueryCriteria {
// 多字段模糊
@Query(blurry = "name,path,component")
private String blurry;
@Query(type = Query.Type.GREATER_THAN,propName = "createTime")
private Timestamp startTime;
@Query(type = Query.Type.LESS_THAN,propName = "createTime")
private Timestamp endTime;
}
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import me.zhengjie.modules.system.domain.Process;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
@Data
public class ProcessDTO implements Serializable {
private String id;
private String name;
private String code;
private String description;
private Boolean publishStatus;
private String processXml;
private Timestamp createTime;
private Date updateTime;
// private String orgId;
private BaseJpOrganizationSmallDTO baseJpOrganization;
}
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
@Data
public class ProcessQueryCriteria {
// 多字段模糊
@Query(blurry = "name,code")
private String blurry;
@Query(propName = "id", type = Query.Type.CONTAINS_NULL, joinName = "baseJpOrganization")
private String orgId;
}
package me.zhengjie.modules.system.service.dto;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Getter
@Setter
public class RoleDTO implements Serializable {
private Long id;
private String name;
private String dataScope;
private Integer level;
private String remark;
private String permission;
private Set<MenuDTO> menus;
private Set<DeptDTO> depts;
private Timestamp createTime;
}
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
import java.sql.Timestamp;
/**
* 公共查询类
*/
@Data
public class RoleQueryCriteria {
// 多字段模糊
@Query(blurry = "name,remark")
private String blurry;
@Query(type = Query.Type.GREATER_THAN,propName = "createTime")
private Timestamp startTime;
@Query(type = Query.Type.LESS_THAN,propName = "createTime")
private Timestamp endTime;
}
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Data
public class RoleSmallDTO implements Serializable {
private Long id;
private String name;
private Integer level;
private String dataScope;
}
package me.zhengjie.modules.system.service.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class UserAvatarDTO {
private String realName;
}
package me.zhengjie.modules.system.service.dto;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import me.zhengjie.modules.system.domain.BaseJpPoliceman;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Getter
@Setter
public class UserDTO implements Serializable {
@ApiModelProperty(hidden = true)
private String id;
private String username;
private String avatar;
private String email;
private String phone;
private Boolean enabled;
private BaseJpOrganizationSmallDTO baseJpOrganization;
private BaseJpPoliceman policeman;
private String nickName;
@JsonIgnore
private String password;
private Date lastPasswordResetTime;
@ApiModelProperty(hidden = true)
private Set<RoleSmallDTO> roles;
@ApiModelProperty(hidden = true)
private JobSmallDTO job;
private DeptSmallDTO dept;
private Long deptId;
private Timestamp createTime;
private String sfzh;
}
package me.zhengjie.modules.system.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Set;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Data
public class UserQueryCriteria implements Serializable {
@Query
private Long id;
@Query(propName = "id", type = Query.Type.IN, joinName = "dept")
private Set<Long> deptIds;
// 多字段模糊
@Query(blurry = "email,username")
private String blurry;
@Query(type = Query.Type.GREATER_THAN,propName = "level")
private Integer level;
@Query
private Boolean enabled;
private Long deptId;
@Query(propName = "id", joinName = "baseJpOrganization")
private String organizationId;
@Query(type = Query.Type.GREATER_THAN,propName = "createTime")
private Timestamp startTime;
@Query(type = Query.Type.LESS_THAN,propName = "createTime")
private Timestamp endTime;
}
package me.zhengjie.modules.system.service.dto;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import me.zhengjie.modules.system.domain.BaseJpPoliceman;
import java.io.Serializable;
@Getter
@Setter
public class UserSmallDTO implements Serializable {
private String id;
private String username;
private Boolean enabled;
@JsonIgnore
private String password;
private BaseJpOrganizationSmallDTO baseJpOrganization;
private String token;
private BaseJpPoliceman policeman;
}
package me.zhengjie.modules.system.service.entity;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2020-02-11 21:39
* 作者:ningzp@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Getter
@Setter
@Accessors(chain = true)
@ToString(callSuper = true)
public class TreeEntity<E, ID extends Serializable> {
/**
* ID
*/
protected ID id;
/**
* 父ID
*/
protected ID pid;
/**
* 排序
*/
protected Integer sortValue;
protected List<E> children;
/**
* 初始化子类
*/
public void initChildren() {
if (getChildren() == null) {
this.setChildren(Lists.newArrayList());
}
}
}
package me.zhengjie.modules.system.service.impl;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import me.zhengjie.modules.system.domain.BaseJpOrganization;
import me.zhengjie.modules.system.domain.vo.GaodeRes;
import me.zhengjie.modules.system.repository.BaseJpOrganizationRepository;
import me.zhengjie.modules.system.service.BaseJpOrganizationService;
import me.zhengjie.modules.system.service.dto.BaseJpOrganizationDTO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class BaseJpOrganizationServiceImpl implements BaseJpOrganizationService {
private final BaseJpOrganizationRepository baseJpOrganizationRepository;
public BaseJpOrganizationServiceImpl(BaseJpOrganizationRepository baseJpOrganizationRepository) {
this.baseJpOrganizationRepository = baseJpOrganizationRepository;
}
@Override
public List<BaseJpOrganization> findByPid(String parentId) {
return this.baseJpOrganizationRepository.findByPid(parentId);
}
@Override
public List<BaseJpOrganization> queryAll() {
return this.baseJpOrganizationRepository.queryAll();
}
@Override
public BaseJpOrganization findById(String id) {
return this.baseJpOrganizationRepository.findById(id).get();
}
@Override
public BaseJpOrganization findByCode(String code) {
return this.baseJpOrganizationRepository.findByCode(code);
}
@Override
public void showPurse(String id, String show) {
this.baseJpOrganizationRepository.updateShowPurse(id, show);
}
@Override
public void updateOrgJWD() {
List<BaseJpOrganization> baseJpOrganizationList = this.baseJpOrganizationRepository.queryAll();
for (BaseJpOrganization item: baseJpOrganizationList) {
String url = "https://restapi.amap.com/v3/geocode/geo";
Map<String, Object> map = new HashMap<String, Object>();
map.put("address", item.getName());
map.put("output", "JSON");
map.put("key", "8ed4581b658ba25c0e196400fa966522");
GaodeRes gaodeRes = JSON.parseObject(HttpUtil.get(url, map, 200), GaodeRes.class);
if (gaodeRes.getGeocodes() != null) {
String[] a = gaodeRes.getGeocodes().get(0).getLocation().split(",");
String longitude = a[0];
String latitude = a[1];
this.baseJpOrganizationRepository.updateJWD(item.getCode(), longitude, latitude);
}
}
}
public List<BaseJpOrganizationDTO> buildTree(List<BaseJpOrganizationDTO> BaseJpOrganizationDTOS) {
if (CollectionUtils.isEmpty(BaseJpOrganizationDTOS)) {
return BaseJpOrganizationDTOS;
}
//记录自己是自己的父节点的id集合
List<String> selfIdEqSelfParent = new ArrayList<>();
// 为每一个节点找到子节点集合
for (BaseJpOrganizationDTO parent : BaseJpOrganizationDTOS) {
String id = parent.getId();
for (BaseJpOrganizationDTO children : BaseJpOrganizationDTOS) {
if (parent != children) {
//parent != children 这个来判断自己的孩子不允许是自己,因为有时候,根节点的parent会被设置成为自己
if (id.equals(children.getParentId())) {
parent.initChildren();
parent.getChildren().add(children);
}
} else if (id.equals(parent.getParentId())) {
selfIdEqSelfParent.add(id);
}
}
}
// 找出根节点集合
List<BaseJpOrganizationDTO> trees = new ArrayList<>();
List<? extends Serializable> allIds = BaseJpOrganizationDTOS.stream().map(node -> node.getId()).collect(Collectors.toList());
for (BaseJpOrganizationDTO baseNode : BaseJpOrganizationDTOS) {
if (!allIds.contains(baseNode.getParentId()) || selfIdEqSelfParent.contains(baseNode.getParentId())) {
trees.add(baseNode);
}
}
return trees;
}
}
package me.zhengjie.modules.system.service.impl;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.system.domain.Dept;
import me.zhengjie.modules.system.service.dto.DeptQueryCriteria;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.modules.system.repository.DeptRepository;
import me.zhengjie.modules.system.service.DeptService;
import me.zhengjie.modules.system.service.dto.DeptDTO;
import me.zhengjie.modules.system.service.mapper.DeptMapper;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2019-03-25
*/
@Service
@CacheConfig(cacheNames = "dept")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class DeptServiceImpl implements DeptService {
private final DeptRepository deptRepository;
private final DeptMapper deptMapper;
public DeptServiceImpl(DeptRepository deptRepository, DeptMapper deptMapper) {
this.deptRepository = deptRepository;
this.deptMapper = deptMapper;
}
@Override
@Cacheable
public List<DeptDTO> queryAll(DeptQueryCriteria criteria) {
return deptMapper.toDto(deptRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
}
@Override
@Cacheable(key = "#p0")
public DeptDTO findById(Long id) {
Dept dept = deptRepository.findById(id).orElseGet(Dept::new);
ValidationUtil.isNull(dept.getId(),"Dept","id",id);
return deptMapper.toDto(dept);
}
@Override
@Cacheable
public List<Dept> findByPid(long pid) {
return deptRepository.findByPid(pid);
}
@Override
public Set<Dept> findByRoleIds(Long id) {
return deptRepository.findByRoles_Id(id);
}
@Override
@Cacheable
public Object buildTree(List<DeptDTO> deptDTOS) {
Set<DeptDTO> trees = new LinkedHashSet<>();
Set<DeptDTO> depts= new LinkedHashSet<>();
List<String> deptNames = deptDTOS.stream().map(DeptDTO::getName).collect(Collectors.toList());
boolean isChild;
for (DeptDTO deptDTO : deptDTOS) {
isChild = false;
if ("0".equals(deptDTO.getPid().toString())) {
trees.add(deptDTO);
}
for (DeptDTO it : deptDTOS) {
if (it.getPid().equals(deptDTO.getId())) {
isChild = true;
if (deptDTO.getChildren() == null) {
deptDTO.setChildren(new ArrayList<>());
}
deptDTO.getChildren().add(it);
}
}
if(isChild)
depts.add(deptDTO);
else if(!deptNames.contains(deptRepository.findNameById(deptDTO.getPid())))
depts.add(deptDTO);
}
if (CollectionUtils.isEmpty(trees)) {
trees = depts;
}
Integer totalElements = deptDTOS.size();
Map<String,Object> map = new HashMap<>();
map.put("totalElements",totalElements);
map.put("content",CollectionUtils.isEmpty(trees)?deptDTOS:trees);
return map;
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public DeptDTO create(Dept resources) {
return deptMapper.toDto(deptRepository.save(resources));
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(Dept resources) {
if(resources.getId().equals(resources.getPid())) {
throw new BadRequestException("上级不能为自己");
}
Dept dept = deptRepository.findById(resources.getId()).orElseGet(Dept::new);
ValidationUtil.isNull( dept.getId(),"Dept","id",resources.getId());
resources.setId(dept.getId());
deptRepository.save(resources);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
deptRepository.deleteById(id);
}
@Override
public void download(List<DeptDTO> deptDTOs, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (DeptDTO deptDTO : deptDTOs) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("部门名称", deptDTO.getName());
map.put("部门状态", deptDTO.getEnabled() ? "启用" : "停用");
map.put("创建日期", deptDTO.getCreateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
\ No newline at end of file
package me.zhengjie.modules.system.service.impl;
import me.zhengjie.modules.system.domain.DictDetail;
import me.zhengjie.modules.system.service.dto.DictDetailQueryCriteria;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.modules.system.repository.DictDetailRepository;
import me.zhengjie.modules.system.service.DictDetailService;
import me.zhengjie.modules.system.service.dto.DictDetailDTO;
import me.zhengjie.modules.system.service.mapper.DictDetailMapper;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
@Service
@CacheConfig(cacheNames = "dictDetail")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class DictDetailServiceImpl implements DictDetailService {
private final DictDetailRepository dictDetailRepository;
private final DictDetailMapper dictDetailMapper;
public DictDetailServiceImpl(DictDetailRepository dictDetailRepository, DictDetailMapper dictDetailMapper) {
this.dictDetailRepository = dictDetailRepository;
this.dictDetailMapper = dictDetailMapper;
}
@Override
@Cacheable
public Map queryAll(DictDetailQueryCriteria criteria, Pageable pageable) {
Page<DictDetail> page = dictDetailRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
return PageUtil.toPage(page.map(dictDetailMapper::toDto));
}
@Override
@Cacheable(key = "#p0")
public DictDetailDTO findById(Long id) {
DictDetail dictDetail = dictDetailRepository.findById(id).orElseGet(DictDetail::new);
ValidationUtil.isNull(dictDetail.getId(),"DictDetail","id",id);
return dictDetailMapper.toDto(dictDetail);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public DictDetailDTO create(DictDetail resources) {
return dictDetailMapper.toDto(dictDetailRepository.save(resources));
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(DictDetail resources) {
DictDetail dictDetail = dictDetailRepository.findById(resources.getId()).orElseGet(DictDetail::new);
ValidationUtil.isNull( dictDetail.getId(),"DictDetail","id",resources.getId());
resources.setId(dictDetail.getId());
dictDetailRepository.save(resources);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
dictDetailRepository.deleteById(id);
}
}
\ No newline at end of file
package me.zhengjie.modules.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import me.zhengjie.modules.system.domain.Dict;
import me.zhengjie.modules.system.service.dto.DictDetailDTO;
import me.zhengjie.modules.system.service.dto.DictQueryCriteria;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.modules.system.repository.DictRepository;
import me.zhengjie.modules.system.service.DictService;
import me.zhengjie.modules.system.service.dto.DictDTO;
import me.zhengjie.modules.system.service.mapper.DictMapper;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
@Service
@CacheConfig(cacheNames = "dict")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class DictServiceImpl implements DictService {
private final DictRepository dictRepository;
private final DictMapper dictMapper;
public DictServiceImpl(DictRepository dictRepository, DictMapper dictMapper) {
this.dictRepository = dictRepository;
this.dictMapper = dictMapper;
}
@Override
@Cacheable
public Map<String, Object> queryAll(DictQueryCriteria dict, Pageable pageable){
Page<Dict> page = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb), pageable);
return PageUtil.toPage(page.map(dictMapper::toDto));
}
@Override
public List<DictDTO> queryAll(DictQueryCriteria dict) {
List<Dict> list = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb));
return dictMapper.toDto(list);
}
@Override
@Cacheable(key = "#p0")
public DictDTO findById(Long id) {
Dict dict = dictRepository.findById(id).orElseGet(Dict::new);
ValidationUtil.isNull(dict.getId(),"Dict","id",id);
return dictMapper.toDto(dict);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public DictDTO create(Dict resources) {
return dictMapper.toDto(dictRepository.save(resources));
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(Dict resources) {
Dict dict = dictRepository.findById(resources.getId()).orElseGet(Dict::new);
ValidationUtil.isNull( dict.getId(),"Dict","id",resources.getId());
resources.setId(dict.getId());
dictRepository.save(resources);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
dictRepository.deleteById(id);
}
@Override
public void download(List<DictDTO> dictDTOS, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (DictDTO dictDTO : dictDTOS) {
if(CollectionUtil.isNotEmpty(dictDTO.getDictDetails())){
for (DictDetailDTO dictDetail : dictDTO.getDictDetails()) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("字典名称", dictDTO.getName());
map.put("字典描述", dictDTO.getRemark());
map.put("字典标签", dictDetail.getLabel());
map.put("字典值", dictDetail.getValue());
map.put("创建日期", dictDetail.getCreateTime());
list.add(map);
}
} else {
Map<String,Object> map = new LinkedHashMap<>();
map.put("字典名称", dictDTO.getName());
map.put("字典描述", dictDTO.getRemark());
map.put("字典标签", null);
map.put("字典值", null);
map.put("创建日期", dictDTO.getCreateTime());
list.add(map);
}
}
FileUtil.downloadExcel(list, response);
}
}
\ No newline at end of file
package me.zhengjie.modules.system.service.impl;
import me.zhengjie.modules.system.domain.Job;
import me.zhengjie.modules.system.repository.DeptRepository;
import me.zhengjie.modules.system.service.dto.JobQueryCriteria;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.modules.system.repository.JobRepository;
import me.zhengjie.modules.system.service.JobService;
import me.zhengjie.modules.system.service.dto.JobDTO;
import me.zhengjie.modules.system.service.mapper.JobMapper;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2019-03-29
*/
@Service
@CacheConfig(cacheNames = "job")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class JobServiceImpl implements JobService {
private final JobRepository jobRepository;
private final JobMapper jobMapper;
private final DeptRepository deptRepository;
public JobServiceImpl(JobRepository jobRepository, JobMapper jobMapper, DeptRepository deptRepository) {
this.jobRepository = jobRepository;
this.jobMapper = jobMapper;
this.deptRepository = deptRepository;
}
@Override
@Cacheable
public Map<String,Object> queryAll(JobQueryCriteria criteria, Pageable pageable) {
Page<Job> page = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
List<JobDTO> jobs = new ArrayList<>();
for (Job job : page.getContent()) {
jobs.add(jobMapper.toDto(job,deptRepository.findNameById(job.getDept().getPid())));
}
return PageUtil.toPage(jobs,page.getTotalElements());
}
@Override
@Cacheable
public List<JobDTO> queryAll(JobQueryCriteria criteria) {
List<Job> list = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
return jobMapper.toDto(list);
}
@Override
@Cacheable(key = "#p0")
public JobDTO findById(Long id) {
Job job = jobRepository.findById(id).orElseGet(Job::new);
ValidationUtil.isNull(job.getId(),"Job","id",id);
return jobMapper.toDto(job);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public JobDTO create(Job resources) {
return jobMapper.toDto(jobRepository.save(resources));
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(Job resources) {
Job job = jobRepository.findById(resources.getId()).orElseGet(Job::new);
ValidationUtil.isNull( job.getId(),"Job","id",resources.getId());
resources.setId(job.getId());
jobRepository.save(resources);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
jobRepository.deleteById(id);
}
@Override
public void download(List<JobDTO> jobDTOs, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (JobDTO jobDTO : jobDTOs) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("岗位名称", jobDTO.getName());
map.put("所属部门", jobDTO.getDept().getName());
map.put("岗位状态", jobDTO.getEnabled() ? "启用" : "停用");
map.put("创建日期", jobDTO.getCreateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
\ No newline at end of file
package me.zhengjie.modules.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import me.zhengjie.modules.system.domain.Menu;
import me.zhengjie.modules.system.domain.vo.MenuMetaVo;
import me.zhengjie.modules.system.domain.vo.MenuVo;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.exception.EntityExistException;
import me.zhengjie.modules.system.repository.MenuRepository;
import me.zhengjie.modules.system.service.MenuService;
import me.zhengjie.modules.system.service.RoleService;
import me.zhengjie.modules.system.service.dto.MenuDTO;
import me.zhengjie.modules.system.service.dto.MenuQueryCriteria;
import me.zhengjie.modules.system.service.dto.RoleSmallDTO;
import me.zhengjie.modules.system.service.mapper.MenuMapper;
import me.zhengjie.modules.util.TreeUtil;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.StringUtils;
import me.zhengjie.utils.ValidationUtil;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletResponse;
import javax.swing.text.StyledEditorKit;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import static java.lang.Math.E;
@Service
@CacheConfig(cacheNames = "menu")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class MenuServiceImpl implements MenuService {
private final MenuRepository menuRepository;
private final MenuMapper menuMapper;
private final RoleService roleService;
public MenuServiceImpl(MenuRepository menuRepository, MenuMapper menuMapper, RoleService roleService) {
this.menuRepository = menuRepository;
this.menuMapper = menuMapper;
this.roleService = roleService;
}
@Override
@Cacheable
public List<MenuDTO> queryAll(MenuQueryCriteria criteria){
// Sort sort = new Sort(Sort.Direction.DESC,"id");
return menuMapper.toDto(menuRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
}
@Override
@Cacheable(key = "#p0")
public MenuDTO findById(long id) {
Menu menu = menuRepository.findById(id).orElseGet(Menu::new);
ValidationUtil.isNull(menu.getId(),"Menu","id",id);
return menuMapper.toDto(menu);
}
@Override
public List<MenuDTO> findByRoles(List<RoleSmallDTO> roles, String code, String show) {
Set<Menu> menus = new LinkedHashSet<>();
for (RoleSmallDTO role : roles) {
List<Menu> menus1 = new ArrayList<>(menuRepository.findByRoles_IdAndTypeIsNotInOrderBySortAsc(role.getId(), 2));
menus.addAll(menus1);
}
Boolean result = ("00").equals(code.substring(6,8)) || ("1").equals(show);
if(result){
if("330200000000".equals(code)) {
return menus.stream().map(menuMapper::toDto).collect(Collectors.toList());
}else {
return menus.stream().filter(s-> !s.getName().equals("销毁管理")).filter(s-> !s.getName().equals("库存装备列表")).map(menuMapper::toDto).collect(Collectors.toList());
}
}else {
return menus.stream().filter(s-> !s.getName().equals("采购管理")).filter(s-> !s.getName().equals("库存阈值")).filter(s-> !s.getName().equals("销毁管理")).filter(s-> !s.getName().equals("库存装备列表")).map(menuMapper::toDto).collect(Collectors.toList());
}
}
// if(result) {
// return menus.stream().map(menuMapper::toDto).collect(Collectors.toList());
// } else {
// return menus.stream().filter(s-> !s.getName().equals("采购管理")).filter(s-> !s.getName().equals("库存阈值")).map(menuMapper::toDto).collect(Collectors.toList());
// }
// }
@Override
@CacheEvict(allEntries = true)
public MenuDTO create(Menu resources) {
if(menuRepository.findByName(resources.getName()) != null){
throw new EntityExistException(Menu.class,"name",resources.getName());
}
if(StringUtils.isNotBlank(resources.getComponentName())){
if(menuRepository.findByComponentName(resources.getComponentName()) != null){
throw new EntityExistException(Menu.class,"componentName",resources.getComponentName());
}
}
if(resources.getIFrame()){
if (!(resources.getPath().toLowerCase().startsWith("http://")||resources.getPath().toLowerCase().startsWith("https://"))) {
throw new BadRequestException("外链必须以http://或者https://开头");
}
}
return menuMapper.toDto(menuRepository.save(resources));
}
@Override
@CacheEvict(allEntries = true)
public void update(Menu resources) {
if(resources.getId().equals(resources.getPid())) {
throw new BadRequestException("上级不能为自己");
}
Menu menu = menuRepository.findById(resources.getId()).orElseGet(Menu::new);
ValidationUtil.isNull(menu.getId(),"Permission","id",resources.getId());
if(resources.getIFrame()){
if (!(resources.getPath().toLowerCase().startsWith("http://")||resources.getPath().toLowerCase().startsWith("https://"))) {
throw new BadRequestException("外链必须以http://或者https://开头");
}
}
Menu menu1 = menuRepository.findByName(resources.getName());
if(menu1 != null && !menu1.getId().equals(menu.getId())){
throw new EntityExistException(Menu.class,"name",resources.getName());
}
if(StringUtils.isNotBlank(resources.getComponentName())){
menu1 = menuRepository.findByComponentName(resources.getComponentName());
if(menu1 != null && !menu1.getId().equals(menu.getId())){
throw new EntityExistException(Menu.class,"componentName",resources.getComponentName());
}
}
menu.setName(resources.getName());
menu.setComponent(resources.getComponent());
menu.setPath(resources.getPath());
menu.setIcon(resources.getIcon());
menu.setIFrame(resources.getIFrame());
menu.setPid(resources.getPid());
menu.setSort(resources.getSort());
menu.setCache(resources.getCache());
menu.setHidden(resources.getHidden());
menu.setComponentName(resources.getComponentName());
menu.setPermission(resources.getPermission());
menu.setType(resources.getType());
menuRepository.save(menu);
}
@Override
public Set<Menu> getDeleteMenus(List<Menu> menuList, Set<Menu> menuSet) {
// 递归找出待删除的菜单
for (Menu menu1 : menuList) {
menuSet.add(menu1);
List<Menu> menus = menuRepository.findByPid(menu1.getId());
if(menus!=null && menus.size()!=0){
getDeleteMenus(menus, menuSet);
}
}
return menuSet;
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Set<Menu> menuSet) {
for (Menu menu : menuSet) {
roleService.untiedMenu(menu.getId());
menuRepository.deleteById(menu.getId());
}
}
@Override
// @Cacheable(key = "'tree'")
public Object getMenuTree(List<Menu> menus) {
List<Map<String,Object>> list = new LinkedList<>();
menus.forEach(menu -> {
if (menu!=null){
List<Menu> menuList = menuRepository.findByPid(menu.getId());
Map<String,Object> map = new HashMap<>();
map.put("id",menu.getId());
map.put("label",menu.getName());
if(menuList!=null && menuList.size()!=0){
map.put("children",getMenuTree(menuList));
}
list.add(map);
}
}
);
return list;
}
@Override
public Object genMenuTree() {
List<Map<String,Object>> list = new LinkedList<>();
List<Menu> menus = menuRepository.findAll();
return TreeUtil.buildTree(menus);
}
@Override
public List<MenuDTO> getMenus(Long pid) {
List<Menu> menus;
if(pid != null && !pid.equals(0L)){
menus = menuRepository.findByPid(pid);
} else {
menus = menuRepository.findByPidIsZero();
}
return menuMapper.toDto(menus);
}
@Override
public Set<Menu> getChildMenus(List<Menu> menuList, Set<Menu> menuSet) {
for (Menu menu : menuList) {
menuSet.add(menu);
List<Menu> menus = menuRepository.findByPid(menu.getId());
if(menus!=null && menus.size()!=0){
getChildMenus(menus, menuSet);
}
}
return menuSet;
}
@Override
@Cacheable(key = "'pid:'+#p0")
public List<Menu> findByPid(long pid) {
return menuRepository.findByPid(pid);
}
@Override
public Map<String,Object> buildTree(List<MenuDTO> menuDTOS) {
List<MenuDTO> trees = new ArrayList<>();
Set<Long> ids = new HashSet<>();
for (MenuDTO menuDTO : menuDTOS) {
if (menuDTO.getPid() == 0) {
trees.add(menuDTO);
}
for (MenuDTO it : menuDTOS) {
if (it.getPid().equals(menuDTO.getId())) {
if (menuDTO.getChildren() == null) {
menuDTO.setChildren(new ArrayList<>());
}
menuDTO.getChildren().add(it);
ids.add(it.getId());
}
}
}
Map<String,Object> map = new HashMap<>();
if(trees.size() == 0){
trees = menuDTOS.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList());
}
map.put("content",trees);
map.put("totalElements", menuDTOS.size());
return map;
}
@Override
public List<MenuVo> buildMenus(List<MenuDTO> menuDTOS) {
List<MenuVo> list = new LinkedList<>();
menuDTOS.forEach(menuDTO -> {
if (menuDTO!=null){
List<MenuDTO> menuDTOList = menuDTO.getChildren();
MenuVo menuVo = new MenuVo();
menuVo.setName(ObjectUtil.isNotEmpty(menuDTO.getComponentName()) ? menuDTO.getComponentName() : menuDTO.getName());
// 一级目录需要加斜杠,不然会报警告
menuVo.setPath(menuDTO.getPid() == 0 ? "/" + menuDTO.getPath() :menuDTO.getPath());
menuVo.setHidden(menuDTO.getHidden());
// 如果不是外链
if(!menuDTO.getIFrame()){
if(menuDTO.getPid() == 0){
menuVo.setComponent(StrUtil.isEmpty(menuDTO.getComponent())?"Layout":menuDTO.getComponent());
}else if(!StrUtil.isEmpty(menuDTO.getComponent())){
menuVo.setComponent(menuDTO.getComponent());
}
}
menuVo.setMeta(new MenuMetaVo(menuDTO.getName(),menuDTO.getIcon(),!menuDTO.getCache()));
if(menuDTOList!=null && menuDTOList.size()!=0){
menuVo.setAlwaysShow(true);
menuVo.setRedirect("noredirect");
menuVo.setChildren(buildMenus(menuDTOList));
// 处理是一级菜单并且没有子菜单的情况
} else if(menuDTO.getPid() == 0){
MenuVo menuVo1 = new MenuVo();
menuVo1.setMeta(menuVo.getMeta());
// 非外链
if(!menuDTO.getIFrame()){
menuVo1.setPath("index");
menuVo1.setName(menuVo.getName());
menuVo1.setComponent(menuVo.getComponent());
} else {
menuVo1.setPath(menuDTO.getPath());
}
menuVo.setName(null);
menuVo.setMeta(null);
menuVo.setComponent("Layout");
List<MenuVo> list1 = new ArrayList<>();
list1.add(menuVo1);
menuVo.setChildren(list1);
}
list.add(menuVo);
}
}
);
return list;
}
@Override
public List<MenuDTO> getSuperior(MenuDTO menuDto, List<Menu> menus) {
if(menuDto.getPid() == 0){
menus.addAll(menuRepository.findByPidIsZero());
return menuMapper.toDto(menus);
}
menus.addAll(menuRepository.findByPid(menuDto.getPid()));
return getSuperior(findById(menuDto.getPid()), menus);
}
@Override
public Menu findOne(Long id) {
Menu menu = menuRepository.findById(id).orElseGet(Menu::new);
ValidationUtil.isNull(menu.getId(),"Menu","id",id);
return menu;
}
@Override
public void download(List<MenuDTO> menuDTOS, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (MenuDTO menuDTO : menuDTOS) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("菜单名称", menuDTO.getName());
map.put("菜单类型", menuDTO.getType() == 0 ? "目录" : menuDTO.getType() == 1 ? "菜单" : "按钮");
map.put("权限标识", menuDTO.getPermission());
map.put("外链菜单", menuDTO.getIFrame() ? "是" : "否");
map.put("菜单可见", menuDTO.getHidden() ? "否" : "是");
map.put("是否缓存", menuDTO.getCache() ? "是" : "否");
map.put("创建日期", menuDTO.getCreateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
package me.zhengjie.modules.system.service.impl;
import me.zhengjie.modules.system.domain.Process;
import me.zhengjie.modules.system.repository.ProcessRepository;
import me.zhengjie.modules.system.service.ProcessService;
import me.zhengjie.modules.system.service.dto.ProcessDTO;
import me.zhengjie.modules.system.service.dto.ProcessQueryCriteria;
import me.zhengjie.modules.system.service.mapper.ProcessMapper;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class ProcessServiceImpl implements ProcessService {
private final ProcessRepository processRepository;
private final ProcessMapper processMapper;
public ProcessServiceImpl(ProcessRepository processRepository, ProcessMapper processMapper) {
this.processRepository = processRepository;
this.processMapper = processMapper;
}
@Override
@Transactional(rollbackFor = Exception.class)
public ProcessDTO create(Process resources) {
return processMapper.toDto(processRepository.save(resources));
}
@Override
public ProcessDTO findById(String id) {
return processMapper.toDto(processRepository.findById(id).get());
}
@Override
public Object queryAll(ProcessQueryCriteria criteria, Pageable pageable) {
Page<Process> page = processRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
return PageUtil.toPage(page.map(processMapper::toDto));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(Process resources) {
Process process = processRepository.findById(resources.getId()).orElseGet(Process::new);
ValidationUtil.isNull( process.getId(),"Process","id",resources.getId());
resources.setId(process.getId());
resources.setProcessXml(resources.getProcessXml());
processRepository.save(resources);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(String id) {
processRepository.deleteById(id);
}
}
package me.zhengjie.modules.system.service.impl;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.exception.EntityExistException;
import me.zhengjie.modules.system.repository.RoleRepository;
import me.zhengjie.modules.system.service.RoleService;
import me.zhengjie.modules.system.service.dto.RoleDTO;
import me.zhengjie.modules.system.service.dto.RoleQueryCriteria;
import me.zhengjie.modules.system.service.dto.RoleSmallDTO;
import me.zhengjie.modules.system.service.mapper.RoleMapper;
import me.zhengjie.modules.system.service.mapper.RoleSmallMapper;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2018-12-03
*/
@Service
@CacheConfig(cacheNames = "role")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class RoleServiceImpl implements RoleService {
private final RoleRepository roleRepository;
private final RoleMapper roleMapper;
private final RoleSmallMapper roleSmallMapper;
public RoleServiceImpl(RoleRepository roleRepository, RoleMapper roleMapper, RoleSmallMapper roleSmallMapper) {
this.roleRepository = roleRepository;
this.roleMapper = roleMapper;
this.roleSmallMapper = roleSmallMapper;
}
@Override
@Cacheable
public Object queryAll(Pageable pageable) {
return roleMapper.toDto(roleRepository.findAll(pageable).getContent());
}
@Override
@Cacheable
public List<RoleDTO> queryAll(RoleQueryCriteria criteria) {
return roleMapper.toDto(roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
}
@Override
@Cacheable
public Object queryAll(RoleQueryCriteria criteria, Pageable pageable) {
Page<Role> page = roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
return PageUtil.toPage(page.map(roleMapper::toDto));
}
@Override
@Cacheable(key = "#p0")
public RoleDTO findById(long id) {
Role role = roleRepository.findById(id).orElseGet(Role::new);
ValidationUtil.isNull(role.getId(),"Role","id",id);
return roleMapper.toDto(role);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public RoleDTO create(Role resources) {
if(roleRepository.findByName(resources.getName()) != null){
throw new EntityExistException(Role.class,"username",resources.getName());
}
return roleMapper.toDto(roleRepository.save(resources));
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(Role resources) {
Role role = roleRepository.findById(resources.getId()).orElseGet(Role::new);
ValidationUtil.isNull(role.getId(),"Role","id",resources.getId());
Role role1 = roleRepository.findByName(resources.getName());
if(role1 != null && !role1.getId().equals(role.getId())){
throw new EntityExistException(Role.class,"username",resources.getName());
}
role.setName(resources.getName());
role.setRemark(resources.getRemark());
role.setDataScope(resources.getDataScope());
role.setDepts(resources.getDepts());
role.setLevel(resources.getLevel());
roleRepository.save(role);
}
@Override
@CacheEvict(allEntries = true)
public void updateMenu(Role resources, RoleDTO roleDTO) {
Role role = roleMapper.toEntity(roleDTO);
role.setMenus(resources.getMenus());
roleRepository.save(role);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void untiedMenu(Long id) {
roleRepository.untiedMenu(id);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
roleRepository.deleteById(id);
}
@Override
@Cacheable(key = "'findByUsers_Id:' + #p0")
public List<RoleSmallDTO> findByUsers_Id(String id) {
return roleSmallMapper.toDto(new ArrayList<>(roleRepository.findByUsers_Id(id)));
}
@Override
@Cacheable
public Integer findByRoles(Set<Role> roles) {
Set<RoleDTO> roleDTOS = new HashSet<>();
for (Role role : roles) {
roleDTOS.add(findById(role.getId()));
}
return Collections.min(roleDTOS.stream().map(RoleDTO::getLevel).collect(Collectors.toList()));
}
@Override
public void download(List<RoleDTO> roles, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (RoleDTO role : roles) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("角色名称", role.getName());
map.put("默认权限", role.getPermission());
map.put("角色级别", role.getLevel());
map.put("描述", role.getRemark());
map.put("创建日期", role.getCreateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
@Override
public List<RoleSmallDTO> findByLevel(Integer level) {
return roleSmallMapper.toDto(roleRepository.findByLevel(level));
}
}
package me.zhengjie.modules.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONObject;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.monitor.service.RedisService;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.exception.EntityExistException;
import me.zhengjie.exception.EntityNotFoundException;
import me.zhengjie.modules.system.domain.UserAvatar;
import me.zhengjie.modules.system.repository.UserAvatarRepository;
import me.zhengjie.modules.system.repository.UserRepository;
import me.zhengjie.modules.system.service.RoleService;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.*;
import me.zhengjie.modules.system.service.mapper.UserMapper;
import me.zhengjie.modules.util.BeanPlusUtil;
import me.zhengjie.utils.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Service
@CacheConfig(cacheNames = "user")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final RedisService redisService;
private final UserAvatarRepository userAvatarRepository;
private final RoleService roleService;
private final UserMapper userMapper;
@Value("${file.avatar}")
private String avatar;
public UserServiceImpl(UserRepository userRepository, RedisService redisService, UserAvatarRepository userAvatarRepository,
UserMapper userMapper, RoleService roleService) {
this.userRepository = userRepository;
this.redisService = redisService;
this.userAvatarRepository = userAvatarRepository;
this.userMapper = userMapper;
this.roleService = roleService;
}
@Override
public Object queryAll(UserQueryCriteria criteria, Pageable pageable) {
Page<User> page = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
return PageUtil.toPage(page.map(item -> userMapper.toDto(item)));
}
@Override
public Object queryPageUser(UserQueryCriteria criteria, Pageable pageable) {
Integer currentLevel = Collections.min(roleService.findByUsers_Id(SecurityUtils.getUserId()).stream().map(RoleSmallDTO::getLevel).collect(Collectors.toList()));
List<User> users = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
List<User> ne = new ArrayList<>();
for (User user: users) {
Integer level = user.getRoles().stream().findFirst().orElseGet(null).getLevel();
if (level >= currentLevel) {
ne.add(user);
}
}
List<User> result = PageUtil.toPage(pageable.getPageNumber(), pageable.getPageSize(), ne);
Map<String,Object> map = new LinkedHashMap<>(2);
map.put("content",result.stream().map(item -> userMapper.toDto(item)));
map.put("totalElements",ne.size());
return map;
}
@Override
public List<UserDTO> queryAll(UserQueryCriteria criteria) {
List<User> users = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
return userMapper.toDto(users);
}
@Override
@Cacheable(key = "#p0")
public UserDTO findById(String id) {
User user = userRepository.findById(id).orElseGet(User::new);
ValidationUtil.isNull(user.getId(),"User","id",id);
return userMapper.toDto(user);
}
@Override
public UserDTO findBySfzh(String sfzh) {
User user = userRepository.findBySfzh(sfzh);
return userMapper.toDto(user);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public UserDTO create(User resources) {
if(userRepository.findByUsername(resources.getUsername())!=null){
// throw new EntityExistException(User.class,"username",resources.getUsername());
throw new BadRequestException("账号名已存在");
}
// 默认密码 123456,此密码是加密后的字符
resources.setPassword("e10adc3949ba59abbe56e057f20f883e");
if (resources.getPoliceman().getId().equals("")) {
resources.setPoliceman(null);
} else {
resources.setPoliceman(resources.getPoliceman());
}
// return BeanPlusUtil.toBean(userRepository.save(resources), UserDTO.class);
return userMapper.toDto(userRepository.save(resources));
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(User resources) {
User user = userRepository.findById(resources.getId()).orElseGet(User::new);
ValidationUtil.isNull(user.getId(),"User","id",resources.getId());
User user1 = userRepository.findByUsername(user.getUsername());
// User user2 = userRepository.findByEmail(user.getEmail());
if(user1 !=null&&!user.getId().equals(user1.getId())){
// throw new EntityExistException(User.class,"username",resources.getUsername());
throw new BadRequestException("账号名已存在");
}
// 如果用户的角色改变了,需要手动清理下缓存
if (!resources.getRoles().equals(user.getRoles())) {
String key = "role::loadPermissionByUser:" + user.getUsername();
redisService.delete(key);
key = "role::findByUsers_Id:" + user.getId();
redisService.delete(key);
}
user.setUsername(resources.getUsername());
user.setNickName(resources.getNickName());
user.setEmail(resources.getEmail());
user.setEnabled(resources.getEnabled());
user.setRoles(resources.getRoles());
user.setDept(resources.getDept());
user.setJob(resources.getJob());
user.setPhone(resources.getPhone());
user.setBaseJpOrganization(resources.getBaseJpOrganization());
user.setSfzh(resources.getSfzh());
if (resources.getPoliceman().getId().equals("")) {
user.setPoliceman(null);
} else {
user.setPoliceman(resources.getPoliceman());
}
userRepository.save(user);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(String id) {
userRepository.deleteById(id);
}
@Override
public User queryByUsername(String username) {
return userRepository.queryByUsername(username);
}
@Override
@Cacheable(key = "'loadUserByUsername:'+#p0")
public UserDTO findByName(String userName) {
User user;
if(ValidationUtil.isEmail(userName)){
user = userRepository.findByEmail(userName);
} else {
user = userRepository.queryByUsername(userName);
}
if (user == null) {
// throw new EntityNotFoundException(User.class, "name", userName);
throw new BadRequestException("账号不存在");
} else {
return userMapper.toDto(user);
// return BeanPlusUtil.toBean(user,UserDTO.class);
}
}
@Override
public UserSmallDTO findByUsername(String userName) {
User user;
if(ValidationUtil.isEmail(userName)){
user = userRepository.findByEmail(userName);
} else {
//user = userRepository.findByUsername(userName);
user = userRepository.queryByUsername(userName);
}
if (user == null) {
// throw new EntityNotFoundException(User.class, "name", userName);
throw new BadRequestException("账号不存在");
} else {
//return userMapper.toDto(user);
return BeanPlusUtil.toBean(user,UserSmallDTO.class);
}
}
@Override
public List<UserDTO> findByOrganizationId(String organizationId) {
return userMapper.toDto(userRepository.queryByOrganizationId(organizationId));
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void updatePass(String username, String pass) {
userRepository.updatePass(username,pass,new Date());
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void updateAvatar(MultipartFile multipartFile) {
User user = userRepository.findByUsername(SecurityUtils.getUsername());
UserAvatar userAvatar = user.getUserAvatar();
String oldPath = "";
if(userAvatar != null){
oldPath = userAvatar.getPath();
}
File file = FileUtil.upload(multipartFile, avatar);
assert file != null;
userAvatar = userAvatarRepository.save(new UserAvatar(userAvatar,file.getName(), file.getPath(), FileUtil.getSize(multipartFile.getSize())));
user.setUserAvatar(userAvatar);
userRepository.save(user);
if(StringUtils.isNotBlank(oldPath)){
FileUtil.del(oldPath);
}
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void updateEmail(String username, String email) {
userRepository.updateEmail(username,email);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateToken(String username, String token) {
userRepository.updateToken(username,token);
}
@Override
public void download(List<UserDTO> queryAll, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (UserDTO userDTO : queryAll) {
List roles = userDTO.getRoles().stream().map(RoleSmallDTO::getName).collect(Collectors.toList());
Map<String,Object> map = new LinkedHashMap<>();
map.put("用户名", userDTO.getUsername());
map.put("头像", userDTO.getAvatar());
map.put("邮箱", userDTO.getEmail());
map.put("状态", userDTO.getEnabled() ? "启用" : "禁用");
map.put("手机号码", userDTO.getPhone());
map.put("角色", roles);
map.put("部门", userDTO.getDept().getName());
map.put("岗位", userDTO.getJob().getName());
map.put("最后修改密码的时间", userDTO.getLastPasswordResetTime());
map.put("创建日期", userDTO.getCreateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.oauth.service.dto.OrgDetailDto;
import me.zhengjie.modules.system.domain.BaseJpOrganization;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface BaseJpOrganizationMapper extends BaseMapper<OrgDetailDto, BaseJpOrganization> {
}
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.BaseJpPoliceman;
import me.zhengjie.modules.system.service.dto.BaseJpPolicemanDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2021/8/19 17:19
* 作者:huangqy@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface BaseJpPolicemanMappper extends BaseMapper<BaseJpPolicemanDTO, BaseJpPoliceman> {
}
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.Dept;
import me.zhengjie.modules.system.service.dto.DeptDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2019-03-25
*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface DeptMapper extends BaseMapper<DeptDTO, Dept> {
}
\ No newline at end of file
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.Dept;
import me.zhengjie.modules.system.service.dto.DeptSmallDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2019-03-25
*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface DeptSmallMapper extends BaseMapper<DeptSmallDTO, Dept> {
}
\ No newline at end of file
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.DictDetail;
import me.zhengjie.modules.system.service.dto.DictDetailDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface DictDetailMapper extends BaseMapper<DictDetailDTO, DictDetail> {
}
\ No newline at end of file
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.Dict;
import me.zhengjie.modules.system.service.dto.DictDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2019-04-10
*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface DictMapper extends BaseMapper<DictDTO, Dict> {
}
\ No newline at end of file
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.Job;
import me.zhengjie.modules.system.service.dto.JobDTO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2019-03-29
*/
@Mapper(componentModel = "spring",uses = {DeptMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface JobMapper extends BaseMapper<JobDTO, Job> {
@Mapping(source = "deptSuperiorName", target = "deptSuperiorName")
JobDTO toDto(Job job, String deptSuperiorName);
}
\ No newline at end of file
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.Job;
import me.zhengjie.modules.system.service.dto.JobSmallDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2019-03-29
*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface JobSmallMapper extends BaseMapper<JobSmallDTO, Job> {
}
\ No newline at end of file
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.Menu;
import me.zhengjie.modules.system.service.dto.MenuDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2018-12-17
*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface MenuMapper extends BaseMapper<MenuDTO, Menu> {
}
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.Process;
import me.zhengjie.modules.system.service.dto.ProcessDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface ProcessMapper extends BaseMapper<ProcessDTO, Process> {
}
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.modules.system.service.dto.RoleDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Mapper(componentModel = "spring", uses = {MenuMapper.class, DeptMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface RoleMapper extends BaseMapper<RoleDTO, Role> {
}
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.modules.system.service.dto.RoleSmallDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2019-5-23
*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface RoleSmallMapper extends BaseMapper<RoleSmallDTO, Role> {
}
package me.zhengjie.modules.system.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.modules.system.service.dto.UserDTO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2018-11-23
*/
@Mapper(componentModel = "spring",uses = {RoleMapper.class, DeptMapper.class, JobMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface UserMapper extends BaseMapper<UserDTO, User> {
@Mapping(source = "user.userAvatar.realName",target = "avatar")
UserDTO toDto(User user);
}
package me.zhengjie.modules.util;
import cn.hutool.core.bean.BeanUtil;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class BeanPlusUtil extends BeanUtil {
/**
* 转换 list
*
* @param sourceList
* @param destinationClass
* @param <T>
* @param <E>
* @return
*/
public static <T, E> List<T> toBeanList(Collection<E> sourceList, Class<T> destinationClass) {
if (sourceList == null || sourceList.isEmpty() || destinationClass == null) {
return Collections.emptyList();
}
return sourceList.parallelStream()
.filter(item -> item != null)
.map((source) -> toBean(source, destinationClass))
.collect(Collectors.toList());
}
}
package me.zhengjie.modules.util;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.fastjson.JSON;
/**
* <pre>
*
* 描述:
* 版本:1.0.0
* 日期:2021/7/20 9:30
* 作者:huangqy@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
public class PageUtils<T> {
/**
* 当前页码
*/
private int currentPage;
/**
* 每页大小
*/
private int pageSize;
/**
* 总数据条数
*/
private int totalNum;
/**
* 首页
*/
private int first = 1;
/**
* 尾页
*/
private int last;
/**
* 总页数
*/
private int totalPage;
/**
* 上一页
*/
private int prev;
/**
* 下一页
*/
private int next;
/**
* 页面序号显示的起始位置
*/
private int startNum;
/**
* 页码显示控制-开始页码
*/
private int start;
/**
* 页码显示控制-结束页码
*/
private int end;
/**
* 显示页码控制-总显示页码(防止页码过多,页面显示拥挤问题)
*/
private int count = 10;
/**
* 数据
*/
private List<T> list = new ArrayList<>();
/**
* 在构造器中根据指定的参数,计算其他所有属性的属性值
* @param currentPage
* @param pageSize
* @param totalNum
*/
public PageUtils(int currentPage, int pageSize, int totalNum) {
this.currentPage = currentPage;
//赋值每天显示的记录条数
this.pageSize = pageSize;
//赋值总记录数(总数据条数)
this.totalNum = totalNum;
//计算获得总页数以及尾页
this.totalPage = this.last = (int)Math.ceil((double)totalNum/pageSize);
//防止当前页小于1
this.currentPage = Math.max(this.currentPage, 1);
//防止当前页超过总页数
this.currentPage = Math.min(this.totalPage, this.currentPage);
//设置上一页:上一页不能小于1
this.prev = Math.max(this.currentPage - 1 , 1);
//设置下一页:下一页不能超过总页数
this.next = Math.min(this.currentPage + 1 , this.totalPage);
//计算获取数据显示的序号位置
this.startNum = (this.currentPage - 1) * pageSize;
//计算显示页码的起始位置:起始位置不能小于1
this.start = Math.max(this.currentPage - this.count/2 , 1);
//计算显示页码的结束位置:结束位置不能超过总页数
this.end = Math.min(this.start + this.count , this.totalPage);
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getTotalNum() {
return totalNum;
}
public void setTotalNum(int totalNum) {
this.totalNum = totalNum;
}
public int getFirst() {
return first;
}
public void setFirst(int first) {
this.first = first;
}
public int getLast() {
return last;
}
public void setLast(int last) {
this.last = last;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getPrev() {
return prev;
}
public void setPrev(int prev) {
this.prev = prev;
}
public int getNext() {
return next;
}
public void setNext(int next) {
this.next = next;
}
public int getStartNum() {
return startNum;
}
public void setStartNum(int startNum) {
this.startNum = startNum;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
public String toString(){
return JSON.toJSONString(this);
}
}
package me.zhengjie.modules.util;
import me.zhengjie.modules.system.service.entity.TreeEntity;
import org.springframework.util.CollectionUtils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* <pre>
*
* 描述:list列表转换tree
* 版本:1.0.0
* 日期:2020-01-26 16:34
* 作者:ningzp@junmp.com.cn
* <br>修改记录
* <br>修改日期 修改人 修改内容
*
* </pre>
*/
public class TreeUtil {
/**
* 构建Tree结构
*
* @param treeList
* @param <E> 实体
* @param <?> 主键
* @return
*/
public static <E extends TreeEntity<E, ? extends Serializable>> List<E> buildTree(List<E> treeList) {
if (CollectionUtils.isEmpty(treeList)) {
return treeList;
}
//记录自己是自己的父节点的id集合
List<Serializable> selfIdEqSelfParent = new ArrayList<>();
// 为每一个节点找到子节点集合
for (E parent : treeList) {
Serializable id = parent.getId();
for (E children : treeList) {
if (parent != children) {
//parent != children 这个来判断自己的孩子不允许是自己,因为有时候,根节点的parent会被设置成为自己
if (id.equals(children.getPid())) {
parent.initChildren();
parent.getChildren().add(children);
}
} else if (id.equals(parent.getPid())) {
selfIdEqSelfParent.add(id);
}
}
}
// 找出根节点集合
List<E> trees = new ArrayList<>();
List<? extends Serializable> allIds = treeList.stream().map(node -> node.getId()).collect(Collectors.toList());
for (E baseNode : treeList) {
if (!allIds.contains(baseNode.getPid()) || selfIdEqSelfParent.contains(baseNode.getPid())) {
trees.add(baseNode);
}
}
return trees;
}
}
#版本信息
version=3.3.2
#专有云(CSB-V2);域名对应的IP(即将停止)
#csb_rest_url=http://41.188.16.160:8086/CSB
#专有云(CSB-V2)(即将停止)
#csb_rest_url=http://csb-broker.yun.zj:8086/CSB
#用户域-公安专区(CSB-V3)(推荐使用)
csb_rest_url=http://41.190.17.18:8086/CSB
#数据域-公安专区(CSB-V3)(暂无)
#csb_rest_url=
#AK、SK信息
accessKey=dbfe5c9cf5ee4c33b73c45d659aea58f
secretkey=OfKg7Crhv+LfgJCn/SFxDyxU410=
#系统标识
requestid=20210813155400018
#系统名称
xtzcmc=C33-00006077
#重试次数(推荐不超过2次)
retry=1
_ _ _
| | | | (_)
___| |______ __ _ __| |_ __ ___ _ _ __
/ _ | |______/ _` |/ _` | '_ ` _ \| | '_ \
| __| | | (_| | (_| | | | | | | | | | |
\___|_| \__,_|\__,_|_| |_| |_|_|_| |_|
:: Spring Boot :: (v2.1.0.RELEASE)
\ No newline at end of file
#配置数据源
spring:
datasource:
druid:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url: jdbc:log4jdbc:mysql://localhost:3306/eladmin?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
username: root
password: 123456
# 初始化配置
initial-size: 3
# 最小连接数
min-idle: 3
# 最大连接数
max-active: 15
# 获取连接超时时间
max-wait: 5000
# 连接有效性检测时间
time-between-eviction-runs-millis: 90000
# 最大空闲时间
min-evictable-idle-time-millis: 1800000
test-while-idle: true
test-on-borrow: false
test-on-return: false
validation-query: select 1
# 配置监控统计拦截的filters
filters: stat
stat-view-servlet:
url-pattern: /druid/*
reset-enable: false
web-stat-filter:
url-pattern: /*
exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
#配置 Jpa
jpa:
hibernate:
# 生产环境设置成 none,避免程序运行时自动更新数据库结构
ddl-auto: update
#jwt
jwt:
header: Authorization
secret: mySecret
# token 过期时间/毫秒,6小时 1小时 = 3600000 毫秒
expiration: 1800000
# 在线用户key
online: online-token
# 验证码
codeKey: code-key
#是否允许生成代码,生产环境设置为false
generator:
enabled: true
#是否开启 swagger-ui
swagger:
enabled: true
# 文件存储路径
file:
path: C:\eladmin\file\
avatar: C:\eladmin\avatar\
# 文件大小 /M
maxSize: 100
avatarMaxSize: 5
#配置数据源
spring:
datasource:
druid:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url: jdbc:log4jdbc:mysql://localhost:3306/eladmin?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
username: root
password: 123456
# 初始化配置
initial-size: 3
# 最小连接数
min-idle: 3
# 最大连接数
max-active: 15
# 获取连接超时时间
max-wait: 5000
# 连接有效性检测时间
time-between-eviction-runs-millis: 90000
# 最大空闲时间
min-evictable-idle-time-millis: 1800000
test-while-idle: true
test-on-borrow: false
test-on-return: false
validation-query: select 1
# 配置监控统计拦截的filters
filters: stat
stat-view-servlet:
url-pattern: /druid/*
reset-enable: false
login-username: admin
login-password: 123456
web-stat-filter:
url-pattern: /*
exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
#配置 Jpa
jpa:
hibernate:
# 生产环境设置成 none,避免程序运行时自动更新数据库结构
ddl-auto: none
#jwt
jwt:
header: Authorization
secret: mySecret
# token 过期时间 2个小时
expiration: 7200000
# 在线用户key
online: online-token
# 验证码
codeKey: code-key
#是否允许生成代码,生产环境设置为false
generator:
enabled: false
#如果生产环境要开启swagger,需要配置请求地址
#springfox:
# documentation:
# swagger:
# v2:
# host: # 接口域名或外网ip
#是否开启 swagger-ui
swagger:
enabled: true
# 文件存储路径
file:
path: /home/eladmin/file/
avatar: /home/eladmin/avatar/
# 文件大小 /M
maxSize: 100
avatarMaxSize: 5
server:
port: 10004
spring:
application:
name: police-user
cloud:
nacos:
config:
#现场
#namespace: 47f9ea0a-03a6-442c-9632-14f91d247bbf
namespace: 04e45a6f-c782-4ee4-b21e-000083ac1ed7
server-addr: 192.168.3.188:18848
file-extension: yml
dataId: application.yml
# shared-configs:
# - dataId: application.yml
# refresh: true
# enabled: true
discovery:
namespace: 04e45a6f-c782-4ee4-b21e-000083ac1ed7
server-addr: 192.168.3.188:18848
#现场
#namespace: 47f9ea0a-03a6-442c-9632-14f91d247bbf
main:
allow-bean-definition-overriding: true
datasource:
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
url: jdbc:sqlserver://192.168.3.188;DatabaseName=junmppolicesqldev
username: sa
password: Junmp123
# druid:
# type: com.alibaba.druid.pool.DruidDataSource
# driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
# url: jdbc:log4jdbc:mysql://192.168.3.32:13306/junmppolicesql?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
# username: root
# password: junmp.com.cn
#
# # 初始化配置
# initial-size: 3
# # 最小连接数
# min-idle: 3
# # 最大连接数
# max-active: 15
# # 获取连接超时时间
# max-wait: 5000
# # 连接有效性检测时间
# time-between-eviction-runs-millis: 90000
# # 最大空闲时间
# min-evictable-idle-time-millis: 1800000
# test-while-idle: true
# test-on-borrow: false
# test-on-return: false
#
# validation-query: select 1
# # 配置监控统计拦截的filters
# filters: stat
# stat-view-servlet:
# url-pattern: /druid/*
# reset-enable: false
#
# web-stat-filter:
# url-pattern: /*
# exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
freemarker:
check-template-location: false
jackson:
time-zone: GMT+8
data:
redis:
repositories:
enabled: false
#配置 Jpa
jpa:
database: sql_server
properties:
hibernate:
default_schema: dbo
dialect: org.hibernate.dialect.SQLServer2008Dialect
# dialect: org.hibernate.dialect.MySQL5InnoDBDialect
open-in-view: true
# show-sql: true
hibernate:
ddl-auto: none
redis:
#数据库索引
database: 11
host: 192.168.3.188
port: 6379
password: ''
#连接超时时间
timeout: 5000
task:
pool:
# 核心线程池大小
core-pool-size: 10
# 最大线程数
max-pool-size: 30
# 活跃时间
keep-alive-seconds: 60
# 队列容量
queue-capacity: 50
dd:
domainName: "openplatform.dg-work.cn"
appkey: "JYZBDD-sSj6kL6oT25L0Z9f8mMbyum"
appsecret: "cY3rToRh74tUyeoKpfZF5kkhJ84KIbCNaq937Nry"
#七牛云
qiniu:
# 文件大小 /M
max-size: 15
#邮箱验证码有效时间/分钟
code:
expiration: 5
#登录图形验证码有效时间/分钟
loginCode:
expiration: 2
#jwt
jwt:
header: Authorization
secret: mySecretmySecretmySecretmySecretmySecretmySecretmySecretmySecretmySecretmySecretmySecretmySecretmySecretmySecret
# token 过期时间/毫秒,6小时 1小时 = 3600000 毫秒
expiration: 604800000
# 在线用户key
online: online-token
# 验证码
codeKey: code-key
#是否允许生成代码,生产环境设置为false
generator:
enabled: true
#是否开启 swagger-ui
swagger:
enabled: true
# 文件存储路径
file:
path: C:\eladmin\file\
avatar: C:\eladmin\avatar\
# 文件大小 /M
maxSize: 100
avatarMaxSize: 5
#数据库类型转Java类型
tinyint=Integer
smallint=Integer
mediumint=Integer
int=Integer
integer=Integer
bigint=Long
float=Float
double=Double
decimal=BigDecimal
bit=Boolean
char=String
varchar=String
tinytext=String
text=String
mediumtext=String
longtext=String
date=Timestamp
datetime=Timestamp
timestamp=Timestamp
\ No newline at end of file
# If you use SLF4J. First, you need to tell log4jdbc-log4j2 that you want to use the SLF4J logger
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
log4jdbc.auto.load.popular.drivers=false
log4jdbc.drivers=com.mysql.cj.jdbc.Driver
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>elAdmin</contextName>
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!--普通日志输出到控制台-->
<root level="info">
<appender-ref ref="console" />
</root>
<!--监控sql日志输出 -->
<logger name="jdbc.sqlonly" level="INFO" additivity="false">
<appender-ref ref="console" />
</logger>
<logger name="jdbc.resultset" level="ERROR" additivity="false">
<appender-ref ref="console" />
</logger>
<!-- 如想看到表格数据,将OFF改为INFO -->
<logger name="jdbc.resultsettable" level="OFF" additivity="false">
<appender-ref ref="console" />
</logger>
<logger name="jdbc.connection" level="OFF" additivity="false">
<appender-ref ref="console" />
</logger>
<logger name="jdbc.sqltiming" level="OFF" additivity="false">
<appender-ref ref="console" />
</logger>
<logger name="jdbc.audit" level="OFF" additivity="false">
<appender-ref ref="console" />
</logger>
</configuration>
\ No newline at end of file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<style>
@page {
margin: 0;
}
</style>
</head>
<body style="margin: 0px;
padding: 0px;
font: 100% SimSun, Microsoft YaHei, Times New Roman, Verdana, Arial, Helvetica, sans-serif;
color: #000;">
<div style="height: auto;
width: 820px;
min-width: 820px;
margin: 0 auto;
margin-top: 20px;
border: 1px solid #eee;">
<div style="padding: 10px;padding-bottom: 0px;">
<p style="margin-bottom: 10px;padding-bottom: 0px;">尊敬的用户,您好:</p>
<p style="text-indent: 2em; margin-bottom: 10px;">您正在申请邮箱验证,您的验证码为:</p>
<p style="text-align: center;
font-family: Times New Roman;
font-size: 22px;
color: #C60024;
padding: 20px 0px;
margin-bottom: 10px;
font-weight: bold;
background: #ebebeb;">${code}</p>
<div style="list-style: none;
margin-top: 22px;
maigin-bottom: 10px;
font-size: 14px;
color: #555;">
<p style="line-height: 12px;">Github:<a hover="color: #DA251D;" style="color: #999;" href="https://github.com/elunez/eladmin" target="_blank">https://github.com/elunez/eladmin</a></p>
</div>
<div class="foot-hr hr" style="margin: 0 auto;
z-index: 111;
width: 800px;
margin-top: 30px;
border-top: 1px solid #DA251D;">
</div>
<div style="text-align: center;
font-size: 12px;
padding: 20px 0px;
font-family: Microsoft YaHei;">
Copyright &copy;${.now?string("yyyy")} EL-ADMIN 后台管理系统 All Rights Reserved.
</div>
</div>
</div>
</body>
</html>
package ${package}.rest;
import me.zhengjie.aop.log.Log;
import ${package}.domain.${className};
import ${package}.service.${className}Service;
import ${package}.service.dto.${className}QueryCriteria;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
/**
* @author ${author}
* @date ${date}
*/
@Api(tags = "${className}管理")
@RestController
@RequestMapping("/api/${changeClassName}")
public class ${className}Controller {
private final ${className}Service ${changeClassName}Service;
public ${className}Controller(${className}Service ${changeClassName}Service) {
this.${changeClassName}Service = ${changeClassName}Service;
}
@Log("导出数据")
@ApiOperation("导出数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('${changeClassName}:list')")
public void download(HttpServletResponse response, ${className}QueryCriteria criteria) throws IOException {
${changeClassName}Service.download(${changeClassName}Service.queryAll(criteria), response);
}
@GetMapping
@Log("查询${className}")
@ApiOperation("查询${className}")
@PreAuthorize("@el.check('${changeClassName}:list')")
public ResponseEntity get${className}s(${className}QueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(${changeClassName}Service.queryAll(criteria,pageable),HttpStatus.OK);
}
@PostMapping
@Log("新增${className}")
@ApiOperation("新增${className}")
@PreAuthorize("@el.check('${changeClassName}:add')")
public ResponseEntity create(@Validated @RequestBody ${className} resources){
return new ResponseEntity<>(${changeClassName}Service.create(resources),HttpStatus.CREATED);
}
@PutMapping
@Log("修改${className}")
@ApiOperation("修改${className}")
@PreAuthorize("@el.check('${changeClassName}:edit')")
public ResponseEntity update(@Validated @RequestBody ${className} resources){
${changeClassName}Service.update(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@DeleteMapping(value = "/{${pkChangeColName}}")
@Log("删除${className}")
@ApiOperation("删除${className}")
@PreAuthorize("@el.check('${changeClassName}:del')")
public ResponseEntity delete(@PathVariable ${pkColumnType} ${pkChangeColName}){
${changeClassName}Service.delete(${pkChangeColName});
return new ResponseEntity(HttpStatus.OK);
}
}
\ No newline at end of file
package ${package}.service.dto;
import lombok.Data;
<#if hasTimestamp>
import java.sql.Timestamp;
</#if>
<#if hasBigDecimal>
import java.math.BigDecimal;
</#if>
import java.io.Serializable;
<#if !auto && pkColumnType = 'Long'>
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
</#if>
/**
* @author ${author}
* @date ${date}
*/
@Data
public class ${className}DTO implements Serializable {
<#if columns??>
<#list columns as column>
<#if column.columnComment != ''>
// ${column.columnComment}
</#if>
<#if column.columnKey = 'PRI'>
<#if !auto && pkColumnType = 'Long'>
// 处理精度丢失问题
@JsonSerialize(using= ToStringSerializer.class)
</#if>
</#if>
private ${column.columnType} ${column.changeColumnName};
</#list>
</#if>
}
\ No newline at end of file
package ${package}.domain;
import lombok.Data;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import javax.persistence.*;
<#if hasTimestamp>
import java.sql.Timestamp;
</#if>
<#if hasBigDecimal>
import java.math.BigDecimal;
</#if>
import java.io.Serializable;
/**
* @author ${author}
* @date ${date}
*/
@Entity
@Data
@Table(name="${tableName}")
public class ${className} implements Serializable {
<#if columns??>
<#list columns as column>
<#if column.columnComment != ''>
// ${column.columnComment}
</#if>
<#if column.columnKey = 'PRI'>
@Id
<#if auto>
@GeneratedValue(strategy = GenerationType.IDENTITY)
</#if>
</#if>
@Column(name = "${column.columnName}"<#if column.columnKey = 'UNI'>,unique = true</#if><#if column.isNullable = 'NO' && column.columnKey != 'PRI'>,nullable = false</#if>)
private ${column.columnType} ${column.changeColumnName};
</#list>
</#if>
public void copy(${className} source){
BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
}
}
\ No newline at end of file
package ${package}.service.mapper;
import me.zhengjie.base.BaseMapper;
import ${package}.domain.${className};
import ${package}.service.dto.${className}DTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author ${author}
* @date ${date}
*/
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface ${className}Mapper extends BaseMapper<${className}DTO, ${className}> {
}
\ No newline at end of file
package ${package}.service.dto;
import lombok.Data;
<#if queryHasTimestamp>
import java.sql.Timestamp;
</#if>
<#if queryHasBigDecimal>
import java.math.BigDecimal;
</#if>
<#if queryColumns??>
import me.zhengjie.annotation.Query;
</#if>
/**
* @author ${author}
* @date ${date}
*/
@Data
public class ${className}QueryCriteria{
<#if queryColumns??>
<#list queryColumns as column>
<#if column.columnQuery = '1'>
// 模糊
@Query(type = Query.Type.INNER_LIKE)
</#if>
<#if column.columnQuery = '2'>
// 精确
@Query
</#if>
private ${column.columnType} ${column.changeColumnName};
</#list>
</#if>
}
\ No newline at end of file
package ${package}.repository;
import ${package}.domain.${className};
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author ${author}
* @date ${date}
*/
public interface ${className}Repository extends JpaRepository<${className}, ${pkColumnType}>, JpaSpecificationExecutor<${className}> {
<#if columns??>
<#list columns as column>
<#if column.columnKey = 'UNI'>
${className} findBy${column.capitalColumnName}(${column.columnType} ${column.columnName});
</#if>
</#list>
</#if>
}
\ No newline at end of file
package ${package}.service;
import ${package}.domain.${className};
import ${package}.service.dto.${className}DTO;
import ${package}.service.dto.${className}QueryCriteria;
import org.springframework.data.domain.Pageable;
import java.util.Map;
import java.util.List;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
/**
* @author ${author}
* @date ${date}
*/
public interface ${className}Service {
/**
* 查询数据分页
* @param criteria 条件参数
* @param pageable 分页参数
* @return Map<String,Object>
*/
Map<String,Object> queryAll(${className}QueryCriteria criteria, Pageable pageable);
/**
* 查询所有数据不分页
* @param criteria 条件参数
* @return List<${className}DTO>
*/
List<${className}DTO> queryAll(${className}QueryCriteria criteria);
/**
* 根据ID查询
* @param ${pkChangeColName} ID
* @return ${className}DTO
*/
${className}DTO findById(${pkColumnType} ${pkChangeColName});
${className}DTO create(${className} resources);
void update(${className} resources);
void delete(${pkColumnType} ${pkChangeColName});
void download(List<${className}DTO> all, HttpServletResponse response) throws IOException;
}
\ No newline at end of file
package ${package}.service.impl;
import ${package}.domain.${className};
<#if columns??>
<#list columns as column>
<#if column.columnKey = 'UNI'>
<#if column_index = 1>
import me.zhengjie.exception.EntityExistException;
</#if>
</#if>
</#list>
</#if>
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.utils.FileUtil;
import ${package}.repository.${className}Repository;
import ${package}.service.${className}Service;
import ${package}.service.dto.${className}DTO;
import ${package}.service.dto.${className}QueryCriteria;
import ${package}.service.mapper.${className}Mapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
<#if !auto && pkColumnType = 'Long'>
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
</#if>
<#if !auto && pkColumnType = 'String'>
import cn.hutool.core.util.IdUtil;
</#if>
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;
import java.util.List;
import java.util.Map;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.LinkedHashMap;
/**
* @author ${author}
* @date ${date}
*/
@Service
@CacheConfig(cacheNames = "${changeClassName}")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class ${className}ServiceImpl implements ${className}Service {
private final ${className}Repository ${changeClassName}Repository;
private final ${className}Mapper ${changeClassName}Mapper;
public ${className}ServiceImpl(${className}Repository ${changeClassName}Repository, ${className}Mapper ${changeClassName}Mapper) {
this.${changeClassName}Repository = ${changeClassName}Repository;
this.${changeClassName}Mapper = ${changeClassName}Mapper;
}
@Override
@Cacheable
public Map<String,Object> queryAll(${className}QueryCriteria criteria, Pageable pageable){
Page<${className}> page = ${changeClassName}Repository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
return PageUtil.toPage(page.map(${changeClassName}Mapper::toDto));
}
@Override
@Cacheable
public List<${className}DTO> queryAll(${className}QueryCriteria criteria){
return ${changeClassName}Mapper.toDto(${changeClassName}Repository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
}
@Override
@Cacheable(key = "#p0")
public ${className}DTO findById(${pkColumnType} ${pkChangeColName}) {
${className} ${changeClassName} = ${changeClassName}Repository.findById(${pkChangeColName}).orElseGet(${className}::new);
ValidationUtil.isNull(${changeClassName}.get${pkCapitalColName}(),"${className}","${pkChangeColName}",${pkChangeColName});
return ${changeClassName}Mapper.toDto(${changeClassName});
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public ${className}DTO create(${className} resources) {
<#if !auto && pkColumnType = 'Long'>
Snowflake snowflake = IdUtil.createSnowflake(1, 1);
resources.set${pkCapitalColName}(snowflake.nextId());
</#if>
<#if !auto && pkColumnType = 'String'>
resources.set${pkCapitalColName}(IdUtil.simpleUUID());
</#if>
<#if columns??>
<#list columns as column>
<#if column.columnKey = 'UNI'>
if(${changeClassName}Repository.findBy${column.capitalColumnName}(resources.get${column.capitalColumnName}()) != null){
throw new EntityExistException(${className}.class,"${column.columnName}",resources.get${column.capitalColumnName}());
}
</#if>
</#list>
</#if>
return ${changeClassName}Mapper.toDto(${changeClassName}Repository.save(resources));
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(${className} resources) {
${className} ${changeClassName} = ${changeClassName}Repository.findById(resources.get${pkCapitalColName}()).orElseGet(${className}::new);
ValidationUtil.isNull( ${changeClassName}.get${pkCapitalColName}(),"${className}","id",resources.get${pkCapitalColName}());
<#if columns??>
<#list columns as column>
<#if column.columnKey = 'UNI'>
<#if column_index = 1>
${className} ${changeClassName}1 = null;
</#if>
${changeClassName}1 = ${changeClassName}Repository.findBy${column.capitalColumnName}(resources.get${column.capitalColumnName}());
if(${changeClassName}1 != null && !${changeClassName}1.get${pkCapitalColName}().equals(${changeClassName}.get${pkCapitalColName}())){
throw new EntityExistException(${className}.class,"${column.columnName}",resources.get${column.capitalColumnName}());
}
</#if>
</#list>
</#if>
${changeClassName}.copy(resources);
${changeClassName}Repository.save(${changeClassName});
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(${pkColumnType} ${pkChangeColName}) {
${changeClassName}Repository.deleteById(${pkChangeColName});
}
@Override
public void download(List<${className}DTO> all, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (${className}DTO ${changeClassName} : all) {
Map<String,Object> map = new LinkedHashMap<>();
<#list columns as column>
<#if column.columnKey != 'PRI'>
<#if column.columnComment != ''>
map.put("${column.columnComment}", ${changeClassName}.get${column.capitalColumnName}());
<#else>
map.put(" ${column.changeColumnName}", ${changeClassName}.get${column.capitalColumnName}());
</#if>
</#if>
</#list>
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
\ No newline at end of file
import request from '@/utils/request'
export function add(data) {
return request({
url: 'api/${changeClassName}',
method: 'post',
data
})
}
export function del(${pkChangeColName}) {
return request({
url: 'api/${changeClassName}/' + ${pkChangeColName},
method: 'delete'
})
}
export function edit(data) {
return request({
url: 'api/${changeClassName}',
method: 'put',
data
})
}
export function download${className}(params) {
return request({
url: 'api/${changeClassName}/download',
method: 'get',
params,
responseType: 'blob'
})
}
<template>
<el-dialog :append-to-body="true" :close-on-click-modal="false" :before-close="cancel" :visible.sync="dialog" :title="isAdd ? '新增' : '编辑'" width="500px">
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="80px">
<#if columns??>
<#list columns as column>
<#if column.changeColumnName != '${pkChangeColName}'>
<el-form-item label="<#if column.columnComment != ''>${column.columnComment}<#else>${column.changeColumnName}</#if>" <#if column.columnKey = 'UNI'>prop="${column.changeColumnName}"</#if>>
<#if column.columnType != 'Timestamp'>
<el-input v-model="form.${column.changeColumnName}" style="width: 370px;"/>
<#else >
<el-date-picker v-model="form.${column.changeColumnName}" type="datetime" style="width: 370px;"/>
</#if>
</el-form-item>
</#if>
</#list>
</#if>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="cancel">取消</el-button>
<el-button :loading="loading" type="primary" @click="doSubmit">确认</el-button>
</div>
</el-dialog>
</template>
<script>
import { add, edit } from '@/api/${changeClassName}'
export default {
props: {
isAdd: {
type: Boolean,
required: true
}
},
data() {
return {
loading: false, dialog: false,
form: {
<#if columns??>
<#list columns as column>
${column.changeColumnName}: ''<#if column_has_next>,</#if>
</#list>
</#if>
},
rules: {
<#list columns as column>
<#if column.columnKey = 'UNI'>
${column.changeColumnName}: [
{ required: true, message: 'please enter', trigger: 'blur' }
]<#if (column_has_next)>,</#if>
</#if>
</#list>
}
}
},
methods: {
cancel() {
this.resetForm()
},
doSubmit() {
this.loading = true
if (this.isAdd) {
this.doAdd()
} else this.doEdit()
},
doAdd() {
add(this.form).then(res => {
this.resetForm()
this.$notify({
title: '添加成功',
type: 'success',
duration: 2500
})
this.loading = false
this.$parent.init()
}).catch(err => {
this.loading = false
console.log(err.response.data.message)
})
},
doEdit() {
edit(this.form).then(res => {
this.resetForm()
this.$notify({
title: '修改成功',
type: 'success',
duration: 2500
})
this.loading = false
this.$parent.init()
}).catch(err => {
this.loading = false
console.log(err.response.data.message)
})
},
resetForm() {
this.dialog = false
this.$refs['form'].resetFields()
this.form = {
<#if columns??>
<#list columns as column>
${column.changeColumnName}: ''<#if column_has_next>,</#if>
</#list>
</#if>
}
}
}
}
</script>
<style scoped>
</style>
<#--noinspection ALL-->
<template>
<div class="app-container">
<!--工具栏-->
<div class="head-container">
<#if hasQuery>
<!-- 搜索 -->
<el-input v-model="query.value" clearable placeholder="输入搜索内容" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-select v-model="query.type" clearable placeholder="类型" class="filter-item" style="width: 130px">
<el-option v-for="item in queryTypeOptions" :key="item.key" :label="item.display_name" :value="item.key"/>
</el-select>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
</#if>
<!-- 新增 -->
<div style="display: inline-block;margin: 0px 2px;">
<el-button
v-permission="['admin','${changeClassName}:add']"
class="filter-item"
size="mini"
type="primary"
icon="el-icon-plus"
@click="add">新增</el-button>
</div>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-download"
@click="download">导出</el-button>
</div>
</div>
<!--表单组件-->
<eForm ref="form" :is-add="isAdd"/>
<!--表格渲染-->
<el-table v-loading="loading" :data="data" size="small" style="width: 100%;">
<#if columns??>
<#list columns as column>
<#if column.columnShow = 'true'>
<#if column.columnType != 'Timestamp'>
<el-table-column prop="${column.changeColumnName}" label="<#if column.columnComment != ''>${column.columnComment}<#else>${column.changeColumnName}</#if>"/>
<#else>
<el-table-column prop="${column.changeColumnName}" label="<#if column.columnComment != ''>${column.columnComment}<#else>${column.changeColumnName}</#if>">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.${column.changeColumnName}) }}</span>
</template>
</el-table-column>
</#if>
</#if>
</#list>
</#if>
<el-table-column v-if="checkPermission(['admin','${changeClassName}:edit','${changeClassName}:del'])" label="操作" width="150px" align="center">
<template slot-scope="scope">
<el-button v-permission="['admin','${changeClassName}:edit']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-popover
v-permission="['admin','${changeClassName}:del']"
:ref="scope.row.${pkChangeColName}"
placement="top"
width="180">
<p>确定删除本条数据吗?</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="$refs[scope.row.${pkChangeColName}].doClose()">取消</el-button>
<el-button :loading="delLoading" type="primary" size="mini" @click="subDelete(scope.row.${pkChangeColName})">确定</el-button>
</div>
<el-button slot="reference" type="danger" icon="el-icon-delete" size="mini"/>
</el-popover>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<el-pagination
:total="total"
:current-page="page + 1"
style="margin-top: 8px;"
layout="total, prev, pager, next, sizes"
@size-change="sizeChange"
@current-change="pageChange"/>
</div>
</template>
<script>
import checkPermission from '@/utils/permission'
import initData from '@/mixins/initData'
import { del, download${className} } from '@/api/${changeClassName}'
<#if hasTimestamp>
import { parseTime, downloadFile } from '@/utils/index'
</#if>
import eForm from './form'
export default {
components: { eForm },
mixins: [initData],
data() {
return {
delLoading: false,
<#if hasQuery>
queryTypeOptions: [
<#if queryColumns??>
<#list queryColumns as column>
{ key: '${column.changeColumnName}', display_name: '<#if column.columnComment != ''>${column.columnComment}<#else>${column.changeColumnName}</#if>' }<#if column_has_next>,</#if>
</#list>
</#if>
]
</#if>
}
},
created() {
this.$nextTick(() => {
this.init()
})
},
methods: {
<#if hasTimestamp>
parseTime,
</#if>
checkPermission,
beforeInit() {
this.url = 'api/${changeClassName}'
const sort = '${pkChangeColName},desc'
this.params = { page: this.page, size: this.size, sort: sort }
<#if hasQuery>
const query = this.query
const type = query.type
const value = query.value
if (type && value) { this.params[type] = value }
</#if>
return true
},
subDelete(${pkChangeColName}) {
this.delLoading = true
del(${pkChangeColName}).then(res => {
this.delLoading = false
this.$refs[${pkChangeColName}].doClose()
this.dleChangePage()
this.init()
this.$notify({
title: '删除成功',
type: 'success',
duration: 2500
})
}).catch(err => {
this.delLoading = false
this.$refs[${pkChangeColName}].doClose()
console.log(err.response.data.message)
})
},
add() {
this.isAdd = true
this.$refs.form.dialog = true
},
edit(data) {
this.isAdd = false
const _this = this.$refs.form
_this.form = {
<#if columns??>
<#list columns as column>
${column.changeColumnName}: data.${column.changeColumnName}<#if column_has_next>,</#if>
</#list>
</#if>
}
_this.dialog = true
},
// 导出
download() {
this.beforeInit()
this.downloadLoading = true
download${className}(this.params).then(result => {
downloadFile(result, '${className}列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
</script>
<style scoped>
</style>
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
<bpmn2:process id="process${id}" name="${name}">
<bpmn2:documentation>${description}</bpmn2:documentation>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="process${id}" />
</bpmndi:BPMNDiagram>
</bpmn2:definitions>
\ No newline at end of file
package me.zhengjie;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class EladminSystemApplicationTests {
@Test
public void contextLoads() {
}
}
<?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>eladmin</artifactId>
<groupId>me.zhengjie</groupId>
<version>2.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eladmin-tools</artifactId>
<name>工具模块</name>
<properties>
<mail.version>1.4.7</mail.version>
<qiniu.version>[7.2.0, 7.2.99]</qiniu.version>
<alipay.version>3.1.0</alipay.version>
</properties>
<dependencies>
<!-- 同时需要common模块和logging模块只需要引入logging模块即可 -->
<dependency>
<groupId>me.zhengjie</groupId>
<artifactId>eladmin-logging</artifactId>
<version>2.3</version>
</dependency>
<!--邮件依赖-->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>${mail.version}</version>
</dependency>
<!--七牛云存储-->
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>${qiniu.version}</version>
</dependency>
<!--支付宝依赖-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>${alipay.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package me.zhengjie.config;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.MultipartConfigElement;
import java.io.File;
/**
* @date 2018-12-28
* @author https://blog.csdn.net/llibin1024530411/article/details/79474953
*/
@Configuration
public class MultipartConfig {
/**
* 文件上传临时路径
*/
@Bean
MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
String location = System.getProperty("user.home") + "/.eladmin/file/tmp";
File tmpFile = new File(location);
if (!tmpFile.exists()) {
tmpFile.mkdirs();
}
factory.setLocation(location);
return factory.createMultipartConfig();
}
}
\ No newline at end of file
package me.zhengjie.domain;
import lombok.Data;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* 支付宝配置类
* @author Zheng Jie
* @date 2018-12-31
*/
@Data
@Entity
@Table(name = "alipay_config")
public class AlipayConfig implements Serializable {
@Id
private Long id;
// 应用ID,APPID,收款账号既是APPID对应支付宝账号
@NotBlank
@Column(name = "app_id")
private String appID;
// 商户私钥,您的PKCS8格式RSA2私钥
@NotBlank
@Column(name = "private_key", columnDefinition = "text")
private String privateKey;
// 支付宝公钥
@NotBlank
@Column(name = "public_key", columnDefinition = "text")
private String publicKey;
// 签名方式,固定格式
@Column(name = "sign_type")
private String signType="RSA2";
// 支付宝开放安全地址,一般不会变
@Column(name = "gateway_url")
private String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
// 编码,固定格式
private String charset= "utf-8";
// 异步通知地址
@NotBlank
@Column(name = "notify_url")
private String notifyUrl;
// 订单完成后返回的页面
@NotBlank
@Column(name = "return_url")
private String returnUrl;
// 类型,固定格式
private String format="JSON";
// 商户号
@NotBlank
@Column(name = "sys_service_provider_id")
private String sysServiceProviderId;
}
package me.zhengjie.domain;
import lombok.Data;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* 邮件配置类,数据存覆盖式存入数据存
* @author Zheng Jie
* @date 2018-12-26
*/
@Entity
@Data
@Table(name = "email_config")
public class EmailConfig implements Serializable {
@Id
private Long id;
// 邮件服务器SMTP地址
@NotBlank
private String host;
// 邮件服务器SMTP端口
@NotBlank
private String port;
// 发件者用户名,默认为发件人邮箱前缀
@NotBlank
private String user;
@NotBlank
private String pass;
// 收件人
@NotBlank
@Column(name = "from_user")
private String fromUser;
}
package me.zhengjie.domain;
import lombok.*;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import me.zhengjie.base.BaseEntity;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-09-05
*/
@Getter
@Setter
@Entity
@Table(name="local_storage")
@NoArgsConstructor
public class LocalStorage implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
// 真实文件名
@Column(name = "real_name")
private String realName;
// 文件名
@Column(name = "name")
private String name;
// 后缀
@Column(name = "suffix")
private String suffix;
// 路径
@Column(name = "path")
private String path;
// 类型
@Column(name = "type")
private String type;
// 大小
@Column(name = "size")
private String size;
// 操作人
@Column(name = "operate")
private String operate;
@Column(name = "create_time")
@CreationTimestamp
private Timestamp createTime;
public LocalStorage(String realName,String name, String suffix, String path, String type, String size, String operate) {
this.realName = realName;
this.name = name;
this.suffix = suffix;
this.path = path;
this.type = type;
this.size = size;
this.operate = operate;
}
public void copy(LocalStorage source){
BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
}
}
\ No newline at end of file
package me.zhengjie.domain;
import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* sm.ms图床
*
* @author Zheng Jie
* @date 2018-12-27
*/
@Data
@Entity
@Table(name = "picture")
public class Picture implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String filename;
private String url;
private String size;
private String height;
private String width;
@Column(name = "delete_url")
private String delete;
private String username;
@CreationTimestamp
@Column(name = "create_time")
private Timestamp createTime;
// 用于检测文件是否重复
private String md5Code;
@Override
public String toString() {
return "Picture{" +
"filename='" + filename + '\'' +
'}';
}
}
package me.zhengjie.domain;
import lombok.Data;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* 七牛云对象存储配置类
* @author Zheng Jie
* @date 2018-12-31
*/
@Data
@Entity
@Table(name = "qiniu_config")
public class QiniuConfig implements Serializable {
@Id
private Long id;
// 一个账号最多拥有两对密钥(Access/Secret Key)
@NotBlank
@Column(name = "access_key", columnDefinition = "text")
private String accessKey;
// 一个账号最多拥有两对密钥(Access/Secret Key)
@NotBlank
@Column(name = "secret_key", columnDefinition = "text")
private String secretKey;
// 存储空间名称作为唯一的 Bucket 识别符
@NotBlank
private String bucket;
/**
* Zone表示与机房的对应关系
* 华东 Zone.zone0()
* 华北 Zone.zone1()
* 华南 Zone.zone2()
* 北美 Zone.zoneNa0()
* 东南亚 Zone.zoneAs0()
*/
@NotBlank
private String zone;
// 外链域名,可自定义,需在七牛云绑定
@NotBlank
private String host;
// 空间类型:公开/私有
private String type = "公开";
}
package me.zhengjie.domain;
import lombok.Data;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* 上传成功后,存储结果
* @author Zheng Jie
* @date 2018-12-31
*/
@Data
@Entity
@Table(name = "qiniu_content")
public class QiniuContent implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 文件名
@Column(name = "name")
private String key;
// 空间名
private String bucket;
// 大小
private String size;
// 文件地址
private String url;
private String suffix;
// 空间类型:公开/私有
private String type = "公开";
// 更新时间
@UpdateTimestamp
@Column(name = "update_time")
private Timestamp updateTime;
}
package me.zhengjie.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2018-12-26
*/
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "verification_code")
public class VerificationCode implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String code;
// 使用场景,自己定义
private String scenes;
// true 为有效,false 为无效,验证时状态+时间+具体的邮箱或者手机号
private Boolean status = true;
// 类型 :phone 和 email
@NotBlank
private String type;
// 具体的phone与email
@NotBlank
private String value;
// 创建日期
@CreationTimestamp
@Column(name = "create_time")
private Timestamp createTime;
public VerificationCode(String code, String scenes, @NotBlank String type, @NotBlank String value) {
this.code = code;
this.scenes = scenes;
this.type = type;
this.value = value;
}
}
package me.zhengjie.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.util.List;
/**
* 发送邮件时,接收参数的类
* @author 郑杰
* @date 2018/09/28 12:02:14
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class EmailVo {
// 收件人,支持多个收件人,用逗号分隔
@NotEmpty
private List<String> tos;
@NotBlank
private String subject;
@NotBlank
private String content;
}
package me.zhengjie.domain.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.sql.Date;
import java.sql.Timestamp;
/**
* 交易详情,按需应该存入数据库,这里存入数据库,仅供临时测试
* @author Zheng Jie
* @date 2018-12-31
*/
@Data
public class TradeVo {
// (必填)商品描述
@NotBlank
private String body;
// (必填)商品名称
@NotBlank
private String subject;
// (必填)商户订单号,应该由后台生成
@ApiModelProperty(hidden = true)
private String outTradeNo;
// (必填)第三方订单号
@ApiModelProperty(hidden = true)
private String tradeNo;
// (必填)价格
@NotBlank
private String totalAmount;
// 订单状态,已支付,未支付,作废
@ApiModelProperty(hidden = true)
private String state;
// 创建时间,存入数据库时需要
@ApiModelProperty(hidden = true)
private Timestamp createTime;
// 作废时间,存入数据库时需要
@ApiModelProperty(hidden = true)
private Date cancelTime;
}
package me.zhengjie.repository;
import me.zhengjie.domain.AlipayConfig;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author Zheng Jie
* @date 2018-12-31
*/
public interface AlipayRepository extends JpaRepository<AlipayConfig,Long> {
}
package me.zhengjie.repository;
import me.zhengjie.domain.EmailConfig;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author Zheng Jie
* @date 2018-12-26
*/
public interface EmailRepository extends JpaRepository<EmailConfig,Long> {
}
package me.zhengjie.repository;
import me.zhengjie.domain.LocalStorage;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author Zheng Jie
* @date 2019-09-05
*/
public interface LocalStorageRepository extends JpaRepository<LocalStorage, Long>, JpaSpecificationExecutor<LocalStorage> {
}
\ No newline at end of file
package me.zhengjie.repository;
import me.zhengjie.domain.Picture;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author Zheng Jie
* @date 2018-12-27
*/
public interface PictureRepository extends JpaRepository<Picture,Long>, JpaSpecificationExecutor<Picture> {
Picture findByMd5Code(String code);
}
package me.zhengjie.repository;
import me.zhengjie.domain.QiniuConfig;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
/**
* @author Zheng Jie
* @date 2018-12-31
*/
public interface QiNiuConfigRepository extends JpaRepository<QiniuConfig,Long> {
@Modifying
@Query(value = "update QiniuConfig set type = ?1")
void update(String type);
}
package me.zhengjie.repository;
import me.zhengjie.domain.QiniuContent;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author Zheng Jie
* @date 2018-12-31
*/
public interface QiniuContentRepository extends JpaRepository<QiniuContent,Long>, JpaSpecificationExecutor<QiniuContent> {
/**
* 根据key查询
* @param key 文件名
* @return QiniuContent
*/
QiniuContent findByKey(String key);
}
package me.zhengjie.repository;
import me.zhengjie.domain.VerificationCode;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author Zheng Jie
* @date 2018-12-26
*/
public interface VerificationCodeRepository extends JpaRepository<VerificationCode, Long> {
/**
* 获取有效的验证码
* @param scenes 业务场景,如重置密码,重置邮箱等等
* @param type 类型
* @param value 值
* @return VerificationCode
*/
VerificationCode findByScenesAndTypeAndValueAndStatusIsTrue(String scenes, String type, String value);
}
package me.zhengjie.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.aop.log.Log;
import me.zhengjie.domain.AlipayConfig;
import me.zhengjie.domain.vo.TradeVo;
import me.zhengjie.service.AlipayService;
import me.zhengjie.utils.AliPayStatusEnum;
import me.zhengjie.utils.AlipayUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.Map;
/**
* @author Zheng Jie
* @date 2018-12-31
*/
@Slf4j
@RestController
@RequestMapping("/api/aliPay")
@Api(tags = "工具:支付宝管理")
public class AliPayController {
private final AlipayUtils alipayUtils;
private final AlipayService alipayService;
public AliPayController(AlipayUtils alipayUtils, AlipayService alipayService) {
this.alipayUtils = alipayUtils;
this.alipayService = alipayService;
}
@GetMapping
public ResponseEntity<AlipayConfig> get(){
return new ResponseEntity<>(alipayService.find(),HttpStatus.OK);
}
@Log("配置支付宝")
@ApiOperation("配置支付宝")
@PutMapping
public ResponseEntity payConfig(@Validated @RequestBody AlipayConfig alipayConfig){
alipayConfig.setId(1L);
alipayService.update(alipayConfig);
return new ResponseEntity(HttpStatus.OK);
}
@Log("支付宝PC网页支付")
@ApiOperation("PC网页支付")
@PostMapping(value = "/toPayAsPC")
public ResponseEntity<String> toPayAsPC(@Validated@RequestBody TradeVo trade) throws Exception{
AlipayConfig alipay = alipayService.find();
trade.setOutTradeNo(alipayUtils.getOrderCode());
String payUrl = alipayService.toPayAsPC(alipay,trade);
return ResponseEntity.ok(payUrl);
}
@Log("支付宝手机网页支付")
@ApiOperation("手机网页支付")
@PostMapping(value = "/toPayAsWeb")
public ResponseEntity<String> toPayAsWeb(@Validated @RequestBody TradeVo trade) throws Exception{
AlipayConfig alipay = alipayService.find();
trade.setOutTradeNo(alipayUtils.getOrderCode());
String payUrl = alipayService.toPayAsWeb(alipay,trade);
return ResponseEntity.ok(payUrl);
}
@ApiIgnore
@GetMapping("/return")
@AnonymousAccess
@ApiOperation("支付之后跳转的链接")
public ResponseEntity<String> returnPage(HttpServletRequest request, HttpServletResponse response){
AlipayConfig alipay = alipayService.find();
response.setContentType("text/html;charset=" + alipay.getCharset());
//内容验签,防止黑客篡改参数
if(alipayUtils.rsaCheck(request,alipay)){
//商户订单号
String outTradeNo = new String(request.getParameter("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
//支付宝交易号
String tradeNo = new String(request.getParameter("trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
System.out.println("商户订单号"+outTradeNo+" "+"第三方交易号"+tradeNo);
// 根据业务需要返回数据,这里统一返回OK
return new ResponseEntity<>("payment successful",HttpStatus.OK);
}else{
// 根据业务需要返回数据
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
@ApiIgnore
@RequestMapping("/notify")
@AnonymousAccess
@ApiOperation("支付异步通知(要公网访问),接收异步通知,检查通知内容app_id、out_trade_no、total_amount是否与请求中的一致,根据trade_status进行后续业务处理")
public ResponseEntity notify(HttpServletRequest request){
AlipayConfig alipay = alipayService.find();
Map<String, String[]> parameterMap = request.getParameterMap();
//内容验签,防止黑客篡改参数
if (alipayUtils.rsaCheck(request,alipay)) {
//交易状态
String tradeStatus = new String(request.getParameter("trade_status").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
// 商户订单号
String outTradeNo = new String(request.getParameter("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
//支付宝交易号
String tradeNo = new String(request.getParameter("trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
//付款金额
String totalAmount = new String(request.getParameter("total_amount").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
//验证
if(tradeStatus.equals(AliPayStatusEnum.SUCCESS.getValue())||tradeStatus.equals(AliPayStatusEnum.FINISHED.getValue())){
// 验证通过后应该根据业务需要处理订单
}
return new ResponseEntity(HttpStatus.OK);
}
return new ResponseEntity(HttpStatus.BAD_REQUEST);
}
}
package me.zhengjie.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.domain.EmailConfig;
import me.zhengjie.domain.vo.EmailVo;
import me.zhengjie.service.EmailService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 发送邮件
* @author 郑杰
* @date 2018/09/28 6:55:53
*/
@RestController
@RequestMapping("api/email")
@Api(tags = "工具:邮件管理")
public class EmailController {
private final EmailService emailService;
public EmailController(EmailService emailService) {
this.emailService = emailService;
}
@GetMapping
public ResponseEntity get(){
return new ResponseEntity<>(emailService.find(),HttpStatus.OK);
}
@Log("配置邮件")
@PutMapping
@ApiOperation("配置邮件")
public ResponseEntity emailConfig(@Validated @RequestBody EmailConfig emailConfig){
emailService.update(emailConfig,emailService.find());
return new ResponseEntity(HttpStatus.OK);
}
@Log("发送邮件")
@PostMapping
@ApiOperation("发送邮件")
public ResponseEntity send(@Validated @RequestBody EmailVo emailVo) throws Exception {
emailService.send(emailVo,emailService.find());
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.rest;
import me.zhengjie.aop.log.Log;
import me.zhengjie.domain.LocalStorage;
import me.zhengjie.service.LocalStorageService;
import me.zhengjie.service.dto.LocalStorageQueryCriteria;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Zheng Jie
* @date 2019-09-05
*/
@Api(tags = "工具:本地存储管理")
@RestController
@RequestMapping("/api/localStorage")
public class LocalStorageController {
private final LocalStorageService localStorageService;
public LocalStorageController(LocalStorageService localStorageService) {
this.localStorageService = localStorageService;
}
@ApiOperation("查询文件")
@GetMapping
@PreAuthorize("@el.check('storage:list')")
public ResponseEntity getLocalStorages(LocalStorageQueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(localStorageService.queryAll(criteria,pageable),HttpStatus.OK);
}
@Log("导出数据")
@ApiOperation("导出数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('storage:list')")
public void download(HttpServletResponse response, LocalStorageQueryCriteria criteria) throws IOException {
localStorageService.download(localStorageService.queryAll(criteria), response);
}
@ApiOperation("上传文件")
@PostMapping
@PreAuthorize("@el.check('storage:add')")
public ResponseEntity create(@RequestParam String name, @RequestParam("file") MultipartFile file){
return new ResponseEntity<>(localStorageService.create(name, file),HttpStatus.CREATED);
}
@ApiOperation("修改文件")
@PutMapping
@PreAuthorize("@el.check('storage:edit')")
public ResponseEntity update(@Validated @RequestBody LocalStorage resources){
localStorageService.update(resources);
return new ResponseEntity(HttpStatus.NO_CONTENT);
}
@ApiOperation("删除文件")
@DeleteMapping(value = "/{id}")
@PreAuthorize("@el.check('storage:del')")
public ResponseEntity delete(@PathVariable Long id){
localStorageService.delete(id);
return new ResponseEntity(HttpStatus.OK);
}
@Log("多选删除")
@DeleteMapping
@ApiOperation("多选删除")
public ResponseEntity deleteAll(@RequestBody Long[] ids) {
localStorageService.deleteAll(ids);
return new ResponseEntity(HttpStatus.OK);
}
}
\ No newline at end of file
package me.zhengjie.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.aop.log.Log;
import me.zhengjie.domain.Picture;
import me.zhengjie.service.PictureService;
import me.zhengjie.service.dto.PictureQueryCriteria;
import me.zhengjie.utils.SecurityUtils;
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 org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author 郑杰
* @date 2018/09/20 14:13:32
*/
@RestController
@RequestMapping("/api/pictures")
@Api(tags = "工具:免费图床管理")
public class PictureController {
private final PictureService pictureService;
public PictureController(PictureService pictureService) {
this.pictureService = pictureService;
}
@Log("查询图片")
@PreAuthorize("@el.check('pictures:list')")
@GetMapping
@ApiOperation("查询图片")
public ResponseEntity getRoles(PictureQueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(pictureService.queryAll(criteria,pageable),HttpStatus.OK);
}
@Log("导出数据")
@ApiOperation("导出数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('pictures:list')")
public void download(HttpServletResponse response, PictureQueryCriteria criteria) throws IOException {
pictureService.download(pictureService.queryAll(criteria), response);
}
@Log("上传图片")
@PreAuthorize("@el.check('pictures:add')")
@PostMapping
@ApiOperation("上传图片")
public ResponseEntity upload(@RequestParam MultipartFile file){
String userName = SecurityUtils.getUsername();
Picture picture = pictureService.upload(file,userName);
Map<String,Object> map = new HashMap<>(3);
map.put("errno",0);
map.put("id",picture.getId());
map.put("data",new String[]{picture.getUrl()});
return new ResponseEntity<>(map,HttpStatus.OK);
}
@Log("删除图片")
@ApiOperation("删除图片")
@PreAuthorize("@el.check('pictures:del')")
@DeleteMapping(value = "/{id}")
public ResponseEntity delete(@PathVariable Long id) {
pictureService.delete(pictureService.findById(id));
return new ResponseEntity(HttpStatus.OK);
}
@Log("多选删除图片")
@ApiOperation("多选删除图片")
@PreAuthorize("@el.check('pictures:del')")
@DeleteMapping
public ResponseEntity deleteAll(@RequestBody Long[] ids) {
pictureService.deleteAll(ids);
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.aop.log.Log;
import me.zhengjie.domain.QiniuConfig;
import me.zhengjie.domain.QiniuContent;
import me.zhengjie.service.QiNiuService;
import me.zhengjie.service.dto.QiniuQueryCriteria;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 发送邮件
* @author 郑杰
* @date 2018/09/28 6:55:53
*/
@Slf4j
@RestController
@RequestMapping("/api/qiNiuContent")
@Api(tags = "工具:七牛云存储管理")
public class QiniuController {
private final QiNiuService qiNiuService;
public QiniuController(QiNiuService qiNiuService) {
this.qiNiuService = qiNiuService;
}
@GetMapping(value = "/config")
public ResponseEntity get(){
return new ResponseEntity<>(qiNiuService.find(), HttpStatus.OK);
}
@Log("配置七牛云存储")
@ApiOperation("配置七牛云存储")
@PutMapping(value = "/config")
public ResponseEntity emailConfig(@Validated @RequestBody QiniuConfig qiniuConfig){
qiNiuService.update(qiniuConfig);
qiNiuService.update(qiniuConfig.getType());
return new ResponseEntity(HttpStatus.OK);
}
@Log("导出数据")
@ApiOperation("导出数据")
@GetMapping(value = "/download/list")
public void download(HttpServletResponse response, QiniuQueryCriteria criteria) throws IOException {
qiNiuService.downloadList(qiNiuService.queryAll(criteria), response);
}
@Log("查询文件")
@ApiOperation("查询文件")
@GetMapping
public ResponseEntity getRoles(QiniuQueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(qiNiuService.queryAll(criteria,pageable),HttpStatus.OK);
}
@Log("上传文件")
@ApiOperation("上传文件")
@PostMapping
public ResponseEntity upload(@RequestParam MultipartFile file){
QiniuContent qiniuContent = qiNiuService.upload(file,qiNiuService.find());
Map<String,Object> map = new HashMap<>(3);
map.put("id",qiniuContent.getId());
map.put("errno",0);
map.put("data",new String[]{qiniuContent.getUrl()});
return new ResponseEntity<>(map,HttpStatus.OK);
}
@Log("同步七牛云数据")
@ApiOperation("同步七牛云数据")
@PostMapping(value = "/synchronize")
public ResponseEntity synchronize(){
qiNiuService.synchronize(qiNiuService.find());
return new ResponseEntity(HttpStatus.OK);
}
@Log("下载文件")
@ApiOperation("下载文件")
@GetMapping(value = "/download/{id}")
public ResponseEntity download(@PathVariable Long id){
Map<String,Object> map = new HashMap<>(1);
map.put("url", qiNiuService.download(qiNiuService.findByContentId(id),qiNiuService.find()));
return new ResponseEntity<>(map,HttpStatus.OK);
}
@Log("删除文件")
@ApiOperation("删除文件")
@DeleteMapping(value = "/{id}")
public ResponseEntity delete(@PathVariable Long id){
qiNiuService.delete(qiNiuService.findByContentId(id),qiNiuService.find());
return new ResponseEntity(HttpStatus.OK);
}
@Log("删除多张图片")
@ApiOperation("删除多张图片")
@DeleteMapping
public ResponseEntity deleteAll(@RequestBody Long[] ids) {
qiNiuService.deleteAll(ids, qiNiuService.find());
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.rest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhengjie.domain.VerificationCode;
import me.zhengjie.domain.vo.EmailVo;
import me.zhengjie.service.EmailService;
import me.zhengjie.service.VerificationCodeService;
import me.zhengjie.utils.ElAdminConstant;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/**
* @author Zheng Jie
* @date 2018-12-26
*/
@RestController
@RequestMapping("/api/code")
@Api(tags = "工具:验证码管理")
public class VerificationCodeController {
private final VerificationCodeService verificationCodeService;
private final EmailService emailService;
public VerificationCodeController(VerificationCodeService verificationCodeService, EmailService emailService) {
this.verificationCodeService = verificationCodeService;
this.emailService = emailService;
}
@PostMapping(value = "/resetEmail")
@ApiOperation("重置邮箱,发送验证码")
public ResponseEntity resetEmail(@RequestBody VerificationCode code) throws Exception {
code.setScenes(ElAdminConstant.RESET_MAIL);
EmailVo emailVo = verificationCodeService.sendEmail(code);
emailService.send(emailVo,emailService.find());
return new ResponseEntity(HttpStatus.OK);
}
@PostMapping(value = "/email/resetPass")
@ApiOperation("重置密码,发送验证码")
public ResponseEntity resetPass(@RequestParam String email) throws Exception {
VerificationCode code = new VerificationCode();
code.setType("email");
code.setValue(email);
code.setScenes(ElAdminConstant.RESET_MAIL);
EmailVo emailVo = verificationCodeService.sendEmail(code);
emailService.send(emailVo,emailService.find());
return new ResponseEntity(HttpStatus.OK);
}
@GetMapping(value = "/validated")
@ApiOperation("验证码验证")
public ResponseEntity validated(VerificationCode code){
verificationCodeService.validated(code);
return new ResponseEntity(HttpStatus.OK);
}
}
package me.zhengjie.service;
import me.zhengjie.domain.AlipayConfig;
import me.zhengjie.domain.vo.TradeVo;
/**
* @author Zheng Jie
* @date 2018-12-31
*/
public interface AlipayService {
/**
* 处理来自PC的交易请求
* @param alipay 支付宝配置
* @param trade 交易详情
* @return String
* @throws Exception 异常
*/
String toPayAsPC(AlipayConfig alipay, TradeVo trade) throws Exception;
/**
* 处理来自手机网页的交易请求
* @param alipay 支付宝配置
* @param trade 交易详情
* @return String
* @throws Exception 异常
*/
String toPayAsWeb(AlipayConfig alipay, TradeVo trade) throws Exception;
/**
* 查询配置
* @return AlipayConfig
*/
AlipayConfig find();
/**
* 更新配置
* @param alipayConfig 支付宝配置
* @return AlipayConfig
*/
AlipayConfig update(AlipayConfig alipayConfig);
}
package me.zhengjie.service;
import me.zhengjie.domain.EmailConfig;
import me.zhengjie.domain.vo.EmailVo;
import org.springframework.scheduling.annotation.Async;
/**
* @author Zheng Jie
* @date 2018-12-26
*/
public interface EmailService {
/**
* 更新邮件配置
* @param emailConfig 邮件配置
* @param old 旧的配置
* @return EmailConfig
*/
EmailConfig update(EmailConfig emailConfig, EmailConfig old);
/**
* 查询配置
* @return EmailConfig 邮件配置
*/
EmailConfig find();
/**
* 发送邮件
* @param emailVo 邮件发送的内容
* @param emailConfig 邮件配置
* @throws Exception /
*/
@Async
void send(EmailVo emailVo, EmailConfig emailConfig) throws Exception;
}
package me.zhengjie.service;
import me.zhengjie.domain.LocalStorage;
import me.zhengjie.service.dto.LocalStorageDTO;
import me.zhengjie.service.dto.LocalStorageQueryCriteria;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @author Zheng Jie
* @date 2019-09-05
*/
public interface LocalStorageService {
Object queryAll(LocalStorageQueryCriteria criteria, Pageable pageable);
List<LocalStorageDTO> queryAll(LocalStorageQueryCriteria criteria);
LocalStorageDTO findById(Long id);
LocalStorageDTO create(String name, MultipartFile file);
void update(LocalStorage resources);
void delete(Long id);
void deleteAll(Long[] ids);
void download(List<LocalStorageDTO> queryAll, HttpServletResponse response) throws IOException;
}
\ No newline at end of file
package me.zhengjie.service;
import me.zhengjie.domain.Picture;
import me.zhengjie.service.dto.PictureQueryCriteria;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @author Zheng Jie
* @date 2018-12-27
*/
public interface PictureService {
Object queryAll(PictureQueryCriteria criteria, Pageable pageable);
List<Picture> queryAll(PictureQueryCriteria criteria);
Picture upload(MultipartFile file, String username);
Picture findById(Long id);
void delete(Picture picture);
void deleteAll(Long[] ids);
void download(List<Picture> queryAll, HttpServletResponse response) throws IOException;
}
package me.zhengjie.service;
import me.zhengjie.domain.QiniuConfig;
import me.zhengjie.domain.QiniuContent;
import me.zhengjie.service.dto.QiniuQueryCriteria;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
* @author Zheng Jie
* @date 2018-12-31
*/
public interface QiNiuService {
Object queryAll(QiniuQueryCriteria criteria, Pageable pageable);
List<QiniuContent> queryAll(QiniuQueryCriteria criteria);
/**
* 查配置
* @return Cacheable
*/
QiniuConfig find();
/**
* 修改配置
* @param qiniuConfig 配置
* @return QiniuConfig
*/
QiniuConfig update(QiniuConfig qiniuConfig);
/**
* 上传文件
* @param file 文件
* @param qiniuConfig 配置
* @return QiniuContent
*/
QiniuContent upload(MultipartFile file, QiniuConfig qiniuConfig);
/**
* 查询文件
* @param id 文件ID
* @return QiniuContent
*/
QiniuContent findByContentId(Long id);
/**
* 下载文件
* @param content 文件信息
* @param config 配置
* @return String
*/
String download(QiniuContent content, QiniuConfig config);
/**
* 删除文件
* @param content 文件
* @param config 配置
*/
void delete(QiniuContent content, QiniuConfig config);
/**
* 同步数据
* @param config 配置
*/
void synchronize(QiniuConfig config);
/**
* 删除文件
* @param ids 文件ID数组
* @param config 配置
*/
void deleteAll(Long[] ids, QiniuConfig config);
/**
* 更新数据
* @param type 类型
*/
void update(String type);
/**
* 导出数据
* @param queryAll /
* @param response /
*/
void downloadList(List<QiniuContent> queryAll, HttpServletResponse response) throws IOException;
}
package me.zhengjie.service;
import me.zhengjie.domain.VerificationCode;
import me.zhengjie.domain.vo.EmailVo;
/**
* @author Zheng Jie
* @date 2018-12-26
*/
public interface VerificationCodeService {
/**
* 发送邮件验证码
* @param code 验证码
* @return EmailVo
*/
EmailVo sendEmail(VerificationCode code);
/**
* 验证
* @param code 验证码
*/
void validated(VerificationCode code);
}
package me.zhengjie.service.dto;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-09-05
*/
@Getter
@Setter
public class LocalStorageDTO implements Serializable {
// ID
private Long id;
private String realName;
// 文件名
private String name;
// 后缀
private String suffix;
// 类型
private String type;
// 大小
private String size;
// 操作人
private String operate;
private Timestamp createTime;
}
\ No newline at end of file
package me.zhengjie.service.dto;
import lombok.Data;
import java.sql.Timestamp;
import me.zhengjie.annotation.Query;
/**
* @author Zheng Jie
* @date 2019-09-05
*/
@Data
public class LocalStorageQueryCriteria{
// 模糊
@Query(blurry = "name,suffix,type,operate,size")
private String blurry;
@Query(type = Query.Type.GREATER_THAN,propName = "createTime")
private Timestamp startTime;
@Query(type = Query.Type.LESS_THAN,propName = "createTime")
private Timestamp endTime;
}
\ No newline at end of file
package me.zhengjie.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
import java.sql.Timestamp;
/**
* sm.ms图床
*
* @author Zheng Jie
* @date 2019-6-4 09:52:09
*/
@Data
public class PictureQueryCriteria{
@Query(type = Query.Type.INNER_LIKE)
private String filename;
@Query(type = Query.Type.INNER_LIKE)
private String username;
@Query(type = Query.Type.GREATER_THAN,propName = "createTime")
private Timestamp startTime;
@Query(type = Query.Type.LESS_THAN,propName = "createTime")
private Timestamp endTime;
}
package me.zhengjie.service.dto;
import lombok.Data;
import me.zhengjie.annotation.Query;
import java.sql.Timestamp;
/**
* @author Zheng Jie
* @date 2019-6-4 09:54:37
*/
@Data
public class QiniuQueryCriteria{
@Query(type = Query.Type.INNER_LIKE)
private String key;
@Query(type = Query.Type.GREATER_THAN,propName = "updateTime")
private Timestamp startTime;
@Query(type = Query.Type.LESS_THAN,propName = "updateTime")
private Timestamp endTime;
}
package me.zhengjie.service.impl;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import me.zhengjie.domain.AlipayConfig;
import me.zhengjie.domain.vo.TradeVo;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.repository.AlipayRepository;
import me.zhengjie.service.AlipayService;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
/**
* @author Zheng Jie
* @date 2018-12-31
*/
@Service
@CacheConfig(cacheNames = "alipay")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class AlipayServiceImpl implements AlipayService {
private final AlipayRepository alipayRepository;
public AlipayServiceImpl(AlipayRepository alipayRepository) {
this.alipayRepository = alipayRepository;
}
@Override
public String toPayAsPC(AlipayConfig alipay, TradeVo trade) throws Exception {
if(alipay.getId() == null){
throw new BadRequestException("请先添加相应配置,再操作");
}
AlipayClient alipayClient = new DefaultAlipayClient(alipay.getGatewayUrl(), alipay.getAppID(), alipay.getPrivateKey(), alipay.getFormat(), alipay.getCharset(), alipay.getPublicKey(), alipay.getSignType());
// double money = Double.parseDouble(trade.getTotalAmount());
// 创建API对应的request(电脑网页版)
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
// 订单完成后返回的页面和异步通知地址
request.setReturnUrl(alipay.getReturnUrl());
request.setNotifyUrl(alipay.getNotifyUrl());
// 填充订单参数
request.setBizContent("{" +
" \"out_trade_no\":\""+trade.getOutTradeNo()+"\"," +
" \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
" \"total_amount\":"+trade.getTotalAmount()+"," +
" \"subject\":\""+trade.getSubject()+"\"," +
" \"body\":\""+trade.getBody()+"\"," +
" \"extend_params\":{" +
" \"sys_service_provider_id\":\""+alipay.getSysServiceProviderId()+"\"" +
" }"+
" }");//填充业务参数
// 调用SDK生成表单, 通过GET方式,口可以获取url
return alipayClient.pageExecute(request, "GET").getBody();
}
@Override
public String toPayAsWeb(AlipayConfig alipay, TradeVo trade) throws Exception {
if(alipay.getId() == null){
throw new BadRequestException("请先添加相应配置,再操作");
}
AlipayClient alipayClient = new DefaultAlipayClient(alipay.getGatewayUrl(), alipay.getAppID(), alipay.getPrivateKey(), alipay.getFormat(), alipay.getCharset(), alipay.getPublicKey(), alipay.getSignType());
double money = Double.parseDouble(trade.getTotalAmount());
if(money <= 0 || money >= 5000){
throw new BadRequestException("测试金额过大");
}
// 创建API对应的request(手机网页版)
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setReturnUrl(alipay.getReturnUrl());
request.setNotifyUrl(alipay.getNotifyUrl());
request.setBizContent("{" +
" \"out_trade_no\":\""+trade.getOutTradeNo()+"\"," +
" \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
" \"total_amount\":"+trade.getTotalAmount()+"," +
" \"subject\":\""+trade.getSubject()+"\"," +
" \"body\":\""+trade.getBody()+"\"," +
" \"extend_params\":{" +
" \"sys_service_provider_id\":\""+alipay.getSysServiceProviderId()+"\"" +
" }"+
" }");//填充业务参数
return alipayClient.pageExecute(request, "GET").getBody();
}
@Override
@Cacheable(key = "'1'")
public AlipayConfig find() {
Optional<AlipayConfig> alipayConfig = alipayRepository.findById(1L);
return alipayConfig.orElseGet(AlipayConfig::new);
}
@Override
@CachePut(key = "'1'")
@Transactional(rollbackFor = Exception.class)
public AlipayConfig update(AlipayConfig alipayConfig) {
return alipayRepository.save(alipayConfig);
}
}
package me.zhengjie.service.impl;
import cn.hutool.extra.mail.Mail;
import cn.hutool.extra.mail.MailAccount;
import me.zhengjie.domain.EmailConfig;
import me.zhengjie.domain.vo.EmailVo;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.repository.EmailRepository;
import me.zhengjie.service.EmailService;
import me.zhengjie.utils.EncryptUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
/**
* @author Zheng Jie
* @date 2018-12-26
*/
@Service
@CacheConfig(cacheNames = "email")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class EmailServiceImpl implements EmailService {
private final EmailRepository emailRepository;
public EmailServiceImpl(EmailRepository emailRepository) {
this.emailRepository = emailRepository;
}
@Override
@CachePut(key = "'1'")
@Transactional(rollbackFor = Exception.class)
public EmailConfig update(EmailConfig emailConfig, EmailConfig old) {
try {
if(!emailConfig.getPass().equals(old.getPass())){
// 对称加密
emailConfig.setPass(EncryptUtils.desEncrypt(emailConfig.getPass()));
}
} catch (Exception e) {
e.printStackTrace();
}
return emailRepository.save(emailConfig);
}
@Override
@Cacheable(key = "'1'")
public EmailConfig find() {
Optional<EmailConfig> emailConfig = emailRepository.findById(1L);
return emailConfig.orElseGet(EmailConfig::new);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void send(EmailVo emailVo, EmailConfig emailConfig){
if(emailConfig == null){
throw new BadRequestException("请先配置,再操作");
}
// 封装
MailAccount account = new MailAccount();
account.setHost(emailConfig.getHost());
account.setPort(Integer.parseInt(emailConfig.getPort()));
account.setAuth(true);
try {
// 对称解密
account.setPass(EncryptUtils.desDecrypt(emailConfig.getPass()));
} catch (Exception e) {
throw new BadRequestException(e.getMessage());
}
account.setFrom(emailConfig.getUser()+"<"+emailConfig.getFromUser()+">");
// ssl方式发送
account.setSslEnable(true);
String content = emailVo.getContent();
// 发送
try {
int size = emailVo.getTos().size();
Mail.create(account)
.setTos(emailVo.getTos().toArray(new String[size]))
.setTitle(emailVo.getSubject())
.setContent(content)
.setHtml(true)
//关闭session
.setUseGlobalSession(false)
.send();
}catch (Exception e){
throw new BadRequestException(e.getMessage());
}
}
}
package me.zhengjie.service.impl;
import cn.hutool.core.util.ObjectUtil;
import me.zhengjie.domain.LocalStorage;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.utils.*;
import me.zhengjie.repository.LocalStorageRepository;
import me.zhengjie.service.LocalStorageService;
import me.zhengjie.service.dto.LocalStorageDTO;
import me.zhengjie.service.dto.LocalStorageQueryCriteria;
import me.zhengjie.service.mapper.LocalStorageMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
/**
* @author Zheng Jie
* @date 2019-09-05
*/
@Service
@CacheConfig(cacheNames = "localStorage")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class LocalStorageServiceImpl implements LocalStorageService {
private final LocalStorageRepository localStorageRepository;
private final LocalStorageMapper localStorageMapper;
@Value("${file.path}")
private String path;
@Value("${file.maxSize}")
private long maxSize;
public LocalStorageServiceImpl(LocalStorageRepository localStorageRepository, LocalStorageMapper localStorageMapper) {
this.localStorageRepository = localStorageRepository;
this.localStorageMapper = localStorageMapper;
}
@Override
@Cacheable
public Object queryAll(LocalStorageQueryCriteria criteria, Pageable pageable){
Page<LocalStorage> page = localStorageRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
return PageUtil.toPage(page.map(localStorageMapper::toDto));
}
@Override
@Cacheable
public List<LocalStorageDTO> queryAll(LocalStorageQueryCriteria criteria){
return localStorageMapper.toDto(localStorageRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
}
@Override
@Cacheable(key = "#p0")
public LocalStorageDTO findById(Long id){
LocalStorage localStorage = localStorageRepository.findById(id).orElseGet(LocalStorage::new);
ValidationUtil.isNull(localStorage.getId(),"LocalStorage","id",id);
return localStorageMapper.toDto(localStorage);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public LocalStorageDTO create(String name, MultipartFile multipartFile) {
FileUtil.checkSize(maxSize, multipartFile.getSize());
String suffix = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
// 可自行选择方式
// String type = FileUtil.getFileTypeByMimeType(suffix);
String type = FileUtil.getFileType(suffix);
File file = FileUtil.upload(multipartFile, path + type + File.separator);
if(ObjectUtil.isNull(file)){
throw new BadRequestException("上传失败");
}
try {
name = StringUtils.isBlank(name) ? FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename()) : name;
LocalStorage localStorage = new LocalStorage(
file.getName(),
name,
suffix,
file.getPath(),
type,
FileUtil.getSize(multipartFile.getSize()),
SecurityUtils.getUsername()
);
return localStorageMapper.toDto(localStorageRepository.save(localStorage));
}catch (Exception e){
FileUtil.del(file);
throw e;
}
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(LocalStorage resources) {
LocalStorage localStorage = localStorageRepository.findById(resources.getId()).orElseGet(LocalStorage::new);
ValidationUtil.isNull( localStorage.getId(),"LocalStorage","id",resources.getId());
localStorage.copy(resources);
localStorageRepository.save(localStorage);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Long id) {
LocalStorage storage = localStorageRepository.findById(id).orElseGet(LocalStorage::new);
FileUtil.del(storage.getPath());
localStorageRepository.delete(storage);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void deleteAll(Long[] ids) {
for (Long id : ids) {
LocalStorage storage = localStorageRepository.findById(id).orElseGet(LocalStorage::new);
FileUtil.del(storage.getPath());
localStorageRepository.delete(storage);
}
}
@Override
public void download(List<LocalStorageDTO> queryAll, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (LocalStorageDTO localStorageDTO : queryAll) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("文件名", localStorageDTO.getRealName());
map.put("备注名", localStorageDTO.getName());
map.put("文件类型", localStorageDTO.getType());
map.put("文件大小", localStorageDTO.getSize());
map.put("操作人", localStorageDTO.getOperate());
map.put("创建日期", localStorageDTO.getCreateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
package me.zhengjie.service.impl;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.domain.Picture;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.repository.PictureRepository;
import me.zhengjie.service.PictureService;
import me.zhengjie.service.dto.PictureQueryCriteria;
import me.zhengjie.utils.*;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author Zheng Jie
* @date 2018-12-27
*/
@Slf4j
@Service(value = "pictureService")
@CacheConfig(cacheNames = "picture")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class PictureServiceImpl implements PictureService {
private final PictureRepository pictureRepository;
private static final String SUCCESS = "success";
private static final String CODE = "code";
private static final String MSG = "message";
public PictureServiceImpl(PictureRepository pictureRepository) {
this.pictureRepository = pictureRepository;
}
@Override
@Cacheable
public Object queryAll(PictureQueryCriteria criteria, Pageable pageable){
return PageUtil.toPage(pictureRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable));
}
@Override
public List<Picture> queryAll(PictureQueryCriteria criteria) {
return pictureRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Throwable.class)
public Picture upload(MultipartFile multipartFile, String username) {
File file = FileUtil.toFile(multipartFile);
// 验证是否重复上传
Picture picture = pictureRepository.findByMd5Code(FileUtil.getMd5(file));
if(picture != null){
return picture;
}
HashMap<String, Object> paramMap = new HashMap<>(1);
paramMap.put("smfile", file);
String result= HttpUtil.post(ElAdminConstant.Url.SM_MS_URL, paramMap);
JSONObject jsonObject = JSONUtil.parseObj(result);
if(!jsonObject.get(CODE).toString().equals(SUCCESS)){
throw new BadRequestException(TranslatorUtil.translate(jsonObject.get(MSG).toString()));
}
picture = JSON.parseObject(jsonObject.get("data").toString(), Picture.class);
picture.setSize(FileUtil.getSize(Integer.parseInt(picture.getSize())));
picture.setUsername(username);
picture.setMd5Code(FileUtil.getMd5(file));
picture.setFilename(FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename())+"."+FileUtil.getExtensionName(multipartFile.getOriginalFilename()));
pictureRepository.save(picture);
//删除临时文件
FileUtil.del(file);
return picture;
}
@Override
@Cacheable(key = "#p0")
public Picture findById(Long id) {
Picture picture = pictureRepository.findById(id).orElseGet(Picture::new);
ValidationUtil.isNull(picture.getId(),"Picture","id",id);
return picture;
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(Picture picture) {
try {
HttpUtil.get(picture.getDelete());
pictureRepository.delete(picture);
} catch(Exception e){
pictureRepository.delete(picture);
}
}
@Override
@CacheEvict(allEntries = true)
public void deleteAll(Long[] ids) {
for (Long id : ids) {
delete(findById(id));
}
}
@Override
public void download(List<Picture> queryAll, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (Picture picture : queryAll) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("文件名", picture.getFilename());
map.put("图片地址", picture.getUrl());
map.put("文件大小", picture.getSize());
map.put("操作人", picture.getUsername());
map.put("高度", picture.getHeight());
map.put("宽度", picture.getWidth());
map.put("删除地址", picture.getDelete());
map.put("创建日期", picture.getCreateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
package me.zhengjie.service.impl;
import com.alibaba.fastjson.JSON;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import me.zhengjie.domain.QiniuConfig;
import me.zhengjie.domain.QiniuContent;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.repository.QiNiuConfigRepository;
import me.zhengjie.repository.QiniuContentRepository;
import me.zhengjie.service.QiNiuService;
import me.zhengjie.service.dto.QiniuQueryCriteria;
import me.zhengjie.utils.FileUtil;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QiNiuUtil;
import me.zhengjie.utils.QueryHelp;
import me.zhengjie.utils.ValidationUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
/**
* @author Zheng Jie
* @date 2018-12-31
*/
@Service
@CacheConfig(cacheNames = "qiNiu")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class QiNiuServiceImpl implements QiNiuService {
private final QiNiuConfigRepository qiNiuConfigRepository;
private final QiniuContentRepository qiniuContentRepository;
public QiNiuServiceImpl(QiNiuConfigRepository qiNiuConfigRepository, QiniuContentRepository qiniuContentRepository) {
this.qiNiuConfigRepository = qiNiuConfigRepository;
this.qiniuContentRepository = qiniuContentRepository;
}
@Value("${qiniu.max-size}")
private Long maxSize;
@Override
@Cacheable
public Object queryAll(QiniuQueryCriteria criteria, Pageable pageable){
return PageUtil.toPage(qiniuContentRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable));
}
@Override
public List<QiniuContent> queryAll(QiniuQueryCriteria criteria) {
return qiniuContentRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
}
@Override
@Cacheable(key = "'1'")
public QiniuConfig find() {
Optional<QiniuConfig> qiniuConfig = qiNiuConfigRepository.findById(1L);
return qiniuConfig.orElseGet(QiniuConfig::new);
}
@Override
@CachePut(cacheNames = "qiNiuConfig", key = "'1'")
@Transactional(rollbackFor = Exception.class)
public QiniuConfig update(QiniuConfig qiniuConfig) {
if (!(qiniuConfig.getHost().toLowerCase().startsWith("http://")||qiniuConfig.getHost().toLowerCase().startsWith("https://"))) {
throw new BadRequestException("外链域名必须以http://或者https://开头");
}
qiniuConfig.setId(1L);
return qiNiuConfigRepository.save(qiniuConfig);
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public QiniuContent upload(MultipartFile file, QiniuConfig qiniuConfig) {
FileUtil.checkSize(maxSize, file.getSize());
if(qiniuConfig.getId() == null){
throw new BadRequestException("请先添加相应配置,再操作");
}
// 构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(QiNiuUtil.getRegion(qiniuConfig.getZone()));
UploadManager uploadManager = new UploadManager(cfg);
Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());
String upToken = auth.uploadToken(qiniuConfig.getBucket());
try {
String key = file.getOriginalFilename();
if(qiniuContentRepository.findByKey(key) != null) {
key = QiNiuUtil.getKey(key);
}
Response response = uploadManager.put(file.getBytes(), key, upToken);
//解析上传成功的结果
DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
//存入数据库
QiniuContent qiniuContent = new QiniuContent();
qiniuContent.setSuffix(FileUtil.getExtensionName(putRet.key));
qiniuContent.setBucket(qiniuConfig.getBucket());
qiniuContent.setType(qiniuConfig.getType());
qiniuContent.setKey(FileUtil.getFileNameNoEx(putRet.key));
qiniuContent.setUrl(qiniuConfig.getHost()+"/"+putRet.key);
qiniuContent.setSize(FileUtil.getSize(Integer.parseInt(file.getSize()+"")));
return qiniuContentRepository.save(qiniuContent);
} catch (Exception e) {
throw new BadRequestException(e.getMessage());
}
}
@Override
@Cacheable
public QiniuContent findByContentId(Long id) {
QiniuContent qiniuContent = qiniuContentRepository.findById(id).orElseGet(QiniuContent::new);
ValidationUtil.isNull(qiniuContent.getId(),"QiniuContent", "id",id);
return qiniuContent;
}
@Override
@Cacheable
public String download(QiniuContent content,QiniuConfig config){
String finalUrl;
String TYPE = "公开";
if(TYPE.equals(content.getType())){
finalUrl = content.getUrl();
} else {
Auth auth = Auth.create(config.getAccessKey(), config.getSecretKey());
// 1小时,可以自定义链接过期时间
long expireInSeconds = 3600;
finalUrl = auth.privateDownloadUrl(content.getUrl(), expireInSeconds);
}
return finalUrl;
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void delete(QiniuContent content, QiniuConfig config) {
//构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(QiNiuUtil.getRegion(config.getZone()));
Auth auth = Auth.create(config.getAccessKey(), config.getSecretKey());
BucketManager bucketManager = new BucketManager(auth, cfg);
try {
bucketManager.delete(content.getBucket(), content.getKey() + "." + content.getSuffix());
qiniuContentRepository.delete(content);
} catch (QiniuException ex) {
qiniuContentRepository.delete(content);
}
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void synchronize(QiniuConfig config) {
if(config.getId() == null){
throw new BadRequestException("请先添加相应配置,再操作");
}
//构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(QiNiuUtil.getRegion(config.getZone()));
Auth auth = Auth.create(config.getAccessKey(), config.getSecretKey());
BucketManager bucketManager = new BucketManager(auth, cfg);
//文件名前缀
String prefix = "";
//每次迭代的长度限制,最大1000,推荐值 1000
int limit = 1000;
//指定目录分隔符,列出所有公共前缀(模拟列出目录效果)。缺省值为空字符串
String delimiter = "";
//列举空间文件列表
BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(config.getBucket(), prefix, limit, delimiter);
while (fileListIterator.hasNext()) {
//处理获取的file list结果
QiniuContent qiniuContent;
FileInfo[] items = fileListIterator.next();
for (FileInfo item : items) {
if(qiniuContentRepository.findByKey(FileUtil.getFileNameNoEx(item.key)) == null){
qiniuContent = new QiniuContent();
qiniuContent.setSize(FileUtil.getSize(Integer.parseInt(item.fsize+"")));
qiniuContent.setSuffix(FileUtil.getExtensionName(item.key));
qiniuContent.setKey(FileUtil.getFileNameNoEx(item.key));
qiniuContent.setType(config.getType());
qiniuContent.setBucket(config.getBucket());
qiniuContent.setUrl(config.getHost()+"/"+item.key);
qiniuContentRepository.save(qiniuContent);
}
}
}
}
@Override
@CacheEvict(allEntries = true)
public void deleteAll(Long[] ids, QiniuConfig config) {
for (Long id : ids) {
delete(findByContentId(id), config);
}
}
@Override
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = Exception.class)
public void update(String type) {
qiNiuConfigRepository.update(type);
}
@Override
public void downloadList(List<QiniuContent> queryAll, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (QiniuContent content : queryAll) {
Map<String,Object> map = new LinkedHashMap<>();
map.put("文件名", content.getKey());
map.put("文件类型", content.getSuffix());
map.put("空间名称", content.getBucket());
map.put("文件大小", content.getSize());
map.put("空间类型", content.getType());
map.put("创建日期", content.getUpdateTime());
list.add(map);
}
FileUtil.downloadExcel(list, response);
}
}
package me.zhengjie.service.impl;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import me.zhengjie.domain.VerificationCode;
import me.zhengjie.domain.vo.EmailVo;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.repository.VerificationCodeRepository;
import me.zhengjie.service.VerificationCodeService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.concurrent.*;
/**
* @author Zheng Jie
* @date 2018-12-26
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class VerificationCodeServiceImpl implements VerificationCodeService {
private final VerificationCodeRepository verificationCodeRepository;
@Value("${code.expiration}")
private Integer expiration;
public VerificationCodeServiceImpl(VerificationCodeRepository verificationCodeRepository) {
this.verificationCodeRepository = verificationCodeRepository;
}
@Override
@Transactional(rollbackFor = Exception.class)
public EmailVo sendEmail(VerificationCode code) {
EmailVo emailVo;
String content;
VerificationCode verificationCode = verificationCodeRepository.findByScenesAndTypeAndValueAndStatusIsTrue(code.getScenes(),code.getType(),code.getValue());
// 如果不存在有效的验证码,就创建一个新的
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
Template template = engine.getTemplate("email/email.ftl");
if(verificationCode == null){
code.setCode(RandomUtil.randomNumbers (6));
content = template.render(Dict.create().set("code",code.getCode()));
emailVo = new EmailVo(Collections.singletonList(code.getValue()),"eladmin后台管理系统",content);
timedDestruction(verificationCodeRepository.save(code));
// 存在就再次发送原来的验证码
} else {
content = template.render(Dict.create().set("code",verificationCode.getCode()));
emailVo = new EmailVo(Collections.singletonList(verificationCode.getValue()),"eladmin后台管理系统",content);
}
return emailVo;
}
@Override
public void validated(VerificationCode code) {
VerificationCode verificationCode = verificationCodeRepository.findByScenesAndTypeAndValueAndStatusIsTrue(code.getScenes(),code.getType(),code.getValue());
if(verificationCode == null || !verificationCode.getCode().equals(code.getCode())){
throw new BadRequestException("无效验证码");
} else {
verificationCode.setStatus(false);
verificationCodeRepository.save(verificationCode);
}
}
/**
* 定时任务,指定分钟后改变验证码状态
* @param verifyCode 验证码
*/
private void timedDestruction(VerificationCode verifyCode) {
//以下示例为程序调用结束继续运行
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
try {
executorService.schedule(() -> {
verifyCode.setStatus(false);
verificationCodeRepository.save(verifyCode);
}, expiration * 60 * 1000L, TimeUnit.MILLISECONDS);
}catch (Exception e){
e.printStackTrace();
}
}
}
package me.zhengjie.service.mapper;
import me.zhengjie.base.BaseMapper;
import me.zhengjie.domain.LocalStorage;
import me.zhengjie.service.dto.LocalStorageDTO;
import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
/**
* @author Zheng Jie
* @date 2019-09-05
*/
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface LocalStorageMapper extends BaseMapper<LocalStorageDTO, LocalStorage> {
}
\ No newline at end of file
package me.zhengjie.utils;
/**
* 支付状态
* @author zhengjie
* @date 2018/08/01 16:45:43
*/
public enum AliPayStatusEnum {
FINISHED("交易成功", "TRADE_FINISHED"),
SUCCESS("支付成功", "TRADE_SUCCESS"),
BUYER_PAY("交易创建", "WAIT_BUYER_PAY"),
CLOSED("交易关闭", "TRADE_CLOSED");
private String value;
AliPayStatusEnum(String name, String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
package me.zhengjie.utils;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import me.zhengjie.domain.AlipayConfig;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 支付宝工具类
* @author zhengjie
* @date 2018/09/30 14:04:35
*/
@Component
public class AlipayUtils {
/**
* 生成订单号
* @return String
*/
public String getOrderCode() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
int a = (int)(Math.random() * 9000.0D) + 1000;
System.out.println(a);
Date date = new Date();
String str = sdf.format(date);
String[] split = str.split("-");
String s = split[0] + split[1] + split[2];
String[] split1 = s.split(" ");
String s1 = split1[0] + split1[1];
String[] split2 = s1.split(":");
return split2[0] + split2[1] + split2[2] + a;
}
/**
* 校验签名
* @param request HttpServletRequest
* @param alipay 阿里云配置
* @return boolean
*/
public boolean rsaCheck(HttpServletRequest request, AlipayConfig alipay){
// 获取支付宝POST过来反馈信息
Map<String,String> params = new HashMap<>(1);
Map requestParams = request.getParameterMap();
for (Object o : requestParams.keySet()) {
String name = (String) o;
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
params.put(name, valueStr);
}
try {
return AlipaySignature.rsaCheckV1(params,
alipay.getPublicKey(),
alipay.getCharset(),
alipay.getSignType());
} catch (AlipayApiException e) {
return false;
}
}
}
package me.zhengjie.utils;
import com.qiniu.storage.Region;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 七牛云存储工具类
* @author Zheng Jie
* @date 2018-12-31
*/
public class QiNiuUtil {
private static final String HUAD = "华东";
private static final String HUAB = "华北";
private static final String HUAN = "华南";
private static final String BEIM = "北美";
/**
* 得到机房的对应关系
* @param zone 机房名称
* @return Region
*/
public static Region getRegion(String zone){
if(HUAD.equals(zone)){
return Region.huadong();
} else if(HUAB.equals(zone)){
return Region.huabei();
} else if(HUAN.equals(zone)){
return Region.huanan();
} else if (BEIM.equals(zone)){
return Region.beimei();
// 否则就是东南亚
} else {
return Region.qvmHuadong();
}
}
/**
* 默认不指定key的情况下,以文件内容的hash值作为文件名
* @param file 文件名
* @return String
*/
public static String getKey(String file){
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = new Date();
return FileUtil.getFileNameNoEx(file) + "-" +
sdf.format(date) +
"." +
FileUtil.getExtensionName(file);
}
}
<?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>me.zhengjie</groupId>
<artifactId>eladmin</artifactId>
<packaging>pom</packaging>
<version>2.3</version>
<modules>
<module>eladmin-common</module>
<module>eladmin-logging</module>
<module>eladmin-system</module>
<module>eladmin-tools</module>
<module>eladmin-generator</module>
</modules>
<name>EL-ADMIN后台管理系统</name>
<url>http://auauz.net</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<jedis.version>2.9.0</jedis.version>
<log4jdbc.version>1.16</log4jdbc.version>
<swagger.version>2.9.2</swagger.version>
<fastjson.version>1.2.54</fastjson.version>
<druid.version>1.1.10</druid.version>
<hutool.version>[4.1.12,)</hutool.version>
<commons-pool2.version>2.5.0</commons-pool2.version>
<mapstruct.version>1.2.0.Final</mapstruct.version>
</properties>
<dependencies>
<!--Spring boot start-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.4.0.RELEASE</version>
</dependency>
<!-- spring cache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--Spring boot end-->
<!--spring2.0集成redis所需common-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>
<!-- RESTful APIs swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.21</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.21</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>
<!--lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!--https://gitee.com/lionsoul/ip2region/tree/v1.4-release/-->
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/xerces/xercesImpl -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.11.0</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!--mapStruct依赖-->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</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>
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
<version>1.20</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>
/*
Navicat Premium Data Transfer
Source Server : 本地
Source Server Type : MySQL
Source Server Version : 50562
Source Host : localhost:3306
Source Schema : eladmin
Target Server Type : MySQL
Target Server Version : 50562
File Encoding : 65001
Date: 31/10/2019 12:24:38
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for alipay_config
-- ----------------------------
DROP TABLE IF EXISTS `alipay_config`;
CREATE TABLE `alipay_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`app_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '应用ID',
`charset` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '编码',
`format` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '类型 固定格式json',
`gateway_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '网关地址',
`notify_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '异步回调',
`private_key` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '私钥',
`public_key` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '公钥',
`return_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '回调地址',
`sign_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '签名方式',
`sys_service_provider_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商户号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of alipay_config
-- ----------------------------
INSERT INTO `alipay_config` VALUES (1, '2016091700532697', 'utf-8', 'JSON', 'https://openapi.alipaydev.com/gateway.do', 'http://api.auauz.net/api/aliPay/notify', 'MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5js8sInU10AJ0cAQ8UMMyXrQ+oHZEkVt5lBwsStmTJ7YikVYgbskx1YYEXTojRsWCb+SH/kDmDU4pK/u91SJ4KFCRMF2411piYuXU/jF96zKrADznYh/zAraqT6hvAIVtQAlMHN53nx16rLzZ/8jDEkaSwT7+HvHiS+7sxSojnu/3oV7BtgISoUNstmSe8WpWHOaWv19xyS+Mce9MY4BfseFhzTICUymUQdd/8hXA28/H6osUfAgsnxAKv7Wil3aJSgaJczWuflYOve0dJ3InZkhw5Cvr0atwpk8YKBQjy5CdkoHqvkOcIB+cYHXJKzOE5tqU7inSwVbHzOLQ3XbnAgMBAAECggEAVJp5eT0Ixg1eYSqFs9568WdetUNCSUchNxDBu6wxAbhUgfRUGZuJnnAll63OCTGGck+EGkFh48JjRcBpGoeoHLL88QXlZZbC/iLrea6gcDIhuvfzzOffe1RcZtDFEj9hlotg8dQj1tS0gy9pN9g4+EBH7zeu+fyv+qb2e/v1l6FkISXUjpkD7RLQr3ykjiiEw9BpeKb7j5s7Kdx1NNIzhkcQKNqlk8JrTGDNInbDM6inZfwwIO2R1DHinwdfKWkvOTODTYa2MoAvVMFT9Bec9FbLpoWp7ogv1JMV9svgrcF9XLzANZ/OQvkbe9TV9GWYvIbxN6qwQioKCWO4GPnCAQKBgQDgW5MgfhX8yjXqoaUy/d1VjI8dHeIyw8d+OBAYwaxRSlCfyQ+tieWcR2HdTzPca0T0GkWcKZm0ei5xRURgxt4DUDLXNh26HG0qObbtLJdu/AuBUuCqgOiLqJ2f1uIbrz6OZUHns+bT/jGW2Ws8+C13zTCZkZt9CaQsrp3QOGDx5wKBgQDTul39hp3ZPwGNFeZdkGoUoViOSd5Lhowd5wYMGAEXWRLlU8z+smT5v0POz9JnIbCRchIY2FAPKRdVTICzmPk2EPJFxYTcwaNbVqL6lN7J2IlXXMiit5QbiLauo55w7plwV6LQmKm9KV7JsZs5XwqF7CEovI7GevFzyD3w+uizAQKBgC3LY1eRhOlpWOIAhpjG6qOoohmeXOphvdmMlfSHq6WYFqbWwmV4rS5d/6LNpNdL6fItXqIGd8I34jzql49taCmi+A2nlR/E559j0mvM20gjGDIYeZUz5MOE8k+K6/IcrhcgofgqZ2ZED1ksHdB/E8DNWCswZl16V1FrfvjeWSNnAoGAMrBplCrIW5xz+J0Hm9rZKrs+AkK5D4fUv8vxbK/KgxZ2KaUYbNm0xv39c+PZUYuFRCz1HDGdaSPDTE6WeWjkMQd5mS6ikl9hhpqFRkyh0d0fdGToO9yLftQKOGE/q3XUEktI1XvXF0xyPwNgUCnq0QkpHyGVZPtGFxwXiDvpvgECgYA5PoB+nY8iDiRaJNko9w0hL4AeKogwf+4TbCw+KWVEn6jhuJa4LFTdSqp89PktQaoVpwv92el/AhYjWOl/jVCm122f9b7GyoelbjMNolToDwe5pF5RnSpEuDdLy9MfE8LnE3PlbE7E5BipQ3UjSebkgNboLHH/lNZA5qvEtvbfvQ==', 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAut9evKRuHJ/2QNfDlLwvN/S8l9hRAgPbb0u61bm4AtzaTGsLeMtScetxTWJnVvAVpMS9luhEJjt+Sbk5TNLArsgzzwARgaTKOLMT1TvWAK5EbHyI+eSrc3s7Awe1VYGwcubRFWDm16eQLv0k7iqiw+4mweHSz/wWyvBJVgwLoQ02btVtAQErCfSJCOmt0Q/oJQjj08YNRV4EKzB19+f5A+HQVAKy72dSybTzAK+3FPtTtNen/+b5wGeat7c32dhYHnGorPkPeXLtsqqUTp1su5fMfd4lElNdZaoCI7osZxWWUo17vBCZnyeXc9fk0qwD9mK6yRAxNbrY72Xx5VqIqwIDAQAB', 'http://api.auauz.net/api/aliPay/return', 'RSA2', '2088102176044281');
-- ----------------------------
-- Table structure for dept
-- ----------------------------
DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '名称',
`pid` bigint(20) NOT NULL COMMENT '上级部门',
`enabled` bit(1) NOT NULL,
`create_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of dept
-- ----------------------------
INSERT INTO `dept` VALUES (1, 'eladmin', 0, b'1', '2019-03-25 09:14:05');
INSERT INTO `dept` VALUES (2, '研发部', 7, b'1', '2019-03-25 09:15:32');
INSERT INTO `dept` VALUES (5, '运维部', 7, b'1', '2019-03-25 09:20:44');
INSERT INTO `dept` VALUES (6, '测试部', 8, b'1', '2019-03-25 09:52:18');
INSERT INTO `dept` VALUES (7, '华南分部', 1, b'1', '2019-03-25 11:04:50');
INSERT INTO `dept` VALUES (8, '华北分部', 1, b'1', '2019-03-25 11:04:53');
INSERT INTO `dept` VALUES (11, '人事部', 8, b'1', '2019-03-25 11:07:58');
-- ----------------------------
-- Table structure for dict
-- ----------------------------
DROP TABLE IF EXISTS `dict`;
CREATE TABLE `dict` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字典名称',
`remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
`create_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of dict
-- ----------------------------
INSERT INTO `dict` VALUES (1, 'user_status', '用户状态', '2019-10-27 20:31:36');
INSERT INTO `dict` VALUES (4, 'dept_status', '部门状态', '2019-10-27 20:31:36');
INSERT INTO `dict` VALUES (5, 'job_status', '岗位状态', '2019-10-27 20:31:36');
-- ----------------------------
-- Table structure for dict_detail
-- ----------------------------
DROP TABLE IF EXISTS `dict_detail`;
CREATE TABLE `dict_detail` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`label` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字典标签',
`value` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字典值',
`sort` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '排序',
`dict_id` bigint(11) NULL DEFAULT NULL COMMENT '字典id',
`create_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `FK5tpkputc6d9nboxojdbgnpmyb`(`dict_id`) USING BTREE,
CONSTRAINT `FK5tpkputc6d9nboxojdbgnpmyb` FOREIGN KEY (`dict_id`) REFERENCES `dict` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 17 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of dict_detail
-- ----------------------------
INSERT INTO `dict_detail` VALUES (1, '激活', 'true', '1', 1, '2019-10-27 20:31:36');
INSERT INTO `dict_detail` VALUES (2, '禁用', 'false', '2', 1, NULL);
INSERT INTO `dict_detail` VALUES (11, '启用', 'true', '1', 4, NULL);
INSERT INTO `dict_detail` VALUES (12, '停用', 'false', '2', 4, '2019-10-27 20:31:36');
INSERT INTO `dict_detail` VALUES (13, '启用', 'true', '1', 5, NULL);
INSERT INTO `dict_detail` VALUES (14, '停用', 'false', '2', 5, '2019-10-27 20:31:36');
-- ----------------------------
-- Table structure for email_config
-- ----------------------------
DROP TABLE IF EXISTS `email_config`;
CREATE TABLE `email_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`from_user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人',
`host` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮件服务器SMTP地址',
`pass` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
`port` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '端口',
`user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '发件者用户名',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for gen_config
-- ----------------------------
DROP TABLE IF EXISTS `gen_config`;
CREATE TABLE `gen_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`author` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '作者',
`cover` bit(1) NULL DEFAULT NULL COMMENT '是否覆盖',
`module_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '模块名称',
`pack` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '至于哪个包下',
`path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '前端代码生成的路径',
`api_path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`prefix` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of gen_config
-- ----------------------------
INSERT INTO `gen_config` VALUES (1, 'Zheng Jie', b'0', 'eladmin-system', 'me.zhengjie.test', 'E:\\workspace\\me\\front\\eladmin-qt\\src\\views\\test1111', 'E:\\workspace\\me\\front\\eladmin-qt\\src\\api', NULL);
-- ----------------------------
-- Table structure for job
-- ----------------------------
DROP TABLE IF EXISTS `job`;
CREATE TABLE `job` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`enabled` bit(1) NOT NULL,
`sort` bigint(20) NOT NULL,
`dept_id` bigint(20) NULL DEFAULT NULL,
`create_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `FKmvhj0rogastlctflsxf1d6k3i`(`dept_id`) USING BTREE,
CONSTRAINT `FKmvhj0rogastlctflsxf1d6k3i` FOREIGN KEY (`dept_id`) REFERENCES `dept` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of job
-- ----------------------------
INSERT INTO `job` VALUES (2, '董事长秘书', b'1', 2, 1, '2019-03-29 14:01:30');
INSERT INTO `job` VALUES (8, '人事专员', b'1', 3, 11, '2019-03-29 14:52:28');
INSERT INTO `job` VALUES (10, '产品经理', b'1', 4, 2, '2019-03-29 14:55:51');
INSERT INTO `job` VALUES (11, '全栈开发', b'1', 6, 2, '2019-03-31 13:39:30');
INSERT INTO `job` VALUES (12, '软件测试', b'1', 5, 2, '2019-03-31 13:39:43');
-- ----------------------------
-- Table structure for local_storage
-- ----------------------------
DROP TABLE IF EXISTS `local_storage`;
CREATE TABLE `local_storage` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`real_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件名',
`suffix` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '后缀',
`path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '路径',
`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '类型',
`size` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '大小',
`operate` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作人',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建日期',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for log
-- ----------------------------
DROP TABLE IF EXISTS `log`;
CREATE TABLE `log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`create_time` datetime NULL DEFAULT NULL,
`description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`exception_detail` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
`log_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`method` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`params` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
`request_ip` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`time` bigint(20) NULL DEFAULT NULL,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`browser` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 17040 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for menu
-- ----------------------------
DROP TABLE IF EXISTS `menu`;
CREATE TABLE `menu` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`i_frame` bit(1) NULL DEFAULT NULL COMMENT '是否外链',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单名称',
`component` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组件',
`pid` bigint(20) NOT NULL COMMENT '上级菜单ID',
`sort` bigint(20) NULL DEFAULT NULL COMMENT '排序',
`icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图标',
`path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '链接地址',
`cache` bit(1) NULL DEFAULT b'0',
`hidden` bit(1) NULL DEFAULT b'0',
`component_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '-',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建日期',
`permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`type` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `FKqcf9gem97gqa5qjm4d3elcqt5`(`pid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 81 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of menu
-- ----------------------------
INSERT INTO `menu` VALUES (1, b'0', '系统管理', NULL, 0, 1, 'system', 'system', b'0', b'0', NULL, '2018-12-18 15:11:29', NULL, 0);
INSERT INTO `menu` VALUES (2, b'0', '用户管理', 'system/user/index', 1, 2, 'peoples', 'user', b'0', b'0', 'User', '2018-12-18 15:14:44', 'user:list', 1);
INSERT INTO `menu` VALUES (3, b'0', '角色管理', 'system/role/index', 1, 3, 'role', 'role', b'0', b'0', 'Role', '2018-12-18 15:16:07', 'roles:list', 1);
INSERT INTO `menu` VALUES (5, b'0', '菜单管理', 'system/menu/index', 1, 5, 'menu', 'menu', b'0', b'0', 'Menu', '2018-12-18 15:17:28', 'menu:list', 1);
INSERT INTO `menu` VALUES (6, b'0', '系统监控', NULL, 0, 10, 'monitor', 'monitor', b'0', b'0', NULL, '2018-12-18 15:17:48', NULL, 0);
INSERT INTO `menu` VALUES (7, b'0', '操作日志', 'monitor/log/index', 6, 11, 'log', 'logs', b'0', b'0', 'Log', '2018-12-18 15:18:26', NULL, 1);
INSERT INTO `menu` VALUES (8, b'0', '系统缓存', 'monitor/redis/index', 6, 13, 'redis', 'redis', b'0', b'0', 'Redis', '2018-12-18 15:19:01', 'redis:list', 1);
INSERT INTO `menu` VALUES (9, b'0', 'SQL监控', 'monitor/sql/index', 6, 14, 'sqlMonitor', 'druid', b'0', b'0', 'Sql', '2018-12-18 15:19:34', NULL, 1);
INSERT INTO `menu` VALUES (10, b'0', '组件管理', NULL, 0, 50, 'zujian', 'components', b'0', b'0', NULL, '2018-12-19 13:38:16', NULL, 0);
INSERT INTO `menu` VALUES (11, b'0', '图标库', 'components/IconSelect', 10, 51, 'icon', 'icon', b'0', b'0', 'Icons', '2018-12-19 13:38:49', NULL, 1);
INSERT INTO `menu` VALUES (14, b'0', '邮件工具', 'tools/email/index', 36, 24, 'email', 'email', b'0', b'0', 'Email', '2018-12-27 10:13:09', NULL, 1);
INSERT INTO `menu` VALUES (15, b'0', '富文本', 'components/Editor', 10, 52, 'fwb', 'tinymce', b'0', b'0', 'Editor', '2018-12-27 11:58:25', NULL, 1);
INSERT INTO `menu` VALUES (16, b'0', '图床管理', 'tools/picture/index', 36, 25, 'image', 'pictures', b'0', b'0', 'Pictures', '2018-12-28 09:36:53', 'pictures:list', 1);
INSERT INTO `menu` VALUES (18, b'0', '存储管理', 'tools/storage/index', 36, 23, 'qiniu', 'storage', b'0', b'0', 'Storage', '2018-12-31 11:12:15', 'storage:list', 1);
INSERT INTO `menu` VALUES (19, b'0', '支付宝工具', 'tools/aliPay/index', 36, 27, 'alipay', 'aliPay', b'0', b'0', 'AliPay', '2018-12-31 14:52:38', NULL, 1);
INSERT INTO `menu` VALUES (21, b'0', '多级菜单', '', 0, 900, 'menu', 'nested', b'0', b'1', NULL, '2019-01-04 16:22:03', NULL, 0);
INSERT INTO `menu` VALUES (22, b'0', '二级菜单1', 'nested/menu1/index', 21, 999, 'menu', 'menu1', b'0', b'0', NULL, '2019-01-04 16:23:29', NULL, 1);
INSERT INTO `menu` VALUES (23, b'0', '二级菜单2', 'nested/menu2/index', 21, 999, 'menu', 'menu2', b'0', b'0', NULL, '2019-01-04 16:23:57', NULL, 1);
INSERT INTO `menu` VALUES (24, b'0', '三级菜单1', 'nested/menu1/menu1-1', 22, 999, 'menu', 'menu1-1', b'0', b'0', NULL, '2019-01-04 16:24:48', NULL, 1);
INSERT INTO `menu` VALUES (27, b'0', '三级菜单2', 'nested/menu1/menu1-2', 22, 999, 'menu', 'menu1-2', b'0', b'0', NULL, '2019-01-07 17:27:32', NULL, 1);
INSERT INTO `menu` VALUES (28, b'0', '定时任务', 'system/timing/index', 36, 21, 'timing', 'timing', b'0', b'0', 'Timing', '2019-01-07 20:34:40', 'timing:list', 1);
INSERT INTO `menu` VALUES (30, b'0', '代码生成', 'generator/index', 36, 22, 'dev', 'generator', b'0', b'0', 'GeneratorIndex', '2019-01-11 15:45:55', NULL, 1);
INSERT INTO `menu` VALUES (32, b'0', '异常日志', 'monitor/log/errorLog', 6, 12, 'error', 'errorLog', b'0', b'0', 'ErrorLog', '2019-01-13 13:49:03', NULL, 1);
INSERT INTO `menu` VALUES (33, b'0', 'Markdown', 'components/MarkDown', 10, 53, 'markdown', 'markdown', b'0', b'0', 'Markdown', '2019-03-08 13:46:44', NULL, 1);
INSERT INTO `menu` VALUES (34, b'0', 'Yaml编辑器', 'components/YamlEdit', 10, 54, 'dev', 'yaml', b'0', b'0', 'YamlEdit', '2019-03-08 15:49:40', NULL, 1);
INSERT INTO `menu` VALUES (35, b'0', '部门管理', 'system/dept/index', 1, 6, 'dept', 'dept', b'0', b'0', 'Dept', '2019-03-25 09:46:00', 'dept:list', 1);
INSERT INTO `menu` VALUES (36, b'0', '系统工具', '', 0, 20, 'sys-tools', 'sys-tools', b'0', b'0', NULL, '2019-03-29 10:57:35', NULL, 0);
INSERT INTO `menu` VALUES (37, b'0', '岗位管理', 'system/job/index', 1, 7, 'Steve-Jobs', 'job', b'0', b'0', 'Job', '2019-03-29 13:51:18', 'job:list', 1);
INSERT INTO `menu` VALUES (38, b'0', '接口文档', 'tools/swagger/index', 36, 26, 'swagger', 'swagger2', b'0', b'0', 'Swagger', '2019-03-29 19:57:53', NULL, 1);
INSERT INTO `menu` VALUES (39, b'0', '字典管理', 'system/dict/index', 1, 8, 'dictionary', 'dict', b'0', b'0', 'Dict', '2019-04-10 11:49:04', 'dict:list', 1);
INSERT INTO `menu` VALUES (41, b'0', '在线用户', 'monitor/online/index', 6, 10, 'Steve-Jobs', 'online', b'0', b'0', 'OnlineUser', '2019-10-26 22:08:43', NULL, 1);
INSERT INTO `menu` VALUES (44, b'0', '用户新增', '', 2, 2, '', '', b'0', b'0', '', '2019-10-29 10:59:46', 'user:add', 2);
INSERT INTO `menu` VALUES (45, b'0', '用户编辑', '', 2, 3, '', '', b'0', b'0', '', '2019-10-29 11:00:08', 'user:edit', 2);
INSERT INTO `menu` VALUES (46, b'0', '用户删除', '', 2, 4, '', '', b'0', b'0', '', '2019-10-29 11:00:23', 'user:del', 2);
INSERT INTO `menu` VALUES (48, b'0', '角色创建', '', 3, 2, '', '', b'0', b'0', '', '2019-10-29 12:45:34', 'roles:add', 2);
INSERT INTO `menu` VALUES (49, b'0', '角色修改', '', 3, 3, '', '', b'0', b'0', '', '2019-10-29 12:46:16', 'roles:edit', 2);
INSERT INTO `menu` VALUES (50, b'0', '角色删除', '', 3, 4, '', '', b'0', b'0', '', '2019-10-29 12:46:51', 'roles:del', 2);
INSERT INTO `menu` VALUES (52, b'0', '菜单新增', '', 5, 2, '', '', b'0', b'0', '', '2019-10-29 12:55:07', 'menu:add', 2);
INSERT INTO `menu` VALUES (53, b'0', '菜单编辑', '', 5, 3, '', '', b'0', b'0', '', '2019-10-29 12:55:40', 'menu:edit', 2);
INSERT INTO `menu` VALUES (54, b'0', '菜单删除', '', 5, 4, '', '', b'0', b'0', '', '2019-10-29 12:56:00', 'menu:del', 2);
INSERT INTO `menu` VALUES (56, b'0', '部门新增', '', 35, 2, '', '', b'0', b'0', '', '2019-10-29 12:57:09', 'dept:add', 2);
INSERT INTO `menu` VALUES (57, b'0', '部门编辑', '', 35, 3, '', '', b'0', b'0', '', '2019-10-29 12:57:27', 'dept:edit', 2);
INSERT INTO `menu` VALUES (58, b'0', '部门删除', '', 35, 4, '', '', b'0', b'0', '', '2019-10-29 12:57:41', 'dept:del', 2);
INSERT INTO `menu` VALUES (60, b'0', '岗位新增', '', 37, 2, '', '', b'0', b'0', '', '2019-10-29 12:58:27', 'job:add', 2);
INSERT INTO `menu` VALUES (61, b'0', '岗位编辑', '', 37, 3, '', '', b'0', b'0', '', '2019-10-29 12:58:45', 'job:edit', 2);
INSERT INTO `menu` VALUES (62, b'0', '岗位删除', '', 37, 4, '', '', b'0', b'0', '', '2019-10-29 12:59:04', 'job:del', 2);
INSERT INTO `menu` VALUES (64, b'0', '字典新增', '', 39, 2, '', '', b'0', b'0', '', '2019-10-29 13:00:17', 'dict:add', 2);
INSERT INTO `menu` VALUES (65, b'0', '字典编辑', '', 39, 3, '', '', b'0', b'0', '', '2019-10-29 13:00:42', 'dict:edit', 2);
INSERT INTO `menu` VALUES (66, b'0', '字典删除', '', 39, 4, '', '', b'0', b'0', '', '2019-10-29 13:00:59', 'dict:del', 2);
INSERT INTO `menu` VALUES (68, b'0', '缓存删除', '', 8, 2, '', '', b'0', b'0', '', '2019-10-29 13:04:07', 'redis:del', 2);
INSERT INTO `menu` VALUES (70, b'0', '图片上传', '', 16, 2, '', '', b'0', b'0', '', '2019-10-29 13:05:34', 'pictures:add', 2);
INSERT INTO `menu` VALUES (71, b'0', '图片删除', '', 16, 3, '', '', b'0', b'0', '', '2019-10-29 13:05:52', 'pictures:del', 2);
INSERT INTO `menu` VALUES (73, b'0', '任务新增', '', 28, 2, '', '', b'0', b'0', '', '2019-10-29 13:07:28', 'timing:add', 2);
INSERT INTO `menu` VALUES (74, b'0', '任务编辑', '', 28, 3, '', '', b'0', b'0', '', '2019-10-29 13:07:41', 'timing:edit', 2);
INSERT INTO `menu` VALUES (75, b'0', '任务删除', '', 28, 4, '', '', b'0', b'0', '', '2019-10-29 13:07:54', 'timing:del', 2);
INSERT INTO `menu` VALUES (77, b'0', '上传文件', '', 18, 2, '', '', b'0', b'0', '', '2019-10-29 13:09:09', 'storage:add', 2);
INSERT INTO `menu` VALUES (78, b'0', '文件编辑', '', 18, 3, '', '', b'0', b'0', '', '2019-10-29 13:09:22', 'storage:edit', 2);
INSERT INTO `menu` VALUES (79, b'0', '文件删除', '', 18, 4, '', '', b'0', b'0', '', '2019-10-29 13:09:34', 'storage:del', 2);
-- ----------------------------
-- Table structure for picture
-- ----------------------------
DROP TABLE IF EXISTS `picture`;
CREATE TABLE `picture` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`create_time` datetime NULL DEFAULT NULL COMMENT '上传日期',
`delete_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '删除的URL',
`filename` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图片名称',
`height` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图片高度',
`size` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图片大小',
`url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图片地址',
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名称',
`width` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图片宽度',
`md5code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for qiniu_config
-- ----------------------------
DROP TABLE IF EXISTS `qiniu_config`;
CREATE TABLE `qiniu_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`access_key` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT 'accessKey',
`bucket` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Bucket 识别符',
`host` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '外链域名',
`secret_key` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT 'secretKey',
`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '空间类型',
`zone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '机房',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for qiniu_content
-- ----------------------------
DROP TABLE IF EXISTS `qiniu_content`;
CREATE TABLE `qiniu_content` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`bucket` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Bucket 识别符',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件名称',
`size` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件大小',
`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件类型:私有或公开',
`update_time` datetime NULL DEFAULT NULL COMMENT '上传或同步的时间',
`url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件url',
`suffix` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for quartz_job
-- ----------------------------
DROP TABLE IF EXISTS `quartz_job`;
CREATE TABLE `quartz_job` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`bean_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Spring Bean名称',
`cron_expression` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'cron 表达式',
`is_pause` bit(1) NULL DEFAULT NULL COMMENT '状态:1暂停、0启用',
`job_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '任务名称',
`method_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '方法名称',
`params` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数',
`remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建日期',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of quartz_job
-- ----------------------------
INSERT INTO `quartz_job` VALUES (1, 'visitsTask', '0 0 0 * * ?', b'0', '更新访客记录', 'run', NULL, '每日0点创建新的访客记录', '2019-01-08 14:53:31');
INSERT INTO `quartz_job` VALUES (2, 'testTask', '0/5 * * * * ?', b'1', '测试1', 'run1', 'test', '带参测试,多参使用json', '2019-08-22 14:08:29');
INSERT INTO `quartz_job` VALUES (3, 'testTask', '0/5 * * * * ?', b'1', '测试', 'run', '', '不带参测试', '2019-09-26 16:44:39');
-- ----------------------------
-- Table structure for quartz_log
-- ----------------------------
DROP TABLE IF EXISTS `quartz_log`;
CREATE TABLE `quartz_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`baen_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`create_time` datetime NULL DEFAULT NULL,
`cron_expression` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`exception_detail` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
`is_success` bit(1) NULL DEFAULT NULL,
`job_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`method_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`params` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`time` bigint(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '名称',
`remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注',
`data_scope` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`level` int(255) NULL DEFAULT NULL,
`create_time` datetime NULL DEFAULT NULL COMMENT '创建日期',
`permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES (1, '超级管理员', '-', '全部', 1, '2018-11-23 11:04:37', 'admin');
INSERT INTO `role` VALUES (2, '普通用户', '-', '自定义', 2, '2018-11-23 13:09:06', 'common');
-- ----------------------------
-- Table structure for roles_depts
-- ----------------------------
DROP TABLE IF EXISTS `roles_depts`;
CREATE TABLE `roles_depts` (
`role_id` bigint(20) NOT NULL,
`dept_id` bigint(20) NOT NULL,
PRIMARY KEY (`role_id`, `dept_id`) USING BTREE,
INDEX `FK7qg6itn5ajdoa9h9o78v9ksur`(`dept_id`) USING BTREE,
CONSTRAINT `FK7qg6itn5ajdoa9h9o78v9ksur` FOREIGN KEY (`dept_id`) REFERENCES `dept` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FKrg1ci4cxxfbja0sb0pddju7k` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of roles_depts
-- ----------------------------
INSERT INTO `roles_depts` VALUES (2, 2);
INSERT INTO `roles_depts` VALUES (2, 5);
-- ----------------------------
-- Table structure for roles_menus
-- ----------------------------
DROP TABLE IF EXISTS `roles_menus`;
CREATE TABLE `roles_menus` (
`menu_id` bigint(20) NOT NULL COMMENT '菜单ID',
`role_id` bigint(20) NOT NULL COMMENT '角色ID',
PRIMARY KEY (`menu_id`, `role_id`) USING BTREE,
INDEX `FKcngg2qadojhi3a651a5adkvbq`(`role_id`) USING BTREE,
CONSTRAINT `FKo7wsmlrrxb2osfaoavp46rv2r` FOREIGN KEY (`menu_id`) REFERENCES `menu` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FKtag324maketmxffly3pdyh193` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of roles_menus
-- ----------------------------
INSERT INTO `roles_menus` VALUES (1, 1);
INSERT INTO `roles_menus` VALUES (2, 1);
INSERT INTO `roles_menus` VALUES (3, 1);
INSERT INTO `roles_menus` VALUES (5, 1);
INSERT INTO `roles_menus` VALUES (6, 1);
INSERT INTO `roles_menus` VALUES (7, 1);
INSERT INTO `roles_menus` VALUES (8, 1);
INSERT INTO `roles_menus` VALUES (9, 1);
INSERT INTO `roles_menus` VALUES (10, 1);
INSERT INTO `roles_menus` VALUES (11, 1);
INSERT INTO `roles_menus` VALUES (14, 1);
INSERT INTO `roles_menus` VALUES (15, 1);
INSERT INTO `roles_menus` VALUES (16, 1);
INSERT INTO `roles_menus` VALUES (18, 1);
INSERT INTO `roles_menus` VALUES (19, 1);
INSERT INTO `roles_menus` VALUES (21, 1);
INSERT INTO `roles_menus` VALUES (22, 1);
INSERT INTO `roles_menus` VALUES (23, 1);
INSERT INTO `roles_menus` VALUES (24, 1);
INSERT INTO `roles_menus` VALUES (27, 1);
INSERT INTO `roles_menus` VALUES (28, 1);
INSERT INTO `roles_menus` VALUES (30, 1);
INSERT INTO `roles_menus` VALUES (32, 1);
INSERT INTO `roles_menus` VALUES (33, 1);
INSERT INTO `roles_menus` VALUES (34, 1);
INSERT INTO `roles_menus` VALUES (35, 1);
INSERT INTO `roles_menus` VALUES (36, 1);
INSERT INTO `roles_menus` VALUES (37, 1);
INSERT INTO `roles_menus` VALUES (38, 1);
INSERT INTO `roles_menus` VALUES (39, 1);
INSERT INTO `roles_menus` VALUES (41, 1);
INSERT INTO `roles_menus` VALUES (44, 1);
INSERT INTO `roles_menus` VALUES (45, 1);
INSERT INTO `roles_menus` VALUES (46, 1);
INSERT INTO `roles_menus` VALUES (48, 1);
INSERT INTO `roles_menus` VALUES (49, 1);
INSERT INTO `roles_menus` VALUES (50, 1);
INSERT INTO `roles_menus` VALUES (52, 1);
INSERT INTO `roles_menus` VALUES (53, 1);
INSERT INTO `roles_menus` VALUES (54, 1);
INSERT INTO `roles_menus` VALUES (56, 1);
INSERT INTO `roles_menus` VALUES (57, 1);
INSERT INTO `roles_menus` VALUES (58, 1);
INSERT INTO `roles_menus` VALUES (60, 1);
INSERT INTO `roles_menus` VALUES (61, 1);
INSERT INTO `roles_menus` VALUES (62, 1);
INSERT INTO `roles_menus` VALUES (64, 1);
INSERT INTO `roles_menus` VALUES (65, 1);
INSERT INTO `roles_menus` VALUES (66, 1);
INSERT INTO `roles_menus` VALUES (68, 1);
INSERT INTO `roles_menus` VALUES (70, 1);
INSERT INTO `roles_menus` VALUES (71, 1);
INSERT INTO `roles_menus` VALUES (73, 1);
INSERT INTO `roles_menus` VALUES (74, 1);
INSERT INTO `roles_menus` VALUES (75, 1);
INSERT INTO `roles_menus` VALUES (77, 1);
INSERT INTO `roles_menus` VALUES (78, 1);
INSERT INTO `roles_menus` VALUES (79, 1);
INSERT INTO `roles_menus` VALUES (1, 2);
INSERT INTO `roles_menus` VALUES (2, 2);
INSERT INTO `roles_menus` VALUES (3, 2);
INSERT INTO `roles_menus` VALUES (5, 2);
INSERT INTO `roles_menus` VALUES (6, 2);
INSERT INTO `roles_menus` VALUES (8, 2);
INSERT INTO `roles_menus` VALUES (9, 2);
INSERT INTO `roles_menus` VALUES (10, 2);
INSERT INTO `roles_menus` VALUES (11, 2);
INSERT INTO `roles_menus` VALUES (14, 2);
INSERT INTO `roles_menus` VALUES (15, 2);
INSERT INTO `roles_menus` VALUES (16, 2);
INSERT INTO `roles_menus` VALUES (18, 2);
INSERT INTO `roles_menus` VALUES (19, 2);
INSERT INTO `roles_menus` VALUES (21, 2);
INSERT INTO `roles_menus` VALUES (23, 2);
INSERT INTO `roles_menus` VALUES (24, 2);
INSERT INTO `roles_menus` VALUES (27, 2);
INSERT INTO `roles_menus` VALUES (28, 2);
INSERT INTO `roles_menus` VALUES (30, 2);
INSERT INTO `roles_menus` VALUES (33, 2);
INSERT INTO `roles_menus` VALUES (34, 2);
INSERT INTO `roles_menus` VALUES (35, 2);
INSERT INTO `roles_menus` VALUES (36, 2);
INSERT INTO `roles_menus` VALUES (37, 2);
INSERT INTO `roles_menus` VALUES (38, 2);
INSERT INTO `roles_menus` VALUES (39, 2);
INSERT INTO `roles_menus` VALUES (70, 2);
INSERT INTO `roles_menus` VALUES (71, 2);
INSERT INTO `roles_menus` VALUES (77, 2);
INSERT INTO `roles_menus` VALUES (78, 2);
INSERT INTO `roles_menus` VALUES (79, 2);
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`avatar_id` bigint(20) NULL DEFAULT NULL COMMENT '头像',
`email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
`enabled` bigint(20) NULL DEFAULT NULL COMMENT '状态:1启用、0禁用',
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
`dept_id` bigint(20) NULL DEFAULT NULL,
`phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`job_id` bigint(20) NULL DEFAULT NULL,
`create_time` datetime NULL DEFAULT NULL COMMENT '创建日期',
`last_password_reset_time` datetime NULL DEFAULT NULL COMMENT '最后修改密码的日期',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `UK_kpubos9gc2cvtkb0thktkbkes`(`email`) USING BTREE,
UNIQUE INDEX `username`(`username`) USING BTREE,
INDEX `FK5rwmryny6jthaaxkogownknqp`(`dept_id`) USING BTREE,
INDEX `FKfftoc2abhot8f2wu6cl9a5iky`(`job_id`) USING BTREE,
INDEX `FKpq2dhypk2qgt68nauh2by22jb`(`avatar_id`) USING BTREE,
CONSTRAINT `FK5rwmryny6jthaaxkogownknqp` FOREIGN KEY (`dept_id`) REFERENCES `dept` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FKfftoc2abhot8f2wu6cl9a5iky` FOREIGN KEY (`job_id`) REFERENCES `job` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FKpq2dhypk2qgt68nauh2by22jb` FOREIGN KEY (`avatar_id`) REFERENCES `user_avatar` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, NULL, 'admin@eladmin.net', 1, 'e10adc3949ba59abbe56e057f20f883e', 'admin', 2, '18888888888', 11, '2018-08-23 09:11:56', '2019-05-18 17:34:21');
INSERT INTO `user` VALUES (3, NULL, 'test@eladmin.net', 1, 'e10adc3949ba59abbe56e057f20f883e', 'test', 2, '17777777777', 12, '2018-12-27 20:05:26', '2019-04-01 09:15:24');
-- ----------------------------
-- Table structure for user_avatar
-- ----------------------------
DROP TABLE IF EXISTS `user_avatar`;
CREATE TABLE `user_avatar` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`real_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`size` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`create_time` datetime NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for users_roles
-- ----------------------------
DROP TABLE IF EXISTS `users_roles`;
CREATE TABLE `users_roles` (
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`role_id` bigint(20) NOT NULL COMMENT '角色ID',
PRIMARY KEY (`user_id`, `role_id`) USING BTREE,
INDEX `FKq4eq273l04bpu4efj0jd0jb98`(`role_id`) USING BTREE,
CONSTRAINT `FKgd3iendaoyh04b95ykqise6qh` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FKt4v0rrweyk393bdgt107vdx0x` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of users_roles
-- ----------------------------
INSERT INTO `users_roles` VALUES (1, 1);
INSERT INTO `users_roles` VALUES (3, 2);
-- ----------------------------
-- Table structure for verification_code
-- ----------------------------
DROP TABLE IF EXISTS `verification_code`;
CREATE TABLE `verification_code` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '验证码',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建日期',
`status` bit(1) NULL DEFAULT NULL COMMENT '状态:1有效、0过期',
`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '验证码类型:email或者短信',
`value` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '接收邮箱或者手机号码',
`scenes` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '业务名称:如重置邮箱、重置密码等',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Table structure for visits
-- ----------------------------
DROP TABLE IF EXISTS `visits`;
CREATE TABLE `visits` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`create_time` datetime NULL DEFAULT NULL,
`date` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`ip_counts` bigint(20) NULL DEFAULT NULL,
`pv_counts` bigint(20) NULL DEFAULT NULL,
`week_day` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `UK_11aksgq87euk9bcyeesfs4vtp`(`date`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 111 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of visits
-- ----------------------------
INSERT INTO `visits` VALUES (108, '2019-10-29 21:45:49', '2019-10-29', 1, 1, 'Tue');
INSERT INTO `visits` VALUES (109, '2019-10-30 08:58:54', '2019-10-30', 2, 11, 'Wed');
INSERT INTO `visits` VALUES (110, '2019-10-31 09:04:18', '2019-10-31', 2, 8, 'Thu');
SET FOREIGN_KEY_CHECKS = 1;
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论