diff --git a/README.md b/README.md index f8dd8b6a..fceb525f 100644 --- a/README.md +++ b/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 | -| 码云 | https://gitee.com/elunez/eladmin | https://gitee.com/elunez/eladmin-qt | +| github | https://github.com/elunez/eladmin | https://github.com/elunez/eladmin-web | +| 码云 | https://gitee.com/elunez/eladmin | https://gitee.com/elunez/eladmin-web | #### 系统功能 - 用户管理:提供用户的相关配置,新增用户后,默认密码为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 公共模块 - - exception 项目统一异常的处理 - - mapper mapstruct的通用mapper - - redis redis缓存相关配置 - - swagger2 接口文档配置 - - utils 系统通用工具类 + - annotation 为系统自定义注解 + - aspect 自定义注解的切面 + - base 提供了Entity、DTO基类和mapstruct的通用mapper + - config 自定义权限实现、redis配置、swagger配置 + - exception 项目统一异常的处理 + - utils 系统通用工具类 - eladmin-system 系统核心模块(系统启动入口) - - config 配置跨域与静态资源,与数据权限 - - modules 系统相关模块(登录授权、定时任务等) + - config 配置跨域与静态资源,与数据权限 + - thread 线程池相关 + - modules 系统相关模块(登录授权、系统监控、定时任务等) - eladmin-logging 系统日志模块 - eladmin-tools 系统第三方工具模块 - eladmin-generator 系统代码生成模块 @@ -78,6 +80,6 @@ eladmin基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前 #### 项目捐赠 -项目的发展离不开你的支持,请作者喝杯咖啡吧 ☕! [Donate](https://docs.auauz.net/#/jz) +项目的发展离不开你的支持,请作者喝杯咖啡吧!ps:辣条也行 ☕! [Donate](https://docs.auauz.net/#/jz) #### 反馈交流 - QQ交流群:891137268 diff --git a/eladmin-common/pom.xml b/eladmin-common/pom.xml index af94c4df..0bdd114f 100644 --- a/eladmin-common/pom.xml +++ b/eladmin-common/pom.xml @@ -5,11 +5,10 @@ eladmin me.zhengjie - 2.2 + 2.3 4.0.0 eladmin-common 公共模块 - \ No newline at end of file diff --git a/eladmin-common/src/main/java/me/zhengjie/annotation/AnonymousAccess.java b/eladmin-common/src/main/java/me/zhengjie/annotation/AnonymousAccess.java new file mode 100644 index 00000000..46d5ab0c --- /dev/null +++ b/eladmin-common/src/main/java/me/zhengjie/annotation/AnonymousAccess.java @@ -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 { + +} diff --git a/eladmin-common/src/main/java/me/zhengjie/annotation/Query.java b/eladmin-common/src/main/java/me/zhengjie/annotation/Query.java index dc394b82..0a583390 100644 --- a/eladmin-common/src/main/java/me/zhengjie/annotation/Query.java +++ b/eladmin-common/src/main/java/me/zhengjie/annotation/Query.java @@ -13,45 +13,42 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) public @interface Query { - /** Dong ZhaoYang 2017/8/7 基本对象的属性名 */ + // Dong ZhaoYang 2017/8/7 基本对象的属性名 String propName() default ""; - /** Dong ZhaoYang 2017/8/7 查询方式 */ + // Dong ZhaoYang 2017/8/7 查询方式 Type type() default Type.EQUAL; /** * 连接查询的属性名,如User类中的dept - * @return */ String joinName() default ""; /** * 默认左连接 - * @return */ Join join() default Join.LEFT; /** * 多字段模糊搜索,仅支持String类型字段,多个用逗号隔开, 如@Query(blurry = "email,username") - * @return */ String blurry() default ""; enum Type { - /** jie 2019/6/4 相等 */ + // jie 2019/6/4 相等 EQUAL - /** Dong ZhaoYang 2017/8/7 大于等于 */ + // Dong ZhaoYang 2017/8/7 大于等于 , GREATER_THAN - /** Dong ZhaoYang 2017/8/7 小于等于 */ + // Dong ZhaoYang 2017/8/7 小于等于 , LESS_THAN - /** Dong ZhaoYang 2017/8/7 中模糊查询 */ + // Dong ZhaoYang 2017/8/7 中模糊查询 , INNER_LIKE - /** Dong ZhaoYang 2017/8/7 左模糊查询 */ + // Dong ZhaoYang 2017/8/7 左模糊查询 , LEFT_LIKE - /** Dong ZhaoYang 2017/8/7 右模糊查询 */ + // Dong ZhaoYang 2017/8/7 右模糊查询 , RIGHT_LIKE - /** Dong ZhaoYang 2017/8/7 小于 */ + // Dong ZhaoYang 2017/8/7 小于 , LESS_THAN_NQ - //** jie 2019/6/4 包含 */ + // jie 2019/6/4 包含 , IN } diff --git a/eladmin-common/src/main/java/me/zhengjie/aspect/LimitAspect.java b/eladmin-common/src/main/java/me/zhengjie/aspect/LimitAspect.java index 555774c7..b8b6cf9f 100644 --- a/eladmin-common/src/main/java/me/zhengjie/aspect/LimitAspect.java +++ b/eladmin-common/src/main/java/me/zhengjie/aspect/LimitAspect.java @@ -12,7 +12,6 @@ import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.RedisScript; @@ -23,10 +22,13 @@ import java.lang.reflect.Method; @Aspect @Component public class LimitAspect { - @Autowired - private RedisTemplate redisTemplate; + + private final RedisTemplate redisTemplate; private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class); + public LimitAspect(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } @Pointcut("@annotation(me.zhengjie.annotation.Limit)") public void pointcut() { @@ -41,20 +43,18 @@ public class LimitAspect { LimitType limitType = limit.limitType(); String key = limit.key(); if (StringUtils.isEmpty(key)) { - switch (limitType) { - case IP: - key = StringUtils.getIP(request); - break; - default: - key = signatureMethod.getName(); + if (limitType == LimitType.IP) { + key = StringUtils.getIp(request); + } else { + key = signatureMethod.getName(); } } - ImmutableList keys = ImmutableList.of(StringUtils.join(limit.prefix(), "_", key, "_", request.getRequestURI().replaceAll("/","_"))); + ImmutableList keys = ImmutableList.of(StringUtils.join(limit.prefix(), "_", key, "_", request.getRequestURI().replaceAll("/","_"))); String luaScript = buildLuaScript(); RedisScript 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()) { logger.info("第{}次访问key为 {},描述为 [{}] 的接口", count, keys, limit.name()); return joinPoint.proceed(); diff --git a/eladmin-common/src/main/java/me/zhengjie/aspect/LimitType.java b/eladmin-common/src/main/java/me/zhengjie/aspect/LimitType.java index 6f383047..1c304eea 100644 --- a/eladmin-common/src/main/java/me/zhengjie/aspect/LimitType.java +++ b/eladmin-common/src/main/java/me/zhengjie/aspect/LimitType.java @@ -1,7 +1,12 @@ package me.zhengjie.aspect; +/** + * 限流枚举 + * @author / + */ public enum LimitType { + // 默认 CUSTOMER, -// by ip addr + // by ip addr IP; } diff --git a/eladmin-common/src/main/java/me/zhengjie/base/BaseDTO.java b/eladmin-common/src/main/java/me/zhengjie/base/BaseDTO.java new file mode 100644 index 00000000..903904df --- /dev/null +++ b/eladmin-common/src/main/java/me/zhengjie/base/BaseDTO.java @@ -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; +} diff --git a/eladmin-common/src/main/java/me/zhengjie/base/BaseEntity.java b/eladmin-common/src/main/java/me/zhengjie/base/BaseEntity.java new file mode 100644 index 00000000..2e9cc934 --- /dev/null +++ b/eladmin-common/src/main/java/me/zhengjie/base/BaseEntity.java @@ -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(); + } +} diff --git a/eladmin-common/src/main/java/me/zhengjie/mapper/EntityMapper.java b/eladmin-common/src/main/java/me/zhengjie/base/BaseMapper.java similarity index 63% rename from eladmin-common/src/main/java/me/zhengjie/mapper/EntityMapper.java rename to eladmin-common/src/main/java/me/zhengjie/base/BaseMapper.java index 98bc55db..82609e50 100644 --- a/eladmin-common/src/main/java/me/zhengjie/mapper/EntityMapper.java +++ b/eladmin-common/src/main/java/me/zhengjie/base/BaseMapper.java @@ -1,4 +1,4 @@ -package me.zhengjie.mapper; +package me.zhengjie.base; import java.util.List; @@ -6,33 +6,25 @@ import java.util.List; * @author Zheng Jie * @date 2018-11-23 */ -public interface EntityMapper { +public interface BaseMapper { /** * DTO转Entity - * @param dto - * @return */ E toEntity(D dto); /** * Entity转DTO - * @param entity - * @return */ D toDto(E entity); /** * DTO集合转Entity集合 - * @param dtoList - * @return */ List toEntity(List dtoList); /** * Entity集合转DTO集合 - * @param entityList - * @return */ List toDto(List entityList); } diff --git a/eladmin-common/src/main/java/me/zhengjie/config/ElPermissionConfig.java b/eladmin-common/src/main/java/me/zhengjie/config/ElPermissionConfig.java new file mode 100644 index 00000000..99e345c9 --- /dev/null +++ b/eladmin-common/src/main/java/me/zhengjie/config/ElPermissionConfig.java @@ -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 elPermissions = SecurityUtils.getUserDetails().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()); + // 判断当前用户的所有权限是否包含接口上定义的权限 + List list = Arrays.stream(permissions).filter(elPermissions::contains).collect(Collectors.toList()); + return elPermissions.contains("admin") || list.size() != 0; + } +} diff --git a/eladmin-common/src/main/java/me/zhengjie/redis/RedisConfig.java b/eladmin-common/src/main/java/me/zhengjie/config/RedisConfig.java similarity index 52% rename from eladmin-common/src/main/java/me/zhengjie/redis/RedisConfig.java rename to eladmin-common/src/main/java/me/zhengjie/config/RedisConfig.java index beb0170a..6e2d21ef 100644 --- a/eladmin-common/src/main/java/me/zhengjie/redis/RedisConfig.java +++ b/eladmin-common/src/main/java/me/zhengjie/config/RedisConfig.java @@ -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.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; import lombok.extern.slf4j.Slf4j; +import me.zhengjie.utils.StringUtils; +import org.apache.commons.codec.digest.DigestUtils; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; @@ -19,7 +23,12 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.time.Duration; +import java.util.HashMap; +import java.util.Map; /** * @author Zheng Jie @@ -28,21 +37,19 @@ import java.time.Duration; @Slf4j @Configuration @EnableCaching -// 自动配置 @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) public class RedisConfig extends CachingConfigurerSupport { /** - * 设置 redis 数据默认过期时间,默认1天 + * 设置 redis 数据默认过期时间,默认6小时 * 设置@cacheable 序列化方式 - * @return */ @Bean public RedisCacheConfiguration redisCacheConfiguration(){ FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); 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; } @@ -51,21 +58,20 @@ public class RedisConfig extends CachingConfigurerSupport { public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate template = new RedisTemplate<>(); //序列化 - FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class); + FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); // value值的序列化采用fastJsonRedisSerializer template.setValueSerializer(fastJsonRedisSerializer); template.setHashValueSerializer(fastJsonRedisSerializer); - - // 全局开启AutoType,不建议使用 - // ParserConfig.getGlobalInstance().setAutoTypeSupport(true); + // 全局开启AutoType,这里方便开发,使用全局的方式 + ParserConfig.getGlobalInstance().setAutoTypeSupport(true); // 建议使用这种方式,小范围指定白名单 - ParserConfig.getGlobalInstance().addAccept("me.zhengjie.domain"); - ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.service.dto"); - ParserConfig.getGlobalInstance().addAccept("me.zhengjie.service.dto"); - ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.domain"); - ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.quartz.domain"); - ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.monitor.domain"); - ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.security.security"); +// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.domain"); +// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.service.dto"); +// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.service.dto"); +// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.system.domain"); +// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.quartz.domain"); +// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.monitor.domain"); +// ParserConfig.getGlobalInstance().addAccept("me.zhengjie.modules.security.security"); // key的序列化采用StringRedisSerializer template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); @@ -75,20 +81,27 @@ public class RedisConfig extends CachingConfigurerSupport { /** * 自定义缓存key生成策略,默认将使用该策略 - * 使用方法 @Cacheable - * @return */ @Bean @Override public KeyGenerator keyGenerator() { return (target, method, params) -> { - StringBuilder sb = new StringBuilder(); - sb.append(target.getClass().getName()); - sb.append(method.getName()); - for (Object obj : params) { - sb.append(JSON.toJSONString(obj).hashCode()); + Map container = new HashMap<>(); + Class targetClassClass = target.getClass(); + // 类地址 + container.put("class",targetClassClass.toGenericString()); + // 方法名称 + container.put("methodName",method.getName()); + // 包名称 + container.put("package",targetClassClass.getPackage()); + // 参数列表 + for (int i = 0; i < params.length; i++) { + container.put(String.valueOf(i),params[i]); } - 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() { // 异常处理,当Redis发生异常时,打印日志,但是程序正常走 log.info("初始化 -> [{}]", "Redis CacheErrorHandler"); - CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() { + return new CacheErrorHandler() { @Override public void handleCacheGetError(RuntimeException e, Cache cache, Object key) { log.error("Redis occur handleCacheGetError:key -> [{}]", key, e); @@ -118,7 +131,74 @@ public class RedisConfig extends CachingConfigurerSupport { log.error("Redis occur handleCacheClearError:", e); } }; - return cacheErrorHandler; } } + +/** + * Value 序列化 + * + * @author / + * @param + */ + class FastJsonRedisSerializer implements RedisSerializer { + + private Class clazz; + + FastJsonRedisSerializer(Class 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 { + + 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); + } +} diff --git a/eladmin-common/src/main/java/me/zhengjie/swagger2/SwaggerConfig.java b/eladmin-common/src/main/java/me/zhengjie/config/SwaggerConfig.java similarity index 53% rename from eladmin-common/src/main/java/me/zhengjie/swagger2/SwaggerConfig.java rename to eladmin-common/src/main/java/me/zhengjie/config/SwaggerConfig.java index 207873cd..4d4520e9 100644 --- a/eladmin-common/src/main/java/me/zhengjie/swagger2/SwaggerConfig.java +++ b/eladmin-common/src/main/java/me/zhengjie/config/SwaggerConfig.java @@ -1,12 +1,20 @@ -package me.zhengjie.swagger2; +package me.zhengjie.config; +import com.fasterxml.classmate.TypeResolver; import com.google.common.base.Predicates; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.data.domain.Pageable; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.ParameterBuilder; import springfox.documentation.builders.PathSelectors; +import springfox.documentation.schema.AlternateTypeRule; +import springfox.documentation.schema.AlternateTypeRuleConvention; import springfox.documentation.schema.ModelRef; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Parameter; @@ -15,6 +23,8 @@ import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.ArrayList; import java.util.List; +import static com.google.common.collect.Lists.newArrayList; +import static springfox.documentation.schema.AlternateTypeRules.newRule; /** * api页面 /swagger-ui.html @@ -33,9 +43,10 @@ public class SwaggerConfig { private Boolean enabled; @Bean + @SuppressWarnings("all") public Docket createRestApi() { ParameterBuilder ticketPar = new ParameterBuilder(); - List pars = new ArrayList(); + List pars = new ArrayList<>(); ticketPar.name(tokenHeader).description("token") .modelRef(new ModelRef("string")) .parameterType("header") @@ -55,8 +66,43 @@ public class SwaggerConfig { private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("eladmin 接口文档") - .version("2.1") + .version("2.3") .build(); } } + +/** + * 将Pageable转换展示在swagger中 + */ +@Configuration +class SwaggerDataConfig { + + @Bean + public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) { + return new AlternateTypeRuleConvention() { + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + + @Override + public List 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 sort; + } +} diff --git a/eladmin-common/src/main/java/me/zhengjie/exception/BadRequestException.java b/eladmin-common/src/main/java/me/zhengjie/exception/BadRequestException.java index adef657a..d17b18dd 100644 --- a/eladmin-common/src/main/java/me/zhengjie/exception/BadRequestException.java +++ b/eladmin-common/src/main/java/me/zhengjie/exception/BadRequestException.java @@ -2,7 +2,6 @@ package me.zhengjie.exception; import lombok.Getter; import org.springframework.http.HttpStatus; - import static org.springframework.http.HttpStatus.BAD_REQUEST; /** diff --git a/eladmin-common/src/main/java/me/zhengjie/exception/EntityExistException.java b/eladmin-common/src/main/java/me/zhengjie/exception/EntityExistException.java index 23417a72..5ade7950 100644 --- a/eladmin-common/src/main/java/me/zhengjie/exception/EntityExistException.java +++ b/eladmin-common/src/main/java/me/zhengjie/exception/EntityExistException.java @@ -2,33 +2,18 @@ package me.zhengjie.exception; import org.springframework.util.StringUtils; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.IntStream; - /** * @author Zheng Jie * @date 2018-11-23 */ public class EntityExistException extends RuntimeException { - public EntityExistException(Class clazz, Object... saveBodyParamsMap) { - super(EntityExistException.generateMessage(clazz.getSimpleName(), toMap(String.class, String.class, saveBodyParamsMap))); + public EntityExistException(Class clazz, String field, String val) { + super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val)); } - private static String generateMessage(String entity, Map saveBodyParams) { - return StringUtils.capitalize(entity) + - " 已存在 " + - saveBodyParams; - } - - private static Map toMap( - Class keyType, Class 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); + private static String generateMessage(String entity, String field, String val) { + return StringUtils.capitalize(entity) + + " with " + field + " "+ val + " existed"; } } \ No newline at end of file diff --git a/eladmin-common/src/main/java/me/zhengjie/exception/EntityNotFoundException.java b/eladmin-common/src/main/java/me/zhengjie/exception/EntityNotFoundException.java index 31e1cbdf..295bb280 100644 --- a/eladmin-common/src/main/java/me/zhengjie/exception/EntityNotFoundException.java +++ b/eladmin-common/src/main/java/me/zhengjie/exception/EntityNotFoundException.java @@ -2,34 +2,18 @@ package me.zhengjie.exception; import org.springframework.util.StringUtils; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.IntStream; - /** * @author Zheng Jie * @date 2018-11-23 */ public class EntityNotFoundException extends RuntimeException { - public EntityNotFoundException(Class clazz, Object... searchParamsMap) { - super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), toMap(String.class, String.class, searchParamsMap))); + public EntityNotFoundException(Class clazz, String field, String val) { + super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val)); } - private static String generateMessage(String entity, Map searchParams) { - return StringUtils.capitalize(entity) + - " 不存在 " + - searchParams; + private static String generateMessage(String entity, String field, String val) { + return StringUtils.capitalize(entity) + + " with " + field + " "+ val + " does not exist"; } - - private static Map toMap( - Class keyType, Class 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); - } - } \ No newline at end of file diff --git a/eladmin-common/src/main/java/me/zhengjie/exception/handler/ApiError.java b/eladmin-common/src/main/java/me/zhengjie/exception/handler/ApiError.java index db43891e..9cabb324 100644 --- a/eladmin-common/src/main/java/me/zhengjie/exception/handler/ApiError.java +++ b/eladmin-common/src/main/java/me/zhengjie/exception/handler/ApiError.java @@ -12,7 +12,7 @@ import java.time.LocalDateTime; @Data class ApiError { - private Integer status; + private Integer status = 400; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime timestamp; private String message; @@ -21,10 +21,17 @@ class ApiError { timestamp = LocalDateTime.now(); } - public ApiError(Integer status,String message) { - this(); - this.status = status; - this.message = message; + public static ApiError error(String message){ + ApiError apiError = new ApiError(); + apiError.setMessage(message); + return apiError; + } + + public static ApiError error(Integer status, String message){ + ApiError apiError = new ApiError(); + apiError.setStatus(status); + apiError.setMessage(message); + return apiError; } } diff --git a/eladmin-common/src/main/java/me/zhengjie/exception/handler/GlobalExceptionHandler.java b/eladmin-common/src/main/java/me/zhengjie/exception/handler/GlobalExceptionHandler.java index 5e58c784..2d0385b9 100644 --- a/eladmin-common/src/main/java/me/zhengjie/exception/handler/GlobalExceptionHandler.java +++ b/eladmin-common/src/main/java/me/zhengjie/exception/handler/GlobalExceptionHandler.java @@ -11,6 +11,7 @@ import org.springframework.security.access.AccessDeniedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import java.util.Objects; import static org.springframework.http.HttpStatus.*; /** @@ -23,91 +24,73 @@ public class GlobalExceptionHandler { /** * 处理所有不可知的异常 - * @param e - * @return */ @ExceptionHandler(Throwable.class) public ResponseEntity handleException(Throwable e){ // 打印堆栈信息 log.error(ThrowableUtil.getStackTrace(e)); - ApiError apiError = new ApiError(BAD_REQUEST.value(),e.getMessage()); - return buildResponseEntity(apiError); + return buildResponseEntity(ApiError.error(e.getMessage())); } /** * 处理 接口无权访问异常AccessDeniedException - * @param e - * @return */ @ExceptionHandler(AccessDeniedException.class) public ResponseEntity handleAccessDeniedException(AccessDeniedException e){ // 打印堆栈信息 log.error(ThrowableUtil.getStackTrace(e)); - ApiError apiError = new ApiError(FORBIDDEN.value(),e.getMessage()); - return buildResponseEntity(apiError); + return buildResponseEntity(ApiError.error(FORBIDDEN.value(),e.getMessage())); } /** * 处理自定义异常 - * @param e - * @return */ @ExceptionHandler(value = BadRequestException.class) public ResponseEntity badRequestException(BadRequestException e) { // 打印堆栈信息 log.error(ThrowableUtil.getStackTrace(e)); - ApiError apiError = new ApiError(e.getStatus(),e.getMessage()); - return buildResponseEntity(apiError); + return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage())); } /** * 处理 EntityExist - * @param e - * @return */ @ExceptionHandler(value = EntityExistException.class) public ResponseEntity entityExistException(EntityExistException e) { // 打印堆栈信息 log.error(ThrowableUtil.getStackTrace(e)); - ApiError apiError = new ApiError(BAD_REQUEST.value(),e.getMessage()); - return buildResponseEntity(apiError); + return buildResponseEntity(ApiError.error(e.getMessage())); } /** * 处理 EntityNotFound - * @param e - * @return */ @ExceptionHandler(value = EntityNotFoundException.class) public ResponseEntity entityNotFoundException(EntityNotFoundException e) { // 打印堆栈信息 log.error(ThrowableUtil.getStackTrace(e)); - ApiError apiError = new ApiError(NOT_FOUND.value(),e.getMessage()); - return buildResponseEntity(apiError); + return buildResponseEntity(ApiError.error(NOT_FOUND.value(),e.getMessage())); } /** * 处理所有接口数据验证异常 - * @param e - * @returns */ @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException e){ // 打印堆栈信息 log.error(ThrowableUtil.getStackTrace(e)); - String[] str = e.getBindingResult().getAllErrors().get(0).getCodes()[1].split("\\."); - StringBuffer msg = new StringBuffer(str[1]+":"); - msg.append(e.getBindingResult().getAllErrors().get(0).getDefaultMessage()); - ApiError apiError = new ApiError(BAD_REQUEST.value(),msg.toString()); - return buildResponseEntity(apiError); + String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\."); + String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage(); + if("不能为空".equals(message)){ + message = str[1] + ":" + message; + } + return buildResponseEntity(ApiError.error(message)); } /** * 统一返回 - * @param apiError - * @return */ private ResponseEntity buildResponseEntity(ApiError apiError) { - return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus())); + return new ResponseEntity<>(apiError, HttpStatus.valueOf(apiError.getStatus())); } } diff --git a/eladmin-common/src/main/java/me/zhengjie/redis/FastJsonRedisSerializer.java b/eladmin-common/src/main/java/me/zhengjie/redis/FastJsonRedisSerializer.java deleted file mode 100644 index d2e224c8..00000000 --- a/eladmin-common/src/main/java/me/zhengjie/redis/FastJsonRedisSerializer.java +++ /dev/null @@ -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 - */ -public class FastJsonRedisSerializer implements RedisSerializer { - - public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); - - private Class clazz; - - public FastJsonRedisSerializer(Class 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); - } - -} diff --git a/eladmin-common/src/main/java/me/zhengjie/redis/StringRedisSerializer.java b/eladmin-common/src/main/java/me/zhengjie/redis/StringRedisSerializer.java deleted file mode 100644 index e0f54f10..00000000 --- a/eladmin-common/src/main/java/me/zhengjie/redis/StringRedisSerializer.java +++ /dev/null @@ -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 { - - 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); - } -} \ No newline at end of file diff --git a/eladmin-common/src/main/java/me/zhengjie/swagger2/SwaggerDataConfig.java b/eladmin-common/src/main/java/me/zhengjie/swagger2/SwaggerDataConfig.java deleted file mode 100644 index 35f0edf1..00000000 --- a/eladmin-common/src/main/java/me/zhengjie/swagger2/SwaggerDataConfig.java +++ /dev/null @@ -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 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 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 getSort() { return sort; } public void setSort(List sort) { this.sort = sort; } } } \ No newline at end of file diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/ElAdminConstant.java b/eladmin-common/src/main/java/me/zhengjie/utils/ElAdminConstant.java index 89bfeaae..47199dba 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/ElAdminConstant.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/ElAdminConstant.java @@ -14,7 +14,7 @@ public class ElAdminConstant { /** * 用于IP定位转换 */ - public static final String REGION = "内网IP|内网IP"; + static final String REGION = "内网IP|内网IP"; /** * 常用接口 diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/EncryptUtils.java b/eladmin-common/src/main/java/me/zhengjie/utils/EncryptUtils.java index 5bddf3a5..1cf6fa16 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/EncryptUtils.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/EncryptUtils.java @@ -6,6 +6,7 @@ import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; 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 { if (source == null || source.length() == 0){ return null; } 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"); 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); 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; - StringBuffer out = new StringBuffer(inStr.length * 2); - for (int n = 0; n < inStr.length; n++) { - stmp = Integer.toHexString(inStr[n] & 0xFF); + StringBuilder out = new StringBuilder(inStr.length * 2); + for (byte b : inStr) { + stmp = Integer.toHexString(b & 0xFF); if (stmp.length() == 1) { // 如果是0至F的单位字符串,则添加0 - out.append("0" + stmp); + out.append("0").append(stmp); } else { out.append(stmp); } @@ -51,8 +49,7 @@ public class EncryptUtils { return out.toString(); } - - public static byte[] hex2byte(byte[] b) { + private static byte[] hex2byte(byte[] b) { if ((b.length % 2) != 0){ throw new IllegalArgumentException("长度不是偶数"); } @@ -66,9 +63,6 @@ public class EncryptUtils { /** * 对称解密 - * @param source - * @return - * @throws Exception */ public static String desDecrypt(String source) throws Exception { if (source == null || source.length() == 0){ @@ -76,10 +70,10 @@ public class EncryptUtils { } byte[] src = hex2byte(source.getBytes()); 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"); 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); byte[] retByte = cipher.doFinal(src); return new String(retByte); @@ -87,8 +81,6 @@ public class EncryptUtils { /** * 密码加密 - * @param password - * @return */ public static String encryptPassword(String password){ return DigestUtils.md5DigestAsHex(password.getBytes()); diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java b/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java index b6a04ac1..151f0283 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/FileUtil.java @@ -11,6 +11,7 @@ import javax.activation.MimetypesFileTypeMap; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.*; +import java.security.MessageDigest; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Date; @@ -44,8 +45,6 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { /** * MultipartFile转File - * @param multipartFile - * @return */ 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) { if ((filename != null) && (filename.length() > 0)) { @@ -93,8 +78,6 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { /** * Java文件操作 获取不带扩展名的文件名 - * @param filename - * @return */ public static String getFileNameNoEx(String filename) { 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){ - String resultSize = ""; + String resultSize; if (size / GB >= 1) { //如果当前Byte的值大于等于1GB resultSize = DF.format(size / (float) GB) + "GB "; @@ -130,18 +111,14 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { /** * 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); if (file.exists()) { return file; } OutputStream os = new FileOutputStream(file); - int bytesRead = 0; + int bytesRead; byte[] buffer = new byte[8192]; while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { 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) { Date date = new Date(); @@ -170,10 +143,10 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { File dest = new File(path); // 检测是否存在目录 if (!dest.getParentFile().exists()) { - dest.getParentFile().mkdirs();// 新建文件夹 + dest.getParentFile().mkdirs(); } - String d = dest.getPath(); - file.transferTo(dest);// 文件写入 + // 文件写入 + file.transferTo(dest); return dest; } catch (Exception e) { e.printStackTrace(); @@ -183,20 +156,16 @@ public class FileUtil extends cn.hutool.core.io.FileUtil { public static String fileToBase64(File file) throws Exception { FileInputStream inputFile = new FileInputStream(file); - String base64 =null; + String base64; byte[] buffer = new byte[(int)file.length()]; inputFile.read(buffer); inputFile.close(); - base64=new Base64().encode(buffer); - String encoded = base64.replaceAll("[\\s*\t\n\r]", ""); - return encoded; + base64=Base64.encode(buffer); + return base64.replaceAll("[\\s*\t\n\r]", ""); } /** * 导出excel - * @param list - * @return - * @throws Exception */ public static void downloadExcel(List> list, HttpServletResponse response) throws IOException { 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) { - 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 video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg"; String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg"; - if(image.indexOf(type) != -1){ + if(image.contains(type)){ return "图片"; - } else if(documents.indexOf(type) != -1){ + } else if(documents.contains(type)){ return "文档"; - } else if(music.indexOf(type) != -1){ + } else if(music.contains(type)){ return "音乐"; - } else if(video.indexOf(type) != -1){ + } else if(video.contains(type)){ return "视频"; - } else return "其他"; + } else { + return "其他"; + } } public static String getFileTypeByMimeType(String type) { String mimeType = new MimetypesFileTypeMap().getContentType("." + type); - return mimeType.split("\\/")[0]; + return mimeType.split("/")[0]; } + public static void checkSize(long maxSize, long size) { if(size > (maxSize * 1024 * 1024)){ throw new BadRequestException("文件超出规定大小"); } } + + /** + * 判断两个文件是否相同 + */ + public static boolean check(File file1, File file2) { + String img1Md5 = getMd5(file1); + String img2Md5 = getMd5(file2); + return img1Md5.equals(img2Md5); + } + + /** + * 判断两个文件是否相同 + */ + public static boolean check(String file1Md5, String file2Md5) { + return file1Md5.equals(file2Md5); + } + + private static byte[] getByte(File file) { + // 得到文件长度 + byte[] b = new byte[(int) file.length()]; + try { + InputStream in = new FileInputStream(file); + try { + in.read(b); + } catch (IOException e) { + e.printStackTrace(); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } + return b; + } + + private static String getMd5(byte[] bytes) { + // 16进制字符 + char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + try { + MessageDigest mdTemp = MessageDigest.getInstance("MD5"); + mdTemp.update(bytes); + byte[] md = mdTemp.digest(); + int j = md.length; + char[] str = new char[j * 2]; + int k = 0; + // 移位 输出字符串 + for (byte byte0 : md) { + str[k++] = hexDigits[byte0 >>> 4 & 0xf]; + str[k++] = hexDigits[byte0 & 0xf]; + } + return new String(str); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static String getMd5(File file) { + return getMd5(getByte(file)); + } + } diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/PageUtil.java b/eladmin-common/src/main/java/me/zhengjie/utils/PageUtil.java index 8ca67b0a..b32e64d7 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/PageUtil.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/PageUtil.java @@ -12,10 +12,6 @@ public class PageUtil extends cn.hutool.core.util.PageUtil { /** * List 分页 - * @param page - * @param size - * @param list - * @return */ public static List toPage(int page, int size , List list) { int fromIndex = page * size; @@ -32,10 +28,8 @@ public class PageUtil extends cn.hutool.core.util.PageUtil { /** * Page 数据处理,预防redis反序列化报错 - * @param page - * @return */ - public static Map toPage(Page page) { + public static Map toPage(Page page) { Map map = new LinkedHashMap<>(2); map.put("content",page.getContent()); 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 toPage(Object object, Object totalElements) { Map map = new LinkedHashMap<>(2); map.put("content",object); map.put("totalElements",totalElements); diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/QueryHelp.java b/eladmin-common/src/main/java/me/zhengjie/utils/QueryHelp.java index 0ea14822..7c82dc1e 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/QueryHelp.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/QueryHelp.java @@ -15,18 +15,12 @@ import java.util.*; @Slf4j public class QueryHelp { - /** - * @描述 : 转换为Predicate - * @作者 : Dong ZhaoYang - * @日期 : 2017/8/7 - * @时间 : 17:25 - */ @SuppressWarnings("unchecked") public static Predicate getPredicate(Root root, Q query, CriteriaBuilder cb) { List list = new ArrayList<>(); if(query == null){ - return cb.and(list.toArray(new Predicate[list.size()])); + return cb.and(list.toArray(new Predicate[0])); } try { List fields = getAllFields(query.getClass(), new ArrayList<>()); @@ -62,19 +56,20 @@ public class QueryHelp { for (String name : joinNames) { switch (q.join()) { case LEFT: - if(ObjectUtil.isNotEmpty(join)){ + if(ObjectUtil.isNotNull(join)){ join = join.join(name, JoinType.LEFT); } else { join = root.join(name, JoinType.LEFT); } break; case RIGHT: - if(ObjectUtil.isNotEmpty(join)){ + if(ObjectUtil.isNotNull(join)){ join = join.join(name, JoinType.RIGHT); } else { join = root.join(name, JoinType.RIGHT); } break; + default: break; } } } @@ -111,6 +106,7 @@ public class QueryHelp { list.add(getExpression(attributeName,join,root).in((Collection) val)); } break; + default: break; } } field.setAccessible(accessible); @@ -118,7 +114,8 @@ public class QueryHelp { } catch (Exception 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") @@ -130,21 +127,19 @@ public class QueryHelp { } } - @SuppressWarnings("unchecked") - public static boolean isBlank(final CharSequence cs) { + private static boolean isBlank(final CharSequence cs) { int strLen; if (cs == null || (strLen = cs.length()) == 0) { return true; } for (int i = 0; i < strLen; i++) { - if (Character.isWhitespace(cs.charAt(i)) == false) { + if (!Character.isWhitespace(cs.charAt(i))) { return false; } } return true; } - @SuppressWarnings("unchecked") private static List getAllFields(Class clazz, List fields) { if (clazz != null) { fields.addAll(Arrays.asList(clazz.getDeclaredFields())); diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/RequestHolder.java b/eladmin-common/src/main/java/me/zhengjie/utils/RequestHolder.java index 343b451b..f9458838 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/RequestHolder.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/RequestHolder.java @@ -3,6 +3,7 @@ package me.zhengjie.utils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; +import java.util.Objects; /** * 获取 HttpServletRequest @@ -12,6 +13,6 @@ import javax.servlet.http.HttpServletRequest; public class RequestHolder { public static HttpServletRequest getHttpServletRequest() { - return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); } } diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/SecurityUtils.java b/eladmin-common/src/main/java/me/zhengjie/utils/SecurityUtils.java index e040c111..0799c968 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/SecurityUtils.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/SecurityUtils.java @@ -13,7 +13,7 @@ import org.springframework.security.core.userdetails.UserDetails; public class SecurityUtils { public static UserDetails getUserDetails() { - UserDetails userDetails = null; + UserDetails userDetails; try { userDetails = (UserDetails) org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication().getPrincipal(); } catch (Exception e) { @@ -28,8 +28,7 @@ public class SecurityUtils { */ public static String getUsername(){ Object obj = getUserDetails(); - JSONObject json = new JSONObject(obj); - return json.get("username", String.class); + return new JSONObject(obj).get("username", String.class); } /** @@ -38,7 +37,6 @@ public class SecurityUtils { */ public static Long getUserId(){ Object obj = getUserDetails(); - JSONObject json = new JSONObject(obj); - return json.get("id", Long.class); + return new JSONObject(obj).get("id", Long.class); } } diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/SpringContextHolder.java b/eladmin-common/src/main/java/me/zhengjie/utils/SpringContextHolder.java index e4bfcbbc..fd255348 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/SpringContextHolder.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/SpringContextHolder.java @@ -7,7 +7,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; /** - * @author + * @author Jie * @date 2019-01-07 */ @Slf4j @@ -15,17 +15,10 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB private static ApplicationContext applicationContext = null; - /** - * 取得存储在静态变量中的ApplicationContext. - */ - public static ApplicationContext getApplicationContext() { - assertContextInjected(); - return applicationContext; - } - /** * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. */ + @SuppressWarnings("unchecked") public static T getBean(String name) { assertContextInjected(); return (T) applicationContext.getBean(name); @@ -52,14 +45,14 @@ public class SpringContextHolder implements ApplicationContextAware, DisposableB /** * 清除SpringContextHolder中的ApplicationContext为Null. */ - public static void clearHolder() { + private static void clearHolder() { log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext); applicationContext = null; } @Override - public void destroy() throws Exception { + public void destroy(){ SpringContextHolder.clearHolder(); } diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/StringUtils.java b/eladmin-common/src/main/java/me/zhengjie/utils/StringUtils.java index fd2647d0..8f865f2e 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/StringUtils.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/StringUtils.java @@ -1,14 +1,16 @@ package me.zhengjie.utils; import cn.hutool.core.io.resource.ClassPathResource; +import eu.bitwalker.useragentutils.Browser; +import eu.bitwalker.useragentutils.UserAgent; import org.lionsoul.ip2region.DataBlock; import org.lionsoul.ip2region.DbConfig; import org.lionsoul.ip2region.DbSearcher; - import javax.servlet.http.HttpServletRequest; import java.io.File; -import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.Calendar; import java.util.Date; @@ -18,25 +20,6 @@ import java.util.Date; public class StringUtils extends org.apache.commons.lang3.StringUtils { 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" * toUnderScoreCase("helloWorld") = "hello_world" */ - public static String toUnderScoreCase(String s) { + static String toUnderScoreCase(String s) { if (s == null) { return null; } @@ -125,53 +108,45 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils { /** * 获取ip地址 - * @param request - * @return */ - public static String getIP(HttpServletRequest request) { + public static String getIp(HttpServletRequest request) { 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"); } - 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"); } - if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } - String[] ips = ip.split(","); - return "0:0:0:0:0:0:0:1".equals(ips[0])?"127.0.0.1":ips[0]; + if (ip.contains(",")) { + ip = ip.split(",")[0]; + } + if ("127.0.0.1".equals(ip)) { + // 获取本机真正的ip地址 + try { + ip = InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + } + return ip; } /** * 根据ip获取详细地址 - * @param ip - * @return */ public static String getCityInfo(String ip) { try { String path = "ip2region/ip2region.db"; String name = "ip2region.db"; - int algorithm = DbSearcher.BTREE_ALGORITHM; DbConfig config = new DbConfig(); File file = FileUtil.inputStreamToFile(new ClassPathResource(path).getStream(), name); DbSearcher searcher = new DbSearcher(config, file.getPath()); - Method method = null; - switch (algorithm) { - case DbSearcher.BTREE_ALGORITHM: - 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; + Method method; + method = searcher.getClass().getMethod("btreeSearch", String.class); + DataBlock dataBlock; dataBlock = (DataBlock) method.invoke(searcher, ip); String address = dataBlock.getRegion().replace("0|",""); if(address.charAt(address.length()-1) == '|'){ @@ -184,6 +159,12 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils { return ""; } + public static String getBrowser(HttpServletRequest request){ + UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent")); + Browser browser = userAgent.getBrowser(); + return browser.getName(); + } + /** * 获得当天是周几 */ diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/ThrowableUtil.java b/eladmin-common/src/main/java/me/zhengjie/utils/ThrowableUtil.java index 6faa8c61..3c1f3f7a 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/ThrowableUtil.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/ThrowableUtil.java @@ -2,30 +2,23 @@ package me.zhengjie.utils; import me.zhengjie.exception.BadRequestException; import org.hibernate.exception.ConstraintViolationException; - import java.io.PrintWriter; import java.io.StringWriter; /** - * 异常工具 + * 异常工具 2019-01-06 * @author Zheng Jie - * @date 2019-01-06 */ public class ThrowableUtil { /** * 获取堆栈信息 - * @param throwable - * @return */ public static String getStackTrace(Throwable throwable){ StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - try { + try (PrintWriter pw = new PrintWriter(sw)) { throwable.printStackTrace(pw); return sw.toString(); - } finally { - pw.close(); } } @@ -34,9 +27,10 @@ public class ThrowableUtil { while ((t != null) && !(t instanceof ConstraintViolationException)) { t = t.getCause(); } - if (t instanceof ConstraintViolationException) { + if (t != null) { throw new BadRequestException(msg); } + assert false; throw new BadRequestException("删除失败:" + t.getMessage()); } } diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/TranslatorUtil.java b/eladmin-common/src/main/java/me/zhengjie/utils/TranslatorUtil.java index 1f34b54c..7a45a810 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/TranslatorUtil.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/TranslatorUtil.java @@ -1,8 +1,6 @@ package me.zhengjie.utils; import cn.hutool.json.JSONArray; -import lombok.var; - import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; @@ -26,7 +24,7 @@ public class TranslatorUtil { BufferedReader in = new BufferedReader( new InputStreamReader(con.getInputStream())); String inputLine; - StringBuffer response = new StringBuffer(); + StringBuilder response = new StringBuilder(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); @@ -38,15 +36,12 @@ public class TranslatorUtil { } } - private static String parseResult(String inputJson) throws Exception { - JSONArray jsonArray = new JSONArray(inputJson); - JSONArray jsonArray2 = (JSONArray) jsonArray.get(0); - String result =""; - - for(var i = 0; i < jsonArray2.size(); i ++){ - result += ((JSONArray) jsonArray2.get(i)).get(0).toString(); + private static String parseResult(String inputJson){ + JSONArray jsonArray2 = (JSONArray) new JSONArray(inputJson).get(0); + StringBuilder result = new StringBuilder(); + for (Object o : jsonArray2) { + result.append(((JSONArray) o).get(0).toString()); } - return result; + return result.toString(); } - } diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/ValidationUtil.java b/eladmin-common/src/main/java/me/zhengjie/utils/ValidationUtil.java index fa8e7baf..7d49adfa 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/ValidationUtil.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/ValidationUtil.java @@ -1,7 +1,7 @@ package me.zhengjie.utils; +import cn.hutool.core.util.ObjectUtil; 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){ - if(!optional.isPresent()){ - String msg = entity - + " 不存在 " - +"{ "+ parameter +":"+ value.toString() +" }"; + public static void isNull(Object obj, String entity, String parameter , Object value){ + if(ObjectUtil.isNull(obj)){ + String msg = entity + " 不存在: "+ parameter +" is "+ value; throw new BadRequestException(msg); } } /** * 验证是否为邮箱 - * @param string - * @return */ public static boolean isEmail(String string) { if (string == null){ return false; } - String regEx1 = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"; + 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); } } diff --git a/eladmin-common/src/test/java/me/zhengjie/utils/StringUtilsTest.java b/eladmin-common/src/test/java/me/zhengjie/utils/StringUtilsTest.java index f18fb1d9..12e875a8 100644 --- a/eladmin-common/src/test/java/me/zhengjie/utils/StringUtilsTest.java +++ b/eladmin-common/src/test/java/me/zhengjie/utils/StringUtilsTest.java @@ -11,12 +11,6 @@ import static org.junit.Assert.*; public class StringUtilsTest { - @Test - public void testInString() { - assertTrue(inString("?", "?")); - assertFalse(inString("?", new String[]{})); - } - @Test public void testToCamelCase() { assertNull(toCamelCase(null)); @@ -44,6 +38,6 @@ public class StringUtilsTest { @Test public void testGetIP() { - assertEquals("127.0.0.1", getIP(new MockHttpServletRequest())); + assertEquals("127.0.0.1", getIp(new MockHttpServletRequest())); } } \ No newline at end of file diff --git a/eladmin-generator/pom.xml b/eladmin-generator/pom.xml index df8ea391..1ac5ccb1 100644 --- a/eladmin-generator/pom.xml +++ b/eladmin-generator/pom.xml @@ -5,7 +5,7 @@ eladmin me.zhengjie - 2.2 + 2.3 4.0.0 @@ -20,7 +20,7 @@ me.zhengjie eladmin-common - 2.2 + 2.3 diff --git a/eladmin-generator/src/main/java/me/zhengjie/domain/GenConfig.java b/eladmin-generator/src/main/java/me/zhengjie/domain/GenConfig.java index 1f79a911..30790e46 100644 --- a/eladmin-generator/src/main/java/me/zhengjie/domain/GenConfig.java +++ b/eladmin-generator/src/main/java/me/zhengjie/domain/GenConfig.java @@ -16,26 +16,26 @@ public class GenConfig { @Id private Long id; - /** 包路径 **/ + // 包路径 private String pack; - /** 模块名 **/ + // 模块名 @Column(name = "module_name") private String moduleName; - /** 前端文件路径 **/ + // 前端文件路径 private String path; - /** 前端文件路径 **/ + // 前端文件路径 @Column(name = "api_path") private String apiPath; - /** 作者 **/ + // 作者 private String author; - /** 表前缀 **/ + // 表前缀 private String prefix; - /** 是否覆盖 **/ + // 是否覆盖 private Boolean cover; } diff --git a/eladmin-generator/src/main/java/me/zhengjie/domain/vo/ColumnInfo.java b/eladmin-generator/src/main/java/me/zhengjie/domain/vo/ColumnInfo.java index 5a8475a2..a22470aa 100644 --- a/eladmin-generator/src/main/java/me/zhengjie/domain/vo/ColumnInfo.java +++ b/eladmin-generator/src/main/java/me/zhengjie/domain/vo/ColumnInfo.java @@ -14,27 +14,27 @@ import lombok.NoArgsConstructor; @NoArgsConstructor public class ColumnInfo { - /** 数据库字段名称 **/ + // 数据库字段名称 private Object columnName; - /** 允许空值 **/ + // 允许空值 private Object isNullable; - /** 数据库字段类型 **/ + // 数据库字段类型 private Object columnType; - /** 数据库字段注释 **/ + // 数据库字段注释 private Object columnComment; - /** 数据库字段键类型 **/ + // 数据库字段键类型 private Object columnKey; - /** 额外的参数 **/ + // 额外的参数 private Object extra; - /** 查询 1:模糊 2:精确 **/ + // 查询 1:模糊 2:精确 private String columnQuery; - /** 是否在列表显示 **/ + // 是否在列表显示 private String columnShow; } diff --git a/eladmin-generator/src/main/java/me/zhengjie/domain/vo/TableInfo.java b/eladmin-generator/src/main/java/me/zhengjie/domain/vo/TableInfo.java index 92712d75..b1b6ba4e 100644 --- a/eladmin-generator/src/main/java/me/zhengjie/domain/vo/TableInfo.java +++ b/eladmin-generator/src/main/java/me/zhengjie/domain/vo/TableInfo.java @@ -14,10 +14,10 @@ import lombok.NoArgsConstructor; @NoArgsConstructor public class TableInfo { - /** 表名称 **/ + // 表名称 private Object tableName; - /** 创建日期 **/ + // 创建日期 private Object createTime; // 数据库引擎 diff --git a/eladmin-generator/src/main/java/me/zhengjie/rest/GenConfigController.java b/eladmin-generator/src/main/java/me/zhengjie/rest/GenConfigController.java index 19c092f8..0650b959 100644 --- a/eladmin-generator/src/main/java/me/zhengjie/rest/GenConfigController.java +++ b/eladmin-generator/src/main/java/me/zhengjie/rest/GenConfigController.java @@ -1,8 +1,9 @@ package me.zhengjie.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import me.zhengjie.domain.GenConfig; import me.zhengjie.service.GenConfigService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; @@ -13,23 +14,25 @@ import org.springframework.web.bind.annotation.*; * @date 2019-01-14 */ @RestController -@RequestMapping("api") +@RequestMapping("/api/genConfig") +@Api(tags = "系统:代码生成器配置管理") public class GenConfigController { - @Autowired - private GenConfigService genConfigService; + private final GenConfigService genConfigService; - /** - * 查询生成器配置 - * @return - */ - @GetMapping(value = "/genConfig") - public ResponseEntity get(){ - return new ResponseEntity(genConfigService.find(), HttpStatus.OK); + public GenConfigController(GenConfigService genConfigService) { + this.genConfigService = genConfigService; } - @PutMapping(value = "/genConfig") + @ApiOperation("查询") + @GetMapping + public ResponseEntity get(){ + return new ResponseEntity<>(genConfigService.find(), HttpStatus.OK); + } + + @ApiOperation("修改") + @PutMapping public ResponseEntity emailConfig(@Validated @RequestBody GenConfig genConfig){ - return new ResponseEntity(genConfigService.update(genConfig),HttpStatus.OK); + return new ResponseEntity<>(genConfigService.update(genConfig),HttpStatus.OK); } } diff --git a/eladmin-generator/src/main/java/me/zhengjie/rest/GeneratorController.java b/eladmin-generator/src/main/java/me/zhengjie/rest/GeneratorController.java index 65158981..653489e2 100644 --- a/eladmin-generator/src/main/java/me/zhengjie/rest/GeneratorController.java +++ b/eladmin-generator/src/main/java/me/zhengjie/rest/GeneratorController.java @@ -1,11 +1,12 @@ package me.zhengjie.rest; import cn.hutool.core.util.PageUtil; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import me.zhengjie.domain.vo.ColumnInfo; import me.zhengjie.exception.BadRequestException; import me.zhengjie.service.GenConfigService; import me.zhengjie.service.GeneratorService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -17,49 +18,39 @@ import java.util.List; * @date 2019-01-02 */ @RestController -@RequestMapping("api") +@RequestMapping("/api/generator") +@Api(tags = "系统:代码生成管理") public class GeneratorController { - @Autowired - private GeneratorService generatorService; + private final GeneratorService generatorService; - @Autowired - private GenConfigService genConfigService; + private final GenConfigService genConfigService; @Value("${generator.enabled}") private Boolean generatorEnabled; - /** - * 查询数据库元数据 - * @param name - * @param page - * @param size - * @return - */ - @GetMapping(value = "/generator/tables") + public GeneratorController(GeneratorService generatorService, GenConfigService genConfigService) { + this.generatorService = generatorService; + this.genConfigService = genConfigService; + } + + @ApiOperation("查询数据库元数据") + @GetMapping(value = "/tables") public ResponseEntity getTables(@RequestParam(defaultValue = "") String name, - @RequestParam(defaultValue = "0")Integer page, - @RequestParam(defaultValue = "10")Integer size){ + @RequestParam(defaultValue = "0")Integer page, + @RequestParam(defaultValue = "10")Integer size){ int[] startEnd = PageUtil.transToStartEnd(page+1, size); - return new ResponseEntity(generatorService.getTables(name,startEnd), HttpStatus.OK); + return new ResponseEntity<>(generatorService.getTables(name,startEnd), HttpStatus.OK); } - /** - * 查询表内元数据 - * @param tableName - * @return - */ - @GetMapping(value = "/generator/columns") + @ApiOperation("查询表内元数据") + @GetMapping(value = "/columns") public ResponseEntity getTables(@RequestParam String tableName){ - return new ResponseEntity(generatorService.getColumns(tableName), HttpStatus.OK); + return new ResponseEntity<>(generatorService.getColumns(tableName), HttpStatus.OK); } - /** - * 生成代码 - * @param columnInfos - * @return - */ - @PostMapping(value = "/generator") + @ApiOperation("生成代码") + @PostMapping public ResponseEntity generator(@RequestBody List columnInfos, @RequestParam String tableName){ if(!generatorEnabled){ throw new BadRequestException("此环境不允许生成代码!"); diff --git a/eladmin-generator/src/main/java/me/zhengjie/service/GenConfigService.java b/eladmin-generator/src/main/java/me/zhengjie/service/GenConfigService.java index 34276545..67afbbf5 100644 --- a/eladmin-generator/src/main/java/me/zhengjie/service/GenConfigService.java +++ b/eladmin-generator/src/main/java/me/zhengjie/service/GenConfigService.java @@ -1,30 +1,14 @@ package me.zhengjie.service; 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 * @date 2019-01-14 */ -@CacheConfig(cacheNames = "genConfig") public interface GenConfigService { - /** - * find - * @return - */ - @Cacheable(key = "'1'") GenConfig find(); - /** - * update - * @param genConfig - * @return - */ - @CacheEvict(allEntries = true) GenConfig update(GenConfig genConfig); } diff --git a/eladmin-generator/src/main/java/me/zhengjie/service/GeneratorService.java b/eladmin-generator/src/main/java/me/zhengjie/service/GeneratorService.java index 8b9158a9..7ddb7f1e 100644 --- a/eladmin-generator/src/main/java/me/zhengjie/service/GeneratorService.java +++ b/eladmin-generator/src/main/java/me/zhengjie/service/GeneratorService.java @@ -12,24 +12,24 @@ public interface GeneratorService { /** * 查询数据库元数据 - * @param name - * @param startEnd - * @return + * @param name 表名 + * @param startEnd 分页参数 + * @return / */ Object getTables(String name, int[] startEnd); /** * 得到数据表的元数据 - * @param name - * @return + * @param name 表名 + * @return / */ Object getColumns(String name); /** * 生成代码 - * @param columnInfos - * @param genConfig - * @param tableName + * @param columnInfos 表字段数据 + * @param genConfig 代码生成配置 + * @param tableName 表名 */ void generator(List columnInfos, GenConfig genConfig, String tableName); } diff --git a/eladmin-generator/src/main/java/me/zhengjie/service/impl/GenConfigServiceImpl.java b/eladmin-generator/src/main/java/me/zhengjie/service/impl/GenConfigServiceImpl.java index 165cd5a1..4dfa354c 100644 --- a/eladmin-generator/src/main/java/me/zhengjie/service/impl/GenConfigServiceImpl.java +++ b/eladmin-generator/src/main/java/me/zhengjie/service/impl/GenConfigServiceImpl.java @@ -3,9 +3,10 @@ package me.zhengjie.service.impl; import me.zhengjie.domain.GenConfig; import me.zhengjie.repository.GenConfigRepository; 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 java.io.File; import java.util.Optional; @@ -14,35 +15,37 @@ import java.util.Optional; * @date 2019-01-14 */ @Service +@CacheConfig(cacheNames = "genConfig") public class GenConfigServiceImpl implements GenConfigService { - @Autowired - private GenConfigRepository genConfigRepository; + private final GenConfigRepository genConfigRepository; - @Override - public GenConfig find() { - Optional genConfig = genConfigRepository.findById(1L); - if(genConfig.isPresent()){ - return genConfig.get(); - } else { - return new GenConfig(); - } + public GenConfigServiceImpl(GenConfigRepository genConfigRepository) { + this.genConfigRepository = genConfigRepository; } @Override + @Cacheable(key = "'1'") + public GenConfig find() { + Optional genConfig = genConfigRepository.findById(1L); + return genConfig.orElseGet(GenConfig::new); + } + + @Override + @CacheEvict(allEntries = true) public GenConfig update(GenConfig genConfig) { genConfig.setId(1L); // 自动设置Api路径,注释掉前需要同步取消前端的注释 String separator = File.separator; - String[] paths = null; + String[] paths; if (separator.equals("\\")) { paths = genConfig.getPath().split("\\\\"); } else paths = genConfig.getPath().split(File.separator); - StringBuffer api = new StringBuffer(); - for (int i = 0; i < paths.length; i++) { - api.append(paths[i]); + StringBuilder api = new StringBuilder(); + for (String path : paths) { + api.append(path); api.append(separator); - if(paths[i].equals("src")){ + if (path.equals("src")) { api.append("api"); break; } diff --git a/eladmin-generator/src/main/java/me/zhengjie/service/impl/GeneratorServiceImpl.java b/eladmin-generator/src/main/java/me/zhengjie/service/impl/GeneratorServiceImpl.java index 49e4e1c5..51198e56 100644 --- a/eladmin-generator/src/main/java/me/zhengjie/service/impl/GeneratorServiceImpl.java +++ b/eladmin-generator/src/main/java/me/zhengjie/service/impl/GeneratorServiceImpl.java @@ -28,6 +28,7 @@ public class GeneratorServiceImpl implements GeneratorService { private EntityManager em; @Override + @SuppressWarnings("all") public Object getTables(String name, int[] startEnd) { // 使用预编译防止sql注入 String sql = "select table_name ,create_time , engine, table_collation, table_comment from information_schema.tables " + @@ -37,10 +38,11 @@ public class GeneratorServiceImpl implements GeneratorService { query.setFirstResult(startEnd[0]); query.setMaxResults(startEnd[1]-startEnd[0]); query.setParameter(1, StringUtils.isNotBlank(name) ? ("%" + name + "%") : "%%"); - List result = query.getResultList(); + List result = query.getResultList(); List tableInfos = new ArrayList<>(); - for (Object[] obj : result) { - tableInfos.add(new TableInfo(obj[0],obj[1],obj[2],obj[3], ObjectUtil.isNotEmpty(obj[4])? obj[4] : "-")); + for (Object obj : result) { + Object[] arr = (Object[]) obj; + tableInfos.add(new TableInfo(arr[0],arr[1],arr[2],arr[3], ObjectUtil.isNotEmpty(arr[4])? arr[4] : "-")); } Query query1 = em.createNativeQuery("SELECT COUNT(*) from information_schema.tables where table_schema = (select database())"); Object totalElements = query1.getSingleResult(); @@ -48,16 +50,18 @@ public class GeneratorServiceImpl implements GeneratorService { } @Override + @SuppressWarnings("all") public Object getColumns(String name) { // 使用预编译防止sql注入 String sql = "select column_name, is_nullable, data_type, column_comment, column_key, extra from information_schema.columns " + "where table_name = ? and table_schema = (select database()) order by ordinal_position"; Query query = em.createNativeQuery(sql); query.setParameter(1, StringUtils.isNotBlank(name) ? name : null); - List result = query.getResultList(); + List result = query.getResultList(); List columnInfos = new ArrayList<>(); - for (Object[] obj : result) { - columnInfos.add(new ColumnInfo(obj[0],obj[1],obj[2],obj[3],obj[4],obj[5],null,"true")); + for (Object obj : result) { + Object[] arr = (Object[]) obj; + columnInfos.add(new ColumnInfo(arr[0],arr[1],arr[2],arr[3],arr[4],arr[5],null,"true")); } return PageUtil.toPage(columnInfos,columnInfos.size()); } diff --git a/eladmin-generator/src/main/java/me/zhengjie/utils/ColUtil.java b/eladmin-generator/src/main/java/me/zhengjie/utils/ColUtil.java index 66026d94..9a119f2a 100644 --- a/eladmin-generator/src/main/java/me/zhengjie/utils/ColUtil.java +++ b/eladmin-generator/src/main/java/me/zhengjie/utils/ColUtil.java @@ -12,11 +12,12 @@ public class ColUtil { /** * 转换mysql数据类型为java数据类型 - * @param type - * @return + * @param type 数据库字段类型 + * @return String */ - public static String cloToJava(String type){ + static String cloToJava(String type){ Configuration config = getConfig(); + assert config != null; return config.getString(type,"unknowType"); } diff --git a/eladmin-generator/src/main/java/me/zhengjie/utils/GenUtil.java b/eladmin-generator/src/main/java/me/zhengjie/utils/GenUtil.java index ca198b31..2fb826c5 100644 --- a/eladmin-generator/src/main/java/me/zhengjie/utils/GenUtil.java +++ b/eladmin-generator/src/main/java/me/zhengjie/utils/GenUtil.java @@ -34,9 +34,9 @@ public class GenUtil { /** * 获取后端代码模板名称 - * @return + * @return List */ - public static List getAdminTemplateNames() { + private static List getAdminTemplateNames() { List templateNames = new ArrayList<>(); templateNames.add("Entity"); templateNames.add("Dto"); @@ -51,9 +51,9 @@ public class GenUtil { /** * 获取前端代码模板名称 - * @return + * @return List */ - public static List getFrontTemplateNames() { + private static List getFrontTemplateNames() { List templateNames = new ArrayList<>(); templateNames.add("api"); templateNames.add("index"); @@ -67,7 +67,7 @@ public class GenUtil { * @param genConfig 生成代码的参数配置,如包路径,作者 */ public static void generatorCode(List columnInfos, GenConfig genConfig, String tableName) throws IOException { - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("package",genConfig.getPack()); map.put("moduleName",genConfig.getModuleName()); map.put("author",genConfig.getAuthor()); @@ -85,6 +85,8 @@ public class GenUtil { map.put("upperCaseClassName", className.toUpperCase()); map.put("changeClassName", changeClassName); map.put("hasTimestamp",false); + map.put("queryHasTimestamp",false); + map.put("queryHasBigDecimal",false); map.put("hasBigDecimal",false); map.put("hasQuery",false); map.put("auto",false); @@ -92,7 +94,7 @@ public class GenUtil { List> columns = new ArrayList<>(); List> queryColumns = new ArrayList<>(); for (ColumnInfo column : columnInfos) { - Map listMap = new HashMap(); + Map listMap = new HashMap<>(); listMap.put("columnComment",column.getColumnComment()); listMap.put("columnKey",column.getColumnKey()); @@ -124,6 +126,12 @@ public class GenUtil { if(!StringUtils.isBlank(column.getColumnQuery())){ listMap.put("columnQuery",column.getColumnQuery()); map.put("hasQuery",true); + if(TIMESTAMP.equals(colType)){ + map.put("queryHasTimestamp",true); + } + if(BIGDECIMAL.equals(colType)){ + map.put("queryHasBigDecimal",true); + } queryColumns.add(listMap); } columns.add(listMap); @@ -138,6 +146,7 @@ public class GenUtil { Template template = engine.getTemplate("generator/admin/"+templateName+".ftl"); String filePath = getAdminFilePath(templateName,genConfig,className); + assert filePath != null; File file = new File(filePath); // 如果非覆盖生成 @@ -154,6 +163,7 @@ public class GenUtil { Template template = engine.getTemplate("generator/front/"+templateName+".ftl"); String filePath = getFrontFilePath(templateName,genConfig,map.get("changeClassName").toString()); + assert filePath != null; File file = new File(filePath); // 如果非覆盖生成 @@ -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 packagePath = projectPath + File.separator + "src" +File.separator+ "main" + File.separator + "java" + File.separator; 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(); if ("api".equals(templateName)) { @@ -230,18 +240,17 @@ public class GenUtil { return null; } - public static void genFile(File file,Template template,Map map) throws IOException { + private static void genFile(File file, Template template, Map map) throws IOException { // 生成目标文件 Writer writer = null; try { FileUtil.touch(file); writer = new FileWriter(file); template.render(map, writer); - } catch (TemplateException e) { - throw new RuntimeException(e); - } catch (IOException e) { + } catch (TemplateException | IOException e) { throw new RuntimeException(e); } finally { + assert writer != null; writer.close(); } } diff --git a/eladmin-logging/pom.xml b/eladmin-logging/pom.xml index 84d79abc..bcd9a326 100644 --- a/eladmin-logging/pom.xml +++ b/eladmin-logging/pom.xml @@ -5,7 +5,7 @@ eladmin me.zhengjie - 2.2 + 2.3 4.0.0 @@ -16,7 +16,7 @@ me.zhengjie eladmin-common - 2.2 + 2.3 \ No newline at end of file diff --git a/eladmin-logging/src/main/java/me/zhengjie/aspect/LogAspect.java b/eladmin-logging/src/main/java/me/zhengjie/aspect/LogAspect.java index 1fbf7cfa..a212ddf4 100644 --- a/eladmin-logging/src/main/java/me/zhengjie/aspect/LogAspect.java +++ b/eladmin-logging/src/main/java/me/zhengjie/aspect/LogAspect.java @@ -2,7 +2,6 @@ package me.zhengjie.aspect; import lombok.extern.slf4j.Slf4j; import me.zhengjie.domain.Log; -import me.zhengjie.exception.BadRequestException; import me.zhengjie.service.LogService; import me.zhengjie.utils.RequestHolder; 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.Aspect; import org.aspectj.lang.annotation.Pointcut; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @@ -28,11 +26,14 @@ import javax.servlet.http.HttpServletRequest; @Slf4j public class LogAspect { - @Autowired - private LogService logService; + private final LogService logService; private long currentTime = 0L; + public LogAspect(LogService logService) { + this.logService = logService; + } + /** * 配置切入点 */ @@ -48,11 +49,12 @@ public class LogAspect { */ @Around("logPointcut()") public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { - Object result = null; + Object result; currentTime = System.currentTimeMillis(); result = joinPoint.proceed(); 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; } @@ -66,7 +68,8 @@ public class LogAspect { public void logAfterThrowing(JoinPoint joinPoint, Throwable e) { Log log = new Log("ERROR",System.currentTimeMillis() - currentTime); 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() { diff --git a/eladmin-logging/src/main/java/me/zhengjie/domain/Log.java b/eladmin-logging/src/main/java/me/zhengjie/domain/Log.java index a7146c01..a977fee9 100644 --- a/eladmin-logging/src/main/java/me/zhengjie/domain/Log.java +++ b/eladmin-logging/src/main/java/me/zhengjie/domain/Log.java @@ -21,56 +21,40 @@ public class Log implements Serializable { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - /** - * 操作用户 - */ + // 操作用户 private String username; - /** - * 描述 - */ + // 描述 private String description; - /** - * 方法名 - */ + // 方法名 private String method; - /** - * 参数 - */ + // 参数 @Column(columnDefinition = "text") private String params; - /** - * 日志类型 - */ + // 日志类型 @Column(name = "log_type") private String logType; - /** - * 请求ip - */ + // 请求ip @Column(name = "request_ip") private String requestIp; @Column(name = "address") private String address; - /** - * 请求耗时 - */ + private String browser; + + // 请求耗时 private Long time; - /** - * 异常详细 - */ + // 异常详细 @Column(name = "exception_detail", columnDefinition = "text") private byte[] exceptionDetail; - /** - * 创建日期 - */ + // 创建日期 @CreationTimestamp @Column(name = "create_time") private Timestamp createTime; diff --git a/eladmin-logging/src/main/java/me/zhengjie/repository/LogRepository.java b/eladmin-logging/src/main/java/me/zhengjie/repository/LogRepository.java index e557f8c6..903386e3 100644 --- a/eladmin-logging/src/main/java/me/zhengjie/repository/LogRepository.java +++ b/eladmin-logging/src/main/java/me/zhengjie/repository/LogRepository.java @@ -11,22 +11,14 @@ import org.springframework.stereotype.Repository; * @date 2018-11-24 */ @Repository -public interface LogRepository extends JpaRepository, JpaSpecificationExecutor { +public interface LogRepository extends JpaRepository, JpaSpecificationExecutor { /** * 获取一个时间段的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) Long findIp(String date1, String date2); - /** - * findExceptionById - * @param id - * @return - */ - @Query(value = "select exception_detail FROM log where id = ?1",nativeQuery = true) - String findExceptionById(Long id); + @Query(value = "select l FROM Log l where l.id = ?1") + Log findExceptionById(Long id); } diff --git a/eladmin-logging/src/main/java/me/zhengjie/rest/LogController.java b/eladmin-logging/src/main/java/me/zhengjie/rest/LogController.java index 051c071d..4f8f9fb9 100644 --- a/eladmin-logging/src/main/java/me/zhengjie/rest/LogController.java +++ b/eladmin-logging/src/main/java/me/zhengjie/rest/LogController.java @@ -1,9 +1,11 @@ package me.zhengjie.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import me.zhengjie.aop.log.Log; import me.zhengjie.service.LogService; import me.zhengjie.service.dto.LogQueryCriteria; import me.zhengjie.utils.SecurityUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; 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.RestController; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + /** * @author Zheng Jie * @date 2018-11-24 */ @RestController -@RequestMapping("api") +@RequestMapping("/api/logs") +@Api(tags = "监控:日志管理") public class LogController { - @Autowired - private LogService logService; + private final LogService logService; - @GetMapping(value = "/logs") - @PreAuthorize("hasAnyRole('ADMIN')") - public ResponseEntity getLogs(LogQueryCriteria criteria, Pageable pageable){ - criteria.setLogType("INFO"); - return new ResponseEntity(logService.queryAll(criteria,pageable), HttpStatus.OK); + public LogController(LogService logService) { + this.logService = logService; } - @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){ criteria.setLogType("INFO"); 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") - @PreAuthorize("hasAnyRole('ADMIN')") + @GetMapping(value = "/error") + @ApiOperation("错误日志查询") + @PreAuthorize("@el.check()") public ResponseEntity getErrorLogs(LogQueryCriteria criteria, Pageable pageable){ criteria.setLogType("ERROR"); - return new ResponseEntity(logService.queryAll(criteria,pageable), HttpStatus.OK); + return new ResponseEntity<>(logService.queryAll(criteria,pageable), HttpStatus.OK); } - @GetMapping(value = "/logs/error/{id}") - @PreAuthorize("hasAnyRole('ADMIN')") + @GetMapping(value = "/error/{id}") + @ApiOperation("日志异常详情查询") + @PreAuthorize("@el.check()") public ResponseEntity getErrorLogs(@PathVariable Long id){ - return new ResponseEntity(logService.findByErrDetail(id), HttpStatus.OK); + return new ResponseEntity<>(logService.findByErrDetail(id), HttpStatus.OK); } } diff --git a/eladmin-logging/src/main/java/me/zhengjie/service/LogService.java b/eladmin-logging/src/main/java/me/zhengjie/service/LogService.java index 3eb69de9..166da508 100644 --- a/eladmin-logging/src/main/java/me/zhengjie/service/LogService.java +++ b/eladmin-logging/src/main/java/me/zhengjie/service/LogService.java @@ -6,42 +6,31 @@ import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.data.domain.Pageable; import org.springframework.scheduling.annotation.Async; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; + /** * @author Zheng Jie * @date 2018-11-24 */ public interface LogService { - /** - * queryAll - * @param criteria - * @param pageable - * @return - */ Object queryAll(LogQueryCriteria criteria, Pageable pageable); - /** - * queryAllByUser - * @param criteria - * @param pageable - * @return - */ + List queryAll(LogQueryCriteria criteria); + Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable); - /** - * 新增日志 - * @param username - * @param ip - * @param joinPoint - * @param log - */ @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 - * @return + * @param id 日志ID + * @return Object */ Object findByErrDetail(Long id); + + void download(List queryAll, HttpServletResponse response) throws IOException; } diff --git a/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogErrorDTO.java b/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogErrorDTO.java index f23ae95f..1548ef00 100644 --- a/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogErrorDTO.java +++ b/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogErrorDTO.java @@ -13,36 +13,26 @@ public class LogErrorDTO implements Serializable { private Long id; - /** - * 操作用户 - */ + // 操作用户 private String username; - /** - * 描述 - */ + // 描述 private String description; - /** - * 方法名 - */ + // 方法名 private String method; - /** - * 参数 - */ + // 参数 private String params; - /** - * 请求ip - */ + private String browser; + + // 请求ip private String requestIp; private String address; - /** - * 创建日期 - */ + // 创建日期 private Timestamp createTime; } \ No newline at end of file diff --git a/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogQueryCriteria.java b/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogQueryCriteria.java index 6b52cc77..bc1499a7 100644 --- a/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogQueryCriteria.java +++ b/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogQueryCriteria.java @@ -3,6 +3,8 @@ package me.zhengjie.service.dto; import lombok.Data; import me.zhengjie.annotation.Query; +import java.sql.Timestamp; + /** * 日志查询类 * @author Zheng Jie @@ -17,4 +19,10 @@ public class LogQueryCriteria { @Query private String logType; + + @Query(type = Query.Type.GREATER_THAN,propName = "createTime") + private Timestamp startTime; + + @Query(type = Query.Type.LESS_THAN,propName = "createTime") + private Timestamp endTime; } diff --git a/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogSmallDTO.java b/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogSmallDTO.java index 33b6abfd..22e41fb2 100644 --- a/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogSmallDTO.java +++ b/eladmin-logging/src/main/java/me/zhengjie/service/dto/LogSmallDTO.java @@ -1,7 +1,6 @@ package me.zhengjie.service.dto; import lombok.Data; - import java.io.Serializable; import java.sql.Timestamp; @@ -12,25 +11,19 @@ import java.sql.Timestamp; @Data public class LogSmallDTO implements Serializable { - /** - * 描述 - */ + // 描述 private String description; - /** - * 请求ip - */ + // 请求ip private String requestIp; - /** - * 请求耗时 - */ + // 请求耗时 private Long time; private String address; - /** - * 创建日期 - */ + private String browser; + + // 创建日期 private Timestamp createTime; } diff --git a/eladmin-logging/src/main/java/me/zhengjie/service/impl/LogServiceImpl.java b/eladmin-logging/src/main/java/me/zhengjie/service/impl/LogServiceImpl.java index 4d39206f..8eb59092 100644 --- a/eladmin-logging/src/main/java/me/zhengjie/service/impl/LogServiceImpl.java +++ b/eladmin-logging/src/main/java/me/zhengjie/service/impl/LogServiceImpl.java @@ -1,6 +1,7 @@ package me.zhengjie.service.impl; import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONObject; import me.zhengjie.domain.Log; import me.zhengjie.repository.LogRepository; @@ -8,18 +9,25 @@ import me.zhengjie.service.LogService; import me.zhengjie.service.dto.LogQueryCriteria; import me.zhengjie.service.mapper.LogErrorMapper; import me.zhengjie.service.mapper.LogSmallMapper; +import me.zhengjie.utils.FileUtil; import me.zhengjie.utils.PageUtil; import me.zhengjie.utils.QueryHelp; import me.zhengjie.utils.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; /** * @author Zheng Jie @@ -29,16 +37,17 @@ import java.lang.reflect.Method; @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class LogServiceImpl implements LogService { - @Autowired - private LogRepository logRepository; + private final LogRepository logRepository; - @Autowired - private LogErrorMapper logErrorMapper; + private final LogErrorMapper logErrorMapper; - @Autowired - private LogSmallMapper logSmallMapper; + private final 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 public Object queryAll(LogQueryCriteria criteria, Pageable pageable){ @@ -49,6 +58,11 @@ public class LogServiceImpl implements LogService { return page; } + @Override + public List queryAll(LogQueryCriteria criteria) { + return logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb))); + } + @Override public Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable) { Page page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)),pageable); @@ -57,38 +71,37 @@ public class LogServiceImpl implements LogService { @Override @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(); Method method = signature.getMethod(); 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 params = "{"; + StringBuilder params = new StringBuilder("{"); //参数值 Object[] argValues = joinPoint.getArgs(); //参数名称 String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames(); if(argValues != null){ for (int i = 0; i < argValues.length; i++) { - params += " " + 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); + String LOGINPATH = "login"; if(LOGINPATH.equals(signature.getName())){ try { - JSONObject jsonObject = new JSONObject(argValues[0]); - username = jsonObject.get("username").toString(); + assert argValues != null; + username = new JSONObject(argValues[0]).get("username").toString(); }catch (Exception e){ e.printStackTrace(); } @@ -96,12 +109,32 @@ public class LogServiceImpl implements LogService { log.setAddress(StringUtils.getCityInfo(log.getRequestIp())); log.setMethod(methodName); log.setUsername(username); - log.setParams(params + " }"); + log.setParams(params.toString() + " }"); + log.setBrowser(browser); logRepository.save(log); } @Override 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 logs, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (Log log : logs) { + Map 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); } } diff --git a/eladmin-logging/src/main/java/me/zhengjie/service/mapper/LogErrorMapper.java b/eladmin-logging/src/main/java/me/zhengjie/service/mapper/LogErrorMapper.java index a2fc4b87..8e033ac1 100644 --- a/eladmin-logging/src/main/java/me/zhengjie/service/mapper/LogErrorMapper.java +++ b/eladmin-logging/src/main/java/me/zhengjie/service/mapper/LogErrorMapper.java @@ -1,7 +1,7 @@ package me.zhengjie.service.mapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.domain.Log; -import me.zhengjie.mapper.EntityMapper; import me.zhengjie.service.dto.LogErrorDTO; import org.mapstruct.Mapper; import org.mapstruct.ReportingPolicy; @@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy; * @author Zheng Jie * @date 2019-5-22 */ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface LogErrorMapper extends EntityMapper { +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface LogErrorMapper extends BaseMapper { } \ No newline at end of file diff --git a/eladmin-logging/src/main/java/me/zhengjie/service/mapper/LogSmallMapper.java b/eladmin-logging/src/main/java/me/zhengjie/service/mapper/LogSmallMapper.java index 8c6d2c63..630be522 100644 --- a/eladmin-logging/src/main/java/me/zhengjie/service/mapper/LogSmallMapper.java +++ b/eladmin-logging/src/main/java/me/zhengjie/service/mapper/LogSmallMapper.java @@ -1,7 +1,7 @@ package me.zhengjie.service.mapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.domain.Log; -import me.zhengjie.mapper.EntityMapper; import me.zhengjie.service.dto.LogSmallDTO; import org.mapstruct.Mapper; import org.mapstruct.ReportingPolicy; @@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy; * @author Zheng Jie * @date 2019-5-22 */ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface LogSmallMapper extends EntityMapper { +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface LogSmallMapper extends BaseMapper { } \ No newline at end of file diff --git a/eladmin-system/pom.xml b/eladmin-system/pom.xml index fbc1e007..b224e0cd 100644 --- a/eladmin-system/pom.xml +++ b/eladmin-system/pom.xml @@ -5,7 +5,7 @@ eladmin me.zhengjie - 2.2 + 2.3 4.0.0 @@ -20,7 +20,7 @@ me.zhengjie eladmin-generator - 2.2 + 2.3 me.zhengjie @@ -32,7 +32,7 @@ me.zhengjie eladmin-tools - 2.2 + 2.3 diff --git a/eladmin-system/src/main/java/me/zhengjie/config/DataScope.java b/eladmin-system/src/main/java/me/zhengjie/config/DataScope.java index 0ae0ff07..13daa454 100644 --- a/eladmin-system/src/main/java/me/zhengjie/config/DataScope.java +++ b/eladmin-system/src/main/java/me/zhengjie/config/DataScope.java @@ -25,14 +25,17 @@ public class DataScope { private final String[] scopeType = {"全部","本级","自定义"}; - @Autowired - private UserService userService; + private final UserService userService; - @Autowired - private RoleService roleService; + private final RoleService roleService; - @Autowired - private DeptService deptService; + private final DeptService deptService; + + public DataScope(UserService userService, RoleService roleService, DeptService deptService) { + this.userService = userService; + this.roleService = roleService; + this.deptService = deptService; + } public Set getDeptIds() { @@ -76,7 +79,7 @@ public class DataScope { deptList.forEach(dept -> { if (dept!=null && dept.getEnabled()){ List depts = deptService.findByPid(dept.getId()); - if(deptList!=null && deptList.size()!=0){ + if(deptList.size() != 0){ list.addAll(getDeptChildren(depts)); } list.add(dept.getId()); diff --git a/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskExecutePool.java b/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskExecutePool.java new file mode 100644 index 00000000..105aad45 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskExecutePool.java @@ -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()); + }; + } +} diff --git a/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskProperties.java b/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskProperties.java new file mode 100644 index 00000000..f836fa09 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskProperties.java @@ -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; +} diff --git a/eladmin-system/src/main/java/me/zhengjie/config/thread/TheadFactoryName.java b/eladmin-system/src/main/java/me/zhengjie/config/thread/TheadFactoryName.java new file mode 100644 index 00000000..d5cb656c --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/config/thread/TheadFactoryName.java @@ -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; + } +} diff --git a/eladmin-system/src/main/java/me/zhengjie/config/thread/ThreadPoolExecutorUtil.java b/eladmin-system/src/main/java/me/zhengjie/config/thread/ThreadPoolExecutorUtil.java new file mode 100644 index 00000000..92627465 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/config/thread/ThreadPoolExecutorUtil.java @@ -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() + ); + } +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/config/VisitsInitialization.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/config/VisitsInitialization.java index f44d72ad..f27e32e3 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/config/VisitsInitialization.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/config/VisitsInitialization.java @@ -1,7 +1,6 @@ package me.zhengjie.modules.monitor.config; import me.zhengjie.modules.monitor.service.VisitsService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; @@ -13,11 +12,14 @@ import org.springframework.stereotype.Component; @Component public class VisitsInitialization implements ApplicationRunner { - @Autowired - private VisitsService visitsService; + private final VisitsService visitsService; + + public VisitsInitialization(VisitsService visitsService) { + this.visitsService = visitsService; + } @Override - public void run(ApplicationArguments args) throws Exception { + public void run(ApplicationArguments args){ System.out.println("--------------- 初始化站点统计,如果存在今日统计则跳过 ---------------"); visitsService.save(); System.out.println("--------------- 初始化站点统计完成 ---------------"); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/domain/Visits.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/domain/Visits.java index 8784121d..7072fedf 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/domain/Visits.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/domain/Visits.java @@ -4,6 +4,7 @@ import lombok.Data; import org.hibernate.annotations.CreationTimestamp; import javax.persistence.*; +import java.io.Serializable; import java.sql.Timestamp; /** @@ -15,7 +16,7 @@ import java.sql.Timestamp; @Entity @Data @Table(name = "visits") -public class Visits { +public class Visits implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/repository/VisitsRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/repository/VisitsRepository.java index 7a41c8f9..8c13338f 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/repository/VisitsRepository.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/repository/VisitsRepository.java @@ -4,7 +4,6 @@ import me.zhengjie.modules.monitor.domain.Visits; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; - import java.util.List; /** @@ -16,18 +15,17 @@ public interface VisitsRepository extends JpaRepository { /** * findByDate - * @param date - * @return + * @param date 日期 + * @return Visits */ Visits findByDate(String date); /** * 获得一个时间段的记录 - * @param date1 - * @param date2 - * @return + * @param date1 日期1 + * @param date2 日期2 + * @return List */ - @Query(value = "select * FROM visits where " + - "create_time between ?1 and ?2",nativeQuery = true) + @Query(value = "select * FROM visits where create_time between ?1 and ?2",nativeQuery = true) List findAllVisits(String date1, String date2); } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/LimitController.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/LimitController.java index 3a742cac..3e369061 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/LimitController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/LimitController.java @@ -1,6 +1,10 @@ package me.zhengjie.modules.monitor.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import me.zhengjie.annotation.AnonymousAccess; import me.zhengjie.annotation.Limit; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -12,15 +16,19 @@ import java.util.concurrent.atomic.AtomicInteger; * 接口限流测试类 */ @RestController -@RequestMapping("api") +@RequestMapping("/api/limit") +@Api(tags = "系统:限流测试管理") public class LimitController { + private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger(); /** * 测试限流注解,下面配置说明该接口 60秒内最多只能访问 10次,保存到redis的键名为 limit_test, */ + @GetMapping + @PreAuthorize("@el.check('anonymous')") + @ApiOperation("测试") @Limit(key = "test", period = 60, count = 10, name = "testLimit", prefix = "limit") - @GetMapping("/limit") public int testLimit() { return ATOMIC_INTEGER.incrementAndGet(); } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/RedisController.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/RedisController.java index f1cca13c..11967500 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/RedisController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/RedisController.java @@ -1,47 +1,65 @@ package me.zhengjie.modules.monitor.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import me.zhengjie.aop.log.Log; import me.zhengjie.modules.monitor.domain.vo.RedisVo; import me.zhengjie.modules.monitor.service.RedisService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + /** * @author Zheng Jie * @date 2018-12-10 */ @RestController -@RequestMapping("api") +@RequestMapping("/api/redis") +@Api(tags = "系统:Redis缓存管理") public class RedisController { - @Autowired - private RedisService redisService; + private final RedisService redisService; + + public RedisController(RedisService redisService) { + this.redisService = redisService; + } @Log("查询Redis缓存") - @GetMapping(value = "/redis") - @PreAuthorize("hasAnyRole('ADMIN','REDIS_ALL','REDIS_SELECT')") + @GetMapping + @ApiOperation("查询Redis缓存") + @PreAuthorize("@el.check('redis:list')") 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缓存") - @DeleteMapping(value = "/redis") - @PreAuthorize("hasAnyRole('ADMIN','REDIS_ALL','REDIS_DELETE')") + @DeleteMapping + @ApiOperation("删除Redis缓存") + @PreAuthorize("@el.check('redis:del')") public ResponseEntity delete(@RequestBody RedisVo resources){ redisService.delete(resources.getKey()); return new ResponseEntity(HttpStatus.OK); } @Log("清空Redis缓存") - @DeleteMapping(value = "/redis/all") - @PreAuthorize("hasAnyRole('ADMIN','REDIS_ALL','REDIS_DELETE')") + @DeleteMapping(value = "/all") + @ApiOperation("清空Redis缓存") + @PreAuthorize("@el.check('redis:del')") public ResponseEntity deleteAll(){ - redisService.flushdb(); + redisService.deleteAll(); return new ResponseEntity(HttpStatus.OK); } } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/VisitsController.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/VisitsController.java index bd73228f..077ee3d4 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/VisitsController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/rest/VisitsController.java @@ -1,8 +1,9 @@ package me.zhengjie.modules.monitor.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import me.zhengjie.modules.monitor.service.VisitsService; import me.zhengjie.utils.RequestHolder; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -15,25 +16,32 @@ import org.springframework.web.bind.annotation.RestController; * @date 2018-12-13 */ @RestController -@RequestMapping("api") +@RequestMapping("/api/visits") +@Api(tags = "系统:访问记录管理") public class VisitsController { - @Autowired - private VisitsService visitsService; + private final VisitsService visitsService; - @PostMapping(value = "/visits") + public VisitsController(VisitsService visitsService) { + this.visitsService = visitsService; + } + + @PostMapping + @ApiOperation("创建访问记录") public ResponseEntity create(){ visitsService.count(RequestHolder.getHttpServletRequest()); return new ResponseEntity(HttpStatus.CREATED); } - @GetMapping(value = "/visits") + @GetMapping + @ApiOperation("查询") 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(){ - return new ResponseEntity(visitsService.getChartData(),HttpStatus.OK); + return new ResponseEntity<>(visitsService.getChartData(),HttpStatus.OK); } } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/RedisService.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/RedisService.java index c31d05c3..47cc977b 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/RedisService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/RedisService.java @@ -4,6 +4,10 @@ import me.zhengjie.modules.monitor.domain.vo.RedisVo; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; + /** * 可自行扩展 * @author Zheng Jie @@ -13,33 +17,47 @@ public interface RedisService { /** * findById - * @param key - * @return + * @param key 键 + * @return / */ Page findByKey(String key, Pageable pageable); + /** + * findById + * @param key 键 + * @return / + */ + List findByKey(String key); + /** * 查询验证码的值 - * @param key - * @return + * @param key 键 + * @return / */ String getCodeVal(String key); /** * 保存验证码 - * @param key - * @param val + * @param key 键 + * @param val 值 */ void saveCode(String key, Object val); /** * delete - * @param key + * @param key 键 */ void delete(String key); /** - * 清空所有缓存 + * 清空缓存 */ - void flushdb(); + void deleteAll(); + + /** + * + * @param redisVos / + * @param response / + */ + void download(List redisVos, HttpServletResponse response) throws IOException; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/VisitsService.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/VisitsService.java index 2f80df2c..a403b089 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/VisitsService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/VisitsService.java @@ -1,7 +1,6 @@ package me.zhengjie.modules.monitor.service; import org.springframework.scheduling.annotation.Async; - import javax.servlet.http.HttpServletRequest; /** @@ -17,20 +16,20 @@ public interface VisitsService { /** * 新增记录 - * @param request + * @param request / */ @Async void count(HttpServletRequest request); /** * 获取数据 - * @return + * @return / */ Object get(); /** * getChartData - * @return + * @return / */ Object getChartData(); } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/impl/RedisServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/impl/RedisServiceImpl.java index 249f1472..52dfe488 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/impl/RedisServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/impl/RedisServiceImpl.java @@ -1,51 +1,71 @@ package me.zhengjie.modules.monitor.service.impl; +import cn.hutool.core.util.ObjectUtil; import me.zhengjie.modules.monitor.domain.vo.RedisVo; import me.zhengjie.modules.monitor.service.RedisService; +import me.zhengjie.utils.FileUtil; import me.zhengjie.utils.PageUtil; -import org.springframework.beans.factory.annotation.Autowired; 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 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.stream.Collectors; /** * @author Zheng Jie * @date 2018-12-10 */ @Service +@SuppressWarnings({"unchecked","all"}) public class RedisServiceImpl implements RedisService { - @Autowired - RedisTemplate redisTemplate; + private final RedisTemplate redisTemplate; @Value("${loginCode.expiration}") private Long expiration; + @Value("${jwt.online}") + private String onlineKey; + + @Value("${jwt.codeKey}") + private String codeKey; + + public RedisServiceImpl(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + @Override public Page findByKey(String key, Pageable pageable){ + List redisVos = findByKey(key); + return new PageImpl( + PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(),redisVos), + pageable, + redisVos.size()); + } + + @Override + public List findByKey(String key) { List redisVos = new ArrayList<>(); if(!"*".equals(key)){ key = "*" + key + "*"; } - for (Object s : redisTemplate.keys(key)) { + Set 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; } - 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); } - Page page = new PageImpl( - PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(),redisVos), - pageable, - redisVos.size()); - return page; + return redisVos; } @Override @@ -54,15 +74,15 @@ public class RedisServiceImpl implements RedisService { } @Override - public void flushdb() { - redisTemplate.getConnectionFactory().getConnection().flushDb(); + public void deleteAll() { + Set keys = redisTemplate.keys( "*"); + redisTemplate.delete(keys.stream().filter(s -> !s.contains(onlineKey)).filter(s -> !s.contains(codeKey)).collect(Collectors.toList())); } @Override public String getCodeVal(String key) { try { - String value = redisTemplate.opsForValue().get(key).toString(); - return value; + return Objects.requireNonNull(redisTemplate.opsForValue().get(key)).toString(); }catch (Exception e){ return ""; } @@ -73,4 +93,16 @@ public class RedisServiceImpl implements RedisService { redisTemplate.opsForValue().set(key,val); redisTemplate.expire(key,expiration, TimeUnit.MINUTES); } + + @Override + public void download(List redisVos, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (RedisVo redisVo : redisVos) { + Map map = new LinkedHashMap<>(); + map.put("key", redisVo.getKey()); + map.put("value", redisVo.getValue()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/impl/VisitsServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/impl/VisitsServiceImpl.java index fa00b02d..ebf93bb5 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/impl/VisitsServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/monitor/service/impl/VisitsServiceImpl.java @@ -26,11 +26,14 @@ import java.util.stream.Collectors; @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class VisitsServiceImpl implements VisitsService { - @Autowired - private VisitsRepository visitsRepository; + private final VisitsRepository visitsRepository; - @Autowired - private LogRepository logRepository; + private final LogRepository logRepository; + + public VisitsServiceImpl(VisitsRepository visitsRepository, LogRepository logRepository) { + this.visitsRepository = visitsRepository; + this.logRepository = logRepository; + } @Override public void save() { @@ -58,7 +61,7 @@ public class VisitsServiceImpl implements VisitsService { @Override public Object get() { - Map map = new HashMap(); + Map map = new HashMap<>(); LocalDate localDate = LocalDate.now(); Visits visits = visitsRepository.findByDate(localDate.toString()); List list = visitsRepository.findAllVisits(localDate.minusDays(6).toString(),localDate.plusDays(1).toString()); @@ -77,7 +80,7 @@ public class VisitsServiceImpl implements VisitsService { @Override public Object getChartData() { - Map map = new HashMap(); + Map map = new HashMap<>(); LocalDate localDate = LocalDate.now(); List list = visitsRepository.findAllVisits(localDate.minusDays(6).toString(),localDate.plusDays(1).toString()); map.put("weekDays",list.stream().map(Visits::getWeekDay).collect(Collectors.toList())); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/config/JobRunner.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/config/JobRunner.java index a66ec06e..557df43c 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/config/JobRunner.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/config/JobRunner.java @@ -3,7 +3,6 @@ package me.zhengjie.modules.quartz.config; import me.zhengjie.modules.quartz.domain.QuartzJob; import me.zhengjie.modules.quartz.repository.QuartzJobRepository; import me.zhengjie.modules.quartz.utils.QuartzManage; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; @@ -17,24 +16,24 @@ import java.util.List; @Component public class JobRunner implements ApplicationRunner { - @Autowired - private QuartzJobRepository quartzJobRepository; + private final QuartzJobRepository quartzJobRepository; - @Autowired - private QuartzManage quartzManage; + private final QuartzManage quartzManage; + + public JobRunner(QuartzJobRepository quartzJobRepository, QuartzManage quartzManage) { + this.quartzJobRepository = quartzJobRepository; + this.quartzManage = quartzManage; + } /** * 项目启动时重新激活启用的定时任务 - * @param applicationArguments - * @throws Exception + * @param applicationArguments / */ @Override public void run(ApplicationArguments applicationArguments){ System.out.println("--------------------注入定时任务---------------------"); List quartzJobs = quartzJobRepository.findByIsPauseIsFalse(); - quartzJobs.forEach(quartzJob -> { - quartzManage.addJob(quartzJob); - }); + quartzJobs.forEach(quartzManage::addJob); System.out.println("--------------------定时任务注入完成---------------------"); } } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/config/QuartzConfig.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/config/QuartzConfig.java index 3486ad81..085534ab 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/config/QuartzConfig.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/config/QuartzConfig.java @@ -2,7 +2,6 @@ package me.zhengjie.modules.quartz.config; import org.quartz.Scheduler; import org.quartz.spi.TriggerFiredBundle; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -12,7 +11,7 @@ import org.springframework.stereotype.Component; /** * 定时任务配置 - * @author + * @author / * @date 2019-01-07 */ @Configuration @@ -22,10 +21,13 @@ public class QuartzConfig { * 解决Job中注入Spring Bean为null的问题 */ @Component("quartzJobFactory") - public class QuartzJobFactory extends AdaptableJobFactory { + public static class QuartzJobFactory extends AdaptableJobFactory { - @Autowired - private AutowireCapableBeanFactory capableBeanFactory; + private final AutowireCapableBeanFactory capableBeanFactory; + + public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) { + this.capableBeanFactory = capableBeanFactory; + } @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { @@ -39,9 +41,9 @@ public class QuartzConfig { /** * 注入scheduler到spring - * @param quartzJobFactory - * @return - * @throws Exception + * @param quartzJobFactory / + * @return Scheduler + * @throws Exception / */ @Bean(name = "scheduler") public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception { diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzJob.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzJob.java index 65692d07..a93f6dce 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzJob.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzJob.java @@ -1,8 +1,8 @@ package me.zhengjie.modules.quartz.domain; -import lombok.Data; -import org.hibernate.annotations.UpdateTimestamp; - +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; import javax.persistence.*; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @@ -13,10 +13,11 @@ import java.sql.Timestamp; * @author Zheng Jie * @date 2019-01-07 */ -@Data +@Getter +@Setter @Entity @Table(name = "quartz_job") -public class QuartzJob implements Serializable { +public class QuartzJob implements Serializable { public static final String JOB_KEY = "JOB_KEY"; @@ -25,58 +26,41 @@ public class QuartzJob implements Serializable { @NotNull(groups = {Update.class}) private Long id; - /** - * 定时器名称 - */ + // 定时器名称 @Column(name = "job_name") private String jobName; - /** - * Bean名称 - */ + // Bean名称 @Column(name = "bean_name") @NotBlank private String beanName; - /** - * 方法名称 - */ + // 方法名称 @Column(name = "method_name") @NotBlank private String methodName; - /** - * 参数 - */ + // 参数 @Column(name = "params") private String params; - /** - * cron表达式 - */ + // cron表达式 @Column(name = "cron_expression") @NotBlank private String cronExpression; - /** - * 状态 - */ + // 状态 @Column(name = "is_pause") private Boolean isPause = false; - /** - * 备注 - */ + // 备注 @Column(name = "remark") @NotBlank private String remark; - /** - * 创建日期 - */ - @UpdateTimestamp - @Column(name = "update_time") - private Timestamp updateTime; + @Column(name = "create_time") + @CreationTimestamp + private Timestamp createTime; - public interface Update{} + public @interface Update {} } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzLog.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzLog.java index 9bd347a6..9958ce6c 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzLog.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzLog.java @@ -20,56 +20,38 @@ public class QuartzLog implements Serializable { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - /** - * 任务名称 - */ + // 任务名称 @Column(name = "job_name") private String jobName; - /** - * Bean名称 - */ + // Bean名称 @Column(name = "baen_name") private String beanName; - /** - * 方法名称 - */ + // 方法名称 @Column(name = "method_name") private String methodName; - /** - * 参数 - */ + // 参数 @Column(name = "params") private String params; - /** - * cron表达式 - */ + // cron表达式 @Column(name = "cron_expression") private String cronExpression; - /** - * 状态 - */ + // 状态 @Column(name = "is_success") private Boolean isSuccess; - /** - * 异常详细 - */ + // 异常详细 @Column(name = "exception_detail",columnDefinition = "text") private String exceptionDetail; - /** - * 耗时(毫秒) - */ + // 耗时(毫秒) private Long time; - /** - * 创建日期 - */ + // 创建日期 @CreationTimestamp @Column(name = "create_time") private Timestamp createTime; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzJobRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzJobRepository.java index 087f0617..e4143f9d 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzJobRepository.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzJobRepository.java @@ -9,11 +9,11 @@ import java.util.List; * @author Zheng Jie * @date 2019-01-07 */ -public interface QuartzJobRepository extends JpaRepository, JpaSpecificationExecutor { +public interface QuartzJobRepository extends JpaRepository, JpaSpecificationExecutor { /** * 查询启用的任务 - * @return + * @return List */ List findByIsPauseIsFalse(); } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzLogRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzLogRepository.java index 6b78d460..f0722a82 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzLogRepository.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzLogRepository.java @@ -8,6 +8,6 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; * @author Zheng Jie * @date 2019-01-07 */ -public interface QuartzLogRepository extends JpaRepository, JpaSpecificationExecutor { +public interface QuartzLogRepository extends JpaRepository, JpaSpecificationExecutor { } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/rest/QuartzJobController.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/rest/QuartzJobController.java index 1a604930..518f7b0c 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/rest/QuartzJobController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/rest/QuartzJobController.java @@ -1,12 +1,13 @@ package me.zhengjie.modules.quartz.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import me.zhengjie.aop.log.Log; import me.zhengjie.exception.BadRequestException; import me.zhengjie.modules.quartz.domain.QuartzJob; import me.zhengjie.modules.quartz.service.QuartzJobService; import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; 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.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + /** * @author Zheng Jie * @date 2019-01-07 */ @Slf4j @RestController -@RequestMapping("/api") +@Api(tags = "系统:定时任务管理") +@RequestMapping("/api/jobs") public class QuartzJobController { private static final String ENTITY_NAME = "quartzJob"; - @Autowired - private QuartzJobService quartzJobService; + private final QuartzJobService quartzJobService; - @Log("查询定时任务") - @GetMapping(value = "/jobs") - @PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_SELECT')") - public ResponseEntity getJobs(JobQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity(quartzJobService.queryAll(criteria,pageable), HttpStatus.OK); + public QuartzJobController(QuartzJobService quartzJobService) { + this.quartzJobService = quartzJobService; } - @GetMapping(value = "/jobLogs") - @PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_SELECT')") + @Log("查询定时任务") + @ApiOperation("查询定时任务") + @GetMapping + @PreAuthorize("@el.check('timing:list')") + public ResponseEntity getJobs(JobQueryCriteria criteria, Pageable pageable){ + return new ResponseEntity<>(quartzJobService.queryAll(criteria,pageable), HttpStatus.OK); + } + + @Log("导出任务数据") + @ApiOperation("导出任务数据") + @GetMapping(value = "/download") + @PreAuthorize("@el.check('timing:list')") + public void download(HttpServletResponse response, JobQueryCriteria criteria) throws IOException { + quartzJobService.download(quartzJobService.queryAll(criteria), response); + } + + @Log("导出日志数据") + @ApiOperation("导出日志数据") + @GetMapping(value = "/download/log") + @PreAuthorize("@el.check('timing:list')") + public void downloadLog(HttpServletResponse response, JobQueryCriteria criteria) throws IOException { + quartzJobService.downloadLog(quartzJobService.queryAllLog(criteria), response); + } + + @ApiOperation("查询任务执行日志") + @GetMapping(value = "/logs") + @PreAuthorize("@el.check('timing:list')") public ResponseEntity getJobLogs(JobQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity(quartzJobService.queryAllLog(criteria,pageable), HttpStatus.OK); + return new ResponseEntity<>(quartzJobService.queryAllLog(criteria,pageable), HttpStatus.OK); } @Log("新增定时任务") - @PostMapping(value = "/jobs") - @PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_CREATE')") + @ApiOperation("新增定时任务") + @PostMapping + @PreAuthorize("@el.check('timing:add')") public ResponseEntity create(@Validated @RequestBody QuartzJob resources){ if (resources.getId() != null) { throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); } - return new ResponseEntity(quartzJobService.create(resources),HttpStatus.CREATED); + return new ResponseEntity<>(quartzJobService.create(resources),HttpStatus.CREATED); } @Log("修改定时任务") - @PutMapping(value = "/jobs") - @PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_EDIT')") + @ApiOperation("修改定时任务") + @PutMapping + @PreAuthorize("@el.check('timing:edit')") public ResponseEntity update(@Validated(QuartzJob.Update.class) @RequestBody QuartzJob resources){ quartzJobService.update(resources); return new ResponseEntity(HttpStatus.NO_CONTENT); } @Log("更改定时任务状态") - @PutMapping(value = "/jobs/{id}") - @PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_EDIT')") + @ApiOperation("更改定时任务状态") + @PutMapping(value = "/{id}") + @PreAuthorize("@el.check('timing:edit')") public ResponseEntity updateIsPause(@PathVariable Long id){ quartzJobService.updateIsPause(quartzJobService.findById(id)); return new ResponseEntity(HttpStatus.NO_CONTENT); } @Log("执行定时任务") - @PutMapping(value = "/jobs/exec/{id}") - @PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_EDIT')") + @ApiOperation("执行定时任务") + @PutMapping(value = "/exec/{id}") + @PreAuthorize("@el.check('timing:edit')") public ResponseEntity execution(@PathVariable Long id){ quartzJobService.execution(quartzJobService.findById(id)); return new ResponseEntity(HttpStatus.NO_CONTENT); } @Log("删除定时任务") - @DeleteMapping(value = "/jobs/{id}") - @PreAuthorize("hasAnyRole('ADMIN','JOB_ALL','JOB_DELETE')") + @ApiOperation("删除定时任务") + @DeleteMapping(value = "/{id}") + @PreAuthorize("@el.check('timing:del')") public ResponseEntity delete(@PathVariable Long id){ quartzJobService.delete(quartzJobService.findById(id)); return new ResponseEntity(HttpStatus.OK); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/QuartzJobService.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/QuartzJobService.java index a5ade06d..3a42ab50 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/QuartzJobService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/QuartzJobService.java @@ -3,76 +3,47 @@ package me.zhengjie.modules.quartz.service; import me.zhengjie.modules.quartz.domain.QuartzJob; import me.zhengjie.modules.quartz.domain.QuartzLog; import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Pageable; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; + /** * @author Zheng Jie * @date 2019-01-07 */ -@CacheConfig(cacheNames = "quartzJob") public interface QuartzJobService { - /** - * queryAll quartzJob - * @param criteria - * @param pageable - * @return - */ - @Cacheable Object queryAll(JobQueryCriteria criteria, Pageable pageable); - /** - * queryAll quartzLog - * @param criteria - * @param pageable - * @return - */ + List queryAll(JobQueryCriteria criteria); + Object queryAllLog(JobQueryCriteria criteria, Pageable pageable); - /** - * create - * @param resources - * @return - */ - @CacheEvict(allEntries = true) + List queryAllLog(JobQueryCriteria criteria); + QuartzJob create(QuartzJob resources); - /** - * update - * @param resources - * @return - */ - @CacheEvict(allEntries = true) void update(QuartzJob resources); - /** - * del - * @param quartzJob - */ - @CacheEvict(allEntries = true) void delete(QuartzJob quartzJob); - /** - * findById - * @param id - * @return - */ - @Cacheable(key = "#p0") QuartzJob findById(Long id); /** * 更改定时任务状态 - * @param quartzJob + * @param quartzJob / */ - @CacheEvict(allEntries = true) void updateIsPause(QuartzJob quartzJob); /** * 立即执行定时任务 - * @param quartzJob + * @param quartzJob / */ void execution(QuartzJob quartzJob); + + void download(List queryAll, HttpServletResponse response) throws IOException; + + void downloadLog(List queryAllLog, HttpServletResponse response) throws IOException; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/dto/JobQueryCriteria.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/dto/JobQueryCriteria.java index 182d8f7c..486760b0 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/dto/JobQueryCriteria.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/dto/JobQueryCriteria.java @@ -3,6 +3,8 @@ package me.zhengjie.modules.quartz.service.dto; import lombok.Data; import me.zhengjie.annotation.Query; +import java.sql.Timestamp; + /** * @author Zheng Jie * @date 2019-6-4 10:33:02 @@ -15,4 +17,10 @@ public class JobQueryCriteria { @Query private Boolean isSuccess; + + @Query(type = Query.Type.GREATER_THAN,propName = "createTime") + private Timestamp startTime; + + @Query(type = Query.Type.LESS_THAN,propName = "createTime") + private Timestamp endTime; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/impl/QuartzJobServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/impl/QuartzJobServiceImpl.java index b38c6c59..1c430c66 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/impl/QuartzJobServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/impl/QuartzJobServiceImpl.java @@ -2,40 +2,55 @@ package me.zhengjie.modules.quartz.service.impl; import me.zhengjie.exception.BadRequestException; import me.zhengjie.modules.quartz.domain.QuartzJob; +import me.zhengjie.modules.quartz.domain.QuartzLog; import me.zhengjie.modules.quartz.repository.QuartzJobRepository; import me.zhengjie.modules.quartz.repository.QuartzLogRepository; import me.zhengjie.modules.quartz.service.QuartzJobService; import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria; import me.zhengjie.modules.quartz.utils.QuartzManage; +import me.zhengjie.utils.FileUtil; import me.zhengjie.utils.PageUtil; import me.zhengjie.utils.QueryHelp; import me.zhengjie.utils.ValidationUtil; import org.quartz.CronExpression; -import org.springframework.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.stereotype.Service; import org.springframework.transaction.annotation.Propagation; 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 * @date 2019-01-07 */ @Service(value = "quartzJobService") +@CacheConfig(cacheNames = "quartzJob") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class QuartzJobServiceImpl implements QuartzJobService { - @Autowired - private QuartzJobRepository quartzJobRepository; + private final QuartzJobRepository quartzJobRepository; - @Autowired - private QuartzLogRepository quartzLogRepository; + private final QuartzLogRepository quartzLogRepository; - @Autowired - private QuartzManage quartzManage; + private final QuartzManage quartzManage; + + public QuartzJobServiceImpl(QuartzJobRepository quartzJobRepository, QuartzLogRepository quartzLogRepository, QuartzManage quartzManage) { + this.quartzJobRepository = quartzJobRepository; + this.quartzLogRepository = quartzLogRepository; + this.quartzManage = quartzManage; + } @Override + @Cacheable public Object queryAll(JobQueryCriteria criteria, Pageable pageable){ return PageUtil.toPage(quartzJobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable)); } @@ -46,13 +61,25 @@ public class QuartzJobServiceImpl implements QuartzJobService { } @Override - public QuartzJob findById(Long id) { - Optional quartzJob = quartzJobRepository.findById(id); - ValidationUtil.isNull(quartzJob,"QuartzJob","id",id); - return quartzJob.get(); + public List queryAll(JobQueryCriteria criteria) { + return quartzJobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); } @Override + public List queryAllLog(JobQueryCriteria criteria) { + return quartzLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); + } + + @Override + @Cacheable(key = "#p0") + public QuartzJob findById(Long id) { + QuartzJob quartzJob = quartzJobRepository.findById(id).orElseGet(QuartzJob::new); + ValidationUtil.isNull(quartzJob.getId(),"QuartzJob","id",id); + return quartzJob; + } + + @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public QuartzJob create(QuartzJob resources) { if (!CronExpression.isValidExpression(resources.getCronExpression())){ @@ -64,6 +91,7 @@ public class QuartzJobServiceImpl implements QuartzJobService { } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void update(QuartzJob resources) { if(resources.getId().equals(1L)){ @@ -77,6 +105,7 @@ public class QuartzJobServiceImpl implements QuartzJobService { } @Override + @CacheEvict(allEntries = true) public void updateIsPause(QuartzJob quartzJob) { if(quartzJob.getId().equals(1L)){ throw new BadRequestException("该任务不可操作"); @@ -100,6 +129,7 @@ public class QuartzJobServiceImpl implements QuartzJobService { } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void delete(QuartzJob quartzJob) { if(quartzJob.getId().equals(1L)){ @@ -108,4 +138,41 @@ public class QuartzJobServiceImpl implements QuartzJobService { quartzManage.deleteJob(quartzJob); quartzJobRepository.delete(quartzJob); } + + @Override + public void download(List quartzJobs, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (QuartzJob quartzJob : quartzJobs) { + Map 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 queryAllLog, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (QuartzLog quartzLog : queryAllLog) { + Map 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); + } } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java index 680e9f1d..757703bb 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java @@ -1,7 +1,6 @@ package me.zhengjie.modules.quartz.task; import lombok.extern.slf4j.Slf4j; -import me.zhengjie.exception.BadRequestException; import org.springframework.stereotype.Component; /** diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/VisitsTask.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/VisitsTask.java index 01e238e2..47bb66c7 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/VisitsTask.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/VisitsTask.java @@ -1,7 +1,6 @@ package me.zhengjie.modules.quartz.task; import me.zhengjie.modules.monitor.service.VisitsService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** @@ -11,8 +10,11 @@ import org.springframework.stereotype.Component; @Component public class VisitsTask { - @Autowired - private VisitsService visitsService; + private final VisitsService visitsService; + + public VisitsTask(VisitsService visitsService) { + this.visitsService = visitsService; + } public void run(){ visitsService.save(); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java index 221d665d..1c0713fd 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java @@ -1,5 +1,7 @@ package me.zhengjie.modules.quartz.utils; +import me.zhengjie.config.thread.TheadFactoryName; +import me.zhengjie.config.thread.ThreadPoolExecutorUtil; import me.zhengjie.modules.quartz.domain.QuartzJob; import me.zhengjie.modules.quartz.domain.QuartzLog; import me.zhengjie.modules.quartz.repository.QuartzLogRepository; @@ -11,13 +13,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.quartz.QuartzJobBean; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; +import java.util.concurrent.*; /** * 参考人人开源,https://gitee.com/renrenio/renren-security - * @author + * @author / * @date 2019-01-07 */ @Async @@ -25,16 +25,16 @@ public class ExecutionJob extends QuartzJobBean { private Logger logger = LoggerFactory.getLogger(this.getClass()); - // 建议自定义线程池实现方式,该处仅供参考 - private ExecutorService executorService = Executors.newSingleThreadExecutor(); + // 该处仅供参考 + private final static ThreadPoolExecutor executor = ThreadPoolExecutorUtil.getPoll(); @Override + @SuppressWarnings("unchecked") protected void executeInternal(JobExecutionContext context) { QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY); // 获取spring bean - QuartzLogRepository quartzLogRepository = SpringContextHolder.getBean("quartzLogRepository"); - QuartzJobService quartzJobService = SpringContextHolder.getBean("quartzJobService"); - QuartzManage quartzManage = SpringContextHolder.getBean("quartzManage"); + QuartzLogRepository quartzLogRepository = SpringContextHolder.getBean(QuartzLogRepository.class); + QuartzJobService quartzJobService = SpringContextHolder.getBean(QuartzJobService.class); QuartzLog log = new QuartzLog(); log.setJobName(quartzJob.getJobName()); @@ -48,7 +48,7 @@ public class ExecutionJob extends QuartzJobBean { logger.info("任务准备执行,任务名称:{}", quartzJob.getJobName()); QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(), quartzJob.getParams()); - Future future = executorService.submit(task); + Future future = executor.submit(task); future.get(); long times = System.currentTimeMillis() - startTime; log.setTime(times); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzManage.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzManage.java index a017df19..1cb6a2ce 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzManage.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzManage.java @@ -56,8 +56,7 @@ public class QuartzManage { /** * 更新job cron表达式 - * @param quartzJob - * @throws SchedulerException + * @param quartzJob / */ public void updateJobCron(QuartzJob quartzJob){ try { @@ -88,8 +87,7 @@ public class QuartzManage { /** * 删除一个job - * @param quartzJob - * @throws SchedulerException + * @param quartzJob / */ public void deleteJob(QuartzJob quartzJob){ try { @@ -104,8 +102,7 @@ public class QuartzManage { /** * 恢复一个job - * @param quartzJob - * @throws SchedulerException + * @param quartzJob / */ public void resumeJob(QuartzJob quartzJob){ try { @@ -124,8 +121,7 @@ public class QuartzManage { /** * 立即执行job - * @param quartzJob - * @throws SchedulerException + * @param quartzJob / */ public void runAJobNow(QuartzJob quartzJob){ try { @@ -146,8 +142,7 @@ public class QuartzManage { /** * 暂停一个job - * @param quartzJob - * @throws SchedulerException + * @param quartzJob / */ public void pauseJob(QuartzJob quartzJob){ try { diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzRunnable.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzRunnable.java index d9407291..f3f8720c 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzRunnable.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzRunnable.java @@ -1,7 +1,6 @@ package me.zhengjie.modules.quartz.utils; import lombok.extern.slf4j.Slf4j; -import me.zhengjie.exception.BadRequestException; import me.zhengjie.utils.SpringContextHolder; import org.apache.commons.lang3.StringUtils; import org.springframework.util.ReflectionUtils; @@ -10,7 +9,7 @@ import java.util.concurrent.Callable; /** * 执行定时任务 - * @author + * @author / */ @Slf4j public class QuartzRunnable implements Callable { diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java index d10bd218..19a7efe5 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java @@ -1,13 +1,17 @@ package me.zhengjie.modules.security.config; +import me.zhengjie.annotation.AnonymousAccess; +import me.zhengjie.config.ElPermissionConfig; import me.zhengjie.modules.security.security.JwtAuthenticationEntryPoint; import me.zhengjie.modules.security.security.JwtAuthorizationTokenFilter; import me.zhengjie.modules.security.service.JwtUserDetailsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; @@ -19,29 +23,37 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { - @Autowired - private JwtAuthenticationEntryPoint unauthorizedHandler; + private final JwtAuthenticationEntryPoint unauthorizedHandler; - @Autowired - private JwtUserDetailsService jwtUserDetailsService; + private final JwtUserDetailsService jwtUserDetailsService; - /** - * 自定义基于JWT的安全过滤器 - */ - @Autowired - JwtAuthorizationTokenFilter authenticationTokenFilter; + private final ApplicationContext applicationContext; + + // 自定义基于JWT的安全过滤器 + private final JwtAuthorizationTokenFilter authenticationTokenFilter; @Value("${jwt.header}") private String tokenHeader; - @Value("${jwt.auth.path}") - private String loginPath; + public SecurityConfig(JwtAuthenticationEntryPoint unauthorizedHandler, JwtUserDetailsService jwtUserDetailsService, JwtAuthorizationTokenFilter authenticationTokenFilter, ApplicationContext applicationContext) { + this.unauthorizedHandler = unauthorizedHandler; + this.jwtUserDetailsService = jwtUserDetailsService; + this.authenticationTokenFilter = authenticationTokenFilter; + this.applicationContext = applicationContext; + } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { @@ -69,18 +81,26 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity httpSecurity) throws Exception { - + // 搜寻 匿名标记 url: PreAuthorize("hasAnyRole('anonymous')") 和 PreAuthorize("@el.check('anonymous')") 和 AnonymousAccess + Map handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods(); + Set anonymousUrls = new HashSet<>(); + for (Map.Entry 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 - // 禁用 CSRF .csrf().disable() - // 授权异常 .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() - // 不创建会话 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() - // 过滤请求 .authorizeRequests() .antMatchers( @@ -90,35 +110,24 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { "/**/*.css", "/**/*.js" ).anonymous() - - .antMatchers( HttpMethod.POST,"/auth/"+loginPath).anonymous() - .antMatchers("/auth/vCode").anonymous() - // 支付宝回调 - .antMatchers("/api/aliPay/return").anonymous() - .antMatchers("/api/aliPay/notify").anonymous() - // swagger start - .antMatchers("/swagger-ui.html").anonymous() - .antMatchers("/swagger-resources/**").anonymous() - .antMatchers("/webjars/**").anonymous() - .antMatchers("/*/api-docs").anonymous() + .antMatchers("/swagger-ui.html").permitAll() + .antMatchers("/swagger-resources/**").permitAll() + .antMatchers("/webjars/**").permitAll() + .antMatchers("/*/api-docs").permitAll() // swagger end - - // 接口限流测试 - .antMatchers("/test/**").anonymous() // 文件 - .antMatchers("/avatar/**").anonymous() - .antMatchers("/file/**").anonymous() - + .antMatchers("/avatar/**").permitAll() + .antMatchers("/file/**").permitAll() // 放行OPTIONS请求 - .antMatchers(HttpMethod.OPTIONS, "/**").anonymous() - - .antMatchers("/druid/**").anonymous() + .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() + .antMatchers("/druid/**").permitAll() + // 自定义匿名访问所有url放行 : 允许 匿名和带权限以及登录用户访问 + .antMatchers(anonymousUrls.toArray(new String[0])).permitAll() // 所有请求都需要认证 .anyRequest().authenticated() // 防止iframe 造成跨域 .and().headers().frameOptions().disable(); - httpSecurity .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/rest/AuthenticationController.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/rest/AuthenticationController.java index baf99159..c6be8204 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/security/rest/AuthenticationController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/rest/AuthenticationController.java @@ -1,31 +1,32 @@ package me.zhengjie.modules.security.rest; -import cn.hutool.core.codec.Base64; 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 me.zhengjie.annotation.AnonymousAccess; import me.zhengjie.aop.log.Log; import me.zhengjie.exception.BadRequestException; import me.zhengjie.modules.monitor.service.RedisService; -import me.zhengjie.modules.security.security.AuthenticationInfo; -import me.zhengjie.modules.security.security.AuthorizationUser; +import me.zhengjie.modules.security.security.AuthInfo; +import me.zhengjie.modules.security.security.AuthUser; import me.zhengjie.modules.security.security.ImgResult; 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.modules.security.utils.JwtTokenUtil; import me.zhengjie.utils.SecurityUtils; 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.Value; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AccountExpiredException; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.io.ByteArrayOutputStream; -import java.io.IOException; +import javax.servlet.http.HttpServletRequest; /** * @author Zheng Jie @@ -34,30 +35,33 @@ import java.io.IOException; */ @Slf4j @RestController -@RequestMapping("auth") +@RequestMapping("/auth") +@Api(tags = "系统:系统授权接口") public class AuthenticationController { - @Value("${jwt.header}") - private String tokenHeader; + @Value("${jwt.codeKey}") + private String codeKey; - @Autowired - private JwtTokenUtil jwtTokenUtil; + private final JwtTokenUtil jwtTokenUtil; - @Autowired - private RedisService redisService; + private final RedisService redisService; - @Autowired - @Qualifier("jwtUserDetailsService") - private UserDetailsService userDetailsService; + private final 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("用户登录") - @PostMapping(value = "${jwt.auth.path}") - public ResponseEntity login(@Validated @RequestBody AuthorizationUser authorizationUser){ + @ApiOperation("登录授权") + @AnonymousAccess + @PostMapping(value = "/login") + public ResponseEntity login(@Validated @RequestBody AuthUser authorizationUser, HttpServletRequest request){ // 查询验证码 String code = redisService.getCodeVal(authorizationUser.getUuid()); @@ -78,45 +82,41 @@ public class AuthenticationController { if(!jwtUser.isEnabled()){ throw new AccountExpiredException("账号已停用,请联系管理员"); } - // 生成令牌 final String token = jwtTokenUtil.generateToken(jwtUser); - + // 保存在线信息 + onlineUserService.save(jwtUser, token, request); // 返回 token - return ResponseEntity.ok(new AuthenticationInfo(token,jwtUser)); + return ResponseEntity.ok(new AuthInfo(token,jwtUser)); } - /** - * 获取用户信息 - * @return - */ - @GetMapping(value = "${jwt.auth.account}") + @ApiOperation("获取用户信息") + @GetMapping(value = "/info") public ResponseEntity getUserInfo(){ JwtUser jwtUser = (JwtUser)userDetailsService.loadUserByUsername(SecurityUtils.getUsername()); return ResponseEntity.ok(jwtUser); } - /** - * 获取验证码 - */ - @GetMapping(value = "vCode") - public ImgResult getCode(HttpServletResponse response) throws IOException { + @ApiOperation("获取验证码") + @AnonymousAccess + @GetMapping(value = "/code") + public ImgResult getCode(){ + // 算术类型 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); + } - //生成随机字串 - String verifyCode = VerifyCodeUtils.generateVerifyCode(4); - String uuid = IdUtil.simpleUUID(); - redisService.saveCode(uuid,verifyCode); - // 生成图片 - int w = 111, h = 36; - 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(); - } + @ApiOperation("退出登录") + @AnonymousAccess + @DeleteMapping(value = "/logout") + public ResponseEntity logout(HttpServletRequest request){ + onlineUserService.logout(jwtTokenUtil.getToken(request)); + return new ResponseEntity(HttpStatus.OK); } } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/rest/OnlineController.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/rest/OnlineController.java new file mode 100644 index 00000000..5a9ccfb5 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/rest/OnlineController.java @@ -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); + } +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthenticationInfo.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthInfo.java similarity index 79% rename from eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthenticationInfo.java rename to eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthInfo.java index 65fa7232..94bb2ab6 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthenticationInfo.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthInfo.java @@ -1,19 +1,19 @@ -package me.zhengjie.modules.security.security; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import java.io.Serializable; - -/** - * @author Zheng Jie - * @date 2018-11-23 - * 返回token - */ -@Getter -@AllArgsConstructor -public class AuthenticationInfo implements Serializable { - - private final String token; - - private final JwtUser user; -} +package me.zhengjie.modules.security.security; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import java.io.Serializable; + +/** + * @author Zheng Jie + * @date 2018-11-23 + * 返回token + */ +@Getter +@AllArgsConstructor +public class AuthInfo implements Serializable { + + private final String token; + + private final JwtUser user; +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthorizationUser.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthUser.java similarity index 93% rename from eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthorizationUser.java rename to eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthUser.java index 1b93aca5..8c3a9608 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthorizationUser.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/AuthUser.java @@ -11,7 +11,7 @@ import javax.validation.constraints.NotBlank; */ @Getter @Setter -public class AuthorizationUser { +public class AuthUser { @NotBlank private String username; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java index f1504671..9569c8be 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java @@ -18,9 +18,7 @@ public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Se public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { - /** - * 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应 - */ + // 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage()); } } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthorizationTokenFilter.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthorizationTokenFilter.java index 1693bcc1..c1e57b12 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthorizationTokenFilter.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthorizationTokenFilter.java @@ -3,11 +3,12 @@ package me.zhengjie.modules.security.security; import io.jsonwebtoken.ExpiredJwtException; import lombok.extern.slf4j.Slf4j; import me.zhengjie.modules.security.utils.JwtTokenUtil; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; @@ -22,38 +23,33 @@ import java.io.IOException; @Component public class JwtAuthorizationTokenFilter extends OncePerRequestFilter { + + @Value("${jwt.online}") + private String onlineKey; + private final UserDetailsService userDetailsService; 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.jwtTokenUtil = jwtTokenUtil; - this.tokenHeader = tokenHeader; + this.redisTemplate = redisTemplate; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { - - final String requestHeader = request.getHeader(this.tokenHeader); - - String username = null; - String authToken = null; - if (requestHeader != null && requestHeader.startsWith("Bearer ")) { - authToken = requestHeader.substring(7); - try { - username = jwtTokenUtil.getUsernameFromToken(authToken); - } catch (ExpiredJwtException e) { - log.error(e.getMessage()); - } + String authToken = jwtTokenUtil.getToken(request); + OnlineUser onlineUser = null; + try { + onlineUser = (OnlineUser)redisTemplate.opsForValue().get(onlineKey + authToken); + } catch (ExpiredJwtException e) { + log.error(e.getMessage()); } - - if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { - + if (onlineUser != null && SecurityContextHolder.getContext().getAuthentication() == null) { // It is not compelling necessary to load the use details from the database. You could also store the information // in the token and read it from it. It's up to you ;) - JwtUser userDetails = (JwtUser)this.userDetailsService.loadUserByUsername(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 // the database compellingly. Again it's up to you ;) if (jwtTokenUtil.validateToken(authToken, userDetails)) { diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/security/OnlineUser.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/OnlineUser.java new file mode 100644 index 00000000..d0bb036c --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/security/OnlineUser.java @@ -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; + + +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/service/JwtPermissionService.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/service/JwtPermissionService.java index c653d205..461841ff 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/security/service/JwtPermissionService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/service/JwtPermissionService.java @@ -1,15 +1,17 @@ package me.zhengjie.modules.security.service; +import me.zhengjie.modules.system.domain.Menu; import me.zhengjie.modules.system.domain.Role; import me.zhengjie.modules.system.repository.RoleRepository; import me.zhengjie.modules.system.service.dto.UserDTO; -import org.springframework.beans.factory.annotation.Autowired; +import me.zhengjie.utils.StringUtils; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.Cacheable; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.stereotype.Service; import java.util.Collection; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -17,13 +19,16 @@ import java.util.stream.Collectors; @CacheConfig(cacheNames = "role") public class JwtPermissionService { - @Autowired - private RoleRepository roleRepository; + private final RoleRepository roleRepository; + + public JwtPermissionService(RoleRepository roleRepository) { + this.roleRepository = roleRepository; + } /** * key的名称如有修改,请同步修改 UserServiceImpl 中的 update 方法 - * @param user - * @return + * @param user 用户信息 + * @return Collection */ @Cacheable(key = "'loadPermissionByUser:' + #p0.username") public Collection mapToGrantedAuthorities(UserDTO user) { @@ -31,9 +36,13 @@ public class JwtPermissionService { System.out.println("--------------------loadPermissionByUser:" + user.getUsername() + "---------------------"); Set roles = roleRepository.findByUsers_Id(user.getId()); - - return roles.stream().flatMap(role -> role.getPermissions().stream()) - .map(permission -> new SimpleGrantedAuthority(permission.getName())) + Set permissions = roles.stream().filter(role -> StringUtils.isNotBlank(role.getPermission())).map(Role::getPermission).collect(Collectors.toSet()); + permissions.addAll( + roles.stream().flatMap(role -> role.getMenus().stream()) + .filter(menu -> StringUtils.isNotBlank(menu.getPermission())) + .map(Menu::getPermission).collect(Collectors.toSet()) + ); + return permissions.stream().map(permission -> new SimpleGrantedAuthority(permission)) .collect(Collectors.toList()); } } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/service/JwtUserDetailsService.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/service/JwtUserDetailsService.java index 91239a04..51656245 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/security/service/JwtUserDetailsService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/service/JwtUserDetailsService.java @@ -4,7 +4,6 @@ import me.zhengjie.exception.BadRequestException; import me.zhengjie.modules.security.security.JwtUser; import me.zhengjie.modules.system.service.UserService; import me.zhengjie.modules.system.service.dto.*; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Service; @@ -20,11 +19,14 @@ import java.util.Optional; @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class JwtUserDetailsService implements UserDetailsService { - @Autowired - private UserService userService; + private final UserService userService; - @Autowired - private JwtPermissionService permissionService; + private final JwtPermissionService permissionService; + + public JwtUserDetailsService(UserService userService, JwtPermissionService permissionService) { + this.userService = userService; + this.permissionService = permissionService; + } @Override public UserDetails loadUserByUsername(String username){ diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/service/OnlineUserService.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/service/OnlineUserService.java new file mode 100644 index 00000000..f897bf8e --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/service/OnlineUserService.java @@ -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 getAll(String filter, Pageable pageable){ + List onlineUsers = getAll(filter); + return new PageImpl( + PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(),onlineUsers), + pageable, + onlineUsers.size()); + } + + public List getAll(String filter){ + List keys = new ArrayList<>(redisTemplate.keys(onlineKey + "*")); + Collections.reverse(keys); + List 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 all, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (OnlineUser user : all) { + Map 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); + } +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/utils/JwtTokenUtil.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/utils/JwtTokenUtil.java index ee7517a7..8a0f2fa1 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/security/utils/JwtTokenUtil.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/security/utils/JwtTokenUtil.java @@ -6,6 +6,8 @@ import me.zhengjie.modules.security.security.JwtUser; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; import java.io.Serializable; import java.util.Date; import java.util.HashMap; @@ -31,15 +33,15 @@ public class JwtTokenUtil implements Serializable { return getClaimFromToken(token, Claims::getSubject); } - public Date getIssuedAtDateFromToken(String token) { + private Date getIssuedAtDateFromToken(String token) { return getClaimFromToken(token, Claims::getIssuedAt); } - public Date getExpirationDateFromToken(String token) { + private Date getExpirationDateFromToken(String token) { return getClaimFromToken(token, Claims::getExpiration); } - public T getClaimFromToken(String token, Function claimsResolver) { + private T getClaimFromToken(String token, Function claimsResolver) { final Claims claims = getAllClaimsFromToken(token); return claimsResolver.apply(claims); } @@ -103,6 +105,14 @@ public class JwtTokenUtil implements Serializable { .compact(); } + public String getToken(HttpServletRequest request){ + final String requestHeader = request.getHeader(tokenHeader); + if (requestHeader != null && requestHeader.startsWith("Bearer ")) { + return requestHeader.substring(7); + } + return null; + } + public Boolean validateToken(String token, UserDetails userDetails) { JwtUser user = (JwtUser) userDetails; final Date created = getIssuedAtDateFromToken(token); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/security/utils/VerifyCodeUtils.java b/eladmin-system/src/main/java/me/zhengjie/modules/security/utils/VerifyCodeUtils.java deleted file mode 100644 index 74eb04a6..00000000 --- a/eladmin-system/src/main/java/me/zhengjie/modules/security/utils/VerifyCodeUtils.java +++ /dev/null @@ -1,203 +0,0 @@ -package me.zhengjie.modules.security.utils; - -import java.awt.Color; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.Random; -import javax.imageio.ImageIO; - -/** - * @author https://blog.csdn.net/ruixue0117/article/details/22829557 - * @date 2019-6-20 17:28:53 - */ -public class VerifyCodeUtils{ - - //使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符 - public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"; - private static Random random = new Random(); - - - /** - * 使用系统默认字符源生成验证码 - * @param verifySize 验证码长度 - * @return - */ - public static String generateVerifyCode(int verifySize){ - return generateVerifyCode(verifySize, VERIFY_CODES); - } - /** - * 使用指定源生成验证码 - * @param verifySize 验证码长度 - * @param sources 验证码字符源 - * @return - */ - public static String generateVerifyCode(int verifySize, String sources){ - if(sources == null || sources.length() == 0){ - sources = VERIFY_CODES; - } - int codesLen = sources.length(); - Random rand = new Random(System.currentTimeMillis()); - StringBuilder verifyCode = new StringBuilder(verifySize); - for(int i = 0; i < verifySize; i++){ - verifyCode.append(sources.charAt(rand.nextInt(codesLen-1))); - } - return verifyCode.toString(); - } - - /** - * 输出指定验证码图片流 - * @param w - * @param h - * @param os - * @param code - * @throws IOException - */ - public static void outputImage(int w, int h, OutputStream os, String code) throws IOException{ - int verifySize = code.length(); - BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); - Random rand = new Random(); - Graphics2D g2 = image.createGraphics(); - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); - Color[] colors = new Color[5]; - Color[] colorSpaces = new Color[] { Color.WHITE, Color.CYAN, - Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, - Color.PINK, Color.YELLOW }; - float[] fractions = new float[colors.length]; - for(int i = 0; i < colors.length; i++){ - colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)]; - fractions[i] = rand.nextFloat(); - } - Arrays.sort(fractions); - - g2.setColor(Color.GRAY);// 设置边框色 - g2.fillRect(0, 0, w, h); - - Color c = getRandColor(200, 250); - g2.setColor(c);// 设置背景色 - g2.fillRect(0, 2, w, h-4); - - //绘制干扰线 - Random random = new Random(); - g2.setColor(getRandColor(160, 200));// 设置线条的颜色 - for (int i = 0; i < 20; i++) { - int x = random.nextInt(w - 1); - int y = random.nextInt(h - 1); - int xl = random.nextInt(6) + 1; - int yl = random.nextInt(12) + 1; - g2.drawLine(x, y, x + xl + 40, y + yl + 20); - } - - // 添加噪点 - float yawpRate = 0.05f;// 噪声率 - int area = (int) (yawpRate * w * h); - for (int i = 0; i < area; i++) { - int x = random.nextInt(w); - int y = random.nextInt(h); - int rgb = getRandomIntColor(); - image.setRGB(x, y, rgb); - } - - shear(g2, w, h, c);// 使图片扭曲 - - g2.setColor(getRandColor(100, 160)); - int fontSize = h-4; - Font font = new Font("Algerian", Font.ITALIC, fontSize); - g2.setFont(font); - char[] chars = code.toCharArray(); - for(int i = 0; i < verifySize; i++){ - AffineTransform affine = new AffineTransform(); - affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2); - g2.setTransform(affine); - g2.drawChars(chars, i, 1, ((w-10) / verifySize) * i + 5, h/2 + fontSize/2 - 10); - } - - g2.dispose(); - ImageIO.write(image, "jpg", os); - } - - private static Color getRandColor(int fc, int bc) { - if (fc > 255) - fc = 255; - if (bc > 255) - bc = 255; - int r = fc + random.nextInt(bc - fc); - int g = fc + random.nextInt(bc - fc); - int b = fc + random.nextInt(bc - fc); - return new Color(r, g, b); - } - - private static int getRandomIntColor() { - int[] rgb = getRandomRgb(); - int color = 0; - for (int c : rgb) { - color = color << 8; - color = color | c; - } - return color; - } - - private static int[] getRandomRgb() { - int[] rgb = new int[3]; - for (int i = 0; i < 3; i++) { - rgb[i] = random.nextInt(255); - } - return rgb; - } - - private static void shear(Graphics g, int w1, int h1, Color color) { - shearX(g, w1, h1, color); - shearY(g, w1, h1, color); - } - - private static void shearX(Graphics g, int w1, int h1, Color color) { - - int period = random.nextInt(2); - - boolean borderGap = true; - int frames = 1; - int phase = random.nextInt(2); - - for (int i = 0; i < h1; i++) { - double d = (double) (period >> 1) - * Math.sin((double) i / (double) period - + (6.2831853071795862D * (double) phase) - / (double) frames); - g.copyArea(0, i, w1, 1, (int) d, 0); - if (borderGap) { - g.setColor(color); - g.drawLine((int) d, i, 0, i); - g.drawLine((int) d + w1, i, w1, i); - } - } - - } - - private static void shearY(Graphics g, int w1, int h1, Color color) { - - int period = random.nextInt(40) + 10; // 50; - - boolean borderGap = true; - int frames = 20; - int phase = 7; - for (int i = 0; i < w1; i++) { - double d = (double) (period >> 1) - * Math.sin((double) i / (double) period - + (6.2831853071795862D * (double) phase) - / (double) frames); - g.copyArea(i, 0, 1, h1, 0, (int) d); - if (borderGap) { - g.setColor(color); - g.drawLine(i, (int) d, i, 0); - g.drawLine(i, (int) d + h1, i, h1); - } - - } - } -} \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Dept.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Dept.java index 5fe611c8..d21273a0 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Dept.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Dept.java @@ -1,13 +1,14 @@ package me.zhengjie.modules.system.domain; import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; import org.hibernate.annotations.CreationTimestamp; import javax.persistence.*; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; -import java.sql.Timestamp; import java.io.Serializable; +import java.sql.Timestamp; import java.util.Set; /** @@ -15,22 +16,17 @@ import java.util.Set; * @date 2019-03-25 */ @Entity -@Data +@Getter +@Setter @Table(name="dept") public class Dept implements Serializable { - /** - * ID - */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") @NotNull(groups = Update.class) private Long id; - /** - * 名称 - */ @Column(name = "name",nullable = false) @NotBlank private String name; @@ -38,9 +34,6 @@ public class Dept implements Serializable { @NotNull private Boolean enabled; - /** - * 上级部门 - */ @Column(name = "pid",nullable = false) @NotNull private Long pid; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Dict.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Dict.java index 83183d3e..cbdde2c4 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Dict.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Dict.java @@ -1,10 +1,14 @@ package me.zhengjie.modules.system.domain; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.zhengjie.base.BaseEntity; +import org.hibernate.annotations.CreationTimestamp; import javax.persistence.*; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.io.Serializable; +import java.sql.Timestamp; import java.util.List; /** @@ -12,7 +16,8 @@ import java.util.List; * @date 2019-04-10 */ @Entity -@Data +@Getter +@Setter @Table(name="dict") public class Dict implements Serializable { @@ -22,19 +27,17 @@ public class Dict implements Serializable { @NotNull(groups = Update.class) private Long id; - /** - * 字典名称 - */ @Column(name = "name",nullable = false,unique = true) @NotBlank private String name; - /** - * 描述 - */ @Column(name = "remark") private String remark; + @Column(name = "create_time") + @CreationTimestamp + private Timestamp createTime; + @OneToMany(mappedBy = "dict",cascade={CascadeType.PERSIST,CascadeType.REMOVE}) private List dictDetails; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/DictDetail.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/DictDetail.java index a3799a31..a06e81ec 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/DictDetail.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/DictDetail.java @@ -1,16 +1,20 @@ package me.zhengjie.modules.system.domain; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; import javax.persistence.*; import javax.validation.constraints.NotNull; import java.io.Serializable; +import java.sql.Timestamp; /** * @author Zheng Jie * @date 2019-04-10 */ @Entity -@Data +@Getter +@Setter @Table(name="dict_detail") public class DictDetail implements Serializable { @@ -20,30 +24,26 @@ public class DictDetail implements Serializable { @NotNull(groups = Update.class) private Long id; - /** - * 字典标签 - */ + // 字典标签 @Column(name = "label",nullable = false) private String label; - /** - * 字典值 - */ + // 字典值 @Column(name = "value",nullable = false) private String value; - /** - * 排序 - */ + // 排序 @Column(name = "sort") private String sort = "999"; - /** - * 字典id - */ + // 字典id @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name = "dict_id") private Dict dict; + @Column(name = "create_time") + @CreationTimestamp + private Timestamp createTime; + public @interface Update {} } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Job.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Job.java index 58f3fd95..272cf424 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Job.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Job.java @@ -1,36 +1,32 @@ package me.zhengjie.modules.system.domain; -import lombok.Data; -import org.hibernate.annotations.*; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; import javax.persistence.*; import javax.persistence.Entity; import javax.persistence.Table; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; -import java.sql.Timestamp; import java.io.Serializable; +import java.sql.Timestamp; /** * @author Zheng Jie * @date 2019-03-29 */ @Entity -@Data +@Getter +@Setter @Table(name="job") public class Job implements Serializable { - /** - * ID - */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") @NotNull(groups = Update.class) private Long id; - /** - * 名称 - */ @Column(name = "name",nullable = false) @NotBlank private String name; @@ -39,9 +35,6 @@ public class Job implements Serializable { @NotNull private Long sort; - /** - * 状态 - */ @Column(name = "enabled",nullable = false) @NotNull private Boolean enabled; @@ -50,9 +43,6 @@ public class Job implements Serializable { @JoinColumn(name = "dept_id") private Dept dept; - /** - * 创建日期 - */ @Column(name = "create_time") @CreationTimestamp private Timestamp createTime; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Menu.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Menu.java index 5ac2e6cb..e4c76d05 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Menu.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Menu.java @@ -31,15 +31,21 @@ public class Menu implements Serializable { private String name; @Column(unique = true) - @NotNull - private Long sort; + private Long sort = 999L; - @NotBlank @Column(name = "path") private String path; private String component; + // 类型 + @Column(name = "type") + private Integer type; + + // 权限 + @Column(name = "permission") + private String permission; + @Column(unique = true,name = "component_name") private String componentName; @@ -51,15 +57,11 @@ public class Menu implements Serializable { @Column(columnDefinition = "bit(1) default 0") private Boolean hidden; - /** - * 上级菜单ID - */ + // 上级菜单ID @Column(name = "pid",nullable = false) private Long pid; - /** - * 是否为外链 true/false - */ + // 是否为外链 true/false @Column(name = "i_frame") private Boolean iFrame; @@ -67,11 +69,11 @@ public class Menu implements Serializable { @JsonIgnore private Set roles; - @CreationTimestamp @Column(name = "create_time") + @CreationTimestamp private Timestamp createTime; - public interface Update{} + public @interface Update {} @Override public boolean equals(Object o) { diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Permission.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Permission.java deleted file mode 100644 index 69272186..00000000 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Permission.java +++ /dev/null @@ -1,62 +0,0 @@ -package me.zhengjie.modules.system.domain; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.Getter; -import lombok.Setter; -import org.hibernate.annotations.CreationTimestamp; -import javax.persistence.*; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.io.Serializable; -import java.sql.Timestamp; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-12-03 - */ -@Entity -@Getter -@Setter -@Table(name = "permission") -public class Permission implements Serializable{ - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @NotNull(groups = {Update.class}) - private Long id; - - @NotBlank - private String name; - - /** - * 上级类目 - */ - @NotNull - @Column(name = "pid",nullable = false) - private Long pid; - - @NotBlank - private String alias; - - @JsonIgnore - @ManyToMany(mappedBy = "permissions") - private Set roles; - - @CreationTimestamp - @Column(name = "create_time") - private Timestamp createTime; - - @Override - public String toString() { - return "Permission{" + - "id=" + id + - ", name='" + name + '\'' + - ", pid=" + pid + - ", alias='" + alias + '\'' + - ", createTime=" + createTime + - '}'; - } - - public interface Update{} -} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Role.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Role.java index c44c97fb..922c7d45 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Role.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/Role.java @@ -43,14 +43,14 @@ public class Role implements Serializable { @Column private String remark; + // 权限 + @Column(name = "permission") + private String permission; + @JsonIgnore @ManyToMany(mappedBy = "roles") private Set users; - @ManyToMany - @JoinTable(name = "roles_permissions", joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "permission_id",referencedColumnName = "id")}) - private Set permissions; - @ManyToMany @JoinTable(name = "roles_menus", joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "menu_id",referencedColumnName = "id")}) private Set menus; @@ -59,19 +59,11 @@ public class Role implements Serializable { @JoinTable(name = "roles_depts", joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "dept_id",referencedColumnName = "id")}) private Set depts; - @CreationTimestamp @Column(name = "create_time") + @CreationTimestamp private Timestamp createTime; - @Override - public String toString() { - return "Role{" + - "id=" + id + - ", name='" + name + '\'' + - ", remark='" + remark + '\'' + - ", createDateTime=" + createTime + - '}'; - } + public @interface Update {} @Override public boolean equals(Object o) { @@ -85,6 +77,4 @@ public class Role implements Serializable { public int hashCode() { return Objects.hash(id); } - - public interface Update{} } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/User.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/User.java index 0bb62850..a6e994c6 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/User.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/User.java @@ -36,7 +36,7 @@ public class User implements Serializable { private UserAvatar userAvatar; @NotBlank - @Pattern(regexp = "([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}",message = "格式错误") + @Pattern(regexp = "([a-z0-9A-Z]+[-|.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}",message = "格式错误") private String email; @NotBlank @@ -47,8 +47,8 @@ public class User implements Serializable { private String password; - @CreationTimestamp @Column(name = "create_time") + @CreationTimestamp private Timestamp createTime; @Column(name = "last_password_reset_time") @@ -66,18 +66,5 @@ public class User implements Serializable { @JoinColumn(name = "dept_id") private Dept dept; - @Override - public String toString() { - return "User{" + - "id=" + id + - ", username='" + username + '\'' + - ", email='" + email + '\'' + - ", enabled=" + enabled + - ", password='" + password + '\'' + - ", createTime=" + createTime + - ", lastPasswordResetTime=" + lastPasswordResetTime + - '}'; - } - public @interface Update {} } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/UserAvatar.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/UserAvatar.java index bba30dc2..216668a2 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/UserAvatar.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/domain/UserAvatar.java @@ -1,10 +1,14 @@ package me.zhengjie.modules.system.domain; import cn.hutool.core.util.ObjectUtil; -import lombok.Data; +import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; +import me.zhengjie.base.BaseEntity; +import org.hibernate.annotations.CreationTimestamp; import javax.persistence.*; +import java.io.Serializable; import java.sql.Timestamp; /** @@ -12,10 +16,11 @@ import java.sql.Timestamp; * @date 2019年9月7日 16:16:59 */ @Entity -@Table(name = "user_avatar") -@Data +@Getter +@Setter @NoArgsConstructor -public class UserAvatar { +@Table(name = "user_avatar") +public class UserAvatar implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -27,6 +32,10 @@ public class UserAvatar { private String size; + @Column(name = "create_time") + @CreationTimestamp + private Timestamp createTime; + public UserAvatar(UserAvatar userAvatar,String realName, String path, String size) { this.id = ObjectUtil.isNotEmpty(userAvatar) ? userAvatar.getId() : null; this.realName = realName; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DeptRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DeptRepository.java index 12feee12..d8817f7c 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DeptRepository.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DeptRepository.java @@ -4,7 +4,6 @@ import me.zhengjie.modules.system.domain.Dept; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; - import java.util.List; import java.util.Set; @@ -12,13 +11,8 @@ import java.util.Set; * @author Zheng Jie * @date 2019-03-25 */ -public interface DeptRepository extends JpaRepository, JpaSpecificationExecutor { +public interface DeptRepository extends JpaRepository, JpaSpecificationExecutor { - /** - * findByPid - * @param id - * @return - */ List findByPid(Long id); @Query(value = "select name from dept where id = ?1",nativeQuery = true) diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DictDetailRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DictDetailRepository.java index 6a8a036f..b394a7ba 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DictDetailRepository.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DictDetailRepository.java @@ -8,5 +8,5 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; * @author Zheng Jie * @date 2019-04-10 */ -public interface DictDetailRepository extends JpaRepository, JpaSpecificationExecutor { +public interface DictDetailRepository extends JpaRepository, JpaSpecificationExecutor { } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DictRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DictRepository.java index 699f130b..f472a014 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DictRepository.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/DictRepository.java @@ -8,5 +8,5 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; * @author Zheng Jie * @date 2019-04-10 */ -public interface DictRepository extends JpaRepository, JpaSpecificationExecutor { +public interface DictRepository extends JpaRepository, JpaSpecificationExecutor { } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/JobRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/JobRepository.java index 38908a28..46f42739 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/JobRepository.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/JobRepository.java @@ -8,5 +8,5 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; * @author Zheng Jie * @date 2019-03-29 */ -public interface JobRepository extends JpaRepository, JpaSpecificationExecutor { +public interface JobRepository extends JpaRepository, JpaSpecificationExecutor { } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/MenuRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/MenuRepository.java index 91c6d798..0d0876be 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/MenuRepository.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/MenuRepository.java @@ -1,41 +1,22 @@ package me.zhengjie.modules.system.repository; import me.zhengjie.modules.system.domain.Menu; -import me.zhengjie.modules.system.domain.Role; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; -import java.util.Set; /** * @author Zheng Jie * @date 2018-12-17 */ -public interface MenuRepository extends JpaRepository, JpaSpecificationExecutor { +public interface MenuRepository extends JpaRepository, JpaSpecificationExecutor { - /** - * findByName - * @param name - * @return - */ Menu findByName(String name); - /** - * findByName - * @param name - * @return - */ Menu findByComponentName(String name); - /** - * findByPid - * @param pid - * @return - */ List findByPid(long pid); - LinkedHashSet findByRoles_IdOrderBySortAsc(Long id); + LinkedHashSet findByRoles_IdAndTypeIsNotInOrderBySortAsc(Long id, Integer type); } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/PermissionRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/PermissionRepository.java deleted file mode 100644 index f27e8653..00000000 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/PermissionRepository.java +++ /dev/null @@ -1,27 +0,0 @@ -package me.zhengjie.modules.system.repository; - -import me.zhengjie.modules.system.domain.Permission; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import java.util.List; - -/** - * @author Zheng Jie - * @date 2018-12-03 - */ -public interface PermissionRepository extends JpaRepository, JpaSpecificationExecutor { - - /** - * findByName - * @param name - * @return - */ - Permission findByName(String name); - - /** - * findByPid - * @param pid - * @return - */ - List findByPid(long pid); -} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/RoleRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/RoleRepository.java index 1e2b15ae..7731ade5 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/RoleRepository.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/RoleRepository.java @@ -5,28 +5,18 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; - import java.util.Set; /** * @author Zheng Jie * @date 2018-12-03 */ -public interface RoleRepository extends JpaRepository, JpaSpecificationExecutor { +public interface RoleRepository extends JpaRepository, JpaSpecificationExecutor { - /** - * findByName - * @param name - * @return - */ Role findByName(String name); Set findByUsers_Id(Long id); - @Modifying - @Query(value = "delete from roles_permissions where permission_id = ?1",nativeQuery = true) - void untiedPermission(Long id); - @Modifying @Query(value = "delete from roles_menus where menu_id = ?1",nativeQuery = true) void untiedMenu(Long id); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/UserAvatarRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/UserAvatarRepository.java index 38136f85..1e7e058c 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/UserAvatarRepository.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/UserAvatarRepository.java @@ -4,12 +4,10 @@ import me.zhengjie.modules.system.domain.UserAvatar; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import java.util.Date; - /** * @author Zheng Jie * @date 2018-11-22 */ -public interface UserAvatarRepository extends JpaRepository, JpaSpecificationExecutor { +public interface UserAvatarRepository extends JpaRepository, JpaSpecificationExecutor { } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/UserRepository.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/UserRepository.java index 6ccf3fdb..186ecf02 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/UserRepository.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/repository/UserRepository.java @@ -1,59 +1,26 @@ package me.zhengjie.modules.system.repository; import me.zhengjie.modules.system.domain.User; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import java.util.Date; -import java.util.List; /** * @author Zheng Jie * @date 2018-11-22 */ -public interface UserRepository extends JpaRepository, JpaSpecificationExecutor { +public interface UserRepository extends JpaRepository, JpaSpecificationExecutor { - /** - * findByUsername - * @param username - * @return - */ User findByUsername(String username); - /** - * findByEmail - * @param email - * @return - */ User findByEmail(String email); - /** - * 修改密码 - * @param username - * @param pass - */ @Modifying @Query(value = "update user set password = ?2 , last_password_reset_time = ?3 where username = ?1",nativeQuery = true) void updatePass(String username, String pass, Date lastPasswordResetTime); - /** - * 修改头像 - * @param username - * @param url - */ - @Modifying - @Query(value = "update user set avatar = ?2 where username = ?1",nativeQuery = true) - void updateAvatar(String username, String url); - - /** - * 修改邮箱 - * @param username - * @param email - */ @Modifying @Query(value = "update user set email = ?2 where username = ?1",nativeQuery = true) void updateEmail(String username, String email); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DeptController.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DeptController.java index b57946bf..ecebf634 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DeptController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DeptController.java @@ -1,5 +1,7 @@ package me.zhengjie.modules.system.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import me.zhengjie.aop.log.Log; import me.zhengjie.config.DataScope; import me.zhengjie.exception.BadRequestException; @@ -8,12 +10,14 @@ import me.zhengjie.modules.system.service.DeptService; import me.zhengjie.modules.system.service.dto.DeptDTO; import me.zhengjie.modules.system.service.dto.DeptQueryCriteria; import me.zhengjie.utils.ThrowableUtil; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.List; /** @@ -21,48 +25,64 @@ import java.util.List; * @date 2019-03-25 */ @RestController -@RequestMapping("api") +@Api(tags = "系统:部门管理") +@RequestMapping("/api/dept") public class DeptController { - @Autowired - private DeptService deptService; + private final DeptService deptService; - @Autowired - private DataScope dataScope; + private final DataScope dataScope; private static final String ENTITY_NAME = "dept"; + public DeptController(DeptService deptService, DataScope dataScope) { + this.deptService = deptService; + this.dataScope = dataScope; + } + + @Log("导出部门数据") + @ApiOperation("导出部门数据") + @GetMapping(value = "/download") + @PreAuthorize("@el.check('dept:list')") + public void download(HttpServletResponse response, DeptQueryCriteria criteria) throws IOException { + deptService.download(deptService.queryAll(criteria), response); + } + @Log("查询部门") - @GetMapping(value = "/dept") - @PreAuthorize("hasAnyRole('ADMIN','USER_ALL','USER_SELECT','DEPT_ALL','DEPT_SELECT')") + @ApiOperation("查询部门") + @GetMapping + @PreAuthorize("@el.check('user:list','dept:list')") public ResponseEntity getDepts(DeptQueryCriteria criteria){ // 数据权限 criteria.setIds(dataScope.getDeptIds()); List deptDTOS = deptService.queryAll(criteria); - return new ResponseEntity(deptService.buildTree(deptDTOS),HttpStatus.OK); + return new ResponseEntity<>(deptService.buildTree(deptDTOS),HttpStatus.OK); } @Log("新增部门") - @PostMapping(value = "/dept") - @PreAuthorize("hasAnyRole('ADMIN','DEPT_ALL','DEPT_CREATE')") + @ApiOperation("新增部门") + @PostMapping + @PreAuthorize("@el.check('dept:add')") public ResponseEntity create(@Validated @RequestBody Dept resources){ if (resources.getId() != null) { throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); } - return new ResponseEntity(deptService.create(resources),HttpStatus.CREATED); + return new ResponseEntity<>(deptService.create(resources),HttpStatus.CREATED); } @Log("修改部门") - @PutMapping(value = "/dept") - @PreAuthorize("hasAnyRole('ADMIN','DEPT_ALL','DEPT_EDIT')") + @ApiOperation("修改部门") + @PutMapping + @PreAuthorize("@el.check('dept:edit')") public ResponseEntity update(@Validated(Dept.Update.class) @RequestBody Dept resources){ deptService.update(resources); return new ResponseEntity(HttpStatus.NO_CONTENT); } @Log("删除部门") - @DeleteMapping(value = "/dept/{id}") - @PreAuthorize("hasAnyRole('ADMIN','DEPT_ALL','DEPT_DELETE')") + @ApiOperation("删除部门") + @DeleteMapping(value = "/{id}") + @PreAuthorize("@el.check('dept:del')") public ResponseEntity delete(@PathVariable Long id){ try { deptService.delete(id); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DictController.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DictController.java index 9480bb60..99f89ff6 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DictController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DictController.java @@ -1,11 +1,12 @@ package me.zhengjie.modules.system.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import me.zhengjie.aop.log.Log; import me.zhengjie.exception.BadRequestException; import me.zhengjie.modules.system.domain.Dict; import me.zhengjie.modules.system.service.DictService; import me.zhengjie.modules.system.service.dto.DictQueryCriteria; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -13,47 +14,66 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + /** * @author Zheng Jie * @date 2019-04-10 */ +@Api(tags = "系统:字典管理") @RestController -@RequestMapping("api") +@RequestMapping("/api/dict") public class DictController { - @Autowired - private DictService dictService; + private final DictService dictService; private static final String ENTITY_NAME = "dict"; + public DictController(DictService dictService) { + this.dictService = dictService; + } + + @Log("导出字典数据") + @ApiOperation("导出字典数据") + @GetMapping(value = "/download") + @PreAuthorize("@el.check('dict:list')") + public void download(HttpServletResponse response, DictQueryCriteria criteria) throws IOException { + dictService.download(dictService.queryAll(criteria), response); + } + @Log("查询字典") - @GetMapping(value = "/dict") - @PreAuthorize("hasAnyRole('ADMIN','DICT_ALL','DICT_SELECT')") + @ApiOperation("查询字典") + @GetMapping + @PreAuthorize("@el.check('dict:list')") public ResponseEntity getDicts(DictQueryCriteria resources, Pageable pageable){ - return new ResponseEntity(dictService.queryAll(resources,pageable),HttpStatus.OK); + return new ResponseEntity<>(dictService.queryAll(resources,pageable),HttpStatus.OK); } @Log("新增字典") - @PostMapping(value = "/dict") - @PreAuthorize("hasAnyRole('ADMIN','DICT_ALL','DICT_CREATE')") + @ApiOperation("新增字典") + @PostMapping + @PreAuthorize("@el.check('dict:add')") public ResponseEntity create(@Validated @RequestBody Dict resources){ if (resources.getId() != null) { throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); } - return new ResponseEntity(dictService.create(resources),HttpStatus.CREATED); + return new ResponseEntity<>(dictService.create(resources),HttpStatus.CREATED); } @Log("修改字典") - @PutMapping(value = "/dict") - @PreAuthorize("hasAnyRole('ADMIN','DICT_ALL','DICT_EDIT')") + @ApiOperation("修改字典") + @PutMapping + @PreAuthorize("@el.check('dict:edit')") public ResponseEntity update(@Validated(Dict.Update.class) @RequestBody Dict resources){ dictService.update(resources); return new ResponseEntity(HttpStatus.NO_CONTENT); } @Log("删除字典") - @DeleteMapping(value = "/dict/{id}") - @PreAuthorize("hasAnyRole('ADMIN','DICT_ALL','DICT_DELETE')") + @ApiOperation("删除字典") + @DeleteMapping(value = "/{id}") + @PreAuthorize("@el.check('dict:del')") public ResponseEntity delete(@PathVariable Long id){ dictService.delete(id); return new ResponseEntity(HttpStatus.OK); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DictDetailController.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DictDetailController.java index a15107fa..0c463994 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DictDetailController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/DictDetailController.java @@ -1,11 +1,12 @@ package me.zhengjie.modules.system.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import me.zhengjie.aop.log.Log; import me.zhengjie.exception.BadRequestException; import me.zhengjie.modules.system.domain.DictDetail; import me.zhengjie.modules.system.service.DictDetailService; import me.zhengjie.modules.system.service.dto.DictDetailQueryCriteria; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; @@ -14,67 +15,72 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; - -import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.stream.Collectors; /** * @author Zheng Jie * @date 2019-04-10 */ @RestController -@RequestMapping("api") +@Api(tags = "系统:字典详情管理") +@RequestMapping("/api/dictDetail") public class DictDetailController { - @Autowired - private DictDetailService dictDetailService; + private final DictDetailService dictDetailService; private static final String ENTITY_NAME = "dictDetail"; + public DictDetailController(DictDetailService dictDetailService) { + this.dictDetailService = dictDetailService; + } + @Log("查询字典详情") - @GetMapping(value = "/dictDetail") + @ApiOperation("查询字典详情") + @GetMapping public ResponseEntity getDictDetails(DictDetailQueryCriteria criteria, - @PageableDefault(value = 10, sort = {"sort"}, direction = Sort.Direction.ASC) Pageable pageable){ - String[] names = criteria.getDictName().split(","); - return new ResponseEntity(dictDetailService.queryAll(criteria,pageable),HttpStatus.OK); + @PageableDefault(sort = {"sort"}, direction = Sort.Direction.ASC) Pageable pageable){ + return new ResponseEntity<>(dictDetailService.queryAll(criteria,pageable),HttpStatus.OK); } @Log("查询多个字典详情") - @GetMapping(value = "/dictDetail/map") + @ApiOperation("查询多个字典详情") + @GetMapping(value = "/map") public ResponseEntity getDictDetailMaps(DictDetailQueryCriteria criteria, - @PageableDefault(value = 10, sort = {"sort"}, direction = Sort.Direction.ASC) Pageable pageable){ + @PageableDefault(sort = {"sort"}, direction = Sort.Direction.ASC) Pageable pageable){ String[] names = criteria.getDictName().split(","); - Map map = new HashMap(names.length); + Map map = new HashMap<>(names.length); for (String name : names) { criteria.setDictName(name); map.put(name,dictDetailService.queryAll(criteria,pageable).get("content")); } - return new ResponseEntity(map,HttpStatus.OK); + return new ResponseEntity<>(map,HttpStatus.OK); } @Log("新增字典详情") - @PostMapping(value = "/dictDetail") - @PreAuthorize("hasAnyRole('ADMIN','DICT_ALL','DICT_CREATE')") + @ApiOperation("新增字典详情") + @PostMapping + @PreAuthorize("@el.check('dict:add')") public ResponseEntity create(@Validated @RequestBody DictDetail resources){ if (resources.getId() != null) { throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); } - return new ResponseEntity(dictDetailService.create(resources),HttpStatus.CREATED); + return new ResponseEntity<>(dictDetailService.create(resources),HttpStatus.CREATED); } @Log("修改字典详情") - @PutMapping(value = "/dictDetail") - @PreAuthorize("hasAnyRole('ADMIN','DICT_ALL','DICT_EDIT')") + @ApiOperation("修改字典详情") + @PutMapping + @PreAuthorize("@el.check('dict:edit')") public ResponseEntity update(@Validated(DictDetail.Update.class) @RequestBody DictDetail resources){ dictDetailService.update(resources); return new ResponseEntity(HttpStatus.NO_CONTENT); } @Log("删除字典详情") - @DeleteMapping(value = "/dictDetail/{id}") - @PreAuthorize("hasAnyRole('ADMIN','DICT_ALL','DICT_DELETE')") + @ApiOperation("删除字典详情") + @DeleteMapping(value = "/{id}") + @PreAuthorize("@el.check('dict:del')") public ResponseEntity delete(@PathVariable Long id){ dictDetailService.delete(id); return new ResponseEntity(HttpStatus.OK); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/JobController.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/JobController.java index 5694ea0c..97b88ae2 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/JobController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/JobController.java @@ -1,5 +1,7 @@ package me.zhengjie.modules.system.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import me.zhengjie.aop.log.Log; import me.zhengjie.config.DataScope; import me.zhengjie.exception.BadRequestException; @@ -7,7 +9,6 @@ import me.zhengjie.modules.system.domain.Job; import me.zhengjie.modules.system.service.JobService; import me.zhengjie.modules.system.service.dto.JobQueryCriteria; import me.zhengjie.utils.ThrowableUtil; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -15,55 +16,72 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.Set; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; /** * @author Zheng Jie * @date 2019-03-29 */ +@Api(tags = "系统:岗位管理") @RestController -@RequestMapping("api") +@RequestMapping("/api/job") public class JobController { - @Autowired - private JobService jobService; + private final JobService jobService; - @Autowired - private DataScope dataScope; + private final DataScope dataScope; private static final String ENTITY_NAME = "job"; + public JobController(JobService jobService, DataScope dataScope) { + this.jobService = jobService; + this.dataScope = dataScope; + } + + @Log("导出岗位数据") + @ApiOperation("导出岗位数据") + @GetMapping(value = "/download") + @PreAuthorize("@el.check('job:list')") + public void download(HttpServletResponse response, JobQueryCriteria criteria) throws IOException { + jobService.download(jobService.queryAll(criteria), response); + } + @Log("查询岗位") - @GetMapping(value = "/job") - @PreAuthorize("hasAnyRole('ADMIN','USERJOB_ALL','USERJOB_SELECT','USER_ALL','USER_SELECT')") + @ApiOperation("查询岗位") + @GetMapping + @PreAuthorize("@el.check('job:list','user:list')") public ResponseEntity getJobs(JobQueryCriteria criteria, Pageable pageable){ // 数据权限 criteria.setDeptIds(dataScope.getDeptIds()); - return new ResponseEntity(jobService.queryAll(criteria, pageable),HttpStatus.OK); + return new ResponseEntity<>(jobService.queryAll(criteria, pageable),HttpStatus.OK); } @Log("新增岗位") - @PostMapping(value = "/job") - @PreAuthorize("hasAnyRole('ADMIN','USERJOB_ALL','USERJOB_CREATE')") + @ApiOperation("新增岗位") + @PostMapping + @PreAuthorize("@el.check('job:add')") public ResponseEntity create(@Validated @RequestBody Job resources){ if (resources.getId() != null) { throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); } - return new ResponseEntity(jobService.create(resources),HttpStatus.CREATED); + return new ResponseEntity<>(jobService.create(resources),HttpStatus.CREATED); } @Log("修改岗位") - @PutMapping(value = "/job") - @PreAuthorize("hasAnyRole('ADMIN','USERJOB_ALL','USERJOB_EDIT')") + @ApiOperation("修改岗位") + @PutMapping + @PreAuthorize("@el.check('job:edit')") public ResponseEntity update(@Validated(Job.Update.class) @RequestBody Job resources){ jobService.update(resources); return new ResponseEntity(HttpStatus.NO_CONTENT); } @Log("删除岗位") - @DeleteMapping(value = "/job/{id}") - @PreAuthorize("hasAnyRole('ADMIN','USERJOB_ALL','USERJOB_DELETE')") + @ApiOperation("删除岗位") + @DeleteMapping(value = "/{id}") + @PreAuthorize("@el.check('job:del')") public ResponseEntity delete(@PathVariable Long id){ try { jobService.delete(id); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/MenuController.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/MenuController.java index 37a65a2b..6d718602 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/MenuController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/MenuController.java @@ -1,5 +1,7 @@ package me.zhengjie.modules.system.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import me.zhengjie.aop.log.Log; import me.zhengjie.modules.system.domain.Menu; import me.zhengjie.exception.BadRequestException; @@ -10,12 +12,14 @@ import me.zhengjie.modules.system.service.dto.MenuDTO; import me.zhengjie.modules.system.service.dto.MenuQueryCriteria; import me.zhengjie.modules.system.service.dto.UserDTO; import me.zhengjie.utils.SecurityUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -24,72 +28,83 @@ import java.util.Set; * @author Zheng Jie * @date 2018-12-03 */ +@Api(tags = "系统:菜单管理") @RestController -@RequestMapping("api") +@RequestMapping("/api/menus") +@SuppressWarnings("unchecked") public class MenuController { - @Autowired - private MenuService menuService; + private final MenuService menuService; - @Autowired - private UserService userService; + private final UserService userService; - @Autowired - private RoleService roleService; + private final RoleService roleService; private static final String ENTITY_NAME = "menu"; - /** - * 构建前端路由所需要的菜单 - * @return - */ - @GetMapping(value = "/menus/build") + public MenuController(MenuService menuService, UserService userService, RoleService roleService) { + this.menuService = menuService; + this.userService = userService; + this.roleService = roleService; + } + + @Log("导出菜单数据") + @ApiOperation("导出菜单数据") + @GetMapping(value = "/download") + @PreAuthorize("@el.check('menu:list')") + public void download(HttpServletResponse response, MenuQueryCriteria criteria) throws IOException { + menuService.download(menuService.queryAll(criteria), response); + } + + @ApiOperation("获取前端所需菜单") + @GetMapping(value = "/build") public ResponseEntity buildMenus(){ UserDTO user = userService.findByName(SecurityUtils.getUsername()); List menuDTOList = menuService.findByRoles(roleService.findByUsers_Id(user.getId())); - List menuDTOTree = (List)menuService.buildTree(menuDTOList).get("content"); - return new ResponseEntity(menuService.buildMenus(menuDTOTree),HttpStatus.OK); + List menuDTOS = (List) menuService.buildTree(menuDTOList).get("content"); + return new ResponseEntity<>(menuService.buildMenus(menuDTOS),HttpStatus.OK); } - /** - * 返回全部的菜单 - * @return - */ - @GetMapping(value = "/menus/tree") - @PreAuthorize("hasAnyRole('ADMIN','MENU_ALL','MENU_CREATE','MENU_EDIT','ROLES_SELECT','ROLES_ALL')") + @ApiOperation("返回全部的菜单") + @GetMapping(value = "/tree") + @PreAuthorize("@el.check('menu:list','roles:list')") public ResponseEntity getMenuTree(){ - return new ResponseEntity(menuService.getMenuTree(menuService.findByPid(0L)),HttpStatus.OK); + return new ResponseEntity<>(menuService.getMenuTree(menuService.findByPid(0L)),HttpStatus.OK); } @Log("查询菜单") - @GetMapping(value = "/menus") - @PreAuthorize("hasAnyRole('ADMIN','MENU_ALL','MENU_SELECT')") + @ApiOperation("查询菜单") + @GetMapping + @PreAuthorize("@el.check('menu:list')") public ResponseEntity getMenus(MenuQueryCriteria criteria){ List menuDTOList = menuService.queryAll(criteria); - return new ResponseEntity(menuService.buildTree(menuDTOList),HttpStatus.OK); + return new ResponseEntity<>(menuService.buildTree(menuDTOList),HttpStatus.OK); } @Log("新增菜单") - @PostMapping(value = "/menus") - @PreAuthorize("hasAnyRole('ADMIN','MENU_ALL','MENU_CREATE')") + @ApiOperation("新增菜单") + @PostMapping + @PreAuthorize("@el.check('menu:add')") public ResponseEntity create(@Validated @RequestBody Menu resources){ if (resources.getId() != null) { throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); } - return new ResponseEntity(menuService.create(resources),HttpStatus.CREATED); + return new ResponseEntity<>(menuService.create(resources),HttpStatus.CREATED); } @Log("修改菜单") - @PutMapping(value = "/menus") - @PreAuthorize("hasAnyRole('ADMIN','MENU_ALL','MENU_EDIT')") + @ApiOperation("修改菜单") + @PutMapping + @PreAuthorize("@el.check('menu:edit')") public ResponseEntity update(@Validated(Menu.Update.class) @RequestBody Menu resources){ menuService.update(resources); return new ResponseEntity(HttpStatus.NO_CONTENT); } @Log("删除菜单") - @DeleteMapping(value = "/menus/{id}") - @PreAuthorize("hasAnyRole('ADMIN','MENU_ALL','MENU_DELETE')") + @ApiOperation("删除菜单") + @DeleteMapping(value = "/{id}") + @PreAuthorize("@el.check('menu:del')") public ResponseEntity delete(@PathVariable Long id){ List menuList = menuService.findByPid(id); Set menuSet = new HashSet<>(); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/PermissionController.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/PermissionController.java deleted file mode 100644 index 216c838a..00000000 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/PermissionController.java +++ /dev/null @@ -1,84 +0,0 @@ -package me.zhengjie.modules.system.rest; - -import me.zhengjie.aop.log.Log; -import me.zhengjie.modules.system.domain.Permission; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.system.service.PermissionService; -import me.zhengjie.modules.system.service.dto.PermissionDTO; -import me.zhengjie.modules.system.service.dto.PermissionQueryCriteria; -import me.zhengjie.modules.system.service.mapper.PermissionMapper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-12-03 - */ -@RestController -@RequestMapping("api") -public class PermissionController { - - @Autowired - private PermissionService permissionService; - - @Autowired - private PermissionMapper permissionMapper; - - private static final String ENTITY_NAME = "permission"; - - /** - * 返回全部的权限,新增角色时下拉选择 - * @return - */ - @GetMapping(value = "/permissions/tree") - @PreAuthorize("hasAnyRole('ADMIN','PERMISSION_ALL','PERMISSION_CREATE','PERMISSION_EDIT','ROLES_SELECT','ROLES_ALL')") - public ResponseEntity getTree(){ - return new ResponseEntity(permissionService.getPermissionTree(permissionService.findByPid(0L)),HttpStatus.OK); - } - - @Log("查询权限") - @GetMapping(value = "/permissions") - @PreAuthorize("hasAnyRole('ADMIN','PERMISSION_ALL','PERMISSION_SELECT')") - public ResponseEntity getPermissions(PermissionQueryCriteria criteria){ - List permissionDTOS = permissionService.queryAll(criteria); - return new ResponseEntity(permissionService.buildTree(permissionDTOS),HttpStatus.OK); - } - - @Log("新增权限") - @PostMapping(value = "/permissions") - @PreAuthorize("hasAnyRole('ADMIN','PERMISSION_ALL','PERMISSION_CREATE')") - public ResponseEntity create(@Validated @RequestBody Permission resources){ - if (resources.getId() != null) { - throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); - } - return new ResponseEntity(permissionService.create(resources),HttpStatus.CREATED); - } - - @Log("修改权限") - @PutMapping(value = "/permissions") - @PreAuthorize("hasAnyRole('ADMIN','PERMISSION_ALL','PERMISSION_EDIT')") - public ResponseEntity update(@Validated(Permission.Update.class) @RequestBody Permission resources){ - permissionService.update(resources); - return new ResponseEntity(HttpStatus.NO_CONTENT); - } - - @Log("删除权限") - @DeleteMapping(value = "/permissions/{id}") - @PreAuthorize("hasAnyRole('ADMIN','PERMISSION_ALL','PERMISSION_DELETE')") - public ResponseEntity delete(@PathVariable Long id){ - List permissions = permissionService.findByPid(id); - Set permissionSet = new HashSet<>(); - permissionSet.add(permissionMapper.toEntity(permissionService.findById(id))); - permissionSet = permissionService.getDeletePermission(permissions, permissionSet); - permissionService.delete(permissionSet); - return new ResponseEntity(HttpStatus.OK); - } -} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/RoleController.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/RoleController.java index 340aa63c..cbbb7d96 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/RoleController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/RoleController.java @@ -1,6 +1,8 @@ package me.zhengjie.modules.system.rest; import cn.hutool.core.lang.Dict; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import me.zhengjie.aop.log.Log; import me.zhengjie.modules.system.domain.Role; import me.zhengjie.exception.BadRequestException; @@ -9,17 +11,17 @@ import me.zhengjie.modules.system.service.dto.RoleQueryCriteria; import me.zhengjie.modules.system.service.dto.RoleSmallDTO; import me.zhengjie.utils.SecurityUtils; import me.zhengjie.utils.ThrowableUtil; -import org.hibernate.exception.ConstraintViolationException; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.transaction.TransactionSystemException; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -28,86 +30,89 @@ import java.util.stream.Collectors; * @author Zheng Jie * @date 2018-12-03 */ +@Api(tags = "系统:角色管理") @RestController -@RequestMapping("api") +@RequestMapping("/api/roles") public class RoleController { - @Autowired - private RoleService roleService; + private final RoleService roleService; private static final String ENTITY_NAME = "role"; - /** - * 获取单个role - * @param id - * @return - */ - @GetMapping(value = "/roles/{id}") - @PreAuthorize("hasAnyRole('ADMIN','ROLES_ALL','ROLES_SELECT')") - public ResponseEntity getRoles(@PathVariable Long id){ - return new ResponseEntity(roleService.findById(id), HttpStatus.OK); + public RoleController(RoleService roleService) { + this.roleService = roleService; } - /** - * 返回全部的角色,新增用户时下拉选择 - * @return - */ - @GetMapping(value = "/roles/all") - @PreAuthorize("hasAnyRole('ADMIN','ROLES_ALL','USER_ALL','USER_CREATE','USER_EDIT')") + @ApiOperation("获取单个role") + @GetMapping(value = "/{id}") + @PreAuthorize("@el.check('roles:list')") + public ResponseEntity getRoles(@PathVariable Long id){ + return new ResponseEntity<>(roleService.findById(id), HttpStatus.OK); + } + + @Log("导出角色数据") + @ApiOperation("导出角色数据") + @GetMapping(value = "/download") + @PreAuthorize("@el.check('role:list')") + public void download(HttpServletResponse response, RoleQueryCriteria criteria) throws IOException { + roleService.download(roleService.queryAll(criteria), response); + } + + @ApiOperation("返回全部的角色") + @GetMapping(value = "/all") + @PreAuthorize("@el.check('roles:list','user:add','user:edit')") public ResponseEntity getAll(@PageableDefault(value = 2000, sort = {"level"}, direction = Sort.Direction.ASC) Pageable pageable){ - return new ResponseEntity(roleService.queryAll(pageable),HttpStatus.OK); + return new ResponseEntity<>(roleService.queryAll(pageable),HttpStatus.OK); } @Log("查询角色") - @GetMapping(value = "/roles") - @PreAuthorize("hasAnyRole('ADMIN','ROLES_ALL','ROLES_SELECT')") + @ApiOperation("查询角色") + @GetMapping + @PreAuthorize("@el.check('roles:list')") public ResponseEntity getRoles(RoleQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity(roleService.queryAll(criteria,pageable),HttpStatus.OK); + return new ResponseEntity<>(roleService.queryAll(criteria,pageable),HttpStatus.OK); } - @GetMapping(value = "/roles/level") + @ApiOperation("获取用户级别") + @GetMapping(value = "/level") public ResponseEntity getLevel(){ List levels = roleService.findByUsers_Id(SecurityUtils.getUserId()).stream().map(RoleSmallDTO::getLevel).collect(Collectors.toList()); - return new ResponseEntity(Dict.create().set("level", Collections.min(levels)),HttpStatus.OK); + return new ResponseEntity<>(Dict.create().set("level", Collections.min(levels)),HttpStatus.OK); } @Log("新增角色") - @PostMapping(value = "/roles") - @PreAuthorize("hasAnyRole('ADMIN','ROLES_ALL','ROLES_CREATE')") + @ApiOperation("新增角色") + @PostMapping + @PreAuthorize("@el.check('roles:add')") public ResponseEntity create(@Validated @RequestBody Role resources){ if (resources.getId() != null) { throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); } - return new ResponseEntity(roleService.create(resources),HttpStatus.CREATED); + return new ResponseEntity<>(roleService.create(resources),HttpStatus.CREATED); } @Log("修改角色") - @PutMapping(value = "/roles") - @PreAuthorize("hasAnyRole('ADMIN','ROLES_ALL','ROLES_EDIT')") + @ApiOperation("修改角色") + @PutMapping + @PreAuthorize("@el.check('roles:edit')") public ResponseEntity update(@Validated(Role.Update.class) @RequestBody Role resources){ roleService.update(resources); return new ResponseEntity(HttpStatus.NO_CONTENT); } - @Log("修改角色权限") - @PutMapping(value = "/roles/permission") - @PreAuthorize("hasAnyRole('ADMIN','ROLES_ALL','ROLES_EDIT')") - public ResponseEntity updatePermission(@RequestBody Role resources){ - roleService.updatePermission(resources,roleService.findById(resources.getId())); - return new ResponseEntity(HttpStatus.NO_CONTENT); - } - @Log("修改角色菜单") - @PutMapping(value = "/roles/menu") - @PreAuthorize("hasAnyRole('ADMIN','ROLES_ALL','ROLES_EDIT')") + @ApiOperation("修改角色菜单") + @PutMapping(value = "/menu") + @PreAuthorize("@el.check('roles:edit')") public ResponseEntity updateMenu(@RequestBody Role resources){ roleService.updateMenu(resources,roleService.findById(resources.getId())); return new ResponseEntity(HttpStatus.NO_CONTENT); } @Log("删除角色") - @DeleteMapping(value = "/roles/{id}") - @PreAuthorize("hasAnyRole('ADMIN','ROLES_ALL','ROLES_DELETE')") + @ApiOperation("删除角色") + @DeleteMapping(value = "/{id}") + @PreAuthorize("@el.check('roles:del')") public ResponseEntity delete(@PathVariable Long id){ try { roleService.delete(id); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/UserController.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/UserController.java index 96bf7657..4084e068 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/UserController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/UserController.java @@ -1,8 +1,9 @@ package me.zhengjie.modules.system.rest; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import me.zhengjie.aop.log.Log; import me.zhengjie.config.DataScope; -import me.zhengjie.domain.Picture; import me.zhengjie.domain.VerificationCode; import me.zhengjie.modules.system.domain.User; import me.zhengjie.exception.BadRequestException; @@ -11,11 +12,9 @@ import me.zhengjie.modules.system.service.DeptService; import me.zhengjie.modules.system.service.RoleService; import me.zhengjie.modules.system.service.dto.RoleSmallDTO; import me.zhengjie.modules.system.service.dto.UserQueryCriteria; -import me.zhengjie.service.PictureService; import me.zhengjie.service.VerificationCodeService; import me.zhengjie.utils.*; import me.zhengjie.modules.system.service.UserService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -35,82 +34,82 @@ import java.util.stream.Collectors; * @author Zheng Jie * @date 2018-11-23 */ +@Api(tags = "系统:用户管理") @RestController -@RequestMapping("api") +@RequestMapping("/api/users") public class UserController { - @Autowired - private UserService userService; + private final UserService userService; - @Autowired - private PictureService pictureService; + private final DataScope dataScope; - @Autowired - private DataScope dataScope; + private final DeptService deptService; - @Autowired - private DeptService deptService; + private final RoleService roleService; - @Autowired - private RoleService roleService; + private final VerificationCodeService verificationCodeService; - @Autowired - private VerificationCodeService verificationCodeService; + public UserController(UserService userService, DataScope dataScope, DeptService deptService, RoleService roleService, VerificationCodeService verificationCodeService) { + this.userService = userService; + this.dataScope = dataScope; + this.deptService = deptService; + this.roleService = roleService; + this.verificationCodeService = verificationCodeService; + } @Log("导出用户数据") - @GetMapping(value = "/users/download") - @PreAuthorize("hasAnyRole('ADMIN','USER_ALL','USER_SELECT')") - public void update(HttpServletResponse response, UserQueryCriteria criteria) throws IOException { + @ApiOperation("导出用户数据") + @GetMapping(value = "/download") + @PreAuthorize("@el.check('user:list')") + public void download(HttpServletResponse response, UserQueryCriteria criteria) throws IOException { userService.download(userService.queryAll(criteria), response); } @Log("查询用户") - @GetMapping(value = "/users") - @PreAuthorize("hasAnyRole('ADMIN','USER_ALL','USER_SELECT')") + @ApiOperation("查询用户") + @GetMapping + @PreAuthorize("@el.check('user:list')") public ResponseEntity getUsers(UserQueryCriteria criteria, Pageable pageable){ Set deptSet = new HashSet<>(); Set result = new HashSet<>(); - if (!ObjectUtils.isEmpty(criteria.getDeptId())) { deptSet.add(criteria.getDeptId()); deptSet.addAll(dataScope.getDeptChildren(deptService.findByPid(criteria.getDeptId()))); } - // 数据权限 Set deptIds = dataScope.getDeptIds(); - // 查询条件不为空并且数据权限不为空则取交集 if (!CollectionUtils.isEmpty(deptIds) && !CollectionUtils.isEmpty(deptSet)){ - // 取交集 result.addAll(deptSet); result.retainAll(deptIds); - // 若无交集,则代表无数据权限 criteria.setDeptIds(result); if(result.size() == 0){ - return new ResponseEntity(PageUtil.toPage(null,0),HttpStatus.OK); - } else return new ResponseEntity(userService.queryAll(criteria,pageable),HttpStatus.OK); + return new ResponseEntity<>(PageUtil.toPage(null,0),HttpStatus.OK); + } else return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK); // 否则取并集 } else { result.addAll(deptSet); result.addAll(deptIds); criteria.setDeptIds(result); - return new ResponseEntity(userService.queryAll(criteria,pageable),HttpStatus.OK); + return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK); } } @Log("新增用户") - @PostMapping(value = "/users") - @PreAuthorize("hasAnyRole('ADMIN','USER_ALL','USER_CREATE')") + @ApiOperation("新增用户") + @PostMapping + @PreAuthorize("@el.check('user:add')") public ResponseEntity create(@Validated @RequestBody User resources){ checkLevel(resources); - return new ResponseEntity(userService.create(resources),HttpStatus.CREATED); + return new ResponseEntity<>(userService.create(resources),HttpStatus.CREATED); } @Log("修改用户") - @PutMapping(value = "/users") - @PreAuthorize("hasAnyRole('ADMIN','USER_ALL','USER_EDIT')") + @ApiOperation("修改用户") + @PutMapping + @PreAuthorize("@el.check('user:edit')") public ResponseEntity update(@Validated(User.Update.class) @RequestBody User resources){ checkLevel(resources); userService.update(resources); @@ -118,8 +117,9 @@ public class UserController { } @Log("删除用户") - @DeleteMapping(value = "/users/{id}") - @PreAuthorize("hasAnyRole('ADMIN','USER_ALL','USER_DELETE')") + @ApiOperation("删除用户") + @DeleteMapping(value = "/{id}") + @PreAuthorize("@el.check('user:del')") public ResponseEntity delete(@PathVariable Long id){ Integer currentLevel = Collections.min(roleService.findByUsers_Id(SecurityUtils.getUserId()).stream().map(RoleSmallDTO::getLevel).collect(Collectors.toList())); Integer optLevel = Collections.min(roleService.findByUsers_Id(id).stream().map(RoleSmallDTO::getLevel).collect(Collectors.toList())); @@ -131,12 +131,8 @@ public class UserController { return new ResponseEntity(HttpStatus.OK); } - /** - * 修改密码 - * @param user - * @return - */ - @PostMapping(value = "/users/updatePass") + @ApiOperation("修改密码") + @PostMapping(value = "/updatePass") public ResponseEntity updatePass(@RequestBody UserPassVo user){ UserDetails userDetails = SecurityUtils.getUserDetails(); if(!userDetails.getPassword().equals(EncryptUtils.encryptPassword(user.getOldPass()))){ @@ -149,25 +145,16 @@ public class UserController { return new ResponseEntity(HttpStatus.OK); } - /** - * 修改头像 - * @param file - * @return - */ - @PostMapping(value = "/users/updateAvatar") + @ApiOperation("修改头像") + @PostMapping(value = "/updateAvatar") public ResponseEntity updateAvatar(@RequestParam MultipartFile file){ userService.updateAvatar(file); return new ResponseEntity(HttpStatus.OK); } - /** - * 修改邮箱 - * @param user - * @param user - * @return - */ @Log("修改邮箱") - @PostMapping(value = "/users/updateEmail/{code}") + @ApiOperation("修改邮箱") + @PostMapping(value = "/updateEmail/{code}") public ResponseEntity updateEmail(@PathVariable String code,@RequestBody User user){ UserDetails userDetails = SecurityUtils.getUserDetails(); if(!userDetails.getPassword().equals(EncryptUtils.encryptPassword(user.getPassword()))){ @@ -179,11 +166,9 @@ public class UserController { return new ResponseEntity(HttpStatus.OK); } - - /** * 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误 - * @param resources + * @param resources / */ private void checkLevel(User resources) { Integer currentLevel = Collections.min(roleService.findByUsers_Id(SecurityUtils.getUserId()).stream().map(RoleSmallDTO::getLevel).collect(Collectors.toList())); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DeptService.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DeptService.java index 792ea137..10c342c8 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DeptService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DeptService.java @@ -3,10 +3,9 @@ package me.zhengjie.modules.system.service; import me.zhengjie.modules.system.domain.Dept; import me.zhengjie.modules.system.service.dto.DeptDTO; import me.zhengjie.modules.system.service.dto.DeptQueryCriteria; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.List; import java.util.Set; @@ -14,62 +13,23 @@ import java.util.Set; * @author Zheng Jie * @date 2019-03-25 */ -@CacheConfig(cacheNames = "dept") public interface DeptService { - /** - * queryAll - * @param criteria - * @return - */ - @Cacheable List queryAll(DeptQueryCriteria criteria); - /** - * findById - * @param id - * @return - */ - @Cacheable(key = "#p0") DeptDTO findById(Long id); - /** - * create - * @param resources - * @return - */ - @CacheEvict(allEntries = true) DeptDTO create(Dept resources); - /** - * update - * @param resources - */ - @CacheEvict(allEntries = true) void update(Dept resources); - /** - * delete - * @param id - */ - @CacheEvict(allEntries = true) void delete(Long id); - /** - * buildTree - * @param deptDTOS - * @return - */ - @Cacheable Object buildTree(List deptDTOS); - /** - * findByPid - * @param pid - * @return - */ - @Cacheable List findByPid(long pid); Set findByRoleIds(Long id); + + void download(List queryAll, HttpServletResponse response) throws IOException; } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DictDetailService.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DictDetailService.java index fe89a027..f6811ded 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DictDetailService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DictDetailService.java @@ -3,50 +3,22 @@ package me.zhengjie.modules.system.service; import me.zhengjie.modules.system.domain.DictDetail; import me.zhengjie.modules.system.service.dto.DictDetailDTO; import me.zhengjie.modules.system.service.dto.DictDetailQueryCriteria; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Pageable; - import java.util.Map; /** * @author Zheng Jie * @date 2019-04-10 */ -@CacheConfig(cacheNames = "dictDetail") public interface DictDetailService { - /** - * findById - * @param id - * @return - */ - @Cacheable(key = "#p0") DictDetailDTO findById(Long id); - /** - * create - * @param resources - * @return - */ - @CacheEvict(allEntries = true) DictDetailDTO create(DictDetail resources); - /** - * update - * @param resources - */ - @CacheEvict(allEntries = true) void update(DictDetail resources); - /** - * delete - * @param id - */ - @CacheEvict(allEntries = true) void delete(Long id); - @Cacheable Map queryAll(DictDetailQueryCriteria criteria, Pageable pageable); } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DictService.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DictService.java index e6f10538..8fa44130 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DictService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/DictService.java @@ -3,54 +3,30 @@ package me.zhengjie.modules.system.service; import me.zhengjie.modules.system.domain.Dict; import me.zhengjie.modules.system.service.dto.DictDTO; import me.zhengjie.modules.system.service.dto.DictQueryCriteria; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Pageable; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; +import java.util.Map; + /** * @author Zheng Jie * @date 2019-04-10 */ -@CacheConfig(cacheNames = "dict") public interface DictService { - /** - * 查询 - * @param dict - * @param pageable - * @return - */ - @Cacheable - Object queryAll(DictQueryCriteria dict, Pageable pageable); + Map queryAll(DictQueryCriteria dict, Pageable pageable); + + List queryAll(DictQueryCriteria dict); - /** - * findById - * @param id - * @return - */ - @Cacheable(key = "#p0") DictDTO findById(Long id); - /** - * create - * @param resources - * @return - */ - @CacheEvict(allEntries = true) DictDTO create(Dict resources); - /** - * update - * @param resources - */ - @CacheEvict(allEntries = true) void update(Dict resources); - /** - * delete - * @param id - */ - @CacheEvict(allEntries = true) void delete(Long id); + + void download(List queryAll, HttpServletResponse response) throws IOException; } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/JobService.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/JobService.java index ecd92a04..875b3bed 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/JobService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/JobService.java @@ -3,53 +3,30 @@ package me.zhengjie.modules.system.service; import me.zhengjie.modules.system.domain.Job; import me.zhengjie.modules.system.service.dto.JobDTO; import me.zhengjie.modules.system.service.dto.JobQueryCriteria; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Pageable; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; +import java.util.Map; + /** * @author Zheng Jie * @date 2019-03-29 */ -@CacheConfig(cacheNames = "job") public interface JobService { - /** - * findById - * @param id - * @return - */ - @Cacheable(key = "#p0") JobDTO findById(Long id); - /** - * create - * @param resources - * @return - */ - @CacheEvict(allEntries = true) JobDTO create(Job resources); - /** - * update - * @param resources - */ - @CacheEvict(allEntries = true) void update(Job resources); - /** - * delete - * @param id - */ - @CacheEvict(allEntries = true) void delete(Long id); - /** - * queryAll - * @param criteria - * @param pageable - * @return - */ - Object queryAll(JobQueryCriteria criteria, Pageable pageable); + Map queryAll(JobQueryCriteria criteria, Pageable pageable); + + List queryAll(JobQueryCriteria criteria); + + void download(List queryAll, HttpServletResponse response) throws IOException; } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/MenuService.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/MenuService.java index 3958c05f..cef99596 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/MenuService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/MenuService.java @@ -4,9 +4,9 @@ import me.zhengjie.modules.system.domain.Menu; import me.zhengjie.modules.system.service.dto.MenuDTO; import me.zhengjie.modules.system.service.dto.MenuQueryCriteria; import me.zhengjie.modules.system.service.dto.RoleSmallDTO; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Set; @@ -15,90 +15,31 @@ import java.util.Set; * @author Zheng Jie * @date 2018-12-17 */ -@CacheConfig(cacheNames = "menu") public interface MenuService { - /** - * queryAll - * @param criteria - * @return - */ - @Cacheable List queryAll(MenuQueryCriteria criteria); - /** - * get - * @param id - * @return - */ - @Cacheable(key = "#p0") MenuDTO findById(long id); - /** - * create - * @param resources - * @return - */ - @CacheEvict(allEntries = true) MenuDTO create(Menu resources); - /** - * update - * @param resources - */ - @CacheEvict(allEntries = true) void update(Menu resources); - /** - * getDeleteMenus - * @param menuList - * @param menuSet - * @return - */ Set getDeleteMenus(List menuList, Set menuSet); - /** - * permission tree - * @return - */ - @Cacheable(key = "'tree'") Object getMenuTree(List menus); - /** - * findByPid - * @param pid - * @return - */ - @Cacheable(key = "'pid:'+#p0") List findByPid(long pid); - /** - * build Tree - * @param menuDTOS - * @return - */ - Map buildTree(List menuDTOS); + Map buildTree(List menuDTOS); - /** - * findByRoles - * @param roles - * @return - */ List findByRoles(List roles); - /** - * buildMenus - * @param byRoles - * @return - */ Object buildMenus(List byRoles); Menu findOne(Long id); - /** - * delete - * @param menuSet - */ - @CacheEvict(allEntries = true) void delete(Set menuSet); + + void download(List queryAll, HttpServletResponse response) throws IOException; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/PermissionService.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/PermissionService.java deleted file mode 100644 index ec6ebc23..00000000 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/PermissionService.java +++ /dev/null @@ -1,82 +0,0 @@ -package me.zhengjie.modules.system.service; - -import me.zhengjie.modules.system.domain.Permission; -import me.zhengjie.modules.system.service.dto.PermissionDTO; -import me.zhengjie.modules.system.service.dto.PermissionQueryCriteria; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; - -import java.util.List; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-12-08 - */ -@CacheConfig(cacheNames = "permission") -public interface PermissionService { - - /** - * get - * @param id - * @return - */ - @Cacheable(key = "#p0") - PermissionDTO findById(long id); - - /** - * create - * @param resources - * @return - */ - @CacheEvict(allEntries = true) - PermissionDTO create(Permission resources); - - /** - * update - * @param resources - */ - @CacheEvict(allEntries = true) - void update(Permission resources); - - /** - * delete - * @param permissions - */ - @CacheEvict(allEntries = true) - void delete(Set permissions); - - /** - * permission tree - * @return - */ - @Cacheable(key = "'tree'") - Object getPermissionTree(List permissions); - - /** - * findByPid - * @param pid - * @return - */ - @Cacheable(key = "'pid:'+#p0") - List findByPid(long pid); - - /** - * build Tree - * @param permissionDTOS - * @return - */ - @Cacheable - Object buildTree(List permissionDTOS); - - /** - * queryAll - * @param criteria - * @return - */ - @Cacheable - List queryAll(PermissionQueryCriteria criteria); - - Set getDeletePermission(List permissions, Set permissionSet); -} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/RoleService.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/RoleService.java index 39973fce..88b96538 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/RoleService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/RoleService.java @@ -4,11 +4,10 @@ import me.zhengjie.modules.system.domain.Role; import me.zhengjie.modules.system.service.dto.RoleDTO; import me.zhengjie.modules.system.service.dto.RoleQueryCriteria; import me.zhengjie.modules.system.service.dto.RoleSmallDTO; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Pageable; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.List; import java.util.Set; @@ -16,95 +15,29 @@ import java.util.Set; * @author Zheng Jie * @date 2018-12-03 */ -@CacheConfig(cacheNames = "role") public interface RoleService { - /** - * get - * @param id - * @return - */ - @Cacheable(key = "#p0") RoleDTO findById(long id); - /** - * create - * @param resources - * @return - */ - @CacheEvict(allEntries = true) RoleDTO create(Role resources); - /** - * update - * @param resources - */ - @CacheEvict(allEntries = true) void update(Role resources); - /** - * delete - * @param id - */ - @CacheEvict(allEntries = true) void delete(Long id); - /** - * key的名称如有修改,请同步修改 UserServiceImpl 中的 update 方法 - * findByUsers_Id - * @param id - * @return - */ - @Cacheable(key = "'findByUsers_Id:' + #p0") List findByUsers_Id(Long id); - @Cacheable Integer findByRoles(Set roles); - /** - * updatePermission - * @param resources - * @param roleDTO - */ - @CacheEvict(allEntries = true) - void updatePermission(Role resources, RoleDTO roleDTO); - - /** - * updateMenu - * @param resources - * @param roleDTO - */ - @CacheEvict(allEntries = true) void updateMenu(Role resources, RoleDTO roleDTO); - @CacheEvict(allEntries = true) void untiedMenu(Long id); - /** - * queryAll - * @param pageable - * @return - */ - @Cacheable Object queryAll(Pageable pageable); - /** - * queryAll - * @param pageable - * @param criteria - * @return - */ - @Cacheable Object queryAll(RoleQueryCriteria criteria, Pageable pageable); - /** - * queryAll - * @param criteria - * @return - */ - @Cacheable List queryAll(RoleQueryCriteria criteria); - @CacheEvict(allEntries = true) - void untiedPermission(Long id); + void download(List queryAll, HttpServletResponse response) throws IOException; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/UserService.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/UserService.java index bedae91a..c404900b 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/UserService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/UserService.java @@ -1,15 +1,10 @@ package me.zhengjie.modules.system.service; import me.zhengjie.modules.system.domain.User; -import me.zhengjie.modules.security.security.JwtUser; import me.zhengjie.modules.system.service.dto.UserDTO; import me.zhengjie.modules.system.service.dto.UserQueryCriteria; -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.web.multipart.MultipartFile; - import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; @@ -18,74 +13,26 @@ import java.util.List; * @author Zheng Jie * @date 2018-11-23 */ -@CacheConfig(cacheNames = "user") public interface UserService { - /** - * get - * @param id - * @return - */ - @Cacheable(key = "#p0") UserDTO findById(long id); - /** - * create - * @param resources - * @return - */ - @CacheEvict(allEntries = true) UserDTO create(User resources); - /** - * update - * @param resources - */ - @CacheEvict(allEntries = true) void update(User resources); - /** - * delete - * @param id - */ - @CacheEvict(allEntries = true) void delete(Long id); - /** - * findByName - * @param userName - * @return - */ - @Cacheable(key = "'loadUserByUsername:'+#p0") UserDTO findByName(String userName); - /** - * 修改密码 - * @param username - * @param encryptPassword - */ - @CacheEvict(allEntries = true) void updatePass(String username, String encryptPassword); - /** - * 修改头像 - * @param file - */ - @CacheEvict(allEntries = true) void updateAvatar(MultipartFile file); - /** - * 修改邮箱 - * @param username - * @param email - */ - @CacheEvict(allEntries = true) void updateEmail(String username, String email); - @Cacheable Object queryAll(UserQueryCriteria criteria, Pageable pageable); - @Cacheable List queryAll(UserQueryCriteria criteria); void download(List queryAll, HttpServletResponse response) throws IOException; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptDTO.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptDTO.java index 47e808ee..2ef07409 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptDTO.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptDTO.java @@ -1,36 +1,31 @@ package me.zhengjie.modules.system.service.dto; import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.Data; - +import lombok.Getter; +import lombok.Setter; import javax.validation.constraints.NotNull; -import java.sql.Timestamp; import java.io.Serializable; +import java.sql.Timestamp; import java.util.List; /** * @author Zheng Jie * @date 2019-03-25 */ -@Data +@Getter +@Setter public class DeptDTO implements Serializable { - /** - * ID - */ + // ID private Long id; - /** - * 名称 - */ + // 名称 private String name; @NotNull private Boolean enabled; - /** - * 上级部门 - */ + // 上级部门 private Long pid; @JsonInclude(JsonInclude.Include.NON_EMPTY) diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptQueryCriteria.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptQueryCriteria.java index bb5000eb..165851b7 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptQueryCriteria.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptQueryCriteria.java @@ -2,6 +2,8 @@ package me.zhengjie.modules.system.service.dto; import lombok.Data; import me.zhengjie.annotation.Query; + +import java.sql.Timestamp; import java.util.Set; /** @@ -22,4 +24,10 @@ public class DeptQueryCriteria{ @Query private Long pid; + + @Query(type = Query.Type.GREATER_THAN,propName = "createTime") + private Timestamp startTime; + + @Query(type = Query.Type.LESS_THAN,propName = "createTime") + private Timestamp endTime; } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptSmallDTO.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptSmallDTO.java index 10620264..0956825d 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptSmallDTO.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptSmallDTO.java @@ -10,13 +10,7 @@ import java.io.Serializable; @Data public class DeptSmallDTO implements Serializable { - /** - * ID - */ private Long id; - /** - * 名称 - */ private String name; } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDTO.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDTO.java index a96a4895..c9753848 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDTO.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDTO.java @@ -1,24 +1,27 @@ package me.zhengjie.modules.system.service.dto; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; + import java.io.Serializable; +import java.sql.Timestamp; +import java.util.List; /** * @author Zheng Jie * @date 2019-04-10 */ -@Data +@Getter +@Setter public class DictDTO implements Serializable { private Long id; - /** - * 字典名称 - */ private String name; - /** - * 描述 - */ private String remark; + + private List dictDetails; + + private Timestamp createTime; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailDTO.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailDTO.java index b39fbb26..6cadec24 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailDTO.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailDTO.java @@ -1,29 +1,26 @@ package me.zhengjie.modules.system.service.dto; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; + import java.io.Serializable; +import java.sql.Timestamp; /** * @author Zheng Jie * @date 2019-04-10 */ -@Data +@Getter +@Setter public class DictDetailDTO implements Serializable { private Long id; - /** - * 字典标签 - */ private String label; - /** - * 字典值 - */ private String value; - /** - * 排序 - */ private String sort; + + private Timestamp createTime; } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobDTO.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobDTO.java index d61c5ee5..0f872195 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobDTO.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobDTO.java @@ -1,48 +1,33 @@ package me.zhengjie.modules.system.service.dto; -import lombok.Data; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import java.sql.Timestamp; import java.io.Serializable; +import java.sql.Timestamp; /** * @author Zheng Jie * @date 2019-03-29 */ -@Data +@Getter +@Setter @NoArgsConstructor public class JobDTO implements Serializable { - /** - * ID - */ private Long id; private Long sort; - /** - * 名称 - */ private String name; - /** - * 状态 - */ private Boolean enabled; private DeptDTO dept; - /** - * 如果分公司存在相同部门,则显示上级部门名称 - */ private String deptSuperiorName; - /** - * 创建日期 - */ private Timestamp createTime; public JobDTO(String name, Boolean enabled) { diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobQueryCriteria.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobQueryCriteria.java index 8d535fb5..313dd9e9 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobQueryCriteria.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobQueryCriteria.java @@ -27,4 +27,10 @@ public class JobQueryCriteria { @Query(propName = "id", joinName = "dept", type = Query.Type.IN) private Set deptIds; + + @Query(type = Query.Type.GREATER_THAN,propName = "createTime") + private Timestamp startTime; + + @Query(type = Query.Type.LESS_THAN,propName = "createTime") + private Timestamp endTime; } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobSmallDTO.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobSmallDTO.java index 2a364547..53c7c923 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobSmallDTO.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/JobSmallDTO.java @@ -12,13 +12,7 @@ import java.io.Serializable; @NoArgsConstructor public class JobSmallDTO implements Serializable { - /** - * ID - */ private Long id; - /** - * 名称 - */ private String name; } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuDTO.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuDTO.java index 3b9aaae6..6a4877a3 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuDTO.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuDTO.java @@ -1,20 +1,26 @@ package me.zhengjie.modules.system.service.dto; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import java.io.Serializable; import java.sql.Timestamp; import java.util.List; -import java.util.Set; /** * @author Zheng Jie * @date 2018-12-17 */ -@Data -public class MenuDTO { +@Getter +@Setter +public class MenuDTO implements Serializable { private Long id; + private Integer type; + + private String permission; + private String name; private Long sort; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuQueryCriteria.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuQueryCriteria.java index ccde232d..d0bf0693 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuQueryCriteria.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuQueryCriteria.java @@ -3,6 +3,8 @@ package me.zhengjie.modules.system.service.dto; import lombok.Data; import me.zhengjie.annotation.Query; +import java.sql.Timestamp; + /** * 公共查询类 */ @@ -12,4 +14,10 @@ public class MenuQueryCriteria { // 多字段模糊 @Query(blurry = "name,path,component") private String blurry; + + @Query(type = Query.Type.GREATER_THAN,propName = "createTime") + private Timestamp startTime; + + @Query(type = Query.Type.LESS_THAN,propName = "createTime") + private Timestamp endTime; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/PermissionDTO.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/PermissionDTO.java deleted file mode 100644 index 3ae4eb6a..00000000 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/PermissionDTO.java +++ /dev/null @@ -1,38 +0,0 @@ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; - -import java.io.Serializable; -import java.sql.Timestamp; -import java.util.List; - -/** - * @author Zheng Jie - * @date 2018-12-03 - */ -@Data -public class PermissionDTO implements Serializable{ - - private Long id; - - private String name; - - private Long pid; - - private String alias; - - private Timestamp createTime; - - private List children; - - @Override - public String toString() { - return "Permission{" + - "id=" + id + - ", name='" + name + '\'' + - ", pid=" + pid + - ", alias='" + alias + '\'' + - ", createTime=" + createTime + - '}'; - } -} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/PermissionQueryCriteria.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/PermissionQueryCriteria.java deleted file mode 100644 index 055b0ec4..00000000 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/PermissionQueryCriteria.java +++ /dev/null @@ -1,15 +0,0 @@ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; - -/** - * 公共查询类 - */ -@Data -public class PermissionQueryCriteria { - - // 多字段模糊 - @Query(blurry = "name,alias") - private String blurry; -} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleDTO.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleDTO.java index c6d68073..5d6ef351 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleDTO.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleDTO.java @@ -1,6 +1,8 @@ package me.zhengjie.modules.system.service.dto; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; + import java.io.Serializable; import java.sql.Timestamp; import java.util.Set; @@ -9,7 +11,8 @@ import java.util.Set; * @author Zheng Jie * @date 2018-11-23 */ -@Data +@Getter +@Setter public class RoleDTO implements Serializable { private Long id; @@ -22,7 +25,7 @@ public class RoleDTO implements Serializable { private String remark; - private Set permissions; + private String permission; private Set menus; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleQueryCriteria.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleQueryCriteria.java index 3c935889..59b00556 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleQueryCriteria.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleQueryCriteria.java @@ -3,6 +3,8 @@ package me.zhengjie.modules.system.service.dto; import lombok.Data; import me.zhengjie.annotation.Query; +import java.sql.Timestamp; + /** * 公共查询类 */ @@ -12,4 +14,10 @@ public class RoleQueryCriteria { // 多字段模糊 @Query(blurry = "name,remark") private String blurry; + + @Query(type = Query.Type.GREATER_THAN,propName = "createTime") + private Timestamp startTime; + + @Query(type = Query.Type.LESS_THAN,propName = "createTime") + private Timestamp endTime; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleSmallDTO.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleSmallDTO.java index 7e9d9fc1..1a6c7a04 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleSmallDTO.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleSmallDTO.java @@ -1,10 +1,7 @@ package me.zhengjie.modules.system.service.dto; import lombok.Data; - import java.io.Serializable; -import java.sql.Timestamp; -import java.util.Set; /** * @author Zheng Jie diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/UserDTO.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/UserDTO.java index 3065471b..9fe06409 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/UserDTO.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/UserDTO.java @@ -2,7 +2,9 @@ package me.zhengjie.modules.system.service.dto; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.annotations.ApiModelProperty; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; + import java.io.Serializable; import java.sql.Timestamp; import java.util.Date; @@ -12,7 +14,8 @@ import java.util.Set; * @author Zheng Jie * @date 2018-11-23 */ -@Data +@Getter +@Setter public class UserDTO implements Serializable { @ApiModelProperty(hidden = true) @@ -31,8 +34,6 @@ public class UserDTO implements Serializable { @JsonIgnore private String password; - private Timestamp createTime; - private Date lastPasswordResetTime; @ApiModelProperty(hidden = true) @@ -44,4 +45,6 @@ public class UserDTO implements Serializable { private DeptSmallDTO dept; private Long deptId; + + private Timestamp createTime; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/UserQueryCriteria.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/UserQueryCriteria.java index a69467c9..8195d732 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/UserQueryCriteria.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/dto/UserQueryCriteria.java @@ -3,6 +3,7 @@ package me.zhengjie.modules.system.service.dto; import lombok.Data; import me.zhengjie.annotation.Query; import java.io.Serializable; +import java.sql.Timestamp; import java.util.Set; /** @@ -26,4 +27,10 @@ public class UserQueryCriteria implements Serializable { private Boolean enabled; private Long deptId; + + @Query(type = Query.Type.GREATER_THAN,propName = "createTime") + private Timestamp startTime; + + @Query(type = Query.Type.LESS_THAN,propName = "createTime") + private Timestamp endTime; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DeptServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DeptServiceImpl.java index f56e1903..20fed2d8 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DeptServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DeptServiceImpl.java @@ -3,17 +3,23 @@ package me.zhengjie.modules.system.service.impl; import me.zhengjie.exception.BadRequestException; import me.zhengjie.modules.system.domain.Dept; import me.zhengjie.modules.system.service.dto.DeptQueryCriteria; +import me.zhengjie.utils.FileUtil; import me.zhengjie.utils.QueryHelp; import me.zhengjie.utils.ValidationUtil; import me.zhengjie.modules.system.repository.DeptRepository; import me.zhengjie.modules.system.service.DeptService; import me.zhengjie.modules.system.service.dto.DeptDTO; import me.zhengjie.modules.system.service.mapper.DeptMapper; -import org.springframework.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.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.*; import java.util.stream.Collectors; @@ -22,28 +28,35 @@ import java.util.stream.Collectors; * @date 2019-03-25 */ @Service +@CacheConfig(cacheNames = "dept") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class DeptServiceImpl implements DeptService { - @Autowired - private DeptRepository deptRepository; + private final DeptRepository deptRepository; - @Autowired - private DeptMapper deptMapper; + private final DeptMapper deptMapper; + + public DeptServiceImpl(DeptRepository deptRepository, DeptMapper deptMapper) { + this.deptRepository = deptRepository; + this.deptMapper = deptMapper; + } @Override + @Cacheable public List queryAll(DeptQueryCriteria criteria) { return deptMapper.toDto(deptRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))); } @Override + @Cacheable(key = "#p0") public DeptDTO findById(Long id) { - Optional dept = deptRepository.findById(id); - ValidationUtil.isNull(dept,"Dept","id",id); - return deptMapper.toDto(dept.get()); + Dept dept = deptRepository.findById(id).orElseGet(Dept::new); + ValidationUtil.isNull(dept.getId(),"Dept","id",id); + return deptMapper.toDto(dept); } @Override + @Cacheable public List findByPid(long pid) { return deptRepository.findByPid(pid); } @@ -54,11 +67,12 @@ public class DeptServiceImpl implements DeptService { } @Override + @Cacheable public Object buildTree(List deptDTOS) { Set trees = new LinkedHashSet<>(); Set depts= new LinkedHashSet<>(); List deptNames = deptDTOS.stream().map(DeptDTO::getName).collect(Collectors.toList()); - Boolean isChild; + boolean isChild; for (DeptDTO deptDTO : deptDTOS) { isChild = false; if ("0".equals(deptDTO.getPid().toString())) { @@ -68,7 +82,7 @@ public class DeptServiceImpl implements DeptService { if (it.getPid().equals(deptDTO.getId())) { isChild = true; if (deptDTO.getChildren() == null) { - deptDTO.setChildren(new ArrayList()); + deptDTO.setChildren(new ArrayList<>()); } deptDTO.getChildren().add(it); } @@ -83,36 +97,51 @@ public class DeptServiceImpl implements DeptService { trees = depts; } - Integer totalElements = deptDTOS!=null?deptDTOS.size():0; + Integer totalElements = deptDTOS.size(); - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("totalElements",totalElements); map.put("content",CollectionUtils.isEmpty(trees)?deptDTOS:trees); return map; } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public DeptDTO create(Dept resources) { return deptMapper.toDto(deptRepository.save(resources)); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void update(Dept resources) { if(resources.getId().equals(resources.getPid())) { throw new BadRequestException("上级不能为自己"); } - Optional optionalDept = deptRepository.findById(resources.getId()); - ValidationUtil.isNull( optionalDept,"Dept","id",resources.getId()); - Dept dept = optionalDept.get(); + Dept dept = deptRepository.findById(resources.getId()).orElseGet(Dept::new); + ValidationUtil.isNull( dept.getId(),"Dept","id",resources.getId()); resources.setId(dept.getId()); deptRepository.save(resources); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void delete(Long id) { deptRepository.deleteById(id); } + + @Override + public void download(List deptDTOs, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (DeptDTO deptDTO : deptDTOs) { + Map map = new LinkedHashMap<>(); + map.put("部门名称", deptDTO.getName()); + map.put("部门状态", deptDTO.getEnabled() ? "启用" : "停用"); + map.put("创建日期", deptDTO.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DictDetailServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DictDetailServiceImpl.java index d8970219..1374202f 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DictDetailServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DictDetailServiceImpl.java @@ -9,60 +9,68 @@ import me.zhengjie.modules.system.repository.DictDetailRepository; import me.zhengjie.modules.system.service.DictDetailService; import me.zhengjie.modules.system.service.dto.DictDetailDTO; import me.zhengjie.modules.system.service.mapper.DictDetailMapper; -import org.springframework.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.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; - import java.util.Map; -import java.util.Optional; /** * @author Zheng Jie * @date 2019-04-10 */ @Service +@CacheConfig(cacheNames = "dictDetail") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class DictDetailServiceImpl implements DictDetailService { - @Autowired - private DictDetailRepository dictDetailRepository; + private final DictDetailRepository dictDetailRepository; - @Autowired - private DictDetailMapper dictDetailMapper; + private final DictDetailMapper dictDetailMapper; + + public DictDetailServiceImpl(DictDetailRepository dictDetailRepository, DictDetailMapper dictDetailMapper) { + this.dictDetailRepository = dictDetailRepository; + this.dictDetailMapper = dictDetailMapper; + } @Override + @Cacheable public Map queryAll(DictDetailQueryCriteria criteria, Pageable pageable) { Page page = dictDetailRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); return PageUtil.toPage(page.map(dictDetailMapper::toDto)); } @Override + @Cacheable(key = "#p0") public DictDetailDTO findById(Long id) { - Optional dictDetail = dictDetailRepository.findById(id); - ValidationUtil.isNull(dictDetail,"DictDetail","id",id); - return dictDetailMapper.toDto(dictDetail.get()); + DictDetail dictDetail = dictDetailRepository.findById(id).orElseGet(DictDetail::new); + ValidationUtil.isNull(dictDetail.getId(),"DictDetail","id",id); + return dictDetailMapper.toDto(dictDetail); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public DictDetailDTO create(DictDetail resources) { return dictDetailMapper.toDto(dictDetailRepository.save(resources)); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void update(DictDetail resources) { - Optional optionalDictDetail = dictDetailRepository.findById(resources.getId()); - ValidationUtil.isNull( optionalDictDetail,"DictDetail","id",resources.getId()); - DictDetail dictDetail = optionalDictDetail.get(); + DictDetail dictDetail = dictDetailRepository.findById(resources.getId()).orElseGet(DictDetail::new); + ValidationUtil.isNull( dictDetail.getId(),"DictDetail","id",resources.getId()); resources.setId(dictDetail.getId()); dictDetailRepository.save(resources); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void delete(Long id) { dictDetailRepository.deleteById(id); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DictServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DictServiceImpl.java index 12ad1da0..e1128a50 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DictServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DictServiceImpl.java @@ -1,7 +1,10 @@ package me.zhengjie.modules.system.service.impl; +import cn.hutool.core.collection.CollectionUtil; import me.zhengjie.modules.system.domain.Dict; +import me.zhengjie.modules.system.service.dto.DictDetailDTO; import me.zhengjie.modules.system.service.dto.DictQueryCriteria; +import me.zhengjie.utils.FileUtil; import me.zhengjie.utils.PageUtil; import me.zhengjie.utils.QueryHelp; import me.zhengjie.utils.ValidationUtil; @@ -9,60 +12,109 @@ import me.zhengjie.modules.system.repository.DictRepository; import me.zhengjie.modules.system.service.DictService; import me.zhengjie.modules.system.service.dto.DictDTO; import me.zhengjie.modules.system.service.mapper.DictMapper; -import org.springframework.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.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; -import java.util.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 * @date 2019-04-10 */ @Service +@CacheConfig(cacheNames = "dict") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class DictServiceImpl implements DictService { - @Autowired - private DictRepository dictRepository; + private final DictRepository dictRepository; - @Autowired - private DictMapper dictMapper; + private final DictMapper dictMapper; + + public DictServiceImpl(DictRepository dictRepository, DictMapper dictMapper) { + this.dictRepository = dictRepository; + this.dictMapper = dictMapper; + } @Override - public Object queryAll(DictQueryCriteria dict, Pageable pageable){ + @Cacheable + public Map queryAll(DictQueryCriteria dict, Pageable pageable){ Page page = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb), pageable); return PageUtil.toPage(page.map(dictMapper::toDto)); } @Override - public DictDTO findById(Long id) { - Optional dict = dictRepository.findById(id); - ValidationUtil.isNull(dict,"Dict","id",id); - return dictMapper.toDto(dict.get()); + public List queryAll(DictQueryCriteria dict) { + List list = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb)); + return dictMapper.toDto(list); } @Override + @Cacheable(key = "#p0") + public DictDTO findById(Long id) { + Dict dict = dictRepository.findById(id).orElseGet(Dict::new); + ValidationUtil.isNull(dict.getId(),"Dict","id",id); + return dictMapper.toDto(dict); + } + + @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public DictDTO create(Dict resources) { return dictMapper.toDto(dictRepository.save(resources)); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void update(Dict resources) { - Optional optionalDict = dictRepository.findById(resources.getId()); - ValidationUtil.isNull( optionalDict,"Dict","id",resources.getId()); - Dict dict = optionalDict.get(); + Dict dict = dictRepository.findById(resources.getId()).orElseGet(Dict::new); + ValidationUtil.isNull( dict.getId(),"Dict","id",resources.getId()); resources.setId(dict.getId()); dictRepository.save(resources); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void delete(Long id) { dictRepository.deleteById(id); } + + @Override + public void download(List dictDTOS, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (DictDTO dictDTO : dictDTOS) { + if(CollectionUtil.isNotEmpty(dictDTO.getDictDetails())){ + for (DictDetailDTO dictDetail : dictDTO.getDictDetails()) { + Map map = new LinkedHashMap<>(); + map.put("字典名称", dictDTO.getName()); + map.put("字典描述", dictDTO.getRemark()); + map.put("字典标签", dictDetail.getLabel()); + map.put("字典值", dictDetail.getValue()); + map.put("创建日期", dictDetail.getCreateTime()); + list.add(map); + } + } else { + Map map = new LinkedHashMap<>(); + map.put("字典名称", dictDTO.getName()); + map.put("字典描述", dictDTO.getRemark()); + map.put("字典标签", null); + map.put("字典值", null); + map.put("创建日期", dictDTO.getCreateTime()); + list.add(map); + } + } + FileUtil.downloadExcel(list, response); + } } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/JobServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/JobServiceImpl.java index 64c90972..ea37db69 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/JobServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/JobServiceImpl.java @@ -3,6 +3,7 @@ package me.zhengjie.modules.system.service.impl; import me.zhengjie.modules.system.domain.Job; import me.zhengjie.modules.system.repository.DeptRepository; import me.zhengjie.modules.system.service.dto.JobQueryCriteria; +import me.zhengjie.utils.FileUtil; import me.zhengjie.utils.PageUtil; import me.zhengjie.utils.QueryHelp; import me.zhengjie.utils.ValidationUtil; @@ -10,35 +11,46 @@ import me.zhengjie.modules.system.repository.JobRepository; import me.zhengjie.modules.system.service.JobService; import me.zhengjie.modules.system.service.dto.JobDTO; import me.zhengjie.modules.system.service.mapper.JobMapper; -import org.springframework.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.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; -import java.util.Optional; +import java.util.Map; /** * @author Zheng Jie * @date 2019-03-29 */ @Service +@CacheConfig(cacheNames = "job") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class JobServiceImpl implements JobService { - @Autowired - private JobRepository jobRepository; + private final JobRepository jobRepository; - @Autowired - private JobMapper jobMapper; + private final JobMapper jobMapper; - @Autowired - private DeptRepository deptRepository; + private final DeptRepository deptRepository; + + public JobServiceImpl(JobRepository jobRepository, JobMapper jobMapper, DeptRepository deptRepository) { + this.jobRepository = jobRepository; + this.jobMapper = jobMapper; + this.deptRepository = deptRepository; + } @Override - public Object queryAll(JobQueryCriteria criteria, Pageable pageable) { + @Cacheable + public Map queryAll(JobQueryCriteria criteria, Pageable pageable) { Page page = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); List jobs = new ArrayList<>(); for (Job job : page.getContent()) { @@ -48,32 +60,55 @@ public class JobServiceImpl implements JobService { } @Override - public JobDTO findById(Long id) { - Optional job = jobRepository.findById(id); - ValidationUtil.isNull(job,"Job","id",id); - return jobMapper.toDto(job.get()); + @Cacheable + public List queryAll(JobQueryCriteria criteria) { + List list = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); + return jobMapper.toDto(list); } @Override + @Cacheable(key = "#p0") + public JobDTO findById(Long id) { + Job job = jobRepository.findById(id).orElseGet(Job::new); + ValidationUtil.isNull(job.getId(),"Job","id",id); + return jobMapper.toDto(job); + } + + @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public JobDTO create(Job resources) { return jobMapper.toDto(jobRepository.save(resources)); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void update(Job resources) { - Optional optionalJob = jobRepository.findById(resources.getId()); - ValidationUtil.isNull( optionalJob,"Job","id",resources.getId()); - - Job job = optionalJob.get(); + Job job = jobRepository.findById(resources.getId()).orElseGet(Job::new); + ValidationUtil.isNull( job.getId(),"Job","id",resources.getId()); resources.setId(job.getId()); jobRepository.save(resources); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void delete(Long id) { jobRepository.deleteById(id); } + + @Override + public void download(List jobDTOs, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (JobDTO jobDTO : jobDTOs) { + Map map = new LinkedHashMap<>(); + map.put("岗位名称", jobDTO.getName()); + map.put("所属部门", jobDTO.getDept().getName()); + map.put("岗位状态", jobDTO.getEnabled() ? "启用" : "停用"); + map.put("创建日期", jobDTO.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java index 1f8afdf4..baadcfa2 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java @@ -1,7 +1,6 @@ package me.zhengjie.modules.system.service.impl; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import me.zhengjie.modules.system.domain.Menu; import me.zhengjie.modules.system.domain.vo.MenuMetaVo; @@ -15,52 +14,66 @@ import me.zhengjie.modules.system.service.dto.MenuDTO; import me.zhengjie.modules.system.service.dto.MenuQueryCriteria; import me.zhengjie.modules.system.service.dto.RoleSmallDTO; import me.zhengjie.modules.system.service.mapper.MenuMapper; +import me.zhengjie.utils.FileUtil; import me.zhengjie.utils.QueryHelp; import me.zhengjie.utils.StringUtils; import me.zhengjie.utils.ValidationUtil; -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.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.*; import java.util.stream.Collectors; @Service +@CacheConfig(cacheNames = "menu") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class MenuServiceImpl implements MenuService { - @Autowired - private MenuRepository menuRepository; + private final MenuRepository menuRepository; - @Autowired - private MenuMapper menuMapper; + private final MenuMapper menuMapper; - @Autowired - private RoleService roleService; + private final RoleService roleService; + + public MenuServiceImpl(MenuRepository menuRepository, MenuMapper menuMapper, RoleService roleService) { + this.menuRepository = menuRepository; + this.menuMapper = menuMapper; + this.roleService = roleService; + } @Override - public List queryAll(MenuQueryCriteria criteria){ + @Cacheable + public List queryAll(MenuQueryCriteria criteria){ +// Sort sort = new Sort(Sort.Direction.DESC,"id"); return menuMapper.toDto(menuRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))); } @Override + @Cacheable(key = "#p0") public MenuDTO findById(long id) { - Optional menu = menuRepository.findById(id); - ValidationUtil.isNull(menu,"Menu","id",id); - return menuMapper.toDto(menu.get()); + Menu menu = menuRepository.findById(id).orElseGet(Menu::new); + ValidationUtil.isNull(menu.getId(),"Menu","id",id); + return menuMapper.toDto(menu); } @Override public List findByRoles(List roles) { Set menus = new LinkedHashSet<>(); for (RoleSmallDTO role : roles) { - List menus1 = menuRepository.findByRoles_IdOrderBySortAsc(role.getId()).stream().collect(Collectors.toList()); + List menus1 = new ArrayList<>(menuRepository.findByRoles_IdAndTypeIsNotInOrderBySortAsc(role.getId(), 2)); menus.addAll(menus1); } return menus.stream().map(menuMapper::toDto).collect(Collectors.toList()); } @Override + @CacheEvict(allEntries = true) public MenuDTO create(Menu resources) { if(menuRepository.findByName(resources.getName()) != null){ throw new EntityExistException(Menu.class,"name",resources.getName()); @@ -79,19 +92,19 @@ public class MenuServiceImpl implements MenuService { } @Override + @CacheEvict(allEntries = true) public void update(Menu resources) { if(resources.getId().equals(resources.getPid())) { throw new BadRequestException("上级不能为自己"); } - Optional optionalPermission = menuRepository.findById(resources.getId()); - ValidationUtil.isNull(optionalPermission,"Permission","id",resources.getId()); + Menu menu = menuRepository.findById(resources.getId()).orElseGet(Menu::new); + ValidationUtil.isNull(menu.getId(),"Permission","id",resources.getId()); if(resources.getIFrame()){ if (!(resources.getPath().toLowerCase().startsWith("http://")||resources.getPath().toLowerCase().startsWith("https://"))) { throw new BadRequestException("外链必须以http://或者https://开头"); } } - Menu menu = optionalPermission.get(); Menu menu1 = menuRepository.findByName(resources.getName()); if(menu1 != null && !menu1.getId().equals(menu.getId())){ @@ -114,6 +127,8 @@ public class MenuServiceImpl implements MenuService { menu.setCache(resources.getCache()); menu.setHidden(resources.getHidden()); menu.setComponentName(resources.getComponentName()); + menu.setPermission(resources.getPermission()); + menu.setType(resources.getType()); menuRepository.save(menu); } @@ -131,6 +146,7 @@ public class MenuServiceImpl implements MenuService { } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void delete(Set menuSet) { for (Menu menu : menuSet) { @@ -140,6 +156,7 @@ public class MenuServiceImpl implements MenuService { } @Override + @Cacheable(key = "'tree'") public Object getMenuTree(List menus) { List> list = new LinkedList<>(); menus.forEach(menu -> { @@ -159,13 +176,14 @@ public class MenuServiceImpl implements MenuService { } @Override + @Cacheable(key = "'pid:'+#p0") public List findByPid(long pid) { return menuRepository.findByPid(pid); } @Override - public Map buildTree(List menuDTOS) { - List trees = new ArrayList(); + public Map buildTree(List menuDTOS) { + List trees = new ArrayList<>(); Set ids = new HashSet<>(); for (MenuDTO menuDTO : menuDTOS) { if (menuDTO.getPid() == 0) { @@ -174,19 +192,19 @@ public class MenuServiceImpl implements MenuService { for (MenuDTO it : menuDTOS) { if (it.getPid().equals(menuDTO.getId())) { if (menuDTO.getChildren() == null) { - menuDTO.setChildren(new ArrayList()); + menuDTO.setChildren(new ArrayList<>()); } menuDTO.getChildren().add(it); ids.add(it.getId()); } } } - Map map = new HashMap(); + Map map = new HashMap<>(); if(trees.size() == 0){ trees = menuDTOS.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList()); } map.put("content",trees); - map.put("totalElements",menuDTOS!=null?menuDTOS.size():0); + map.put("totalElements", menuDTOS.size()); return map; } @@ -229,7 +247,7 @@ public class MenuServiceImpl implements MenuService { menuVo.setName(null); menuVo.setMeta(null); menuVo.setComponent("Layout"); - List list1 = new ArrayList(); + List list1 = new ArrayList<>(); list1.add(menuVo1); menuVo.setChildren(list1); } @@ -242,8 +260,25 @@ public class MenuServiceImpl implements MenuService { @Override public Menu findOne(Long id) { - Optional menu = menuRepository.findById(id); - ValidationUtil.isNull(menu,"Menu","id",id); - return menu.get(); + Menu menu = menuRepository.findById(id).orElseGet(Menu::new); + ValidationUtil.isNull(menu.getId(),"Menu","id",id); + return menu; + } + + @Override + public void download(List menuDTOS, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (MenuDTO menuDTO : menuDTOS) { + Map map = new LinkedHashMap<>(); + map.put("菜单名称", menuDTO.getName()); + map.put("菜单类型", menuDTO.getType() == 0 ? "目录" : menuDTO.getType() == 1 ? "菜单" : "按钮"); + map.put("权限标识", menuDTO.getPermission()); + map.put("外链菜单", menuDTO.getIFrame() ? "是" : "否"); + map.put("菜单可见", menuDTO.getHidden() ? "否" : "是"); + map.put("是否缓存", menuDTO.getCache() ? "是" : "否"); + map.put("创建日期", menuDTO.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); } } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/PermissionServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/PermissionServiceImpl.java deleted file mode 100644 index e8c48c76..00000000 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/PermissionServiceImpl.java +++ /dev/null @@ -1,155 +0,0 @@ -package me.zhengjie.modules.system.service.impl; - -import me.zhengjie.modules.system.domain.Permission; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.exception.EntityExistException; -import me.zhengjie.modules.system.repository.PermissionRepository; -import me.zhengjie.modules.system.service.PermissionService; -import me.zhengjie.modules.system.service.RoleService; -import me.zhengjie.modules.system.service.dto.PermissionDTO; -import me.zhengjie.modules.system.service.dto.PermissionQueryCriteria; -import me.zhengjie.modules.system.service.mapper.PermissionMapper; -import me.zhengjie.utils.QueryHelp; -import me.zhengjie.utils.ValidationUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; -import java.util.*; - -/** - * @author Zheng Jie - * @date 2018-12-03 - */ -@Service -@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) -public class PermissionServiceImpl implements PermissionService { - - @Autowired - private PermissionRepository permissionRepository; - - @Autowired - private PermissionMapper permissionMapper; - - @Autowired - private RoleService roleService; - - @Override - public List queryAll(PermissionQueryCriteria criteria) { - return permissionMapper.toDto(permissionRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))); - } - - @Override - public PermissionDTO findById(long id) { - Optional permission = permissionRepository.findById(id); - ValidationUtil.isNull(permission,"Permission","id",id); - return permissionMapper.toDto(permission.get()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public PermissionDTO create(Permission resources) { - if(permissionRepository.findByName(resources.getName()) != null){ - throw new EntityExistException(Permission.class,"name",resources.getName()); - } - return permissionMapper.toDto(permissionRepository.save(resources)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(Permission resources) { - Optional optionalPermission = permissionRepository.findById(resources.getId()); - if(resources.getId().equals(resources.getPid())) { - throw new BadRequestException("上级不能为自己"); - } - ValidationUtil.isNull(optionalPermission,"Permission","id",resources.getId()); - - Permission permission = optionalPermission.get(); - - Permission permission1 = permissionRepository.findByName(resources.getName()); - - if(permission1 != null && !permission1.getId().equals(permission.getId())){ - throw new EntityExistException(Permission.class,"name",resources.getName()); - } - - permission.setName(resources.getName()); - permission.setAlias(resources.getAlias()); - permission.setPid(resources.getPid()); - permissionRepository.save(permission); - } - - @Override - public Set getDeletePermission(List permissions, Set permissionSet) { - // 递归找出待删除的菜单 - for (Permission permission : permissions) { - permissionSet.add(permission); - List permissionList = permissionRepository.findByPid(permission.getId()); - if(permissionList!=null && permissionList.size()!=0){ - getDeletePermission(permissionList, permissionSet); - } - } - return permissionSet; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set permissions) { - for (Permission permission : permissions) { - roleService.untiedPermission(permission.getId()); - permissionRepository.delete(permission); - } - } - - @Override - public Object getPermissionTree(List permissions) { - List> list = new LinkedList<>(); - permissions.forEach(permission -> { - if (permission!=null){ - List permissionList = permissionRepository.findByPid(permission.getId()); - Map map = new HashMap<>(); - map.put("id",permission.getId()); - map.put("label",permission.getAlias()); - if(permissionList!=null && permissionList.size()!=0){ - map.put("children",getPermissionTree(permissionList)); - } - list.add(map); - } - } - ); - return list; - } - - @Override - public List findByPid(long pid) { - return permissionRepository.findByPid(pid); - } - - @Override - public Object buildTree(List permissionDTOS) { - - List trees = new ArrayList(); - - for (PermissionDTO permissionDTO : permissionDTOS) { - - if ("0".equals(permissionDTO.getPid().toString())) { - trees.add(permissionDTO); - } - - for (PermissionDTO it : permissionDTOS) { - if (it.getPid().equals(permissionDTO.getId())) { - if (permissionDTO.getChildren() == null) { - permissionDTO.setChildren(new ArrayList()); - } - permissionDTO.getChildren().add(it); - } - } - } - - Integer totalElements = permissionDTOS!=null?permissionDTOS.size():0; - - Map map = new HashMap(); - map.put("content",trees.size() == 0?permissionDTOS:trees); - map.put("totalElements",totalElements); - return map; - } -} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/RoleServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/RoleServiceImpl.java index bc33f266..1b9725f0 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/RoleServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/RoleServiceImpl.java @@ -9,15 +9,21 @@ import me.zhengjie.modules.system.service.dto.RoleQueryCriteria; import me.zhengjie.modules.system.service.dto.RoleSmallDTO; import me.zhengjie.modules.system.service.mapper.RoleMapper; import me.zhengjie.modules.system.service.mapper.RoleSmallMapper; +import me.zhengjie.utils.FileUtil; import me.zhengjie.utils.PageUtil; import me.zhengjie.utils.QueryHelp; import me.zhengjie.utils.ValidationUtil; -import org.springframework.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.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.*; import java.util.stream.Collectors; @@ -26,42 +32,51 @@ import java.util.stream.Collectors; * @date 2018-12-03 */ @Service +@CacheConfig(cacheNames = "role") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class RoleServiceImpl implements RoleService { - @Autowired - private RoleRepository roleRepository; + private final RoleRepository roleRepository; - @Autowired - private RoleMapper roleMapper; + private final RoleMapper roleMapper; - @Autowired - private RoleSmallMapper roleSmallMapper; + private final RoleSmallMapper roleSmallMapper; + + public RoleServiceImpl(RoleRepository roleRepository, RoleMapper roleMapper, RoleSmallMapper roleSmallMapper) { + this.roleRepository = roleRepository; + this.roleMapper = roleMapper; + this.roleSmallMapper = roleSmallMapper; + } @Override + @Cacheable public Object queryAll(Pageable pageable) { return roleMapper.toDto(roleRepository.findAll(pageable).getContent()); } @Override + @Cacheable public List queryAll(RoleQueryCriteria criteria) { return roleMapper.toDto(roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))); } @Override + @Cacheable public Object queryAll(RoleQueryCriteria criteria, Pageable pageable) { Page page = roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); return PageUtil.toPage(page.map(roleMapper::toDto)); } @Override + @Cacheable(key = "#p0") public RoleDTO findById(long id) { - Optional role = roleRepository.findById(id); - ValidationUtil.isNull(role,"Role","id",id); - return roleMapper.toDto(role.get()); + Role role = roleRepository.findById(id).orElseGet(Role::new); + ValidationUtil.isNull(role.getId(),"Role","id",id); + return roleMapper.toDto(role); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public RoleDTO create(Role resources) { if(roleRepository.findByName(resources.getName()) != null){ @@ -71,13 +86,11 @@ public class RoleServiceImpl implements RoleService { } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void update(Role resources) { - - Optional optionalRole = roleRepository.findById(resources.getId()); - ValidationUtil.isNull(optionalRole,"Role","id",resources.getId()); - - Role role = optionalRole.get(); + Role role = roleRepository.findById(resources.getId()).orElseGet(Role::new); + ValidationUtil.isNull(role.getId(),"Role","id",resources.getId()); Role role1 = roleRepository.findByName(resources.getName()); @@ -94,13 +107,7 @@ public class RoleServiceImpl implements RoleService { } @Override - public void updatePermission(Role resources, RoleDTO roleDTO) { - Role role = roleMapper.toEntity(roleDTO); - role.setPermissions(resources.getPermissions()); - roleRepository.save(role); - } - - @Override + @CacheEvict(allEntries = true) public void updateMenu(Role resources, RoleDTO roleDTO) { Role role = roleMapper.toEntity(roleDTO); role.setMenus(resources.getMenus()); @@ -108,29 +115,27 @@ public class RoleServiceImpl implements RoleService { } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void untiedMenu(Long id) { roleRepository.untiedMenu(id); } @Override - @Transactional(rollbackFor = Exception.class) - public void untiedPermission(Long id) { - roleRepository.untiedPermission(id); - } - - @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void delete(Long id) { roleRepository.deleteById(id); } @Override + @Cacheable(key = "'findByUsers_Id:' + #p0") public List findByUsers_Id(Long id) { - return roleSmallMapper.toDto(roleRepository.findByUsers_Id(id).stream().collect(Collectors.toList())); + return roleSmallMapper.toDto(new ArrayList<>(roleRepository.findByUsers_Id(id))); } @Override + @Cacheable public Integer findByRoles(Set roles) { Set roleDTOS = new HashSet<>(); for (Role role : roles) { @@ -138,4 +143,19 @@ public class RoleServiceImpl implements RoleService { } return Collections.min(roleDTOS.stream().map(RoleDTO::getLevel).collect(Collectors.toList())); } + + @Override + public void download(List roles, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (RoleDTO role : roles) { + Map map = new LinkedHashMap<>(); + map.put("角色名称", role.getName()); + map.put("默认权限", role.getPermission()); + map.put("角色级别", role.getLevel()); + map.put("描述", role.getRemark()); + map.put("创建日期", role.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/UserServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/UserServiceImpl.java index 2685d743..ee64b6bb 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/UserServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/UserServiceImpl.java @@ -1,8 +1,5 @@ package me.zhengjie.modules.system.service.impl; -import cn.hutool.core.io.IoUtil; -import cn.hutool.poi.excel.ExcelUtil; -import cn.hutool.poi.excel.ExcelWriter; import me.zhengjie.modules.monitor.service.RedisService; import me.zhengjie.modules.system.domain.User; import me.zhengjie.exception.EntityExistException; @@ -16,16 +13,16 @@ import me.zhengjie.modules.system.service.dto.UserDTO; import me.zhengjie.modules.system.service.dto.UserQueryCriteria; import me.zhengjie.modules.system.service.mapper.UserMapper; import me.zhengjie.utils.*; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; - -import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; @@ -37,44 +34,52 @@ import java.util.stream.Collectors; * @date 2018-11-23 */ @Service +@CacheConfig(cacheNames = "user") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class UserServiceImpl implements UserService { - @Autowired - private UserRepository userRepository; + private final UserRepository userRepository; - @Autowired - private UserMapper userMapper; + private final UserMapper userMapper; - @Autowired - private RedisService redisService; + private final RedisService redisService; - @Autowired - private UserAvatarRepository userAvatarRepository; + private final UserAvatarRepository userAvatarRepository; @Value("${file.avatar}") private String avatar; + public UserServiceImpl(UserRepository userRepository, UserMapper userMapper, RedisService redisService, UserAvatarRepository userAvatarRepository) { + this.userRepository = userRepository; + this.userMapper = userMapper; + this.redisService = redisService; + this.userAvatarRepository = userAvatarRepository; + } + @Override + @Cacheable public Object queryAll(UserQueryCriteria criteria, Pageable pageable) { Page page = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); return PageUtil.toPage(page.map(userMapper::toDto)); } @Override + @Cacheable public List queryAll(UserQueryCriteria criteria) { List users = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); return userMapper.toDto(users); } @Override + @Cacheable(key = "#p0") public UserDTO findById(long id) { - Optional user = userRepository.findById(id); - ValidationUtil.isNull(user,"User","id",id); - return userMapper.toDto(user.get()); + User user = userRepository.findById(id).orElseGet(User::new); + ValidationUtil.isNull(user.getId(),"User","id",id); + return userMapper.toDto(user); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public UserDTO create(User resources) { @@ -92,13 +97,11 @@ public class UserServiceImpl implements UserService { } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void update(User resources) { - Optional userOptional = userRepository.findById(resources.getId()); - ValidationUtil.isNull(userOptional,"User","id",resources.getId()); - - User user = userOptional.get(); - + User user = userRepository.findById(resources.getId()).orElseGet(User::new); + ValidationUtil.isNull(user.getId(),"User","id",resources.getId()); User user1 = userRepository.findByUsername(user.getUsername()); User user2 = userRepository.findByEmail(user.getEmail()); @@ -129,14 +132,16 @@ public class UserServiceImpl implements UserService { } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void delete(Long id) { userRepository.deleteById(id); } @Override + @Cacheable(key = "'loadUserByUsername:'+#p0") public UserDTO findByName(String userName) { - User user = null; + User user; if(ValidationUtil.isEmail(userName)){ user = userRepository.findByEmail(userName); } else { @@ -150,12 +155,14 @@ public class UserServiceImpl implements UserService { } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void updatePass(String username, String pass) { userRepository.updatePass(username,pass,new Date()); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void updateAvatar(MultipartFile multipartFile) { User user = userRepository.findByUsername(SecurityUtils.getUsername()); @@ -165,6 +172,7 @@ public class UserServiceImpl implements UserService { oldPath = userAvatar.getPath(); } File file = FileUtil.upload(multipartFile, avatar); + assert file != null; userAvatar = userAvatarRepository.save(new UserAvatar(userAvatar,file.getName(), file.getPath(), FileUtil.getSize(multipartFile.getSize()))); user.setUserAvatar(userAvatar); userRepository.save(user); @@ -174,6 +182,7 @@ public class UserServiceImpl implements UserService { } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void updateEmail(String username, String email) { userRepository.updateEmail(username,email); @@ -184,7 +193,7 @@ public class UserServiceImpl implements UserService { List> list = new ArrayList<>(); for (UserDTO userDTO : queryAll) { List roles = userDTO.getRoles().stream().map(RoleSmallDTO::getName).collect(Collectors.toList()); - Map map = new LinkedHashMap(); + Map map = new LinkedHashMap<>(); map.put("用户名", userDTO.getUsername()); map.put("头像", userDTO.getAvatar()); map.put("邮箱", userDTO.getEmail()); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DeptMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DeptMapper.java index 46da4c2c..ba3be01d 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DeptMapper.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DeptMapper.java @@ -1,6 +1,6 @@ package me.zhengjie.modules.system.service.mapper; -import me.zhengjie.mapper.EntityMapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.modules.system.domain.Dept; import me.zhengjie.modules.system.service.dto.DeptDTO; import org.mapstruct.Mapper; @@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy; * @author Zheng Jie * @date 2019-03-25 */ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DeptMapper extends EntityMapper { +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface DeptMapper extends BaseMapper { } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DeptSmallMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DeptSmallMapper.java index 338d55a4..c964081d 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DeptSmallMapper.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DeptSmallMapper.java @@ -1,6 +1,6 @@ package me.zhengjie.modules.system.service.mapper; -import me.zhengjie.mapper.EntityMapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.modules.system.domain.Dept; import me.zhengjie.modules.system.service.dto.DeptSmallDTO; import org.mapstruct.Mapper; @@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy; * @author Zheng Jie * @date 2019-03-25 */ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DeptSmallMapper extends EntityMapper { +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface DeptSmallMapper extends BaseMapper { } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DictDetailMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DictDetailMapper.java index 797c1dab..f82c1bd5 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DictDetailMapper.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DictDetailMapper.java @@ -1,6 +1,6 @@ package me.zhengjie.modules.system.service.mapper; -import me.zhengjie.mapper.EntityMapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.modules.system.domain.DictDetail; import me.zhengjie.modules.system.service.dto.DictDetailDTO; import org.mapstruct.Mapper; @@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy; * @author Zheng Jie * @date 2019-04-10 */ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DictDetailMapper extends EntityMapper { +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface DictDetailMapper extends BaseMapper { } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DictMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DictMapper.java index 1d1f93d5..c5b70a25 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DictMapper.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/DictMapper.java @@ -1,6 +1,6 @@ package me.zhengjie.modules.system.service.mapper; -import me.zhengjie.mapper.EntityMapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.modules.system.domain.Dict; import me.zhengjie.modules.system.service.dto.DictDTO; import org.mapstruct.Mapper; @@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy; * @author Zheng Jie * @date 2019-04-10 */ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DictMapper extends EntityMapper { +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface DictMapper extends BaseMapper { } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/JobMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/JobMapper.java index b4d2b347..59565dfa 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/JobMapper.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/JobMapper.java @@ -1,6 +1,6 @@ package me.zhengjie.modules.system.service.mapper; -import me.zhengjie.mapper.EntityMapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.modules.system.domain.Job; import me.zhengjie.modules.system.service.dto.JobDTO; import org.mapstruct.Mapper; @@ -12,7 +12,7 @@ import org.mapstruct.ReportingPolicy; * @date 2019-03-29 */ @Mapper(componentModel = "spring",uses = {DeptMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface JobMapper extends EntityMapper { +public interface JobMapper extends BaseMapper { @Mapping(source = "deptSuperiorName", target = "deptSuperiorName") JobDTO toDto(Job job, String deptSuperiorName); diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/JobSmallMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/JobSmallMapper.java index c48b4d36..96282b2c 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/JobSmallMapper.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/JobSmallMapper.java @@ -1,6 +1,6 @@ package me.zhengjie.modules.system.service.mapper; -import me.zhengjie.mapper.EntityMapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.modules.system.domain.Job; import me.zhengjie.modules.system.service.dto.JobSmallDTO; import org.mapstruct.Mapper; @@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy; * @author Zheng Jie * @date 2019-03-29 */ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface JobSmallMapper extends EntityMapper { +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface JobSmallMapper extends BaseMapper { } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/MenuMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/MenuMapper.java index 513f1bc3..6887537f 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/MenuMapper.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/MenuMapper.java @@ -1,7 +1,7 @@ package me.zhengjie.modules.system.service.mapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.modules.system.domain.Menu; -import me.zhengjie.mapper.EntityMapper; import me.zhengjie.modules.system.service.dto.MenuDTO; import org.mapstruct.Mapper; import org.mapstruct.ReportingPolicy; @@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy; * @author Zheng Jie * @date 2018-12-17 */ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface MenuMapper extends EntityMapper { +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface MenuMapper extends BaseMapper { } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/PermissionMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/PermissionMapper.java deleted file mode 100644 index f86c9d4c..00000000 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/PermissionMapper.java +++ /dev/null @@ -1,16 +0,0 @@ -package me.zhengjie.modules.system.service.mapper; - -import me.zhengjie.modules.system.domain.Permission; -import me.zhengjie.mapper.EntityMapper; -import me.zhengjie.modules.system.service.dto.PermissionDTO; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface PermissionMapper extends EntityMapper { - -} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/RoleMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/RoleMapper.java index 9acaf31b..d1533b0c 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/RoleMapper.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/RoleMapper.java @@ -1,7 +1,7 @@ package me.zhengjie.modules.system.service.mapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.modules.system.domain.Role; -import me.zhengjie.mapper.EntityMapper; import me.zhengjie.modules.system.service.dto.RoleDTO; import org.mapstruct.Mapper; import org.mapstruct.ReportingPolicy; @@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy; * @author Zheng Jie * @date 2018-11-23 */ -@Mapper(componentModel = "spring", uses = {PermissionMapper.class, MenuMapper.class, DeptMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface RoleMapper extends EntityMapper { +@Mapper(componentModel = "spring", uses = {MenuMapper.class, DeptMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface RoleMapper extends BaseMapper { } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/RoleSmallMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/RoleSmallMapper.java index c5858fb4..ae23cdd3 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/RoleSmallMapper.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/RoleSmallMapper.java @@ -1,8 +1,7 @@ package me.zhengjie.modules.system.service.mapper; -import me.zhengjie.mapper.EntityMapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.modules.system.domain.Role; -import me.zhengjie.modules.system.service.dto.RoleDTO; import me.zhengjie.modules.system.service.dto.RoleSmallDTO; import org.mapstruct.Mapper; import org.mapstruct.ReportingPolicy; @@ -11,7 +10,7 @@ import org.mapstruct.ReportingPolicy; * @author Zheng Jie * @date 2019-5-23 */ -@Mapper(componentModel = "spring", uses = {}, unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface RoleSmallMapper extends EntityMapper { +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface RoleSmallMapper extends BaseMapper { } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/UserMapper.java b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/UserMapper.java index 248003a3..13654868 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/UserMapper.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/system/service/mapper/UserMapper.java @@ -1,20 +1,18 @@ package me.zhengjie.modules.system.service.mapper; +import me.zhengjie.base.BaseMapper; import me.zhengjie.modules.system.domain.User; -import me.zhengjie.mapper.EntityMapper; import me.zhengjie.modules.system.service.dto.UserDTO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.ReportingPolicy; -import java.util.List; - /** * @author Zheng Jie * @date 2018-11-23 */ @Mapper(componentModel = "spring",uses = {RoleMapper.class, DeptMapper.class, JobMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface UserMapper extends EntityMapper { +public interface UserMapper extends BaseMapper { @Mapping(source = "user.userAvatar.realName",target = "avatar") UserDTO toDto(User user); diff --git a/eladmin-system/src/main/resources/config/application-dev.yml b/eladmin-system/src/main/resources/config/application-dev.yml index 45b7a500..d2c26ad3 100644 --- a/eladmin-system/src/main/resources/config/application-dev.yml +++ b/eladmin-system/src/main/resources/config/application-dev.yml @@ -45,13 +45,12 @@ spring: jwt: header: Authorization secret: mySecret - # token 过期时间 6个小时 - expiration: 21000000 - auth: - # 授权路径 - path: /login - # 获取用户信息 - account: /info + # token 过期时间/毫秒,6小时 1小时 = 3600000 毫秒 + expiration: 21600000 + # 在线用户key + online: online-token + # 验证码 + codeKey: code-key #是否允许生成代码,生产环境设置为false generator: diff --git a/eladmin-system/src/main/resources/config/application-prod.yml b/eladmin-system/src/main/resources/config/application-prod.yml index a1ae2b74..5cdd61a1 100644 --- a/eladmin-system/src/main/resources/config/application-prod.yml +++ b/eladmin-system/src/main/resources/config/application-prod.yml @@ -49,11 +49,10 @@ jwt: secret: mySecret # token 过期时间 2个小时 expiration: 7200000 - auth: - # 授权路径 - path: /login - # 获取用户信息 - account: /info + # 在线用户key + online: online-token + # 验证码 + codeKey: code-key #是否允许生成代码,生产环境设置为false generator: diff --git a/eladmin-system/src/main/resources/config/application.yml b/eladmin-system/src/main/resources/config/application.yml index c45c9529..6ebf8549 100644 --- a/eladmin-system/src/main/resources/config/application.yml +++ b/eladmin-system/src/main/resources/config/application.yml @@ -29,6 +29,17 @@ spring: #连接超时时间 timeout: 5000 +task: + pool: + # 核心线程池大小 + core-pool-size: 10 + # 最大线程数 + max-pool-size: 30 + # 活跃时间 + keep-alive-seconds: 60 + # 队列容量 + queue-capacity: 50 + #七牛云 qiniu: # 文件大小 /M diff --git a/eladmin-system/src/main/resources/template/generator/admin/Controller.ftl b/eladmin-system/src/main/resources/template/generator/admin/Controller.ftl index 9ec0b10c..3ea9a093 100644 --- a/eladmin-system/src/main/resources/template/generator/admin/Controller.ftl +++ b/eladmin-system/src/main/resources/template/generator/admin/Controller.ftl @@ -4,7 +4,6 @@ import me.zhengjie.aop.log.Log; import ${package}.domain.${className}; import ${package}.service.${className}Service; import ${package}.service.dto.${className}QueryCriteria; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -12,6 +11,8 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import io.swagger.annotations.*; +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; /** * @author ${author} @@ -19,41 +20,52 @@ import io.swagger.annotations.*; */ @Api(tags = "${className}管理") @RestController -@RequestMapping("api") +@RequestMapping("/api/${changeClassName}") public class ${className}Controller { - @Autowired - private ${className}Service ${changeClassName}Service; + private final ${className}Service ${changeClassName}Service; + public ${className}Controller(${className}Service ${changeClassName}Service) { + this.${changeClassName}Service = ${changeClassName}Service; + } + + @Log("导出数据") + @ApiOperation("导出数据") + @GetMapping(value = "/download") + @PreAuthorize("@el.check('${changeClassName}:list')") + public void download(HttpServletResponse response, ${className}QueryCriteria criteria) throws IOException { + ${changeClassName}Service.download(${changeClassName}Service.queryAll(criteria), response); + } + + @GetMapping @Log("查询${className}") - @ApiOperation(value = "查询${className}") - @GetMapping(value = "/${changeClassName}") - @PreAuthorize("hasAnyRole('ADMIN','${upperCaseClassName}_ALL','${upperCaseClassName}_SELECT')") + @ApiOperation("查询${className}") + @PreAuthorize("@el.check('${changeClassName}:list')") public ResponseEntity get${className}s(${className}QueryCriteria criteria, Pageable pageable){ - return new ResponseEntity(${changeClassName}Service.queryAll(criteria,pageable),HttpStatus.OK); + return new ResponseEntity<>(${changeClassName}Service.queryAll(criteria,pageable),HttpStatus.OK); } + @PostMapping @Log("新增${className}") - @ApiOperation(value = "新增${className}") - @PostMapping(value = "/${changeClassName}") - @PreAuthorize("hasAnyRole('ADMIN','${upperCaseClassName}_ALL','${upperCaseClassName}_CREATE')") + @ApiOperation("新增${className}") + @PreAuthorize("@el.check('${changeClassName}:add')") public ResponseEntity create(@Validated @RequestBody ${className} resources){ - return new ResponseEntity(${changeClassName}Service.create(resources),HttpStatus.CREATED); + return new ResponseEntity<>(${changeClassName}Service.create(resources),HttpStatus.CREATED); } + @PutMapping @Log("修改${className}") - @ApiOperation(value = "修改${className}") - @PutMapping(value = "/${changeClassName}") - @PreAuthorize("hasAnyRole('ADMIN','${upperCaseClassName}_ALL','${upperCaseClassName}_EDIT')") + @ApiOperation("修改${className}") + @PreAuthorize("@el.check('${changeClassName}:edit')") public ResponseEntity update(@Validated @RequestBody ${className} resources){ ${changeClassName}Service.update(resources); return new ResponseEntity(HttpStatus.NO_CONTENT); } + @DeleteMapping(value = "/{${pkChangeColName}}") @Log("删除${className}") - @ApiOperation(value = "删除${className}") - @DeleteMapping(value = "/${changeClassName}/{${pkChangeColName}}") - @PreAuthorize("hasAnyRole('ADMIN','${upperCaseClassName}_ALL','${upperCaseClassName}_DELETE')") + @ApiOperation("删除${className}") + @PreAuthorize("@el.check('${changeClassName}:del')") public ResponseEntity delete(@PathVariable ${pkColumnType} ${pkChangeColName}){ ${changeClassName}Service.delete(${pkChangeColName}); return new ResponseEntity(HttpStatus.OK); diff --git a/eladmin-system/src/main/resources/template/generator/admin/Mapper.ftl b/eladmin-system/src/main/resources/template/generator/admin/Mapper.ftl index 2f067d30..0b207a7b 100644 --- a/eladmin-system/src/main/resources/template/generator/admin/Mapper.ftl +++ b/eladmin-system/src/main/resources/template/generator/admin/Mapper.ftl @@ -1,6 +1,6 @@ package ${package}.service.mapper; -import me.zhengjie.mapper.EntityMapper; +import me.zhengjie.base.BaseMapper; import ${package}.domain.${className}; import ${package}.service.dto.${className}DTO; import org.mapstruct.Mapper; @@ -10,7 +10,7 @@ import org.mapstruct.ReportingPolicy; * @author ${author} * @date ${date} */ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface ${className}Mapper extends EntityMapper<${className}DTO, ${className}> { +@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface ${className}Mapper extends BaseMapper<${className}DTO, ${className}> { } \ No newline at end of file diff --git a/eladmin-system/src/main/resources/template/generator/admin/QueryCriteria.ftl b/eladmin-system/src/main/resources/template/generator/admin/QueryCriteria.ftl index 514e92cd..2f5e20a7 100644 --- a/eladmin-system/src/main/resources/template/generator/admin/QueryCriteria.ftl +++ b/eladmin-system/src/main/resources/template/generator/admin/QueryCriteria.ftl @@ -1,10 +1,10 @@ package ${package}.service.dto; import lombok.Data; -<#if hasTimestamp> +<#if queryHasTimestamp> import java.sql.Timestamp; -<#if hasBigDecimal> +<#if queryHasBigDecimal> import java.math.BigDecimal; <#if queryColumns??> diff --git a/eladmin-system/src/main/resources/template/generator/admin/Repository.ftl b/eladmin-system/src/main/resources/template/generator/admin/Repository.ftl index 9b896818..73d4e9e9 100644 --- a/eladmin-system/src/main/resources/template/generator/admin/Repository.ftl +++ b/eladmin-system/src/main/resources/template/generator/admin/Repository.ftl @@ -8,16 +8,11 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; * @author ${author} * @date ${date} */ -public interface ${className}Repository extends JpaRepository<${className}, ${pkColumnType}>, JpaSpecificationExecutor { +public interface ${className}Repository extends JpaRepository<${className}, ${pkColumnType}>, JpaSpecificationExecutor<${className}> { <#if columns??> <#list columns as column> <#if column.columnKey = 'UNI'> - /** - * findBy${column.capitalColumnName} - * @param ${column.columnName} - * @return - */ ${className} findBy${column.capitalColumnName}(${column.columnType} ${column.columnName}); diff --git a/eladmin-system/src/main/resources/template/generator/admin/Service.ftl b/eladmin-system/src/main/resources/template/generator/admin/Service.ftl index ba236c16..18264298 100644 --- a/eladmin-system/src/main/resources/template/generator/admin/Service.ftl +++ b/eladmin-system/src/main/resources/template/generator/admin/Service.ftl @@ -3,64 +3,45 @@ package ${package}.service; import ${package}.domain.${className}; import ${package}.service.dto.${className}DTO; import ${package}.service.dto.${className}QueryCriteria; -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 java.util.Map; import java.util.List; +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; /** * @author ${author} * @date ${date} */ -//@CacheConfig(cacheNames = "${changeClassName}") public interface ${className}Service { /** * 查询数据分页 - * @param criteria - * @param pageable - * @return + * @param criteria 条件参数 + * @param pageable 分页参数 + * @return Map */ - //@Cacheable Map queryAll(${className}QueryCriteria criteria, Pageable pageable); /** * 查询所有数据不分页 - * @param criteria - * @return + * @param criteria 条件参数 + * @return List<${className}DTO> */ - //@Cacheable List<${className}DTO> queryAll(${className}QueryCriteria criteria); /** * 根据ID查询 - * @param ${pkChangeColName} - * @return + * @param ${pkChangeColName} ID + * @return ${className}DTO */ - //@Cacheable(key = "#p0") ${className}DTO findById(${pkColumnType} ${pkChangeColName}); - /** - * 创建 - * @param resources - * @return - */ - //@CacheEvict(allEntries = true) ${className}DTO create(${className} resources); - /** - * 编辑 - * @param resources - */ - //@CacheEvict(allEntries = true) void update(${className} resources); - /** - * 删除 - * @param ${pkChangeColName} - */ - //@CacheEvict(allEntries = true) void delete(${pkColumnType} ${pkChangeColName}); + + void download(List<${className}DTO> all, HttpServletResponse response) throws IOException; } \ No newline at end of file diff --git a/eladmin-system/src/main/resources/template/generator/admin/ServiceImpl.ftl b/eladmin-system/src/main/resources/template/generator/admin/ServiceImpl.ftl index d22a9536..b81db3b5 100644 --- a/eladmin-system/src/main/resources/template/generator/admin/ServiceImpl.ftl +++ b/eladmin-system/src/main/resources/template/generator/admin/ServiceImpl.ftl @@ -11,16 +11,15 @@ import me.zhengjie.exception.EntityExistException; import me.zhengjie.utils.ValidationUtil; +import me.zhengjie.utils.FileUtil; import ${package}.repository.${className}Repository; import ${package}.service.${className}Service; import ${package}.service.dto.${className}DTO; import ${package}.service.dto.${className}QueryCriteria; import ${package}.service.mapper.${className}Mapper; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; -import java.util.Optional; <#if !auto && pkColumnType = 'Long'> import cn.hutool.core.lang.Snowflake; import cn.hutool.core.util.IdUtil; @@ -28,46 +27,61 @@ import cn.hutool.core.util.IdUtil; <#if !auto && pkColumnType = 'String'> import cn.hutool.core.util.IdUtil; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import me.zhengjie.utils.PageUtil; import me.zhengjie.utils.QueryHelp; import java.util.List; import java.util.Map; +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.LinkedHashMap; /** * @author ${author} * @date ${date} */ @Service +@CacheConfig(cacheNames = "${changeClassName}") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class ${className}ServiceImpl implements ${className}Service { - @Autowired - private ${className}Repository ${changeClassName}Repository; + private final ${className}Repository ${changeClassName}Repository; - @Autowired - private ${className}Mapper ${changeClassName}Mapper; + private final ${className}Mapper ${changeClassName}Mapper; + + public ${className}ServiceImpl(${className}Repository ${changeClassName}Repository, ${className}Mapper ${changeClassName}Mapper) { + this.${changeClassName}Repository = ${changeClassName}Repository; + this.${changeClassName}Mapper = ${changeClassName}Mapper; + } @Override + @Cacheable public Map queryAll(${className}QueryCriteria criteria, Pageable pageable){ Page<${className}> page = ${changeClassName}Repository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); return PageUtil.toPage(page.map(${changeClassName}Mapper::toDto)); } @Override + @Cacheable public List<${className}DTO> queryAll(${className}QueryCriteria criteria){ return ${changeClassName}Mapper.toDto(${changeClassName}Repository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))); } @Override + @Cacheable(key = "#p0") public ${className}DTO findById(${pkColumnType} ${pkChangeColName}) { - Optional<${className}> ${changeClassName} = ${changeClassName}Repository.findById(${pkChangeColName}); - ValidationUtil.isNull(${changeClassName},"${className}","${pkChangeColName}",${pkChangeColName}); - return ${changeClassName}Mapper.toDto(${changeClassName}.get()); + ${className} ${changeClassName} = ${changeClassName}Repository.findById(${pkChangeColName}).orElseGet(${className}::new); + ValidationUtil.isNull(${changeClassName}.get${pkCapitalColName}(),"${className}","${pkChangeColName}",${pkChangeColName}); + return ${changeClassName}Mapper.toDto(${changeClassName}); } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public ${className}DTO create(${className} resources) { <#if !auto && pkColumnType = 'Long'> @@ -90,11 +104,11 @@ public class ${className}ServiceImpl implements ${className}Service { } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void update(${className} resources) { - Optional<${className}> optional${className} = ${changeClassName}Repository.findById(resources.get${pkCapitalColName}()); - ValidationUtil.isNull( optional${className},"${className}","id",resources.get${pkCapitalColName}()); - ${className} ${changeClassName} = optional${className}.get(); + ${className} ${changeClassName} = ${changeClassName}Repository.findById(resources.get${pkCapitalColName}()).orElseGet(${className}::new); + ValidationUtil.isNull( ${changeClassName}.get${pkCapitalColName}(),"${className}","id",resources.get${pkCapitalColName}()); <#if columns??> <#list columns as column> <#if column.columnKey = 'UNI'> @@ -113,8 +127,29 @@ public class ${className}ServiceImpl implements ${className}Service { } @Override + @CacheEvict(allEntries = true) @Transactional(rollbackFor = Exception.class) public void delete(${pkColumnType} ${pkChangeColName}) { ${changeClassName}Repository.deleteById(${pkChangeColName}); } + + + @Override + public void download(List<${className}DTO> all, HttpServletResponse response) throws IOException { + List> list = new ArrayList<>(); + for (${className}DTO ${changeClassName} : all) { + Map map = new LinkedHashMap<>(); + <#list columns as column> + <#if column.columnKey != 'PRI'> + <#if column.columnComment != ''> + map.put("${column.columnComment}", ${changeClassName}.get${column.capitalColumnName}()); + <#else> + map.put(" ${column.changeColumnName}", ${changeClassName}.get${column.capitalColumnName}()); + + + + list.add(map); + } + FileUtil.downloadExcel(list, response); + } } \ No newline at end of file diff --git a/eladmin-system/src/main/resources/template/generator/front/api.ftl b/eladmin-system/src/main/resources/template/generator/front/api.ftl index a39d3bc7..a848db14 100644 --- a/eladmin-system/src/main/resources/template/generator/front/api.ftl +++ b/eladmin-system/src/main/resources/template/generator/front/api.ftl @@ -22,3 +22,12 @@ export function edit(data) { data }) } + +export function download${className}(params) { + return request({ + url: 'api/${changeClassName}/download', + method: 'get', + params, + responseType: 'blob' + }) +} diff --git a/eladmin-system/src/main/resources/template/generator/front/eForm.ftl b/eladmin-system/src/main/resources/template/generator/front/eForm.ftl index 1e8fbcd9..de44a6ae 100644 --- a/eladmin-system/src/main/resources/template/generator/front/eForm.ftl +++ b/eladmin-system/src/main/resources/template/generator/front/eForm.ftl @@ -5,7 +5,11 @@ <#list columns as column> <#if column.changeColumnName != '${pkChangeColName}'> prop="${column.changeColumnName}"> + <#if column.columnType != 'Timestamp'> + <#else > + + diff --git a/eladmin-system/src/main/resources/template/generator/front/index.ftl b/eladmin-system/src/main/resources/template/generator/front/index.ftl index c5e6ab88..456e955a 100644 --- a/eladmin-system/src/main/resources/template/generator/front/index.ftl +++ b/eladmin-system/src/main/resources/template/generator/front/index.ftl @@ -14,13 +14,23 @@
新增
+ +
+ 导出 +
@@ -41,11 +51,11 @@ - +