mirror of https://github.com/elunez/eladmin
Merge branch '2.3dev'
commit
fd9fb2a600
26
README.md
26
README.md
|
|
@ -21,13 +21,12 @@ eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前
|
||||||
|
|
||||||
| | 后端源码 | 前端源码 |
|
| | 后端源码 | 前端源码 |
|
||||||
|--- |--- | --- |
|
|--- |--- | --- |
|
||||||
| github | https://github.com/elunez/eladmin | https://github.com/elunez/eladmin-qd |
|
| github | https://github.com/elunez/eladmin | https://github.com/elunez/eladmin-web |
|
||||||
| 码云 | https://gitee.com/elunez/eladmin | https://gitee.com/elunez/eladmin-qt |
|
| 码云 | https://gitee.com/elunez/eladmin | https://gitee.com/elunez/eladmin-web |
|
||||||
|
|
||||||
#### 系统功能
|
#### 系统功能
|
||||||
- 用户管理:提供用户的相关配置,新增用户后,默认密码为123456
|
- 用户管理:提供用户的相关配置,新增用户后,默认密码为123456
|
||||||
- 角色管理:对权限与菜单进行分配,可根据部门设置角色的数据权限
|
- 角色管理:对权限与菜单进行分配,可根据部门设置角色的数据权限
|
||||||
- 权限管理:权限细化到接口,可以理解成按钮权限
|
|
||||||
- 菜单管理:已实现菜单动态路由,后端可配置化,支持多级菜单
|
- 菜单管理:已实现菜单动态路由,后端可配置化,支持多级菜单
|
||||||
- 部门管理:可配置系统组织架构,树形表格展示
|
- 部门管理:可配置系统组织架构,树形表格展示
|
||||||
- 岗位管理:配置各个部门的职位
|
- 岗位管理:配置各个部门的职位
|
||||||
|
|
@ -44,16 +43,19 @@ eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前
|
||||||
- 支付宝支付:整合了支付宝支付并且提供了测试账号,可自行测试
|
- 支付宝支付:整合了支付宝支付并且提供了测试账号,可自行测试
|
||||||
|
|
||||||
#### 项目结构
|
#### 项目结构
|
||||||
项目采用分模块开发方式,将通用的配置放在公共模块,```system```模块为系统核心模块也是项目入口模块,```logging``` 模块为系统的日志模块,```tools``` 为第三方工具模块,包含了图床、邮件、七牛云、支付宝,```generator``` 为系统的代码生成模块
|
项目采用按功能分模块开发方式,将通用的配置放在公共模块,```system```模块为系统核心模块也是项目入口模块,```logging``` 模块为系统的日志模块,```tools``` 为第三方工具模块,包含了图床、邮件、七牛云、支付宝,```generator``` 为系统的代码生成模块
|
||||||
|
|
||||||
- eladmin-common 公共模块
|
- eladmin-common 公共模块
|
||||||
- exception 项目统一异常的处理
|
- annotation 为系统自定义注解
|
||||||
- mapper mapstruct的通用mapper
|
- aspect 自定义注解的切面
|
||||||
- redis redis缓存相关配置
|
- base 提供了Entity、DTO基类和mapstruct的通用mapper
|
||||||
- swagger2 接口文档配置
|
- config 自定义权限实现、redis配置、swagger配置
|
||||||
- utils 系统通用工具类
|
- exception 项目统一异常的处理
|
||||||
|
- utils 系统通用工具类
|
||||||
- eladmin-system 系统核心模块(系统启动入口)
|
- eladmin-system 系统核心模块(系统启动入口)
|
||||||
- config 配置跨域与静态资源,与数据权限
|
- config 配置跨域与静态资源,与数据权限
|
||||||
- modules 系统相关模块(登录授权、定时任务等)
|
- thread 线程池相关
|
||||||
|
- modules 系统相关模块(登录授权、系统监控、定时任务等)
|
||||||
- eladmin-logging 系统日志模块
|
- eladmin-logging 系统日志模块
|
||||||
- eladmin-tools 系统第三方工具模块
|
- eladmin-tools 系统第三方工具模块
|
||||||
- eladmin-generator 系统代码生成模块
|
- eladmin-generator 系统代码生成模块
|
||||||
|
|
@ -78,6 +80,6 @@ eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
#### 项目捐赠
|
#### 项目捐赠
|
||||||
项目的发展离不开你的支持,请作者喝杯咖啡吧 ☕! [Donate](https://docs.auauz.net/#/jz)
|
项目的发展离不开你的支持,请作者喝杯咖啡吧!ps:辣条也行 ☕! [Donate](https://docs.auauz.net/#/jz)
|
||||||
#### 反馈交流
|
#### 反馈交流
|
||||||
- QQ交流群:891137268
|
- QQ交流群:891137268
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,10 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>eladmin</artifactId>
|
<artifactId>eladmin</artifactId>
|
||||||
<groupId>me.zhengjie</groupId>
|
<groupId>me.zhengjie</groupId>
|
||||||
<version>2.2</version>
|
<version>2.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<artifactId>eladmin-common</artifactId>
|
<artifactId>eladmin-common</artifactId>
|
||||||
<name>公共模块</name>
|
<name>公共模块</name>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
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 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -13,45 +13,42 @@ import java.lang.annotation.Target;
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Query {
|
public @interface Query {
|
||||||
|
|
||||||
/** Dong ZhaoYang 2017/8/7 基本对象的属性名 */
|
// Dong ZhaoYang 2017/8/7 基本对象的属性名
|
||||||
String propName() default "";
|
String propName() default "";
|
||||||
/** Dong ZhaoYang 2017/8/7 查询方式 */
|
// Dong ZhaoYang 2017/8/7 查询方式
|
||||||
Type type() default Type.EQUAL;
|
Type type() default Type.EQUAL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 连接查询的属性名,如User类中的dept
|
* 连接查询的属性名,如User类中的dept
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
String joinName() default "";
|
String joinName() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认左连接
|
* 默认左连接
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
Join join() default Join.LEFT;
|
Join join() default Join.LEFT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多字段模糊搜索,仅支持String类型字段,多个用逗号隔开, 如@Query(blurry = "email,username")
|
* 多字段模糊搜索,仅支持String类型字段,多个用逗号隔开, 如@Query(blurry = "email,username")
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
String blurry() default "";
|
String blurry() default "";
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
/** jie 2019/6/4 相等 */
|
// jie 2019/6/4 相等
|
||||||
EQUAL
|
EQUAL
|
||||||
/** Dong ZhaoYang 2017/8/7 大于等于 */
|
// Dong ZhaoYang 2017/8/7 大于等于
|
||||||
, GREATER_THAN
|
, GREATER_THAN
|
||||||
/** Dong ZhaoYang 2017/8/7 小于等于 */
|
// Dong ZhaoYang 2017/8/7 小于等于
|
||||||
, LESS_THAN
|
, LESS_THAN
|
||||||
/** Dong ZhaoYang 2017/8/7 中模糊查询 */
|
// Dong ZhaoYang 2017/8/7 中模糊查询
|
||||||
, INNER_LIKE
|
, INNER_LIKE
|
||||||
/** Dong ZhaoYang 2017/8/7 左模糊查询 */
|
// Dong ZhaoYang 2017/8/7 左模糊查询
|
||||||
, LEFT_LIKE
|
, LEFT_LIKE
|
||||||
/** Dong ZhaoYang 2017/8/7 右模糊查询 */
|
// Dong ZhaoYang 2017/8/7 右模糊查询
|
||||||
, RIGHT_LIKE
|
, RIGHT_LIKE
|
||||||
/** Dong ZhaoYang 2017/8/7 小于 */
|
// Dong ZhaoYang 2017/8/7 小于
|
||||||
, LESS_THAN_NQ
|
, LESS_THAN_NQ
|
||||||
//** jie 2019/6/4 包含 */
|
// jie 2019/6/4 包含
|
||||||
, IN
|
, IN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import org.aspectj.lang.annotation.Pointcut;
|
||||||
import org.aspectj.lang.reflect.MethodSignature;
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||||
import org.springframework.data.redis.core.script.RedisScript;
|
import org.springframework.data.redis.core.script.RedisScript;
|
||||||
|
|
@ -23,10 +22,13 @@ import java.lang.reflect.Method;
|
||||||
@Aspect
|
@Aspect
|
||||||
@Component
|
@Component
|
||||||
public class LimitAspect {
|
public class LimitAspect {
|
||||||
@Autowired
|
|
||||||
private RedisTemplate redisTemplate;
|
private final RedisTemplate<Object,Object> redisTemplate;
|
||||||
private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class);
|
private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class);
|
||||||
|
|
||||||
|
public LimitAspect(RedisTemplate<Object,Object> redisTemplate) {
|
||||||
|
this.redisTemplate = redisTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
@Pointcut("@annotation(me.zhengjie.annotation.Limit)")
|
@Pointcut("@annotation(me.zhengjie.annotation.Limit)")
|
||||||
public void pointcut() {
|
public void pointcut() {
|
||||||
|
|
@ -41,20 +43,18 @@ public class LimitAspect {
|
||||||
LimitType limitType = limit.limitType();
|
LimitType limitType = limit.limitType();
|
||||||
String key = limit.key();
|
String key = limit.key();
|
||||||
if (StringUtils.isEmpty(key)) {
|
if (StringUtils.isEmpty(key)) {
|
||||||
switch (limitType) {
|
if (limitType == LimitType.IP) {
|
||||||
case IP:
|
key = StringUtils.getIp(request);
|
||||||
key = StringUtils.getIP(request);
|
} else {
|
||||||
break;
|
key = signatureMethod.getName();
|
||||||
default:
|
|
||||||
key = signatureMethod.getName();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmutableList keys = ImmutableList.of(StringUtils.join(limit.prefix(), "_", key, "_", request.getRequestURI().replaceAll("/","_")));
|
ImmutableList<Object> keys = ImmutableList.of(StringUtils.join(limit.prefix(), "_", key, "_", request.getRequestURI().replaceAll("/","_")));
|
||||||
|
|
||||||
String luaScript = buildLuaScript();
|
String luaScript = buildLuaScript();
|
||||||
RedisScript<Number> redisScript = new DefaultRedisScript<>(luaScript, Number.class);
|
RedisScript<Number> redisScript = new DefaultRedisScript<>(luaScript, Number.class);
|
||||||
Number count = (Number) redisTemplate.execute(redisScript, keys, limit.count(), limit.period());
|
Number count = redisTemplate.execute(redisScript, keys, limit.count(), limit.period());
|
||||||
if (null != count && count.intValue() <= limit.count()) {
|
if (null != count && count.intValue() <= limit.count()) {
|
||||||
logger.info("第{}次访问key为 {},描述为 [{}] 的接口", count, keys, limit.name());
|
logger.info("第{}次访问key为 {},描述为 [{}] 的接口", count, keys, limit.name());
|
||||||
return joinPoint.proceed();
|
return joinPoint.proceed();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
package me.zhengjie.aspect;
|
package me.zhengjie.aspect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流枚举
|
||||||
|
* @author /
|
||||||
|
*/
|
||||||
public enum LimitType {
|
public enum LimitType {
|
||||||
|
// 默认
|
||||||
CUSTOMER,
|
CUSTOMER,
|
||||||
// by ip addr
|
// by ip addr
|
||||||
IP;
|
IP;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package me.zhengjie.mapper;
|
package me.zhengjie.base;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -6,33 +6,25 @@ import java.util.List;
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
*/
|
*/
|
||||||
public interface EntityMapper<D, E> {
|
public interface BaseMapper<D, E> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DTO转Entity
|
* DTO转Entity
|
||||||
* @param dto
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
E toEntity(D dto);
|
E toEntity(D dto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity转DTO
|
* Entity转DTO
|
||||||
* @param entity
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
D toDto(E entity);
|
D toDto(E entity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DTO集合转Entity集合
|
* DTO集合转Entity集合
|
||||||
* @param dtoList
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
List <E> toEntity(List<D> dtoList);
|
List <E> toEntity(List<D> dtoList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity集合转DTO集合
|
* Entity集合转DTO集合
|
||||||
* @param entityList
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
List <D> toDto(List<E> entityList);
|
List <D> toDto(List<E> entityList);
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
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());
|
||||||
|
// 判断当前用户的所有权限是否包含接口上定义的权限
|
||||||
|
List<String> list = Arrays.stream(permissions).filter(elPermissions::contains).collect(Collectors.toList());
|
||||||
|
return elPermissions.contains("admin") || list.size() != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
package me.zhengjie.redis;
|
package me.zhengjie.config;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.parser.ParserConfig;
|
import com.alibaba.fastjson.parser.ParserConfig;
|
||||||
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||||||
|
|
@ -19,7 +23,12 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
import org.springframework.data.redis.core.RedisOperations;
|
import org.springframework.data.redis.core.RedisOperations;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
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.time.Duration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
|
|
@ -28,21 +37,19 @@ import java.time.Duration;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableCaching
|
@EnableCaching
|
||||||
// 自动配置
|
|
||||||
@ConditionalOnClass(RedisOperations.class)
|
@ConditionalOnClass(RedisOperations.class)
|
||||||
@EnableConfigurationProperties(RedisProperties.class)
|
@EnableConfigurationProperties(RedisProperties.class)
|
||||||
public class RedisConfig extends CachingConfigurerSupport {
|
public class RedisConfig extends CachingConfigurerSupport {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置 redis 数据默认过期时间,默认1天
|
* 设置 redis 数据默认过期时间,默认6小时
|
||||||
* 设置@cacheable 序列化方式
|
* 设置@cacheable 序列化方式
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public RedisCacheConfiguration redisCacheConfiguration(){
|
public RedisCacheConfiguration redisCacheConfiguration(){
|
||||||
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
|
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
|
||||||
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
|
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
|
||||||
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofDays(1));
|
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(6));
|
||||||
return configuration;
|
return configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,21 +58,20 @@ public class RedisConfig extends CachingConfigurerSupport {
|
||||||
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||||||
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
||||||
//序列化
|
//序列化
|
||||||
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
|
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
|
||||||
// value值的序列化采用fastJsonRedisSerializer
|
// value值的序列化采用fastJsonRedisSerializer
|
||||||
template.setValueSerializer(fastJsonRedisSerializer);
|
template.setValueSerializer(fastJsonRedisSerializer);
|
||||||
template.setHashValueSerializer(fastJsonRedisSerializer);
|
template.setHashValueSerializer(fastJsonRedisSerializer);
|
||||||
|
// 全局开启AutoType,这里方便开发,使用全局的方式
|
||||||
// 全局开启AutoType,不建议使用
|
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
|
||||||
// ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
|
|
||||||
// 建议使用这种方式,小范围指定白名单
|
// 建议使用这种方式,小范围指定白名单
|
||||||
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.domain");
|
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.domain");
|
||||||
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.service.dto");
|
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.service.dto");
|
||||||
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.service.dto");
|
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.service.dto");
|
||||||
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.domain");
|
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.domain");
|
||||||
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.quartz.domain");
|
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.quartz.domain");
|
||||||
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.monitor.domain");
|
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.monitor.domain");
|
||||||
ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.security.security");
|
// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.security.security");
|
||||||
// key的序列化采用StringRedisSerializer
|
// key的序列化采用StringRedisSerializer
|
||||||
template.setKeySerializer(new StringRedisSerializer());
|
template.setKeySerializer(new StringRedisSerializer());
|
||||||
template.setHashKeySerializer(new StringRedisSerializer());
|
template.setHashKeySerializer(new StringRedisSerializer());
|
||||||
|
|
@ -75,20 +81,27 @@ public class RedisConfig extends CachingConfigurerSupport {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义缓存key生成策略,默认将使用该策略
|
* 自定义缓存key生成策略,默认将使用该策略
|
||||||
* 使用方法 @Cacheable
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
@Override
|
@Override
|
||||||
public KeyGenerator keyGenerator() {
|
public KeyGenerator keyGenerator() {
|
||||||
return (target, method, params) -> {
|
return (target, method, params) -> {
|
||||||
StringBuilder sb = new StringBuilder();
|
Map<String,Object> container = new HashMap<>();
|
||||||
sb.append(target.getClass().getName());
|
Class<?> targetClassClass = target.getClass();
|
||||||
sb.append(method.getName());
|
// 类地址
|
||||||
for (Object obj : params) {
|
container.put("class",targetClassClass.toGenericString());
|
||||||
sb.append(JSON.toJSONString(obj).hashCode());
|
// 方法名称
|
||||||
|
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]);
|
||||||
}
|
}
|
||||||
return sb.toString();
|
// 转为JSON字符串
|
||||||
|
String jsonString = JSON.toJSONString(container);
|
||||||
|
// 做SHA256 Hash计算,得到一个SHA256摘要作为Key
|
||||||
|
return DigestUtils.sha256Hex(jsonString);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,7 +110,7 @@ public class RedisConfig extends CachingConfigurerSupport {
|
||||||
public CacheErrorHandler errorHandler() {
|
public CacheErrorHandler errorHandler() {
|
||||||
// 异常处理,当Redis发生异常时,打印日志,但是程序正常走
|
// 异常处理,当Redis发生异常时,打印日志,但是程序正常走
|
||||||
log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
|
log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
|
||||||
CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
|
return new CacheErrorHandler() {
|
||||||
@Override
|
@Override
|
||||||
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
|
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
|
||||||
log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
|
log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
|
||||||
|
|
@ -118,7 +131,74 @@ public class RedisConfig extends CachingConfigurerSupport {
|
||||||
log.error("Redis occur handleCacheClearError:", e);
|
log.error("Redis occur handleCacheClearError:", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return cacheErrorHandler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,20 @@
|
||||||
package me.zhengjie.swagger2;
|
package me.zhengjie.config;
|
||||||
|
|
||||||
|
import com.fasterxml.classmate.TypeResolver;
|
||||||
import com.google.common.base.Predicates;
|
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.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
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.ApiInfoBuilder;
|
||||||
import springfox.documentation.builders.ParameterBuilder;
|
import springfox.documentation.builders.ParameterBuilder;
|
||||||
import springfox.documentation.builders.PathSelectors;
|
import springfox.documentation.builders.PathSelectors;
|
||||||
|
import springfox.documentation.schema.AlternateTypeRule;
|
||||||
|
import springfox.documentation.schema.AlternateTypeRuleConvention;
|
||||||
import springfox.documentation.schema.ModelRef;
|
import springfox.documentation.schema.ModelRef;
|
||||||
import springfox.documentation.service.ApiInfo;
|
import springfox.documentation.service.ApiInfo;
|
||||||
import springfox.documentation.service.Parameter;
|
import springfox.documentation.service.Parameter;
|
||||||
|
|
@ -15,6 +23,8 @@ import springfox.documentation.spring.web.plugins.Docket;
|
||||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
|
import static springfox.documentation.schema.AlternateTypeRules.newRule;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* api页面 /swagger-ui.html
|
* api页面 /swagger-ui.html
|
||||||
|
|
@ -33,9 +43,10 @@ public class SwaggerConfig {
|
||||||
private Boolean enabled;
|
private Boolean enabled;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@SuppressWarnings("all")
|
||||||
public Docket createRestApi() {
|
public Docket createRestApi() {
|
||||||
ParameterBuilder ticketPar = new ParameterBuilder();
|
ParameterBuilder ticketPar = new ParameterBuilder();
|
||||||
List<Parameter> pars = new ArrayList<Parameter>();
|
List<Parameter> pars = new ArrayList<>();
|
||||||
ticketPar.name(tokenHeader).description("token")
|
ticketPar.name(tokenHeader).description("token")
|
||||||
.modelRef(new ModelRef("string"))
|
.modelRef(new ModelRef("string"))
|
||||||
.parameterType("header")
|
.parameterType("header")
|
||||||
|
|
@ -55,8 +66,43 @@ public class SwaggerConfig {
|
||||||
private ApiInfo apiInfo() {
|
private ApiInfo apiInfo() {
|
||||||
return new ApiInfoBuilder()
|
return new ApiInfoBuilder()
|
||||||
.title("eladmin 接口文档")
|
.title("eladmin 接口文档")
|
||||||
.version("2.1")
|
.version("2.3")
|
||||||
.build();
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,6 @@ package me.zhengjie.exception;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -2,33 +2,18 @@ package me.zhengjie.exception;
|
||||||
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
*/
|
*/
|
||||||
public class EntityExistException extends RuntimeException {
|
public class EntityExistException extends RuntimeException {
|
||||||
|
|
||||||
public EntityExistException(Class clazz, Object... saveBodyParamsMap) {
|
public EntityExistException(Class clazz, String field, String val) {
|
||||||
super(EntityExistException.generateMessage(clazz.getSimpleName(), toMap(String.class, String.class, saveBodyParamsMap)));
|
super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String generateMessage(String entity, Map<String, String> saveBodyParams) {
|
private static String generateMessage(String entity, String field, String val) {
|
||||||
return StringUtils.capitalize(entity) +
|
return StringUtils.capitalize(entity)
|
||||||
" 已存在 " +
|
+ " with " + field + " "+ val + " existed";
|
||||||
saveBodyParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <K, V> Map<K, V> toMap(
|
|
||||||
Class<K> keyType, Class<V> valueType, Object... entries) {
|
|
||||||
if (entries.length % 2 == 1)
|
|
||||||
throw new IllegalArgumentException("Invalid entries");
|
|
||||||
return IntStream.range(0, entries.length / 2).map(i -> i * 2)
|
|
||||||
.collect(HashMap::new,
|
|
||||||
(m, i) -> m.put(keyType.cast(entries[i]), valueType.cast(entries[i + 1])),
|
|
||||||
Map::putAll);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,34 +2,18 @@ package me.zhengjie.exception;
|
||||||
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
*/
|
*/
|
||||||
public class EntityNotFoundException extends RuntimeException {
|
public class EntityNotFoundException extends RuntimeException {
|
||||||
|
|
||||||
public EntityNotFoundException(Class clazz, Object... searchParamsMap) {
|
public EntityNotFoundException(Class clazz, String field, String val) {
|
||||||
super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), toMap(String.class, String.class, searchParamsMap)));
|
super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String generateMessage(String entity, Map<String, String> searchParams) {
|
private static String generateMessage(String entity, String field, String val) {
|
||||||
return StringUtils.capitalize(entity) +
|
return StringUtils.capitalize(entity)
|
||||||
" 不存在 " +
|
+ " with " + field + " "+ val + " does not exist";
|
||||||
searchParams;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <K, V> Map<K, V> toMap(
|
|
||||||
Class<K> keyType, Class<V> valueType, Object... entries) {
|
|
||||||
if (entries.length % 2 == 1)
|
|
||||||
throw new IllegalArgumentException("Invalid entries");
|
|
||||||
return IntStream.range(0, entries.length / 2).map(i -> i * 2)
|
|
||||||
.collect(HashMap::new,
|
|
||||||
(m, i) -> m.put(keyType.cast(entries[i]), valueType.cast(entries[i + 1])),
|
|
||||||
Map::putAll);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +12,7 @@ import java.time.LocalDateTime;
|
||||||
@Data
|
@Data
|
||||||
class ApiError {
|
class ApiError {
|
||||||
|
|
||||||
private Integer status;
|
private Integer status = 400;
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private LocalDateTime timestamp;
|
private LocalDateTime timestamp;
|
||||||
private String message;
|
private String message;
|
||||||
|
|
@ -21,10 +21,17 @@ class ApiError {
|
||||||
timestamp = LocalDateTime.now();
|
timestamp = LocalDateTime.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApiError(Integer status,String message) {
|
public static ApiError error(String message){
|
||||||
this();
|
ApiError apiError = new ApiError();
|
||||||
this.status = status;
|
apiError.setMessage(message);
|
||||||
this.message = message;
|
return apiError;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiError error(Integer status, String message){
|
||||||
|
ApiError apiError = new ApiError();
|
||||||
|
apiError.setStatus(status);
|
||||||
|
apiError.setMessage(message);
|
||||||
|
return apiError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
import java.util.Objects;
|
||||||
import static org.springframework.http.HttpStatus.*;
|
import static org.springframework.http.HttpStatus.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -23,91 +24,73 @@ public class GlobalExceptionHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理所有不可知的异常
|
* 处理所有不可知的异常
|
||||||
* @param e
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@ExceptionHandler(Throwable.class)
|
@ExceptionHandler(Throwable.class)
|
||||||
public ResponseEntity handleException(Throwable e){
|
public ResponseEntity handleException(Throwable e){
|
||||||
// 打印堆栈信息
|
// 打印堆栈信息
|
||||||
log.error(ThrowableUtil.getStackTrace(e));
|
log.error(ThrowableUtil.getStackTrace(e));
|
||||||
ApiError apiError = new ApiError(BAD_REQUEST.value(),e.getMessage());
|
return buildResponseEntity(ApiError.error(e.getMessage()));
|
||||||
return buildResponseEntity(apiError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理 接口无权访问异常AccessDeniedException
|
* 处理 接口无权访问异常AccessDeniedException
|
||||||
* @param e
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@ExceptionHandler(AccessDeniedException.class)
|
@ExceptionHandler(AccessDeniedException.class)
|
||||||
public ResponseEntity handleAccessDeniedException(AccessDeniedException e){
|
public ResponseEntity handleAccessDeniedException(AccessDeniedException e){
|
||||||
// 打印堆栈信息
|
// 打印堆栈信息
|
||||||
log.error(ThrowableUtil.getStackTrace(e));
|
log.error(ThrowableUtil.getStackTrace(e));
|
||||||
ApiError apiError = new ApiError(FORBIDDEN.value(),e.getMessage());
|
return buildResponseEntity(ApiError.error(FORBIDDEN.value(),e.getMessage()));
|
||||||
return buildResponseEntity(apiError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理自定义异常
|
* 处理自定义异常
|
||||||
* @param e
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@ExceptionHandler(value = BadRequestException.class)
|
@ExceptionHandler(value = BadRequestException.class)
|
||||||
public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
|
public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
|
||||||
// 打印堆栈信息
|
// 打印堆栈信息
|
||||||
log.error(ThrowableUtil.getStackTrace(e));
|
log.error(ThrowableUtil.getStackTrace(e));
|
||||||
ApiError apiError = new ApiError(e.getStatus(),e.getMessage());
|
return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage()));
|
||||||
return buildResponseEntity(apiError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理 EntityExist
|
* 处理 EntityExist
|
||||||
* @param e
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@ExceptionHandler(value = EntityExistException.class)
|
@ExceptionHandler(value = EntityExistException.class)
|
||||||
public ResponseEntity<ApiError> entityExistException(EntityExistException e) {
|
public ResponseEntity<ApiError> entityExistException(EntityExistException e) {
|
||||||
// 打印堆栈信息
|
// 打印堆栈信息
|
||||||
log.error(ThrowableUtil.getStackTrace(e));
|
log.error(ThrowableUtil.getStackTrace(e));
|
||||||
ApiError apiError = new ApiError(BAD_REQUEST.value(),e.getMessage());
|
return buildResponseEntity(ApiError.error(e.getMessage()));
|
||||||
return buildResponseEntity(apiError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理 EntityNotFound
|
* 处理 EntityNotFound
|
||||||
* @param e
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@ExceptionHandler(value = EntityNotFoundException.class)
|
@ExceptionHandler(value = EntityNotFoundException.class)
|
||||||
public ResponseEntity<ApiError> entityNotFoundException(EntityNotFoundException e) {
|
public ResponseEntity<ApiError> entityNotFoundException(EntityNotFoundException e) {
|
||||||
// 打印堆栈信息
|
// 打印堆栈信息
|
||||||
log.error(ThrowableUtil.getStackTrace(e));
|
log.error(ThrowableUtil.getStackTrace(e));
|
||||||
ApiError apiError = new ApiError(NOT_FOUND.value(),e.getMessage());
|
return buildResponseEntity(ApiError.error(NOT_FOUND.value(),e.getMessage()));
|
||||||
return buildResponseEntity(apiError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理所有接口数据验证异常
|
* 处理所有接口数据验证异常
|
||||||
* @param e
|
|
||||||
* @returns
|
|
||||||
*/
|
*/
|
||||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
public ResponseEntity<ApiError> handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
|
public ResponseEntity<ApiError> handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
|
||||||
// 打印堆栈信息
|
// 打印堆栈信息
|
||||||
log.error(ThrowableUtil.getStackTrace(e));
|
log.error(ThrowableUtil.getStackTrace(e));
|
||||||
String[] str = e.getBindingResult().getAllErrors().get(0).getCodes()[1].split("\\.");
|
String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
|
||||||
StringBuffer msg = new StringBuffer(str[1]+":");
|
String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
|
||||||
msg.append(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
if("不能为空".equals(message)){
|
||||||
ApiError apiError = new ApiError(BAD_REQUEST.value(),msg.toString());
|
message = str[1] + ":" + message;
|
||||||
return buildResponseEntity(apiError);
|
}
|
||||||
|
return buildResponseEntity(ApiError.error(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一返回
|
* 统一返回
|
||||||
* @param apiError
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
|
private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
|
||||||
return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
|
return new ResponseEntity<>(apiError, HttpStatus.valueOf(apiError.getStatus()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
package me.zhengjie.redis;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
|
||||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
|
||||||
import org.springframework.data.redis.serializer.SerializationException;
|
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Value 序列化
|
|
||||||
*
|
|
||||||
* @author /
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
|
|
||||||
|
|
||||||
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
|
||||||
|
|
||||||
private Class<T> clazz;
|
|
||||||
|
|
||||||
public FastJsonRedisSerializer(Class<T> clazz) {
|
|
||||||
super();
|
|
||||||
this.clazz = clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] serialize(T t) throws SerializationException {
|
|
||||||
if (t == null) {
|
|
||||||
return new byte[0];
|
|
||||||
}
|
|
||||||
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T deserialize(byte[] bytes) throws SerializationException {
|
|
||||||
if (bytes == null || bytes.length <= 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String str = new String(bytes, DEFAULT_CHARSET);
|
|
||||||
return (T) JSON.parseObject(str, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
package me.zhengjie.redis;
|
|
||||||
|
|
||||||
import cn.hutool.core.lang.Assert;
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重写序列化器
|
|
||||||
*
|
|
||||||
* @author /
|
|
||||||
*/
|
|
||||||
public class StringRedisSerializer implements RedisSerializer<Object> {
|
|
||||||
|
|
||||||
private final Charset charset;
|
|
||||||
|
|
||||||
private final String target = "\"";
|
|
||||||
|
|
||||||
private final String replacement = "";
|
|
||||||
|
|
||||||
public StringRedisSerializer() {
|
|
||||||
this(Charset.forName("UTF8"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public 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 (string == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
string = string.replace(target, replacement);
|
|
||||||
return string.getBytes(charset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
package me.zhengjie.swagger2;
import com.fasterxml.classmate.TypeResolver;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
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.schema.AlternateTypeRule;
import springfox.documentation.schema.AlternateTypeRuleConvention;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
import static springfox.documentation.schema.AlternateTypeRules.newRule;
/**
* 将Pageable转换展示在swagger中
*/
@Configuration
public 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
static class Page {
@ApiModelProperty("页码 (0..N)")
private Integer page;
@ApiModelProperty("每页显示的数目")
private Integer size;
@ApiModelProperty("以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc")
private List<String> sort;
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public List<String> getSort() {
return sort;
}
public void setSort(List<String> sort) {
this.sort = sort;
}
}
}
|
|
||||||
|
|
@ -14,7 +14,7 @@ public class ElAdminConstant {
|
||||||
/**
|
/**
|
||||||
* 用于IP定位转换
|
* 用于IP定位转换
|
||||||
*/
|
*/
|
||||||
public static final String REGION = "内网IP|内网IP";
|
static final String REGION = "内网IP|内网IP";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 常用接口
|
* 常用接口
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import javax.crypto.SecretKey;
|
||||||
import javax.crypto.SecretKeyFactory;
|
import javax.crypto.SecretKeyFactory;
|
||||||
import javax.crypto.spec.DESKeySpec;
|
import javax.crypto.spec.DESKeySpec;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加密
|
* 加密
|
||||||
|
|
@ -18,32 +19,29 @@ public class EncryptUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对称加密
|
* 对称加密
|
||||||
* @param source
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public static String desEncrypt(String source) throws Exception {
|
public static String desEncrypt(String source) throws Exception {
|
||||||
if (source == null || source.length() == 0){
|
if (source == null || source.length() == 0){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
|
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
|
||||||
DESKeySpec desKeySpec = new DESKeySpec(strKey.getBytes("UTF-8"));
|
DESKeySpec desKeySpec = new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8));
|
||||||
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
|
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
|
||||||
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
|
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
|
||||||
IvParameterSpec iv = new IvParameterSpec(strParam.getBytes("UTF-8"));
|
IvParameterSpec iv = new IvParameterSpec(strParam.getBytes(StandardCharsets.UTF_8));
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
|
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
|
||||||
return byte2hex(
|
return byte2hex(
|
||||||
cipher.doFinal(source.getBytes("UTF-8"))).toUpperCase();
|
cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String byte2hex(byte[] inStr) {
|
private static String byte2hex(byte[] inStr) {
|
||||||
String stmp;
|
String stmp;
|
||||||
StringBuffer out = new StringBuffer(inStr.length * 2);
|
StringBuilder out = new StringBuilder(inStr.length * 2);
|
||||||
for (int n = 0; n < inStr.length; n++) {
|
for (byte b : inStr) {
|
||||||
stmp = Integer.toHexString(inStr[n] & 0xFF);
|
stmp = Integer.toHexString(b & 0xFF);
|
||||||
if (stmp.length() == 1) {
|
if (stmp.length() == 1) {
|
||||||
// 如果是0至F的单位字符串,则添加0
|
// 如果是0至F的单位字符串,则添加0
|
||||||
out.append("0" + stmp);
|
out.append("0").append(stmp);
|
||||||
} else {
|
} else {
|
||||||
out.append(stmp);
|
out.append(stmp);
|
||||||
}
|
}
|
||||||
|
|
@ -51,8 +49,7 @@ public class EncryptUtils {
|
||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static byte[] hex2byte(byte[] b) {
|
||||||
public static byte[] hex2byte(byte[] b) {
|
|
||||||
if ((b.length % 2) != 0){
|
if ((b.length % 2) != 0){
|
||||||
throw new IllegalArgumentException("长度不是偶数");
|
throw new IllegalArgumentException("长度不是偶数");
|
||||||
}
|
}
|
||||||
|
|
@ -66,9 +63,6 @@ public class EncryptUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对称解密
|
* 对称解密
|
||||||
* @param source
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public static String desDecrypt(String source) throws Exception {
|
public static String desDecrypt(String source) throws Exception {
|
||||||
if (source == null || source.length() == 0){
|
if (source == null || source.length() == 0){
|
||||||
|
|
@ -76,10 +70,10 @@ public class EncryptUtils {
|
||||||
}
|
}
|
||||||
byte[] src = hex2byte(source.getBytes());
|
byte[] src = hex2byte(source.getBytes());
|
||||||
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
|
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
|
||||||
DESKeySpec desKeySpec = new DESKeySpec(strKey.getBytes("UTF-8"));
|
DESKeySpec desKeySpec = new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8));
|
||||||
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
|
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
|
||||||
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
|
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
|
||||||
IvParameterSpec iv = new IvParameterSpec(strParam.getBytes("UTF-8"));
|
IvParameterSpec iv = new IvParameterSpec(strParam.getBytes(StandardCharsets.UTF_8));
|
||||||
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
|
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
|
||||||
byte[] retByte = cipher.doFinal(src);
|
byte[] retByte = cipher.doFinal(src);
|
||||||
return new String(retByte);
|
return new String(retByte);
|
||||||
|
|
@ -87,8 +81,6 @@ public class EncryptUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 密码加密
|
* 密码加密
|
||||||
* @param password
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static String encryptPassword(String password){
|
public static String encryptPassword(String password){
|
||||||
return DigestUtils.md5DigestAsHex(password.getBytes());
|
return DigestUtils.md5DigestAsHex(password.getBytes());
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import javax.activation.MimetypesFileTypeMap;
|
||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
@ -44,8 +45,6 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MultipartFile转File
|
* MultipartFile转File
|
||||||
* @param multipartFile
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static File toFile(MultipartFile multipartFile){
|
public static File toFile(MultipartFile multipartFile){
|
||||||
// 获取文件名
|
// 获取文件名
|
||||||
|
|
@ -65,21 +64,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除
|
* 获取文件扩展名,不带 .
|
||||||
* @param files
|
|
||||||
*/
|
|
||||||
public static void deleteFile(File... files) {
|
|
||||||
for (File file : files) {
|
|
||||||
if (file.exists()) {
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取文件扩展名
|
|
||||||
* @param filename
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static String getExtensionName(String filename) {
|
public static String getExtensionName(String filename) {
|
||||||
if ((filename != null) && (filename.length() > 0)) {
|
if ((filename != null) && (filename.length() > 0)) {
|
||||||
|
|
@ -93,8 +78,6 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Java文件操作 获取不带扩展名的文件名
|
* Java文件操作 获取不带扩展名的文件名
|
||||||
* @param filename
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static String getFileNameNoEx(String filename) {
|
public static String getFileNameNoEx(String filename) {
|
||||||
if ((filename != null) && (filename.length() > 0)) {
|
if ((filename != null) && (filename.length() > 0)) {
|
||||||
|
|
@ -108,11 +91,9 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件大小转换
|
* 文件大小转换
|
||||||
* @param size
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static String getSize(long size){
|
public static String getSize(long size){
|
||||||
String resultSize = "";
|
String resultSize;
|
||||||
if (size / GB >= 1) {
|
if (size / GB >= 1) {
|
||||||
//如果当前Byte的值大于等于1GB
|
//如果当前Byte的值大于等于1GB
|
||||||
resultSize = DF.format(size / (float) GB) + "GB ";
|
resultSize = DF.format(size / (float) GB) + "GB ";
|
||||||
|
|
@ -130,18 +111,14 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* inputStream 转 File
|
* inputStream 转 File
|
||||||
* @param ins
|
|
||||||
* @param name
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public static File inputStreamToFile(InputStream ins, String name) throws Exception{
|
static File inputStreamToFile(InputStream ins, String name) throws Exception{
|
||||||
File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name);
|
File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name);
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
OutputStream os = new FileOutputStream(file);
|
OutputStream os = new FileOutputStream(file);
|
||||||
int bytesRead = 0;
|
int bytesRead;
|
||||||
byte[] buffer = new byte[8192];
|
byte[] buffer = new byte[8192];
|
||||||
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
|
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
|
||||||
os.write(buffer, 0, bytesRead);
|
os.write(buffer, 0, bytesRead);
|
||||||
|
|
@ -153,10 +130,6 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将文件名解析成文件的上传路径
|
* 将文件名解析成文件的上传路径
|
||||||
*
|
|
||||||
* @param file
|
|
||||||
* @param filePath
|
|
||||||
* @return 上传到服务器的文件名
|
|
||||||
*/
|
*/
|
||||||
public static File upload(MultipartFile file, String filePath) {
|
public static File upload(MultipartFile file, String filePath) {
|
||||||
Date date = new Date();
|
Date date = new Date();
|
||||||
|
|
@ -170,10 +143,10 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||||
File dest = new File(path);
|
File dest = new File(path);
|
||||||
// 检测是否存在目录
|
// 检测是否存在目录
|
||||||
if (!dest.getParentFile().exists()) {
|
if (!dest.getParentFile().exists()) {
|
||||||
dest.getParentFile().mkdirs();// 新建文件夹
|
dest.getParentFile().mkdirs();
|
||||||
}
|
}
|
||||||
String d = dest.getPath();
|
// 文件写入
|
||||||
file.transferTo(dest);// 文件写入
|
file.transferTo(dest);
|
||||||
return dest;
|
return dest;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
@ -183,20 +156,16 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||||
|
|
||||||
public static String fileToBase64(File file) throws Exception {
|
public static String fileToBase64(File file) throws Exception {
|
||||||
FileInputStream inputFile = new FileInputStream(file);
|
FileInputStream inputFile = new FileInputStream(file);
|
||||||
String base64 =null;
|
String base64;
|
||||||
byte[] buffer = new byte[(int)file.length()];
|
byte[] buffer = new byte[(int)file.length()];
|
||||||
inputFile.read(buffer);
|
inputFile.read(buffer);
|
||||||
inputFile.close();
|
inputFile.close();
|
||||||
base64=new Base64().encode(buffer);
|
base64=Base64.encode(buffer);
|
||||||
String encoded = base64.replaceAll("[\\s*\t\n\r]", "");
|
return base64.replaceAll("[\\s*\t\n\r]", "");
|
||||||
return encoded;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出excel
|
* 导出excel
|
||||||
* @param list
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
|
public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
|
||||||
String tempPath =System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx";
|
String tempPath =System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx";
|
||||||
|
|
@ -217,28 +186,91 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getFileType(String type) {
|
public static String getFileType(String type) {
|
||||||
String documents = "txt doc pdf ppt pps xlsx xls";
|
String documents = "txt doc pdf ppt pps xlsx xls docx";
|
||||||
String music = "mp3 wav wma mpa ram ra aac aif m4a";
|
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 video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
|
||||||
String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
|
String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
|
||||||
if(image.indexOf(type) != -1){
|
if(image.contains(type)){
|
||||||
return "图片";
|
return "图片";
|
||||||
} else if(documents.indexOf(type) != -1){
|
} else if(documents.contains(type)){
|
||||||
return "文档";
|
return "文档";
|
||||||
} else if(music.indexOf(type) != -1){
|
} else if(music.contains(type)){
|
||||||
return "音乐";
|
return "音乐";
|
||||||
} else if(video.indexOf(type) != -1){
|
} else if(video.contains(type)){
|
||||||
return "视频";
|
return "视频";
|
||||||
} else return "其他";
|
} else {
|
||||||
|
return "其他";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getFileTypeByMimeType(String type) {
|
public static String getFileTypeByMimeType(String type) {
|
||||||
String mimeType = new MimetypesFileTypeMap().getContentType("." + type);
|
String mimeType = new MimetypesFileTypeMap().getContentType("." + type);
|
||||||
return mimeType.split("\\/")[0];
|
return mimeType.split("/")[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkSize(long maxSize, long size) {
|
public static void checkSize(long maxSize, long size) {
|
||||||
if(size > (maxSize * 1024 * 1024)){
|
if(size > (maxSize * 1024 * 1024)){
|
||||||
throw new BadRequestException("文件超出规定大小");
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,6 @@ public class PageUtil extends cn.hutool.core.util.PageUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List 分页
|
* List 分页
|
||||||
* @param page
|
|
||||||
* @param size
|
|
||||||
* @param list
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static List toPage(int page, int size , List list) {
|
public static List toPage(int page, int size , List list) {
|
||||||
int fromIndex = page * size;
|
int fromIndex = page * size;
|
||||||
|
|
@ -32,10 +28,8 @@ public class PageUtil extends cn.hutool.core.util.PageUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page 数据处理,预防redis反序列化报错
|
* Page 数据处理,预防redis反序列化报错
|
||||||
* @param page
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static Map toPage(Page page) {
|
public static Map<String,Object> toPage(Page page) {
|
||||||
Map<String,Object> map = new LinkedHashMap<>(2);
|
Map<String,Object> map = new LinkedHashMap<>(2);
|
||||||
map.put("content",page.getContent());
|
map.put("content",page.getContent());
|
||||||
map.put("totalElements",page.getTotalElements());
|
map.put("totalElements",page.getTotalElements());
|
||||||
|
|
@ -43,11 +37,9 @@ public class PageUtil extends cn.hutool.core.util.PageUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param object
|
* 自定义分页
|
||||||
* @param totalElements
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static Map toPage(Object object, Object totalElements) {
|
public static Map<String,Object> toPage(Object object, Object totalElements) {
|
||||||
Map<String,Object> map = new LinkedHashMap<>(2);
|
Map<String,Object> map = new LinkedHashMap<>(2);
|
||||||
map.put("content",object);
|
map.put("content",object);
|
||||||
map.put("totalElements",totalElements);
|
map.put("totalElements",totalElements);
|
||||||
|
|
|
||||||
|
|
@ -15,18 +15,12 @@ import java.util.*;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class QueryHelp {
|
public class QueryHelp {
|
||||||
|
|
||||||
/**
|
|
||||||
* @描述 : 转换为Predicate
|
|
||||||
* @作者 : Dong ZhaoYang
|
|
||||||
* @日期 : 2017/8/7
|
|
||||||
* @时间 : 17:25
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <R, Q> Predicate getPredicate(Root<R> root, Q query, CriteriaBuilder cb) {
|
public static <R, Q> Predicate getPredicate(Root<R> root, Q query, CriteriaBuilder cb) {
|
||||||
List<Predicate> list = new ArrayList<>();
|
List<Predicate> list = new ArrayList<>();
|
||||||
|
|
||||||
if(query == null){
|
if(query == null){
|
||||||
return cb.and(list.toArray(new Predicate[list.size()]));
|
return cb.and(list.toArray(new Predicate[0]));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
List<Field> fields = getAllFields(query.getClass(), new ArrayList<>());
|
List<Field> fields = getAllFields(query.getClass(), new ArrayList<>());
|
||||||
|
|
@ -62,19 +56,20 @@ public class QueryHelp {
|
||||||
for (String name : joinNames) {
|
for (String name : joinNames) {
|
||||||
switch (q.join()) {
|
switch (q.join()) {
|
||||||
case LEFT:
|
case LEFT:
|
||||||
if(ObjectUtil.isNotEmpty(join)){
|
if(ObjectUtil.isNotNull(join)){
|
||||||
join = join.join(name, JoinType.LEFT);
|
join = join.join(name, JoinType.LEFT);
|
||||||
} else {
|
} else {
|
||||||
join = root.join(name, JoinType.LEFT);
|
join = root.join(name, JoinType.LEFT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RIGHT:
|
case RIGHT:
|
||||||
if(ObjectUtil.isNotEmpty(join)){
|
if(ObjectUtil.isNotNull(join)){
|
||||||
join = join.join(name, JoinType.RIGHT);
|
join = join.join(name, JoinType.RIGHT);
|
||||||
} else {
|
} else {
|
||||||
join = root.join(name, JoinType.RIGHT);
|
join = root.join(name, JoinType.RIGHT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -111,6 +106,7 @@ public class QueryHelp {
|
||||||
list.add(getExpression(attributeName,join,root).in((Collection<Long>) val));
|
list.add(getExpression(attributeName,join,root).in((Collection<Long>) val));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
field.setAccessible(accessible);
|
field.setAccessible(accessible);
|
||||||
|
|
@ -118,7 +114,8 @@ public class QueryHelp {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
return cb.and(list.toArray(new Predicate[list.size()]));
|
int size = list.size();
|
||||||
|
return cb.and(list.toArray(new Predicate[size]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
@ -130,21 +127,19 @@ public class QueryHelp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
private static boolean isBlank(final CharSequence cs) {
|
||||||
public static boolean isBlank(final CharSequence cs) {
|
|
||||||
int strLen;
|
int strLen;
|
||||||
if (cs == null || (strLen = cs.length()) == 0) {
|
if (cs == null || (strLen = cs.length()) == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < strLen; i++) {
|
for (int i = 0; i < strLen; i++) {
|
||||||
if (Character.isWhitespace(cs.charAt(i)) == false) {
|
if (!Character.isWhitespace(cs.charAt(i))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static List<Field> getAllFields(Class clazz, List<Field> fields) {
|
private static List<Field> getAllFields(Class clazz, List<Field> fields) {
|
||||||
if (clazz != null) {
|
if (clazz != null) {
|
||||||
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package me.zhengjie.utils;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 HttpServletRequest
|
* 获取 HttpServletRequest
|
||||||
|
|
@ -12,6 +13,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
public class RequestHolder {
|
public class RequestHolder {
|
||||||
|
|
||||||
public static HttpServletRequest getHttpServletRequest() {
|
public static HttpServletRequest getHttpServletRequest() {
|
||||||
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import org.springframework.security.core.userdetails.UserDetails;
|
||||||
public class SecurityUtils {
|
public class SecurityUtils {
|
||||||
|
|
||||||
public static UserDetails getUserDetails() {
|
public static UserDetails getUserDetails() {
|
||||||
UserDetails userDetails = null;
|
UserDetails userDetails;
|
||||||
try {
|
try {
|
||||||
userDetails = (UserDetails) org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
userDetails = (UserDetails) org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
@ -28,8 +28,7 @@ public class SecurityUtils {
|
||||||
*/
|
*/
|
||||||
public static String getUsername(){
|
public static String getUsername(){
|
||||||
Object obj = getUserDetails();
|
Object obj = getUserDetails();
|
||||||
JSONObject json = new JSONObject(obj);
|
return new JSONObject(obj).get("username", String.class);
|
||||||
return json.get("username", String.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -38,7 +37,6 @@ public class SecurityUtils {
|
||||||
*/
|
*/
|
||||||
public static Long getUserId(){
|
public static Long getUserId(){
|
||||||
Object obj = getUserDetails();
|
Object obj = getUserDetails();
|
||||||
JSONObject json = new JSONObject(obj);
|
return new JSONObject(obj).get("id", Long.class);
|
||||||
return json.get("id", Long.class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author
|
* @author Jie
|
||||||
* @date 2019-01-07
|
* @date 2019-01-07
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
|
@ -15,17 +15,10 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
|
||||||
|
|
||||||
private static ApplicationContext applicationContext = null;
|
private static ApplicationContext applicationContext = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* 取得存储在静态变量中的ApplicationContext.
|
|
||||||
*/
|
|
||||||
public static ApplicationContext getApplicationContext() {
|
|
||||||
assertContextInjected();
|
|
||||||
return applicationContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
|
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> T getBean(String name) {
|
public static <T> T getBean(String name) {
|
||||||
assertContextInjected();
|
assertContextInjected();
|
||||||
return (T) applicationContext.getBean(name);
|
return (T) applicationContext.getBean(name);
|
||||||
|
|
@ -52,14 +45,14 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB
|
||||||
/**
|
/**
|
||||||
* 清除SpringContextHolder中的ApplicationContext为Null.
|
* 清除SpringContextHolder中的ApplicationContext为Null.
|
||||||
*/
|
*/
|
||||||
public static void clearHolder() {
|
private static void clearHolder() {
|
||||||
log.debug("清除SpringContextHolder中的ApplicationContext:"
|
log.debug("清除SpringContextHolder中的ApplicationContext:"
|
||||||
+ applicationContext);
|
+ applicationContext);
|
||||||
applicationContext = null;
|
applicationContext = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy() throws Exception {
|
public void destroy(){
|
||||||
SpringContextHolder.clearHolder();
|
SpringContextHolder.clearHolder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
package me.zhengjie.utils;
|
package me.zhengjie.utils;
|
||||||
|
|
||||||
import cn.hutool.core.io.resource.ClassPathResource;
|
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.DataBlock;
|
||||||
import org.lionsoul.ip2region.DbConfig;
|
import org.lionsoul.ip2region.DbConfig;
|
||||||
import org.lionsoul.ip2region.DbSearcher;
|
import org.lionsoul.ip2region.DbSearcher;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
@ -18,25 +20,6 @@ import java.util.Date;
|
||||||
public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||||
|
|
||||||
private static final char SEPARATOR = '_';
|
private static final char SEPARATOR = '_';
|
||||||
private static final String CHARSET_NAME = "UTF-8";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否包含字符串
|
|
||||||
*
|
|
||||||
* @param str 验证字符串
|
|
||||||
* @param strs 字符串组
|
|
||||||
* @return 包含返回true
|
|
||||||
*/
|
|
||||||
public static boolean inString(String str, String... strs) {
|
|
||||||
if (str != null) {
|
|
||||||
for (String s : strs) {
|
|
||||||
if (str.equals(trim(s))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 驼峰命名法工具
|
* 驼峰命名法工具
|
||||||
|
|
@ -92,7 +75,7 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||||
* toCapitalizeCamelCase("hello_world") == "HelloWorld"
|
* toCapitalizeCamelCase("hello_world") == "HelloWorld"
|
||||||
* toUnderScoreCase("helloWorld") = "hello_world"
|
* toUnderScoreCase("helloWorld") = "hello_world"
|
||||||
*/
|
*/
|
||||||
public static String toUnderScoreCase(String s) {
|
static String toUnderScoreCase(String s) {
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -125,53 +108,45 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取ip地址
|
* 获取ip地址
|
||||||
* @param request
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static String getIP(HttpServletRequest request) {
|
public static String getIp(HttpServletRequest request) {
|
||||||
String ip = request.getHeader("x-forwarded-for");
|
String ip = request.getHeader("x-forwarded-for");
|
||||||
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
ip = request.getHeader("Proxy-Client-IP");
|
ip = request.getHeader("Proxy-Client-IP");
|
||||||
}
|
}
|
||||||
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
ip = request.getHeader("WL-Proxy-Client-IP");
|
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||||
}
|
}
|
||||||
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
|
||||||
ip = request.getRemoteAddr();
|
ip = request.getRemoteAddr();
|
||||||
}
|
}
|
||||||
String[] ips = ip.split(",");
|
if (ip.contains(",")) {
|
||||||
return "0:0:0:0:0:0:0:1".equals(ips[0])?"127.0.0.1":ips[0];
|
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获取详细地址
|
* 根据ip获取详细地址
|
||||||
* @param ip
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static String getCityInfo(String ip) {
|
public static String getCityInfo(String ip) {
|
||||||
try {
|
try {
|
||||||
String path = "ip2region/ip2region.db";
|
String path = "ip2region/ip2region.db";
|
||||||
String name = "ip2region.db";
|
String name = "ip2region.db";
|
||||||
int algorithm = DbSearcher.BTREE_ALGORITHM;
|
|
||||||
DbConfig config = new DbConfig();
|
DbConfig config = new DbConfig();
|
||||||
File file = FileUtil.inputStreamToFile(new ClassPathResource(path).getStream(), name);
|
File file = FileUtil.inputStreamToFile(new ClassPathResource(path).getStream(), name);
|
||||||
DbSearcher searcher = new DbSearcher(config, file.getPath());
|
DbSearcher searcher = new DbSearcher(config, file.getPath());
|
||||||
Method method = null;
|
Method method;
|
||||||
switch (algorithm) {
|
method = searcher.getClass().getMethod("btreeSearch", String.class);
|
||||||
case DbSearcher.BTREE_ALGORITHM:
|
DataBlock dataBlock;
|
||||||
method = searcher.getClass().getMethod("btreeSearch", String.class);
|
|
||||||
break;
|
|
||||||
case DbSearcher.BINARY_ALGORITHM:
|
|
||||||
method = searcher.getClass().getMethod("binarySearch", String.class);
|
|
||||||
break;
|
|
||||||
case DbSearcher.MEMORY_ALGORITYM:
|
|
||||||
method = searcher.getClass().getMethod("memorySearch", String.class);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
method = searcher.getClass().getMethod("memorySearch", String.class);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
DataBlock dataBlock = null;
|
|
||||||
dataBlock = (DataBlock) method.invoke(searcher, ip);
|
dataBlock = (DataBlock) method.invoke(searcher, ip);
|
||||||
String address = dataBlock.getRegion().replace("0|","");
|
String address = dataBlock.getRegion().replace("0|","");
|
||||||
if(address.charAt(address.length()-1) == '|'){
|
if(address.charAt(address.length()-1) == '|'){
|
||||||
|
|
@ -184,6 +159,12 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getBrowser(HttpServletRequest request){
|
||||||
|
UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
|
||||||
|
Browser browser = userAgent.getBrowser();
|
||||||
|
return browser.getName();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得当天是周几
|
* 获得当天是周几
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,23 @@ package me.zhengjie.utils;
|
||||||
|
|
||||||
import me.zhengjie.exception.BadRequestException;
|
import me.zhengjie.exception.BadRequestException;
|
||||||
import org.hibernate.exception.ConstraintViolationException;
|
import org.hibernate.exception.ConstraintViolationException;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 异常工具
|
* 异常工具 2019-01-06
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2019-01-06
|
|
||||||
*/
|
*/
|
||||||
public class ThrowableUtil {
|
public class ThrowableUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取堆栈信息
|
* 获取堆栈信息
|
||||||
* @param throwable
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static String getStackTrace(Throwable throwable){
|
public static String getStackTrace(Throwable throwable){
|
||||||
StringWriter sw = new StringWriter();
|
StringWriter sw = new StringWriter();
|
||||||
PrintWriter pw = new PrintWriter(sw);
|
try (PrintWriter pw = new PrintWriter(sw)) {
|
||||||
try {
|
|
||||||
throwable.printStackTrace(pw);
|
throwable.printStackTrace(pw);
|
||||||
return sw.toString();
|
return sw.toString();
|
||||||
} finally {
|
|
||||||
pw.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,9 +27,10 @@ public class ThrowableUtil {
|
||||||
while ((t != null) && !(t instanceof ConstraintViolationException)) {
|
while ((t != null) && !(t instanceof ConstraintViolationException)) {
|
||||||
t = t.getCause();
|
t = t.getCause();
|
||||||
}
|
}
|
||||||
if (t instanceof ConstraintViolationException) {
|
if (t != null) {
|
||||||
throw new BadRequestException(msg);
|
throw new BadRequestException(msg);
|
||||||
}
|
}
|
||||||
|
assert false;
|
||||||
throw new BadRequestException("删除失败:" + t.getMessage());
|
throw new BadRequestException("删除失败:" + t.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
package me.zhengjie.utils;
|
package me.zhengjie.utils;
|
||||||
|
|
||||||
import cn.hutool.json.JSONArray;
|
import cn.hutool.json.JSONArray;
|
||||||
import lombok.var;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
|
@ -26,7 +24,7 @@ public class TranslatorUtil {
|
||||||
BufferedReader in = new BufferedReader(
|
BufferedReader in = new BufferedReader(
|
||||||
new InputStreamReader(con.getInputStream()));
|
new InputStreamReader(con.getInputStream()));
|
||||||
String inputLine;
|
String inputLine;
|
||||||
StringBuffer response = new StringBuffer();
|
StringBuilder response = new StringBuilder();
|
||||||
|
|
||||||
while ((inputLine = in.readLine()) != null) {
|
while ((inputLine = in.readLine()) != null) {
|
||||||
response.append(inputLine);
|
response.append(inputLine);
|
||||||
|
|
@ -38,15 +36,12 @@ public class TranslatorUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String parseResult(String inputJson) throws Exception {
|
private static String parseResult(String inputJson){
|
||||||
JSONArray jsonArray = new JSONArray(inputJson);
|
JSONArray jsonArray2 = (JSONArray) new JSONArray(inputJson).get(0);
|
||||||
JSONArray jsonArray2 = (JSONArray) jsonArray.get(0);
|
StringBuilder result = new StringBuilder();
|
||||||
String result ="";
|
for (Object o : jsonArray2) {
|
||||||
|
result.append(((JSONArray) o).get(0).toString());
|
||||||
for(var i = 0; i < jsonArray2.size(); i ++){
|
|
||||||
result += ((JSONArray) jsonArray2.get(i)).get(0).toString();
|
|
||||||
}
|
}
|
||||||
return result;
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package me.zhengjie.utils;
|
package me.zhengjie.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import me.zhengjie.exception.BadRequestException;
|
import me.zhengjie.exception.BadRequestException;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证工具
|
* 验证工具
|
||||||
|
|
@ -12,27 +12,22 @@ public class ValidationUtil{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证空
|
* 验证空
|
||||||
* @param optional
|
|
||||||
*/
|
*/
|
||||||
public static void isNull(Optional optional, String entity,String parameter , Object value){
|
public static void isNull(Object obj, String entity, String parameter , Object value){
|
||||||
if(!optional.isPresent()){
|
if(ObjectUtil.isNull(obj)){
|
||||||
String msg = entity
|
String msg = entity + " 不存在: "+ parameter +" is "+ value;
|
||||||
+ " 不存在 "
|
|
||||||
+"{ "+ parameter +":"+ value.toString() +" }";
|
|
||||||
throw new BadRequestException(msg);
|
throw new BadRequestException(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证是否为邮箱
|
* 验证是否为邮箱
|
||||||
* @param string
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public static boolean isEmail(String string) {
|
public static boolean isEmail(String string) {
|
||||||
if (string == null){
|
if (string == null){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String regEx1 = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
|
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);
|
return string.matches(regEx1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,6 @@ import static org.junit.Assert.*;
|
||||||
|
|
||||||
public class StringUtilsTest {
|
public class StringUtilsTest {
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInString() {
|
|
||||||
assertTrue(inString("?", "?"));
|
|
||||||
assertFalse(inString("?", new String[]{}));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToCamelCase() {
|
public void testToCamelCase() {
|
||||||
assertNull(toCamelCase(null));
|
assertNull(toCamelCase(null));
|
||||||
|
|
@ -44,6 +38,6 @@ public class StringUtilsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetIP() {
|
public void testGetIP() {
|
||||||
assertEquals("127.0.0.1", getIP(new MockHttpServletRequest()));
|
assertEquals("127.0.0.1", getIp(new MockHttpServletRequest()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>eladmin</artifactId>
|
<artifactId>eladmin</artifactId>
|
||||||
<groupId>me.zhengjie</groupId>
|
<groupId>me.zhengjie</groupId>
|
||||||
<version>2.2</version>
|
<version>2.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>me.zhengjie</groupId>
|
<groupId>me.zhengjie</groupId>
|
||||||
<artifactId>eladmin-common</artifactId>
|
<artifactId>eladmin-common</artifactId>
|
||||||
<version>2.2</version>
|
<version>2.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--模板引擎-->
|
<!--模板引擎-->
|
||||||
|
|
|
||||||
|
|
@ -16,26 +16,26 @@ public class GenConfig {
|
||||||
@Id
|
@Id
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/** 包路径 **/
|
// 包路径
|
||||||
private String pack;
|
private String pack;
|
||||||
|
|
||||||
/** 模块名 **/
|
// 模块名
|
||||||
@Column(name = "module_name")
|
@Column(name = "module_name")
|
||||||
private String moduleName;
|
private String moduleName;
|
||||||
|
|
||||||
/** 前端文件路径 **/
|
// 前端文件路径
|
||||||
private String path;
|
private String path;
|
||||||
|
|
||||||
/** 前端文件路径 **/
|
// 前端文件路径
|
||||||
@Column(name = "api_path")
|
@Column(name = "api_path")
|
||||||
private String apiPath;
|
private String apiPath;
|
||||||
|
|
||||||
/** 作者 **/
|
// 作者
|
||||||
private String author;
|
private String author;
|
||||||
|
|
||||||
/** 表前缀 **/
|
// 表前缀
|
||||||
private String prefix;
|
private String prefix;
|
||||||
|
|
||||||
/** 是否覆盖 **/
|
// 是否覆盖
|
||||||
private Boolean cover;
|
private Boolean cover;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,27 +14,27 @@ import lombok.NoArgsConstructor;
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class ColumnInfo {
|
public class ColumnInfo {
|
||||||
|
|
||||||
/** 数据库字段名称 **/
|
// 数据库字段名称
|
||||||
private Object columnName;
|
private Object columnName;
|
||||||
|
|
||||||
/** 允许空值 **/
|
// 允许空值
|
||||||
private Object isNullable;
|
private Object isNullable;
|
||||||
|
|
||||||
/** 数据库字段类型 **/
|
// 数据库字段类型
|
||||||
private Object columnType;
|
private Object columnType;
|
||||||
|
|
||||||
/** 数据库字段注释 **/
|
// 数据库字段注释
|
||||||
private Object columnComment;
|
private Object columnComment;
|
||||||
|
|
||||||
/** 数据库字段键类型 **/
|
// 数据库字段键类型
|
||||||
private Object columnKey;
|
private Object columnKey;
|
||||||
|
|
||||||
/** 额外的参数 **/
|
// 额外的参数
|
||||||
private Object extra;
|
private Object extra;
|
||||||
|
|
||||||
/** 查询 1:模糊 2:精确 **/
|
// 查询 1:模糊 2:精确
|
||||||
private String columnQuery;
|
private String columnQuery;
|
||||||
|
|
||||||
/** 是否在列表显示 **/
|
// 是否在列表显示
|
||||||
private String columnShow;
|
private String columnShow;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,10 @@ import lombok.NoArgsConstructor;
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class TableInfo {
|
public class TableInfo {
|
||||||
|
|
||||||
/** 表名称 **/
|
// 表名称
|
||||||
private Object tableName;
|
private Object tableName;
|
||||||
|
|
||||||
/** 创建日期 **/
|
// 创建日期
|
||||||
private Object createTime;
|
private Object createTime;
|
||||||
|
|
||||||
// 数据库引擎
|
// 数据库引擎
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
package me.zhengjie.rest;
|
package me.zhengjie.rest;
|
||||||
|
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
import me.zhengjie.domain.GenConfig;
|
import me.zhengjie.domain.GenConfig;
|
||||||
import me.zhengjie.service.GenConfigService;
|
import me.zhengjie.service.GenConfigService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
@ -13,23 +14,25 @@ import org.springframework.web.bind.annotation.*;
|
||||||
* @date 2019-01-14
|
* @date 2019-01-14
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("api")
|
@RequestMapping("/api/genConfig")
|
||||||
|
@Api(tags = "系统:代码生成器配置管理")
|
||||||
public class GenConfigController {
|
public class GenConfigController {
|
||||||
|
|
||||||
@Autowired
|
private final GenConfigService genConfigService;
|
||||||
private GenConfigService genConfigService;
|
|
||||||
|
|
||||||
/**
|
public GenConfigController(GenConfigService genConfigService) {
|
||||||
* 查询生成器配置
|
this.genConfigService = genConfigService;
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@GetMapping(value = "/genConfig")
|
|
||||||
public ResponseEntity get(){
|
|
||||||
return new ResponseEntity(genConfigService.find(), HttpStatus.OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping(value = "/genConfig")
|
@ApiOperation("查询")
|
||||||
|
@GetMapping
|
||||||
|
public ResponseEntity get(){
|
||||||
|
return new ResponseEntity<>(genConfigService.find(), HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("修改")
|
||||||
|
@PutMapping
|
||||||
public ResponseEntity emailConfig(@Validated @RequestBody GenConfig genConfig){
|
public ResponseEntity emailConfig(@Validated @RequestBody GenConfig genConfig){
|
||||||
return new ResponseEntity(genConfigService.update(genConfig),HttpStatus.OK);
|
return new ResponseEntity<>(genConfigService.update(genConfig),HttpStatus.OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
package me.zhengjie.rest;
|
package me.zhengjie.rest;
|
||||||
|
|
||||||
import cn.hutool.core.util.PageUtil;
|
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.domain.vo.ColumnInfo;
|
||||||
import me.zhengjie.exception.BadRequestException;
|
import me.zhengjie.exception.BadRequestException;
|
||||||
import me.zhengjie.service.GenConfigService;
|
import me.zhengjie.service.GenConfigService;
|
||||||
import me.zhengjie.service.GeneratorService;
|
import me.zhengjie.service.GeneratorService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
@ -17,49 +18,39 @@ import java.util.List;
|
||||||
* @date 2019-01-02
|
* @date 2019-01-02
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("api")
|
@RequestMapping("/api/generator")
|
||||||
|
@Api(tags = "系统:代码生成管理")
|
||||||
public class GeneratorController {
|
public class GeneratorController {
|
||||||
|
|
||||||
@Autowired
|
private final GeneratorService generatorService;
|
||||||
private GeneratorService generatorService;
|
|
||||||
|
|
||||||
@Autowired
|
private final GenConfigService genConfigService;
|
||||||
private GenConfigService genConfigService;
|
|
||||||
|
|
||||||
@Value("${generator.enabled}")
|
@Value("${generator.enabled}")
|
||||||
private Boolean generatorEnabled;
|
private Boolean generatorEnabled;
|
||||||
|
|
||||||
/**
|
public GeneratorController(GeneratorService generatorService, GenConfigService genConfigService) {
|
||||||
* 查询数据库元数据
|
this.generatorService = generatorService;
|
||||||
* @param name
|
this.genConfigService = genConfigService;
|
||||||
* @param page
|
}
|
||||||
* @param size
|
|
||||||
* @return
|
@ApiOperation("查询数据库元数据")
|
||||||
*/
|
@GetMapping(value = "/tables")
|
||||||
@GetMapping(value = "/generator/tables")
|
|
||||||
public ResponseEntity getTables(@RequestParam(defaultValue = "") String name,
|
public ResponseEntity getTables(@RequestParam(defaultValue = "") String name,
|
||||||
@RequestParam(defaultValue = "0")Integer page,
|
@RequestParam(defaultValue = "0")Integer page,
|
||||||
@RequestParam(defaultValue = "10")Integer size){
|
@RequestParam(defaultValue = "10")Integer size){
|
||||||
int[] startEnd = PageUtil.transToStartEnd(page+1, size);
|
int[] startEnd = PageUtil.transToStartEnd(page+1, size);
|
||||||
return new ResponseEntity(generatorService.getTables(name,startEnd), HttpStatus.OK);
|
return new ResponseEntity<>(generatorService.getTables(name,startEnd), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@ApiOperation("查询表内元数据")
|
||||||
* 查询表内元数据
|
@GetMapping(value = "/columns")
|
||||||
* @param tableName
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@GetMapping(value = "/generator/columns")
|
|
||||||
public ResponseEntity getTables(@RequestParam String tableName){
|
public ResponseEntity getTables(@RequestParam String tableName){
|
||||||
return new ResponseEntity(generatorService.getColumns(tableName), HttpStatus.OK);
|
return new ResponseEntity<>(generatorService.getColumns(tableName), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@ApiOperation("生成代码")
|
||||||
* 生成代码
|
@PostMapping
|
||||||
* @param columnInfos
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@PostMapping(value = "/generator")
|
|
||||||
public ResponseEntity generator(@RequestBody List<ColumnInfo> columnInfos, @RequestParam String tableName){
|
public ResponseEntity generator(@RequestBody List<ColumnInfo> columnInfos, @RequestParam String tableName){
|
||||||
if(!generatorEnabled){
|
if(!generatorEnabled){
|
||||||
throw new BadRequestException("此环境不允许生成代码!");
|
throw new BadRequestException("此环境不允许生成代码!");
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,14 @@
|
||||||
package me.zhengjie.service;
|
package me.zhengjie.service;
|
||||||
|
|
||||||
import me.zhengjie.domain.GenConfig;
|
import me.zhengjie.domain.GenConfig;
|
||||||
import org.springframework.cache.annotation.CacheConfig;
|
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
|
||||||
import org.springframework.cache.annotation.CachePut;
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2019-01-14
|
* @date 2019-01-14
|
||||||
*/
|
*/
|
||||||
@CacheConfig(cacheNames = "genConfig")
|
|
||||||
public interface GenConfigService {
|
public interface GenConfigService {
|
||||||
|
|
||||||
/**
|
|
||||||
* find
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Cacheable(key = "'1'")
|
|
||||||
GenConfig find();
|
GenConfig find();
|
||||||
|
|
||||||
/**
|
|
||||||
* update
|
|
||||||
* @param genConfig
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@CacheEvict(allEntries = true)
|
|
||||||
GenConfig update(GenConfig genConfig);
|
GenConfig update(GenConfig genConfig);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,24 +12,24 @@ public interface GeneratorService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询数据库元数据
|
* 查询数据库元数据
|
||||||
* @param name
|
* @param name 表名
|
||||||
* @param startEnd
|
* @param startEnd 分页参数
|
||||||
* @return
|
* @return /
|
||||||
*/
|
*/
|
||||||
Object getTables(String name, int[] startEnd);
|
Object getTables(String name, int[] startEnd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 得到数据表的元数据
|
* 得到数据表的元数据
|
||||||
* @param name
|
* @param name 表名
|
||||||
* @return
|
* @return /
|
||||||
*/
|
*/
|
||||||
Object getColumns(String name);
|
Object getColumns(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成代码
|
* 生成代码
|
||||||
* @param columnInfos
|
* @param columnInfos 表字段数据
|
||||||
* @param genConfig
|
* @param genConfig 代码生成配置
|
||||||
* @param tableName
|
* @param tableName 表名
|
||||||
*/
|
*/
|
||||||
void generator(List<ColumnInfo> columnInfos, GenConfig genConfig, String tableName);
|
void generator(List<ColumnInfo> columnInfos, GenConfig genConfig, String tableName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ package me.zhengjie.service.impl;
|
||||||
import me.zhengjie.domain.GenConfig;
|
import me.zhengjie.domain.GenConfig;
|
||||||
import me.zhengjie.repository.GenConfigRepository;
|
import me.zhengjie.repository.GenConfigRepository;
|
||||||
import me.zhengjie.service.GenConfigService;
|
import me.zhengjie.service.GenConfigService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.stereotype.Service;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
|
@ -14,35 +15,37 @@ import java.util.Optional;
|
||||||
* @date 2019-01-14
|
* @date 2019-01-14
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
@CacheConfig(cacheNames = "genConfig")
|
||||||
public class GenConfigServiceImpl implements GenConfigService {
|
public class GenConfigServiceImpl implements GenConfigService {
|
||||||
|
|
||||||
@Autowired
|
private final GenConfigRepository genConfigRepository;
|
||||||
private GenConfigRepository genConfigRepository;
|
|
||||||
|
|
||||||
@Override
|
public GenConfigServiceImpl(GenConfigRepository genConfigRepository) {
|
||||||
public GenConfig find() {
|
this.genConfigRepository = genConfigRepository;
|
||||||
Optional<GenConfig> genConfig = genConfigRepository.findById(1L);
|
|
||||||
if(genConfig.isPresent()){
|
|
||||||
return genConfig.get();
|
|
||||||
} else {
|
|
||||||
return new GenConfig();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
public GenConfig update(GenConfig genConfig) {
|
||||||
genConfig.setId(1L);
|
genConfig.setId(1L);
|
||||||
// 自动设置Api路径,注释掉前需要同步取消前端的注释
|
// 自动设置Api路径,注释掉前需要同步取消前端的注释
|
||||||
String separator = File.separator;
|
String separator = File.separator;
|
||||||
String[] paths = null;
|
String[] paths;
|
||||||
if (separator.equals("\\")) {
|
if (separator.equals("\\")) {
|
||||||
paths = genConfig.getPath().split("\\\\");
|
paths = genConfig.getPath().split("\\\\");
|
||||||
} else paths = genConfig.getPath().split(File.separator);
|
} else paths = genConfig.getPath().split(File.separator);
|
||||||
StringBuffer api = new StringBuffer();
|
StringBuilder api = new StringBuilder();
|
||||||
for (int i = 0; i < paths.length; i++) {
|
for (String path : paths) {
|
||||||
api.append(paths[i]);
|
api.append(path);
|
||||||
api.append(separator);
|
api.append(separator);
|
||||||
if(paths[i].equals("src")){
|
if (path.equals("src")) {
|
||||||
api.append("api");
|
api.append("api");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||||
private EntityManager em;
|
private EntityManager em;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("all")
|
||||||
public Object getTables(String name, int[] startEnd) {
|
public Object getTables(String name, int[] startEnd) {
|
||||||
// 使用预编译防止sql注入
|
// 使用预编译防止sql注入
|
||||||
String sql = "select table_name ,create_time , engine, table_collation, table_comment from information_schema.tables " +
|
String sql = "select table_name ,create_time , engine, table_collation, table_comment from information_schema.tables " +
|
||||||
|
|
@ -37,10 +38,11 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||||
query.setFirstResult(startEnd[0]);
|
query.setFirstResult(startEnd[0]);
|
||||||
query.setMaxResults(startEnd[1]-startEnd[0]);
|
query.setMaxResults(startEnd[1]-startEnd[0]);
|
||||||
query.setParameter(1, StringUtils.isNotBlank(name) ? ("%" + name + "%") : "%%");
|
query.setParameter(1, StringUtils.isNotBlank(name) ? ("%" + name + "%") : "%%");
|
||||||
List<Object[]> result = query.getResultList();
|
List result = query.getResultList();
|
||||||
List<TableInfo> tableInfos = new ArrayList<>();
|
List<TableInfo> tableInfos = new ArrayList<>();
|
||||||
for (Object[] obj : result) {
|
for (Object obj : result) {
|
||||||
tableInfos.add(new TableInfo(obj[0],obj[1],obj[2],obj[3], ObjectUtil.isNotEmpty(obj[4])? obj[4] : "-"));
|
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())");
|
Query query1 = em.createNativeQuery("SELECT COUNT(*) from information_schema.tables where table_schema = (select database())");
|
||||||
Object totalElements = query1.getSingleResult();
|
Object totalElements = query1.getSingleResult();
|
||||||
|
|
@ -48,16 +50,18 @@ public class GeneratorServiceImpl implements GeneratorService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("all")
|
||||||
public Object getColumns(String name) {
|
public Object getColumns(String name) {
|
||||||
// 使用预编译防止sql注入
|
// 使用预编译防止sql注入
|
||||||
String sql = "select column_name, is_nullable, data_type, column_comment, column_key, extra from information_schema.columns " +
|
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";
|
"where table_name = ? and table_schema = (select database()) order by ordinal_position";
|
||||||
Query query = em.createNativeQuery(sql);
|
Query query = em.createNativeQuery(sql);
|
||||||
query.setParameter(1, StringUtils.isNotBlank(name) ? name : null);
|
query.setParameter(1, StringUtils.isNotBlank(name) ? name : null);
|
||||||
List<Object[]> result = query.getResultList();
|
List result = query.getResultList();
|
||||||
List<ColumnInfo> columnInfos = new ArrayList<>();
|
List<ColumnInfo> columnInfos = new ArrayList<>();
|
||||||
for (Object[] obj : result) {
|
for (Object obj : result) {
|
||||||
columnInfos.add(new ColumnInfo(obj[0],obj[1],obj[2],obj[3],obj[4],obj[5],null,"true"));
|
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());
|
return PageUtil.toPage(columnInfos,columnInfos.size());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,12 @@ public class ColUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换mysql数据类型为java数据类型
|
* 转换mysql数据类型为java数据类型
|
||||||
* @param type
|
* @param type 数据库字段类型
|
||||||
* @return
|
* @return String
|
||||||
*/
|
*/
|
||||||
public static String cloToJava(String type){
|
static String cloToJava(String type){
|
||||||
Configuration config = getConfig();
|
Configuration config = getConfig();
|
||||||
|
assert config != null;
|
||||||
return config.getString(type,"unknowType");
|
return config.getString(type,"unknowType");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,9 +34,9 @@ public class GenUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取后端代码模板名称
|
* 获取后端代码模板名称
|
||||||
* @return
|
* @return List
|
||||||
*/
|
*/
|
||||||
public static List<String> getAdminTemplateNames() {
|
private static List<String> getAdminTemplateNames() {
|
||||||
List<String> templateNames = new ArrayList<>();
|
List<String> templateNames = new ArrayList<>();
|
||||||
templateNames.add("Entity");
|
templateNames.add("Entity");
|
||||||
templateNames.add("Dto");
|
templateNames.add("Dto");
|
||||||
|
|
@ -51,9 +51,9 @@ public class GenUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取前端代码模板名称
|
* 获取前端代码模板名称
|
||||||
* @return
|
* @return List
|
||||||
*/
|
*/
|
||||||
public static List<String> getFrontTemplateNames() {
|
private static List<String> getFrontTemplateNames() {
|
||||||
List<String> templateNames = new ArrayList<>();
|
List<String> templateNames = new ArrayList<>();
|
||||||
templateNames.add("api");
|
templateNames.add("api");
|
||||||
templateNames.add("index");
|
templateNames.add("index");
|
||||||
|
|
@ -67,7 +67,7 @@ public class GenUtil {
|
||||||
* @param genConfig 生成代码的参数配置,如包路径,作者
|
* @param genConfig 生成代码的参数配置,如包路径,作者
|
||||||
*/
|
*/
|
||||||
public static void generatorCode(List<ColumnInfo> columnInfos, GenConfig genConfig, String tableName) throws IOException {
|
public static void generatorCode(List<ColumnInfo> columnInfos, GenConfig genConfig, String tableName) throws IOException {
|
||||||
Map<String,Object> map = new HashMap();
|
Map<String,Object> map = new HashMap<>();
|
||||||
map.put("package",genConfig.getPack());
|
map.put("package",genConfig.getPack());
|
||||||
map.put("moduleName",genConfig.getModuleName());
|
map.put("moduleName",genConfig.getModuleName());
|
||||||
map.put("author",genConfig.getAuthor());
|
map.put("author",genConfig.getAuthor());
|
||||||
|
|
@ -85,6 +85,8 @@ public class GenUtil {
|
||||||
map.put("upperCaseClassName", className.toUpperCase());
|
map.put("upperCaseClassName", className.toUpperCase());
|
||||||
map.put("changeClassName", changeClassName);
|
map.put("changeClassName", changeClassName);
|
||||||
map.put("hasTimestamp",false);
|
map.put("hasTimestamp",false);
|
||||||
|
map.put("queryHasTimestamp",false);
|
||||||
|
map.put("queryHasBigDecimal",false);
|
||||||
map.put("hasBigDecimal",false);
|
map.put("hasBigDecimal",false);
|
||||||
map.put("hasQuery",false);
|
map.put("hasQuery",false);
|
||||||
map.put("auto",false);
|
map.put("auto",false);
|
||||||
|
|
@ -92,7 +94,7 @@ public class GenUtil {
|
||||||
List<Map<String,Object>> columns = new ArrayList<>();
|
List<Map<String,Object>> columns = new ArrayList<>();
|
||||||
List<Map<String,Object>> queryColumns = new ArrayList<>();
|
List<Map<String,Object>> queryColumns = new ArrayList<>();
|
||||||
for (ColumnInfo column : columnInfos) {
|
for (ColumnInfo column : columnInfos) {
|
||||||
Map<String,Object> listMap = new HashMap();
|
Map<String,Object> listMap = new HashMap<>();
|
||||||
listMap.put("columnComment",column.getColumnComment());
|
listMap.put("columnComment",column.getColumnComment());
|
||||||
listMap.put("columnKey",column.getColumnKey());
|
listMap.put("columnKey",column.getColumnKey());
|
||||||
|
|
||||||
|
|
@ -124,6 +126,12 @@ public class GenUtil {
|
||||||
if(!StringUtils.isBlank(column.getColumnQuery())){
|
if(!StringUtils.isBlank(column.getColumnQuery())){
|
||||||
listMap.put("columnQuery",column.getColumnQuery());
|
listMap.put("columnQuery",column.getColumnQuery());
|
||||||
map.put("hasQuery",true);
|
map.put("hasQuery",true);
|
||||||
|
if(TIMESTAMP.equals(colType)){
|
||||||
|
map.put("queryHasTimestamp",true);
|
||||||
|
}
|
||||||
|
if(BIGDECIMAL.equals(colType)){
|
||||||
|
map.put("queryHasBigDecimal",true);
|
||||||
|
}
|
||||||
queryColumns.add(listMap);
|
queryColumns.add(listMap);
|
||||||
}
|
}
|
||||||
columns.add(listMap);
|
columns.add(listMap);
|
||||||
|
|
@ -138,6 +146,7 @@ public class GenUtil {
|
||||||
Template template = engine.getTemplate("generator/admin/"+templateName+".ftl");
|
Template template = engine.getTemplate("generator/admin/"+templateName+".ftl");
|
||||||
String filePath = getAdminFilePath(templateName,genConfig,className);
|
String filePath = getAdminFilePath(templateName,genConfig,className);
|
||||||
|
|
||||||
|
assert filePath != null;
|
||||||
File file = new File(filePath);
|
File file = new File(filePath);
|
||||||
|
|
||||||
// 如果非覆盖生成
|
// 如果非覆盖生成
|
||||||
|
|
@ -154,6 +163,7 @@ public class GenUtil {
|
||||||
Template template = engine.getTemplate("generator/front/"+templateName+".ftl");
|
Template template = engine.getTemplate("generator/front/"+templateName+".ftl");
|
||||||
String filePath = getFrontFilePath(templateName,genConfig,map.get("changeClassName").toString());
|
String filePath = getFrontFilePath(templateName,genConfig,map.get("changeClassName").toString());
|
||||||
|
|
||||||
|
assert filePath != null;
|
||||||
File file = new File(filePath);
|
File file = new File(filePath);
|
||||||
|
|
||||||
// 如果非覆盖生成
|
// 如果非覆盖生成
|
||||||
|
|
@ -168,7 +178,7 @@ public class GenUtil {
|
||||||
/**
|
/**
|
||||||
* 定义后端文件路径以及名称
|
* 定义后端文件路径以及名称
|
||||||
*/
|
*/
|
||||||
public static String getAdminFilePath(String templateName, GenConfig genConfig, String className) {
|
private static String getAdminFilePath(String templateName, GenConfig genConfig, String className) {
|
||||||
String projectPath = System.getProperty("user.dir") + File.separator + genConfig.getModuleName();
|
String projectPath = System.getProperty("user.dir") + File.separator + genConfig.getModuleName();
|
||||||
String packagePath = projectPath + File.separator + "src" +File.separator+ "main" + File.separator + "java" + File.separator;
|
String packagePath = projectPath + File.separator + "src" +File.separator+ "main" + File.separator + "java" + File.separator;
|
||||||
if (!ObjectUtils.isEmpty(genConfig.getPack())) {
|
if (!ObjectUtils.isEmpty(genConfig.getPack())) {
|
||||||
|
|
@ -213,7 +223,7 @@ public class GenUtil {
|
||||||
/**
|
/**
|
||||||
* 定义前端文件路径以及名称
|
* 定义前端文件路径以及名称
|
||||||
*/
|
*/
|
||||||
public static String getFrontFilePath(String templateName, GenConfig genConfig, String apiName) {
|
private static String getFrontFilePath(String templateName, GenConfig genConfig, String apiName) {
|
||||||
String path = genConfig.getPath();
|
String path = genConfig.getPath();
|
||||||
|
|
||||||
if ("api".equals(templateName)) {
|
if ("api".equals(templateName)) {
|
||||||
|
|
@ -230,18 +240,17 @@ public class GenUtil {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void genFile(File file,Template template,Map<String,Object> map) throws IOException {
|
private static void genFile(File file, Template template, Map<String, Object> map) throws IOException {
|
||||||
// 生成目标文件
|
// 生成目标文件
|
||||||
Writer writer = null;
|
Writer writer = null;
|
||||||
try {
|
try {
|
||||||
FileUtil.touch(file);
|
FileUtil.touch(file);
|
||||||
writer = new FileWriter(file);
|
writer = new FileWriter(file);
|
||||||
template.render(map, writer);
|
template.render(map, writer);
|
||||||
} catch (TemplateException e) {
|
} catch (TemplateException | IOException e) {
|
||||||
throw new RuntimeException(e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} finally {
|
} finally {
|
||||||
|
assert writer != null;
|
||||||
writer.close();
|
writer.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>eladmin</artifactId>
|
<artifactId>eladmin</artifactId>
|
||||||
<groupId>me.zhengjie</groupId>
|
<groupId>me.zhengjie</groupId>
|
||||||
<version>2.2</version>
|
<version>2.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>me.zhengjie</groupId>
|
<groupId>me.zhengjie</groupId>
|
||||||
<artifactId>eladmin-common</artifactId>
|
<artifactId>eladmin-common</artifactId>
|
||||||
<version>2.2</version>
|
<version>2.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -2,7 +2,6 @@ package me.zhengjie.aspect;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.zhengjie.domain.Log;
|
import me.zhengjie.domain.Log;
|
||||||
import me.zhengjie.exception.BadRequestException;
|
|
||||||
import me.zhengjie.service.LogService;
|
import me.zhengjie.service.LogService;
|
||||||
import me.zhengjie.utils.RequestHolder;
|
import me.zhengjie.utils.RequestHolder;
|
||||||
import me.zhengjie.utils.SecurityUtils;
|
import me.zhengjie.utils.SecurityUtils;
|
||||||
|
|
@ -14,7 +13,6 @@ import org.aspectj.lang.annotation.AfterThrowing;
|
||||||
import org.aspectj.lang.annotation.Around;
|
import org.aspectj.lang.annotation.Around;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Pointcut;
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
@ -28,11 +26,14 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class LogAspect {
|
public class LogAspect {
|
||||||
|
|
||||||
@Autowired
|
private final LogService logService;
|
||||||
private LogService logService;
|
|
||||||
|
|
||||||
private long currentTime = 0L;
|
private long currentTime = 0L;
|
||||||
|
|
||||||
|
public LogAspect(LogService logService) {
|
||||||
|
this.logService = logService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置切入点
|
* 配置切入点
|
||||||
*/
|
*/
|
||||||
|
|
@ -48,11 +49,12 @@ public class LogAspect {
|
||||||
*/
|
*/
|
||||||
@Around("logPointcut()")
|
@Around("logPointcut()")
|
||||||
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
Object result = null;
|
Object result;
|
||||||
currentTime = System.currentTimeMillis();
|
currentTime = System.currentTimeMillis();
|
||||||
result = joinPoint.proceed();
|
result = joinPoint.proceed();
|
||||||
Log log = new Log("INFO",System.currentTimeMillis() - currentTime);
|
Log log = new Log("INFO",System.currentTimeMillis() - currentTime);
|
||||||
logService.save(getUsername(), StringUtils.getIP(RequestHolder.getHttpServletRequest()),joinPoint, log);
|
HttpServletRequest request = RequestHolder.getHttpServletRequest();
|
||||||
|
logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request),joinPoint, log);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,7 +68,8 @@ public class LogAspect {
|
||||||
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
|
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
|
||||||
Log log = new Log("ERROR",System.currentTimeMillis() - currentTime);
|
Log log = new Log("ERROR",System.currentTimeMillis() - currentTime);
|
||||||
log.setExceptionDetail(ThrowableUtil.getStackTrace(e).getBytes());
|
log.setExceptionDetail(ThrowableUtil.getStackTrace(e).getBytes());
|
||||||
logService.save(getUsername(), StringUtils.getIP(RequestHolder.getHttpServletRequest()), (ProceedingJoinPoint)joinPoint, log);
|
HttpServletRequest request = RequestHolder.getHttpServletRequest();
|
||||||
|
logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint)joinPoint, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
|
|
|
||||||
|
|
@ -21,56 +21,40 @@ public class Log implements Serializable {
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/**
|
// 操作用户
|
||||||
* 操作用户
|
|
||||||
*/
|
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
/**
|
// 描述
|
||||||
* 描述
|
|
||||||
*/
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
/**
|
// 方法名
|
||||||
* 方法名
|
|
||||||
*/
|
|
||||||
private String method;
|
private String method;
|
||||||
|
|
||||||
/**
|
// 参数
|
||||||
* 参数
|
|
||||||
*/
|
|
||||||
@Column(columnDefinition = "text")
|
@Column(columnDefinition = "text")
|
||||||
private String params;
|
private String params;
|
||||||
|
|
||||||
/**
|
// 日志类型
|
||||||
* 日志类型
|
|
||||||
*/
|
|
||||||
@Column(name = "log_type")
|
@Column(name = "log_type")
|
||||||
private String logType;
|
private String logType;
|
||||||
|
|
||||||
/**
|
// 请求ip
|
||||||
* 请求ip
|
|
||||||
*/
|
|
||||||
@Column(name = "request_ip")
|
@Column(name = "request_ip")
|
||||||
private String requestIp;
|
private String requestIp;
|
||||||
|
|
||||||
@Column(name = "address")
|
@Column(name = "address")
|
||||||
private String address;
|
private String address;
|
||||||
|
|
||||||
/**
|
private String browser;
|
||||||
* 请求耗时
|
|
||||||
*/
|
// 请求耗时
|
||||||
private Long time;
|
private Long time;
|
||||||
|
|
||||||
/**
|
// 异常详细
|
||||||
* 异常详细
|
|
||||||
*/
|
|
||||||
@Column(name = "exception_detail", columnDefinition = "text")
|
@Column(name = "exception_detail", columnDefinition = "text")
|
||||||
private byte[] exceptionDetail;
|
private byte[] exceptionDetail;
|
||||||
|
|
||||||
/**
|
// 创建日期
|
||||||
* 创建日期
|
|
||||||
*/
|
|
||||||
@CreationTimestamp
|
@CreationTimestamp
|
||||||
@Column(name = "create_time")
|
@Column(name = "create_time")
|
||||||
private Timestamp createTime;
|
private Timestamp createTime;
|
||||||
|
|
|
||||||
|
|
@ -11,22 +11,14 @@ import org.springframework.stereotype.Repository;
|
||||||
* @date 2018-11-24
|
* @date 2018-11-24
|
||||||
*/
|
*/
|
||||||
@Repository
|
@Repository
|
||||||
public interface LogRepository extends JpaRepository<Log,Long>, JpaSpecificationExecutor {
|
public interface LogRepository extends JpaRepository<Log,Long>, JpaSpecificationExecutor<Log> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取一个时间段的IP记录
|
* 获取一个时间段的IP记录
|
||||||
* @param date1
|
|
||||||
* @param date2
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@Query(value = "select count(*) FROM (select request_ip FROM log where create_time between ?1 and ?2 GROUP BY request_ip) as s",nativeQuery = true)
|
@Query(value = "select count(*) FROM (select request_ip FROM log where create_time between ?1 and ?2 GROUP BY request_ip) as s",nativeQuery = true)
|
||||||
Long findIp(String date1, String date2);
|
Long findIp(String date1, String date2);
|
||||||
|
|
||||||
/**
|
@Query(value = "select l FROM Log l where l.id = ?1")
|
||||||
* findExceptionById
|
Log findExceptionById(Long id);
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Query(value = "select exception_detail FROM log where id = ?1",nativeQuery = true)
|
|
||||||
String findExceptionById(Long id);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
package me.zhengjie.rest;
|
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.LogService;
|
||||||
import me.zhengjie.service.dto.LogQueryCriteria;
|
import me.zhengjie.service.dto.LogQueryCriteria;
|
||||||
import me.zhengjie.utils.SecurityUtils;
|
import me.zhengjie.utils.SecurityUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
@ -13,41 +15,60 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2018-11-24
|
* @date 2018-11-24
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("api")
|
@RequestMapping("/api/logs")
|
||||||
|
@Api(tags = "监控:日志管理")
|
||||||
public class LogController {
|
public class LogController {
|
||||||
|
|
||||||
@Autowired
|
private final LogService logService;
|
||||||
private LogService logService;
|
|
||||||
|
|
||||||
@GetMapping(value = "/logs")
|
public LogController(LogService logService) {
|
||||||
@PreAuthorize("hasAnyRole('ADMIN')")
|
this.logService = logService;
|
||||||
public ResponseEntity getLogs(LogQueryCriteria criteria, Pageable pageable){
|
|
||||||
criteria.setLogType("INFO");
|
|
||||||
return new ResponseEntity(logService.queryAll(criteria,pageable), HttpStatus.OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/logs/user")
|
@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){
|
public ResponseEntity getUserLogs(LogQueryCriteria criteria, Pageable pageable){
|
||||||
criteria.setLogType("INFO");
|
criteria.setLogType("INFO");
|
||||||
criteria.setBlurry(SecurityUtils.getUsername());
|
criteria.setBlurry(SecurityUtils.getUsername());
|
||||||
return new ResponseEntity(logService.queryAllByUser(criteria,pageable), HttpStatus.OK);
|
return new ResponseEntity<>(logService.queryAllByUser(criteria,pageable), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/logs/error")
|
@GetMapping(value = "/error")
|
||||||
@PreAuthorize("hasAnyRole('ADMIN')")
|
@ApiOperation("错误日志查询")
|
||||||
|
@PreAuthorize("@el.check()")
|
||||||
public ResponseEntity getErrorLogs(LogQueryCriteria criteria, Pageable pageable){
|
public ResponseEntity getErrorLogs(LogQueryCriteria criteria, Pageable pageable){
|
||||||
criteria.setLogType("ERROR");
|
criteria.setLogType("ERROR");
|
||||||
return new ResponseEntity(logService.queryAll(criteria,pageable), HttpStatus.OK);
|
return new ResponseEntity<>(logService.queryAll(criteria,pageable), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/logs/error/{id}")
|
@GetMapping(value = "/error/{id}")
|
||||||
@PreAuthorize("hasAnyRole('ADMIN')")
|
@ApiOperation("日志异常详情查询")
|
||||||
|
@PreAuthorize("@el.check()")
|
||||||
public ResponseEntity getErrorLogs(@PathVariable Long id){
|
public ResponseEntity getErrorLogs(@PathVariable Long id){
|
||||||
return new ResponseEntity(logService.findByErrDetail(id), HttpStatus.OK);
|
return new ResponseEntity<>(logService.findByErrDetail(id), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,42 +6,31 @@ import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2018-11-24
|
* @date 2018-11-24
|
||||||
*/
|
*/
|
||||||
public interface LogService {
|
public interface LogService {
|
||||||
|
|
||||||
/**
|
|
||||||
* queryAll
|
|
||||||
* @param criteria
|
|
||||||
* @param pageable
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Object queryAll(LogQueryCriteria criteria, Pageable pageable);
|
Object queryAll(LogQueryCriteria criteria, Pageable pageable);
|
||||||
|
|
||||||
/**
|
List<Log> queryAll(LogQueryCriteria criteria);
|
||||||
* queryAllByUser
|
|
||||||
* @param criteria
|
|
||||||
* @param pageable
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable);
|
Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable);
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增日志
|
|
||||||
* @param username
|
|
||||||
* @param ip
|
|
||||||
* @param joinPoint
|
|
||||||
* @param log
|
|
||||||
*/
|
|
||||||
@Async
|
@Async
|
||||||
void save(String username, String ip, ProceedingJoinPoint joinPoint, Log log);
|
void save(String username, String browser, String ip, ProceedingJoinPoint joinPoint, Log log);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询异常详情
|
* 查询异常详情
|
||||||
* @param id
|
* @param id 日志ID
|
||||||
* @return
|
* @return Object
|
||||||
*/
|
*/
|
||||||
Object findByErrDetail(Long id);
|
Object findByErrDetail(Long id);
|
||||||
|
|
||||||
|
void download(List<Log> queryAll, HttpServletResponse response) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,36 +13,26 @@ public class LogErrorDTO implements Serializable {
|
||||||
|
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/**
|
// 操作用户
|
||||||
* 操作用户
|
|
||||||
*/
|
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
/**
|
// 描述
|
||||||
* 描述
|
|
||||||
*/
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
/**
|
// 方法名
|
||||||
* 方法名
|
|
||||||
*/
|
|
||||||
private String method;
|
private String method;
|
||||||
|
|
||||||
/**
|
// 参数
|
||||||
* 参数
|
|
||||||
*/
|
|
||||||
private String params;
|
private String params;
|
||||||
|
|
||||||
/**
|
private String browser;
|
||||||
* 请求ip
|
|
||||||
*/
|
// 请求ip
|
||||||
private String requestIp;
|
private String requestIp;
|
||||||
|
|
||||||
private String address;
|
private String address;
|
||||||
|
|
||||||
|
|
||||||
/**
|
// 创建日期
|
||||||
* 创建日期
|
|
||||||
*/
|
|
||||||
private Timestamp createTime;
|
private Timestamp createTime;
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,8 @@ package me.zhengjie.service.dto;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import me.zhengjie.annotation.Query;
|
import me.zhengjie.annotation.Query;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志查询类
|
* 日志查询类
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
|
|
@ -17,4 +19,10 @@ public class LogQueryCriteria {
|
||||||
|
|
||||||
@Query
|
@Query
|
||||||
private String logType;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package me.zhengjie.service.dto;
|
package me.zhengjie.service.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
|
@ -12,25 +11,19 @@ import java.sql.Timestamp;
|
||||||
@Data
|
@Data
|
||||||
public class LogSmallDTO implements Serializable {
|
public class LogSmallDTO implements Serializable {
|
||||||
|
|
||||||
/**
|
// 描述
|
||||||
* 描述
|
|
||||||
*/
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
/**
|
// 请求ip
|
||||||
* 请求ip
|
|
||||||
*/
|
|
||||||
private String requestIp;
|
private String requestIp;
|
||||||
|
|
||||||
/**
|
// 请求耗时
|
||||||
* 请求耗时
|
|
||||||
*/
|
|
||||||
private Long time;
|
private Long time;
|
||||||
|
|
||||||
private String address;
|
private String address;
|
||||||
|
|
||||||
/**
|
private String browser;
|
||||||
* 创建日期
|
|
||||||
*/
|
// 创建日期
|
||||||
private Timestamp createTime;
|
private Timestamp createTime;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package me.zhengjie.service.impl;
|
package me.zhengjie.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.lang.Dict;
|
import cn.hutool.core.lang.Dict;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONObject;
|
||||||
import me.zhengjie.domain.Log;
|
import me.zhengjie.domain.Log;
|
||||||
import me.zhengjie.repository.LogRepository;
|
import me.zhengjie.repository.LogRepository;
|
||||||
|
|
@ -8,18 +9,25 @@ import me.zhengjie.service.LogService;
|
||||||
import me.zhengjie.service.dto.LogQueryCriteria;
|
import me.zhengjie.service.dto.LogQueryCriteria;
|
||||||
import me.zhengjie.service.mapper.LogErrorMapper;
|
import me.zhengjie.service.mapper.LogErrorMapper;
|
||||||
import me.zhengjie.service.mapper.LogSmallMapper;
|
import me.zhengjie.service.mapper.LogSmallMapper;
|
||||||
|
import me.zhengjie.utils.FileUtil;
|
||||||
import me.zhengjie.utils.PageUtil;
|
import me.zhengjie.utils.PageUtil;
|
||||||
import me.zhengjie.utils.QueryHelp;
|
import me.zhengjie.utils.QueryHelp;
|
||||||
import me.zhengjie.utils.StringUtils;
|
import me.zhengjie.utils.StringUtils;
|
||||||
import org.aspectj.lang.ProceedingJoinPoint;
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
import org.aspectj.lang.reflect.MethodSignature;
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
|
|
@ -29,16 +37,17 @@ import java.lang.reflect.Method;
|
||||||
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
||||||
public class LogServiceImpl implements LogService {
|
public class LogServiceImpl implements LogService {
|
||||||
|
|
||||||
@Autowired
|
private final LogRepository logRepository;
|
||||||
private LogRepository logRepository;
|
|
||||||
|
|
||||||
@Autowired
|
private final LogErrorMapper logErrorMapper;
|
||||||
private LogErrorMapper logErrorMapper;
|
|
||||||
|
|
||||||
@Autowired
|
private final LogSmallMapper logSmallMapper;
|
||||||
private LogSmallMapper logSmallMapper;
|
|
||||||
|
|
||||||
private final String LOGINPATH = "login";
|
public LogServiceImpl(LogRepository logRepository, LogErrorMapper logErrorMapper, LogSmallMapper logSmallMapper) {
|
||||||
|
this.logRepository = logRepository;
|
||||||
|
this.logErrorMapper = logErrorMapper;
|
||||||
|
this.logSmallMapper = logSmallMapper;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object queryAll(LogQueryCriteria criteria, Pageable pageable){
|
public Object queryAll(LogQueryCriteria criteria, Pageable pageable){
|
||||||
|
|
@ -49,6 +58,11 @@ public class LogServiceImpl implements LogService {
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Log> queryAll(LogQueryCriteria criteria) {
|
||||||
|
return logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable) {
|
public Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable) {
|
||||||
Page<Log> page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)),pageable);
|
Page<Log> page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)),pageable);
|
||||||
|
|
@ -57,38 +71,37 @@ public class LogServiceImpl implements LogService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void save(String username, String ip, ProceedingJoinPoint joinPoint, Log log){
|
public void save(String username, String browser, String ip, ProceedingJoinPoint joinPoint, Log log){
|
||||||
|
|
||||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
Method method = signature.getMethod();
|
Method method = signature.getMethod();
|
||||||
me.zhengjie.aop.log.Log aopLog = method.getAnnotation(me.zhengjie.aop.log.Log.class);
|
me.zhengjie.aop.log.Log aopLog = method.getAnnotation(me.zhengjie.aop.log.Log.class);
|
||||||
|
|
||||||
// 描述
|
|
||||||
if (log != null) {
|
|
||||||
log.setDescription(aopLog.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 方法路径
|
// 方法路径
|
||||||
String methodName = joinPoint.getTarget().getClass().getName()+"."+signature.getName()+"()";
|
String methodName = joinPoint.getTarget().getClass().getName()+"."+signature.getName()+"()";
|
||||||
|
|
||||||
String params = "{";
|
StringBuilder params = new StringBuilder("{");
|
||||||
//参数值
|
//参数值
|
||||||
Object[] argValues = joinPoint.getArgs();
|
Object[] argValues = joinPoint.getArgs();
|
||||||
//参数名称
|
//参数名称
|
||||||
String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
|
String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
|
||||||
if(argValues != null){
|
if(argValues != null){
|
||||||
for (int i = 0; i < argValues.length; i++) {
|
for (int i = 0; i < argValues.length; i++) {
|
||||||
params += " " + argNames[i] + ": " + argValues[i];
|
params.append(" ").append(argNames[i]).append(": ").append(argValues[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 描述
|
||||||
// 获取IP地址
|
if (log != null) {
|
||||||
|
log.setDescription(aopLog.value());
|
||||||
|
}
|
||||||
|
assert log != null;
|
||||||
log.setRequestIp(ip);
|
log.setRequestIp(ip);
|
||||||
|
|
||||||
|
String LOGINPATH = "login";
|
||||||
if(LOGINPATH.equals(signature.getName())){
|
if(LOGINPATH.equals(signature.getName())){
|
||||||
try {
|
try {
|
||||||
JSONObject jsonObject = new JSONObject(argValues[0]);
|
assert argValues != null;
|
||||||
username = jsonObject.get("username").toString();
|
username = new JSONObject(argValues[0]).get("username").toString();
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
@ -96,12 +109,32 @@ public class LogServiceImpl implements LogService {
|
||||||
log.setAddress(StringUtils.getCityInfo(log.getRequestIp()));
|
log.setAddress(StringUtils.getCityInfo(log.getRequestIp()));
|
||||||
log.setMethod(methodName);
|
log.setMethod(methodName);
|
||||||
log.setUsername(username);
|
log.setUsername(username);
|
||||||
log.setParams(params + " }");
|
log.setParams(params.toString() + " }");
|
||||||
|
log.setBrowser(browser);
|
||||||
logRepository.save(log);
|
logRepository.save(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object findByErrDetail(Long id) {
|
public Object findByErrDetail(Long id) {
|
||||||
return Dict.create().set("exception",logRepository.findExceptionById(id));
|
byte[] details = logRepository.findExceptionById(id).getExceptionDetail();
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package me.zhengjie.service.mapper;
|
package me.zhengjie.service.mapper;
|
||||||
|
|
||||||
|
import me.zhengjie.base.BaseMapper;
|
||||||
import me.zhengjie.domain.Log;
|
import me.zhengjie.domain.Log;
|
||||||
import me.zhengjie.mapper.EntityMapper;
|
|
||||||
import me.zhengjie.service.dto.LogErrorDTO;
|
import me.zhengjie.service.dto.LogErrorDTO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.ReportingPolicy;
|
import org.mapstruct.ReportingPolicy;
|
||||||
|
|
@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy;
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2019-5-22
|
* @date 2019-5-22
|
||||||
*/
|
*/
|
||||||
@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||||
public interface LogErrorMapper extends EntityMapper<LogErrorDTO, Log> {
|
public interface LogErrorMapper extends BaseMapper<LogErrorDTO, Log> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package me.zhengjie.service.mapper;
|
package me.zhengjie.service.mapper;
|
||||||
|
|
||||||
|
import me.zhengjie.base.BaseMapper;
|
||||||
import me.zhengjie.domain.Log;
|
import me.zhengjie.domain.Log;
|
||||||
import me.zhengjie.mapper.EntityMapper;
|
|
||||||
import me.zhengjie.service.dto.LogSmallDTO;
|
import me.zhengjie.service.dto.LogSmallDTO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.ReportingPolicy;
|
import org.mapstruct.ReportingPolicy;
|
||||||
|
|
@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy;
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2019-5-22
|
* @date 2019-5-22
|
||||||
*/
|
*/
|
||||||
@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||||
public interface LogSmallMapper extends EntityMapper<LogSmallDTO, Log> {
|
public interface LogSmallMapper extends BaseMapper<LogSmallDTO, Log> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>eladmin</artifactId>
|
<artifactId>eladmin</artifactId>
|
||||||
<groupId>me.zhengjie</groupId>
|
<groupId>me.zhengjie</groupId>
|
||||||
<version>2.2</version>
|
<version>2.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>me.zhengjie</groupId>
|
<groupId>me.zhengjie</groupId>
|
||||||
<artifactId>eladmin-generator</artifactId>
|
<artifactId>eladmin-generator</artifactId>
|
||||||
<version>2.2</version>
|
<version>2.3</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>me.zhengjie</groupId>
|
<groupId>me.zhengjie</groupId>
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>me.zhengjie</groupId>
|
<groupId>me.zhengjie</groupId>
|
||||||
<artifactId>eladmin-tools</artifactId>
|
<artifactId>eladmin-tools</artifactId>
|
||||||
<version>2.2</version>
|
<version>2.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--jwt-->
|
<!--jwt-->
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,17 @@ public class DataScope {
|
||||||
|
|
||||||
private final String[] scopeType = {"全部","本级","自定义"};
|
private final String[] scopeType = {"全部","本级","自定义"};
|
||||||
|
|
||||||
@Autowired
|
private final UserService userService;
|
||||||
private UserService userService;
|
|
||||||
|
|
||||||
@Autowired
|
private final RoleService roleService;
|
||||||
private RoleService roleService;
|
|
||||||
|
|
||||||
@Autowired
|
private final DeptService deptService;
|
||||||
private DeptService deptService;
|
|
||||||
|
public DataScope(UserService userService, RoleService roleService, DeptService deptService) {
|
||||||
|
this.userService = userService;
|
||||||
|
this.roleService = roleService;
|
||||||
|
this.deptService = deptService;
|
||||||
|
}
|
||||||
|
|
||||||
public Set<Long> getDeptIds() {
|
public Set<Long> getDeptIds() {
|
||||||
|
|
||||||
|
|
@ -76,7 +79,7 @@ public class DataScope {
|
||||||
deptList.forEach(dept -> {
|
deptList.forEach(dept -> {
|
||||||
if (dept!=null && dept.getEnabled()){
|
if (dept!=null && dept.getEnabled()){
|
||||||
List<Dept> depts = deptService.findByPid(dept.getId());
|
List<Dept> depts = deptService.findByPid(dept.getId());
|
||||||
if(deptList!=null && deptList.size()!=0){
|
if(deptList.size() != 0){
|
||||||
list.addAll(getDeptChildren(depts));
|
list.addAll(getDeptChildren(depts));
|
||||||
}
|
}
|
||||||
list.add(dept.getId());
|
list.add(dept.getId());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
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());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
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()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package me.zhengjie.modules.monitor.config;
|
package me.zhengjie.modules.monitor.config;
|
||||||
|
|
||||||
import me.zhengjie.modules.monitor.service.VisitsService;
|
import me.zhengjie.modules.monitor.service.VisitsService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.ApplicationArguments;
|
import org.springframework.boot.ApplicationArguments;
|
||||||
import org.springframework.boot.ApplicationRunner;
|
import org.springframework.boot.ApplicationRunner;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
@ -13,11 +12,14 @@ import org.springframework.stereotype.Component;
|
||||||
@Component
|
@Component
|
||||||
public class VisitsInitialization implements ApplicationRunner {
|
public class VisitsInitialization implements ApplicationRunner {
|
||||||
|
|
||||||
@Autowired
|
private final VisitsService visitsService;
|
||||||
private VisitsService visitsService;
|
|
||||||
|
public VisitsInitialization(VisitsService visitsService) {
|
||||||
|
this.visitsService = visitsService;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(ApplicationArguments args) throws Exception {
|
public void run(ApplicationArguments args){
|
||||||
System.out.println("--------------- 初始化站点统计,如果存在今日统计则跳过 ---------------");
|
System.out.println("--------------- 初始化站点统计,如果存在今日统计则跳过 ---------------");
|
||||||
visitsService.save();
|
visitsService.save();
|
||||||
System.out.println("--------------- 初始化站点统计完成 ---------------");
|
System.out.println("--------------- 初始化站点统计完成 ---------------");
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import lombok.Data;
|
||||||
import org.hibernate.annotations.CreationTimestamp;
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -15,7 +16,7 @@ import java.sql.Timestamp;
|
||||||
@Entity
|
@Entity
|
||||||
@Data
|
@Data
|
||||||
@Table(name = "visits")
|
@Table(name = "visits")
|
||||||
public class Visits {
|
public class Visits implements Serializable {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import me.zhengjie.modules.monitor.domain.Visits;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -16,18 +15,17 @@ public interface VisitsRepository extends JpaRepository<Visits,Long> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* findByDate
|
* findByDate
|
||||||
* @param date
|
* @param date 日期
|
||||||
* @return
|
* @return Visits
|
||||||
*/
|
*/
|
||||||
Visits findByDate(String date);
|
Visits findByDate(String date);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得一个时间段的记录
|
* 获得一个时间段的记录
|
||||||
* @param date1
|
* @param date1 日期1
|
||||||
* @param date2
|
* @param date2 日期2
|
||||||
* @return
|
* @return List
|
||||||
*/
|
*/
|
||||||
@Query(value = "select * FROM visits where " +
|
@Query(value = "select * FROM visits where create_time between ?1 and ?2",nativeQuery = true)
|
||||||
"create_time between ?1 and ?2",nativeQuery = true)
|
|
||||||
List<Visits> findAllVisits(String date1, String date2);
|
List<Visits> findAllVisits(String date1, String date2);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
package me.zhengjie.modules.monitor.rest;
|
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 me.zhengjie.annotation.Limit;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
@ -12,15 +16,19 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
* 接口限流测试类
|
* 接口限流测试类
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("api")
|
@RequestMapping("/api/limit")
|
||||||
|
@Api(tags = "系统:限流测试管理")
|
||||||
public class LimitController {
|
public class LimitController {
|
||||||
|
|
||||||
private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger();
|
private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 测试限流注解,下面配置说明该接口 60秒内最多只能访问 10次,保存到redis的键名为 limit_test,
|
* 测试限流注解,下面配置说明该接口 60秒内最多只能访问 10次,保存到redis的键名为 limit_test,
|
||||||
*/
|
*/
|
||||||
|
@GetMapping
|
||||||
|
@PreAuthorize("@el.check('anonymous')")
|
||||||
|
@ApiOperation("测试")
|
||||||
@Limit(key = "test", period = 60, count = 10, name = "testLimit", prefix = "limit")
|
@Limit(key = "test", period = 60, count = 10, name = "testLimit", prefix = "limit")
|
||||||
@GetMapping("/limit")
|
|
||||||
public int testLimit() {
|
public int testLimit() {
|
||||||
return ATOMIC_INTEGER.incrementAndGet();
|
return ATOMIC_INTEGER.incrementAndGet();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,65 @@
|
||||||
package me.zhengjie.modules.monitor.rest;
|
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.aop.log.Log;
|
||||||
import me.zhengjie.modules.monitor.domain.vo.RedisVo;
|
import me.zhengjie.modules.monitor.domain.vo.RedisVo;
|
||||||
import me.zhengjie.modules.monitor.service.RedisService;
|
import me.zhengjie.modules.monitor.service.RedisService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2018-12-10
|
* @date 2018-12-10
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("api")
|
@RequestMapping("/api/redis")
|
||||||
|
@Api(tags = "系统:Redis缓存管理")
|
||||||
public class RedisController {
|
public class RedisController {
|
||||||
|
|
||||||
@Autowired
|
private final RedisService redisService;
|
||||||
private RedisService redisService;
|
|
||||||
|
public RedisController(RedisService redisService) {
|
||||||
|
this.redisService = redisService;
|
||||||
|
}
|
||||||
|
|
||||||
@Log("查询Redis缓存")
|
@Log("查询Redis缓存")
|
||||||
@GetMapping(value = "/redis")
|
@GetMapping
|
||||||
@PreAuthorize("hasAnyRole('ADMIN','REDIS_ALL','REDIS_SELECT')")
|
@ApiOperation("查询Redis缓存")
|
||||||
|
@PreAuthorize("@el.check('redis:list')")
|
||||||
public ResponseEntity getRedis(String key, Pageable pageable){
|
public ResponseEntity getRedis(String key, Pageable pageable){
|
||||||
return new ResponseEntity(redisService.findByKey(key,pageable), HttpStatus.OK);
|
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缓存")
|
@Log("删除Redis缓存")
|
||||||
@DeleteMapping(value = "/redis")
|
@DeleteMapping
|
||||||
@PreAuthorize("hasAnyRole('ADMIN','REDIS_ALL','REDIS_DELETE')")
|
@ApiOperation("删除Redis缓存")
|
||||||
|
@PreAuthorize("@el.check('redis:del')")
|
||||||
public ResponseEntity delete(@RequestBody RedisVo resources){
|
public ResponseEntity delete(@RequestBody RedisVo resources){
|
||||||
redisService.delete(resources.getKey());
|
redisService.delete(resources.getKey());
|
||||||
return new ResponseEntity(HttpStatus.OK);
|
return new ResponseEntity(HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Log("清空Redis缓存")
|
@Log("清空Redis缓存")
|
||||||
@DeleteMapping(value = "/redis/all")
|
@DeleteMapping(value = "/all")
|
||||||
@PreAuthorize("hasAnyRole('ADMIN','REDIS_ALL','REDIS_DELETE')")
|
@ApiOperation("清空Redis缓存")
|
||||||
|
@PreAuthorize("@el.check('redis:del')")
|
||||||
public ResponseEntity deleteAll(){
|
public ResponseEntity deleteAll(){
|
||||||
redisService.flushdb();
|
redisService.deleteAll();
|
||||||
return new ResponseEntity(HttpStatus.OK);
|
return new ResponseEntity(HttpStatus.OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
package me.zhengjie.modules.monitor.rest;
|
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.modules.monitor.service.VisitsService;
|
||||||
import me.zhengjie.utils.RequestHolder;
|
import me.zhengjie.utils.RequestHolder;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
@ -15,25 +16,32 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
* @date 2018-12-13
|
* @date 2018-12-13
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("api")
|
@RequestMapping("/api/visits")
|
||||||
|
@Api(tags = "系统:访问记录管理")
|
||||||
public class VisitsController {
|
public class VisitsController {
|
||||||
|
|
||||||
@Autowired
|
private final VisitsService visitsService;
|
||||||
private VisitsService visitsService;
|
|
||||||
|
|
||||||
@PostMapping(value = "/visits")
|
public VisitsController(VisitsService visitsService) {
|
||||||
|
this.visitsService = visitsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@ApiOperation("创建访问记录")
|
||||||
public ResponseEntity create(){
|
public ResponseEntity create(){
|
||||||
visitsService.count(RequestHolder.getHttpServletRequest());
|
visitsService.count(RequestHolder.getHttpServletRequest());
|
||||||
return new ResponseEntity(HttpStatus.CREATED);
|
return new ResponseEntity(HttpStatus.CREATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/visits")
|
@GetMapping
|
||||||
|
@ApiOperation("查询")
|
||||||
public ResponseEntity get(){
|
public ResponseEntity get(){
|
||||||
return new ResponseEntity(visitsService.get(),HttpStatus.OK);
|
return new ResponseEntity<>(visitsService.get(),HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/visits/chartData")
|
@GetMapping(value = "/chartData")
|
||||||
|
@ApiOperation("查询图表数据")
|
||||||
public ResponseEntity getChartData(){
|
public ResponseEntity getChartData(){
|
||||||
return new ResponseEntity(visitsService.getChartData(),HttpStatus.OK);
|
return new ResponseEntity<>(visitsService.getChartData(),HttpStatus.OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,10 @@ import me.zhengjie.modules.monitor.domain.vo.RedisVo;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可自行扩展
|
* 可自行扩展
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
|
|
@ -13,33 +17,47 @@ public interface RedisService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* findById
|
* findById
|
||||||
* @param key
|
* @param key 键
|
||||||
* @return
|
* @return /
|
||||||
*/
|
*/
|
||||||
Page findByKey(String key, Pageable pageable);
|
Page findByKey(String key, Pageable pageable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* findById
|
||||||
|
* @param key 键
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
List<RedisVo> findByKey(String key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询验证码的值
|
* 查询验证码的值
|
||||||
* @param key
|
* @param key 键
|
||||||
* @return
|
* @return /
|
||||||
*/
|
*/
|
||||||
String getCodeVal(String key);
|
String getCodeVal(String key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存验证码
|
* 保存验证码
|
||||||
* @param key
|
* @param key 键
|
||||||
* @param val
|
* @param val 值
|
||||||
*/
|
*/
|
||||||
void saveCode(String key, Object val);
|
void saveCode(String key, Object val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* delete
|
* delete
|
||||||
* @param key
|
* @param key 键
|
||||||
*/
|
*/
|
||||||
void delete(String key);
|
void delete(String key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清空所有缓存
|
* 清空缓存
|
||||||
*/
|
*/
|
||||||
void flushdb();
|
void deleteAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param redisVos /
|
||||||
|
* @param response /
|
||||||
|
*/
|
||||||
|
void download(List<RedisVo> redisVos, HttpServletResponse response) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package me.zhengjie.modules.monitor.service;
|
package me.zhengjie.modules.monitor.service;
|
||||||
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -17,20 +16,20 @@ public interface VisitsService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增记录
|
* 新增记录
|
||||||
* @param request
|
* @param request /
|
||||||
*/
|
*/
|
||||||
@Async
|
@Async
|
||||||
void count(HttpServletRequest request);
|
void count(HttpServletRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取数据
|
* 获取数据
|
||||||
* @return
|
* @return /
|
||||||
*/
|
*/
|
||||||
Object get();
|
Object get();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getChartData
|
* getChartData
|
||||||
* @return
|
* @return /
|
||||||
*/
|
*/
|
||||||
Object getChartData();
|
Object getChartData();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,51 +1,71 @@
|
||||||
package me.zhengjie.modules.monitor.service.impl;
|
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.domain.vo.RedisVo;
|
||||||
import me.zhengjie.modules.monitor.service.RedisService;
|
import me.zhengjie.modules.monitor.service.RedisService;
|
||||||
|
import me.zhengjie.utils.FileUtil;
|
||||||
import me.zhengjie.utils.PageUtil;
|
import me.zhengjie.utils.PageUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2018-12-10
|
* @date 2018-12-10
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
@SuppressWarnings({"unchecked","all"})
|
||||||
public class RedisServiceImpl implements RedisService {
|
public class RedisServiceImpl implements RedisService {
|
||||||
|
|
||||||
@Autowired
|
private final RedisTemplate redisTemplate;
|
||||||
RedisTemplate redisTemplate;
|
|
||||||
|
|
||||||
@Value("${loginCode.expiration}")
|
@Value("${loginCode.expiration}")
|
||||||
private Long expiration;
|
private Long expiration;
|
||||||
|
|
||||||
|
@Value("${jwt.online}")
|
||||||
|
private String onlineKey;
|
||||||
|
|
||||||
|
@Value("${jwt.codeKey}")
|
||||||
|
private String codeKey;
|
||||||
|
|
||||||
|
public RedisServiceImpl(RedisTemplate redisTemplate) {
|
||||||
|
this.redisTemplate = redisTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<RedisVo> findByKey(String key, Pageable pageable){
|
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<>();
|
List<RedisVo> redisVos = new ArrayList<>();
|
||||||
if(!"*".equals(key)){
|
if(!"*".equals(key)){
|
||||||
key = "*" + key + "*";
|
key = "*" + key + "*";
|
||||||
}
|
}
|
||||||
for (Object s : redisTemplate.keys(key)) {
|
Set<String> keys = redisTemplate.keys(key);
|
||||||
|
for (String s : keys) {
|
||||||
// 过滤掉权限的缓存
|
// 过滤掉权限的缓存
|
||||||
if (s.toString().indexOf("role::loadPermissionByUser") != -1 || s.toString().indexOf("user::loadUserByUsername") != -1) {
|
if (s.contains("role::loadPermissionByUser") || s.contains("user::loadUserByUsername") || s.contains(onlineKey) || s.contains(codeKey)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
RedisVo redisVo = new RedisVo(s.toString(),redisTemplate.opsForValue().get(s.toString()).toString());
|
RedisVo redisVo = new RedisVo(s, Objects.requireNonNull(redisTemplate.opsForValue().get(s)).toString());
|
||||||
redisVos.add(redisVo);
|
redisVos.add(redisVo);
|
||||||
}
|
}
|
||||||
Page<RedisVo> page = new PageImpl<RedisVo>(
|
return redisVos;
|
||||||
PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(),redisVos),
|
|
||||||
pageable,
|
|
||||||
redisVos.size());
|
|
||||||
return page;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -54,15 +74,15 @@ public class RedisServiceImpl implements RedisService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void flushdb() {
|
public void deleteAll() {
|
||||||
redisTemplate.getConnectionFactory().getConnection().flushDb();
|
Set<String> keys = redisTemplate.keys( "*");
|
||||||
|
redisTemplate.delete(keys.stream().filter(s -> !s.contains(onlineKey)).filter(s -> !s.contains(codeKey)).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCodeVal(String key) {
|
public String getCodeVal(String key) {
|
||||||
try {
|
try {
|
||||||
String value = redisTemplate.opsForValue().get(key).toString();
|
return Objects.requireNonNull(redisTemplate.opsForValue().get(key)).toString();
|
||||||
return value;
|
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
@ -73,4 +93,16 @@ public class RedisServiceImpl implements RedisService {
|
||||||
redisTemplate.opsForValue().set(key,val);
|
redisTemplate.opsForValue().set(key,val);
|
||||||
redisTemplate.expire(key,expiration, TimeUnit.MINUTES);
|
redisTemplate.expire(key,expiration, 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,14 @@ import java.util.stream.Collectors;
|
||||||
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
||||||
public class VisitsServiceImpl implements VisitsService {
|
public class VisitsServiceImpl implements VisitsService {
|
||||||
|
|
||||||
@Autowired
|
private final VisitsRepository visitsRepository;
|
||||||
private VisitsRepository visitsRepository;
|
|
||||||
|
|
||||||
@Autowired
|
private final LogRepository logRepository;
|
||||||
private LogRepository logRepository;
|
|
||||||
|
public VisitsServiceImpl(VisitsRepository visitsRepository, LogRepository logRepository) {
|
||||||
|
this.visitsRepository = visitsRepository;
|
||||||
|
this.logRepository = logRepository;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save() {
|
public void save() {
|
||||||
|
|
@ -58,7 +61,7 @@ public class VisitsServiceImpl implements VisitsService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object get() {
|
public Object get() {
|
||||||
Map map = new HashMap();
|
Map<String,Object> map = new HashMap<>();
|
||||||
LocalDate localDate = LocalDate.now();
|
LocalDate localDate = LocalDate.now();
|
||||||
Visits visits = visitsRepository.findByDate(localDate.toString());
|
Visits visits = visitsRepository.findByDate(localDate.toString());
|
||||||
List<Visits> list = visitsRepository.findAllVisits(localDate.minusDays(6).toString(),localDate.plusDays(1).toString());
|
List<Visits> list = visitsRepository.findAllVisits(localDate.minusDays(6).toString(),localDate.plusDays(1).toString());
|
||||||
|
|
@ -77,7 +80,7 @@ public class VisitsServiceImpl implements VisitsService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getChartData() {
|
public Object getChartData() {
|
||||||
Map map = new HashMap();
|
Map<String,Object> map = new HashMap<>();
|
||||||
LocalDate localDate = LocalDate.now();
|
LocalDate localDate = LocalDate.now();
|
||||||
List<Visits> list = visitsRepository.findAllVisits(localDate.minusDays(6).toString(),localDate.plusDays(1).toString());
|
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("weekDays",list.stream().map(Visits::getWeekDay).collect(Collectors.toList()));
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package me.zhengjie.modules.quartz.config;
|
||||||
import me.zhengjie.modules.quartz.domain.QuartzJob;
|
import me.zhengjie.modules.quartz.domain.QuartzJob;
|
||||||
import me.zhengjie.modules.quartz.repository.QuartzJobRepository;
|
import me.zhengjie.modules.quartz.repository.QuartzJobRepository;
|
||||||
import me.zhengjie.modules.quartz.utils.QuartzManage;
|
import me.zhengjie.modules.quartz.utils.QuartzManage;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.ApplicationArguments;
|
import org.springframework.boot.ApplicationArguments;
|
||||||
import org.springframework.boot.ApplicationRunner;
|
import org.springframework.boot.ApplicationRunner;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
@ -17,24 +16,24 @@ import java.util.List;
|
||||||
@Component
|
@Component
|
||||||
public class JobRunner implements ApplicationRunner {
|
public class JobRunner implements ApplicationRunner {
|
||||||
|
|
||||||
@Autowired
|
private final QuartzJobRepository quartzJobRepository;
|
||||||
private QuartzJobRepository quartzJobRepository;
|
|
||||||
|
|
||||||
@Autowired
|
private final QuartzManage quartzManage;
|
||||||
private QuartzManage quartzManage;
|
|
||||||
|
public JobRunner(QuartzJobRepository quartzJobRepository, QuartzManage quartzManage) {
|
||||||
|
this.quartzJobRepository = quartzJobRepository;
|
||||||
|
this.quartzManage = quartzManage;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 项目启动时重新激活启用的定时任务
|
* 项目启动时重新激活启用的定时任务
|
||||||
* @param applicationArguments
|
* @param applicationArguments /
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run(ApplicationArguments applicationArguments){
|
public void run(ApplicationArguments applicationArguments){
|
||||||
System.out.println("--------------------注入定时任务---------------------");
|
System.out.println("--------------------注入定时任务---------------------");
|
||||||
List<QuartzJob> quartzJobs = quartzJobRepository.findByIsPauseIsFalse();
|
List<QuartzJob> quartzJobs = quartzJobRepository.findByIsPauseIsFalse();
|
||||||
quartzJobs.forEach(quartzJob -> {
|
quartzJobs.forEach(quartzManage::addJob);
|
||||||
quartzManage.addJob(quartzJob);
|
|
||||||
});
|
|
||||||
System.out.println("--------------------定时任务注入完成---------------------");
|
System.out.println("--------------------定时任务注入完成---------------------");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package me.zhengjie.modules.quartz.config;
|
||||||
|
|
||||||
import org.quartz.Scheduler;
|
import org.quartz.Scheduler;
|
||||||
import org.quartz.spi.TriggerFiredBundle;
|
import org.quartz.spi.TriggerFiredBundle;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
@ -12,7 +11,7 @@ import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时任务配置
|
* 定时任务配置
|
||||||
* @author
|
* @author /
|
||||||
* @date 2019-01-07
|
* @date 2019-01-07
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
|
@ -22,10 +21,13 @@ public class QuartzConfig {
|
||||||
* 解决Job中注入Spring Bean为null的问题
|
* 解决Job中注入Spring Bean为null的问题
|
||||||
*/
|
*/
|
||||||
@Component("quartzJobFactory")
|
@Component("quartzJobFactory")
|
||||||
public class QuartzJobFactory extends AdaptableJobFactory {
|
public static class QuartzJobFactory extends AdaptableJobFactory {
|
||||||
|
|
||||||
@Autowired
|
private final AutowireCapableBeanFactory capableBeanFactory;
|
||||||
private AutowireCapableBeanFactory capableBeanFactory;
|
|
||||||
|
public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) {
|
||||||
|
this.capableBeanFactory = capableBeanFactory;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
|
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
|
||||||
|
|
@ -39,9 +41,9 @@ public class QuartzConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注入scheduler到spring
|
* 注入scheduler到spring
|
||||||
* @param quartzJobFactory
|
* @param quartzJobFactory /
|
||||||
* @return
|
* @return Scheduler
|
||||||
* @throws Exception
|
* @throws Exception /
|
||||||
*/
|
*/
|
||||||
@Bean(name = "scheduler")
|
@Bean(name = "scheduler")
|
||||||
public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception {
|
public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package me.zhengjie.modules.quartz.domain;
|
package me.zhengjie.modules.quartz.domain;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Getter;
|
||||||
import org.hibernate.annotations.UpdateTimestamp;
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
@ -13,10 +13,11 @@ import java.sql.Timestamp;
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2019-01-07
|
* @date 2019-01-07
|
||||||
*/
|
*/
|
||||||
@Data
|
@Getter
|
||||||
|
@Setter
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "quartz_job")
|
@Table(name = "quartz_job")
|
||||||
public class QuartzJob implements Serializable {
|
public class QuartzJob implements Serializable {
|
||||||
|
|
||||||
public static final String JOB_KEY = "JOB_KEY";
|
public static final String JOB_KEY = "JOB_KEY";
|
||||||
|
|
||||||
|
|
@ -25,58 +26,41 @@ public class QuartzJob implements Serializable {
|
||||||
@NotNull(groups = {Update.class})
|
@NotNull(groups = {Update.class})
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/**
|
// 定时器名称
|
||||||
* 定时器名称
|
|
||||||
*/
|
|
||||||
@Column(name = "job_name")
|
@Column(name = "job_name")
|
||||||
private String jobName;
|
private String jobName;
|
||||||
|
|
||||||
/**
|
// Bean名称
|
||||||
* Bean名称
|
|
||||||
*/
|
|
||||||
@Column(name = "bean_name")
|
@Column(name = "bean_name")
|
||||||
@NotBlank
|
@NotBlank
|
||||||
private String beanName;
|
private String beanName;
|
||||||
|
|
||||||
/**
|
// 方法名称
|
||||||
* 方法名称
|
|
||||||
*/
|
|
||||||
@Column(name = "method_name")
|
@Column(name = "method_name")
|
||||||
@NotBlank
|
@NotBlank
|
||||||
private String methodName;
|
private String methodName;
|
||||||
|
|
||||||
/**
|
// 参数
|
||||||
* 参数
|
|
||||||
*/
|
|
||||||
@Column(name = "params")
|
@Column(name = "params")
|
||||||
private String params;
|
private String params;
|
||||||
|
|
||||||
/**
|
// cron表达式
|
||||||
* cron表达式
|
|
||||||
*/
|
|
||||||
@Column(name = "cron_expression")
|
@Column(name = "cron_expression")
|
||||||
@NotBlank
|
@NotBlank
|
||||||
private String cronExpression;
|
private String cronExpression;
|
||||||
|
|
||||||
/**
|
// 状态
|
||||||
* 状态
|
|
||||||
*/
|
|
||||||
@Column(name = "is_pause")
|
@Column(name = "is_pause")
|
||||||
private Boolean isPause = false;
|
private Boolean isPause = false;
|
||||||
|
|
||||||
/**
|
// 备注
|
||||||
* 备注
|
|
||||||
*/
|
|
||||||
@Column(name = "remark")
|
@Column(name = "remark")
|
||||||
@NotBlank
|
@NotBlank
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
/**
|
@Column(name = "create_time")
|
||||||
* 创建日期
|
@CreationTimestamp
|
||||||
*/
|
private Timestamp createTime;
|
||||||
@UpdateTimestamp
|
|
||||||
@Column(name = "update_time")
|
|
||||||
private Timestamp updateTime;
|
|
||||||
|
|
||||||
public interface Update{}
|
public @interface Update {}
|
||||||
}
|
}
|
||||||
|
|
@ -20,56 +20,38 @@ public class QuartzLog implements Serializable {
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
/**
|
// 任务名称
|
||||||
* 任务名称
|
|
||||||
*/
|
|
||||||
@Column(name = "job_name")
|
@Column(name = "job_name")
|
||||||
private String jobName;
|
private String jobName;
|
||||||
|
|
||||||
/**
|
// Bean名称
|
||||||
* Bean名称
|
|
||||||
*/
|
|
||||||
@Column(name = "baen_name")
|
@Column(name = "baen_name")
|
||||||
private String beanName;
|
private String beanName;
|
||||||
|
|
||||||
/**
|
// 方法名称
|
||||||
* 方法名称
|
|
||||||
*/
|
|
||||||
@Column(name = "method_name")
|
@Column(name = "method_name")
|
||||||
private String methodName;
|
private String methodName;
|
||||||
|
|
||||||
/**
|
// 参数
|
||||||
* 参数
|
|
||||||
*/
|
|
||||||
@Column(name = "params")
|
@Column(name = "params")
|
||||||
private String params;
|
private String params;
|
||||||
|
|
||||||
/**
|
// cron表达式
|
||||||
* cron表达式
|
|
||||||
*/
|
|
||||||
@Column(name = "cron_expression")
|
@Column(name = "cron_expression")
|
||||||
private String cronExpression;
|
private String cronExpression;
|
||||||
|
|
||||||
/**
|
// 状态
|
||||||
* 状态
|
|
||||||
*/
|
|
||||||
@Column(name = "is_success")
|
@Column(name = "is_success")
|
||||||
private Boolean isSuccess;
|
private Boolean isSuccess;
|
||||||
|
|
||||||
/**
|
// 异常详细
|
||||||
* 异常详细
|
|
||||||
*/
|
|
||||||
@Column(name = "exception_detail",columnDefinition = "text")
|
@Column(name = "exception_detail",columnDefinition = "text")
|
||||||
private String exceptionDetail;
|
private String exceptionDetail;
|
||||||
|
|
||||||
/**
|
// 耗时(毫秒)
|
||||||
* 耗时(毫秒)
|
|
||||||
*/
|
|
||||||
private Long time;
|
private Long time;
|
||||||
|
|
||||||
/**
|
// 创建日期
|
||||||
* 创建日期
|
|
||||||
*/
|
|
||||||
@CreationTimestamp
|
@CreationTimestamp
|
||||||
@Column(name = "create_time")
|
@Column(name = "create_time")
|
||||||
private Timestamp createTime;
|
private Timestamp createTime;
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,11 @@ import java.util.List;
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2019-01-07
|
* @date 2019-01-07
|
||||||
*/
|
*/
|
||||||
public interface QuartzJobRepository extends JpaRepository<QuartzJob,Long>, JpaSpecificationExecutor {
|
public interface QuartzJobRepository extends JpaRepository<QuartzJob,Long>, JpaSpecificationExecutor<QuartzJob> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询启用的任务
|
* 查询启用的任务
|
||||||
* @return
|
* @return List
|
||||||
*/
|
*/
|
||||||
List<QuartzJob> findByIsPauseIsFalse();
|
List<QuartzJob> findByIsPauseIsFalse();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,6 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2019-01-07
|
* @date 2019-01-07
|
||||||
*/
|
*/
|
||||||
public interface QuartzLogRepository extends JpaRepository<QuartzLog,Long>, JpaSpecificationExecutor {
|
public interface QuartzLogRepository extends JpaRepository<QuartzLog,Long>, JpaSpecificationExecutor<QuartzLog> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
package me.zhengjie.modules.quartz.rest;
|
package me.zhengjie.modules.quartz.rest;
|
||||||
|
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.zhengjie.aop.log.Log;
|
import me.zhengjie.aop.log.Log;
|
||||||
import me.zhengjie.exception.BadRequestException;
|
import me.zhengjie.exception.BadRequestException;
|
||||||
import me.zhengjie.modules.quartz.domain.QuartzJob;
|
import me.zhengjie.modules.quartz.domain.QuartzJob;
|
||||||
import me.zhengjie.modules.quartz.service.QuartzJobService;
|
import me.zhengjie.modules.quartz.service.QuartzJobService;
|
||||||
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria;
|
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
@ -14,70 +15,100 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2019-01-07
|
* @date 2019-01-07
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api")
|
@Api(tags = "系统:定时任务管理")
|
||||||
|
@RequestMapping("/api/jobs")
|
||||||
public class QuartzJobController {
|
public class QuartzJobController {
|
||||||
|
|
||||||
private static final String ENTITY_NAME = "quartzJob";
|
private static final String ENTITY_NAME = "quartzJob";
|
||||||
|
|
||||||
@Autowired
|
private final QuartzJobService quartzJobService;
|
||||||
private QuartzJobService quartzJobService;
|
|
||||||
|
|
||||||
@Log("查询定时任务")
|
public QuartzJobController(QuartzJobService quartzJobService) {
|
||||||
@GetMapping(value = "/jobs")
|
this.quartzJobService = quartzJobService;
|
||||||
@PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_SELECT')")
|
|
||||||
public ResponseEntity getJobs(JobQueryCriteria criteria, Pageable pageable){
|
|
||||||
return new ResponseEntity(quartzJobService.queryAll(criteria,pageable), HttpStatus.OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/jobLogs")
|
@Log("查询定时任务")
|
||||||
@PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_SELECT')")
|
@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){
|
public ResponseEntity getJobLogs(JobQueryCriteria criteria, Pageable pageable){
|
||||||
return new ResponseEntity(quartzJobService.queryAllLog(criteria,pageable), HttpStatus.OK);
|
return new ResponseEntity<>(quartzJobService.queryAllLog(criteria,pageable), HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Log("新增定时任务")
|
@Log("新增定时任务")
|
||||||
@PostMapping(value = "/jobs")
|
@ApiOperation("新增定时任务")
|
||||||
@PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_CREATE')")
|
@PostMapping
|
||||||
|
@PreAuthorize("@el.check('timing:add')")
|
||||||
public ResponseEntity create(@Validated @RequestBody QuartzJob resources){
|
public ResponseEntity create(@Validated @RequestBody QuartzJob resources){
|
||||||
if (resources.getId() != null) {
|
if (resources.getId() != null) {
|
||||||
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
|
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
|
||||||
}
|
}
|
||||||
return new ResponseEntity(quartzJobService.create(resources),HttpStatus.CREATED);
|
return new ResponseEntity<>(quartzJobService.create(resources),HttpStatus.CREATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Log("修改定时任务")
|
@Log("修改定时任务")
|
||||||
@PutMapping(value = "/jobs")
|
@ApiOperation("修改定时任务")
|
||||||
@PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_EDIT')")
|
@PutMapping
|
||||||
|
@PreAuthorize("@el.check('timing:edit')")
|
||||||
public ResponseEntity update(@Validated(QuartzJob.Update.class) @RequestBody QuartzJob resources){
|
public ResponseEntity update(@Validated(QuartzJob.Update.class) @RequestBody QuartzJob resources){
|
||||||
quartzJobService.update(resources);
|
quartzJobService.update(resources);
|
||||||
return new ResponseEntity(HttpStatus.NO_CONTENT);
|
return new ResponseEntity(HttpStatus.NO_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Log("更改定时任务状态")
|
@Log("更改定时任务状态")
|
||||||
@PutMapping(value = "/jobs/{id}")
|
@ApiOperation("更改定时任务状态")
|
||||||
@PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_EDIT')")
|
@PutMapping(value = "/{id}")
|
||||||
|
@PreAuthorize("@el.check('timing:edit')")
|
||||||
public ResponseEntity updateIsPause(@PathVariable Long id){
|
public ResponseEntity updateIsPause(@PathVariable Long id){
|
||||||
quartzJobService.updateIsPause(quartzJobService.findById(id));
|
quartzJobService.updateIsPause(quartzJobService.findById(id));
|
||||||
return new ResponseEntity(HttpStatus.NO_CONTENT);
|
return new ResponseEntity(HttpStatus.NO_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Log("执行定时任务")
|
@Log("执行定时任务")
|
||||||
@PutMapping(value = "/jobs/exec/{id}")
|
@ApiOperation("执行定时任务")
|
||||||
@PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_EDIT')")
|
@PutMapping(value = "/exec/{id}")
|
||||||
|
@PreAuthorize("@el.check('timing:edit')")
|
||||||
public ResponseEntity execution(@PathVariable Long id){
|
public ResponseEntity execution(@PathVariable Long id){
|
||||||
quartzJobService.execution(quartzJobService.findById(id));
|
quartzJobService.execution(quartzJobService.findById(id));
|
||||||
return new ResponseEntity(HttpStatus.NO_CONTENT);
|
return new ResponseEntity(HttpStatus.NO_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Log("删除定时任务")
|
@Log("删除定时任务")
|
||||||
@DeleteMapping(value = "/jobs/{id}")
|
@ApiOperation("删除定时任务")
|
||||||
@PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_DELETE')")
|
@DeleteMapping(value = "/{id}")
|
||||||
|
@PreAuthorize("@el.check('timing:del')")
|
||||||
public ResponseEntity delete(@PathVariable Long id){
|
public ResponseEntity delete(@PathVariable Long id){
|
||||||
quartzJobService.delete(quartzJobService.findById(id));
|
quartzJobService.delete(quartzJobService.findById(id));
|
||||||
return new ResponseEntity(HttpStatus.OK);
|
return new ResponseEntity(HttpStatus.OK);
|
||||||
|
|
|
||||||
|
|
@ -3,76 +3,47 @@ package me.zhengjie.modules.quartz.service;
|
||||||
import me.zhengjie.modules.quartz.domain.QuartzJob;
|
import me.zhengjie.modules.quartz.domain.QuartzJob;
|
||||||
import me.zhengjie.modules.quartz.domain.QuartzLog;
|
import me.zhengjie.modules.quartz.domain.QuartzLog;
|
||||||
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria;
|
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria;
|
||||||
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.data.domain.Pageable;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2019-01-07
|
* @date 2019-01-07
|
||||||
*/
|
*/
|
||||||
@CacheConfig(cacheNames = "quartzJob")
|
|
||||||
public interface QuartzJobService {
|
public interface QuartzJobService {
|
||||||
|
|
||||||
/**
|
|
||||||
* queryAll quartzJob
|
|
||||||
* @param criteria
|
|
||||||
* @param pageable
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Cacheable
|
|
||||||
Object queryAll(JobQueryCriteria criteria, Pageable pageable);
|
Object queryAll(JobQueryCriteria criteria, Pageable pageable);
|
||||||
|
|
||||||
/**
|
List<QuartzJob> queryAll(JobQueryCriteria criteria);
|
||||||
* queryAll quartzLog
|
|
||||||
* @param criteria
|
|
||||||
* @param pageable
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Object queryAllLog(JobQueryCriteria criteria, Pageable pageable);
|
Object queryAllLog(JobQueryCriteria criteria, Pageable pageable);
|
||||||
|
|
||||||
/**
|
List<QuartzLog> queryAllLog(JobQueryCriteria criteria);
|
||||||
* create
|
|
||||||
* @param resources
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@CacheEvict(allEntries = true)
|
|
||||||
QuartzJob create(QuartzJob resources);
|
QuartzJob create(QuartzJob resources);
|
||||||
|
|
||||||
/**
|
|
||||||
* update
|
|
||||||
* @param resources
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@CacheEvict(allEntries = true)
|
|
||||||
void update(QuartzJob resources);
|
void update(QuartzJob resources);
|
||||||
|
|
||||||
/**
|
|
||||||
* del
|
|
||||||
* @param quartzJob
|
|
||||||
*/
|
|
||||||
@CacheEvict(allEntries = true)
|
|
||||||
void delete(QuartzJob quartzJob);
|
void delete(QuartzJob quartzJob);
|
||||||
|
|
||||||
/**
|
|
||||||
* findById
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Cacheable(key = "#p0")
|
|
||||||
QuartzJob findById(Long id);
|
QuartzJob findById(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更改定时任务状态
|
* 更改定时任务状态
|
||||||
* @param quartzJob
|
* @param quartzJob /
|
||||||
*/
|
*/
|
||||||
@CacheEvict(allEntries = true)
|
|
||||||
void updateIsPause(QuartzJob quartzJob);
|
void updateIsPause(QuartzJob quartzJob);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 立即执行定时任务
|
* 立即执行定时任务
|
||||||
* @param quartzJob
|
* @param quartzJob /
|
||||||
*/
|
*/
|
||||||
void execution(QuartzJob quartzJob);
|
void execution(QuartzJob quartzJob);
|
||||||
|
|
||||||
|
void download(List<QuartzJob> queryAll, HttpServletResponse response) throws IOException;
|
||||||
|
|
||||||
|
void downloadLog(List<QuartzLog> queryAllLog, HttpServletResponse response) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ package me.zhengjie.modules.quartz.service.dto;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import me.zhengjie.annotation.Query;
|
import me.zhengjie.annotation.Query;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2019-6-4 10:33:02
|
* @date 2019-6-4 10:33:02
|
||||||
|
|
@ -15,4 +17,10 @@ public class JobQueryCriteria {
|
||||||
|
|
||||||
@Query
|
@Query
|
||||||
private Boolean isSuccess;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,40 +2,55 @@ package me.zhengjie.modules.quartz.service.impl;
|
||||||
|
|
||||||
import me.zhengjie.exception.BadRequestException;
|
import me.zhengjie.exception.BadRequestException;
|
||||||
import me.zhengjie.modules.quartz.domain.QuartzJob;
|
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.QuartzJobRepository;
|
||||||
import me.zhengjie.modules.quartz.repository.QuartzLogRepository;
|
import me.zhengjie.modules.quartz.repository.QuartzLogRepository;
|
||||||
import me.zhengjie.modules.quartz.service.QuartzJobService;
|
import me.zhengjie.modules.quartz.service.QuartzJobService;
|
||||||
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria;
|
import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria;
|
||||||
import me.zhengjie.modules.quartz.utils.QuartzManage;
|
import me.zhengjie.modules.quartz.utils.QuartzManage;
|
||||||
|
import me.zhengjie.utils.FileUtil;
|
||||||
import me.zhengjie.utils.PageUtil;
|
import me.zhengjie.utils.PageUtil;
|
||||||
import me.zhengjie.utils.QueryHelp;
|
import me.zhengjie.utils.QueryHelp;
|
||||||
import me.zhengjie.utils.ValidationUtil;
|
import me.zhengjie.utils.ValidationUtil;
|
||||||
import org.quartz.CronExpression;
|
import org.quartz.CronExpression;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.data.domain.Pageable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import java.util.Optional;
|
|
||||||
|
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
|
* @author Zheng Jie
|
||||||
* @date 2019-01-07
|
* @date 2019-01-07
|
||||||
*/
|
*/
|
||||||
@Service(value = "quartzJobService")
|
@Service(value = "quartzJobService")
|
||||||
|
@CacheConfig(cacheNames = "quartzJob")
|
||||||
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
||||||
public class QuartzJobServiceImpl implements QuartzJobService {
|
public class QuartzJobServiceImpl implements QuartzJobService {
|
||||||
|
|
||||||
@Autowired
|
private final QuartzJobRepository quartzJobRepository;
|
||||||
private QuartzJobRepository quartzJobRepository;
|
|
||||||
|
|
||||||
@Autowired
|
private final QuartzLogRepository quartzLogRepository;
|
||||||
private QuartzLogRepository quartzLogRepository;
|
|
||||||
|
|
||||||
@Autowired
|
private final QuartzManage quartzManage;
|
||||||
private QuartzManage quartzManage;
|
|
||||||
|
public QuartzJobServiceImpl(QuartzJobRepository quartzJobRepository, QuartzLogRepository quartzLogRepository, QuartzManage quartzManage) {
|
||||||
|
this.quartzJobRepository = quartzJobRepository;
|
||||||
|
this.quartzLogRepository = quartzLogRepository;
|
||||||
|
this.quartzManage = quartzManage;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Cacheable
|
||||||
public Object queryAll(JobQueryCriteria criteria, Pageable pageable){
|
public Object queryAll(JobQueryCriteria criteria, Pageable pageable){
|
||||||
return PageUtil.toPage(quartzJobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable));
|
return PageUtil.toPage(quartzJobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable));
|
||||||
}
|
}
|
||||||
|
|
@ -46,13 +61,25 @@ public class QuartzJobServiceImpl implements QuartzJobService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QuartzJob findById(Long id) {
|
public List<QuartzJob> queryAll(JobQueryCriteria criteria) {
|
||||||
Optional<QuartzJob> quartzJob = quartzJobRepository.findById(id);
|
return quartzJobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
|
||||||
ValidationUtil.isNull(quartzJob,"QuartzJob","id",id);
|
|
||||||
return quartzJob.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public QuartzJob create(QuartzJob resources) {
|
public QuartzJob create(QuartzJob resources) {
|
||||||
if (!CronExpression.isValidExpression(resources.getCronExpression())){
|
if (!CronExpression.isValidExpression(resources.getCronExpression())){
|
||||||
|
|
@ -64,6 +91,7 @@ public class QuartzJobServiceImpl implements QuartzJobService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@CacheEvict(allEntries = true)
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void update(QuartzJob resources) {
|
public void update(QuartzJob resources) {
|
||||||
if(resources.getId().equals(1L)){
|
if(resources.getId().equals(1L)){
|
||||||
|
|
@ -77,6 +105,7 @@ public class QuartzJobServiceImpl implements QuartzJobService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@CacheEvict(allEntries = true)
|
||||||
public void updateIsPause(QuartzJob quartzJob) {
|
public void updateIsPause(QuartzJob quartzJob) {
|
||||||
if(quartzJob.getId().equals(1L)){
|
if(quartzJob.getId().equals(1L)){
|
||||||
throw new BadRequestException("该任务不可操作");
|
throw new BadRequestException("该任务不可操作");
|
||||||
|
|
@ -100,6 +129,7 @@ public class QuartzJobServiceImpl implements QuartzJobService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@CacheEvict(allEntries = true)
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void delete(QuartzJob quartzJob) {
|
public void delete(QuartzJob quartzJob) {
|
||||||
if(quartzJob.getId().equals(1L)){
|
if(quartzJob.getId().equals(1L)){
|
||||||
|
|
@ -108,4 +138,41 @@ public class QuartzJobServiceImpl implements QuartzJobService {
|
||||||
quartzManage.deleteJob(quartzJob);
|
quartzManage.deleteJob(quartzJob);
|
||||||
quartzJobRepository.delete(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package me.zhengjie.modules.quartz.task;
|
package me.zhengjie.modules.quartz.task;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.zhengjie.exception.BadRequestException;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package me.zhengjie.modules.quartz.task;
|
package me.zhengjie.modules.quartz.task;
|
||||||
|
|
||||||
import me.zhengjie.modules.monitor.service.VisitsService;
|
import me.zhengjie.modules.monitor.service.VisitsService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -11,8 +10,11 @@ import org.springframework.stereotype.Component;
|
||||||
@Component
|
@Component
|
||||||
public class VisitsTask {
|
public class VisitsTask {
|
||||||
|
|
||||||
@Autowired
|
private final VisitsService visitsService;
|
||||||
private VisitsService visitsService;
|
|
||||||
|
public VisitsTask(VisitsService visitsService) {
|
||||||
|
this.visitsService = visitsService;
|
||||||
|
}
|
||||||
|
|
||||||
public void run(){
|
public void run(){
|
||||||
visitsService.save();
|
visitsService.save();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package me.zhengjie.modules.quartz.utils;
|
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.QuartzJob;
|
||||||
import me.zhengjie.modules.quartz.domain.QuartzLog;
|
import me.zhengjie.modules.quartz.domain.QuartzLog;
|
||||||
import me.zhengjie.modules.quartz.repository.QuartzLogRepository;
|
import me.zhengjie.modules.quartz.repository.QuartzLogRepository;
|
||||||
|
|
@ -11,13 +13,11 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 参考人人开源,https://gitee.com/renrenio/renren-security
|
* 参考人人开源,https://gitee.com/renrenio/renren-security
|
||||||
* @author
|
* @author /
|
||||||
* @date 2019-01-07
|
* @date 2019-01-07
|
||||||
*/
|
*/
|
||||||
@Async
|
@Async
|
||||||
|
|
@ -25,16 +25,16 @@ public class ExecutionJob extends QuartzJobBean {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
// 建议自定义线程池实现方式,该处仅供参考
|
// 该处仅供参考
|
||||||
private ExecutorService executorService = Executors.newSingleThreadExecutor();
|
private final static ThreadPoolExecutor executor = ThreadPoolExecutorUtil.getPoll();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
protected void executeInternal(JobExecutionContext context) {
|
protected void executeInternal(JobExecutionContext context) {
|
||||||
QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY);
|
QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY);
|
||||||
// 获取spring bean
|
// 获取spring bean
|
||||||
QuartzLogRepository quartzLogRepository = SpringContextHolder.getBean("quartzLogRepository");
|
QuartzLogRepository quartzLogRepository = SpringContextHolder.getBean(QuartzLogRepository.class);
|
||||||
QuartzJobService quartzJobService = SpringContextHolder.getBean("quartzJobService");
|
QuartzJobService quartzJobService = SpringContextHolder.getBean(QuartzJobService.class);
|
||||||
QuartzManage quartzManage = SpringContextHolder.getBean("quartzManage");
|
|
||||||
|
|
||||||
QuartzLog log = new QuartzLog();
|
QuartzLog log = new QuartzLog();
|
||||||
log.setJobName(quartzJob.getJobName());
|
log.setJobName(quartzJob.getJobName());
|
||||||
|
|
@ -48,7 +48,7 @@ public class ExecutionJob extends QuartzJobBean {
|
||||||
logger.info("任务准备执行,任务名称:{}", quartzJob.getJobName());
|
logger.info("任务准备执行,任务名称:{}", quartzJob.getJobName());
|
||||||
QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),
|
QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),
|
||||||
quartzJob.getParams());
|
quartzJob.getParams());
|
||||||
Future<?> future = executorService.submit(task);
|
Future<?> future = executor.submit(task);
|
||||||
future.get();
|
future.get();
|
||||||
long times = System.currentTimeMillis() - startTime;
|
long times = System.currentTimeMillis() - startTime;
|
||||||
log.setTime(times);
|
log.setTime(times);
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,7 @@ public class QuartzManage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新job cron表达式
|
* 更新job cron表达式
|
||||||
* @param quartzJob
|
* @param quartzJob /
|
||||||
* @throws SchedulerException
|
|
||||||
*/
|
*/
|
||||||
public void updateJobCron(QuartzJob quartzJob){
|
public void updateJobCron(QuartzJob quartzJob){
|
||||||
try {
|
try {
|
||||||
|
|
@ -88,8 +87,7 @@ public class QuartzManage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除一个job
|
* 删除一个job
|
||||||
* @param quartzJob
|
* @param quartzJob /
|
||||||
* @throws SchedulerException
|
|
||||||
*/
|
*/
|
||||||
public void deleteJob(QuartzJob quartzJob){
|
public void deleteJob(QuartzJob quartzJob){
|
||||||
try {
|
try {
|
||||||
|
|
@ -104,8 +102,7 @@ public class QuartzManage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 恢复一个job
|
* 恢复一个job
|
||||||
* @param quartzJob
|
* @param quartzJob /
|
||||||
* @throws SchedulerException
|
|
||||||
*/
|
*/
|
||||||
public void resumeJob(QuartzJob quartzJob){
|
public void resumeJob(QuartzJob quartzJob){
|
||||||
try {
|
try {
|
||||||
|
|
@ -124,8 +121,7 @@ public class QuartzManage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 立即执行job
|
* 立即执行job
|
||||||
* @param quartzJob
|
* @param quartzJob /
|
||||||
* @throws SchedulerException
|
|
||||||
*/
|
*/
|
||||||
public void runAJobNow(QuartzJob quartzJob){
|
public void runAJobNow(QuartzJob quartzJob){
|
||||||
try {
|
try {
|
||||||
|
|
@ -146,8 +142,7 @@ public class QuartzManage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 暂停一个job
|
* 暂停一个job
|
||||||
* @param quartzJob
|
* @param quartzJob /
|
||||||
* @throws SchedulerException
|
|
||||||
*/
|
*/
|
||||||
public void pauseJob(QuartzJob quartzJob){
|
public void pauseJob(QuartzJob quartzJob){
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package me.zhengjie.modules.quartz.utils;
|
package me.zhengjie.modules.quartz.utils;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.zhengjie.exception.BadRequestException;
|
|
||||||
import me.zhengjie.utils.SpringContextHolder;
|
import me.zhengjie.utils.SpringContextHolder;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
@ -10,7 +9,7 @@ import java.util.concurrent.Callable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行定时任务
|
* 执行定时任务
|
||||||
* @author
|
* @author /
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class QuartzRunnable implements Callable {
|
public class QuartzRunnable implements Callable {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,17 @@
|
||||||
package me.zhengjie.modules.security.config;
|
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.JwtAuthenticationEntryPoint;
|
||||||
import me.zhengjie.modules.security.security.JwtAuthorizationTokenFilter;
|
import me.zhengjie.modules.security.security.JwtAuthorizationTokenFilter;
|
||||||
import me.zhengjie.modules.security.service.JwtUserDetailsService;
|
import me.zhengjie.modules.security.service.JwtUserDetailsService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
|
|
@ -19,29 +23,37 @@ import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
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
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
@Autowired
|
private final JwtAuthenticationEntryPoint unauthorizedHandler;
|
||||||
private JwtAuthenticationEntryPoint unauthorizedHandler;
|
|
||||||
|
|
||||||
@Autowired
|
private final JwtUserDetailsService jwtUserDetailsService;
|
||||||
private JwtUserDetailsService jwtUserDetailsService;
|
|
||||||
|
|
||||||
/**
|
private final ApplicationContext applicationContext;
|
||||||
* 自定义基于JWT的安全过滤器
|
|
||||||
*/
|
// 自定义基于JWT的安全过滤器
|
||||||
@Autowired
|
private final JwtAuthorizationTokenFilter authenticationTokenFilter;
|
||||||
JwtAuthorizationTokenFilter authenticationTokenFilter;
|
|
||||||
|
|
||||||
@Value("${jwt.header}")
|
@Value("${jwt.header}")
|
||||||
private String tokenHeader;
|
private String tokenHeader;
|
||||||
|
|
||||||
@Value("${jwt.auth.path}")
|
public SecurityConfig(JwtAuthenticationEntryPoint unauthorizedHandler, JwtUserDetailsService jwtUserDetailsService, JwtAuthorizationTokenFilter authenticationTokenFilter, ApplicationContext applicationContext) {
|
||||||
private String loginPath;
|
this.unauthorizedHandler = unauthorizedHandler;
|
||||||
|
this.jwtUserDetailsService = jwtUserDetailsService;
|
||||||
|
this.authenticationTokenFilter = authenticationTokenFilter;
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||||
|
|
@ -69,18 +81,26 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity httpSecurity) throws Exception {
|
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().contains("anonymous")) {
|
||||||
|
anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
|
||||||
|
} else if (null != anonymousAccess && null == preAuthorize) {
|
||||||
|
anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
|
||||||
|
}
|
||||||
|
}
|
||||||
httpSecurity
|
httpSecurity
|
||||||
|
|
||||||
// 禁用 CSRF
|
// 禁用 CSRF
|
||||||
.csrf().disable()
|
.csrf().disable()
|
||||||
|
|
||||||
// 授权异常
|
// 授权异常
|
||||||
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
|
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
|
||||||
|
|
||||||
// 不创建会话
|
// 不创建会话
|
||||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
|
||||||
|
|
||||||
// 过滤请求
|
// 过滤请求
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
.antMatchers(
|
.antMatchers(
|
||||||
|
|
@ -90,35 +110,24 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
"/**/*.css",
|
"/**/*.css",
|
||||||
"/**/*.js"
|
"/**/*.js"
|
||||||
).anonymous()
|
).anonymous()
|
||||||
|
|
||||||
.antMatchers( HttpMethod.POST,"/auth/"+loginPath).anonymous()
|
|
||||||
.antMatchers("/auth/vCode").anonymous()
|
|
||||||
// 支付宝回调
|
|
||||||
.antMatchers("/api/aliPay/return").anonymous()
|
|
||||||
.antMatchers("/api/aliPay/notify").anonymous()
|
|
||||||
|
|
||||||
// swagger start
|
// swagger start
|
||||||
.antMatchers("/swagger-ui.html").anonymous()
|
.antMatchers("/swagger-ui.html").permitAll()
|
||||||
.antMatchers("/swagger-resources/**").anonymous()
|
.antMatchers("/swagger-resources/**").permitAll()
|
||||||
.antMatchers("/webjars/**").anonymous()
|
.antMatchers("/webjars/**").permitAll()
|
||||||
.antMatchers("/*/api-docs").anonymous()
|
.antMatchers("/*/api-docs").permitAll()
|
||||||
// swagger end
|
// swagger end
|
||||||
|
|
||||||
// 接口限流测试
|
|
||||||
.antMatchers("/test/**").anonymous()
|
|
||||||
// 文件
|
// 文件
|
||||||
.antMatchers("/avatar/**").anonymous()
|
.antMatchers("/avatar/**").permitAll()
|
||||||
.antMatchers("/file/**").anonymous()
|
.antMatchers("/file/**").permitAll()
|
||||||
|
|
||||||
// 放行OPTIONS请求
|
// 放行OPTIONS请求
|
||||||
.antMatchers(HttpMethod.OPTIONS, "/**").anonymous()
|
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
||||||
|
.antMatchers("/druid/**").permitAll()
|
||||||
.antMatchers("/druid/**").anonymous()
|
// 自定义匿名访问所有url放行 : 允许 匿名和带权限以及登录用户访问
|
||||||
|
.antMatchers(anonymousUrls.toArray(new String[0])).permitAll()
|
||||||
// 所有请求都需要认证
|
// 所有请求都需要认证
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
// 防止iframe 造成跨域
|
// 防止iframe 造成跨域
|
||||||
.and().headers().frameOptions().disable();
|
.and().headers().frameOptions().disable();
|
||||||
|
|
||||||
httpSecurity
|
httpSecurity
|
||||||
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,32 @@
|
||||||
package me.zhengjie.modules.security.rest;
|
package me.zhengjie.modules.security.rest;
|
||||||
|
|
||||||
import cn.hutool.core.codec.Base64;
|
|
||||||
import cn.hutool.core.util.IdUtil;
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import com.wf.captcha.ArithmeticCaptcha;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.zhengjie.annotation.AnonymousAccess;
|
||||||
import me.zhengjie.aop.log.Log;
|
import me.zhengjie.aop.log.Log;
|
||||||
import me.zhengjie.exception.BadRequestException;
|
import me.zhengjie.exception.BadRequestException;
|
||||||
import me.zhengjie.modules.monitor.service.RedisService;
|
import me.zhengjie.modules.monitor.service.RedisService;
|
||||||
import me.zhengjie.modules.security.security.AuthenticationInfo;
|
import me.zhengjie.modules.security.security.AuthInfo;
|
||||||
import me.zhengjie.modules.security.security.AuthorizationUser;
|
import me.zhengjie.modules.security.security.AuthUser;
|
||||||
import me.zhengjie.modules.security.security.ImgResult;
|
import me.zhengjie.modules.security.security.ImgResult;
|
||||||
import me.zhengjie.modules.security.security.JwtUser;
|
import me.zhengjie.modules.security.security.JwtUser;
|
||||||
import me.zhengjie.modules.security.utils.VerifyCodeUtils;
|
import me.zhengjie.modules.security.service.OnlineUserService;
|
||||||
import me.zhengjie.utils.EncryptUtils;
|
import me.zhengjie.utils.EncryptUtils;
|
||||||
import me.zhengjie.modules.security.utils.JwtTokenUtil;
|
import me.zhengjie.modules.security.utils.JwtTokenUtil;
|
||||||
import me.zhengjie.utils.SecurityUtils;
|
import me.zhengjie.utils.SecurityUtils;
|
||||||
import me.zhengjie.utils.StringUtils;
|
import me.zhengjie.utils.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.authentication.AccountExpiredException;
|
import org.springframework.security.authentication.AccountExpiredException;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
|
|
@ -34,30 +35,33 @@ import java.io.IOException;
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("auth")
|
@RequestMapping("/auth")
|
||||||
|
@Api(tags = "系统:系统授权接口")
|
||||||
public class AuthenticationController {
|
public class AuthenticationController {
|
||||||
|
|
||||||
@Value("${jwt.header}")
|
@Value("${jwt.codeKey}")
|
||||||
private String tokenHeader;
|
private String codeKey;
|
||||||
|
|
||||||
@Autowired
|
private final JwtTokenUtil jwtTokenUtil;
|
||||||
private JwtTokenUtil jwtTokenUtil;
|
|
||||||
|
|
||||||
@Autowired
|
private final RedisService redisService;
|
||||||
private RedisService redisService;
|
|
||||||
|
|
||||||
@Autowired
|
private final UserDetailsService userDetailsService;
|
||||||
@Qualifier("jwtUserDetailsService")
|
|
||||||
private UserDetailsService userDetailsService;
|
private final OnlineUserService onlineUserService;
|
||||||
|
|
||||||
|
public AuthenticationController(JwtTokenUtil jwtTokenUtil, RedisService redisService, @Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService, OnlineUserService onlineUserService) {
|
||||||
|
this.jwtTokenUtil = jwtTokenUtil;
|
||||||
|
this.redisService = redisService;
|
||||||
|
this.userDetailsService = userDetailsService;
|
||||||
|
this.onlineUserService = onlineUserService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 登录授权
|
|
||||||
* @param authorizationUser
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Log("用户登录")
|
@Log("用户登录")
|
||||||
@PostMapping(value = "${jwt.auth.path}")
|
@ApiOperation("登录授权")
|
||||||
public ResponseEntity login(@Validated @RequestBody AuthorizationUser authorizationUser){
|
@AnonymousAccess
|
||||||
|
@PostMapping(value = "/login")
|
||||||
|
public ResponseEntity login(@Validated @RequestBody AuthUser authorizationUser, HttpServletRequest request){
|
||||||
|
|
||||||
// 查询验证码
|
// 查询验证码
|
||||||
String code = redisService.getCodeVal(authorizationUser.getUuid());
|
String code = redisService.getCodeVal(authorizationUser.getUuid());
|
||||||
|
|
@ -78,45 +82,41 @@ public class AuthenticationController {
|
||||||
if(!jwtUser.isEnabled()){
|
if(!jwtUser.isEnabled()){
|
||||||
throw new AccountExpiredException("账号已停用,请联系管理员");
|
throw new AccountExpiredException("账号已停用,请联系管理员");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成令牌
|
// 生成令牌
|
||||||
final String token = jwtTokenUtil.generateToken(jwtUser);
|
final String token = jwtTokenUtil.generateToken(jwtUser);
|
||||||
|
// 保存在线信息
|
||||||
|
onlineUserService.save(jwtUser, token, request);
|
||||||
// 返回 token
|
// 返回 token
|
||||||
return ResponseEntity.ok(new AuthenticationInfo(token,jwtUser));
|
return ResponseEntity.ok(new AuthInfo(token,jwtUser));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@ApiOperation("获取用户信息")
|
||||||
* 获取用户信息
|
@GetMapping(value = "/info")
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@GetMapping(value = "${jwt.auth.account}")
|
|
||||||
public ResponseEntity getUserInfo(){
|
public ResponseEntity getUserInfo(){
|
||||||
JwtUser jwtUser = (JwtUser)userDetailsService.loadUserByUsername(SecurityUtils.getUsername());
|
JwtUser jwtUser = (JwtUser)userDetailsService.loadUserByUsername(SecurityUtils.getUsername());
|
||||||
return ResponseEntity.ok(jwtUser);
|
return ResponseEntity.ok(jwtUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@ApiOperation("获取验证码")
|
||||||
* 获取验证码
|
@AnonymousAccess
|
||||||
*/
|
@GetMapping(value = "/code")
|
||||||
@GetMapping(value = "vCode")
|
public ImgResult getCode(){
|
||||||
public ImgResult getCode(HttpServletResponse response) throws IOException {
|
// 算术类型 https://gitee.com/whvse/EasyCaptcha
|
||||||
|
ArithmeticCaptcha captcha = new ArithmeticCaptcha(111, 36);
|
||||||
|
// 几位数运算,默认是两位
|
||||||
|
captcha.setLen(2);
|
||||||
|
// 获取运算的结果:5
|
||||||
|
String result = captcha.text();
|
||||||
|
String uuid = codeKey + IdUtil.simpleUUID();
|
||||||
|
redisService.saveCode(uuid,result);
|
||||||
|
return new ImgResult(captcha.toBase64(),uuid);
|
||||||
|
}
|
||||||
|
|
||||||
//生成随机字串
|
@ApiOperation("退出登录")
|
||||||
String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
|
@AnonymousAccess
|
||||||
String uuid = IdUtil.simpleUUID();
|
@DeleteMapping(value = "/logout")
|
||||||
redisService.saveCode(uuid,verifyCode);
|
public ResponseEntity logout(HttpServletRequest request){
|
||||||
// 生成图片
|
onlineUserService.logout(jwtTokenUtil.getToken(request));
|
||||||
int w = 111, h = 36;
|
return new ResponseEntity(HttpStatus.OK);
|
||||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
||||||
VerifyCodeUtils.outputImage(w, h, stream, verifyCode);
|
|
||||||
try {
|
|
||||||
return new ImgResult(Base64.encode(stream.toByteArray()),uuid);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
package me.zhengjie.modules.security.security;
|
package me.zhengjie.modules.security.security;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Zheng Jie
|
* @author Zheng Jie
|
||||||
* @date 2018-11-23
|
* @date 2018-11-23
|
||||||
* 返回token
|
* 返回token
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class AuthenticationInfo implements Serializable {
|
public class AuthInfo implements Serializable {
|
||||||
|
|
||||||
private final String token;
|
private final String token;
|
||||||
|
|
||||||
private final JwtUser user;
|
private final JwtUser user;
|
||||||
}
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ import javax.validation.constraints.NotBlank;
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class AuthorizationUser {
|
public class AuthUser {
|
||||||
|
|
||||||
@NotBlank
|
@NotBlank
|
||||||
private String username;
|
private String username;
|
||||||
|
|
@ -18,9 +18,7 @@ public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Se
|
||||||
public void commence(HttpServletRequest request,
|
public void commence(HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
AuthenticationException authException) throws IOException {
|
AuthenticationException authException) throws IOException {
|
||||||
/**
|
// 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
|
||||||
* 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
|
|
||||||
*/
|
|
||||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
|
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,12 @@ package me.zhengjie.modules.security.security;
|
||||||
import io.jsonwebtoken.ExpiredJwtException;
|
import io.jsonwebtoken.ExpiredJwtException;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import me.zhengjie.modules.security.utils.JwtTokenUtil;
|
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.Qualifier;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
@ -22,38 +23,33 @@ import java.io.IOException;
|
||||||
@Component
|
@Component
|
||||||
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
|
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
|
||||||
|
@Value("${jwt.online}")
|
||||||
|
private String onlineKey;
|
||||||
|
|
||||||
private final UserDetailsService userDetailsService;
|
private final UserDetailsService userDetailsService;
|
||||||
private final JwtTokenUtil jwtTokenUtil;
|
private final JwtTokenUtil jwtTokenUtil;
|
||||||
private final String tokenHeader;
|
private final RedisTemplate redisTemplate;
|
||||||
|
|
||||||
public JwtAuthorizationTokenFilter(@Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, @Value("${jwt.header}") String tokenHeader) {
|
public JwtAuthorizationTokenFilter(@Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, RedisTemplate redisTemplate) {
|
||||||
this.userDetailsService = userDetailsService;
|
this.userDetailsService = userDetailsService;
|
||||||
this.jwtTokenUtil = jwtTokenUtil;
|
this.jwtTokenUtil = jwtTokenUtil;
|
||||||
this.tokenHeader = tokenHeader;
|
this.redisTemplate = redisTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
|
||||||
|
String authToken = jwtTokenUtil.getToken(request);
|
||||||
final String requestHeader = request.getHeader(this.tokenHeader);
|
OnlineUser onlineUser = null;
|
||||||
|
try {
|
||||||
String username = null;
|
onlineUser = (OnlineUser)redisTemplate.opsForValue().get(onlineKey + authToken);
|
||||||
String authToken = null;
|
} catch (ExpiredJwtException e) {
|
||||||
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
|
log.error(e.getMessage());
|
||||||
authToken = requestHeader.substring(7);
|
|
||||||
try {
|
|
||||||
username = jwtTokenUtil.getUsernameFromToken(authToken);
|
|
||||||
} catch (ExpiredJwtException e) {
|
|
||||||
log.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (onlineUser != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
|
||||||
|
|
||||||
// It is not compelling necessary to load the use details from the database. You could also store the information
|
// 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 ;)
|
// in the token and read it from it. It's up to you ;)
|
||||||
JwtUser userDetails = (JwtUser)this.userDetailsService.loadUserByUsername(username);
|
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
|
// 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 ;)
|
// the database compellingly. Again it's up to you ;)
|
||||||
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
|
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
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 Date loginTime;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
package me.zhengjie.modules.security.service;
|
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.domain.Role;
|
||||||
import me.zhengjie.modules.system.repository.RoleRepository;
|
import me.zhengjie.modules.system.repository.RoleRepository;
|
||||||
import me.zhengjie.modules.system.service.dto.UserDTO;
|
import me.zhengjie.modules.system.service.dto.UserDTO;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import me.zhengjie.utils.StringUtils;
|
||||||
import org.springframework.cache.annotation.CacheConfig;
|
import org.springframework.cache.annotation.CacheConfig;
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
@ -17,13 +19,16 @@ import java.util.stream.Collectors;
|
||||||
@CacheConfig(cacheNames = "role")
|
@CacheConfig(cacheNames = "role")
|
||||||
public class JwtPermissionService {
|
public class JwtPermissionService {
|
||||||
|
|
||||||
@Autowired
|
private final RoleRepository roleRepository;
|
||||||
private RoleRepository roleRepository;
|
|
||||||
|
public JwtPermissionService(RoleRepository roleRepository) {
|
||||||
|
this.roleRepository = roleRepository;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* key的名称如有修改,请同步修改 UserServiceImpl 中的 update 方法
|
* key的名称如有修改,请同步修改 UserServiceImpl 中的 update 方法
|
||||||
* @param user
|
* @param user 用户信息
|
||||||
* @return
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
@Cacheable(key = "'loadPermissionByUser:' + #p0.username")
|
@Cacheable(key = "'loadPermissionByUser:' + #p0.username")
|
||||||
public Collection<GrantedAuthority> mapToGrantedAuthorities(UserDTO user) {
|
public Collection<GrantedAuthority> mapToGrantedAuthorities(UserDTO user) {
|
||||||
|
|
@ -31,9 +36,13 @@ public class JwtPermissionService {
|
||||||
System.out.println("--------------------loadPermissionByUser:" + user.getUsername() + "---------------------");
|
System.out.println("--------------------loadPermissionByUser:" + user.getUsername() + "---------------------");
|
||||||
|
|
||||||
Set<Role> roles = roleRepository.findByUsers_Id(user.getId());
|
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());
|
||||||
return roles.stream().flatMap(role -> role.getPermissions().stream())
|
permissions.addAll(
|
||||||
.map(permission -> new SimpleGrantedAuthority(permission.getName()))
|
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());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import me.zhengjie.exception.BadRequestException;
|
||||||
import me.zhengjie.modules.security.security.JwtUser;
|
import me.zhengjie.modules.security.security.JwtUser;
|
||||||
import me.zhengjie.modules.system.service.UserService;
|
import me.zhengjie.modules.system.service.UserService;
|
||||||
import me.zhengjie.modules.system.service.dto.*;
|
import me.zhengjie.modules.system.service.dto.*;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
@ -20,11 +19,14 @@ import java.util.Optional;
|
||||||
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
|
||||||
public class JwtUserDetailsService implements UserDetailsService {
|
public class JwtUserDetailsService implements UserDetailsService {
|
||||||
|
|
||||||
@Autowired
|
private final UserService userService;
|
||||||
private UserService userService;
|
|
||||||
|
|
||||||
@Autowired
|
private final JwtPermissionService permissionService;
|
||||||
private JwtPermissionService permissionService;
|
|
||||||
|
public JwtUserDetailsService(UserService userService, JwtPermissionService permissionService) {
|
||||||
|
this.userService = userService;
|
||||||
|
this.permissionService = permissionService;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserDetails loadUserByUsername(String username){
|
public UserDetails loadUserByUsername(String username){
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
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, 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), new Date());
|
||||||
|
} 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,8 @@ import me.zhengjie.modules.security.security.JwtUser;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -31,15 +33,15 @@ public class JwtTokenUtil implements Serializable {
|
||||||
return getClaimFromToken(token, Claims::getSubject);
|
return getClaimFromToken(token, Claims::getSubject);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getIssuedAtDateFromToken(String token) {
|
private Date getIssuedAtDateFromToken(String token) {
|
||||||
return getClaimFromToken(token, Claims::getIssuedAt);
|
return getClaimFromToken(token, Claims::getIssuedAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getExpirationDateFromToken(String token) {
|
private Date getExpirationDateFromToken(String token) {
|
||||||
return getClaimFromToken(token, Claims::getExpiration);
|
return getClaimFromToken(token, Claims::getExpiration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
|
private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
|
||||||
final Claims claims = getAllClaimsFromToken(token);
|
final Claims claims = getAllClaimsFromToken(token);
|
||||||
return claimsResolver.apply(claims);
|
return claimsResolver.apply(claims);
|
||||||
}
|
}
|
||||||
|
|
@ -103,6 +105,14 @@ public class JwtTokenUtil implements Serializable {
|
||||||
.compact();
|
.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) {
|
public Boolean validateToken(String token, UserDetails userDetails) {
|
||||||
JwtUser user = (JwtUser) userDetails;
|
JwtUser user = (JwtUser) userDetails;
|
||||||
final Date created = getIssuedAtDateFromToken(token);
|
final Date created = getIssuedAtDateFromToken(token);
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue