v2.0 代码提交

This commit is contained in:
zhuoda
2022-10-27 22:14:48 +08:00
parent 207b949484
commit f7e5f6d539
1851 changed files with 108157 additions and 2231 deletions

View File

@@ -0,0 +1,15 @@
1 超管默认账号
sa/123456
2 执行脚本:
先执行src/main/resources/sql/smart-admin.sql
再执行src/main/resources/sql/quartz_mysql_2.3.0.sql
3 除dev之外文件
4 刷新页面,获取权限是否走缓存
LoginService.getSession
5 test类中去掉代码生成run
6 前端百度统计

View File

@@ -0,0 +1,276 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>net.1024lab</groupId>
<artifactId>smart-admin-service-parent</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>smart-admin-api</artifactId>
<packaging>jar</packaging>
<name>smart-admin-api</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--springboot starter dependency begin -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<exclusions>
<exclusion>
<artifactId>logback-classic</artifactId>
<groupId>ch.qos.logback</groupId>
</exclusion>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--springboot starter dependency end -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--velocity begin-->
<dependency>
<artifactId>velocity</artifactId>
<groupId>org.apache.velocity</groupId>
<exclusions>
<exclusion>
<artifactId>commons-collections</artifactId>
<groupId>commons-collections</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
</dependency>
<!--velocity end-->
<!--fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!-- p6spy -->
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
</dependency>
<!-- swagger begin -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<!-- swagger end -->
<!-- knife4j begin -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<!-- knife4j end -->
<!-- guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<!-- oss begin -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<!-- oss end -->
<!--jjwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!-- easy poi begin -->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
</dependency>
<!-- easy poi end -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
<resource>
<filtering>false</filtering>
<directory>src/main/resources</directory>
<excludes>
<exclude>dev/*</exclude>
<exclude>sit/*</exclude>
<exclude>pre/*</exclude>
<exclude>prod/*</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources/${profiles.active}</directory>
<filtering>true</filtering>
<includes>
<include>*.properties</include>
<include>*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,29 @@
package net.lab1024.smartadmin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* [ admin 项目启动类 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*
*/
@SpringBootApplication(scanBasePackages = {"net.lab1024.smartadmin", "cn.afterturn.easypoi"})
@EnableCaching
@EnableScheduling
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class SmartAdminApplication {
public static void main(String[] args) {
SpringApplication.run(SmartAdminApplication.class, args);
}
}

View File

@@ -0,0 +1,47 @@
package net.lab1024.smartadmin.common.anno;
import net.lab1024.smartadmin.common.domain.BaseEnum;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 枚举类字段属性的注解
*
* @author listen
* @date 2019/05/16 15:18
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiModelPropertyEnum {
/**
* 枚举类对象
*
* @return
*/
Class<? extends BaseEnum> value();
String example() default "";
/**
* 是否隐藏
*
* @return
*/
boolean hidden() default false;
/**
* 是否必须
*
* @return
*/
boolean required() default true;
String dataType() default "";
String enumDesc() default "";
}

View File

@@ -0,0 +1,49 @@
package net.lab1024.smartadmin.common.anno;
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeTypeEnum;
import net.lab1024.smartadmin.module.system.datascope.constant.DataScopeWhereInTypeEnum;
import net.lab1024.smartadmin.module.system.datascope.strategy.DataScopePowerStrategy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* [ 数据范围 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataScope {
DataScopeTypeEnum dataScopeType() default DataScopeTypeEnum.DEFAULT;
DataScopeWhereInTypeEnum whereInType() default DataScopeWhereInTypeEnum.EMPLOYEE;
/**
* DataScopeWhereInTypeEnum.CUSTOM_STRATEGY类型 才可使用joinSqlImplClazz属性
* @return
*/
Class<? extends DataScopePowerStrategy> joinSqlImplClazz() default DataScopePowerStrategy.class;
/**
*
* 第几个where 条件 从0开始
* @return
*/
int whereIndex() default 0;
/**
* DataScopeWhereInTypeEnum为CUSTOM_STRATEGY类型时此属性无效
* @return
*/
String joinSql() default "";
}

View File

@@ -0,0 +1,22 @@
package net.lab1024.smartadmin.common.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* [ 不需要登陆 ]
*
* @version 1.0
* @since JDK1.8
* @author yandanyang
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface NoNeedLogin {
}

View File

@@ -0,0 +1,20 @@
package net.lab1024.smartadmin.common.anno;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
*
* [ 不需要权限验证 ]
*
* @version 1.0
* @since JDK1.8
* @author yandanyang
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface NoValidPrivilege {
}

View File

@@ -0,0 +1,20 @@
package net.lab1024.smartadmin.common.anno;
import java.lang.annotation.*;
/**
* [ 用户操作日志 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface OperateLog {
}

View File

@@ -0,0 +1,57 @@
package net.lab1024.smartadmin.common.constant;
import net.lab1024.smartadmin.common.domain.BaseEnum;
/**
* 全局排序枚举类
*
* @author listen
* @date 2018/01/13 14:24
*/
public enum CommentSortTypeEnum implements BaseEnum {
/**
* 正序 ASC 1
*/
ASC(1, "ASC"),
/**
* 倒序 DESC 2
*/
DESC(2, "DESC");
private Integer value;
private String desc;
/**
* 排序类型1正序 | 2倒序
*/
public static final String INFO = "排序类型1正序 | 2倒序";
CommentSortTypeEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
/**
* 获取枚举类的值
*
* @return Integer
*/
@Override
public Integer getValue() {
return value;
}
/**
* 获取枚举类的说明
*
* @return String
*/
@Override
public String getDesc() {
return desc;
}
}

View File

@@ -0,0 +1,52 @@
package net.lab1024.smartadmin.common.constant;
import net.lab1024.smartadmin.common.domain.BaseEnum;
import java.util.Arrays;
import java.util.Optional;
/**
*
* [ 是与否]
*
* @version 1.0
* @since JDK1.8
* @author yandanyang
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
*/
public enum JudgeEnum implements BaseEnum {
NO(0, ""),
YES(1, "");
private Integer value;
private String desc;
JudgeEnum(Integer value, String desc) {
this.value = value;
this.desc = desc;
}
@Override
public Integer getValue() {
return value;
}
@Override
public String getDesc() {
return desc;
}
public static JudgeEnum valueOf(Integer status) {
JudgeEnum[] values = JudgeEnum.values();
Optional<JudgeEnum> first = Arrays.stream(values).filter(e -> e.getValue().equals(status)).findFirst();
return !first.isPresent() ? null : first.get();
}
public static boolean isExist(Integer status) {
JudgeEnum judgeEnum = valueOf(status);
return judgeEnum != null;
}
}

View File

@@ -0,0 +1,181 @@
package net.lab1024.smartadmin.common.constant;
import net.lab1024.smartadmin.module.system.department.DepartmentResponseCodeConst;
import net.lab1024.smartadmin.module.system.employee.constant.EmployeeResponseCodeConst;
import net.lab1024.smartadmin.module.support.file.constant.FileResponseCodeConst;
import net.lab1024.smartadmin.module.business.log.orderoperatelog.constant.OrderOperateLogOperateTypeConst;
import net.lab1024.smartadmin.module.system.login.LoginResponseCodeConst;
import net.lab1024.smartadmin.module.system.position.PositionResponseCodeConst;
import net.lab1024.smartadmin.module.system.privilege.constant.PrivilegeResponseCodeConst;
import net.lab1024.smartadmin.module.system.role.basic.RoleResponseCodeConst;
import net.lab1024.smartadmin.module.system.systemconfig.constant.SystemConfigResponseCodeConst;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* 每个业务100个范围值就够了.
*/
@Slf4j
public class ResponseCodeConst {
// 范围声明
static {
// 系统功能从0开始step=1000
ResponseCodeContainer.register(ResponseCodeConst.class, 0, 1000);
ResponseCodeContainer.register(LoginResponseCodeConst.class, 1001, 1999);
ResponseCodeContainer.register(DepartmentResponseCodeConst.class, 2001, 2999);
ResponseCodeContainer.register(EmployeeResponseCodeConst.class, 3001, 3999);
ResponseCodeContainer.register(FileResponseCodeConst.class, 4001, 4999);
ResponseCodeContainer.register(SystemConfigResponseCodeConst.class, 5001, 5999);
ResponseCodeContainer.register(RoleResponseCodeConst.class, 6001, 6999);
ResponseCodeContainer.register(PrivilegeResponseCodeConst.class, 7001, 7999);
ResponseCodeContainer.register(OrderOperateLogOperateTypeConst.class, 8001, 8999);
ResponseCodeContainer.register(PositionResponseCodeConst.class, 13000, 13999);
}
public static final ResponseCodeConst SUCCESS = new ResponseCodeConst(1, "操作成功!", true);
public static final ResponseCodeConst ERROR_PARAM = new ResponseCodeConst(101, "参数异常!");
public static final ResponseCodeConst ERROR_PARAM_ANY = new ResponseCodeConst(102, "%s参数异常");
public static final ResponseCodeConst SYSTEM_ERROR = new ResponseCodeConst(111, "系统错误");
public static final ResponseCodeConst DEVELOPMENT = new ResponseCodeConst(112, "此功能正在开发中");
public static final ResponseCodeConst NOT_EXISTS = new ResponseCodeConst(113, "数据不存在");
public static ResponseCodeConst REQUEST_METHOD_ERROR = new ResponseCodeConst(114, "请求方式错误");
public static ResponseCodeConst JSON_FORMAT_ERROR = new ResponseCodeConst(115, "JSON格式错误");
protected int code;
protected String msg;
protected boolean success;
public ResponseCodeConst() {
}
protected ResponseCodeConst(int code, String msg) {
super();
this.code = code;
this.msg = msg;
ResponseCodeContainer.put(this);
}
protected ResponseCodeConst(int code, String msg, boolean success) {
super();
this.code = code;
this.msg = msg;
this.success = success;
ResponseCodeContainer.put(this);
}
protected ResponseCodeConst(int code) {
super();
this.code = code;
ResponseCodeContainer.put(this);
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public static void init() {
log.info("ResponseCodeConst init....");
}
// =======================分割=======================
/**
* 内部类用于检测code范围
*
* @author Anders
*/
@Slf4j
private static class ResponseCodeContainer {
private static final Map<Integer, ResponseCodeConst> RESPONSE_CODE_MAP = new HashMap<>();
private static final Map<Class<? extends ResponseCodeConst>, int[]> RESPONSE_CODE_RANGE_MAP = new HashMap<>();
/**
* id的范围[start, end]左闭右闭
*
* @param clazz
* @param start
* @param end
*/
private static void register(Class<? extends ResponseCodeConst> clazz, int start, int end) {
if (start > end) {
throw new IllegalArgumentException("<ResponseDTO> start > end!");
}
if (RESPONSE_CODE_RANGE_MAP.containsKey(clazz)) {
throw new IllegalArgumentException(String.format("<ResponseDTO> Class:%s already exist!", clazz.getSimpleName()));
}
RESPONSE_CODE_RANGE_MAP.forEach((k, v) -> {
if ((start >= v[0] && start <= v[1]) || (end >= v[0] && end <= v[1])) {
throw new IllegalArgumentException(String.format("<ResponseDTO> Class:%s 's id range[%d,%d] has " + "intersection with " + "class:%s", clazz.getSimpleName(), start, end,
k.getSimpleName()));
}
});
RESPONSE_CODE_RANGE_MAP.put(clazz, new int[]{start, end});
// 提前初始化static变量进行范围检测
Field[] fields = clazz.getFields();
if (fields.length != 0) {
try {
fields[0].get(clazz);
} catch (IllegalArgumentException | IllegalAccessException e) {
log.error("", e);
}
}
}
public static void put(ResponseCodeConst codeConst) {
int[] idRange = RESPONSE_CODE_RANGE_MAP.get(codeConst.getClass());
if (idRange == null) {
throw new IllegalArgumentException(String.format("<ResponseDTO> Class:%s has not been registered!", codeConst.getClass().getSimpleName()));
}
int code = codeConst.code;
if (code < idRange[0] || code > idRange[1]) {
throw new IllegalArgumentException(String.format("<ResponseDTO> Id(%d) out of range[%d,%d], " + "class:%s", code, idRange[0], idRange[1], codeConst.getClass().getSimpleName()));
}
if (RESPONSE_CODE_MAP.keySet().contains(code)) {
log.error(String.format("<ResponseDTO> Id(%d) out of range[%d,%d], " + "class:%s code is repeat!", code, idRange[0], idRange[1], codeConst.getClass().getSimpleName()));
System.exit(0);
}
RESPONSE_CODE_MAP.put(code, codeConst);
}
}
}

View File

@@ -0,0 +1,42 @@
package net.lab1024.smartadmin.common.controller;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* @author: zhuoda
* @create: 2020-03-31 08:54 PM from win10
*/
@Slf4j
public class BaseController {
/**
* 下载 Excel 消息头
* @param fileName
* @param workbook
* @param response
*/
public void downloadExcel(String fileName, Workbook workbook, HttpServletResponse response) {
try {
fileName = URLEncoder.encode(fileName, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.error("", e);
}
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xls");
try {
workbook.write(response.getOutputStream());
workbook.close();
} catch (IOException e) {
log.error("", e);
}
}
}

View File

@@ -0,0 +1,39 @@
package net.lab1024.smartadmin.common.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Date;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/3/27 0027 上午 11:15
* @since JDK1.8
*/
@Data
public class BaseEntity {
/**
* 主键id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 更新时间
*/
private Date updateTime;
/**
* 创建时间
*/
private Date createTime;
}

View File

@@ -0,0 +1,97 @@
package net.lab1024.smartadmin.common.domain;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONAware;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.CaseFormat;
import lombok.Data;
import java.util.LinkedHashMap;
import java.util.Objects;
/**
* @author listen
* @date 2018-07-17 下午 3:52
*/
public interface BaseEnum {
/**
* 获取枚举类的值
*
* @return Object
*/
Object getValue();
/**
* 获取枚举类的说明
*
* @return String
*/
String getDesc();
/**
* 比较参数是否与枚举类的value相同
*
* @param value
* @return boolean
*/
default boolean equalsValue(Object value) {
return Objects.equals(getValue(), value);
}
/**
* 比较枚举类是否相同
*
* @param baseEnum
* @return boolean
*/
default boolean equals(BaseEnum baseEnum) {
return Objects.equals(getValue(), baseEnum.getValue()) && Objects.equals(getDesc(), baseEnum.getDesc());
}
/**
* 返回枚举类的说明
*
* @param clazz 枚举类类对象
* @return
*/
static String getInfo(Class<? extends BaseEnum> clazz) {
BaseEnum[] enums = clazz.getEnumConstants();
LinkedHashMap<String, JSONObject> json = new LinkedHashMap<>(enums.length);
for (BaseEnum e : enums) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("value", new DeletedQuotationAware(e.getValue()));
jsonObject.put("desc", new DeletedQuotationAware(e.getDesc()));
json.put(e.toString(), jsonObject);
}
String enumJson = JSON.toJSONString(json, true);
enumJson = enumJson.replaceAll("\"", "");
enumJson= enumJson.replaceAll("\t","&nbsp;&nbsp;");
enumJson = enumJson.replaceAll("\n","<br>");
String prefix = " <br> export const <br> " + CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, clazz.getSimpleName() + " = <br> ");
return prefix + "" + enumJson + " <br>";
}
@Data
class DeletedQuotationAware implements JSONAware {
private String value;
public DeletedQuotationAware(Object value) {
if(value == null){
this.value = "";
}else if (value instanceof String) {
this.value = "'" + value + "'";
}else {
this.value = value.toString();
}
}
@Override
public String toJSONString() {
return value;
}
}
}

View File

@@ -0,0 +1,16 @@
package net.lab1024.smartadmin.common.domain;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/4/13 0013 下午 14:23
* @since JDK1.8
*/
public interface ITask {
void execute(String paramJson) throws Exception;
}

View File

@@ -0,0 +1,16 @@
package net.lab1024.smartadmin.common.domain;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
* @author: zhuoda
* @create: 2020-03-20 09:07 PM from win10
*/
@Slf4j
@Data
public class OrderItemDTO {
private String column;
private boolean asc = true;
}

View File

@@ -0,0 +1,33 @@
package net.lab1024.smartadmin.common.domain;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 分页基础参数
*
* @author lihaifan
* @Date Created in 2017/10/28 16:19
*/
@Data
public class PageParamDTO {
@NotNull(message = "分页参数不能为空")
@ApiModelProperty(value = "页码(不能为空)", example = "1")
protected Integer pageNum;
@NotNull(message = "每页数量不能为空")
@ApiModelProperty(value = "每页数量(不能为空)", example = "10")
@Max(value = 500, message = "每页最大为500")
protected Integer pageSize;
@ApiModelProperty("是否查询总条数")
protected Boolean searchCount;
@ApiModelProperty("排序")
protected List<OrderItemDTO> orders;
}

View File

@@ -0,0 +1,47 @@
package net.lab1024.smartadmin.common.domain;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* Page返回对象
*
* @Author lihaifan
* @Date Created in 2017/10/31 15:05
*/
@Data
public class PageResultDTO<T> {
/**
* 当前页
*/
@ApiModelProperty(value = "当前页")
private Long pageNum;
/**
* 每页的数量
*/
@ApiModelProperty(value = "每页的数量")
private Long pageSize;
/**
* 总记录数
*/
@ApiModelProperty(value = "总记录数")
private Long total;
/**
* 总页数
*/
@ApiModelProperty(value = "总页数")
private Long pages;
/**
* 结果集
*/
@ApiModelProperty(value = "结果集")
private List<T> list;
}

View File

@@ -0,0 +1,132 @@
package net.lab1024.smartadmin.common.domain;
import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
/**
* 返回类
*
* @param <T>
* @author zhuoda
*/
public class ResponseDTO<T> {
protected Integer code;
protected String msg;
protected Boolean success;
protected T data;
public ResponseDTO() {
}
public ResponseDTO(ResponseCodeConst responseCodeConst, String msg) {
this.code = responseCodeConst.getCode();
this.msg = msg;
this.success = responseCodeConst.isSuccess();
}
public ResponseDTO(ResponseCodeConst responseCodeConst, T data) {
super();
this.code = responseCodeConst.getCode();
this.msg = responseCodeConst.getMsg();
this.data = data;
this.success = responseCodeConst.isSuccess();
}
public ResponseDTO(ResponseCodeConst responseCodeConst, T data, String msg) {
super();
this.code = responseCodeConst.getCode();
this.msg = msg;
this.data = data;
this.success = responseCodeConst.isSuccess();
}
private ResponseDTO(ResponseCodeConst responseCodeConst) {
this.code = responseCodeConst.getCode();
this.msg = responseCodeConst.getMsg();
this.success = responseCodeConst.isSuccess();
}
public ResponseDTO(ResponseDTO responseDTO) {
this.code = responseDTO.getCode();
this.msg = responseDTO.getMsg();
this.success = responseDTO.isSuccess();
}
public static <T> ResponseDTO<T> succ() {
return new ResponseDTO(ResponseCodeConst.SUCCESS);
}
public static <T> ResponseDTO<T> succData(T data, String msg) {
return new ResponseDTO(ResponseCodeConst.SUCCESS, data, msg);
}
public static <T> ResponseDTO<T> succData(T data) {
return new ResponseDTO(ResponseCodeConst.SUCCESS, data);
}
public static <T> ResponseDTO succMsg(String msg) {
return new ResponseDTO(ResponseCodeConst.SUCCESS, msg);
}
public static <T> ResponseDTO<T> wrap(ResponseCodeConst codeConst) {
return new ResponseDTO<>(codeConst);
}
public static <T> ResponseDTO<T> wrap(ResponseCodeConst codeConst, T t) {
return new ResponseDTO<T>(codeConst, t);
}
public static <T> ResponseDTO<T> wrap(ResponseCodeConst codeConst, String msg) {
return new ResponseDTO<T>(codeConst, msg);
}
public static <T> ResponseDTO<T> wrapMsg(ResponseCodeConst codeConst, String msg) {
return new ResponseDTO<T>(codeConst, msg);
}
public String getMsg() {
return msg;
}
public ResponseDTO setMsg(String msg) {
this.msg = msg;
return this;
}
public int getCode() {
return code;
}
public ResponseDTO setCode(Integer code) {
this.code = code;
return this;
}
public T getData() {
return data;
}
public ResponseDTO setData(T data) {
this.data = data;
return this;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
@Override
public String toString() {
return "ResponseDTO{" + "code=" + code + ", msg='" + msg + '\'' + ", success=" + success + ", data=" + data +
'}';
}
}

View File

@@ -0,0 +1,148 @@
package net.lab1024.smartadmin.common.domain;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.*;
/**
* @author: zhuoda
* @create: 2020-02-03 17:37 PM from win10
*/
public class ValidateList<E> implements List<E> {
@Valid
@NotEmpty(message = "数据长度请大于0")
private List<E> list;
public ValidateList() {
this.list = new ArrayList<>();
}
public ValidateList(List<E> list) {
this.list = list;
}
public List<E> getList() {
return list;
}
public void setList(List<E> list) {
this.list = list;
}
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public boolean contains(Object o) {
return list.contains(o);
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
@Override
public boolean add(E e) {
return list.add(e);
}
@Override
public boolean remove(Object o) {
return list.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends E> c) {
return list.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
return list.addAll(index, c);
}
@Override
public boolean removeAll(Collection<?> c) {
return list.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return list.retainAll(c);
}
@Override
public void clear() {
list.clear();
}
@Override
public E get(int index) {
return list.get(index);
}
@Override
public E set(int index, E element) {
return list.set(index, element);
}
@Override
public void add(int index, E element) {
list.add(index, element);
}
@Override
public E remove(int index) {
return list.remove(index);
}
@Override
public int indexOf(Object o) {
return list.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
@Override
public ListIterator<E> listIterator() {
return list.listIterator();
}
@Override
public ListIterator<E> listIterator(int index) {
return list.listIterator(index);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
}

View File

@@ -0,0 +1,33 @@
package net.lab1024.smartadmin.common.exception;
/**
*
* [ 业务逻辑异常,全局异常拦截后统一返回ResponseCodeConst.SYSTEM_ERROR ]
*
* @version 1.0
* @since JDK1.8
* @author yandanyang
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
*/
public class SmartBusinessException extends RuntimeException {
public SmartBusinessException() {
}
public SmartBusinessException(String message) {
super(message);
}
public SmartBusinessException(String message, Throwable cause) {
super(message, cause);
}
public SmartBusinessException(Throwable cause) {
super(cause);
}
public SmartBusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@@ -0,0 +1,24 @@
package net.lab1024.smartadmin.common.exception;
/**
* [ 全局异常拦截后保留ResponseCode码的异常]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/8/7 0007 下午 16:11
* @since JDK1.8
*/
public class SmartResponseCodeException extends RuntimeException{
private Integer code;
public SmartResponseCodeException(Integer code, String message) {
super(message);
this.code = code;
}
public Integer getCode() {
return code;
}
}

View File

@@ -0,0 +1,90 @@
package net.lab1024.smartadmin.common.heartbeat;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
/**
* @Description: 心跳服务
* @Author: simajinqiang
* @Date: 2018/7/9 16:26
*/
public abstract class AbstractHeartBeatCommand implements HeartBeatRecordCommendInterface {
ScheduledExecutorService executorService;
int threadNum = 1;
/**
* 项目路径
*/
private String projectPath;
/**
* 服务器ip多网卡
*/
private List<String> serverIps;
/**
* 进程号
*/
private Integer processNo;
/**
* 进程开启时间
*/
private Date processStartTime;
HeartBeatLogger logger;
/**
* 初始化
*/
public void init(HeartBeatConfig config, HeartBeatLogger logger){
this.handlerHeartBeat();
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("AbstractHeartBeatCommand-%s").build();
executorService = Executors.newScheduledThreadPool(threadNum, threadFactory);
executorService.scheduleWithFixedDelay(new DoHeartBeat(), config.getDelayHandlerTime(), config.getIntervalTime(), TimeUnit.MILLISECONDS);
}
public void handlerHeartBeat(){
try {
projectPath = HeatBeatRecordHelper.getProjectPath();
serverIps = IpUtil.getLocalIPS();
processNo = HeatBeatRecordHelper.getProcessID();
processStartTime = HeatBeatRecordHelper.getStartTime();
}catch (Throwable e){
logger.error("get heart beat info error.", e);
}
}
/**
* 销毁线程池
*/
public void destroy(){
if (executorService != null && !executorService.isShutdown()) {
executorService.shutdown();
executorService = null;
}
}
public class DoHeartBeat implements Runnable{
@Override
public void run() {
try {
HeartBeatRecordDTO heartBeatRecord = new HeartBeatRecordDTO();
heartBeatRecord.setProjectPath(projectPath);
heartBeatRecord.setServerIp(StringUtil.join(serverIps,";"));
heartBeatRecord.setProcessNo(processNo);
heartBeatRecord.setProcessStartTime(processStartTime);
heartBeatRecord.setHeartBeatTime(new Date());
handler(heartBeatRecord);
}catch (Throwable t){
logger.error("handler heartbeat error.", t);
}
}
}
}

View File

@@ -0,0 +1,29 @@
package net.lab1024.smartadmin.common.heartbeat;
import lombok.Builder;
import lombok.Data;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/8/8 0008 下午 16:22
* @since JDK1.8
*/
@Data
@Builder
public class HeartBeatConfig {
/**
* 延迟执行时间
*/
private Long delayHandlerTime;
/**
* 间隔执行时间
*/
private Long intervalTime;
}

View File

@@ -0,0 +1,20 @@
package net.lab1024.smartadmin.common.heartbeat;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/8/8 0008 下午 16:23
* @since JDK1.8
*/
public interface HeartBeatLogger {
void error(String string);
void error(String string, Throwable e);
void info(String string);
}

View File

@@ -0,0 +1,17 @@
package net.lab1024.smartadmin.common.heartbeat;
/**
* @Description:
* @Author: simajinqiang
* @Date: 2018/7/9 14:06
*/
public interface HeartBeatRecordCommendInterface {
/**
* 处理
* @param heartBeatRecord
*/
void handler(HeartBeatRecordDTO heartBeatRecord);
}

View File

@@ -0,0 +1,37 @@
package net.lab1024.smartadmin.common.heartbeat;
import lombok.Data;
import java.util.Date;
/**
* @Description: 心跳记录日志
* @Author: simajinqiang
* @Date: 2018/7/9 11:11
*/
@Data
public class HeartBeatRecordDTO {
/**
* 项目名字
*/
private String projectPath;
/**
* 服务器ip
*/
private String serverIp;
/**
* 进程号
*/
private Integer processNo;
/**
* 进程开启时间
*/
private Date processStartTime;
/**
* 心跳当前时间
*/
private Date heartBeatTime;
}

View File

@@ -0,0 +1,45 @@
package net.lab1024.smartadmin.common.heartbeat;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.Date;
/**
* @Description: 心跳工具类
* @Author: simajinqiang
* @Date: 2018/7/9 11:48
*/
public class HeatBeatRecordHelper {
/**
* 获取进程号
* @return
*/
public static final Integer getProcessID() {
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
return Integer.valueOf(runtimeMXBean.getName().split("@")[0])
.intValue();
}
/**
* 获取项目名称
* @return
*/
public static final String getProjectPath(){
return System.getProperty("user.dir");
}
/**
* 获取进程启动时间
* @return
*/
public static final Date getStartTime(){
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
return new Date(runtimeMXBean.getStartTime());
}
}

View File

@@ -0,0 +1,81 @@
package net.lab1024.smartadmin.common.heartbeat;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
/**
* @Description: ip工具类
* @Author: sbq
* @CreateDate: 2019/8/8 10:33
* @Version: 1.0
*/
public class IpUtil {
/**
* 获得服务器的IP地址
*/
public static String getLocalIP() {
String sIP = "";
InetAddress ip = null;
try {
boolean bFindIP = false;
Enumeration<NetworkInterface> netInterfaces = (Enumeration<NetworkInterface>) NetworkInterface
.getNetworkInterfaces();
while (netInterfaces.hasMoreElements()) {
if (bFindIP) {
break;
}
NetworkInterface ni = (NetworkInterface) netInterfaces
.nextElement();
Enumeration<InetAddress> ips = ni.getInetAddresses();
while (ips.hasMoreElements()) {
ip = (InetAddress) ips.nextElement();
if (!ip.isLoopbackAddress()
&& ip.getHostAddress().matches(
"(\\d{1,3}\\.){3}\\d{1,3}")) {
bFindIP = true;
break;
}
}
}
} catch (Exception e) {
}
if (null != ip) {
sIP = ip.getHostAddress();
}
return sIP;
}
/**
* @Description: 获得服务器的IP地址(多网卡)
* @Author: sbq
* @CreateDate: 2019/8/8 10:34
* @Version: 1.0
*/
public static List<String> getLocalIPS() {
InetAddress ip = null;
List<String> ipList = new ArrayList<String>();
try {
Enumeration<NetworkInterface> netInterfaces = (Enumeration<NetworkInterface>) NetworkInterface
.getNetworkInterfaces();
while (netInterfaces.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) netInterfaces
.nextElement();
Enumeration<InetAddress> ips = ni.getInetAddresses();
while (ips.hasMoreElements()) {
ip = (InetAddress) ips.nextElement();
if (!ip.isLoopbackAddress()
&& ip.getHostAddress().matches(
"(\\d{1,3}\\.){3}\\d{1,3}")) {
ipList.add(ip.getHostAddress());
}
}
}
} catch (Exception e) {
}
return ipList;
}
}

View File

@@ -0,0 +1,60 @@
package net.lab1024.smartadmin.common.heartbeat;
import java.util.Iterator;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/8/8 0008 下午 16:27
* @since JDK1.8
*/
public class StringUtil {
public static String join(Iterable<?> iterable, String separator) {
return iterable == null ? null : join(iterable.iterator(), separator);
}
public static String join(Iterator<?> iterator, String separator) {
if (iterator == null) {
return null;
} else if (!iterator.hasNext()) {
return "";
} else {
Object first = iterator.next();
if (!iterator.hasNext()) {
String result = toString(first);
return result;
} else {
StringBuilder buf = new StringBuilder(256);
if (first != null) {
buf.append(first);
}
while(iterator.hasNext()) {
if (separator != null) {
buf.append(separator);
}
Object obj = iterator.next();
if (obj != null) {
buf.append(obj);
}
}
return buf.toString();
}
}
}
public static String toString(Object obj) {
return obj == null ? "" : obj.toString();
}
}

View File

@@ -0,0 +1,21 @@
package net.lab1024.smartadmin.common.json;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
public class LongJsonDeserializer extends JsonDeserializer<Long> {
@Override
public Long deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String value = jsonParser.getText();
try {
return value == null ? null : Long.parseLong(value);
} catch (NumberFormatException e) {
return null;
}
}
}

View File

@@ -0,0 +1,19 @@
package net.lab1024.smartadmin.common.json;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class LongJsonSerializer extends JsonSerializer<Long> {
@Override
public void serialize(Long value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
String text = (value == null ? null : String.valueOf(value));
if (text != null) {
jsonGenerator.writeString(text);
}
}
}

View File

@@ -0,0 +1,39 @@
package net.lab1024.smartadmin.common.kaptcha;
import com.google.common.collect.Lists;
import java.awt.*;
import java.util.List;
import java.util.Random;
/**
* [ 验证码颜色 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/7/6 0006 上午 10:51
* @since JDK1.8
*/
public class KaptchaColor {
public static Color getColor() {
List<Color> colors = Lists.newArrayList();
colors.add(new Color(0, 135, 255));
colors.add(new Color(51, 153, 51));
colors.add(new Color(255, 102, 102));
colors.add(new Color(255, 153, 0));
colors.add(new Color(153, 102, 0));
colors.add(new Color(153, 102, 153));
colors.add(new Color(51, 153, 153));
colors.add(new Color(102, 102, 255));
colors.add(new Color(0, 102, 204));
colors.add(new Color(204, 51, 51));
colors.add(new Color(128, 153, 65));
Random random = new Random();
int colorIndex = random.nextInt(10);
return colors.get(colorIndex);
}
}

View File

@@ -0,0 +1,44 @@
package net.lab1024.smartadmin.common.kaptcha;
import com.google.code.kaptcha.NoiseProducer;
import com.google.code.kaptcha.util.Configurable;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* [ 验证码加噪处理 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/7/6 0006 上午 10:47
* @since JDK1.8
*/
public class KaptchaNoise extends Configurable implements NoiseProducer {
public KaptchaNoise() {
}
@Override
public void makeNoise(BufferedImage image, float factorOne, float factorTwo, float factorThree, float factorFour) {
int width = image.getWidth();
int height = image.getHeight();
Graphics2D graph = (Graphics2D)image.getGraphics();
graph.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
graph.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
Random random = new Random();
int noiseLineNum = random.nextInt(3);
if(noiseLineNum == 0){
noiseLineNum = 1;
}
for (int i = 0; i < noiseLineNum; i++){
graph.setColor(KaptchaColor.getColor());
graph.drawLine(random.nextInt(width), random.nextInt(height), 10 + random.nextInt(20), 10 + random.nextInt(20));
}
graph.dispose();
}
}

View File

@@ -0,0 +1,75 @@
package net.lab1024.smartadmin.common.kaptcha;
import com.google.code.kaptcha.util.Configurable;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* [ 验证码字体生成 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/7/6 0006 上午 9:43
* @since JDK1.8
*/
public class KaptchaWordRenderer extends Configurable implements com.google.code.kaptcha.text.WordRenderer {
public KaptchaWordRenderer() {
}
@Override
public BufferedImage renderWord(String word, int width, int height) {
int fontSize = this.getConfig().getTextProducerFontSize();
Font[] fonts = this.getConfig().getTextProducerFonts(fontSize);
int charSpace = this.getConfig().getTextProducerCharSpace();
BufferedImage image = new BufferedImage(width, height, 2);
Graphics2D g2D = image.createGraphics();
g2D.setColor(Color.WHITE);
RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
hints.add(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2D.setRenderingHints(hints);
g2D.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
FontRenderContext frc = g2D.getFontRenderContext();
Random random = new Random();
int startPosY = (height - fontSize) / 5 + fontSize;
char[] wordChars = word.toCharArray();
Font[] chosenFonts = new Font[wordChars.length];
int[] charWidths = new int[wordChars.length];
int widthNeeded = 0;
int startPosX;
for(startPosX = 0; startPosX < wordChars.length; ++startPosX) {
chosenFonts[startPosX] = fonts[random.nextInt(fonts.length)];
char[] charToDraw = new char[]{wordChars[startPosX]};
GlyphVector gv = chosenFonts[startPosX].createGlyphVector(frc, charToDraw);
charWidths[startPosX] = (int)gv.getVisualBounds().getWidth();
if (startPosX > 0) {
widthNeeded += 2;
}
widthNeeded += charWidths[startPosX];
}
startPosX = (width - widthNeeded) / 2;
for(int i = 0; i < wordChars.length; ++i) {
g2D.setColor(KaptchaColor.getColor());
g2D.setFont(chosenFonts[i].deriveFont(Font.PLAIN));
char[] charToDraw = new char[]{wordChars[i]};
g2D.drawChars(charToDraw, 0, charToDraw.length, startPosX, startPosY);
startPosX = startPosX + charWidths[i] + charSpace;
}
return image;
}
}

View File

@@ -0,0 +1,134 @@
package net.lab1024.smartadmin.common.reload;
import net.lab1024.smartadmin.common.reload.annotation.SmartReload;
import net.lab1024.smartadmin.common.reload.domain.AbstractSmartReloadObject;
import net.lab1024.smartadmin.common.reload.domain.AnnotationReloadObject;
import net.lab1024.smartadmin.common.reload.domain.InterfaceReloadObject;
import net.lab1024.smartadmin.common.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.common.reload.domain.entity.SmartReloadResult;
import net.lab1024.smartadmin.common.reload.interfaces.SmartReloadCommandInterface;
import net.lab1024.smartadmin.common.reload.interfaces.SmartReloadThreadLogger;
import net.lab1024.smartadmin.common.reload.interfaces.SmartReloadable;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import static java.util.Objects.requireNonNull;
/**
* SmartReloadManager 管理器
* <p>
* 可以在此类中添加 检测任务 以及注册 处理程序
*
* @author zhuoda
*/
public class SmartReloadManager {
private Map<String, AbstractSmartReloadObject> tagReloadObject;
private SmartReloadScheduler reloadScheduler;
private SmartReloadThreadLogger logger;
public SmartReloadManager(SmartReloadThreadLogger logger, int threadCount) {
this.tagReloadObject = new ConcurrentHashMap<>();
if (logger == null) {
throw new ExceptionInInitializerError("SmartReloadLoggerImp cannot be null");
}
if (threadCount < 1) {
throw new ExceptionInInitializerError("threadCount must be greater than 1");
}
this.logger = logger;
this.reloadScheduler = new SmartReloadScheduler(this.logger, threadCount);
}
/**
* 默认创建单个线程
*
* @param logger
*/
public SmartReloadManager(SmartReloadThreadLogger logger) {
this(logger, 1);
}
/**
* 停止
*/
public void shutdown() {
reloadScheduler.shutdown();
}
/**
* 添加任务
*
* @param command SmartReloadCommand实现类
* @param initialDelay 第一次执行前的延迟时间
* @param delay 任务间隔时间
* @param unit 延迟单位 TimeUnit 天、小时、分、秒等
*/
public void addCommand(SmartReloadCommandInterface command, long initialDelay, long delay, TimeUnit unit) {
reloadScheduler.addCommand(command, initialDelay, delay, unit);
}
/**
* 注册 实现接口的方式
*
* @param tag
* @param reloadable
*/
public void register(String tag, SmartReloadable reloadable) {
requireNonNull(reloadable);
requireNonNull(tag);
if (tagReloadObject.containsKey(tag)) {
logger.error("<<SmartReloadManager>> register duplicated tag reload : " + tag + " , and it will be cover!");
}
tagReloadObject.put(tag, new InterfaceReloadObject(reloadable));
}
/**
* 注册 要求此类必须包含使用了SmartReload注解的方法
*
* @param reloadObject
*/
public void register(Object reloadObject) {
requireNonNull(reloadObject);
Method[] declaredMethods = reloadObject.getClass().getDeclaredMethods();
if (declaredMethods != null) {
for (int i = 0; i < declaredMethods.length; i++) {
Method method = declaredMethods[i];
SmartReload annotation = method.getAnnotation(SmartReload.class);
if (annotation != null) {
String reloadTag = annotation.value();
this.register(reloadTag, new AnnotationReloadObject(reloadObject, method));
}
}
}
}
private void register(String tag, AbstractSmartReloadObject reloadObject) {
if (tagReloadObject.containsKey(tag)) {
logger.error("<<SmartReloadManager>> register duplicated tag reload : " + tag + " , and it will be cover!");
}
tagReloadObject.put(tag, reloadObject);
}
/**
* Reload 已注册的ReloadItem
*
* @param reloadItem
* @return SmartReloadResult
*/
public SmartReloadResult doReload(ReloadItem reloadItem) {
AbstractSmartReloadObject reloadObject = tagReloadObject.get(reloadItem.getTag());
if (reloadObject != null) {
return reloadObject.reload(reloadItem);
}
// 返回注册结果
return new SmartReloadResult(reloadItem.getTag(), reloadItem.getArgs(), reloadItem.getIdentification(), false, "No registered reload handler was found");
}
}

View File

@@ -0,0 +1,87 @@
package net.lab1024.smartadmin.common.reload;
import net.lab1024.smartadmin.common.reload.interfaces.SmartReloadCommandInterface;
import net.lab1024.smartadmin.common.reload.interfaces.SmartReloadThreadLogger;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Reload 调度器
*
* @author zhuoda
*/
public class SmartReloadScheduler {
private ScheduledThreadPoolExecutor executor;
private SmartReloadThreadLogger logger;
SmartReloadScheduler(SmartReloadThreadLogger logger, int threadCount) {
this.executor = new ScheduledThreadPoolExecutor(threadCount, new SmartReloadSchedulerThreadFactory());
this.logger = logger;
}
void shutdown() {
try {
executor.shutdown();
} catch (Throwable e) {
logger.error("<<SmartReloadScheduler>> shutdown ", e);
}
}
void addCommand(SmartReloadCommandInterface command, long initialDelay, long delay, TimeUnit unit) {
executor.scheduleWithFixedDelay(new ScheduleRunnable(command, this.logger), initialDelay, delay, unit);
}
static class ScheduleRunnable implements Runnable {
private SmartReloadCommandInterface command;
private SmartReloadThreadLogger logger;
public ScheduleRunnable(SmartReloadCommandInterface command, SmartReloadThreadLogger logger) {
this.command = command;
this.logger = logger;
}
@Override
public void run() {
try {
command.doTask();
} catch (Throwable e) {
logger.error("", e);
}
}
}
static class SmartReloadSchedulerThreadFactory 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;
SmartReloadSchedulerThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
namePrefix = "smartreload-" + poolNumber.getAndIncrement() + "-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
}

View File

@@ -0,0 +1,66 @@
package net.lab1024.smartadmin.common.reload.abstracts;
import net.lab1024.smartadmin.common.reload.SmartReloadManager;
import net.lab1024.smartadmin.common.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.common.reload.interfaces.SmartReloadCommandInterface;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* 检测是否 Reload 的类
*
* @author zhuoda
*/
public abstract class AbstractSmartReloadCommand implements SmartReloadCommandInterface {
/**
* 当前ReloadItem的存储器
*/
private ConcurrentHashMap<String, String> currentTags = null;
/**
* Reload的执行类
*/
private SmartReloadManager reloadManager;
public AbstractSmartReloadCommand(SmartReloadManager reloadManager) {
this.reloadManager = reloadManager;
this.currentTags = new ConcurrentHashMap<>();
// 初始获取ReloadItem数据
List<ReloadItem> readTagStatesFromDb = readReloadItem();
if (readTagStatesFromDb != null) {
for (ReloadItem reloadItem : readTagStatesFromDb) {
String tag = reloadItem.getTag();
String tagChangeIdentifier = reloadItem.getIdentification();
this.currentTags.put(tag, tagChangeIdentifier);
}
}
}
/**
* 任务:
* 读取数据库中 ReloadItem 数据
* 校验是否发生变化
* 执行重加载动作
*/
@Override
public void doTask() {
// 获取数据库数据
List<ReloadItem> readTagStatesFromDb = readReloadItem();
String tag;
String tagIdentifier;
String preTagChangeIdentifier;
for (ReloadItem reloadItem : readTagStatesFromDb) {
tag = reloadItem.getTag();
tagIdentifier = reloadItem.getIdentification();
preTagChangeIdentifier = currentTags.get(tag);
// 数据不一致
if (preTagChangeIdentifier == null || ! preTagChangeIdentifier.equals(tagIdentifier)) {
// 更新map数据
currentTags.put(tag, tagIdentifier);
// 执行重新加载此项的动作
handleReloadResult(this.reloadManager.doReload(reloadItem));
}
}
}
}

View File

@@ -0,0 +1,67 @@
package net.lab1024.smartadmin.common.reload.abstracts;
import net.lab1024.smartadmin.common.reload.SmartReloadManager;
import net.lab1024.smartadmin.common.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.common.reload.interfaces.SmartReloadCommandInterface;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
* 检测是否 Reload 的类
*
* @author zhuoda
*/
public abstract class AbstractSmartReloadCommand4Spring implements SmartReloadCommandInterface {
/**
* 当前ReloadItem的存储器
*/
protected ConcurrentHashMap<String, String> currentTags = new ConcurrentHashMap<>();
/**
* Reload的执行类
*/
@Autowired
protected SmartReloadManager reloadManager;
// @PostConstruct
public void init() {
List<ReloadItem> readTagStatesFromDb = readReloadItem();
if (readTagStatesFromDb != null) {
for (ReloadItem reloadItem : readTagStatesFromDb) {
String tag = reloadItem.getTag();
String tagChangeIdentifier = reloadItem.getIdentification();
this.currentTags.put(tag, tagChangeIdentifier);
}
}
}
/**
* 任务:
* 读取数据库中 ReloadItem 数据
* 校验是否发生变化
* 执行重加载动作
*/
@Override
public void doTask() {
// 获取数据库数据
List<ReloadItem> readTagStatesFromDb = readReloadItem();
String tag;
String tagIdentifier;
String preTagChangeIdentifier;
for (ReloadItem reloadItem : readTagStatesFromDb) {
tag = reloadItem.getTag();
tagIdentifier = reloadItem.getIdentification();
preTagChangeIdentifier = currentTags.get(tag);
// 数据不一致
if (preTagChangeIdentifier == null || ! preTagChangeIdentifier.equals(tagIdentifier)) {
// 更新map数据
currentTags.put(tag, tagIdentifier);
// 执行重新加载此项的动作
handleReloadResult(this.reloadManager.doReload(reloadItem));
}
}
}
}

View File

@@ -0,0 +1,18 @@
package net.lab1024.smartadmin.common.reload.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 定义 SmartReload 注解
*
* @author zhuoda
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SmartReload {
String value();
}

View File

@@ -0,0 +1,31 @@
package net.lab1024.smartadmin.common.reload.domain;
import net.lab1024.smartadmin.common.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.common.reload.domain.entity.SmartReloadResult;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* AbstractSmartReloadObject 处理程序的抽象类
*
* @author zhuoda
*/
public abstract class AbstractSmartReloadObject {
protected String getStackTrace(Throwable e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
return sw.toString();
}
/**
* 通过reloadItem参数reload获得结果
*
* @param reloadItem
* @return boolean
* @author zhuokongming
* @date 2016年10月21日 下午2:09:44
*/
public abstract SmartReloadResult reload(ReloadItem reloadItem);
}

View File

@@ -0,0 +1,44 @@
package net.lab1024.smartadmin.common.reload.domain;
import net.lab1024.smartadmin.common.reload.annotation.SmartReload;
import net.lab1024.smartadmin.common.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.common.reload.domain.entity.SmartReloadResult;
import java.lang.reflect.Method;
/**
* Reload 处理程序的实现类
* 用于包装以注解 SmartReload 实现的处理类
*
* @author zhuoda
*/
public class AnnotationReloadObject extends AbstractSmartReloadObject {
private Object reloadObject;
private Method method;
public AnnotationReloadObject(Object reloadObject, Method method) {
super();
this.reloadObject = reloadObject;
this.method = method;
this.method.setAccessible(true);
}
@Override
public SmartReloadResult reload(ReloadItem reloadItem) {
SmartReloadResult result = new SmartReloadResult();
String tag = method.getAnnotation(SmartReload.class).value();
result.setTag(tag);
result.setArgs(reloadItem.getArgs());
result.setIdentification(reloadItem.getIdentification());
try {
Object invoke = method.invoke(reloadObject, reloadItem.getArgs());
result.setResult((Boolean) invoke);
} catch (Throwable e) {
result.setException(getStackTrace(e));
}
return result;
}
}

View File

@@ -0,0 +1,37 @@
package net.lab1024.smartadmin.common.reload.domain;
import net.lab1024.smartadmin.common.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.common.reload.domain.entity.SmartReloadResult;
import net.lab1024.smartadmin.common.reload.interfaces.SmartReloadable;
/**
* Reload 处理程序的实现类
* 用于处理以接口实现的处理类
*
* @author zhuoda
*/
public class InterfaceReloadObject extends AbstractSmartReloadObject {
private SmartReloadable object;
public InterfaceReloadObject(SmartReloadable object) {
super();
this.object = object;
}
@Override
public SmartReloadResult reload(ReloadItem reloadItem) {
SmartReloadResult reloadResult = new SmartReloadResult();
reloadResult.setArgs(reloadItem.getArgs());
reloadResult.setIdentification(reloadItem.getIdentification());
reloadResult.setTag(reloadItem.getTag());
try {
boolean res = object.reload(reloadItem);
reloadResult.setResult(res);
} catch (Throwable e) {
reloadResult.setException(getStackTrace(e));
}
return reloadResult;
}
}

View File

@@ -0,0 +1,55 @@
package net.lab1024.smartadmin.common.reload.domain.entity;
/**
* ReloadItem 类
*
* @author zhuoda
*/
public class ReloadItem {
/**
* 项名称
*/
private String tag;
/**
* 参数
*/
private String args;
/**
* 标识
*/
private String identification;
public ReloadItem() {
}
public ReloadItem(String tag, String identification, String args) {
this.tag = tag;
this.identification = identification;
this.args = args;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public String getIdentification() {
return identification;
}
public void setIdentification(String identification) {
this.identification = identification;
}
public String getArgs() {
return args;
}
public void setArgs(String args) {
this.args = args;
}
@Override
public String toString() {
return "ReloadItem{" + "tag='" + tag + '\'' + ", identification='" + identification + '\'' + ", args='" + args + '\'' + '}';
}
}

View File

@@ -0,0 +1,102 @@
package net.lab1024.smartadmin.common.reload.domain.entity;
/**
* t_reload_result 表 实体类
*
* @author zhuoda
*/
public class SmartReloadResult {
/**
* 项名称
*/
private String tag;
/**
* 参数
*/
private String args;
/**
* 标识
*/
private String identification;
/**
* 处理结果
*/
private boolean result;
/**
* 异常说明
*/
private String exception;
public SmartReloadResult() {
}
public SmartReloadResult(String tag, String args, boolean result, String exception) {
this.tag = tag;
this.args = args;
this.result = result;
this.exception = exception;
}
public SmartReloadResult(String tag, String args, String identification, boolean result, String exception) {
this.tag = tag;
this.args = args;
this.identification = identification;
this.result = result;
this.exception = exception;
}
public void setTag(String tag) {
this.tag = tag;
}
public void setArgs(String args) {
this.args = args;
}
public void setIdentification(String identification) {
this.identification = identification;
}
public void setResult(boolean result) {
this.result = result;
}
public void setException(String exception) {
this.exception = exception;
}
public String getTag() {
return tag;
}
public String getArgs() {
return args;
}
public String getIdentification() {
return identification;
}
public boolean isResult() {
return result;
}
public String getException() {
return exception;
}
@Override
public String toString() {
return "SmartReloadResult{" +
"tag='" + tag + '\'' +
", args='" + args + '\'' +
", identification='" + identification + '\'' +
", result=" + result +
", exception='" + exception + '\'' +
'}';
}
}

View File

@@ -0,0 +1,38 @@
package net.lab1024.smartadmin.common.reload.interfaces;
import net.lab1024.smartadmin.common.reload.domain.entity.ReloadItem;
import net.lab1024.smartadmin.common.reload.domain.entity.SmartReloadResult;
import java.util.List;
/**
* 检测是否 Reload 的类
*
* @author zhuoda
*/
public interface SmartReloadCommandInterface {
/**
* 任务:
* 读取数据库中 ReloadItem 数据
* 校验是否发生变化
* 执行重加载动作
*/
void doTask();
/**
* 该方法返回一个List<ReloadItem></>:<br>
* ReloadItem对象的tagIdentify为该tag的 状态状态其实就是个字符串如果该字符串跟上次有变化则进行reload操作<br>
* ReloadItem对象的args为 reload操作需要的参数<br><br>
*
* @return List<ReloadItem>
*/
List<ReloadItem> readReloadItem();
/**
* 处理Reload结果
*
* @param reloadResult
*/
void handleReloadResult(SmartReloadResult reloadResult);
}

View File

@@ -0,0 +1,12 @@
package net.lab1024.smartadmin.common.reload.interfaces;
/**
* SmartReloadThreadLogger 日志类
*/
public interface SmartReloadThreadLogger {
void error(String string);
void error(String string, Throwable e);
}

View File

@@ -0,0 +1,19 @@
package net.lab1024.smartadmin.common.reload.interfaces;
import net.lab1024.smartadmin.common.reload.domain.entity.ReloadItem;
/**
* reload 接口<br>
* 需要reload的业务实现类
*/
@FunctionalInterface
public interface SmartReloadable {
/**
* reload
*
* @param reloadItem
* @return boolean
*/
boolean reload(ReloadItem reloadItem);
}

View File

@@ -0,0 +1,90 @@
/*
*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package net.lab1024.smartadmin.common.swagger;
import net.lab1024.smartadmin.common.anno.ApiModelPropertyEnum;
import net.lab1024.smartadmin.common.domain.BaseEnum;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotationUtils;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
import springfox.documentation.swagger.common.SwaggerPluginSupport;
import java.lang.reflect.AnnotatedElement;
import static springfox.documentation.schema.Annotations.findPropertyAnnotation;
/**
* swagger 用于说明枚举类字段说明
* SWAGGER_PLUGIN_ORDER+1 是将此配置放在原来的后面执行
*
* @author listen
* @date 2019年5月16日 15:36:56
*/
public class SmartSwaggerApiModelEnumPlugin implements ModelPropertyBuilderPlugin {
@Override
public void apply(ModelPropertyContext context) {
Optional<ApiModelPropertyEnum> enumOptional = Optional.absent();
if (context.getAnnotatedElement().isPresent()) {
enumOptional = enumOptional.or(findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
}
if (context.getBeanPropertyDefinition().isPresent()) {
enumOptional = enumOptional.or(findPropertyAnnotation(context.getBeanPropertyDefinition().get(), ApiModelPropertyEnum.class));
}
if (enumOptional.isPresent()) {
ApiModelPropertyEnum anEnum = enumOptional.get();
String enumInfo = BaseEnum.getInfo(anEnum.value());
context.getBuilder()
.required(enumOptional.transform(toIsRequired()).or(false))
.description(anEnum.enumDesc() + ":" + enumInfo)
.example(enumOptional.transform(toExample()).orNull())
.isHidden(anEnum.hidden());
}
}
@Override
public boolean supports(DocumentationType delimiter) {
return SwaggerPluginSupport.pluginDoesApply(delimiter);
}
static Function<ApiModelPropertyEnum, Boolean> toIsRequired() {
return annotation -> annotation.required();
}
public static Optional<ApiModelPropertyEnum> findApiModePropertyAnnotation(AnnotatedElement annotated) {
return Optional.fromNullable(AnnotationUtils.getAnnotation(annotated, ApiModelPropertyEnum.class));
}
static Function<ApiModelPropertyEnum, String> toExample() {
return annotation -> {
String example = annotation.example();
if (StringUtils.isBlank(example)) {
return "";
}
return example;
};
}
}

View File

@@ -0,0 +1,73 @@
package net.lab1024.smartadmin.common.validator.bigdecimal;
import net.lab1024.smartadmin.util.SmartBigDecimalUtil;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.math.BigDecimal;
/**
* BigDecimal 类校验器
*
* @author listen
* @date 2018年3月20日 13:51:46
*/
public class BigDecimalValidator implements ConstraintValidator<CheckBigDecimal, BigDecimal> {
/**
* 获取定义的数值
*/
private BigDecimal value;
/**
* 获取比较符
*/
private ComparisonSymbolEnum symbolEnum;
/**
* 是否必须
*/
private boolean required;
@Override
public void initialize(CheckBigDecimal constraintAnnotation) {
// 初始化属性
value = new BigDecimal(constraintAnnotation.value());
symbolEnum = constraintAnnotation.symbolEnum();
required = constraintAnnotation.required();
}
@Override
public boolean isValid(BigDecimal decimal, ConstraintValidatorContext constraintValidatorContext) {
// 如果数值为空,校验是否必须
if (null == decimal) {
return ! required;
}
// 根据操作符,校验结果
switch (symbolEnum) {
// 等于
case EQUAL:
return SmartBigDecimalUtil.equals(decimal, value);
// 不等于
case NOT_EQUAL:
return ! SmartBigDecimalUtil.equals(decimal, value);
// 小于
case LESS_THAN:
return SmartBigDecimalUtil.isLessThan(decimal, value);
// 小于等于
case LESS_THAN_OR_EQUAL:
return SmartBigDecimalUtil.isLessThan(decimal, value) || SmartBigDecimalUtil.equals(decimal, value);
// 大于
case GREATER_THAN:
return SmartBigDecimalUtil.isGreaterThan(decimal, value);
// 大于等于
case GREATER_THAN_OR_EQUAL:
return SmartBigDecimalUtil.isGreaterThan(decimal, value) || SmartBigDecimalUtil.equals(decimal, value);
default:
}
return false;
}
}

View File

@@ -0,0 +1,53 @@
package net.lab1024.smartadmin.common.validator.bigdecimal;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义的属性校验注解
*
* @author listen
* @date 2018年3月20日 13:53:33
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = BigDecimalValidator.class)// 自定义验证的处理类
public @interface CheckBigDecimal {
/**
* 与这个数值校验
*
* @return
*/
String value();
/**
* 比较符 请使用 ComparisonSymbolEnum 枚举类
*
* @return
*/
ComparisonSymbolEnum symbolEnum();
/**
* 默认的错误提示信息
*
* @return String
*/
String message() default "非法的数值";
/**
* 是否必须 : 默认 true
*
* @return boolean
*/
boolean required() default true;
//下面这两个属性必须添加 :不然会报错
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

View File

@@ -0,0 +1,40 @@
package net.lab1024.smartadmin.common.validator.bigdecimal;
/**
* 比较符枚举类
*
* @author listen
* @date 2018/03/20 14:01
*/
public enum ComparisonSymbolEnum {
/**
* 等于
*/
EQUAL,
/**
* 不等于
*/
NOT_EQUAL,
/**
* 小于
*/
LESS_THAN,
/**
* 小于等于
*/
LESS_THAN_OR_EQUAL,
/**
* 大于
*/
GREATER_THAN,
/**
* 大于等于
*/
GREATER_THAN_OR_EQUAL,
}

View File

@@ -0,0 +1,50 @@
package net.lab1024.smartadmin.common.validator.en;
import net.lab1024.smartadmin.common.domain.BaseEnum;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义的属性校验注解
* 为了方便与校验属性的值是否为合法的枚举值
*
* @author listen
* @date 2017/11/11 15:31
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumValidator.class)// 自定义验证的处理类
public @interface CheckEnum {
/**
* 默认的错误提示信息
*
* @return String
*/
String message() default "非法的枚举值";
/**
* 枚举类对象 必须实现BaseEnum接口
*
* @return
*/
Class<? extends BaseEnum> enumClazz();
/**
* 是否必须
*
* @return boolean
*/
boolean required() default false;
//下面这两个属性必须添加 :不然会报错
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

View File

@@ -0,0 +1,71 @@
package net.lab1024.smartadmin.common.validator.en;
import net.lab1024.smartadmin.common.domain.BaseEnum;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 枚举类校验器
*
* @author listen
* @date 2017/11/11 15:34
*/
public class EnumValidator implements ConstraintValidator<CheckEnum, Object> {
/**
* 枚举类实例集合
*/
private List<Object> enumValList;
/**
* 是否必须
*/
private boolean required;
@Override
public void initialize(CheckEnum constraintAnnotation) {
// 获取注解传入的枚举类对象
required = constraintAnnotation.required();
Class<? extends BaseEnum> enumClass = constraintAnnotation.enumClazz();
enumValList = Stream.of(enumClass.getEnumConstants()).map(BaseEnum::getValue).collect(Collectors.toList());
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
// 判断是否必须
if (null == value) {
return !required;
}
if (value instanceof List) {
// 如果为 List 集合数据
return this.checkList((List<Object>) value);
}
// 校验是否为合法的枚举值
return enumValList.contains(value);
}
/**
* 校验集合类型
*
* @param list
* @return
*/
private boolean checkList(List<Object> list) {
if (required && list.isEmpty()) {
// 必须的情况下 list 不能为空
return false;
}
// 校验是否重复
long count = list.stream().distinct().count();
if (count != list.size()) {
return false;
}
return enumValList.containsAll(list);
}
}

View File

@@ -0,0 +1,25 @@
package net.lab1024.smartadmin.config;
import net.lab1024.smartadmin.interceptor.SmartAuthenticationInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
@Configuration
public class SmartAdminWebAppConfig implements WebMvcConfigurer {
@Autowired
private SmartAuthenticationInterceptor smartAuthenticationInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(smartAuthenticationInterceptor).addPathPatterns("/**");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/druidMonitor").setViewName("redirect:/druid/index.html");
registry.addViewController("/swaggerApi").setViewName("redirect:/swagger-ui.html");
}
}

View File

@@ -0,0 +1,172 @@
package net.lab1024.smartadmin.config;
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
import com.alibaba.druid.util.JdbcConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* [ 数据源配置 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
@Slf4j
@Configuration
public class SmartDruidDataSourceConfig {
@Value("${spring.datasource.driver-class-name}")
String driver;
@Value("${spring.datasource.url}")
String url;
@Value("${spring.datasource.username}")
String username;
@Value("${spring.datasource.password}")
String password;
@Value("${spring.datasource.initial-size}")
int initialSize;
@Value("${spring.datasource.min-idle}")
int minIdle;
@Value("${spring.datasource.max-active}")
int maxActive;
@Value("${spring.datasource.max-wait}")
long maxWait;
@Value("${spring.datasource.time-between-eviction-runs-millis}")
long timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.min-evictable-idle-time-millis}")
long minEvictableIdleTimeMillis;
@Value("${spring.datasource.filters}")
String filters;
@Value("${spring.datasource.druid.username}")
String druidUserName;
@Value("${spring.datasource.druid.password}")
String druidPassword;
@Value("${spring.datasource.druid.login.enabled}")
boolean druidLoginEnable;
@Autowired
private StatFilter logSlowSql;
@Autowired
private DruidStatInterceptor druidStatInterceptor;
@Bean
@Primary
public DataSource druidDataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDbType(JdbcConstants.MYSQL);
druidDataSource.setDriverClassName(driver);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
druidDataSource.setInitialSize(initialSize);
druidDataSource.setMinIdle(minIdle);
druidDataSource.setMaxActive(maxActive);
druidDataSource.setMaxWait(maxWait);
druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
try {
druidDataSource.setFilters(filters);
ArrayList<Filter> arrayList = new ArrayList<>();
arrayList.add(logSlowSql);
druidDataSource.setProxyFilters(arrayList);
druidDataSource.init();
} catch (SQLException e) {
log.error("初始化数据源出错", e);
}
return druidDataSource;
}
@Bean
public ServletRegistrationBean druidServlet() {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
servletRegistrationBean.setServlet(new StatViewServlet());
servletRegistrationBean.addUrlMappings("/druid/*");
Map<String, String> initParameters = new HashMap<String, String>();
//不设置用户名密码可以直接通过druid/index.html访问
if (druidLoginEnable) {
initParameters.put("loginUsername", druidUserName);
initParameters.put("loginPassword", druidPassword);
}
initParameters.put("resetEnable", "false");
servletRegistrationBean.setInitParameters(initParameters);
return servletRegistrationBean;
}
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
@Bean
public StatFilter logSlowSql() {
StatFilter statFilter = new StatFilter();
statFilter.setMergeSql(true);
statFilter.setSlowSqlMillis(300);
statFilter.setLogSlowSql(true);
return statFilter;
}
@Bean(name = "druid-stat-interceptor")
public DruidStatInterceptor druidStatInterceptor() {
DruidStatInterceptor dsInterceptor = new DruidStatInterceptor();
return dsInterceptor;
}
@Bean
public JdkRegexpMethodPointcut jdkRegexpMethodPointcut() {
JdkRegexpMethodPointcut jdkRegexpMethodPointcut = new JdkRegexpMethodPointcut();
jdkRegexpMethodPointcut.setPatterns("net.lab1024.smartadmin.module..*Service.*");
return jdkRegexpMethodPointcut;
}
@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor() {
DefaultPointcutAdvisor pointcutAdvisor = new DefaultPointcutAdvisor();
pointcutAdvisor.setPointcut(jdkRegexpMethodPointcut());
pointcutAdvisor.setAdvice(druidStatInterceptor);
return pointcutAdvisor;
}
}

View File

@@ -0,0 +1,33 @@
package net.lab1024.smartadmin.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
*
* [ ]
*
* @version 1.0
* @since JDK1.8
* @author yandanyang
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
*/
@Data
@Configuration
public class SmartHeartBeatConfig {
/**
* 延迟执行时间
*/
@Value("${heart-beat.delayHandlerTime}")
private Long delayHandlerTime;
/**
* 间隔执行时间
*/
@Value("${heart-beat.intervalTime}")
private Long intervalTime;
}

View File

@@ -0,0 +1,49 @@
package net.lab1024.smartadmin.config;
import net.lab1024.smartadmin.common.kaptcha.KaptchaNoise;
import net.lab1024.smartadmin.common.kaptcha.KaptchaWordRenderer;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
/**
* [ 验证码配置 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/7/4 0004 上午 9:40
* @since JDK1.8
*/
@Configuration
public class SmartKaptchaConfig {
@Bean
public DefaultKaptcha getDefaultKaptcha(){
DefaultKaptcha defaultKaptcha=new DefaultKaptcha();
Properties properties=new Properties();
properties.setProperty("kaptcha.border", "no");
properties.setProperty("kaptcha.border.color", "34,114,200");
properties.setProperty("kaptcha.image.width", "125");
properties.setProperty("kaptcha.image.height", "45");
properties.setProperty("kaptcha.textproducer.char.string", "0123456789");
properties.setProperty("kaptcha.textproducer.char.length", "4");
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Arial Narrow,Serif,Helvetica,Tahoma,Times New Roman,Verdana");
properties.setProperty("kaptcha.textproducer.font.size", "38");
properties.setProperty("kaptcha.background.clear.from", "white");
properties.setProperty("kaptcha.background.clear.to", "white");
properties.setProperty("kaptcha.word.impl", KaptchaWordRenderer.class.getName());
properties.setProperty("kaptcha.noise.impl", KaptchaNoise.class.getName());
Config config=new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}

View File

@@ -0,0 +1,27 @@
package net.lab1024.smartadmin.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* @author zhuoda
*/
@EnableTransactionManagement
@Configuration
@MapperScan(basePackages = {"net.lab1024.smartadmin.module.*"})
public class SmartMybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
// 开启 count 的 join 优化,只针对 left join !!!
return new PaginationInterceptor().setCountSqlParser(new JsqlParserCountOptimize(true));
}
}

View File

@@ -0,0 +1,74 @@
package net.lab1024.smartadmin.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* [ redis配置 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
@Configuration
public class SmartRedisConfig {
@Autowired
private RedisConnectionFactory factory;
@Bean
public RedisTemplate<String, Object> redisTemplate() {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashKeySerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.setDefaultSerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
@Bean
public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
return redisTemplate.opsForValue();
}
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}

View File

@@ -0,0 +1,45 @@
package net.lab1024.smartadmin.config;
import net.lab1024.smartadmin.common.reload.SmartReloadManager;
import net.lab1024.smartadmin.common.reload.interfaces.SmartReloadThreadLogger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/3/28 0028 下午 20:15
* @since JDK1.8
*/
@Slf4j
@Configuration
public class SmartReloadConfig {
@Value("${smart-reload.thread-count}")
private Integer threadCount;
@Bean
public SmartReloadManager initSmartReloadManager() {
/**
* 创建 Reload Manager 调度器
*/
SmartReloadManager smartReloadManager = new SmartReloadManager(new SmartReloadThreadLogger() {
@Override
public void error(String string) {
log.error(string);
}
@Override
public void error(String string, Throwable e) {
log.error(string, e);
}
}, threadCount);
return smartReloadManager;
}
}

View File

@@ -0,0 +1,109 @@
package net.lab1024.smartadmin.config;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
@Configuration
public class SmartRestTemplateConfig {
@Value("${http.pool.max-total}")
private Integer maxTotal;
@Value("${http.pool.default-max-per-route}")
private Integer defaultMaxPerRoute;
@Value("${http.pool.socket-timeout}")
private Integer socketTimeout;
@Value("${http.pool.connect-timeout}")
private Integer connectTimeout;
@Value("${http.pool.connection-request-timeout}")
private Integer connectionRequestTimeout;
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory httpRequestFactory() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient());
return factory;
}
/**
* fastJsonRestTemplate
*
* @return
*/
@Bean(name = "fastJsonRestTemplate")
public RestTemplate fastJsonRestTemplate() {
RestTemplate restTemplate = new RestTemplate(httpRequestFactory());
HttpMessageConverter<?> converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastConverter.setSupportedMediaTypes(fastMediaTypes);
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
converters.add(1,converter);
converters.add(fastConverter);
return restTemplate;
}
@Bean
public HttpClient httpClient() {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
connectionManager.setMaxTotal(maxTotal);
connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(socketTimeout)
.setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout)
.build();
return HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.build();
}
}

View File

@@ -0,0 +1,29 @@
package net.lab1024.smartadmin.config;
import net.lab1024.smartadmin.common.swagger.SmartSwaggerApiModelEnumPlugin;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.Order;
import springfox.documentation.swagger.common.SwaggerPluginSupport;
/**
* [ 对于枚举类进行swagger注解与前端的vue-enum相匹配 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/8/9 0009 上午 9:46
* @since JDK1.8
*/
@Configuration
@Profile({"dev", "sit", "pre", "prod"})
public class SmartSwaggerApiModelEnumConfig {
@Bean
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1)
public SmartSwaggerApiModelEnumPlugin swaggerEnum(){
return new SmartSwaggerApiModelEnumPlugin();
}
}

View File

@@ -0,0 +1,236 @@
package net.lab1024.smartadmin.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.smartadmin.constant.SwaggerTagConst;
import net.lab1024.smartadmin.interceptor.SmartAuthenticationInterceptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* [ 根据SwaggerTagConst内部类动态生成Swagger group ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/8/7 0007 下午 19:20
* @since JDK1.8
*/
@Slf4j
@EnableSwagger2
@EnableKnife4j
@Configuration
@Profile({"dev", "sit", "pre", "prod"})
public class SmartSwaggerDynamicGroupConfig implements EnvironmentAware, BeanDefinitionRegistryPostProcessor {
/**
* 分组名称
*/
private String apiGroupName;
/**
* 文档标题
*/
private String title;
/**
* 文档描述
*/
private String description;
/**
* api版本
*/
private String version;
/**
* service url
*/
private String serviceUrl;
/**
* controller 包路径
*/
private String packAge;
private int groupIndex = 0;
private String groupName = "default";
private final List<String> groupList = Lists.newArrayList();
private final Map<String, List<String>> groupMap = Maps.newHashMap();
@Override
public void setEnvironment(Environment environment) {
this.apiGroupName = environment.getProperty("swagger.apiGroupName");
this.title = environment.getProperty("swagger.title");
this.description = environment.getProperty("swagger.description");
this.version = environment.getProperty("swagger.version");
this.serviceUrl = environment.getProperty("swagger.serviceUrl");
this.packAge = environment.getProperty("swagger.packAge");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
this.groupBuild();
for (Map.Entry<String, List<String>> entry : groupMap.entrySet()) {
String group = entry.getKey();
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Docket.class, this::baseDocket);
BeanDefinition beanDefinition = builder.getRawBeanDefinition();
registry.registerBeanDefinition(group + "Api", beanDefinition);
}
}
private void groupBuild() {
Class clazz = SwaggerTagConst.class;
Class[] innerClazz = clazz.getDeclaredClasses();
for (Class cls : innerClazz) {
String group = cls.getSimpleName();
List<String> apiTags = Lists.newArrayList();
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
boolean isFinal = Modifier.isFinal(field.getModifiers());
if (isFinal) {
try {
apiTags.add(field.get(null).toString());
} catch (Exception e) {
log.error("", e);
}
}
}
groupList.add(group);
groupMap.put(group, apiTags);
}
}
private Docket baseDocket() {
// 配置全局参数 token
ParameterBuilder tokenPar = new ParameterBuilder();
Parameter parameter = tokenPar.name(SmartAuthenticationInterceptor.TOKEN_NAME)
.description("token")
.modelRef(new ModelRef("string"))
.parameterType("header")
.defaultValue("")
.required(false)
.build();
// 请求类型过滤规则
Predicate<RequestHandler> controllerPredicate = getControllerPredicate();
// controller 包路径
Predicate<RequestHandler> controllerPackage = RequestHandlerSelectors.basePackage(packAge);
return new Docket(DocumentationType.SWAGGER_2)
.groupName(groupName)
.forCodeGeneration(true)
.select()
.apis(controllerPackage)
.apis(controllerPredicate)
.paths(PathSelectors.any())
.build()
.apiInfo(this.serviceApiInfo())
.securitySchemes(securitySchemes())
.securityContexts(securityContexts())
.globalOperationParameters(Lists.newArrayList(parameter));
}
private List<ApiKey> securitySchemes() {
List<ApiKey> apiKeyList = new ArrayList<>();
apiKeyList.add(new ApiKey("x-access-token", "x-access-token", "header"));
return apiKeyList;
}
private List<SecurityContext> securityContexts() {
List<SecurityContext> securityContexts = new ArrayList<>();
securityContexts.add(
SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.any())
.build());
return securityContexts;
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
List<SecurityReference> securityReferences = new ArrayList<>();
securityReferences.add(new SecurityReference("x-access-token", authorizationScopes));
return securityReferences;
}
private Predicate<RequestHandler> getControllerPredicate() {
groupName = groupList.get(groupIndex);
List<String> apiTags = groupMap.get(groupName);
Predicate<RequestHandler> methodPredicate = (input) -> {
Api api = null;
Optional<Api> apiOptional = input.findControllerAnnotation(Api.class);
if (apiOptional.isPresent()) {
api = apiOptional.get();
}
List<String> tags = Arrays.asList(api.tags());
if (api != null && apiTags.containsAll(tags)) {
return true;
}
return false;
};
groupIndex++;
return Predicates.or(
Predicates.and(RequestHandlerSelectors.withClassAnnotation(RestController.class), methodPredicate),
Predicates.and(
RequestHandlerSelectors.withMethodAnnotation(ResponseBody.class), methodPredicate)
);
}
private ApiInfo serviceApiInfo() {
return new ApiInfoBuilder()
.title(title)
.description(description)
.version(version)
.license("Apache License Version 2.0")
.contact(new Contact("1024创新实验室", "http://www.1024lab.net", ""))
.termsOfServiceUrl(serviceUrl)
.build();
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}

View File

@@ -0,0 +1,25 @@
package net.lab1024.smartadmin.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* [ WebSocketConfig ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/7/10 0010 下午 16:07
* @since JDK1.8
*/
@Configuration
public class SmartWebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

View File

@@ -0,0 +1,22 @@
package net.lab1024.smartadmin.config;
import net.lab1024.smartadmin.constant.SystemEnvironmentEnum;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* 是否是正式环境
*
* @author listen
* @date 2019/08/27 08:56
*/
public class SystemEnvironmentCondition implements Condition {
@Value("${spring.profiles.active}")
private String systemEnvironment;
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return ! SystemEnvironmentEnum.PROD.equalsValue(systemEnvironment);
}
}

View File

@@ -0,0 +1,51 @@
package net.lab1024.smartadmin.constant;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.collections4.CollectionUtils;
import java.util.Set;
/**
*
* [ 通用常量 ]
*
* @version 1.0
* @since JDK1.8
* @author yandanyang
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
*/
public class CommonConst {
public static final class Page {
public static final Integer SIZE = 10;
}
public static final class Password {
public static final String DEFAULT = "123456";
public static final String SALT_FORMAT = "smart_%s_admin";
}
public static final String IGNORE_H5_URL_MAPPING = "/h5/api";
public static final class CommonCollection {
public static final Set<String> IGNORE_URL = ImmutableSet.of("/swagger", "Excel");
public static final Set<String> IGNORE_URL_MAPPING = ImmutableSet.of(IGNORE_H5_URL_MAPPING);
public static Boolean contain(Set<String> ignores, String uri) {
if (CollectionUtils.isEmpty(ignores)) {
return false;
}
for (String ignoreUrl : ignores) {
if (uri.startsWith(ignoreUrl)) {
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,16 @@
package net.lab1024.smartadmin.constant;
/**
* smart initDefines 项 常量
*
* @author listen
* @date 2018/02/10 14:29
*/
public class SmartReloadTagConst {
/**
* 系统环境设置 DEMO
*/
public static final String SYSTEM_CONFIG = "system_config";
}

View File

@@ -0,0 +1,69 @@
package net.lab1024.smartadmin.constant;
/**
* []
*
* @author yandanyang
* @version 1.0
* @since JDK1.8
*/
public class SwaggerTagConst {
public static class Admin {
public static final String MANAGER_SYSTEM_CONFIG = "管理端-系统配置";
public static final String MANAGER_USER = "管理端-用户";
public static final String MANAGER_USER_LOGIN = "管理端-用户登录";
public static final String MANAGER_DEPARTMENT = "管理端-部门";
public static final String MANAGER_ROLE = "管理端-角色";
public static final String MANAGER_ROLE_USER = "管理端-角色用户";
public static final String MANAGER_ROLE_PRIVILEGE = "管理端-角色权限";
public static final String MANAGER_SMART_RELOAD = "管理端-smart reload";
public static final String MANAGER_ORDER_OPERATE_LOG = "管理端-单据操作日志";
public static final String MANAGER_TASK_SCHEDULER = "管理端-任务调度";
public static final String MANAGER_USER_LOGIN_LOG = "管理端-用户登录日志";
public static final String MANAGER_USER_OPERATE_LOG = "管理端-用户操作日志";
public static final String MANAGER_DATA_SCOPE = "管理端-数据范围";
public static final String MANAGER_JOB = "管理端-岗位";
public static final String MANAGER_NOTICE = "管理端-系统通知";
public static final String MANAGER_FILE = "通用-文件服务";
public static final String MANAGER_PRIVILEGE = "通用-权限";
public static final String MANAGER_EMAIL = "通用-邮件发送";
public static final String MANAGER_HEART_BEAT = "通用-心跳服务";
}
/**
* 自定义分组2
*/
public static class Group2 {
}
/**
* 自定义分组2
*/
public static class Group3 {
}
}

View File

@@ -0,0 +1,67 @@
package net.lab1024.smartadmin.constant;
import net.lab1024.smartadmin.common.domain.BaseEnum;
/**
* 系统环境枚举类
*
* @author listen
* @date 2019年4月11日 17:34:59
*/
public enum SystemEnvironmentEnum implements BaseEnum {
/**
* dev
*/
DEV("dev", "开发环境"),
/**
* sit
*/
SIT("sit", "测试环境"),
/**
* pre
*/
PRE("pre", "预发布环境"),
/**
* prod
*/
PROD("prod", "生产环境");
public static final String DEV_ENV = "dev";
private String value;
private String desc;
SystemEnvironmentEnum(String value, String desc) {
this.value = value;
this.desc = desc;
}
/**
* 获取定义枚举value值
*
* @return Integer
*/
@Override
public String getValue() {
return value;
}
/**
* 获取枚举类的说明
*
* @return String
*/
@Override
public String getDesc() {
return desc;
}
}

View File

@@ -0,0 +1,73 @@
package net.lab1024.smartadmin.handler;
import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
import net.lab1024.smartadmin.common.domain.ResponseDTO;
import net.lab1024.smartadmin.common.exception.SmartBusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.stream.Collectors;
/**
* [ 全局异常拦截 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
@Slf4j
@ControllerAdvice
public class SmartGlobalExceptionHandler {
/**
* 添加全局异常处理流程
*
* @param e
* @return
* @throws Exception
*/
@ResponseBody
@ExceptionHandler(Exception.class)
public ResponseDTO exceptionHandler(Exception e) {
log.error("error:", e);
// http 请求方式错误
if (e instanceof HttpRequestMethodNotSupportedException) {
return ResponseDTO.wrap(ResponseCodeConst.REQUEST_METHOD_ERROR);
}
// 参数类型错误
if (e instanceof TypeMismatchException) {
return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM);
}
// json 格式错误
if (e instanceof HttpMessageNotReadableException) {
return ResponseDTO.wrap(ResponseCodeConst.JSON_FORMAT_ERROR);
}
// 参数校验未通过
if (e instanceof MethodArgumentNotValidException) {
List<FieldError> fieldErrors = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();
List<String> msgList = fieldErrors.stream().map(FieldError :: getDefaultMessage).collect(Collectors.toList());
return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM, String.join(",", msgList));
}
if (e instanceof SmartBusinessException) {
return ResponseDTO.wrap(ResponseCodeConst.SYSTEM_ERROR);
}
return ResponseDTO.wrap(ResponseCodeConst.SYSTEM_ERROR);
}
}

View File

@@ -0,0 +1,167 @@
package net.lab1024.smartadmin.handler;
import com.alibaba.fastjson.JSON;
import net.lab1024.smartadmin.common.anno.OperateLog;
import net.lab1024.smartadmin.common.constant.JudgeEnum;
import net.lab1024.smartadmin.module.business.log.LogService;
import net.lab1024.smartadmin.module.business.log.useroperatelog.domain.UserOperateLogEntity;
import net.lab1024.smartadmin.module.system.login.domain.RequestTokenBO;
import net.lab1024.smartadmin.util.SmartRequestTokenUtil;
import net.lab1024.smartadmin.util.SmartStringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
/**
* [ 操作日志记录处理,对所有OperateLog注解的Controller进行操作日志监控 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
@Slf4j
@Aspect
@Component
public class SmartOperateLogAspect {
@Autowired
private LogService logService;
@Pointcut("execution(* net.lab1024.smartadmin.module..*Controller.*(..)))")
public void logPointCut() {
}
@AfterReturning(pointcut = "logPointCut()")
public void doAfterReturning(JoinPoint joinPoint) {
handleLog(joinPoint, null);
}
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
handleLog(joinPoint, e);
}
protected void handleLog(final JoinPoint joinPoint, final Exception e) {
try {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
OperateLog operateLog = this.getAnnotationLog(joinPoint);
if (operateLog == null) {
return;
}
RequestTokenBO requestToken = SmartRequestTokenUtil.getRequestUser();
if (requestToken == null) {
return;
}
// 设置方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
String operateMethod = className + "." + methodName;
Object[] args = joinPoint.getArgs();
StringBuilder sb = new StringBuilder();
for (Object obj : args) {
sb.append(obj.getClass().getSimpleName());
sb.append("[");
sb.append(JSON.toJSONString(obj));
sb.append("]");
}
String params = sb.toString();
String failReason = null;
Integer result = JudgeEnum.YES.getValue();
if (e != null) {
result = JudgeEnum.NO.getValue();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
e.printStackTrace(pw);
failReason = sw.toString();
pw.flush();
pw.close();
sw.flush();
sw.close();
}
UserOperateLogEntity operateLogEntity =
UserOperateLogEntity.builder().userId(requestToken.getRequestUserId()).userName(requestToken.getEmployeeBO().getActualName()).url(request.getRequestURI()).method(operateMethod).param(params).failReason(failReason).result(result).build();
ApiOperation apiOperation = this.getApiOperation(joinPoint);
if (apiOperation != null) {
operateLogEntity.setContent(apiOperation.value());
}
Api api = this.getApi(joinPoint);
if (api != null) {
String[] tags = api.tags();
operateLogEntity.setModule(SmartStringUtil.join(tags, ","));
}
logService.addLog(operateLogEntity);
} catch (Exception exp) {
log.error("保存操作日志异常:{}", exp.getMessage());
exp.printStackTrace();
}
}
private OperateLog getAnnotationLog(JoinPoint joinPoint) throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
OperateLog classAnnotation = AnnotationUtils.findAnnotation(method.getDeclaringClass(), OperateLog.class);
if (method != null) {
return classAnnotation;
}
return null;
}
/**
* swagger API
*
* @param joinPoint
* @return
* @throws Exception
*/
private Api getApi(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
Api classAnnotation = AnnotationUtils.findAnnotation(method.getDeclaringClass(), Api.class);
if (method != null) {
return classAnnotation;
}
return null;
}
/**
* swagger ApiOperation
*
* @param joinPoint
* @return
* @throws Exception
*/
private ApiOperation getApiOperation(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
return method.getAnnotation(ApiOperation.class);
}
return null;
}
}

View File

@@ -0,0 +1,158 @@
package net.lab1024.smartadmin.interceptor;
import com.alibaba.fastjson.JSONObject;
import net.lab1024.smartadmin.common.anno.NoNeedLogin;
import net.lab1024.smartadmin.common.anno.NoValidPrivilege;
import net.lab1024.smartadmin.common.domain.ResponseDTO;
import net.lab1024.smartadmin.constant.CommonConst;
import net.lab1024.smartadmin.module.system.login.LoginResponseCodeConst;
import net.lab1024.smartadmin.module.system.login.LoginTokenService;
import net.lab1024.smartadmin.module.system.login.domain.RequestTokenBO;
import net.lab1024.smartadmin.module.system.privilege.service.PrivilegeEmployeeService;
import net.lab1024.smartadmin.util.SmartRequestTokenUtil;
import net.lab1024.smartadmin.util.SmartStringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
/**
* [ 登录拦截器 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
@Component
public class SmartAuthenticationInterceptor extends HandlerInterceptorAdapter {
public static final String TOKEN_NAME = "x-access-token";
@Value("${access-control-allow-origin}")
private String accessControlAllowOrigin;
@Autowired
private LoginTokenService loginTokenService;
@Autowired
private PrivilegeEmployeeService privilegeEmployeeService;
/**
* 拦截服务器端响应处理ajax请求返回结果
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//跨域设置
this.crossDomainConfig(response);
boolean isHandlerMethod = handler instanceof HandlerMethod;
if (! isHandlerMethod) {
return true;
}
//不需要登录的注解
Boolean isNoNeedLogin = ((HandlerMethod) handler).getMethodAnnotation(NoNeedLogin.class) != null;
if (isNoNeedLogin) {
return true;
}
//放行的Uri前缀
String uri = request.getRequestURI();
String contextPath = request.getContextPath();
String target = uri.replaceFirst(contextPath, "");
if (CommonConst.CommonCollection.contain(CommonConst.CommonCollection.IGNORE_URL, target)) {
return true;
}
//需要做token校验, 消息头的token优先于请求query参数的token
String xHeaderToken = request.getHeader(TOKEN_NAME);
String xRequestToken = request.getParameter(TOKEN_NAME);
String xAccessToken = null != xHeaderToken ? xHeaderToken : xRequestToken;
if (null == xAccessToken) {
this.outputResult(response, LoginResponseCodeConst.LOGIN_ERROR);
return false;
}
//根据token获取登录用户
RequestTokenBO requestToken = loginTokenService.getEmployeeTokenInfo(xAccessToken);
if (null == requestToken) {
this.outputResult(response, LoginResponseCodeConst.LOGIN_ERROR);
return false;
}
//判断接口权限
String methodName = ((HandlerMethod) handler).getMethod().getName();
String className = ((HandlerMethod) handler).getBeanType().getName();
List<String> list = SmartStringUtil.splitConvertToList(className, "\\.");
String controllerName = list.get(list.size() - 1);
Method m = ((HandlerMethod) handler).getMethod();
Class<?> cls = ((HandlerMethod) handler).getBeanType();
boolean isClzAnnotation = cls.isAnnotationPresent(NoValidPrivilege.class);
boolean isMethodAnnotation = m.isAnnotationPresent(NoValidPrivilege.class);
NoValidPrivilege noValidPrivilege = null;
if (isClzAnnotation) {
noValidPrivilege = cls.getAnnotation(NoValidPrivilege.class);
} else if (isMethodAnnotation) {
noValidPrivilege = m.getAnnotation(NoValidPrivilege.class);
}
//不需验证权限
if (noValidPrivilege != null) {
SmartRequestTokenUtil.setUser(request, requestToken);
return true;
}
//需要验证权限
Boolean privilegeValidPass = privilegeEmployeeService.checkEmployeeHavePrivilege(requestToken, controllerName, methodName);
if (! privilegeValidPass) {
this.outputResult(response, LoginResponseCodeConst.NOT_HAVE_PRIVILEGES);
return false;
}
SmartRequestTokenUtil.setUser(request, requestToken);
return true;
}
/**
* 配置跨域
*
* @param response
*/
private void crossDomainConfig(HttpServletResponse response) {
response.setHeader("Access-Control-Allow-Origin", accessControlAllowOrigin);
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
response.setHeader("Access-Control-Expose-Headers", "*");
response.setHeader("Access-Control-Allow-Headers", "Authentication,Origin, X-Requested-With, Content-Type, " + "Accept, x-access-token");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires ", "-1");
}
/**
* 错误输出
*
* @param response
* @param responseCodeConst
* @throws IOException
*/
private void outputResult(HttpServletResponse response, LoginResponseCodeConst responseCodeConst) throws IOException {
ResponseDTO<Object> wrap = ResponseDTO.wrap(responseCodeConst);
String msg = JSONObject.toJSONString(wrap);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(msg);
response.flushBuffer();
}
}

View File

@@ -0,0 +1,22 @@
package net.lab1024.smartadmin.listener;
import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
/**
* 应用启动以后检测code码
*
* @author zhuo
* @version 1.0
* @since JDK1.8
*/
@Component
public class SmartAdminStartupRunner implements CommandLineRunner {
@Override
public void run(String... args) {
ResponseCodeConst.init();
}
}

View File

@@ -0,0 +1,81 @@
package net.lab1024.smartadmin.module.business.email;
import net.lab1024.smartadmin.common.anno.NoValidPrivilege;
import net.lab1024.smartadmin.common.anno.OperateLog;
import net.lab1024.smartadmin.common.domain.PageResultDTO;
import net.lab1024.smartadmin.constant.SwaggerTagConst;
import net.lab1024.smartadmin.common.domain.ResponseDTO;
import net.lab1024.smartadmin.module.business.email.domain.dto.EmailDTO;
import net.lab1024.smartadmin.module.business.email.domain.dto.EmailQueryDTO;
import net.lab1024.smartadmin.module.business.email.domain.dto.EmailVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date 2019-05-13 17:10:16
* @since JDK1.8
*/
@RestController
@OperateLog
@Api(tags = {SwaggerTagConst.Admin.MANAGER_EMAIL})
public class EmailController {
@Autowired
private EmailService emailService;
@ApiOperation(value = "分页查询",notes = "@author yandanyang")
@PostMapping("/email/page/query")
@NoValidPrivilege
public ResponseDTO<PageResultDTO<EmailVO>> queryByPage(@RequestBody @Validated EmailQueryDTO queryDTO) {
return emailService.queryByPage(queryDTO);
}
@ApiOperation(value = "添加",notes = "@author yandanyang")
@PostMapping("/email/add")
@NoValidPrivilege
public ResponseDTO<Long> add(@RequestBody @Valid EmailDTO addTO){
return emailService.add(addTO);
}
@ApiOperation(value="修改",notes = "@author yandanyang")
@PostMapping("/email/update")
@NoValidPrivilege
public ResponseDTO<Long> update(@RequestBody @Valid EmailDTO updateDTO){
return emailService.update(updateDTO);
}
@ApiOperation(value="删除",notes = "@author yandanyang")
@GetMapping("/email/delete/{id}")
@NoValidPrivilege
public ResponseDTO<String> delete(@PathVariable("id") Long id){
return emailService.delete(id);
}
@ApiOperation(value="详情",notes = "@author yandanyang")
@GetMapping("/email/detail/{id}")
@NoValidPrivilege
public ResponseDTO<EmailVO> detail(@PathVariable("id") Long id){
return emailService.detail(id);
}
@ApiOperation(value="发送",notes = "@author yandanyang")
@GetMapping("/email/send/{id}")
@NoValidPrivilege
public ResponseDTO<String> send(@PathVariable("id") Long id){
return emailService.send(id);
}
}

View File

@@ -0,0 +1,47 @@
package net.lab1024.smartadmin.module.business.email;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.lab1024.smartadmin.module.business.email.domain.dto.EmailQueryDTO;
import net.lab1024.smartadmin.module.business.email.domain.entity.EmailEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019-05-13 17:10:16
* @since JDK1.8
*/
@Mapper
@Component
public interface EmailDao extends BaseMapper<EmailEntity> {
/**
* 分页查询
* @param queryDTO
* @return EmailEntity
*/
List<EmailEntity> queryByPage(Page page, @Param("queryDTO") EmailQueryDTO queryDTO);
/**
* 根据id删除
* @param id
* @return
*/
void deleteById(@Param("id") Long id);
/**
* 批量删除
* @param idList
* @return
*/
void deleteByIds(@Param("idList") List<Long> idList);
}

View File

@@ -0,0 +1,37 @@
package net.lab1024.smartadmin.module.business.email;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/4/28 0028 下午 15:37
* @since JDK1.8
*/
public enum EmailSendStatusEnum {
NOT_SEND(0,"未发送"),
SEND(1,"已发送");
private Integer type;
private String desc;
EmailSendStatusEnum(Integer type, String desc) {
this.type = type;
this.desc = desc;
}
public Integer getType() {
return type;
}
public String getDesc() {
return desc;
}
}

View File

@@ -0,0 +1,122 @@
package net.lab1024.smartadmin.module.business.email;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
import net.lab1024.smartadmin.common.domain.PageResultDTO;
import net.lab1024.smartadmin.common.domain.ResponseDTO;
import net.lab1024.smartadmin.module.business.email.domain.dto.EmailConfigDTO;
import net.lab1024.smartadmin.module.business.email.domain.dto.EmailDTO;
import net.lab1024.smartadmin.module.business.email.domain.dto.EmailQueryDTO;
import net.lab1024.smartadmin.module.business.email.domain.dto.EmailVO;
import net.lab1024.smartadmin.module.business.email.domain.entity.EmailEntity;
import net.lab1024.smartadmin.module.system.systemconfig.SystemConfigService;
import net.lab1024.smartadmin.module.system.systemconfig.constant.SystemConfigEnum;
import net.lab1024.smartadmin.util.SmartBeanUtil;
import net.lab1024.smartadmin.util.SmartPageUtil;
import net.lab1024.smartadmin.util.SmartSendMailUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date 2019-05-13 17:10:16
* @since JDK1.8
*/
@Service
public class EmailService {
@Autowired
private EmailDao emailDao;
@Autowired
private SystemConfigService systemConfigService;
/**
* @author yandanyang
* @description 分页查询
* @date 2019-05-13 17:10:16
*/
public ResponseDTO<PageResultDTO<EmailVO>> queryByPage(EmailQueryDTO queryDTO) {
Page page = SmartPageUtil.convert2QueryPage(queryDTO);
List<EmailEntity> entities = emailDao.queryByPage(page, queryDTO);
List<EmailVO> dtoList = SmartBeanUtil.copyList(entities, EmailVO.class);
page.setRecords(dtoList);
PageResultDTO<EmailVO> pageResultDTO = SmartPageUtil.convert2PageResult(page);
return ResponseDTO.succData(pageResultDTO);
}
/**
* @author yandanyang
* @description 添加
* @date 2019-05-13 17:10:16
*/
public ResponseDTO<Long> add(EmailDTO addDTO) {
EmailEntity entity = SmartBeanUtil.copy(addDTO, EmailEntity.class);
emailDao.insert(entity);
return ResponseDTO.succData(entity.getId());
}
/**
* @author yandanyang
* @description 编辑
* @date 2019-05-13 17:10:16
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<Long> update(EmailDTO updateDTO) {
EmailEntity entity = SmartBeanUtil.copy(updateDTO, EmailEntity.class);
emailDao.updateById(entity);
return ResponseDTO.succData(entity.getId());
}
/**
* @author yandanyang
* @description 删除
* @date 2019-05-13 17:10:16
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> delete(Long id) {
emailDao.deleteById(id);
return ResponseDTO.succ();
}
/**
* @author yandanyang
* @description 根据ID查询
* @date 2019-05-13 17:10:16
*/
public ResponseDTO<EmailVO> detail(Long id) {
EmailEntity entity = emailDao.selectById(id);
EmailVO dto = SmartBeanUtil.copy(entity, EmailVO.class);
return ResponseDTO.succData(dto);
}
/**
* 发送某个已创建的邮件
*
* @param id
* @return
*/
public ResponseDTO<String> send(Long id) {
EmailEntity entity = emailDao.selectById(id);
EmailConfigDTO emailConfig = systemConfigService.selectByKey2Obj(SystemConfigEnum.Key.EMAIL_CONFIG.name(), EmailConfigDTO.class);
String toEmails = entity.getToEmails();
if (StringUtils.isEmpty(toEmails)) {
return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM, "收件人信息为空");
}
String[] emails = toEmails.split(";");
SmartSendMailUtil.sendMail(emailConfig.getUsername(), emailConfig.getPassword(), emailConfig.getUsername(), emails, "", emailConfig.getSmtpHost(), entity.getTitle(), entity.getContent());
entity.setSendStatus(EmailSendStatusEnum.SEND.getType());
emailDao.updateById(entity);
return ResponseDTO.succ();
}
}

View File

@@ -0,0 +1,30 @@
package net.lab1024.smartadmin.module.business.email.domain.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/5/13 0013 下午 16:52
* @since JDK1.8
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EmailConfigDTO {
private String smtpHost;
private String username;
private String password;
}

View File

@@ -0,0 +1,44 @@
package net.lab1024.smartadmin.module.business.email.domain.dto;
import lombok.Data;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/3/27 0027 下午 12:27
* @since JDK1.8
*/
@Data
public class EmailDTO {
@ApiModelProperty("主键")
private Long id;
@ApiModelProperty("标题")
private String title;
@ApiModelProperty("收件人")
private String toEmails;
@ApiModelProperty("发送状态 0未发送 1已发送")
private Integer sendStatus;
@ApiModelProperty("邮件内容")
private String content;
@ApiModelProperty("创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@ApiModelProperty("更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

View File

@@ -0,0 +1,35 @@
package net.lab1024.smartadmin.module.business.email.domain.dto;
import net.lab1024.smartadmin.common.domain.PageParamDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date 2019-05-13 17:10:16
* @since JDK1.8
*/
@Data
public class EmailQueryDTO extends PageParamDTO {
@ApiModelProperty("开始日期")
private String startDate;
@ApiModelProperty("结束日期")
private String endDate;
@ApiModelProperty("标题")
private String title;
@ApiModelProperty("发送状态 0未发送 1已发送")
private Integer sendStatus;
}

View File

@@ -0,0 +1,45 @@
package net.lab1024.smartadmin.module.business.email.domain.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/3/27 0027 下午 12:27
* @since JDK1.8
*/
@Data
public class EmailVO {
@ApiModelProperty("主键")
private Long id;
@ApiModelProperty("标题")
private String title;
@ApiModelProperty("收件人")
private String toEmails;
@ApiModelProperty("发送状态 0未发送 1已发送")
private Integer sendStatus;
@ApiModelProperty("邮件内容")
private String content;
@ApiModelProperty("创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@ApiModelProperty("更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
}

View File

@@ -0,0 +1,40 @@
package net.lab1024.smartadmin.module.business.email.domain.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import net.lab1024.smartadmin.common.domain.BaseEntity;
import lombok.Data;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019-05-13 17:10:16
* @since JDK1.8
*/
@Data
@TableName("t_email")
public class EmailEntity extends BaseEntity {
/**
* 标题
*/
private String title;
/**
* 收件人
*/
private String toEmails;
/**
* 发送状态 0未发送 1已发送
*/
private Integer sendStatus;
/**
* 邮件内容
*/
private String content;
}

View File

@@ -0,0 +1,75 @@
package net.lab1024.smartadmin.module.business.log;
import net.lab1024.smartadmin.module.business.log.orderoperatelog.OrderOperateLogDao;
import net.lab1024.smartadmin.module.business.log.orderoperatelog.domain.entity.OrderOperateLogEntity;
import net.lab1024.smartadmin.module.business.log.userloginlog.UserLoginLogDao;
import net.lab1024.smartadmin.module.business.log.userloginlog.domain.UserLoginLogEntity;
import net.lab1024.smartadmin.module.business.log.useroperatelog.UserOperateLogDao;
import net.lab1024.smartadmin.module.business.log.useroperatelog.domain.UserOperateLogEntity;
import net.lab1024.smartadmin.util.SmartThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* [ ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/4/4 0004 下午 16:19
* @since JDK1.8
*/
@Slf4j
@Service
public class LogService {
private ThreadPoolExecutor threadPoolExecutor;
@Autowired
private UserLoginLogDao userLoginLogDao;
@Autowired
private OrderOperateLogDao orderOperateLogDao;
@Autowired
private UserOperateLogDao userOperateLogDao;
@PostConstruct
void init() {
if (threadPoolExecutor == null) {
threadPoolExecutor = new ThreadPoolExecutor(1, 1, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2000), SmartThreadFactory.create("LogAspect"));
}
}
@PreDestroy
void destroy() {
if (threadPoolExecutor != null) {
threadPoolExecutor.shutdown();
threadPoolExecutor = null;
}
}
public void addLog(Object object) {
try {
if (object instanceof UserLoginLogEntity) {
threadPoolExecutor.execute(() -> userLoginLogDao.insert((UserLoginLogEntity) object));
}
if (object instanceof OrderOperateLogEntity) {
threadPoolExecutor.execute(() -> orderOperateLogDao.insert((OrderOperateLogEntity) object));
}
if (object instanceof UserOperateLogEntity) {
threadPoolExecutor.execute(() -> userOperateLogDao.insert((UserOperateLogEntity) object));
}
} catch (Throwable e) {
log.error("userLogAfterAdvice:{}", e);
}
}
}

View File

@@ -0,0 +1,44 @@
package net.lab1024.smartadmin.module.business.log.orderoperatelog;
import net.lab1024.smartadmin.common.anno.OperateLog;
import net.lab1024.smartadmin.common.domain.ResponseDTO;
import net.lab1024.smartadmin.constant.SwaggerTagConst;
import net.lab1024.smartadmin.module.business.log.orderoperatelog.constant.OrderOperateLogOrderTypeEnum;
import net.lab1024.smartadmin.module.business.log.orderoperatelog.domain.vo.OrderOperateLogVO;
import net.lab1024.smartadmin.util.SmartStringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.stream.Collectors;
/**
* 单据操作记录Controller
*
* @author lidoudou
* @date: 2018/1/31 16:56
*/
@Api(tags = {SwaggerTagConst.Admin.MANAGER_ORDER_OPERATE_LOG})
@OperateLog
@RestController
public class OrderOperateLogController {
@Autowired
private OrderOperateLogService orderOperateLogService;
@ApiOperation(value = "查询单据操作日志", notes = "查询单据操作日志")
@GetMapping("/orderOperateLog/list/{orderId}")
@ApiImplicitParams({@ApiImplicitParam(name = "orderId", value = "业务id", paramType = "path"), @ApiImplicitParam(name = "orderType", value = "业务类型" + OrderOperateLogOrderTypeEnum.INFO, paramType
= "query")})
public ResponseDTO<List<OrderOperateLogVO>> list(@PathVariable Long orderId, String orderType) {
List<Integer> orderTypeList = SmartStringUtil.splitConverToIntSet(orderType, ",").stream().collect(Collectors.toList());
return orderOperateLogService.listOrderOperateLogsByOrderTypeAndOrderId(orderId, orderTypeList);
}
}

View File

@@ -0,0 +1,30 @@
package net.lab1024.smartadmin.module.business.log.orderoperatelog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.lab1024.smartadmin.module.business.log.orderoperatelog.domain.entity.OrderOperateLogEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* <p>
* 各种单据操作记录
* Mapper 接口
* </p>
*
* @author anders
* @since 2018-01-09
*/
@Mapper
@Component
public interface OrderOperateLogDao extends BaseMapper<OrderOperateLogEntity> {
List<OrderOperateLogEntity> listOrderOperateLogsByOrderTypeAndOrderId(@Param("orderId") Long orderId, @Param("orderTypeList") List<Integer> orderTypeList);
List<OrderOperateLogEntity> listOrderOperateLogsByOrderTypeAndOrderIds(@Param("orderIds") List<Long> orderIds, @Param("orderTypeList") List<Integer> orderTypeList);
void batchInsert(List<OrderOperateLogEntity> list);
}

View File

@@ -0,0 +1,64 @@
package net.lab1024.smartadmin.module.business.log.orderoperatelog;
import net.lab1024.smartadmin.common.domain.ResponseDTO;
import net.lab1024.smartadmin.module.business.log.orderoperatelog.domain.dto.OrderOperateLogSaveDTO;
import net.lab1024.smartadmin.module.business.log.orderoperatelog.domain.entity.OrderOperateLogEntity;
import net.lab1024.smartadmin.module.business.log.orderoperatelog.domain.vo.OrderOperateLogVO;
import net.lab1024.smartadmin.util.SmartBeanUtil;
import net.lab1024.smartadmin.util.SmartStringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 各种单据操作记录
* 服务实现类
* </p>
*
* @author anders
* @since 2018-01-09
*/
@Service
public class OrderOperateLogService {
@Autowired
private OrderOperateLogDao orderOperateLogDao;
public void batchSaveOrderOperateLog(List<OrderOperateLogSaveDTO> orderOperateLogSaveDTOList) {
List<OrderOperateLogEntity> entityList = new ArrayList<>();
orderOperateLogSaveDTOList.forEach(e -> {
OrderOperateLogEntity orderOperateLogEntity = SmartBeanUtil.copy(e, OrderOperateLogEntity.class);
orderOperateLogEntity.setOperateType(e.getOperateType().getCode());
if (SmartStringUtil.isNotBlank(e.getOperateContent())) {
orderOperateLogEntity.setOperateContent(e.getOperateContent());
} else {
orderOperateLogEntity.setOperateContent(e.getOperateType().getMsg());
}
orderOperateLogEntity.setOperateRemark(e.getOperateRemark());
orderOperateLogEntity.setExtData(e.getExtData());
orderOperateLogEntity.setCreateTime(new Date());
orderOperateLogEntity.setOrderType(e.getOrderType().getType());
entityList.add(orderOperateLogEntity);
});
//批量添加
orderOperateLogDao.batchInsert(entityList);
}
public ResponseDTO<List<OrderOperateLogVO>> listOrderOperateLogsByOrderTypeAndOrderId(Long orderId, List<Integer> orderTypeList) {
List<OrderOperateLogEntity> orderOperateLogEntities = orderOperateLogDao.listOrderOperateLogsByOrderTypeAndOrderId(orderId, orderTypeList);
List<OrderOperateLogVO> dtoList = orderOperateLogEntities.stream().map(e -> SmartBeanUtil.copy(e, OrderOperateLogVO.class)).collect(Collectors.toList());
return ResponseDTO.succData(dtoList);
}
public ResponseDTO<List<OrderOperateLogVO>> listOrderOperateLogsByOrderTypeAndOrderIds(List<Long> orderIds, List<Integer> orderTypeList) {
List<OrderOperateLogEntity> orderOperateLogEntities = orderOperateLogDao.listOrderOperateLogsByOrderTypeAndOrderIds(orderIds, orderTypeList);
List<OrderOperateLogVO> dtoList = orderOperateLogEntities.stream().map(e -> SmartBeanUtil.copy(e, OrderOperateLogVO.class)).collect(Collectors.toList());
return ResponseDTO.succData(dtoList);
}
}

View File

@@ -0,0 +1,37 @@
package net.lab1024.smartadmin.module.business.log.orderoperatelog.constant;
/**
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
public enum OrderOperateLogDefaultEmpEnum {
DEFAULT_EMP(0,"系统");
private Integer empId;
private String empName;
OrderOperateLogDefaultEmpEnum(Integer empId,String empName) {
this.empId = empId;
this.empName = empName;
}
public int getEmpId() {
return empId;
}
public String getEmpName() {
return empName;
}
}

View File

@@ -0,0 +1,30 @@
package net.lab1024.smartadmin.module.business.log.orderoperatelog.constant;
import net.lab1024.smartadmin.common.constant.ResponseCodeConst;
/**
* [ 8001 -8999 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
public class OrderOperateLogOperateTypeConst extends ResponseCodeConst {
public static final OrderOperateLogOperateTypeConst ADD = new OrderOperateLogOperateTypeConst(8001, "创建并提交");
public static final OrderOperateLogOperateTypeConst UPDATE = new OrderOperateLogOperateTypeConst(8002, "修改并提交");
public static final OrderOperateLogOperateTypeConst DELETE = new OrderOperateLogOperateTypeConst(8003, "删除");
private OrderOperateLogOperateTypeConst(int code, String msg) {
super(code, msg);
}
}

View File

@@ -0,0 +1,51 @@
package net.lab1024.smartadmin.module.business.log.orderoperatelog.constant;
import java.util.Arrays;
import java.util.Optional;
/**
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
public enum OrderOperateLogOrderTypeEnum {
EXAMPLE(1, "样例");
public static final String INFO = "";
private int type;
private String typeName;
OrderOperateLogOrderTypeEnum(int type, String typeName) {
this.type = type;
this.typeName = typeName;
}
public int getType() {
return type;
}
public String getTypeName() {
return typeName;
}
public static OrderOperateLogOrderTypeEnum getValueByName(String name) {
OrderOperateLogOrderTypeEnum[] values = OrderOperateLogOrderTypeEnum.values();
Optional<OrderOperateLogOrderTypeEnum> first = Arrays.stream(values).filter(e -> e.getTypeName().equals(name)).findFirst();
if (!first.isPresent()) {
return null;
}
if (!first.isPresent()) {
return null;
}
OrderOperateLogOrderTypeEnum orderType = first.get();
return orderType;
}
}

View File

@@ -0,0 +1,80 @@
package net.lab1024.smartadmin.module.business.log.orderoperatelog.domain.dto;
import net.lab1024.smartadmin.module.business.log.orderoperatelog.constant.OrderOperateLogOperateTypeConst;
import net.lab1024.smartadmin.module.business.log.orderoperatelog.constant.OrderOperateLogOrderTypeEnum;
import lombok.Data;
/**
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date
* @since JDK1.8
*/
@Data
public class OrderOperateLogSaveDTO {
/**
* 各种单据的id
*/
private Long orderId;
/**
* 单据类型
*/
private OrderOperateLogOrderTypeEnum orderType;
/**
* 操作类型
*/
private OrderOperateLogOperateTypeConst operateType;
/**
*操作类型 对应的中文
*/
private String operateContent;
/**
* 操作备注
*/
private String operateRemark;
/**
* 员工id
*/
private Long employeeId;
/**
* 员工名称
*/
private String employeeName;
/**
* 额外信息
*/
private String extData;
public OrderOperateLogSaveDTO() {
}
public OrderOperateLogSaveDTO(Long orderId, OrderOperateLogOrderTypeEnum orderType, OrderOperateLogOperateTypeConst operateType, String
operateRemark, Long employeeId, String employeeName, String extData) {
this.orderId = orderId;
this.orderType = orderType;
this.operateType = operateType;
this.operateRemark = operateRemark;
this.employeeId = employeeId;
this.employeeName = employeeName;
this.extData = extData;
}
@Override
public String toString() {
return "OrderOperateLogSaveDTO{" + "orderId=" + orderId + ", orderType=" + orderType + ", operateType=" + operateType + ", operateRemark='"
+ operateRemark + '\'' + ", employeeId=" + employeeId + ", employeeName='" + employeeName + '\'' + ", extData='" + extData + '\'' + '}';
}
}

View File

@@ -0,0 +1,44 @@
package net.lab1024.smartadmin.module.business.log.orderoperatelog.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 预存款申请/提取单流水临时文件
* @author zzr
*/
@Data
public class SupplierOrderOperateVO {
/**
* 流水类型
*/
private Integer tradingType;
/**
* 总重
*/
private BigDecimal totalWeight;
/**
* 金额
*/
private BigDecimal amount;
/**
* 操作人名称
*/
private String buyerName;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createTime;
}

View File

@@ -0,0 +1,58 @@
package net.lab1024.smartadmin.module.business.log.orderoperatelog.domain.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import net.lab1024.smartadmin.common.domain.BaseEntity;
import lombok.Builder;
import lombok.Data;
/**
* <p>
* 各种单据操作记录
*
* </p>
*
* @author anders
* @since 2018-01-09
*/
@Data
@Builder
@TableName("t_order_operate_log")
public class OrderOperateLogEntity extends BaseEntity {
/**
* 各种单据的id
*/
private Long orderId;
/**
* 单据类型
*/
private Integer orderType;
/**
* 操作类型
*/
private Integer operateType;
/**
* 操作类型 对应的中文
*/
private String operateContent;
/**
* 操作备注
*/
private String operateRemark;
/**
* 员工id
*/
private Long employeeId;
/**
* 员工名称
*/
private String employeeName;
/**
* 额外信息
*/
private String extData;
}

View File

@@ -0,0 +1,69 @@
package net.lab1024.smartadmin.module.business.log.orderoperatelog.domain.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* @author bhr
* @Description: 操作日志
* @date 2019/8/28 9:31
*/
@Data
public class OrderOperateLogVO {
private Long id;
/**
* 各种单据的id
*/
@ApiModelProperty("各种单据的id")
private Long orderId;
/**
* 单据类型
*/
@ApiModelProperty("单据类型")
private Integer orderType;
/**
* 操作类型
*/
@ApiModelProperty("操作类型")
private Integer operateType;
/**
* 操作类型 对应的中文
*/
@ApiModelProperty("操作类型 对应的中文")
private String operateContent;
/**
* 操作备注
*/
@ApiModelProperty("操作备注")
private String operateRemark;
@ApiModelProperty("操作备注,包含审批人名使用别名显示")
private String operateSecondRemark;
/**
* 员工id
*/
@ApiModelProperty("员工id")
private Long employeeId;
/**
* 员工名称
*/
@ApiModelProperty("员工名称")
private String employeeName;
/**
* 员工名称
*/
@ApiModelProperty("员工别名")
private String employeeSecondName;
/**
* 额外信息
*/
@ApiModelProperty("额外信息")
private String extData;
/**
* 创建时间
*/
@ApiModelProperty("创建时间")
private Date createTime;
}

View File

@@ -0,0 +1,54 @@
package net.lab1024.smartadmin.module.business.log.userloginlog;
import net.lab1024.smartadmin.common.anno.OperateLog;
import net.lab1024.smartadmin.common.domain.PageResultDTO;
import net.lab1024.smartadmin.common.domain.ResponseDTO;
import net.lab1024.smartadmin.constant.SwaggerTagConst;
import net.lab1024.smartadmin.module.system.employee.domain.dto.EmployeeQueryDTO;
import net.lab1024.smartadmin.module.system.employee.domain.vo.EmployeeVO;
import net.lab1024.smartadmin.module.business.log.userloginlog.domain.UserLoginLogDTO;
import net.lab1024.smartadmin.module.business.log.userloginlog.domain.UserLoginLogQueryDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/**
* [ 用户登录日志 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date 2019-05-15 10:25:21
* @since JDK1.8
*/
@RestController
@Api(tags = {SwaggerTagConst.Admin.MANAGER_USER_LOGIN_LOG})
@OperateLog
public class UserLoginLogController {
@Autowired
private UserLoginLogService userLoginLogService;
@ApiOperation(value = "分页查询用户登录日志", notes = "@author yandanyang")
@PostMapping("/userLoginLog/page/query")
public ResponseDTO<PageResultDTO<UserLoginLogDTO>> queryByPage(@RequestBody UserLoginLogQueryDTO queryDTO) {
return userLoginLogService.queryByPage(queryDTO);
}
@ApiOperation(value = "删除用户登录日志", notes = "@author yandanyang")
@GetMapping("/userLoginLog/delete/{id}")
public ResponseDTO<String> delete(@PathVariable("id") Long id) {
return userLoginLogService.delete(id);
}
@ApiOperation(value = "查询员工在线状态", notes = "@author zzr")
@PostMapping("/userOnLine/query")
public ResponseDTO<PageResultDTO<EmployeeVO>> queryUserOnLine(@RequestBody @Valid EmployeeQueryDTO queryDTO) {
return userLoginLogService.queryUserOnLine(queryDTO);
}
}

View File

@@ -0,0 +1,47 @@
package net.lab1024.smartadmin.module.business.log.userloginlog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.lab1024.smartadmin.module.business.log.userloginlog.domain.UserLoginLogQueryDTO;
import net.lab1024.smartadmin.module.business.log.userloginlog.domain.UserLoginLogEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* [ 用户登录日志 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019-05-15 10:25:21
* @since JDK1.8
*/
@Mapper
@Component
public interface UserLoginLogDao extends BaseMapper<UserLoginLogEntity> {
/**
* 分页查询
* @param queryDTO
* @return UserLoginLogEntity
*/
List<UserLoginLogEntity> queryByPage(Page page, @Param("queryDTO") UserLoginLogQueryDTO queryDTO);
/**
* 根据id删除
* @param id
* @return
*/
void deleteById(@Param("id") Long id);
/**
* 批量删除
* @param idList
* @return
*/
void deleteByIds(@Param("idList") List<Long> idList);
}

View File

@@ -0,0 +1,82 @@
package net.lab1024.smartadmin.module.business.log.userloginlog;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.lab1024.smartadmin.common.domain.PageResultDTO;
import net.lab1024.smartadmin.common.domain.ResponseDTO;
import net.lab1024.smartadmin.module.system.employee.EmployeeService;
import net.lab1024.smartadmin.module.system.employee.domain.dto.EmployeeQueryDTO;
import net.lab1024.smartadmin.module.system.employee.domain.vo.EmployeeVO;
import net.lab1024.smartadmin.module.business.log.userloginlog.domain.UserLoginLogDTO;
import net.lab1024.smartadmin.module.business.log.userloginlog.domain.UserLoginLogEntity;
import net.lab1024.smartadmin.module.business.log.userloginlog.domain.UserLoginLogQueryDTO;
import net.lab1024.smartadmin.module.support.websocket.WebSocketServer;
import net.lab1024.smartadmin.util.SmartBeanUtil;
import net.lab1024.smartadmin.util.SmartPageUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* [ 用户登录日志 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date 2019-05-15 10:25:21
* @since JDK1.8
*/
@Service
public class UserLoginLogService {
@Autowired
private UserLoginLogDao userLoginLogDao;
@Autowired
private EmployeeService employeeService;
/**
* @author yandanyang
* @description 分页查询
* @date 2019-05-15 10:25:21
*/
public ResponseDTO<PageResultDTO<UserLoginLogDTO>> queryByPage(UserLoginLogQueryDTO queryDTO) {
Page page = SmartPageUtil.convert2QueryPage(queryDTO);
List<UserLoginLogEntity> entities = userLoginLogDao.queryByPage(page, queryDTO);
List<UserLoginLogDTO> dtoList = SmartBeanUtil.copyList(entities, UserLoginLogDTO.class);
page.setRecords(dtoList);
PageResultDTO<UserLoginLogDTO> pageResultDTO = SmartPageUtil.convert2PageResult(page);
return ResponseDTO.succData(pageResultDTO);
}
/**
* @author yandanyang
* @description 删除
* @date 2019-05-15 10:25:21
*/
@Transactional(rollbackFor = Exception.class)
public ResponseDTO<String> delete(Long id) {
userLoginLogDao.deleteById(id);
return ResponseDTO.succ();
}
/**
* 查询员工在线状态
*
* @param queryDTO
* @return
*/
public ResponseDTO<PageResultDTO<EmployeeVO>> queryUserOnLine(EmployeeQueryDTO queryDTO) {
List<Long> onLineUserList = WebSocketServer.getOnLineUserList();
if (CollectionUtils.isEmpty(onLineUserList)) {
return ResponseDTO.succ();
}
queryDTO.setEmployeeIds(onLineUserList);
ResponseDTO<PageResultDTO<EmployeeVO>> employeeList = employeeService.selectEmployeeList(queryDTO);
return employeeList;
}
}

View File

@@ -0,0 +1,53 @@
package net.lab1024.smartadmin.module.business.log.userloginlog.domain;
import lombok.Data;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
/**
* [ 用户登录日志 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019/3/27 0027 下午 12:27
* @since JDK1.8
*/
@Data
public class UserLoginLogDTO {
@ApiModelProperty("主键")
private Long id;
@ApiModelProperty("员工id")
private Long userId;
@ApiModelProperty("用户名")
private String userName;
@ApiModelProperty("用户ip")
private String remoteIp;
@ApiModelProperty("用户端口")
private Integer remotePort;
@ApiModelProperty("浏览器")
private String remoteBrowser;
@ApiModelProperty("操作系统")
private String remoteOs;
@ApiModelProperty("登录状态")
private Integer loginStatus;
@ApiModelProperty("更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
@ApiModelProperty("创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
}

View File

@@ -0,0 +1,60 @@
package net.lab1024.smartadmin.module.business.log.userloginlog.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import net.lab1024.smartadmin.common.domain.BaseEntity;
import lombok.*;
/**
* [ 用户登录日志]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
* @date 2019-05-15 10:25:21
* @since JDK1.8
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("t_user_login_log")
public class UserLoginLogEntity extends BaseEntity {
/**
* 员工id
*/
private Long userId;
/**
* 用户名
*/
private String userName;
/**
* 用户ip
*/
private String remoteIp;
/**
* 用户端口
*/
private Integer remotePort;
/**
* 浏览器
*/
private String remoteBrowser;
/**
* 操作系统
*/
private String remoteOs;
/**
* 登录状态
*/
private Integer loginStatus;
}

View File

@@ -0,0 +1,31 @@
package net.lab1024.smartadmin.module.business.log.userloginlog.domain;
import net.lab1024.smartadmin.common.domain.PageParamDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* [ 用户登录日志 ]
*
* @author yandanyang
* @version 1.0
* @company 1024lab.net
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
* @date 2019-05-15 10:25:21
* @since JDK1.8
*/
@Data
public class UserLoginLogQueryDTO extends PageParamDTO {
@ApiModelProperty("开始日期")
private String startDate;
@ApiModelProperty("结束日期")
private String endDate;
@ApiModelProperty("用户名")
private String userName;
}

Some files were not shown because too many files have changed in this diff Show More