mirror of
https://gitee.com/lab1024/smart-admin.git
synced 2025-11-12 13:43:49 +08:00
v1.0.0
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
package com.gangquan360.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 = {"com.gangquan360.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.gangquan360.smartadmin.common.anno;
|
||||
|
||||
import com.gangquan360.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 "";
|
||||
|
||||
boolean required() default true;
|
||||
|
||||
String dataType() default "";
|
||||
|
||||
String enumDesc() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.gangquan360.smartadmin.common.anno;
|
||||
|
||||
import com.gangquan360.smartadmin.module.datascope.constant.DataScopeTypeEnum;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 第几个where 条件 从0开始
|
||||
* @return
|
||||
*/
|
||||
int whereIndex() default 0;
|
||||
|
||||
String joinSql() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.gangquan360.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 {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.gangquan360.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 {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.gangquan360.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 {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.gangquan360.smartadmin.common.constant;
|
||||
|
||||
|
||||
import com.gangquan360.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.gangquan360.smartadmin.common.constant;
|
||||
|
||||
import com.gangquan360.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package com.gangquan360.smartadmin.common.constant;
|
||||
|
||||
import com.gangquan360.smartadmin.module.department.DepartmentResponseCodeConst;
|
||||
import com.gangquan360.smartadmin.module.employee.constant.EmployeeResponseCodeConst;
|
||||
import com.gangquan360.smartadmin.module.file.constant.FileResponseCodeConst;
|
||||
import com.gangquan360.smartadmin.module.log.orderoperatelog.constant.OrderOperateLogOperateTypeConst;
|
||||
import com.gangquan360.smartadmin.module.login.LoginResponseCodeConst;
|
||||
import com.gangquan360.smartadmin.module.position.PositionResponseCodeConst;
|
||||
import com.gangquan360.smartadmin.module.privilege.constant.PrivilegeResponseCodeConst;
|
||||
import com.gangquan360.smartadmin.module.role.basic.RoleResponseCodeConst;
|
||||
import com.gangquan360.smartadmin.module.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, "success", true);
|
||||
|
||||
public static final ResponseCodeConst COMMON_ERROR = new ResponseCodeConst(2, "我错了....");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.gangquan360.smartadmin.common.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotations.TableId;
|
||||
import com.baomidou.mybatisplus.enums.IdType;
|
||||
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 上午 11:15
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
public class BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键id
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.gangquan360.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"," ");
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.gangquan360.smartadmin.common.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 分页基础参数
|
||||
*
|
||||
* @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 = 200, message = "每页最大为200")
|
||||
protected Integer pageSize;
|
||||
|
||||
@ApiModelProperty("排序规则:true正序 | false 倒序")
|
||||
protected Boolean sort;
|
||||
|
||||
@ApiModelProperty("排序字段")
|
||||
protected String orderByField;
|
||||
|
||||
@ApiModelProperty("是否查询总条数")
|
||||
protected Boolean searchCount;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.gangquan360.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 Integer pageNum;
|
||||
|
||||
/**
|
||||
* 每页的数量
|
||||
*/
|
||||
@ApiModelProperty(value = "每页的数量")
|
||||
private Integer pageSize;
|
||||
|
||||
/**
|
||||
* 总记录数
|
||||
*/
|
||||
@ApiModelProperty(value = "总记录数")
|
||||
private Long total;
|
||||
|
||||
/**
|
||||
* 总页数
|
||||
*/
|
||||
@ApiModelProperty(value = "总页数")
|
||||
private Integer pages;
|
||||
|
||||
/**
|
||||
* 结果集
|
||||
*/
|
||||
@ApiModelProperty(value = "结果集")
|
||||
private List<T> list;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.gangquan360.smartadmin.common.domain;
|
||||
|
||||
|
||||
import com.gangquan360.smartadmin.common.constant.ResponseCodeConst;
|
||||
|
||||
/**
|
||||
* 返回类
|
||||
*
|
||||
* @param <T>
|
||||
* @author gangquan
|
||||
*/
|
||||
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 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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.gangquan360.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.gangquan360.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.gangquan360.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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.gangquan360.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;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.gangquan360.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);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.gangquan360.smartadmin.common.heartbeat;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @Description:
|
||||
* @Author: simajinqiang
|
||||
* @Date: 2018/7/9 14:06
|
||||
*/
|
||||
public interface HeartBeatRecordCommendInterface {
|
||||
/**
|
||||
* 处理
|
||||
* @param heartBeatRecord
|
||||
*/
|
||||
void handler(HeartBeatRecordDTO heartBeatRecord);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.gangquan360.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;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.gangquan360.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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.gangquan360.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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.gangquan360.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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.gangquan360.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.gangquan360.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.gangquan360.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.gangquan360.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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.gangquan360.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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.gangquan360.smartadmin.common.reload;
|
||||
|
||||
import com.gangquan360.smartadmin.common.reload.annotation.SmartReload;
|
||||
import com.gangquan360.smartadmin.common.reload.domain.AbstractSmartReloadObject;
|
||||
import com.gangquan360.smartadmin.common.reload.domain.AnnotationReloadObject;
|
||||
import com.gangquan360.smartadmin.common.reload.domain.InterfaceReloadObject;
|
||||
import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
|
||||
import com.gangquan360.smartadmin.common.reload.domain.entity.SmartReloadResult;
|
||||
import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadCommandInterface;
|
||||
import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadThreadLogger;
|
||||
import com.gangquan360.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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.gangquan360.smartadmin.common.reload;
|
||||
|
||||
import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadCommandInterface;
|
||||
import com.gangquan360.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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.gangquan360.smartadmin.common.reload.abstracts;
|
||||
|
||||
import com.gangquan360.smartadmin.common.reload.SmartReloadManager;
|
||||
import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
|
||||
import com.gangquan360.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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.gangquan360.smartadmin.common.reload.abstracts;
|
||||
|
||||
import com.gangquan360.smartadmin.common.reload.SmartReloadManager;
|
||||
import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
|
||||
import com.gangquan360.smartadmin.common.reload.interfaces.SmartReloadCommandInterface;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.gangquan360.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();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.gangquan360.smartadmin.common.reload.domain;
|
||||
|
||||
import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
|
||||
import com.gangquan360.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);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.gangquan360.smartadmin.common.reload.domain;
|
||||
|
||||
import com.gangquan360.smartadmin.common.reload.annotation.SmartReload;
|
||||
import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
|
||||
import com.gangquan360.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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.gangquan360.smartadmin.common.reload.domain;
|
||||
|
||||
import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
|
||||
import com.gangquan360.smartadmin.common.reload.domain.entity.SmartReloadResult;
|
||||
import com.gangquan360.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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.gangquan360.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 + '\'' + '}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.gangquan360.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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.gangquan360.smartadmin.common.reload.interfaces;
|
||||
|
||||
import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
|
||||
import com.gangquan360.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);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.gangquan360.smartadmin.common.reload.interfaces;
|
||||
|
||||
/**
|
||||
* SmartReloadThreadLogger 日志类
|
||||
*/
|
||||
public interface SmartReloadThreadLogger {
|
||||
|
||||
void error(String string);
|
||||
|
||||
void error(String string, Throwable e);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.gangquan360.smartadmin.common.reload.interfaces;
|
||||
|
||||
import com.gangquan360.smartadmin.common.reload.domain.entity.ReloadItem;
|
||||
/**
|
||||
* reload 接口<br>
|
||||
* 需要reload的业务实现类
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SmartReloadable {
|
||||
|
||||
/**
|
||||
* reload
|
||||
*
|
||||
* @param reloadItem
|
||||
* @return boolean
|
||||
*/
|
||||
boolean reload(ReloadItem reloadItem);
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
*
|
||||
* 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 com.gangquan360.smartadmin.common.swagger;
|
||||
|
||||
import com.gangquan360.smartadmin.common.anno.ApiModelPropertyEnum;
|
||||
import com.gangquan360.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 org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
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> annotation = Optional.absent();
|
||||
|
||||
if (context.getAnnotatedElement().isPresent()) {
|
||||
annotation = annotation.or(findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
|
||||
}
|
||||
if (context.getBeanPropertyDefinition().isPresent()) {
|
||||
annotation = annotation.or(findPropertyAnnotation(context.getBeanPropertyDefinition().get(), ApiModelPropertyEnum.class));
|
||||
}
|
||||
|
||||
if (annotation.isPresent()) {
|
||||
Class<? extends BaseEnum> aClass = annotation.get().value();
|
||||
String enumInfo = BaseEnum.getInfo(aClass);
|
||||
String enumDesc = annotation.get().enumDesc();
|
||||
context.getBuilder().required(annotation.transform(toIsRequired()).or(false))
|
||||
.description(enumDesc +":"+enumInfo)
|
||||
.example(annotation.transform(toExample()).orNull());
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.gangquan360.smartadmin.common.validator.bigdecimal;
|
||||
|
||||
import com.gangquan360.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.gangquan360.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 {};
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.gangquan360.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,
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.gangquan360.smartadmin.common.validator.en;
|
||||
|
||||
|
||||
import com.gangquan360.smartadmin.common.domain.BaseEnum;
|
||||
import com.gangquan360.smartadmin.common.validator.en.EnumValidator;
|
||||
|
||||
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 {};
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.gangquan360.smartadmin.common.validator.en;
|
||||
|
||||
import com.gangquan360.smartadmin.common.domain.BaseEnum;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 枚举类校验器
|
||||
*
|
||||
* @author listen
|
||||
* @date 2017/11/11 15:34
|
||||
*/
|
||||
public class EnumValidator implements ConstraintValidator<CheckEnum, Object> {
|
||||
|
||||
/**
|
||||
* 枚举类的类对象
|
||||
*/
|
||||
private Class<? extends BaseEnum> enumClass;
|
||||
|
||||
/**
|
||||
* 是否必须
|
||||
*/
|
||||
private boolean required;
|
||||
|
||||
@Override
|
||||
public void initialize(CheckEnum constraintAnnotation) {
|
||||
// 获取注解传入的枚举类对象
|
||||
enumClass = constraintAnnotation.enumClazz();
|
||||
required = constraintAnnotation.required();
|
||||
}
|
||||
|
||||
@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 this.hasEnum(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验集合类型
|
||||
*
|
||||
* @param list
|
||||
* @return
|
||||
*/
|
||||
private boolean checkList(List<Object> list) {
|
||||
if (required && list.isEmpty()) {
|
||||
// 必须的情况下 list 不能为空
|
||||
return false;
|
||||
}
|
||||
for (Object obj : list) {
|
||||
boolean hasEnum = this.hasEnum(obj);
|
||||
if (!hasEnum) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hasEnum(Object value) {
|
||||
// 校验是否为合法的枚举值
|
||||
BaseEnum[] enums = enumClass.getEnumConstants();
|
||||
for (BaseEnum baseEnum : enums) {
|
||||
if (baseEnum.getValue().equals(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.gangquan360.smartadmin.config;
|
||||
|
||||
import com.gangquan360.smartadmin.interceptor.SmartAuthenticationInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.*;
|
||||
|
||||
/**
|
||||
* @Description
|
||||
* @Author lihaifan
|
||||
* @Date Created in 2017/10/24 13:48
|
||||
*/
|
||||
@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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package com.gangquan360.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 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-edle-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.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("com.gangquan360.smartadmin.module..*Service.*");
|
||||
return jdkRegexpMethodPointcut;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultPointcutAdvisor defaultPointcutAdvisor() {
|
||||
DefaultPointcutAdvisor pointcutAdvisor = new DefaultPointcutAdvisor();
|
||||
pointcutAdvisor.setPointcut(jdkRegexpMethodPointcut());
|
||||
pointcutAdvisor.setAdvice(druidStatInterceptor);
|
||||
return pointcutAdvisor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.gangquan360.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;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.gangquan360.smartadmin.config;
|
||||
|
||||
import com.gangquan360.smartadmin.common.kaptcha.KaptchaNoise;
|
||||
import com.gangquan360.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", "ABCDEFG23456789");
|
||||
properties.setProperty("kaptcha.textproducer.char.length", "5");
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.gangquan360.smartadmin.config;
|
||||
|
||||
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
|
||||
import com.baomidou.mybatisplus.plugins.PerformanceInterceptor;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
/**
|
||||
* description
|
||||
*
|
||||
* @author listen
|
||||
* @date 2017/12/19 13:54
|
||||
*/
|
||||
@EnableTransactionManagement
|
||||
@Configuration
|
||||
@MapperScan(basePackages = {"com.gangquan360.smartadmin.module.*"})
|
||||
public class SmartMybatisPlusConfig {
|
||||
|
||||
/**
|
||||
* 分页插件
|
||||
*/
|
||||
@Bean
|
||||
public PaginationInterceptor paginationInterceptor() {
|
||||
return new PaginationInterceptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* mybatis-plus SQL执行效率插件【生产环境可以关闭】
|
||||
*/
|
||||
@Bean
|
||||
@Conditional(SystemEnvironmentCondition.class)
|
||||
public PerformanceInterceptor performanceInterceptor() {
|
||||
return new PerformanceInterceptor();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.gangquan360.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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.gangquan360.smartadmin.config;
|
||||
|
||||
import com.gangquan360.smartadmin.common.reload.SmartReloadManager;
|
||||
import com.gangquan360.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.gangquan360.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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.gangquan360.smartadmin.config;
|
||||
|
||||
import com.gangquan360.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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
package com.gangquan360.smartadmin.config;
|
||||
|
||||
import com.gangquan360.smartadmin.constant.SwaggerTagConst;
|
||||
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 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.RestController;
|
||||
import springfox.documentation.RequestHandler;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
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
|
||||
@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 List<String> groupList = Lists.newArrayList();
|
||||
|
||||
private 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() {
|
||||
// 请求类型过滤规则
|
||||
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());
|
||||
}
|
||||
|
||||
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.and(RequestHandlerSelectors.withClassAnnotation(RestController.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 {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.gangquan360.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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.gangquan360.smartadmin.config;
|
||||
import com.gangquan360.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.gangquan360.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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.gangquan360.smartadmin.constant;
|
||||
/**
|
||||
* smart initDefines 项 常量
|
||||
*
|
||||
* @author listen
|
||||
* @date 2018/02/10 14:29
|
||||
*/
|
||||
public class SmartReloadTagConst {
|
||||
|
||||
/**
|
||||
* 系统环境设置 DEMO
|
||||
*/
|
||||
public static final String SYSTEM_CONFIG = "system_config";
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.gangquan360.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 {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.gangquan360.smartadmin.constant;
|
||||
|
||||
import com.gangquan360.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", "生产环境");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.gangquan360.smartadmin.handler;
|
||||
|
||||
import com.gangquan360.smartadmin.common.constant.ResponseCodeConst;
|
||||
import com.gangquan360.smartadmin.common.domain.ResponseDTO;
|
||||
import com.gangquan360.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) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
log.error("error:", e);
|
||||
|
||||
return ResponseDTO.wrap(ResponseCodeConst.SYSTEM_ERROR);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package com.gangquan360.smartadmin.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.gangquan360.smartadmin.common.anno.OperateLog;
|
||||
import com.gangquan360.smartadmin.common.constant.JudgeEnum;
|
||||
import com.gangquan360.smartadmin.module.log.LogService;
|
||||
import com.gangquan360.smartadmin.module.log.useroperatelog.domain.UserOperateLogEntity;
|
||||
import com.gangquan360.smartadmin.module.login.domain.RequestTokenBO;
|
||||
import com.gangquan360.smartadmin.util.SmartRequestTokenUtil;
|
||||
import com.gangquan360.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(* com.gangquan360.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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.gangquan360.smartadmin.interceptor;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.gangquan360.smartadmin.common.anno.NoNeedLogin;
|
||||
import com.gangquan360.smartadmin.common.anno.NoValidPrivilege;
|
||||
import com.gangquan360.smartadmin.common.domain.ResponseDTO;
|
||||
import com.gangquan360.smartadmin.constant.CommonConst;
|
||||
import com.gangquan360.smartadmin.module.login.LoginResponseCodeConst;
|
||||
import com.gangquan360.smartadmin.module.login.LoginTokenService;
|
||||
import com.gangquan360.smartadmin.module.login.domain.RequestTokenBO;
|
||||
import com.gangquan360.smartadmin.module.privilege.service.PrivilegeEmployeeService;
|
||||
import com.gangquan360.smartadmin.util.SmartRequestTokenUtil;
|
||||
import com.gangquan360.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 {
|
||||
|
||||
private 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.gangquan360.smartadmin.listener;
|
||||
|
||||
import com.gangquan360.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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.gangquan360.smartadmin.module.codegenerator.constant;
|
||||
|
||||
|
||||
/**
|
||||
* [ gt,lt 目前只支持Date]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @since JDK1.8
|
||||
*/
|
||||
public enum SqlOperateTypeEnum{
|
||||
|
||||
|
||||
LIKE(1, "like"),
|
||||
EQUALS(2, "equals"),
|
||||
IN(3, "in"),
|
||||
TIME_EQUALS(5, "time_equals"),
|
||||
TIME_BETWEEN(6, "time_between");
|
||||
|
||||
private Integer type;
|
||||
|
||||
private String name;
|
||||
|
||||
SqlOperateTypeEnum(Integer type, String name) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.gangquan360.smartadmin.module.codegenerator.dao;
|
||||
|
||||
import com.gangquan360.smartadmin.module.codegenerator.domain.ColumnVO;
|
||||
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/5/10 0010 下午 18:59
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Mapper
|
||||
@Component
|
||||
public interface TableDao {
|
||||
|
||||
|
||||
/**
|
||||
* 查询表描述
|
||||
* @param tableName
|
||||
* @return
|
||||
*/
|
||||
String selectTableDesc(@Param("tableName") String tableName);
|
||||
|
||||
/**
|
||||
* 查询表列信息
|
||||
* @param tableName
|
||||
* @return
|
||||
*/
|
||||
List<ColumnVO> selectTableColumn(@Param("tableName") String tableName);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.gangquan360.smartadmin.module.codegenerator.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/5/11 0011 上午 10:12
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class CodeGeneratorDTO {
|
||||
|
||||
/**
|
||||
* 需要生成代码的表名
|
||||
*/
|
||||
private String tableName;
|
||||
|
||||
/**
|
||||
* 表前缀
|
||||
*/
|
||||
private String tablePrefix;
|
||||
|
||||
/**
|
||||
* 基础包路径
|
||||
*/
|
||||
private String basePackage;
|
||||
|
||||
/**
|
||||
* 公司
|
||||
*/
|
||||
private String company;
|
||||
|
||||
/**
|
||||
* 作者
|
||||
*/
|
||||
private String author;
|
||||
|
||||
/**
|
||||
* 需要构建查询方法的列
|
||||
*/
|
||||
private List<CodeGeneratorQueryColumnDTO> queryColumnList;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.gangquan360.smartadmin.module.codegenerator.domain;
|
||||
|
||||
import com.gangquan360.smartadmin.module.codegenerator.constant.SqlOperateTypeEnum;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/5/11 0011 上午 10:13
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class CodeGeneratorQueryColumnDTO {
|
||||
|
||||
/**
|
||||
* 生成查询方法的查询列名
|
||||
*/
|
||||
private String columnName;
|
||||
|
||||
/**
|
||||
* 此列的查询动作
|
||||
*/
|
||||
private SqlOperateTypeEnum sqlOperate;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.gangquan360.smartadmin.module.codegenerator.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/5/10 0010 下午 17:55
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class ColumnVO {
|
||||
|
||||
private String columnName;
|
||||
|
||||
private String columnType;
|
||||
|
||||
private String columnDesc;
|
||||
|
||||
private String fieldType;
|
||||
|
||||
private String fieldName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.gangquan360.smartadmin.module.codegenerator.domain;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/5/10 0010 下午 17:56
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class QueryFieldVO {
|
||||
|
||||
private String fieldName;
|
||||
|
||||
private String columnName;
|
||||
|
||||
private String columnDesc;
|
||||
|
||||
private String fieldType;
|
||||
|
||||
private String sqlOperate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.gangquan360.smartadmin.module.codegenerator.service;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/5/11 0011 上午 8:33
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Component
|
||||
public class CodeGeneratorComponent {
|
||||
|
||||
private static Map<String,String> dataMap = new HashMap<>(16);
|
||||
|
||||
static {
|
||||
dataMap();
|
||||
}
|
||||
|
||||
public static void dataMap(){
|
||||
dataMap.put("int","Integer");
|
||||
dataMap.put("tinyint","Integer");
|
||||
dataMap.put("smallint","Integer");
|
||||
dataMap.put("integer","Integer");
|
||||
dataMap.put("bigint","Long");
|
||||
dataMap.put("float","Float");
|
||||
dataMap.put("double","Double");
|
||||
dataMap.put("decimal","BigDecimal");
|
||||
|
||||
dataMap.put("char","String");
|
||||
dataMap.put("varchar","String");
|
||||
dataMap.put("tinytext","String");
|
||||
dataMap.put("text","String");
|
||||
dataMap.put("longtext","String");
|
||||
|
||||
dataMap.put("date","Date");
|
||||
dataMap.put("datetime","Date");
|
||||
dataMap.put("timestamp","Date");
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Map<String,String> codeTemplates(String moduleClass, String basePackage, String modulePackage){
|
||||
String javaPackagePath = "src"+File.separator+"main" + File.separator + "java" + File.separator;
|
||||
javaPackagePath = javaPackagePath + basePackage.replace(".", File.separator) + File.separator+"module"+File.separator + modulePackage + File.separator;
|
||||
String xmlPackagePath = "src"+File.separator+"main" + File.separator + "resources" + File.separator +"mapper"+File.separator+ modulePackage + File.separator;
|
||||
Map<String,String> templateMap = new HashMap<>(7);
|
||||
templateMap.put("templates/codegenerator/Controller.java.vm",javaPackagePath+"controller"+File.separator+moduleClass+"Controller.java");
|
||||
templateMap.put("templates/codegenerator/Dao.java.vm",javaPackagePath+"dao"+File.separator+moduleClass+"Dao.java");
|
||||
templateMap.put("templates/codegenerator/Dao.xml.vm",xmlPackagePath+moduleClass+"Mapper.xml");
|
||||
templateMap.put("templates/codegenerator/DTO.java.vm",javaPackagePath+"domain"+File.separator+"dto"+File.separator+moduleClass+"DTO.java");
|
||||
templateMap.put("templates/codegenerator/Entity.java.vm",javaPackagePath+"domain"+File.separator+"entity"+File.separator+moduleClass+"Entity.java");
|
||||
templateMap.put("templates/codegenerator/QueryDTO.java.vm",javaPackagePath+"domain"+File.separator+"dto"+File.separator+moduleClass+"QueryDTO.java");
|
||||
templateMap.put("templates/codegenerator/Service.java.vm",javaPackagePath+"service"+File.separator+moduleClass+"Service.java");
|
||||
return templateMap;
|
||||
}
|
||||
|
||||
public String getJavaType(String mysqlType ){
|
||||
String javaType = dataMap.get(mysqlType);
|
||||
return javaType;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
package com.gangquan360.smartadmin.module.codegenerator.service;
|
||||
|
||||
import com.gangquan360.smartadmin.module.codegenerator.dao.TableDao;
|
||||
import com.gangquan360.smartadmin.module.codegenerator.domain.CodeGeneratorDTO;
|
||||
import com.gangquan360.smartadmin.module.codegenerator.domain.CodeGeneratorQueryColumnDTO;
|
||||
import com.gangquan360.smartadmin.module.codegenerator.domain.ColumnVO;
|
||||
import com.gangquan360.smartadmin.module.codegenerator.domain.QueryFieldVO;
|
||||
import com.gangquan360.smartadmin.util.SmartDateUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.velocity.Template;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.app.Velocity;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/5/11 0011 上午 9:36
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class CodeGeneratorService {
|
||||
|
||||
@Autowired
|
||||
private TableDao tableDao;
|
||||
|
||||
@Autowired
|
||||
private CodeGeneratorComponent codeGeneratorComponent;
|
||||
|
||||
/**
|
||||
* 大家注意了开始生成代码了
|
||||
*
|
||||
* @param codeGenerator
|
||||
* @throws Exception
|
||||
*/
|
||||
public void codeGenerator(CodeGeneratorDTO codeGenerator) throws Exception {
|
||||
this.basicValid(codeGenerator);
|
||||
String date = SmartDateUtil.formatYMDHMS(new Date());
|
||||
String tableDesc = this.getTableDesc(codeGenerator.getTableName());
|
||||
String author = codeGenerator.getAuthor();
|
||||
String basePackage = codeGenerator.getBasePackage();
|
||||
if (StringUtils.isEmpty(basePackage)) {
|
||||
basePackage = "com.gangquan360.smartadmin";
|
||||
}
|
||||
String moduleClass = this.tableName2Class(codeGenerator.getTableName(), codeGenerator.getTablePrefix());
|
||||
String moduleVar = this.tableName2Var(codeGenerator.getTableName(), codeGenerator.getTablePrefix());
|
||||
String modulePackage = this.tableName2Package(codeGenerator.getTableName(), codeGenerator.getTablePrefix());
|
||||
|
||||
List<ColumnVO> columnList = this.columnList(codeGenerator.getTableName());
|
||||
List<QueryFieldVO> queryFieldList = this.buildQueryField(codeGenerator, columnList);
|
||||
Map<String, String> codeTemplates = codeGeneratorComponent.codeTemplates(moduleClass, basePackage, modulePackage);
|
||||
List<String> queryImports = this.buildQueryImport(queryFieldList);
|
||||
List<String> dtoImports = this.buildDTOImport(columnList);
|
||||
List<String> entityImports = this.buildEntityImport(columnList);
|
||||
Properties p = new Properties();
|
||||
p.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
|
||||
p.put("directive.foreach.counter.name", "velocityCount");
|
||||
p.put("directive.foreach.counter.initial.value", "1");
|
||||
Velocity.init(p);
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("company", codeGenerator.getCompany());
|
||||
map.put("tableName", codeGenerator.getTableName());
|
||||
map.put("basePackage", basePackage);
|
||||
map.put("modulePackage", modulePackage);
|
||||
map.put("moduleClass", moduleClass);
|
||||
map.put("tableDesc", tableDesc);
|
||||
map.put("author", author);
|
||||
map.put("date", date);
|
||||
map.put("moduleVar", moduleVar);
|
||||
map.put("columnList", columnList);
|
||||
map.put("queryFieldList", queryFieldList);
|
||||
map.put("queryImports", queryImports);
|
||||
map.put("dtoImports", dtoImports);
|
||||
map.put("entityImports", entityImports);
|
||||
VelocityContext context = new VelocityContext(map);
|
||||
this.codeGenerator(context, codeTemplates);
|
||||
}
|
||||
|
||||
private List<String> buildQueryImport(List<QueryFieldVO> queryFieldList) {
|
||||
List<String> queryImports = Lists.newArrayList();
|
||||
if (CollectionUtils.isNotEmpty(queryFieldList)) {
|
||||
queryFieldList.forEach(e -> {
|
||||
importPackage(queryImports, e.getFieldType());
|
||||
if ("in".equals(e.getSqlOperate())) {
|
||||
queryImports.add("import java.util.List;");
|
||||
}
|
||||
});
|
||||
}
|
||||
return queryImports;
|
||||
}
|
||||
|
||||
private List<String> buildDTOImport(List<ColumnVO> columnList) {
|
||||
List<String> dtoImports = Lists.newArrayList();
|
||||
if (CollectionUtils.isNotEmpty(columnList)) {
|
||||
columnList.forEach(e -> {
|
||||
importPackage(dtoImports, e.getFieldType());
|
||||
});
|
||||
}
|
||||
return dtoImports;
|
||||
}
|
||||
|
||||
private List<String> buildEntityImport(List<ColumnVO> columnList) {
|
||||
List<String> entityImports = Lists.newArrayList();
|
||||
if (CollectionUtils.isNotEmpty(columnList)) {
|
||||
columnList.forEach(e -> {
|
||||
if (! e.getFieldName().equals("createTime") && ! e.getFieldName().equals("updateTime") && ! e.getFieldName().equals("id")) {
|
||||
importPackage(entityImports, e.getFieldType());
|
||||
}
|
||||
});
|
||||
}
|
||||
return entityImports;
|
||||
}
|
||||
|
||||
private void importPackage(List<String> imports, String fieldType) {
|
||||
if ("Date".equals(fieldType) && ! imports.contains("import java.util.Date;")) {
|
||||
imports.add("import java.util.Date;");
|
||||
}
|
||||
if ("BigDecimal".equals(fieldType) && ! imports.contains("import java.math.BigDecimal;")) {
|
||||
imports.add("import java.math.BigDecimal;");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成代码
|
||||
*
|
||||
* @param context
|
||||
* @param codeTemplates
|
||||
*/
|
||||
private void codeGenerator(VelocityContext context, Map<String, String> codeTemplates) throws Exception {
|
||||
String projectPath = ResourceUtils.getURL("classpath:").getPath();
|
||||
String targetDir = "target";
|
||||
int targetIndex = StringUtils.indexOf(projectPath, targetDir);
|
||||
projectPath = projectPath.substring(0, targetIndex + targetDir.length() + 1);
|
||||
projectPath = projectPath.replace("target/", "").replaceFirst("/", "");
|
||||
for (Entry<String, String> entry : codeTemplates.entrySet()) {
|
||||
String template = entry.getKey();
|
||||
String filePath = projectPath + entry.getValue();
|
||||
String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
|
||||
String fileDir = filePath.replace(fileName, "");
|
||||
File directory = new File(fileDir);
|
||||
if (! directory.exists()) {
|
||||
directory.mkdirs();
|
||||
}
|
||||
FileWriter writer;
|
||||
try {
|
||||
writer = new FileWriter(filePath);
|
||||
Template tpl = Velocity.getTemplate(template, "UTF-8");
|
||||
tpl.merge(context, writer);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
int i = 1 / 0;
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void basicValid(CodeGeneratorDTO codeGenerator) throws Exception {
|
||||
if (StringUtils.isEmpty(codeGenerator.getTableName())) {
|
||||
throw new Exception("你没建表吗?");
|
||||
}
|
||||
if (StringUtils.isEmpty(codeGenerator.getTablePrefix())) {
|
||||
throw new Exception("你的表没前缀吗?");
|
||||
}
|
||||
if (StringUtils.isEmpty(codeGenerator.getAuthor())) {
|
||||
throw new Exception("输入下你的大名");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询集合
|
||||
*
|
||||
* @param codeGenerator
|
||||
* @param columnList
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private List<QueryFieldVO> buildQueryField(CodeGeneratorDTO codeGenerator, List<ColumnVO> columnList) throws Exception {
|
||||
List<QueryFieldVO> queryFieldList = Lists.newArrayList();
|
||||
Map<String, ColumnVO> storageMap = columnList.stream().collect(Collectors.toMap(ColumnVO:: getColumnName, e -> e));
|
||||
List<CodeGeneratorQueryColumnDTO> queryColumnList = codeGenerator.getQueryColumnList();
|
||||
if (CollectionUtils.isEmpty(queryColumnList)) {
|
||||
return queryFieldList;
|
||||
}
|
||||
for (CodeGeneratorQueryColumnDTO queryColumn : queryColumnList) {
|
||||
ColumnVO columnDTO = storageMap.get(queryColumn.getColumnName());
|
||||
if (columnDTO == null) {
|
||||
String errorMsg = "sql列[" + queryColumn.getColumnName() + "]在表[" + codeGenerator.getTableName() + "]中不存在。";
|
||||
log.error(errorMsg);
|
||||
throw new Exception(errorMsg);
|
||||
}
|
||||
QueryFieldVO queryField =
|
||||
QueryFieldVO.builder().fieldName(columnDTO.getFieldName()).fieldType(columnDTO.getFieldType()).columnName(columnDTO.getColumnName()).columnDesc(columnDTO.getColumnDesc()).sqlOperate(queryColumn.getSqlOperate().getName()).build();
|
||||
queryFieldList.add(queryField);
|
||||
}
|
||||
return queryFieldList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 列数据 组合
|
||||
*
|
||||
* @param tableName
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private List<ColumnVO> columnList(String tableName) throws Exception {
|
||||
List<ColumnVO> list = tableDao.selectTableColumn(tableName);
|
||||
for (ColumnVO column : list) {
|
||||
String javaType = codeGeneratorComponent.getJavaType(column.getColumnType());
|
||||
if (StringUtils.isEmpty(javaType)) {
|
||||
String errorMsg = "sql数据类型[" + column.getColumnType() + "]缺少对应的java类型。";
|
||||
log.error(errorMsg);
|
||||
throw new Exception(errorMsg);
|
||||
}
|
||||
if ("Integer".equals(javaType) && column.getColumnName().contains("id")) {
|
||||
column.setFieldType("Long");
|
||||
} else {
|
||||
column.setFieldType(javaType);
|
||||
}
|
||||
column.setFieldName(this.columnName2Field(column.getColumnName()));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列注释为类描述
|
||||
*
|
||||
* @param tableName
|
||||
* @return
|
||||
*/
|
||||
private String getTableDesc(String tableName) {
|
||||
return tableDao.selectTableDesc(tableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 列名转字段名
|
||||
*
|
||||
* @param columnName
|
||||
* @return
|
||||
*/
|
||||
private String columnName2Field(String columnName) {
|
||||
String transName = WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", "");
|
||||
return WordUtils.uncapitalize(transName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 表名转类名前缀
|
||||
*
|
||||
* @param tableName
|
||||
* @param tablePrefix
|
||||
* @return
|
||||
*/
|
||||
private String tableName2Class(String tableName, String tablePrefix) {
|
||||
if (StringUtils.isNotBlank(tablePrefix)) {
|
||||
tableName = tableName.replaceFirst(tablePrefix, "");
|
||||
}
|
||||
return WordUtils.capitalizeFully(tableName, new char[]{'_'}).replace("_", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 表名转包名
|
||||
*
|
||||
* @param tableName
|
||||
* @param tablePrefix
|
||||
* @return
|
||||
*/
|
||||
private String tableName2Package(String tableName, String tablePrefix) {
|
||||
if (StringUtils.isNotBlank(tablePrefix)) {
|
||||
tableName = tableName.replaceFirst(tablePrefix, "");
|
||||
}
|
||||
return tableName.replace("_", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 表名转 java变量前缀
|
||||
*
|
||||
* @param tableName
|
||||
* @param tablePrefix
|
||||
* @return
|
||||
*/
|
||||
private String tableName2Var(String tableName, String tablePrefix) {
|
||||
if (StringUtils.isNotBlank(tablePrefix)) {
|
||||
tableName = tableName.replaceFirst(tablePrefix, "");
|
||||
}
|
||||
String transName = WordUtils.capitalizeFully(tableName, new char[]{'_'}).replace("_", "");
|
||||
return WordUtils.uncapitalize(transName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.gangquan360.smartadmin.module.datascope;
|
||||
|
||||
import com.gangquan360.smartadmin.common.anno.NoValidPrivilege;
|
||||
import com.gangquan360.smartadmin.common.anno.OperateLog;
|
||||
import com.gangquan360.smartadmin.constant.SwaggerTagConst;
|
||||
import com.gangquan360.smartadmin.common.domain.ResponseDTO;
|
||||
import com.gangquan360.smartadmin.module.datascope.domain.dto.*;
|
||||
import com.gangquan360.smartadmin.module.datascope.service.DataScopeService;
|
||||
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;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/27 0027 下午 15:12
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Api(tags = {SwaggerTagConst.Admin.MANAGER_DATA_SCOPE})
|
||||
@OperateLog
|
||||
@RestController
|
||||
public class DataScopeController {
|
||||
|
||||
@Autowired
|
||||
private DataScopeService dataScopeService;
|
||||
|
||||
@ApiOperation(value = "获取当前系统所配置的所有数据范围")
|
||||
@GetMapping("/dataScope/list")
|
||||
@NoValidPrivilege
|
||||
public ResponseDTO<List<DataScopeAndViewTypeVO>> dataScopeList() {
|
||||
return dataScopeService.dataScopeList();
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取某角色所设置的数据范围")
|
||||
@GetMapping("/dataScope/listByRole/{roleId}")
|
||||
@NoValidPrivilege
|
||||
public ResponseDTO<List<DataScopeSelectVO>> dataScopeListByRole(@PathVariable Long roleId) {
|
||||
return dataScopeService.dataScopeListByRole(roleId);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "批量设置某角色数据范围")
|
||||
@PostMapping("/dataScope/batchSet")
|
||||
@NoValidPrivilege
|
||||
public ResponseDTO<String> dataScopeBatchSet(@RequestBody @Valid DataScopeBatchSetRoleDTO batchSetRoleDTO) {
|
||||
return dataScopeService.dataScopeBatchSet(batchSetRoleDTO);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.gangquan360.smartadmin.module.datascope;
|
||||
|
||||
import com.baomidou.mybatisplus.mapper.BaseMapper;
|
||||
import com.gangquan360.smartadmin.module.datascope.domain.entity.DataScopeRoleEntity;
|
||||
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/4/27 0027 下午 14:41
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Mapper
|
||||
@Component
|
||||
public interface DataScopeRoleDao extends BaseMapper<DataScopeRoleEntity> {
|
||||
|
||||
/**
|
||||
* 获取某个角色的设置信息
|
||||
* @param roleId
|
||||
* @return
|
||||
*/
|
||||
List<DataScopeRoleEntity> listByRoleId(@Param("roleId") Long roleId);
|
||||
|
||||
/**
|
||||
* 获取某批角色的所有数据范围配置信息
|
||||
* @param roleIdList
|
||||
* @return
|
||||
*/
|
||||
List<DataScopeRoleEntity> listByRoleIdList(@Param("roleIdList") List<Long> roleIdList);
|
||||
|
||||
/**
|
||||
* 删除某个角色的设置信息
|
||||
* @param roleId
|
||||
* @return
|
||||
*/
|
||||
void deleteByRoleId(@Param("roleId") Long roleId);
|
||||
|
||||
|
||||
/**
|
||||
* 批量添加设置信息
|
||||
* @param list
|
||||
*/
|
||||
void batchInsert(@Param("list")List<DataScopeRoleEntity> list);
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package com.gangquan360.smartadmin.module.datascope;
|
||||
|
||||
import com.gangquan360.smartadmin.module.datascope.domain.dto.DataScopeSqlConfigDTO;
|
||||
import com.gangquan360.smartadmin.module.datascope.service.DataScopeSqlConfigService;
|
||||
import com.gangquan360.smartadmin.third.SmartApplicationContext;
|
||||
import com.gangquan360.smartadmin.util.SmartStringUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.mapping.*;
|
||||
import org.apache.ibatis.plugin.*;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* [ mybaits sql 拦截 ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
|
||||
* @date
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Intercepts({@Signature(type = org.apache.ibatis.executor.Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
|
||||
@Component
|
||||
public class MyBatisPlugin implements Interceptor {
|
||||
|
||||
@Override
|
||||
public Object intercept(Invocation invocation) throws Throwable {
|
||||
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
|
||||
Object parameter = invocation.getArgs()[1];
|
||||
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
|
||||
String originalSql = boundSql.getSql().trim();
|
||||
String id = mappedStatement.getId();
|
||||
List<String> methodStrList = SmartStringUtil.splitConvertToList(id, "\\.");
|
||||
String path = methodStrList.get(methodStrList.size() - 2) + "." + methodStrList.get(methodStrList.size() - 1);
|
||||
DataScopeSqlConfigService dataScopeSqlConfigService = this.dataScopeSqlConfigService();
|
||||
if (dataScopeSqlConfigService == null) {
|
||||
return invocation.proceed();
|
||||
}
|
||||
DataScopeSqlConfigDTO sqlConfigDTO = dataScopeSqlConfigService.getSqlConfig(path);
|
||||
if (sqlConfigDTO != null) {
|
||||
BoundSql newBoundSql = copyFromBoundSql(mappedStatement, boundSql, this.joinSql(originalSql, sqlConfigDTO));
|
||||
ParameterMap map = mappedStatement.getParameterMap();
|
||||
MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql), map);
|
||||
invocation.getArgs()[0] = newMs;
|
||||
}
|
||||
|
||||
Object obj = invocation.proceed();
|
||||
return obj;
|
||||
}
|
||||
|
||||
private String joinSql(String sql, DataScopeSqlConfigDTO sqlConfigDTO) {
|
||||
if (null == sqlConfigDTO) {
|
||||
return sql;
|
||||
}
|
||||
String appendSql = this.dataScopeSqlConfigService().getJoinSql(sqlConfigDTO);
|
||||
if (StringUtils.isEmpty(appendSql)) {
|
||||
return sql;
|
||||
}
|
||||
Integer appendSqlWhereIndex = sqlConfigDTO.getWhereIndex();
|
||||
String where = "where";
|
||||
String order = "order by";
|
||||
String group = "group by";
|
||||
int whereIndex = StringUtils.ordinalIndexOf(sql.toLowerCase(), where, appendSqlWhereIndex + 1);
|
||||
int orderIndex = sql.toLowerCase().indexOf(order);
|
||||
int groupIndex = sql.toLowerCase().indexOf(group);
|
||||
if (whereIndex > - 1) {
|
||||
String subSql = sql.substring(0, whereIndex + where.length() + 1);
|
||||
subSql = subSql + " " + appendSql + " AND " + sql.substring(whereIndex + where.length() + 1);
|
||||
return subSql;
|
||||
}
|
||||
|
||||
if (groupIndex > - 1) {
|
||||
String subSql = sql.substring(0, groupIndex);
|
||||
subSql = subSql + " where " + appendSql + " " + sql.substring(groupIndex);
|
||||
return subSql;
|
||||
}
|
||||
if (orderIndex > - 1) {
|
||||
String subSql = sql.substring(0, orderIndex);
|
||||
subSql = subSql + " where " + appendSql + " " + sql.substring(orderIndex);
|
||||
return subSql;
|
||||
}
|
||||
sql += " where " + appendSql;
|
||||
return sql;
|
||||
}
|
||||
|
||||
public DataScopeSqlConfigService dataScopeSqlConfigService() {
|
||||
return (DataScopeSqlConfigService) SmartApplicationContext.getBean("dataScopeSqlConfigService");
|
||||
}
|
||||
|
||||
public class BoundSqlSqlSource implements SqlSource {
|
||||
|
||||
BoundSql boundSql;
|
||||
|
||||
public BoundSqlSqlSource(BoundSql boundSql) {
|
||||
this.boundSql = boundSql;
|
||||
}
|
||||
@Override
|
||||
public BoundSql getBoundSql(Object parameterObject) {
|
||||
return boundSql;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制MappedStatement对象
|
||||
*/
|
||||
private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource, ParameterMap parameterMap) {
|
||||
|
||||
MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());
|
||||
builder.resource(ms.getResource());
|
||||
builder.fetchSize(ms.getFetchSize());
|
||||
builder.statementType(ms.getStatementType());
|
||||
builder.keyGenerator(ms.getKeyGenerator());
|
||||
builder.timeout(ms.getTimeout());
|
||||
builder.parameterMap(parameterMap);
|
||||
builder.resultMaps(ms.getResultMaps());
|
||||
builder.resultSetType(ms.getResultSetType());
|
||||
builder.cache(ms.getCache());
|
||||
builder.flushCacheRequired(ms.isFlushCacheRequired());
|
||||
builder.useCache(ms.isUseCache());
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制BoundSql对象
|
||||
*/
|
||||
private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) {
|
||||
BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, boundSql.getParameterMappings(), boundSql.getParameterObject());
|
||||
for (ParameterMapping mapping : boundSql.getParameterMappings()) {
|
||||
String prop = mapping.getProperty();
|
||||
if (boundSql.hasAdditionalParameter(prop)) {
|
||||
newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
|
||||
}
|
||||
}
|
||||
return newBoundSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object plugin(Object arg0) {
|
||||
return Plugin.wrap(arg0, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties arg0) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.constant;
|
||||
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @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 DataScopeTypeEnum {
|
||||
|
||||
DEFAULT(0,0,"默认类型","数据范围样例");
|
||||
|
||||
private Integer type;
|
||||
private Integer sort;
|
||||
private String name;
|
||||
private String desc;
|
||||
|
||||
DataScopeTypeEnum(Integer type,Integer sort,String name,String desc) {
|
||||
this.type = type;
|
||||
this.sort = sort;
|
||||
this.name = name;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Integer getSort() {
|
||||
return sort;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.constant;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @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 DataScopeViewTypeEnum {
|
||||
|
||||
ME(0,0,"本人"),
|
||||
|
||||
DEPARTMENT(1,5,"本部门"),
|
||||
|
||||
DEPARTMENT_AND_SUB(2,10,"本部门及下属子部门"),
|
||||
|
||||
ALL(3,15,"全部");
|
||||
|
||||
private Integer type;
|
||||
private Integer level;
|
||||
private String name;
|
||||
|
||||
DataScopeViewTypeEnum(Integer type,Integer level, String name) {
|
||||
this.type = type;
|
||||
this.level = level;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Integer getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static DataScopeViewTypeEnum valueOf(Integer type) {
|
||||
DataScopeViewTypeEnum[] values = DataScopeViewTypeEnum.values();
|
||||
Optional<DataScopeViewTypeEnum> first = Arrays.stream(values).filter(e -> e.getType().equals(type)).findFirst();
|
||||
return !first.isPresent() ? null : first.get();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.constant;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/5/8 0008 下午 16:00
|
||||
* @since JDK1.8
|
||||
*/
|
||||
public enum DataScopeWhereInTypeEnum {
|
||||
|
||||
EMPLOYEE(0,"以员工IN"),
|
||||
|
||||
DEPARTMENT(1,"以部门IN");
|
||||
|
||||
private Integer type;
|
||||
private String desc;
|
||||
|
||||
DataScopeWhereInTypeEnum(Integer type, String desc) {
|
||||
this.type = type;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/27 0027 下午 16:37
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
public class DataScopeAndViewTypeVO {
|
||||
|
||||
@ApiModelProperty("数据范围类型")
|
||||
private Integer dataScopeType;
|
||||
|
||||
@ApiModelProperty("数据范围名称")
|
||||
private String dataScopeTypeName;
|
||||
|
||||
@ApiModelProperty("描述")
|
||||
private String dataScopeTypeDesc;
|
||||
|
||||
@ApiModelProperty("顺序")
|
||||
private Integer dataScopeTypeSort;
|
||||
|
||||
@ApiModelProperty("可见范围列表")
|
||||
private List<DataScopeViewTypeVO> viewTypeList;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/27 0027 下午 16:51
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
public class DataScopeBatchSetDTO {
|
||||
|
||||
@ApiModelProperty("数据范围类型")
|
||||
@NotNull(message = "数据范围类型不能为空")
|
||||
private Integer dataScopeType;
|
||||
|
||||
@ApiModelProperty("可见范围")
|
||||
@NotNull(message = "可见范围不能为空")
|
||||
private Integer viewType;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/27 0027 下午 16:47
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
public class DataScopeBatchSetRoleDTO {
|
||||
|
||||
@ApiModelProperty("角色id")
|
||||
@NotNull(message = "角色id不能为空")
|
||||
private Long roleId;
|
||||
|
||||
@ApiModelProperty("设置信息")
|
||||
@Valid
|
||||
private List<DataScopeBatchSetDTO> batchSetList;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/27 0027 下午 16:37
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class DataScopeDTO {
|
||||
|
||||
@ApiModelProperty("数据范围类型")
|
||||
private Integer dataScopeType;
|
||||
|
||||
@ApiModelProperty("数据范围名称")
|
||||
private String dataScopeTypeName;
|
||||
|
||||
@ApiModelProperty("描述")
|
||||
private String dataScopeTypeDesc;
|
||||
|
||||
@ApiModelProperty("顺序")
|
||||
private Integer dataScopeTypeSort;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/27 0027 下午 16:43
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
public class DataScopeSelectVO {
|
||||
|
||||
@ApiModelProperty("数据范围id")
|
||||
private Integer dataScopeType;
|
||||
|
||||
@ApiModelProperty("可见范围")
|
||||
private Integer viewType;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/28 0028 下午 17:21
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
public class DataScopeSqlConfigDTO {
|
||||
|
||||
private Integer dataScopeType;
|
||||
|
||||
private String joinSql;
|
||||
|
||||
private Integer whereIndex;
|
||||
|
||||
private Integer dataScopeWhereInType;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/28 0028 下午 15:41
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public class DataScopeViewTypeVO {
|
||||
|
||||
@ApiModelProperty("可见范围")
|
||||
private Integer viewType;
|
||||
@ApiModelProperty("可见范围名称")
|
||||
private String viewTypeName;
|
||||
|
||||
@ApiModelProperty("级别,用于表示范围大小")
|
||||
private Integer viewTypeLevel;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.domain.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotations.TableName;
|
||||
import com.gangquan360.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/4/27 0027 下午 14:43
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
@TableName("t_role_data_scope")
|
||||
public class DataScopeRoleEntity extends BaseEntity{
|
||||
|
||||
/**
|
||||
* 数据范围id
|
||||
*/
|
||||
private Integer dataScopeType;
|
||||
/**
|
||||
* 数据范围类型
|
||||
*/
|
||||
private Integer viewType;
|
||||
/**
|
||||
* 角色id
|
||||
*/
|
||||
private Long roleId;
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.service;
|
||||
|
||||
import com.gangquan360.smartadmin.common.constant.ResponseCodeConst;
|
||||
import com.gangquan360.smartadmin.common.domain.ResponseDTO;
|
||||
import com.gangquan360.smartadmin.module.datascope.DataScopeRoleDao;
|
||||
import com.gangquan360.smartadmin.module.datascope.constant.DataScopeTypeEnum;
|
||||
import com.gangquan360.smartadmin.module.datascope.constant.DataScopeViewTypeEnum;
|
||||
import com.gangquan360.smartadmin.module.datascope.domain.dto.*;
|
||||
import com.gangquan360.smartadmin.module.datascope.domain.entity.DataScopeRoleEntity;
|
||||
import com.gangquan360.smartadmin.util.SmartBeanUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/27 0027 下午 14:52
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Service
|
||||
public class DataScopeService {
|
||||
|
||||
@Autowired
|
||||
private DataScopeRoleDao dataScopeRoleDao;
|
||||
|
||||
/**
|
||||
* 获取所有可以进行数据范围配置的信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ResponseDTO<List<DataScopeAndViewTypeVO>> dataScopeList() {
|
||||
List<DataScopeDTO> dataScopeList = this.getDataScopeType();
|
||||
List<DataScopeAndViewTypeVO> dataScopeAndTypeList = SmartBeanUtil.copyList(dataScopeList, DataScopeAndViewTypeVO.class);
|
||||
List<DataScopeViewTypeVO> typeList = this.getViewType();
|
||||
dataScopeAndTypeList.forEach(e -> {
|
||||
e.setViewTypeList(typeList);
|
||||
});
|
||||
return ResponseDTO.succData(dataScopeAndTypeList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前系统存在的数据可见范围
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<DataScopeViewTypeVO> getViewType() {
|
||||
List<DataScopeViewTypeVO> viewTypeList = Lists.newArrayList();
|
||||
DataScopeViewTypeEnum[] enums = DataScopeViewTypeEnum.class.getEnumConstants();
|
||||
DataScopeViewTypeVO dataScopeViewTypeDTO;
|
||||
for (DataScopeViewTypeEnum viewTypeEnum : enums) {
|
||||
dataScopeViewTypeDTO = DataScopeViewTypeVO.builder().viewType(viewTypeEnum.getType()).viewTypeLevel(viewTypeEnum.getLevel()).viewTypeName(viewTypeEnum.getName()).build();
|
||||
viewTypeList.add(dataScopeViewTypeDTO);
|
||||
}
|
||||
Comparator<DataScopeViewTypeVO> comparator = (h1, h2) -> h1.getViewTypeLevel().compareTo(h2.getViewTypeLevel());
|
||||
viewTypeList.sort(comparator);
|
||||
return viewTypeList;
|
||||
}
|
||||
|
||||
public List<DataScopeDTO> getDataScopeType() {
|
||||
List<DataScopeDTO> dataScopeTypeList = Lists.newArrayList();
|
||||
DataScopeTypeEnum[] enums = DataScopeTypeEnum.class.getEnumConstants();
|
||||
DataScopeDTO dataScopeDTO;
|
||||
for (DataScopeTypeEnum typeEnum : enums) {
|
||||
dataScopeDTO =
|
||||
DataScopeDTO.builder().dataScopeType(typeEnum.getType()).dataScopeTypeDesc(typeEnum.getDesc()).dataScopeTypeName(typeEnum.getName()).dataScopeTypeSort(typeEnum.getSort()).build();
|
||||
dataScopeTypeList.add(dataScopeDTO);
|
||||
}
|
||||
Comparator<DataScopeDTO> comparator = (h1, h2) -> h1.getDataScopeTypeSort().compareTo(h2.getDataScopeTypeSort());
|
||||
dataScopeTypeList.sort(comparator);
|
||||
return dataScopeTypeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个角色的数据范围设置信息
|
||||
*
|
||||
* @param roleId
|
||||
* @return
|
||||
*/
|
||||
public ResponseDTO<List<DataScopeSelectVO>> dataScopeListByRole(Long roleId) {
|
||||
|
||||
List<DataScopeRoleEntity> dataScopeRoleEntityList = dataScopeRoleDao.listByRoleId(roleId);
|
||||
if (CollectionUtils.isEmpty(dataScopeRoleEntityList)) {
|
||||
return ResponseDTO.succData(Lists.newArrayList());
|
||||
}
|
||||
List<DataScopeSelectVO> dataScopeSelects = SmartBeanUtil.copyList(dataScopeRoleEntityList, DataScopeSelectVO.class);
|
||||
return ResponseDTO.succData(dataScopeSelects);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量设置某个角色的数据范围设置信息
|
||||
*
|
||||
* @param batchSetRoleDTO
|
||||
* @return
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseDTO<String> dataScopeBatchSet(DataScopeBatchSetRoleDTO batchSetRoleDTO) {
|
||||
List<DataScopeBatchSetDTO> batchSetList = batchSetRoleDTO.getBatchSetList();
|
||||
if (CollectionUtils.isEmpty(batchSetList)) {
|
||||
return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM, "缺少配置信息");
|
||||
}
|
||||
List<DataScopeRoleEntity> dataScopeRoleEntityList = SmartBeanUtil.copyList(batchSetList, DataScopeRoleEntity.class);
|
||||
dataScopeRoleEntityList.forEach(e -> e.setRoleId(batchSetRoleDTO.getRoleId()));
|
||||
dataScopeRoleDao.deleteByRoleId(batchSetRoleDTO.getRoleId());
|
||||
dataScopeRoleDao.batchInsert(dataScopeRoleEntityList);
|
||||
return ResponseDTO.succ();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.service;
|
||||
|
||||
import com.gangquan360.smartadmin.common.anno.DataScope;
|
||||
import com.gangquan360.smartadmin.module.datascope.constant.DataScopeWhereInTypeEnum;
|
||||
import com.gangquan360.smartadmin.module.datascope.domain.dto.DataScopeSqlConfigDTO;
|
||||
import com.gangquan360.smartadmin.module.login.domain.RequestTokenBO;
|
||||
import com.gangquan360.smartadmin.util.SmartRequestTokenUtil;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.MethodAnnotationsScanner;
|
||||
import org.reflections.util.ClasspathHelper;
|
||||
import org.reflections.util.ConfigurationBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/29 0029 上午 10:12
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Service
|
||||
public class DataScopeSqlConfigService {
|
||||
|
||||
private ConcurrentHashMap<String, DataScopeSqlConfigDTO> dataScopeMethodMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Autowired
|
||||
private DataScopeViewService dataScopeViewService;
|
||||
|
||||
@Value("${swagger.packAge}")
|
||||
private String scanPackage;
|
||||
|
||||
/**
|
||||
* 注解joinsql 参数
|
||||
*/
|
||||
private static final String EMPLOYEE_PARAM = "#employeeIds";
|
||||
|
||||
private static final String DEPARTMENT_PARAM = "#departmentIds";
|
||||
|
||||
@PostConstruct
|
||||
private void initDataScopeMethodMap() {
|
||||
this.refreshDataScopeMethodMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新 所有添加数据范围注解的接口方法配置<class.method,DataScopeSqlConfigDTO></>
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Map<String, DataScopeSqlConfigDTO> refreshDataScopeMethodMap() {
|
||||
Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(scanPackage)).setScanners(new MethodAnnotationsScanner()));
|
||||
Set<Method> methods = reflections.getMethodsAnnotatedWith(DataScope.class);
|
||||
for (Method method : methods) {
|
||||
DataScope dataScopeAnnotation = method.getAnnotation(DataScope.class);
|
||||
if (dataScopeAnnotation != null) {
|
||||
DataScopeSqlConfigDTO configDTO = new DataScopeSqlConfigDTO();
|
||||
configDTO.setDataScopeType(dataScopeAnnotation.dataScopeType().getType());
|
||||
configDTO.setJoinSql(dataScopeAnnotation.joinSql());
|
||||
configDTO.setWhereIndex(dataScopeAnnotation.whereIndex());
|
||||
dataScopeMethodMap.put(method.getDeclaringClass().getSimpleName() + "." + method.getName(), configDTO);
|
||||
}
|
||||
}
|
||||
return dataScopeMethodMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据调用的方法获取,此方法的配置信息
|
||||
*
|
||||
* @param method
|
||||
* @return
|
||||
*/
|
||||
public DataScopeSqlConfigDTO getSqlConfig(String method) {
|
||||
DataScopeSqlConfigDTO sqlConfigDTO = this.dataScopeMethodMap.get(method);
|
||||
return sqlConfigDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装需要拼接的sql
|
||||
*
|
||||
* @param sqlConfigDTO
|
||||
* @return
|
||||
*/
|
||||
public String getJoinSql(DataScopeSqlConfigDTO sqlConfigDTO) {
|
||||
Integer dataScopeType = sqlConfigDTO.getDataScopeType();
|
||||
String joinSql = sqlConfigDTO.getJoinSql();
|
||||
RequestTokenBO requestToken = SmartRequestTokenUtil.getThreadLocalUser();
|
||||
Long employeeId = requestToken.getRequestUserId();
|
||||
if (DataScopeWhereInTypeEnum.EMPLOYEE.getType().equals(sqlConfigDTO.getDataScopeWhereInType())) {
|
||||
List<Long> canViewEmployeeIds = dataScopeViewService.getCanViewEmployeeId(dataScopeType, employeeId);
|
||||
if (CollectionUtils.isEmpty(canViewEmployeeIds)) {
|
||||
return "";
|
||||
}
|
||||
String employeeIds = StringUtils.join(canViewEmployeeIds, ",");
|
||||
String sql = joinSql.replaceAll(EMPLOYEE_PARAM, employeeIds);
|
||||
return sql;
|
||||
}
|
||||
if (DataScopeWhereInTypeEnum.DEPARTMENT.getType().equals(sqlConfigDTO.getDataScopeWhereInType())) {
|
||||
List<Long> canViewDepartmentIds = dataScopeViewService.getCanViewDepartmentId(dataScopeType, employeeId);
|
||||
if (CollectionUtils.isEmpty(canViewDepartmentIds)) {
|
||||
return "";
|
||||
}
|
||||
String departmentIds = StringUtils.join(canViewDepartmentIds, ",");
|
||||
String sql = joinSql.replaceAll(DEPARTMENT_PARAM, departmentIds);
|
||||
return sql;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package com.gangquan360.smartadmin.module.datascope.service;
|
||||
|
||||
import com.gangquan360.smartadmin.module.datascope.DataScopeRoleDao;
|
||||
import com.gangquan360.smartadmin.module.datascope.constant.DataScopeViewTypeEnum;
|
||||
import com.gangquan360.smartadmin.module.datascope.domain.entity.DataScopeRoleEntity;
|
||||
import com.gangquan360.smartadmin.module.department.DepartmentTreeService;
|
||||
import com.gangquan360.smartadmin.module.employee.EmployeeDao;
|
||||
import com.gangquan360.smartadmin.module.employee.domain.dto.EmployeeDTO;
|
||||
import com.gangquan360.smartadmin.module.employee.domain.entity.EmployeeEntity;
|
||||
import com.gangquan360.smartadmin.module.employee.domain.vo.EmployeeVO;
|
||||
import com.gangquan360.smartadmin.module.privilege.service.PrivilegeEmployeeService;
|
||||
import com.gangquan360.smartadmin.module.role.roleemployee.RoleEmployeeDao;
|
||||
import com.gangquan360.smartadmin.module.systemconfig.SystemConfigService;
|
||||
import com.gangquan360.smartadmin.module.systemconfig.constant.SystemConfigEnum;
|
||||
import com.gangquan360.smartadmin.module.systemconfig.domain.dto.SystemConfigDTO;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/28 0028 下午 15:56
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Service
|
||||
public class DataScopeViewService {
|
||||
|
||||
@Autowired
|
||||
private RoleEmployeeDao roleEmployeeDao;
|
||||
|
||||
@Autowired
|
||||
private DataScopeRoleDao dataScopeRoleDao;
|
||||
|
||||
@Autowired
|
||||
private DepartmentTreeService departmentTreeService;
|
||||
|
||||
@Autowired
|
||||
private EmployeeDao employeeDao;
|
||||
|
||||
@Autowired
|
||||
private PrivilegeEmployeeService privilegeEmployeeService;
|
||||
|
||||
/**
|
||||
* 获取某人可以查看的所有人员信息
|
||||
*
|
||||
* @param dataScopeType
|
||||
* @param employeeId
|
||||
* @return
|
||||
*/
|
||||
public List<Long> getCanViewEmployeeId(Integer dataScopeType, Long employeeId) {
|
||||
Integer viewType = this.getEmployeeDataScopeViewType(dataScopeType, employeeId);
|
||||
if (DataScopeViewTypeEnum.ME.getType().equals(viewType)) {
|
||||
return this.getMeEmployeeIdList(employeeId);
|
||||
}
|
||||
if (DataScopeViewTypeEnum.DEPARTMENT.getType().equals(viewType)) {
|
||||
return this.getDepartmentEmployeeIdList(employeeId);
|
||||
}
|
||||
if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB.getType().equals(viewType)) {
|
||||
return this.getDepartmentAndSubEmployeeIdList(employeeId);
|
||||
}
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
public List<Long> getCanViewDepartmentId(Integer dataScopeType, Long employeeId) {
|
||||
Integer viewType = this.getEmployeeDataScopeViewType(dataScopeType, employeeId);
|
||||
if (DataScopeViewTypeEnum.ME.getType().equals(viewType)) {
|
||||
return this.getMeDepartmentIdList(employeeId);
|
||||
}
|
||||
if (DataScopeViewTypeEnum.DEPARTMENT.getType().equals(viewType)) {
|
||||
return this.getMeDepartmentIdList(employeeId);
|
||||
}
|
||||
if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB.getType().equals(viewType)) {
|
||||
return this.getDepartmentAndSubIdList(employeeId);
|
||||
}
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
private List<Long> getMeDepartmentIdList(Long employeeId) {
|
||||
EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
|
||||
return Lists.newArrayList(employeeEntity.getDepartmentId());
|
||||
}
|
||||
|
||||
private List<Long> getDepartmentAndSubIdList(Long employeeId) {
|
||||
EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
|
||||
List<Long> allDepartmentIds = Lists.newArrayList();
|
||||
departmentTreeService.buildIdList(employeeEntity.getDepartmentId(), allDepartmentIds);
|
||||
return allDepartmentIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据员工id 获取各数据范围最大的可见范围 map<dataScopeType,viewType></>
|
||||
*
|
||||
* @param employeeId
|
||||
* @return
|
||||
*/
|
||||
private Integer getEmployeeDataScopeViewType(Integer dataScopeType, Long employeeId) {
|
||||
if (employeeId == null) {
|
||||
return DataScopeViewTypeEnum.ME.getType();
|
||||
}
|
||||
|
||||
if (privilegeEmployeeService.isSuperman(employeeId)) {
|
||||
return DataScopeViewTypeEnum.ALL.getType();
|
||||
}
|
||||
List<Long> roleIdList = roleEmployeeDao.selectRoleIdByEmployeeId(employeeId);
|
||||
//未设置角色 默认本人
|
||||
if (CollectionUtils.isEmpty(roleIdList)) {
|
||||
return DataScopeViewTypeEnum.ME.getType();
|
||||
}
|
||||
//未设置角色数据范围 默认本人
|
||||
List<DataScopeRoleEntity> dataScopeRoleList = dataScopeRoleDao.listByRoleIdList(roleIdList);
|
||||
if (CollectionUtils.isEmpty(dataScopeRoleList)) {
|
||||
return DataScopeViewTypeEnum.ME.getType();
|
||||
}
|
||||
Map<Integer, List<DataScopeRoleEntity>> listMap = dataScopeRoleList.stream().collect(Collectors.groupingBy(DataScopeRoleEntity :: getDataScopeType));
|
||||
List<DataScopeRoleEntity> viewLevelList = listMap.get(dataScopeType);
|
||||
DataScopeRoleEntity maxLevel = viewLevelList.stream().max(Comparator.comparing(e -> DataScopeViewTypeEnum.valueOf(e.getViewType()).getLevel())).get();
|
||||
return maxLevel.getViewType();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本人相关 可查看员工id
|
||||
*
|
||||
* @param employeeId
|
||||
* @return
|
||||
*/
|
||||
private List<Long> getMeEmployeeIdList(Long employeeId) {
|
||||
return Lists.newArrayList(employeeId);
|
||||
}
|
||||
/**
|
||||
* 获取本部门相关 可查看员工id
|
||||
*
|
||||
* @param employeeId
|
||||
* @return
|
||||
*/
|
||||
private List<Long> getDepartmentEmployeeIdList(Long employeeId) {
|
||||
EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
|
||||
List<EmployeeVO> employeeList = employeeDao.getEmployeeIdByDeptId(employeeEntity.getDepartmentId());
|
||||
List<Long> employeeIdList = employeeList.stream().map(e -> e.getId()).collect(Collectors.toList());
|
||||
return employeeIdList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本部门及下属子部门相关 可查看员工id
|
||||
*
|
||||
* @param employeeId
|
||||
* @return
|
||||
*/
|
||||
private List<Long> getDepartmentAndSubEmployeeIdList(Long employeeId) {
|
||||
EmployeeEntity employeeEntity = employeeDao.selectById(employeeId);
|
||||
List<Long> allDepartmentIds = Lists.newArrayList();
|
||||
departmentTreeService.buildIdList(employeeEntity.getDepartmentId(), allDepartmentIds);
|
||||
List<EmployeeDTO> employeeList = employeeDao.getEmployeeIdByDeptIds(allDepartmentIds);
|
||||
List<Long> employeeIdList = employeeList.stream().map(e -> e.getId()).collect(Collectors.toList());
|
||||
return employeeIdList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.gangquan360.smartadmin.module.department;
|
||||
|
||||
import com.gangquan360.smartadmin.common.anno.OperateLog;
|
||||
import com.gangquan360.smartadmin.constant.SwaggerTagConst;
|
||||
import com.gangquan360.smartadmin.common.domain.ResponseDTO;
|
||||
import com.gangquan360.smartadmin.module.department.domain.dto.DepartmentCreateDTO;
|
||||
import com.gangquan360.smartadmin.module.department.domain.dto.DepartmentUpdateDTO;
|
||||
import com.gangquan360.smartadmin.module.department.domain.dto.DepartmentVO;
|
||||
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;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部门管理路由器
|
||||
*
|
||||
* @author listen
|
||||
* @date 2017/12/19 14:29
|
||||
*/
|
||||
@Api(tags = {SwaggerTagConst.Admin.MANAGER_DEPARTMENT})
|
||||
@OperateLog
|
||||
@RestController
|
||||
public class DepartmentController {
|
||||
|
||||
@Autowired
|
||||
private DepartmentService departmentService;
|
||||
|
||||
@ApiOperation(value = "查询部门树形列表", notes = "查询部门列表")
|
||||
@GetMapping("/department/list")
|
||||
public ResponseDTO<List<DepartmentVO>> listDepartment() {
|
||||
return departmentService.listDepartment();
|
||||
}
|
||||
|
||||
@ApiOperation(value = "查询部门及员工列表", notes = "查询部门及员工列表")
|
||||
@GetMapping("/department/listEmployee")
|
||||
public ResponseDTO<List<DepartmentVO>> listDepartmentEmployee() {
|
||||
return departmentService.listAllDepartmentEmployee(null);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "根据部门名称查询部门及员工列表", notes = "根据部门名称查询部门及员工列表")
|
||||
@GetMapping("/department/listEmployeeByDepartmentName")
|
||||
public ResponseDTO<List<DepartmentVO>> listDepartmentEmployee(String departmentName) {
|
||||
return departmentService.listAllDepartmentEmployee(departmentName);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "添加部门", notes = "添加部门")
|
||||
@PostMapping("/department/add")
|
||||
public ResponseDTO<String> addDepartment(@Valid @RequestBody DepartmentCreateDTO departmentCreateDTO) {
|
||||
return departmentService.addDepartment(departmentCreateDTO);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "更新部门信息", notes = "更新部门信息")
|
||||
@PostMapping("/department/update")
|
||||
public ResponseDTO<String> updateDepartment(@Valid @RequestBody DepartmentUpdateDTO departmentUpdateDTO) {
|
||||
return departmentService.updateDepartment(departmentUpdateDTO);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除部门", notes = "删除部门")
|
||||
@PostMapping("/department/delete/{departmentId}")
|
||||
public ResponseDTO<String> delDepartment(@PathVariable("departmentId") Long departmentId) {
|
||||
return departmentService.delDepartment(departmentId);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "获取部门信息", notes = "获取部门")
|
||||
@GetMapping("/department/query/{departmentId}")
|
||||
public ResponseDTO<DepartmentVO> getDepartment(@PathVariable("departmentId") Long departmentId) {
|
||||
return departmentService.getDepartmentById(departmentId);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "查询部门列表", notes = "查询部门列表")
|
||||
@GetMapping("/department/listAll")
|
||||
public ResponseDTO<List<DepartmentVO>> listAll() {
|
||||
return departmentService.listAll();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation(value = "上下移动")
|
||||
@GetMapping("/department/upOrDown/{departmentId}/{swapId}")
|
||||
public ResponseDTO<String> upOrDown(@PathVariable("departmentId") Long departmentId,@PathVariable("swapId") Long swapId) {
|
||||
return departmentService.upOrDown(departmentId,swapId);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "升级")
|
||||
@GetMapping("/department/upgrade/{departmentId}")
|
||||
public ResponseDTO<String> upgrade(@PathVariable("departmentId") Long departmentId) {
|
||||
return departmentService.upgrade(departmentId);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "降级")
|
||||
@GetMapping("/department/downgrade/{departmentId}/{preId}")
|
||||
public ResponseDTO<String> downgrade(@PathVariable("departmentId") Long departmentId,@PathVariable("preId") Long preId) {
|
||||
return departmentService.downgrade(departmentId,preId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.gangquan360.smartadmin.module.department;
|
||||
|
||||
import com.baomidou.mybatisplus.mapper.BaseMapper;
|
||||
import com.gangquan360.smartadmin.module.department.domain.dto.DepartmentVO;
|
||||
import com.gangquan360.smartadmin.module.department.domain.entity.DepartmentEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* t_department dao接口
|
||||
*
|
||||
* @author listen
|
||||
* @date 2017/12/19 10:58
|
||||
*/
|
||||
@Component
|
||||
@Mapper
|
||||
public interface DepartmentDao extends BaseMapper<DepartmentEntity> {
|
||||
|
||||
|
||||
/**
|
||||
* 根据部门id,查询此部门子部门的数量
|
||||
*
|
||||
* @param departmentId
|
||||
* @return int 子部门的数量
|
||||
*/
|
||||
Integer countSubDepartment(@Param("departmentId") Long departmentId);
|
||||
|
||||
/**
|
||||
* 获取全部部门列表
|
||||
*
|
||||
* @return List<DepartmentVO>
|
||||
*/
|
||||
List<DepartmentVO> listAll();
|
||||
|
||||
/**
|
||||
* 功能描述: 根据父部门id查询
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
* @auther yandanyang
|
||||
* @date 2018/8/25 0025 上午 9:46
|
||||
*/
|
||||
List<DepartmentVO> selectByParentId(@Param("departmentId") Long departmentId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.gangquan360.smartadmin.module.department;
|
||||
|
||||
import com.gangquan360.smartadmin.common.constant.ResponseCodeConst;
|
||||
|
||||
/**
|
||||
* 部门返回信息常量类
|
||||
* 2001 - 2999
|
||||
*
|
||||
* @author listen
|
||||
* @date 2017/12/19 18:52
|
||||
*/
|
||||
public class DepartmentResponseCodeConst extends ResponseCodeConst {
|
||||
|
||||
/**
|
||||
* 部门不存在 1001
|
||||
*/
|
||||
public static final DepartmentResponseCodeConst DEPT_NOT_EXISTS = new DepartmentResponseCodeConst(2001, "部门不存在!");
|
||||
|
||||
/**
|
||||
* 当前部门有子级部门 不能删除 10003
|
||||
*/
|
||||
public static final DepartmentResponseCodeConst CANNOT_DEL_DEPARTMENT_WITH_CHILD = new
|
||||
DepartmentResponseCodeConst(2002, "当前部门有子级部门,无法删除!");
|
||||
|
||||
/**
|
||||
* 当前部门有员工 不能删除 10004
|
||||
*/
|
||||
public static final DepartmentResponseCodeConst CANNOT_DEL_DEPARTMENT_WITH_EMPLOYEE = new
|
||||
DepartmentResponseCodeConst(2003, "当前部门有员工,无法删除!");
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static final DepartmentResponseCodeConst PARENT_ID_ERROR = new DepartmentResponseCodeConst(2004, "上级部门id不能等于当前部门id");
|
||||
|
||||
public DepartmentResponseCodeConst(int code, String msg) {
|
||||
super(code, msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
package com.gangquan360.smartadmin.module.department;
|
||||
|
||||
import com.gangquan360.smartadmin.common.domain.ResponseDTO;
|
||||
import com.gangquan360.smartadmin.module.department.domain.dto.DepartmentCreateDTO;
|
||||
import com.gangquan360.smartadmin.module.department.domain.dto.DepartmentUpdateDTO;
|
||||
import com.gangquan360.smartadmin.module.department.domain.dto.DepartmentVO;
|
||||
import com.gangquan360.smartadmin.module.department.domain.entity.DepartmentEntity;
|
||||
import com.gangquan360.smartadmin.module.employee.EmployeeDao;
|
||||
import com.gangquan360.smartadmin.module.employee.domain.dto.EmployeeDTO;
|
||||
import com.gangquan360.smartadmin.util.SmartBeanUtil;
|
||||
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.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 部门管理业务类
|
||||
*
|
||||
* @author listen
|
||||
* @date 2017/12/19 14:25
|
||||
*/
|
||||
@Service
|
||||
public class DepartmentService {
|
||||
|
||||
@Autowired
|
||||
private DepartmentDao departmentDao;
|
||||
|
||||
@Autowired
|
||||
private EmployeeDao employeeDao;
|
||||
|
||||
@Autowired
|
||||
private DepartmentTreeService departmentTreeService;
|
||||
|
||||
/**
|
||||
* 获取部门树形结构
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ResponseDTO<List<DepartmentVO>> listDepartment() {
|
||||
List<DepartmentVO> departmentVOList = departmentDao.listAll();
|
||||
List<DepartmentVO> result = departmentTreeService.buildTree(departmentVOList);
|
||||
return ResponseDTO.succData(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有部门和员工信息
|
||||
*
|
||||
* @param departmentName
|
||||
* @return
|
||||
*/
|
||||
public ResponseDTO<List<DepartmentVO>> listAllDepartmentEmployee(String departmentName) {
|
||||
|
||||
// 获取全部部门列表
|
||||
List<DepartmentVO> departmentVOList = departmentDao.listAll();
|
||||
if (StringUtils.isNotBlank(departmentName)) {
|
||||
// 检索条件不为空的时候 过滤部门列表
|
||||
departmentVOList = filterDepartment(departmentVOList, departmentName);
|
||||
}
|
||||
|
||||
Map<Long, DepartmentVO> departmentMap = departmentVOList.stream().collect(Collectors.toMap(DepartmentVO :: getId, Function.identity()));
|
||||
// 获取全部员工列表
|
||||
List<EmployeeDTO> employeeList = employeeDao.listAll();
|
||||
employeeList.forEach(employeeDTO -> {
|
||||
|
||||
DepartmentVO departmentVO = departmentMap.get(employeeDTO.getDepartmentId());
|
||||
if (null == departmentVO) {
|
||||
return;
|
||||
}
|
||||
List<EmployeeDTO> employeeDTOList = departmentVO.getEmployees();
|
||||
if (null == employeeDTOList) {
|
||||
employeeDTOList = new ArrayList<>();
|
||||
}
|
||||
employeeDTOList.add(employeeDTO);
|
||||
departmentVO.setEmployees(employeeDTOList);
|
||||
});
|
||||
List<DepartmentVO> result = departmentTreeService.buildTree(departmentVOList);
|
||||
return ResponseDTO.succData(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤部门名称,获取过滤后的结果
|
||||
*
|
||||
* @author lidoudou
|
||||
* @date 2019/4/28 20:17
|
||||
*/
|
||||
private List<DepartmentVO> filterDepartment(List<DepartmentVO> departmentVOList, String departmentName) {
|
||||
Map<Long, DepartmentVO> departmentMap = new HashMap<>();
|
||||
departmentVOList.forEach(item -> {
|
||||
if (item.getName().indexOf(departmentName) < 0) {
|
||||
return;
|
||||
}
|
||||
// 当前部门包含关键字
|
||||
departmentMap.put(item.getId(), item);
|
||||
Long parentId = item.getParentId();
|
||||
if (null != parentId) {
|
||||
List<DepartmentVO> filterResult = new ArrayList<>();
|
||||
getParentDepartment(departmentVOList, parentId, filterResult);
|
||||
for (DepartmentVO dto : filterResult) {
|
||||
if (! departmentMap.containsKey(dto.getId())) {
|
||||
departmentMap.put(dto.getId(), dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return departmentMap.values().stream().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<DepartmentVO> getParentDepartment(List<DepartmentVO> departmentVOList, Long parentId, List<DepartmentVO> result) {
|
||||
List<DepartmentVO> deptList = departmentVOList.stream().filter(e -> e.getId().equals(parentId)).collect(Collectors.toList());
|
||||
for (DepartmentVO item : deptList) {
|
||||
result.add(item);
|
||||
if (item.getParentId() != 0 && item.getParentId() != null) {
|
||||
result.addAll(getParentDepartment(departmentVOList, item.getParentId(), result));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增添加部门
|
||||
*
|
||||
* @param departmentCreateDTO
|
||||
* @return AjaxResult
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseDTO<String> addDepartment(DepartmentCreateDTO departmentCreateDTO) {
|
||||
DepartmentEntity departmentEntity = SmartBeanUtil.copy(departmentCreateDTO, DepartmentEntity.class);
|
||||
departmentEntity.setSort(0L);
|
||||
departmentDao.insert(departmentEntity);
|
||||
departmentEntity.setSort(departmentEntity.getId());
|
||||
departmentDao.updateById(departmentEntity);
|
||||
return ResponseDTO.succ();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新部门信息
|
||||
*
|
||||
* @param updateDTO
|
||||
* @return AjaxResult<String>
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseDTO<String> updateDepartment(DepartmentUpdateDTO updateDTO) {
|
||||
if (updateDTO.getParentId() == null) {
|
||||
return ResponseDTO.wrap(DepartmentResponseCodeConst.PARENT_ID_ERROR);
|
||||
}
|
||||
DepartmentEntity entity = departmentDao.selectById(updateDTO.getId());
|
||||
if (entity == null) {
|
||||
return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS);
|
||||
}
|
||||
DepartmentEntity departmentEntity = SmartBeanUtil.copy(updateDTO, DepartmentEntity.class);
|
||||
departmentEntity.setSort(entity.getSort());
|
||||
departmentDao.updateById(departmentEntity);
|
||||
return ResponseDTO.succ();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id删除部门
|
||||
* 1、需要判断当前部门是否有子部门,有子部门则不允许删除
|
||||
* 2、需要判断当前部门是否有员工,有员工则不能删除
|
||||
*
|
||||
* @param departmentId
|
||||
* @return AjaxResult<String>
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseDTO<String> delDepartment(Long departmentId) {
|
||||
// 是否有子级部门
|
||||
int subDepartmentNum = departmentDao.countSubDepartment(departmentId);
|
||||
if (subDepartmentNum > 0) {
|
||||
return ResponseDTO.wrap(DepartmentResponseCodeConst.CANNOT_DEL_DEPARTMENT_WITH_CHILD);
|
||||
}
|
||||
|
||||
// 是否有员工
|
||||
int employeeNum = employeeDao.countByDepartmentId(departmentId);
|
||||
if (employeeNum > 0) {
|
||||
return ResponseDTO.wrap(DepartmentResponseCodeConst.CANNOT_DEL_DEPARTMENT_WITH_EMPLOYEE);
|
||||
}
|
||||
departmentDao.deleteById(departmentId);
|
||||
return ResponseDTO.succ();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id获取部门信息
|
||||
*
|
||||
* @param departmentId
|
||||
* @return AjaxResult<DepartmentVO>
|
||||
*/
|
||||
public ResponseDTO<DepartmentVO> getDepartmentById(Long departmentId) {
|
||||
DepartmentEntity departmentEntity = departmentDao.selectById(departmentId);
|
||||
if (departmentEntity == null) {
|
||||
return ResponseDTO.wrap(DepartmentResponseCodeConst.DEPT_NOT_EXISTS);
|
||||
}
|
||||
DepartmentVO departmentVO = SmartBeanUtil.copy(departmentEntity, DepartmentVO.class);
|
||||
return ResponseDTO.succData(departmentVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有部门
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ResponseDTO<List<DepartmentVO>> listAll() {
|
||||
List<DepartmentVO> departmentVOList = departmentDao.listAll();
|
||||
return ResponseDTO.succData(departmentVOList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上下移动
|
||||
*
|
||||
* @param departmentId
|
||||
* @param swapId
|
||||
* @return
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseDTO<String> upOrDown(Long departmentId, Long swapId) {
|
||||
DepartmentEntity departmentEntity = departmentDao.selectById(departmentId);
|
||||
if (departmentEntity == null) {
|
||||
return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS);
|
||||
}
|
||||
DepartmentEntity swapEntity = departmentDao.selectById(swapId);
|
||||
if (swapEntity == null) {
|
||||
return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS);
|
||||
}
|
||||
Long departmentSort = departmentEntity.getSort();
|
||||
departmentEntity.setSort(swapEntity.getSort());
|
||||
departmentDao.updateById(departmentEntity);
|
||||
swapEntity.setSort(departmentSort);
|
||||
departmentDao.updateById(swapEntity);
|
||||
return ResponseDTO.succ();
|
||||
}
|
||||
|
||||
/**
|
||||
* 部门升级
|
||||
*
|
||||
* @param departmentId
|
||||
* @return
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseDTO<String> upgrade(Long departmentId) {
|
||||
DepartmentEntity departmentEntity = departmentDao.selectById(departmentId);
|
||||
if (departmentEntity == null) {
|
||||
return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS);
|
||||
}
|
||||
if (departmentEntity.getParentId() == null || departmentEntity.getParentId().equals(0)) {
|
||||
return ResponseDTO.wrap(DepartmentResponseCodeConst.ERROR_PARAM, "此部门已经是根节点无法移动");
|
||||
}
|
||||
DepartmentEntity parentEntity = departmentDao.selectById(departmentEntity.getParentId());
|
||||
|
||||
departmentEntity.setParentId(parentEntity.getParentId());
|
||||
departmentDao.updateById(departmentEntity);
|
||||
return ResponseDTO.succ();
|
||||
}
|
||||
|
||||
/**
|
||||
* 部门降级
|
||||
*
|
||||
* @param departmentId
|
||||
* @param preId
|
||||
* @return
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseDTO<String> downgrade(Long departmentId, Long preId) {
|
||||
DepartmentEntity departmentEntity = departmentDao.selectById(departmentId);
|
||||
if (departmentEntity == null) {
|
||||
return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS);
|
||||
}
|
||||
DepartmentEntity preEntity = departmentDao.selectById(preId);
|
||||
if (preEntity == null) {
|
||||
return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS);
|
||||
}
|
||||
departmentEntity.setParentId(preEntity.getId());
|
||||
departmentDao.updateById(departmentEntity);
|
||||
return ResponseDTO.succ();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.gangquan360.smartadmin.module.department;
|
||||
|
||||
import com.gangquan360.smartadmin.module.department.domain.dto.DepartmentVO;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2018 1024lab.netInc. All rights reserved.
|
||||
* @date 2019/4/29 0029 下午 13:52
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Service
|
||||
public class DepartmentTreeService {
|
||||
|
||||
@Autowired
|
||||
private DepartmentDao departmentDao;
|
||||
|
||||
/**
|
||||
* 构建部门树结构
|
||||
* @param departmentVOList
|
||||
* @return
|
||||
*/
|
||||
public List<DepartmentVO> buildTree(List<DepartmentVO> departmentVOList) {
|
||||
if(CollectionUtils.isEmpty(departmentVOList)){
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
List<DepartmentVO> list = departmentVOList.stream().filter(e -> e.getParentId() == null || e.getParentId() == 0).collect(Collectors.toList());
|
||||
if(CollectionUtils.isEmpty(list)){
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
this.buildTree(list,departmentVOList);
|
||||
return list;
|
||||
}
|
||||
|
||||
private void buildTree(List<DepartmentVO> nodeList,List<DepartmentVO> departmentVOList){
|
||||
int nodeSize = nodeList.size();
|
||||
for(int i =0 ;i< nodeSize;i++){
|
||||
int preIndex = i-1;
|
||||
int nextIndex = i+1;
|
||||
DepartmentVO node = nodeList.get(i);
|
||||
if(preIndex>-1){
|
||||
node.setPreId(nodeList.get(preIndex).getId());
|
||||
}
|
||||
if(nextIndex<nodeSize){
|
||||
node.setNextId(nodeList.get(nextIndex).getId());
|
||||
}
|
||||
buildTree(node, departmentVOList);
|
||||
}
|
||||
}
|
||||
|
||||
private void buildTree(DepartmentVO node, List<DepartmentVO> departmentVOList) {
|
||||
List<DepartmentVO> children = getChildren(node, departmentVOList);
|
||||
if (CollectionUtils.isNotEmpty(children)) {
|
||||
node.setChildrenDepartment(children);
|
||||
this.buildTree(children,departmentVOList);
|
||||
}
|
||||
}
|
||||
|
||||
private List<DepartmentVO> getChildren(DepartmentVO node, List<DepartmentVO> departmentVOList) {
|
||||
Long id = node.getId();
|
||||
return departmentVOList.stream().filter(e -> id.equals(e.getParentId())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 通过部门id,获取当前以及下属部门
|
||||
*/
|
||||
public void buildIdList(Long deptId, List<Long> result) {
|
||||
List<DepartmentVO> departmentVOList = departmentDao.listAll();
|
||||
result.add(deptId);
|
||||
if (null == deptId) {
|
||||
result.addAll(departmentVOList.stream().map(DepartmentVO::getId).collect(Collectors.toList()));
|
||||
return;
|
||||
}
|
||||
List<DepartmentVO> children = getChildrenIdList(deptId, departmentVOList);
|
||||
if (!children.isEmpty()) {
|
||||
result.addAll(children.stream().map(DepartmentVO::getId).collect(Collectors.toList()));
|
||||
for (DepartmentVO child : children) {
|
||||
buildTree(child, departmentVOList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<DepartmentVO> getChildrenIdList(Long deptId, List<DepartmentVO> departmentVOList) {
|
||||
return departmentVOList.stream().filter(e -> deptId.equals(e.getParentId())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.gangquan360.smartadmin.module.department.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
*
|
||||
* [ ]
|
||||
*
|
||||
* @version 1.0
|
||||
* @since JDK1.8
|
||||
* @author yandanyang
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
|
||||
* @date
|
||||
*/
|
||||
@Data
|
||||
public class DepartmentCreateDTO {
|
||||
|
||||
|
||||
@ApiModelProperty("部门名称")
|
||||
@Length(min = 1, max = 50, message = "请输入正确的部门名称(1-50个字符)")
|
||||
@NotNull(message = "请输入正确的部门名称(1-50个字符)")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("部门简称")
|
||||
private String shortName;
|
||||
|
||||
@ApiModelProperty("部门负责人id")
|
||||
private Long managerId;
|
||||
|
||||
@ApiModelProperty("上级部门id (可选)")
|
||||
private Long parentId;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.gangquan360.smartadmin.module.department.domain.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* [ ]
|
||||
*
|
||||
* @author yandanyang
|
||||
* @version 1.0
|
||||
* @company 1024lab.net
|
||||
* @copyright (c) 2019 1024lab.netInc. All rights reserved.
|
||||
* @date
|
||||
* @since JDK1.8
|
||||
*/
|
||||
@Data
|
||||
public class DepartmentUpdateDTO extends DepartmentCreateDTO {
|
||||
|
||||
@ApiModelProperty("部门id")
|
||||
@NotNull(message = "部门id不能为空")
|
||||
private Long id;
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user