增加 系统字典

v1.4.1
Parker 5 years ago
parent 88d2830fdb
commit a8ae3e0b1d

@ -5,10 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.springframework.http.HttpStatus;
import java.io.Serializable;
@ -32,48 +29,38 @@ public class ResultVo<T> implements Serializable {
/** 成功状态 */
@ApiModelProperty(value = "成功状态")
@JsonProperty("success")
private boolean success;
/** 消息 */
@ApiModelProperty(value = "消息")
@JsonProperty("msg")
private String msg;
/** 状态码 */
@ApiModelProperty(value = "状态码")
@JsonProperty("code")
private Integer code;
/** 时间戳 */
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
@ApiModelProperty(value = "时间戳")
private long timestamp;
@JsonProperty("timestamp")
private Long timestamp;
/** 数据对象 */
@ApiModelProperty(value = "数据")
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
@JsonProperty("data")
private T data;
public T getData() {
return data;
}
/**
*
* @param data
* @return ResultVo<T>
*/
public ResultVo<T> put(T data) {
public ResultVo<T> setData(T data) {
this.data = data;
return this;
}
/**
*
* @return T
*/
public T get(){
return this.data;
}
/**
* Json
* @return String
@ -127,7 +114,7 @@ public class ResultVo<T> implements Serializable {
@JsonIgnore//返回对象时忽略此属性
public static <T> ResultVo<T> success(T data) {
ResultVo<T> ret = new ResultVo<>();
ret.put(data);
ret.setData(data);
return ret;
}
@ -141,7 +128,7 @@ public class ResultVo<T> implements Serializable {
@JsonIgnore//返回对象时忽略此属性
public static <T> ResultVo<T> success(String msg, T data) {
ResultVo<T> ret = new ResultVo<>();
ret.put(data);
ret.setData(data);
return ret;
}
@ -187,7 +174,7 @@ public class ResultVo<T> implements Serializable {
ResultVo<T> ret = new ResultVo<>();
ret.setMsg(msg);
ret.setCode(code);
ret.put(data);
ret.setData(data);
ret.setSuccess(false);
return ret;
}

@ -82,7 +82,6 @@ public abstract class ApiWrapper implements Serializable {
/** 乐观锁 版本 */
@ApiModelProperty(value = "版本")
@ExcelIgnore
@CellStyleFormat
@Version
private Integer version;

@ -4,6 +4,7 @@ import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ReflectUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.api.msg.ValidationMsg;
import org.opsli.api.wrapper.system.dict.SysDictModel;
import org.opsli.common.annotation.validation.ValidationArgs;
@ -79,6 +80,8 @@ public final class ValidationUtil {
fieldName = annotation.value();
}
String value = String.valueOf(fieldValue);
// 循环验证
for (ValiArgsType type : types) {
try {
@ -94,7 +97,8 @@ public final class ValidationUtil {
break;
// 字母,数字和下划线
case IS_GENERAL:
boolean general = Validator.isGeneral(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean general = Validator.isGeneral(value);
if(!general){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_GENERAL;
msg.setFieldName(fieldName);
@ -103,7 +107,8 @@ public final class ValidationUtil {
break;
// 数字
case IS_NUMBER:
boolean number = Validator.isNumber(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean number = Validator.isNumber(value);
if(!number){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_NUMBER;
msg.setFieldName(fieldName);
@ -112,7 +117,8 @@ public final class ValidationUtil {
break;
// 纯字母
case IS_LETTER:
boolean letter = Validator.isLetter(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean letter = Validator.isLetter(value);
if(!letter){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_LETTER;
msg.setFieldName(fieldName);
@ -121,7 +127,8 @@ public final class ValidationUtil {
break;
// 大写
case IS_UPPER_CASE:
boolean upperCase = Validator.isUpperCase(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean upperCase = Validator.isUpperCase(value);
if(!upperCase){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_UPPER_CASE;
msg.setFieldName(fieldName);
@ -130,7 +137,8 @@ public final class ValidationUtil {
break;
// 小写
case IS_LOWER_CASE:
boolean lowerCase = Validator.isLowerCase(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean lowerCase = Validator.isLowerCase(value);
if(!lowerCase){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_LOWER_CASE;
msg.setFieldName(fieldName);
@ -139,7 +147,8 @@ public final class ValidationUtil {
break;
// IPV4
case IS_IPV4:
boolean ipv4 = Validator.isIpv4(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean ipv4 = Validator.isIpv4(value);
if(!ipv4){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_IPV4;
msg.setFieldName(fieldName);
@ -148,7 +157,8 @@ public final class ValidationUtil {
break;
// 金额
case IS_MONEY:
boolean money = Validator.isMoney(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean money = Validator.isMoney(value);
if(!money){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_MONEY;
msg.setFieldName(fieldName);
@ -157,7 +167,8 @@ public final class ValidationUtil {
break;
// 邮箱
case IS_EMAIL:
boolean email = Validator.isEmail(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean email = Validator.isEmail(value);
if(!email){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_EMAIL;
msg.setFieldName(fieldName);
@ -166,7 +177,8 @@ public final class ValidationUtil {
break;
// 手机号
case IS_MOBILE:
boolean mobile = Validator.isMobile(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean mobile = Validator.isMobile(value);
if(!mobile){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_MOBILE;
msg.setFieldName(fieldName);
@ -175,7 +187,8 @@ public final class ValidationUtil {
break;
// 18位身份证
case IS_CITIZENID:
boolean citizenId = Validator.isCitizenId(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean citizenId = Validator.isCitizenId(value);
if(!citizenId){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_CITIZENID;
msg.setFieldName(fieldName);
@ -184,7 +197,8 @@ public final class ValidationUtil {
break;
// 邮编
case IS_ZIPCODE:
boolean zipCode = Validator.isZipCode(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean zipCode = Validator.isZipCode(value);
if(!zipCode){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_ZIPCODE;
msg.setFieldName(fieldName);
@ -193,7 +207,8 @@ public final class ValidationUtil {
break;
// URL
case IS_URL:
boolean url = Validator.isUrl(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean url = Validator.isUrl(value);
if(!url){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_URL;
msg.setFieldName(fieldName);
@ -202,7 +217,8 @@ public final class ValidationUtil {
break;
// 汉字
case IS_CHINESE:
boolean chinese = Validator.isChinese(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean chinese = Validator.isChinese(value);
if(!chinese){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_CHINESE;
msg.setFieldName(fieldName);
@ -211,7 +227,8 @@ public final class ValidationUtil {
break;
// 汉字,字母,数字和下划线
case IS_GENERAL_WITH_CHINESE:
boolean generalWithChinese = Validator.isGeneralWithChinese(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean generalWithChinese = Validator.isGeneralWithChinese(value);
if(!generalWithChinese){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_GENERAL_WITH_CHINESE;
msg.setFieldName(fieldName);
@ -220,7 +237,8 @@ public final class ValidationUtil {
break;
// MAC地址
case IS_MAC:
boolean mac = Validator.isMac(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean mac = Validator.isMac(value);
if(!mac){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_MAC;
msg.setFieldName(fieldName);
@ -229,7 +247,8 @@ public final class ValidationUtil {
break;
// 中国车牌
case IS_PLATE_NUMBER:
boolean plateNumber = Validator.isPlateNumber(String.valueOf(fieldValue));
if(StringUtils.isEmpty(value) || "null".equals(value)) break;
boolean plateNumber = Validator.isPlateNumber(value);
if(!plateNumber){
ValidationMsg msg = ValidationMsg.EXCEPTION_IS_PLATE_NUMBER;
msg.setFieldName(fieldName);

@ -0,0 +1,112 @@
package org.opsli.api.web.system.dict;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.wrapper.system.dict.SysDictModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.web
* @Author: Parker
* @CreateTime: 2020-09-13 17:40
* @Description: API
*
* API @GetMapping @PostMapping
* Mapping Controller
*
*
*
*
*/
public interface DictApi {
/** 标题 */
String TITLE = "数据字典";
/**
*
* @param model
* @return ResultVo
*/
@GetMapping("/get")
ResultVo<SysDictModel> get(SysDictModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
);
/**
*
* @param model
* @return ResultVo
*/
@PostMapping("/insert")
ResultVo<?> insert(SysDictModel model);
/**
*
* @param model
* @return ResultVo
*/
@PostMapping("/update")
ResultVo<?> update(SysDictModel model);
/**
*
* @param id ID
* @return ResultVo
*/
@PostMapping("/del")
ResultVo<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String[] ids);
/**
* Excel
* @param request request
* @param response response
* @return ResultVo
*/
@GetMapping("/exportExcel")
ResultVo<?> exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@GetMapping("/exportImport")
ResultVo<?> excelImport(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
* @return ResultVo
*/
@GetMapping("/exportImport/template")
ResultVo<?> importTemplate(HttpServletResponse response);
}

@ -0,0 +1,125 @@
package org.opsli.api.web.system.dict;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.wrapper.system.dict.SysDictDetailModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.web
* @Author: Parker
* @CreateTime: 2020-09-13 17:40
* @Description: API
*
* API @GetMapping @PostMapping
* Mapping Controller
*
*
*
*
*/
public interface DictDetailApi {
/** 标题 */
String TITLE = "数据字典明细";
/**
*
* @param model
* @return ResultVo
*/
@GetMapping("/get")
ResultVo<SysDictDetailModel> get(SysDictDetailModel model);
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
*/
@GetMapping("/findPage")
ResultVo<?> findPage(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest request
);
/**
*
* @param model
* @return ResultVo
*/
@PostMapping("/insert")
ResultVo<?> insert(SysDictDetailModel model);
/**
*
* @param model
* @return ResultVo
*/
@PostMapping("/update")
ResultVo<?> update(SysDictDetailModel model);
/**
*
* @param id ID
* @return ResultVo
*/
@PostMapping("/del")
ResultVo<?> del(String id);
/**
*
* @param ids ID
* @return ResultVo
*/
@PostMapping("/delAll")
ResultVo<?> delAll(String[] ids);
/**
* Excel
* @param request request
* @param response response
* @return ResultVo
*/
@GetMapping("/exportExcel")
ResultVo<?> exportExcel(HttpServletRequest request, HttpServletResponse response);
/**
* Excel
* @param request request
* @return ResultVo
*/
@GetMapping("/exportImport")
ResultVo<?> excelImport(MultipartHttpServletRequest request);
/**
* Excel
* @param response response
* @return ResultVo
*/
@GetMapping("/exportImport/template")
ResultVo<?> importTemplate(HttpServletResponse response);
// ================================
/**
*
*
* @param typeCode
* @return
*/
@GetMapping("/findListByTypeCode")
ResultVo<List<SysDictDetailModel>> findListByTypeCode(String typeCode);
}

@ -60,7 +60,6 @@ public interface TestApi {
*
* @return
*/
@ApiOperation(value = "新增数据", notes = "新增数据")
@GetMapping("/insert")
ResultVo<TestModel> insert(TestModel entity);
@ -101,7 +100,7 @@ public interface TestApi {
* @return
*/
@GetMapping("/findList")
ResultVo<List<TestModel>> findList();
ResultVo<List<TestModel>> findList(HttpServletRequest request);
/**

@ -0,0 +1,29 @@
package org.opsli.api.wrapper.system.dict;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.entity
* @Author: Parker
* @CreateTime: 2020-09-16 17:33
* @Description: -
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class DictModel {
/** 类型编号 - 冗余 */
private String typeCode;
/** 字典名称 */
private String dictName;
/** 字典值 */
private String dictValue;
/** 消息 */
private SysDictDetailModel model;
}

@ -0,0 +1,83 @@
package org.opsli.api.wrapper.system.dict;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.common.annotation.validation.ValidationArgs;
import org.opsli.common.annotation.validation.ValidationArgsMax;
import org.opsli.common.enums.ValiArgsType;
import org.opsli.plugins.excel.annotation.CellStyleFormat;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.entity
* @Author: Parker
* @CreateTime: 2020-09-16 17:33
* @Description: -
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class SysDictDetailModel extends ApiWrapper {
/** 字典ID */
@ApiModelProperty(value = "字典类型ID")
@ExcelIgnore
@ValidationArgs(ValiArgsType.IS_NOT_NULL)
private String typeId;
/** 类型编号 - 冗余 */
@ApiModelProperty(value = "字典类型Code")
@ExcelIgnore
// 验证器
@ValidationArgs({ValiArgsType.IS_NOT_NULL, ValiArgsType.IS_GENERAL})
@ValidationArgsMax(120)
private String typeCode;
/** 字典名称 */
@ApiModelProperty(value = "字典名称")
@ExcelProperty(value = "字典名称", order = 1)
@CellStyleFormat
// 验证器
@ValidationArgs({ValiArgsType.IS_NOT_NULL, ValiArgsType.IS_GENERAL_WITH_CHINESE})
@ValidationArgsMax(120)
private String dictName;
/** 字典值 */
@ApiModelProperty(value = "字典值")
@ExcelProperty(value = "字典值", order = 2)
@CellStyleFormat
// 验证器
@ValidationArgs({ValiArgsType.IS_NOT_NULL})
@ValidationArgsMax(120)
private String dictValue;
/** 是否内置数据 */
@ApiModelProperty(value = "是否内置数据")
@ExcelProperty(value = "是否内置数据", order = 2)
@CellStyleFormat
// 验证器
@ValidationArgs({ValiArgsType.IS_NOT_NULL})
private Character izLock;
/** 排序 */
@ApiModelProperty(value = "排序")
@ExcelProperty(value = "排序", order = 2)
@CellStyleFormat
// 验证器
@ValidationArgs({ValiArgsType.IS_NOT_NULL, ValiArgsType.IS_NUMBER})
private Integer sortNo;
/** 备注 */
@ApiModelProperty(value = "备注")
@ExcelProperty(value = "备注", order = 2)
@CellStyleFormat
// 验证器
@ValidationArgsMax(255)
private String remark;
}

@ -0,0 +1,61 @@
package org.opsli.api.wrapper.system.dict;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.common.annotation.validation.ValidationArgs;
import org.opsli.common.annotation.validation.ValidationArgsMax;
import org.opsli.common.enums.ValiArgsType;
import org.opsli.plugins.excel.annotation.CellStyleFormat;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.entity
* @Author: Parker
* @CreateTime: 2020-09-16 17:33
* @Description:
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class SysDictModel extends ApiWrapper {
/** 字典类型编号 */
@ApiModelProperty(value = "字典类型编号")
@ExcelProperty(value = "字典类型编号", order = 1)
@CellStyleFormat
// 验证器
@ValidationArgs({ValiArgsType.IS_NOT_NULL, ValiArgsType.IS_GENERAL})
@ValidationArgsMax(120)
private String typeCode;
/** 字典类型名称 */
@ApiModelProperty(value = "字典类型名称")
@ExcelProperty(value = "字典类型名称", order = 2)
@CellStyleFormat
// 验证器
@ValidationArgs({ValiArgsType.IS_NOT_NULL, ValiArgsType.IS_GENERAL_WITH_CHINESE})
@ValidationArgsMax(120)
private String typeName;
/** 是否内置数据 */
@ApiModelProperty(value = "是否内置数据")
@ExcelProperty(value = "是否内置数据", order = 3)
@CellStyleFormat
// 验证器
@ValidationArgs(ValiArgsType.IS_NOT_NULL)
private Character izLock;
/** 备注 */
@ApiModelProperty(value = "备注")
@ExcelProperty(value = "备注", order = 4)
@CellStyleFormat
// 验证器
@ValidationArgsMax(255)
private String remark;
}

@ -15,10 +15,10 @@ import java.util.Map;
* @author Parker
*
*/
public class ResultVo extends HashMap<String,Object> implements Serializable {
public class ResultVoMap extends HashMap<String,Object> implements Serializable {
public ResultVo(){
public ResultVoMap(){
this.put("success", true);
this.put("code", HttpStatus.OK.value());
this.put("msg", "操作成功");
@ -57,39 +57,39 @@ public class ResultVo extends HashMap<String,Object> implements Serializable {
// -------------------------------------------
@JsonIgnore//返回对象时忽略此属性
public static ResultVo success(String msg) {
ResultVo j = new ResultVo();
public static ResultVoMap success(String msg) {
ResultVoMap j = new ResultVoMap();
j.setMsg(msg);
return j;
}
@JsonIgnore//返回对象时忽略此属性
public static ResultVo error(String msg) {
ResultVo j = new ResultVo();
public static ResultVoMap error(String msg) {
ResultVoMap j = new ResultVoMap();
j.setSuccess(false);
j.setMsg(msg);
return j;
}
@JsonIgnore//返回对象时忽略此属性
public static ResultVo success(Map<String, Object> map) {
ResultVo restResponse = new ResultVo();
public static ResultVoMap success(Map<String, Object> map) {
ResultVoMap restResponse = new ResultVoMap();
restResponse.putAll(map);
return restResponse;
}
@JsonIgnore//返回对象时忽略此属性
public static ResultVo success() {
return new ResultVo();
public static ResultVoMap success() {
return new ResultVoMap();
}
@Override
public ResultVo put(String key, Object value) {
public ResultVoMap put(String key, Object value) {
super.put(key, value);
return this;
}
public ResultVo putMap(Map m) {
public ResultVoMap putMap(Map m) {
super.putAll(m);
return this;
}

@ -12,7 +12,9 @@ public interface CacheConstants {
/** 热点数据 */
String HOT_DATA = "hotData";
/** 系统常量 */
/** 永久常量 */
String EDEN_DATA = "edenData";
/** 永久Hash常量 */
String EDEN_HASH_DATA = "edenHashData";
}

@ -0,0 +1,18 @@
package org.opsli.common.constants;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.common.constants
* @Author: Parker
* @CreateTime: 2020-09-16 17:42
* @Description:
*/
public interface DictConstants {
/** 缓存前缀 */
String CACHE_PREFIX_NAME = "dict:name:";
/** 缓存前缀 */
String CACHE_PREFIX_VALUE = "dict:value:";
}

@ -7,16 +7,17 @@ package org.opsli.common.constants;
*/
public interface OrderConstants {
/** SQL 切面执行顺序 */
int SQL_ORDER = 190;
/** 热点数据加载顺序 */
int HOT_DATA_ORDER = 180;
/** 参数非法验证顺序 */
int PARAM_VALIDATE_AOP_SORT = 185;
/** SQL 切面执行顺序 */
int SQL_ORDER = 190;
/** Controller异常拦截顺序 */
int EXCEPTION_HANDLER_ORDER = 260;
/** 参数非法验证顺序 */
int PARAM_VALIDATE_AOP_SORT = 500;
}

@ -39,7 +39,7 @@ public class SQLDataAop {
public void insertHadnler(Object ret){
try {
if(ret == null){
throw new ServiceException(CoreMsg.SQL_EXCEPTION_UPDATE);
throw new ServiceException(CoreMsg.SQL_EXCEPTION_INSERT);
}
} catch (ServiceException e) {
throw e;

@ -2,13 +2,27 @@ package org.opsli.core.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.api.utils.ValidationUtil;
import org.opsli.common.annotation.HotDataPut;
import org.opsli.common.exception.ServiceException;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import static org.opsli.common.constants.OrderConstants.PARAM_VALIDATE_AOP_SORT;
@ -34,13 +48,27 @@ public class ValitaionArgsAop {
* @param point
*/
@Before("requestMapping()")
public void doBefore(JoinPoint point) {
public void validation(JoinPoint point) throws Throwable {
Object[] args = point.getArgs();
for (Object arg : args) {
// 参数校验
if(arg instanceof ApiWrapper){
ValidationUtil.verify(arg);
}
try {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
HttpServletRequest request = sra.getRequest();
String method = request.getMethod();
// 只有 post 请求 才会去验证数据
if("POST".equals(method)){
for (Object arg : args) {
// 参数校验
if(arg instanceof ApiWrapper){
ValidationUtil.verify(arg);
}
}
}
}catch (ServiceException e){
throw e;
}catch (Exception e){
log.error(e.getMessage(),e);
}
}

@ -23,6 +23,8 @@ import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.msg.CoreMsg;
import org.opsli.plugins.excel.ExcelUtil;
import org.opsli.plugins.excel.exception.ExcelPluginException;
import org.opsli.plugins.redis.RedisLockPlugins;
import org.opsli.plugins.redis.lock.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestParam;
@ -64,7 +66,8 @@ public abstract class BaseRestController <E extends ApiWrapper, T extends BaseEn
@Autowired(required = false)
protected S IService;
@Autowired
private RedisLockPlugins redisLockPlugins;
/**
*
@ -85,14 +88,46 @@ public abstract class BaseRestController <E extends ApiWrapper, T extends BaseEn
return model;
}
}
// 如果缓存没读到 则去数据库读
model = WrapperUtil.transformInstance(IService.get(id),modelClazz);
if(model != null){
// 如果开启缓存 将数据库查询对象 存如缓存
// 防止缓存穿透判断
boolean hasNilFlag = false;
// 如果开启缓存 防止缓存穿透判断
if(hotDataFlag){
hasNilFlag = CacheUtil.hasNilFlag("get:" + id);
}
if(!hasNilFlag){
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName("getLock:"+id)
.setAcquireTimeOut(3000L)
.setLockTimeOut(10000L);
// 这里增加分布式锁 防止缓存击穿
if(hotDataFlag){
// 这里会 同步更新到本地Ehcache 和 Redis缓存
// 如果其他服务器缓存也丢失了 则 回去Redis拉取
CacheUtil.put(id, model);
// 加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
throw new ServiceException(CoreMsg.CACHE_PUNCTURE_EXCEPTION);
}
// 如果缓存没读到 则去数据库读
model = WrapperUtil.transformInstance(IService.get(id),modelClazz);
// 释放锁
redisLockPlugins.unLock(redisLock);
redisLock = null;
}else{
// 如果缓存没读到 则去数据库读
model = WrapperUtil.transformInstance(IService.get(id),modelClazz);
}
// 获得数据后处理
if(model != null){
// 如果开启缓存 将数据库查询对象 存如缓存
if(hotDataFlag){
// 这里会 同步更新到本地Ehcache 和 Redis缓存
// 如果其他服务器缓存也丢失了 则 回去Redis拉取
CacheUtil.put(id, model);
}
}else {
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag("get:" + id);
}
}
}
@ -153,7 +188,7 @@ public abstract class BaseRestController <E extends ApiWrapper, T extends BaseEn
* @param response
*/
protected ResultVo<?> importTemplate(String fileName, HttpServletResponse response){
return this.excelExport(fileName+" - 模版 ",null, response);
return this.excelExport(fileName + " 模版 ",null, response);
}
/**

@ -1,26 +1,24 @@
package org.opsli.core.base.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.TypeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.common.constants.MyBatisConstants;
import org.opsli.common.utils.HumpUtil;
import org.opsli.common.utils.WrapperUtil;
import org.opsli.core.base.entity.BaseEntity;
import org.opsli.core.base.service.base.BaseService;
import org.opsli.core.base.service.interfaces.CrudServiceInterface;
import org.opsli.core.persistence.Page;
import org.opsli.core.utils.UserUtil;
import org.opsli.core.persistence.querybuilder.GenQueryBuilder;
import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.persistence.querybuilder.chain.TenantHandler;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
@ -44,6 +42,7 @@ import java.util.List;
*
*/
@Slf4j
@Transactional(readOnly = true)
public abstract class CrudServiceImpl<M extends BaseMapper<T>, E extends ApiWrapper, T extends BaseEntity>
extends BaseService<M, T> implements CrudServiceInterface<E,T> {
@ -58,9 +57,6 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, E extends ApiWrap
private static final int entityIndex = 2;
/** 多租户状态 */
protected boolean tenantFlag = false;
@Override
public E get(String id) {
return transformT2M(
@ -77,6 +73,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, E extends ApiWrap
}
@Override
@Transactional(readOnly = false)
public E insert(E model) {
if(model == null) return null;
T entity = transformM2T(model);
@ -88,6 +85,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, E extends ApiWrap
}
@Override
@Transactional(readOnly = false)
public boolean insertBatch(List<E> models) {
if(models == null || models.size() == 0) return false;
List<T> entitys = transformMs2Ts(models);
@ -95,6 +93,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, E extends ApiWrap
}
@Override
@Transactional(readOnly = false)
public E update(E model) {
if(model == null) return null;
T entity = transformM2T(model);
@ -106,17 +105,20 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, E extends ApiWrap
}
@Override
@Transactional(readOnly = false)
public boolean delete(String id) {
return super.removeById(id);
}
@Override
@Transactional(readOnly = false)
public boolean delete(E model) {
if(model == null) return false;
return super.removeById(model.getId());
}
@Override
@Transactional(readOnly = false)
public boolean deleteAll(String[] ids) {
if(ids == null) return false;
List<String> idList = Convert.toList(String.class, ids);
@ -124,6 +126,7 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, E extends ApiWrap
}
@Override
@Transactional(readOnly = false)
public boolean deleteAll(Collection<E> models) {
if(models == null || models.isEmpty()) return false;
List<String> idList = Lists.newArrayListWithCapacity(models.size());
@ -135,27 +138,19 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, E extends ApiWrap
@Override
public List<T> findList(QueryWrapper<T> queryWrapper) {
// 判断多租户
if(this.tenantFlag) {
String tenantId = UserUtil.getTenantId();
if (StringUtils.isNotEmpty(tenantId)) {
queryWrapper.eq(HumpUtil.humpToUnderline(MyBatisConstants.FIELD_TENANT), tenantId);
}
}
return super.list(queryWrapper);
// 多租户处理
TenantHandler tenantHandler = new TenantHandler();
QueryWrapper<T> qWrapper = tenantHandler.handler(entityClazz, queryWrapper);
return super.list(qWrapper);
}
@Override
public List<T> findAllList() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
// 判断多租户
if(this.tenantFlag){
String tenantId = UserUtil.getTenantId();
if(StringUtils.isNotEmpty(tenantId)){
queryWrapper.eq(HumpUtil.humpToUnderline(MyBatisConstants.FIELD_TENANT), tenantId);
}
}
return super.list(queryWrapper);
QueryBuilder<T> queryBuilder = new GenQueryBuilder<>();
// 多租户处理
TenantHandler tenantHandler = new TenantHandler();
QueryWrapper<T> qWrapper = tenantHandler.handler(entityClazz, queryBuilder.build());
return super.list(qWrapper);
}
@Override
@ -224,8 +219,6 @@ public abstract class CrudServiceImpl<M extends BaseMapper<T>, E extends ApiWrap
try {
this.modelClazz = this.getModelClass();
this.entityClazz = this.getEntityClass();
// 多租户判断
this.tenantFlag = ReflectUtil.hasField(entityClazz, MyBatisConstants.FIELD_TENANT);
}catch (Exception e){
log.error(e.getMessage(),e);
}

@ -681,6 +681,26 @@ public class CacheUtil {
return ret;
}
/**
*
* 穿
*
* @param key
* @return boolean
*/
public static boolean delNilFlag(String key) {
boolean ret = false;
try {
// 存入Redis
redisPlugin.del(NIL_FLAG_PREFIX + key);
ret = true;
}catch (Exception e){
log.error(e.getMessage(),e);
}
return ret;
}
/**
* 5
* 穿

@ -0,0 +1,20 @@
package org.opsli.core.cache.pushsub.enums;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.cache.pushsub.enums
* @Author: Parker
* @CreateTime: 2020-09-16 22:28
* @Description:
*/
public enum DictModelType {
/** 对象 */
OBJECT,
/** 集合 */
COLLECTION,
;
}

@ -9,13 +9,13 @@ package org.opsli.core.cache.pushsub.enums;
*/
public enum MsgArgsType {
/** 字典Key */
DICT_KEY,
/** 字典Field */
DICT_FIELD,
/** 字典Value */
DICT_VALUE,
/** 字典Value */
/** 字典模型 */
DICT_MODEL,
/** 字典模型-集合 */
DICT_MODELS,
/** 字典模型-传输类型 */
DICT_MODEL_TYPE,
/** 字典操作类型 */
DICT_TYPE,
/** 缓存数据Key */

@ -1,7 +1,20 @@
package org.opsli.core.cache.pushsub.handler;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.opsli.api.wrapper.system.dict.DictModel;
import org.opsli.common.constants.CacheConstants;
import org.opsli.common.constants.DictConstants;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.enums.DictModelType;
import org.opsli.core.cache.pushsub.enums.MsgArgsType;
import org.opsli.core.cache.pushsub.enums.PushSubType;
import org.opsli.plugins.cache.EhCachePlugin;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Collection;
import java.util.List;
/**
* @BelongsProject: opsli-boot
@ -10,8 +23,12 @@ import org.opsli.core.cache.pushsub.enums.PushSubType;
* @CreateTime: 2020-09-15 16:24
* @Description:
*/
@Slf4j
public class DictHandler implements RedisPushSubHandler{
@Autowired
EhCachePlugin ehCachePlugin;
@Override
public PushSubType getType() {
return PushSubType.DICT;
@ -19,7 +36,54 @@ public class DictHandler implements RedisPushSubHandler{
@Override
public void handler(JSONObject msgJson) {
System.out.println(msgJson.toJSONString());
DictModelType dictModelType = DictModelType.valueOf((String) msgJson.get(MsgArgsType.DICT_MODEL_TYPE.toString()));
CacheType type = CacheType.valueOf((String) msgJson.get(MsgArgsType.DICT_TYPE.toString()));
if(DictModelType.COLLECTION == dictModelType){
Collection<Object> dicts = (Collection<Object>) msgJson.get(MsgArgsType.DICT_MODELS.toString());
for (Object dictObj : dicts) {
JSONObject jsonObject = (JSONObject) dictObj;
DictModel dictModel = JSONObject.toJavaObject(jsonObject, DictModel.class);
this.handler(dictModel, type);
}
} else if(DictModelType.OBJECT == dictModelType){
Object dictObj = msgJson.get(MsgArgsType.DICT_MODEL.toString());
JSONObject jsonObject = (JSONObject) dictObj;
DictModel dictModel = JSONObject.toJavaObject(jsonObject, DictModel.class);
this.handler(dictModel, type);
}
}
/**
* -
* @param dictModel
* @param type
*/
private void handler(DictModel dictModel, CacheType type){
// 解析 key
String ehKeyByName = CacheUtil.handleKey(CacheConstants.EDEN_HASH_DATA,
DictConstants.CACHE_PREFIX_NAME + dictModel.getTypeCode() + ":" + dictModel.getDictName());
String ehKeyByValue = CacheUtil.handleKey(CacheConstants.EDEN_HASH_DATA,
DictConstants.CACHE_PREFIX_VALUE + dictModel.getTypeCode() + ":" + dictModel.getDictValue());
// 缓存更新
if(CacheType.UPDATE == type){
ehCachePlugin.delete(CacheConstants.HOT_DATA, ehKeyByName);
ehCachePlugin.delete(CacheConstants.HOT_DATA, ehKeyByValue);
// 统一转换为 JSONObject
String jsonStr = JSONObject.toJSONString(dictModel.getModel());
JSONObject value = JSONObject.parseObject(jsonStr);
ehCachePlugin.put(CacheConstants.HOT_DATA, ehKeyByName, value);
ehCachePlugin.put(CacheConstants.HOT_DATA, ehKeyByValue, value);
}
// 缓存删除
else if(CacheType.DELETE == type){
ehCachePlugin.delete(CacheConstants.HOT_DATA, ehKeyByName);
ehCachePlugin.delete(CacheConstants.HOT_DATA, ehKeyByValue);
}
}
}

@ -2,10 +2,14 @@ package org.opsli.core.cache.pushsub.handler;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.constants.CacheConstants;
import org.opsli.common.constants.DictConstants;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.enums.MsgArgsType;
import org.opsli.core.cache.pushsub.enums.PushSubType;
import org.opsli.plugins.cache.EhCachePlugin;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @BelongsProject: opsli-boot
@ -17,6 +21,9 @@ import org.opsli.core.cache.pushsub.enums.PushSubType;
@Slf4j
public class EdenDataHandler implements RedisPushSubHandler{
@Autowired
EhCachePlugin ehCachePlugin;
@Override
public PushSubType getType() {
return PushSubType.EDEN_DATA;
@ -28,13 +35,16 @@ public class EdenDataHandler implements RedisPushSubHandler{
Object value = msgJson.get(MsgArgsType.CACHE_DATA_VALUE.toString());
CacheType type = CacheType.valueOf((String )msgJson.get(MsgArgsType.CACHE_DATA_TYPE.toString()));
// 解析 key
String handleKey = CacheUtil.handleKey(CacheConstants.EDEN_DATA,key);
// 缓存更新
if(CacheType.UPDATE == type){
CacheUtil.putEdenByKeyOriginal(key, value);
ehCachePlugin.put(CacheConstants.HOT_DATA, handleKey, value);
}
// 缓存删除
else if(CacheType.DELETE == type){
CacheUtil.del(key);
ehCachePlugin.delete(CacheConstants.HOT_DATA, handleKey);
}
}

@ -2,10 +2,13 @@ package org.opsli.core.cache.pushsub.handler;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.constants.CacheConstants;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.enums.MsgArgsType;
import org.opsli.core.cache.pushsub.enums.PushSubType;
import org.opsli.plugins.cache.EhCachePlugin;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @BelongsProject: opsli-boot
@ -17,6 +20,9 @@ import org.opsli.core.cache.pushsub.enums.PushSubType;
@Slf4j
public class HotDataHandler implements RedisPushSubHandler{
@Autowired
EhCachePlugin ehCachePlugin;
@Override
public PushSubType getType() {
return PushSubType.HOT_DATA;
@ -28,15 +34,16 @@ public class HotDataHandler implements RedisPushSubHandler{
Object value = msgJson.get(MsgArgsType.CACHE_DATA_VALUE.toString());
CacheType type = CacheType.valueOf((String )msgJson.get(MsgArgsType.CACHE_DATA_TYPE.toString()));
// 缓存更新
// 解析 key
String handleKey = CacheUtil.handleKey(CacheConstants.HOT_DATA, key);
if(CacheType.UPDATE == type){
CacheUtil.putByKeyOriginal(key, value);
ehCachePlugin.put(CacheConstants.HOT_DATA, handleKey, value);
}
// 缓存删除
else if(CacheType.DELETE == type){
CacheUtil.del(key);
ehCachePlugin.delete(CacheConstants.HOT_DATA, handleKey);
}
}
}

@ -3,12 +3,16 @@ package org.opsli.core.cache.pushsub.msgs;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.experimental.Accessors;
import org.opsli.api.wrapper.system.dict.DictModel;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.enums.DictModelType;
import org.opsli.core.cache.pushsub.enums.MsgArgsType;
import org.opsli.core.cache.pushsub.enums.PushSubType;
import org.opsli.core.cache.pushsub.receiver.RedisPushSubReceiver;
import org.opsli.plugins.redis.pushsub.entity.BaseSubMessage;
import java.util.List;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.cache.pushsub.msgs
@ -29,13 +33,12 @@ public final class DictMsgFactory extends BaseSubMessage{
/**
*
*/
public static BaseSubMessage createMsg(String key, String field, Object value, CacheType cacheType){
public static BaseSubMessage createMsg(DictModel dictModel, CacheType cacheType){
BaseSubMessage baseSubMessage = new BaseSubMessage();
// 数据
JSONObject jsonObj = new JSONObject();
jsonObj.put(MsgArgsType.DICT_KEY.toString(),key);
jsonObj.put(MsgArgsType.DICT_FIELD.toString(),field);
jsonObj.put(MsgArgsType.DICT_VALUE.toString(),value);
jsonObj.put(MsgArgsType.DICT_MODEL.toString(),dictModel);
jsonObj.put(MsgArgsType.DICT_MODEL_TYPE.toString(), DictModelType.OBJECT);
jsonObj.put(MsgArgsType.DICT_TYPE.toString(),cacheType.toString());
// DICT 字典
@ -43,4 +46,19 @@ public final class DictMsgFactory extends BaseSubMessage{
return baseSubMessage;
}
/**
*
*/
public static BaseSubMessage createMsg(List<DictModel> dictModels, CacheType cacheType){
BaseSubMessage baseSubMessage = new BaseSubMessage();
// 数据
JSONObject jsonObj = new JSONObject();
jsonObj.put(MsgArgsType.DICT_MODELS.toString(),dictModels);
jsonObj.put(MsgArgsType.DICT_MODEL_TYPE.toString(), DictModelType.COLLECTION);
jsonObj.put(MsgArgsType.DICT_TYPE.toString(),cacheType.toString());
// DICT 字典
baseSubMessage.build(CHANNEL,PushSubType.DICT.toString(),jsonObj);
return baseSubMessage;
}
}

@ -101,9 +101,9 @@ public class RedisPushSubReceiver extends BaseReceiver {
String type = (String) msgJson.get(BaseSubMessage.BASE_TYPE);
String identifier = (String) msgJson.get(BaseSubMessage.BASE_ID);
// 本机不广播
if(SystemInfo.INSTANCE.getSystemID().equals(identifier)){
return;
}
// if(SystemInfo.INSTANCE.getSystemID().equals(identifier)){
// return;
// }
PushSubType pt = PushSubType.valueOf(type);
RedisPushSubHandler redisPushSubHandler = HANDLER_MAP.get(pt);
if(redisPushSubHandler == null){

@ -1,17 +1,17 @@
package org.opsli.core.handler;
import cn.hutool.core.text.StrFormatter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.api.base.result.ResultVo;
import org.opsli.common.exception.EmptyException;
import org.opsli.common.exception.ServiceException;
import org.opsli.core.msg.CoreMsg;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.*;
import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;
import static org.opsli.common.constants.OrderConstants.EXCEPTION_HANDLER_ORDER;
@ -21,10 +21,42 @@ import static org.opsli.common.constants.OrderConstants.EXCEPTION_HANDLER_ORDER;
* @date 2020-09-13
*/
@Slf4j
@ControllerAdvice
@RestControllerAdvice
@Order(EXCEPTION_HANDLER_ORDER)
public class GlobalExceptionHandler {
/*
ArithmeticException
NullPointerException
ClassCastException
NegativeArrayException
ArrayIndexOutOfBoundsException
SecturityException
EOFException
FileNotFoundException
NumberFormatException
SQLException
IOException
NoSuchMethodException
IndexOutOfBoundsExecption
SystemException
NegativeArraySizeException
NumberFormatException
SecurityException
UnsupportedOperationException
线NetworkOnMainThreadException
IllegalStateException extends RuntimeException IllegalComponentStateException Java Java
HttpHostConnectException
线ThreadUI view ViewRootImpl$CalledFromWrongThreadException
SSLExceptionero
Method.invoke(obj, args...)InvocationTargetException
EventBus使EventBusException
IllegalArgumentException
0ZeroException
*/
/**
*
*/
@ -67,6 +99,23 @@ public class GlobalExceptionHandler {
return ResultVo.error(e.getCode(), CoreMsg.SQL_EXCEPTION_INTEGRITY_CONSTRAINT_VIOLATION.getMessage());
}
/**
*
*/
@ExceptionHandler(SQLException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ResultVo<?> sqlException(SQLException e) {
//log.error("数据异常:{}",e.getMessage(),e);
// 默认值异常
if(StringUtils.contains(e.getMessage(),"doesn't have a default value")){
String Field = e.getMessage().replaceAll("Field '","")
.replaceAll("' doesn't have a default value","");
String msg = StrFormatter.format(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getMessage(), Field);
return ResultVo.error(CoreMsg.SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE.getCode(), msg);
}
String msg = StrFormatter.format(CoreMsg.SQL_EXCEPTION_UNKNOWN.getMessage(), e.getMessage());
return ResultVo.error(CoreMsg.SQL_EXCEPTION_UNKNOWN.getCode(), msg);
}
}

@ -16,6 +16,9 @@ public enum CoreMsg implements BaseMsg {
SQL_EXCEPTION_INSERT(10101,"新增数据失败,请稍后再次尝试!"),
SQL_EXCEPTION_DELETE(10102,"删除数据失败,请稍后再次尝试!"),
SQL_EXCEPTION_INTEGRITY_CONSTRAINT_VIOLATION(10105,"数据主键冲突或者已有该数据!"),
SQL_EXCEPTION_NOT_HAVE_DEFAULT_VALUE(10106,"数据异常:{} 字段没有默认值!"),
SQL_EXCEPTION_UNKNOWN(10106,"数据异常:未知异常,请联系系统管理员 {}"),
/**
* Redis
@ -30,8 +33,12 @@ public enum CoreMsg implements BaseMsg {
EXCEL_IMPORT_SUCCESS(10302,"EXCEL 导入成功!数据行数:{} 耗时(秒){}"),
EXCEL_IMPORT_ERROR(10303,"Excel导入失败{} 耗时(秒){}"),
EXCEL_IMPORT_NO(10304,""),
EXCEL_FILE_NULL(10305,"请选择文件")
EXCEL_FILE_NULL(10305,"请选择文件"),
/**
*
*/
CACHE_PUNCTURE_EXCEPTION(10405, "当期服务繁忙,客官请稍微再次尝试!")
;
private int code;

@ -0,0 +1,29 @@
package org.opsli.core.persistence.querybuilder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.opsli.core.base.entity.BaseEntity;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.persistence.querybuilder
* @Author: Parker
* @CreateTime: 2020-09-21 23:57
* @Description: Web
*/
public class GenQueryBuilder<T extends BaseEntity> implements QueryBuilder<T> {
/**
*
*/
public GenQueryBuilder(){
}
@Override
public QueryWrapper<T> build() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
return queryWrapper;
}
}

@ -0,0 +1,23 @@
package org.opsli.core.persistence.querybuilder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.opsli.core.base.entity.BaseEntity;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.persistence.querybuilder
* @Author: Parker
* @CreateTime: 2020-09-21 23:53
* @Description:
*/
public interface QueryBuilder<T extends BaseEntity> {
/**
*
* @param <T>
* @return
*/
QueryWrapper<T> build();
}

@ -1,10 +1,8 @@
package org.opsli.core.persistence;
package org.opsli.core.persistence.querybuilder;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.api.base.warpper.ApiWrapper;
import org.opsli.common.constants.MyBatisConstants;
import org.opsli.common.utils.HumpUtil;
import org.opsli.core.base.entity.BaseEntity;
@ -13,20 +11,12 @@ import java.util.Map;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.persistence
* @BelongsPackage: org.opsli.core.persistence.querybuilder
* @Author: Parker
* @CreateTime: 2020-09-19 21:15
* @Description:
*
*
* eq
* like
* begin end
*
* @CreateTime: 2020-09-21 23:57
* @Description: Web
*/
@Slf4j
public class PageQueryBuilder<E extends ApiWrapper,T extends BaseEntity>{
public class WebQueryBuilder<T extends BaseEntity> implements QueryBuilder<T>{
// == 匹配条件 ==
/** 全值匹配 */
@ -41,66 +31,48 @@ public class PageQueryBuilder<E extends ApiWrapper,T extends BaseEntity>{
private static final String ORDER_ASC = "ASC";
private static final String ORDER_DESC = "DESC";
/** 当前页 */
private Integer pageNo;
/** 每页数量 */
private Integer pageSize;
/** 参数 */
private Map<String, String[]> parameterMap;
/** Entity Clazz */
private Class<T> entityClazz;
private Class<? extends BaseEntity> entityClazz;
/** 默认排序字段 */
private String defaultOrderField;
/**
*
*
* @param entityClazz Entity clazz
* @param pageNo
* @param pageSize
* @param parameterMap request
*/
public PageQueryBuilder(Class<T> entityClazz, Integer pageNo, Integer pageSize, Map<String, String[]> parameterMap){
this.pageNo = pageNo;
this.pageSize = pageSize;
public WebQueryBuilder(Class<T> entityClazz, Map<String, String[]> parameterMap){
this.parameterMap = parameterMap;
this.entityClazz = entityClazz;
this.defaultOrderField = MyBatisConstants.FIELD_UPDATE_TIME;
}
/**
*
* @param entityClazz Entity clazz
* @param parameterMap request
* @param defaultOrderField
*/
public PageQueryBuilder(Class<T> entityClazz, Map<String, String[]> parameterMap){
public WebQueryBuilder(Class<T> entityClazz, Map<String, String[]> parameterMap,
String defaultOrderField){
this.parameterMap = parameterMap;
this.entityClazz = entityClazz;
this.defaultOrderField = defaultOrderField;
}
/**
* builderPage
* @return
*/
public Page<E,T> builderPage(){
Page<E,T> page = new Page<>(this.pageNo,this.pageSize);
QueryWrapper<T> queryWrapper = this.createQueryWrapper();
page.setQueryWrapper(queryWrapper);
return page;
}
/**
*
* @return
*/
public QueryWrapper<T> builderQueryWrapper(){
return this.createQueryWrapper();
@Override
public QueryWrapper<T> build() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
return this.createQueryWrapper(queryWrapper);
}
/**
*
* @return
*/
private QueryWrapper<T> createQueryWrapper(){
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
private <T extends BaseEntity> QueryWrapper<T> createQueryWrapper(QueryWrapper<T> queryWrapper){
if(this.parameterMap == null){
return queryWrapper;
}
@ -142,7 +114,7 @@ public class PageQueryBuilder<E extends ApiWrapper,T extends BaseEntity>{
}
// 如果没有排序 默认按照 修改时间倒叙排序
if(orderCount == 0){
queryWrapper.orderByDesc(HumpUtil.humpToUnderline(MyBatisConstants.FIELD_UPDATE_TIME));
queryWrapper.orderByDesc(HumpUtil.humpToUnderline(this.defaultOrderField));
}
return queryWrapper;
}
@ -155,10 +127,10 @@ public class PageQueryBuilder<E extends ApiWrapper,T extends BaseEntity>{
* @param value
* @return
*/
private void handlerValue(QueryWrapper<T> queryWrapper, String handle, String key, String value){
private <T extends BaseEntity> void handlerValue(QueryWrapper<T> queryWrapper, String handle, String key, String value){
if(queryWrapper == null || StringUtils.isEmpty(handle)
|| StringUtils.isEmpty(key) || StringUtils.isEmpty(value)
){
|| StringUtils.isEmpty(key) || StringUtils.isEmpty(value)
){
return;
}
// 转换驼峰 为 数据库下划线字段
@ -224,5 +196,4 @@ public class PageQueryBuilder<E extends ApiWrapper,T extends BaseEntity>{
}
return false;
}
}

@ -0,0 +1,22 @@
package org.opsli.core.persistence.querybuilder.chain;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.opsli.core.base.entity.BaseEntity;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.persistence.querybuilder.chain
* @Author: Parker
* @CreateTime: 2020-09-22 10:35
* @Description:
*/
public interface QueryBuilderChain {
/**
*
* @param wrapper
* @param <T>
*/
<T extends BaseEntity> QueryWrapper<T> handler(Class<T> entityClazz, QueryWrapper<T> wrapper);
}

@ -0,0 +1,62 @@
package org.opsli.core.persistence.querybuilder.chain;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.opsli.common.constants.MyBatisConstants;
import org.opsli.common.utils.HumpUtil;
import org.opsli.core.base.entity.BaseEntity;
import org.opsli.core.utils.UserUtil;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.tenant
* @Author: Parker
* @CreateTime: 2020-09-22 00:50
* @Description:
*/
public class TenantHandler implements QueryBuilderChain{
/**
*
*/
private QueryBuilderChain queryBuilderChain;
public TenantHandler(){}
/**
*
* @param queryBuilderChain
*/
public TenantHandler(QueryBuilderChain queryBuilderChain){
this.queryBuilderChain = queryBuilderChain;
}
/**
*
* @param entityClazz
* @param wrapper
* @param <T>
* @return
*/
@Override
public <T extends BaseEntity> QueryWrapper<T> handler(Class<T> entityClazz, QueryWrapper<T> wrapper) {
// 执行责任链
if(queryBuilderChain != null){
wrapper = queryBuilderChain.handler(entityClazz, wrapper);
}
// 判断多租户
boolean tenantFlag = ReflectUtil.hasField(entityClazz, MyBatisConstants.FIELD_TENANT);
if(tenantFlag) {
String tenantId = UserUtil.getTenantId();
if (StringUtils.isNotEmpty(tenantId)) {
wrapper.eq(HumpUtil.humpToUnderline(MyBatisConstants.FIELD_TENANT), tenantId);
}
}
return wrapper;
}
}

@ -0,0 +1,274 @@
package org.opsli.core.utils;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.web.system.dict.DictDetailApi;
import org.opsli.api.wrapper.system.dict.DictModel;
import org.opsli.api.wrapper.system.dict.SysDictDetailModel;
import org.opsli.common.constants.DictConstants;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.plugins.redis.RedisLockPlugins;
import org.opsli.plugins.redis.RedisPlugin;
import org.opsli.plugins.redis.lock.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.utils
* @Author: Parker
* @CreateTime: 2020-09-22 11:17
* @Description:
*/
@Slf4j
@Component
public class DictUtil {
/** Redis插件 */
private static RedisPlugin redisPlugin;
/** Redis分布式锁 */
private static RedisLockPlugins redisLockPlugins;
/** 字典Service */
private static DictDetailApi dictDetailApi;
/**
*
* @param typeCode Code
* @param dictValue
* @param defaultVal
* @return
*/
public static String getDictNameByValue(String typeCode, String dictValue, String defaultVal){
try {
String dictName = "";
SysDictDetailModel cacheModel = CacheUtil.getHash(DictConstants.CACHE_PREFIX_VALUE + typeCode,
dictValue, SysDictDetailModel.class);
if (cacheModel != null){
dictName = cacheModel.getDictName();
}
if (StringUtils.isNotEmpty(dictName)) return dictName;
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag("dict:" + typeCode + ":" + dictValue);
if(hasNilFlag){
return defaultVal;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName("dictLock:" + typeCode + ":" + dictValue)
.setAcquireTimeOut(3000L)
.setLockTimeOut(5000L);
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
return defaultVal;
}
// 查询数据库 并保存到缓存内
ResultVo<List<SysDictDetailModel>> resultVo = dictDetailApi.findListByTypeCode(typeCode);
if(resultVo.isSuccess()){
List<SysDictDetailModel> sysDictDetailModels = resultVo.getData();
for (SysDictDetailModel model : sysDictDetailModels) {
if(model.getDictValue().equals(dictValue)){
// 名称
dictName = model.getDictName();
DictModel dictModel = new DictModel();
dictModel.setTypeCode(model.getTypeCode());
dictModel.setDictName(model.getDictName());
dictModel.setDictValue(model.getDictValue());
dictModel.setModel(model);
// 保存至缓存
DictUtil.put(dictModel);
break;
}
}
}
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
redisLock = null;
// 如果名称还是 为空 则赋默认值
if(StringUtils.isEmpty(dictName)){
// 加入缓存防穿透
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag("dict:" + typeCode + ":" + dictValue);
dictName = defaultVal;
}
return dictName;
}catch (Exception e){
log.error(e.getMessage(),e);
return defaultVal;
}
}
/**
*
* @param typeCode Code
* @param dictName
* @param defaultVal
* @return
*/
public static String getDictValueByName(String typeCode, String dictName, String defaultVal){
try {
String dictValue = "";
SysDictDetailModel cacheModel = CacheUtil.getHash(DictConstants.CACHE_PREFIX_NAME + typeCode,
dictName, SysDictDetailModel.class);
if (cacheModel != null){
dictValue = cacheModel.getDictValue();
}
if (StringUtils.isNotEmpty(dictValue)) return dictValue;
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag("dict:" + typeCode + ":" + dictName);
if(hasNilFlag){
return defaultVal;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName("dictLock:" + typeCode + ":" + dictName)
.setAcquireTimeOut(3000L)
.setLockTimeOut(10000L);
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
return defaultVal;
}
// 查询数据库 并保存到缓存内
ResultVo<List<SysDictDetailModel>> resultVo = dictDetailApi.findListByTypeCode(typeCode);
if(resultVo.isSuccess()){
List<SysDictDetailModel> sysDictDetailModels = resultVo.getData();
for (SysDictDetailModel model : sysDictDetailModels) {
if(model.getDictName().equals(dictName)){
// 值
dictValue = model.getDictValue();
DictModel dictModel = new DictModel();
dictModel.setTypeCode(model.getTypeCode());
dictModel.setDictName(model.getDictName());
dictModel.setDictValue(model.getDictValue());
dictModel.setModel(model);
// 保存至缓存
DictUtil.put(dictModel);
break;
}
}
}
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
redisLock = null;
// 如果值还是 为空 则赋默认值
if(StringUtils.isEmpty(dictValue)){
// 加入缓存防穿透
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag("dict:" + typeCode + ":" + dictName);
dictValue = defaultVal;
}
return dictValue;
}catch (Exception e){
log.error(e.getMessage(),e);
return defaultVal;
}
}
/**
* code
* @param typeCode
* @return
*/
public static List<DictModel> getDictList(String typeCode){
List<DictModel> dictModels = Lists.newArrayList();
try {
Map<Object, Object> dictMap = redisPlugin.hGetAll(DictConstants.CACHE_PREFIX_VALUE + typeCode);
Set<Map.Entry<Object, Object>> entries = dictMap.entrySet();
for (Map.Entry<Object, Object> entry : entries) {
// 赋值
SysDictDetailModel model = (SysDictDetailModel) entry.getValue();
DictModel dictModel = new DictModel();
dictModel.setTypeCode(typeCode);
dictModel.setDictName(model.getDictName());
dictModel.setDictValue(model.getDictValue());
dictModels.add(dictModel);
}
}catch (Exception e){
log.error(e.getMessage(),e);
dictModels = Lists.newArrayList();
}
return dictModels;
}
// ===============
/**
*
* @param model
* @return
*/
public static void put(DictModel model){
CacheUtil.putEdenHash(DictConstants.CACHE_PREFIX_NAME + model.getTypeCode(),
model.getDictName(), model.getModel());
CacheUtil.putEdenHash(DictConstants.CACHE_PREFIX_VALUE + model.getTypeCode(),
model.getDictValue(), model.getModel());
// 删除 空属性 拦截
CacheUtil.putNilFlag("dict:" + model.getTypeCode() + ":" + model.getDictName());
CacheUtil.putNilFlag("dict:" + model.getTypeCode() + ":" + model.getTypeCode());
}
/**
*
* @param model
* @return
*/
public static void del(DictModel model){
CacheUtil.delEdenHash(DictConstants.CACHE_PREFIX_NAME + model.getTypeCode(), model.getDictName());
CacheUtil.delEdenHash(DictConstants.CACHE_PREFIX_VALUE + model.getTypeCode(), model.getDictValue());
}
/**
* typeCode
* @param typeCode
* @return
*/
public static void delAll(String typeCode){
List<DictModel> dictList = DictUtil.getDictList(typeCode);
for (DictModel dictModel : dictList) {
DictUtil.del(dictModel);
}
}
// ===================================
@Autowired
public void setRedisPlugin(RedisPlugin redisPlugin) {
DictUtil.redisPlugin = redisPlugin;
}
@Autowired
public void setRedisLockPlugins(RedisLockPlugins redisLockPlugins) {
DictUtil.redisLockPlugins = redisLockPlugins;
}
@Autowired
public void setDictDetailApi(DictDetailApi dictDetailApi) {
DictUtil.dictDetailApi = dictDetailApi;
}
}

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>opsli-modulars</artifactId>
<groupId>org.opsliframework.boot</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>opsli-modulars-system</artifactId>
</project>

@ -0,0 +1,41 @@
package org.opsli.modulars.system;
import org.opsli.common.base.msg.BaseMsg;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.core.msg
* @Author: Parker
* @CreateTime: 2020-09-13 19:36
* @Description: -
*/
public enum SystemMsg implements BaseMsg {
/**
*
*/
EXCEL_DICT_UNIQUE(20000,"字典编号重复,该字典已存在!"),
EXCEL_DICT_DETAIL_UNIQUE(20001,"字典名称或值重复,该字典已存在!"),
;
private int code;
private String message;
SystemMsg(int code, String message){
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
}

@ -0,0 +1,40 @@
package org.opsli.modulars.system.dict.entity;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.opsli.core.base.entity.BaseEntity;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.entity
* @Author: Parker
* @CreateTime: 2020-09-16 17:33
* @Description:
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class SysDict extends BaseEntity {
/** 字典类型编号 */
private String typeCode;
/** 字典类型名称 */
private String typeName;
/** 是否内置数据 */
private Character izLock;
/** 备注 */
private String remark;
// ========================================
/** 逻辑删除字段 */
@TableLogic
private Integer deleted;
}

@ -0,0 +1,48 @@
package org.opsli.modulars.system.dict.entity;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.opsli.core.base.entity.BaseEntity;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.entity
* @Author: Parker
* @CreateTime: 2020-09-16 17:33
* @Description: -
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class SysDictDetail extends BaseEntity {
/** 字典类型ID */
private String typeId;
/** 字典类型Code 冗余字段 */
private String typeCode;
/** 字典文本 */
private String dictName;
/** 字典值 */
private String dictValue;
/** 是否内置数据 */
private Character izLock;
/** 排序 */
private Integer sortNo;
/** 备注 */
private String remark;
// ========================================
/** 逻辑删除字段 */
@TableLogic
private Integer deleted;
}

@ -0,0 +1,24 @@
package org.opsli.modulars.system.dict.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.opsli.modulars.system.dict.entity.SysDictDetail;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.mapper
* @Author: Parker
* @CreateTime: 2020-09-17 13:01
* @Description: Mapper
*/
@Mapper
public interface DictDetailMapper extends BaseMapper<SysDictDetail> {
/**
*
* @param entity
* @return
*/
Integer uniqueVerificationByNameOrValue(SysDictDetail entity);
}

@ -0,0 +1,24 @@
package org.opsli.modulars.system.dict.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.opsli.modulars.system.dict.entity.SysDict;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.mapper
* @Author: Parker
* @CreateTime: 2020-09-17 13:01
* @Description: Mapper
*/
@Mapper
public interface DictMapper extends BaseMapper<SysDict> {
/**
*
* @param entity
* @return
*/
Integer uniqueVerificationByCode(SysDict entity);
}

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.opsli.modulars.system.dict.mapper.DictDetailMapper">
<!-- 数据库字段 -->
<sql id="SysDictDetailColumns">
a.id as id,
a.type_id as typeId,
a.type_code as typeCode,
a.dict_name as dictName,
a.dict_value as dictValue,
a.iz_lock as izLock,
a.sort_no as sortNo,
a.remark as remark,
a.create_by as createBy,
a.create_time as createTime,
a.update_by as updateBy,
a.update_time as updateTime,
a.version as version,
a.deleted as deleted
</sql>
<sql id="SysDictDetailJoins">
</sql>
<select id="uniqueVerificationByNameOrValue" parameterType="SysDictDetail" resultType="Integer">
select count(0)
from sys_dict_detail a
where
(
a.dict_name = #{dictName}
or
a.type_code = #{typeCode}
)
and a.deleted = 0
<if test="id != null and id != ''">
and a.id != #{id}
</if>
</select>
</mapper>

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.opsli.modulars.system.dict.mapper.DictMapper">
<!-- 数据库字段 -->
<sql id="SysDictColumns">
a.id as id,
a.type_code as dictTypeCode,
a.type_name as dictTypeName,
a.iz_lock as izLock,
a.remark as remark,
a.create_by as createBy,
a.create_time as createTime,
a.update_by as updateBy,
a.update_time as updateTime,
a.version as version,
a.deleted as deleted
</sql>
<sql id="SysDictJoins">
</sql>
<select id="uniqueVerificationByCode" parameterType="SysDict" resultType="Integer">
select count(0)
from sys_dict a
where
a.type_code = #{typeCode}
and a.deleted = 0
<if test="id != null and id != ''">
AND a.id != #{id}
</if>
</select>
</mapper>

@ -0,0 +1,33 @@
package org.opsli.modulars.system.dict.service;
import org.opsli.api.wrapper.system.dict.SysDictDetailModel;
import org.opsli.core.base.service.interfaces.CrudServiceInterface;
import org.opsli.modulars.system.dict.entity.SysDictDetail;
import java.util.List;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.service
* @Author: Parker
* @CreateTime: 2020-09-17 13:07
* @Description:
*/
public interface IDictDetailService extends CrudServiceInterface<SysDictDetailModel, SysDictDetail> {
/**
* ID
* @param parentId ID
* @return
*/
boolean delByParent(String parentId);
/**
*
*
* @param typeCode
* @return
*/
List<SysDictDetailModel> findListByTypeCode(String typeCode);
}

@ -0,0 +1,18 @@
package org.opsli.modulars.system.dict.service;
import org.opsli.api.wrapper.system.dict.SysDictModel;
import org.opsli.core.base.service.interfaces.CrudServiceInterface;
import org.opsli.modulars.system.dict.entity.SysDict;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.service
* @Author: Parker
* @CreateTime: 2020-09-17 13:07
* @Description:
*/
public interface IDictService extends CrudServiceInterface<SysDictModel, SysDict> {
}

@ -0,0 +1,334 @@
package org.opsli.modulars.system.dict.service.impl;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.opsli.api.wrapper.system.dict.DictModel;
import org.opsli.api.wrapper.system.dict.SysDictDetailModel;
import org.opsli.api.wrapper.system.dict.SysDictModel;
import org.opsli.common.constants.MyBatisConstants;
import org.opsli.common.exception.ServiceException;
import org.opsli.common.utils.HumpUtil;
import org.opsli.common.utils.WrapperUtil;
import org.opsli.core.base.service.impl.CrudServiceImpl;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.msgs.DictMsgFactory;
import org.opsli.core.persistence.querybuilder.GenQueryBuilder;
import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.utils.DictUtil;
import org.opsli.modulars.system.SystemMsg;
import org.opsli.modulars.system.dict.entity.SysDictDetail;
import org.opsli.modulars.system.dict.mapper.DictDetailMapper;
import org.opsli.modulars.system.dict.service.IDictDetailService;
import org.opsli.modulars.system.dict.service.IDictService;
import org.opsli.plugins.redis.RedisPlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.service
* @Author: Parker
* @CreateTime: 2020-09-16 17:34
* @Description:
*/
@Service
public class DictDetailServiceImpl extends CrudServiceImpl<DictDetailMapper, SysDictDetailModel, SysDictDetail> implements IDictDetailService {
@Autowired(required = false)
private DictDetailMapper mapper;
@Autowired
private IDictService iDictService;
@Autowired
private RedisPlugin redisPlugin;
/**
*
* @param model model
* @return
*/
@Transactional(rollbackFor = Exception.class)
@Override
public SysDictDetailModel insert(SysDictDetailModel model) {
SysDictDetail entity = WrapperUtil.transformInstance(model, SysDictDetail.class);
// 唯一验证
Integer count = mapper.uniqueVerificationByNameOrValue(entity);
if(count != null && count > 0){
// 重复
throw new ServiceException(SystemMsg.EXCEL_DICT_UNIQUE);
}
SysDictDetailModel ret = super.insert(model);
if(ret != null){
DictModel dictModel = new DictModel();
dictModel.setTypeCode(model.getTypeCode());
dictModel.setDictName(model.getDictName());
dictModel.setDictValue(model.getDictValue());
dictModel.setModel(ret);
// 先删老缓存
DictUtil.del(dictModel);
// 广播缓存数据 - 通知其他服务器同步数据
redisPlugin.sendMessage(
DictMsgFactory.createMsg(dictModel, CacheType.DELETE)
);
// 再存 防止脏数据
DictUtil.put(dictModel);
// 广播缓存数据 - 通知其他服务器同步数据
redisPlugin.sendMessage(
DictMsgFactory.createMsg(dictModel, CacheType.UPDATE)
);
}
return ret;
}
/**
*
* @param model model
* @return
*/
@Transactional(rollbackFor = Exception.class)
@Override
public SysDictDetailModel update(SysDictDetailModel model) {
SysDictDetail entity = WrapperUtil.transformInstance(model, SysDictDetail.class);
// 唯一验证
Integer count = mapper.uniqueVerificationByNameOrValue(entity);
if(count != null && count > 0){
// 重复
throw new ServiceException(SystemMsg.EXCEL_DICT_DETAIL_UNIQUE);
}
// 旧数据 用于删除老缓存
SysDictDetailModel oldModel = this.get(model);
SysDictDetailModel ret = super.update(model);
if(ret != null){
// 先删老缓存
DictModel oldDictModel = new DictModel();
oldDictModel.setTypeCode(oldModel.getTypeCode());
oldDictModel.setDictName(oldModel.getDictName());
oldDictModel.setDictValue(oldModel.getDictValue());
DictUtil.del(oldDictModel);
// 广播缓存数据 - 通知其他服务器同步数据
redisPlugin.sendMessage(
DictMsgFactory.createMsg(oldDictModel, CacheType.DELETE)
);
// 再put新缓存
DictModel dictModel = new DictModel();
dictModel.setTypeCode(model.getTypeCode());
dictModel.setDictName(model.getDictName());
dictModel.setDictValue(model.getDictValue());
dictModel.setModel(ret);
DictUtil.put(dictModel);
// 广播缓存数据 - 通知其他服务器同步数据
redisPlugin.sendMessage(
DictMsgFactory.createMsg(dictModel, CacheType.UPDATE)
);
}
return ret;
}
/**
*
* @param id ID
* @return
*/
@Override
public boolean delete(String id) {
SysDictDetailModel sysDictDetailModel = this.get(id);
boolean ret = super.delete(id);
if(ret){
DictModel dictModel = new DictModel();
dictModel.setTypeCode(sysDictDetailModel.getTypeCode());
dictModel.setDictName(sysDictDetailModel.getDictName());
dictModel.setDictValue(sysDictDetailModel.getDictValue());
// 删除缓存
DictUtil.del(dictModel);
// 广播缓存数据 - 通知其他服务器同步数据
redisPlugin.sendMessage(
DictMsgFactory.createMsg(dictModel, CacheType.DELETE)
);
}
return ret;
}
/**
*
* @param model
* @return
*/
@Override
public boolean delete(SysDictDetailModel model) {
SysDictDetailModel sysDictDetailModel = this.get(model);
boolean ret = super.delete(model);
if(ret){
DictModel dictModel = new DictModel();
dictModel.setTypeCode(sysDictDetailModel.getTypeCode());
dictModel.setDictName(sysDictDetailModel.getDictName());
dictModel.setDictValue(sysDictDetailModel.getDictValue());
// 删除缓存
DictUtil.del(dictModel);
// 广播缓存数据 - 通知其他服务器同步数据
redisPlugin.sendMessage(
DictMsgFactory.createMsg(dictModel, CacheType.DELETE)
);
}
return ret;
}
/**
* -
* @param ids id
* @return
*/
@Override
public boolean deleteAll(String[] ids) {
QueryBuilder<SysDictDetail> queryBuilder = new GenQueryBuilder<>();
QueryWrapper<SysDictDetail> queryWrapper = queryBuilder.build();
List<?> idList = Convert.toList(ids);
queryWrapper.in(HumpUtil.humpToUnderline(MyBatisConstants.FIELD_ID),idList);
List<SysDictDetail> list = this.findList(queryWrapper);
boolean ret = super.deleteAll(ids);
if(ret){
if(list != null && list.size() > 0){
List<DictModel> dictModels = Lists.newArrayListWithCapacity(list.size());
// 删除缓存
for (SysDictDetail sysDictDetail : list) {
DictModel dictModel = new DictModel();
dictModel.setTypeCode(sysDictDetail.getTypeCode());
dictModel.setDictName(sysDictDetail.getDictName());
dictModel.setDictValue(sysDictDetail.getDictValue());
// 删除缓存
DictUtil.del(dictModel);
dictModels.add(dictModel);
}
// 广播缓存数据 - 通知其他服务器同步数据
redisPlugin.sendMessage(
DictMsgFactory.createMsg(dictModels, CacheType.DELETE)
);
}
}
return ret;
}
/**
* -
* @param models
* @return
*/
@Override
public boolean deleteAll(Collection<SysDictDetailModel> models) {
QueryBuilder<SysDictDetail> queryBuilder = new GenQueryBuilder<>();
QueryWrapper<SysDictDetail> queryWrapper = queryBuilder.build();
List<String> idList = Lists.newArrayListWithCapacity(models.size());
for (SysDictDetailModel model : models) {
idList.add(model.getId());
}
queryWrapper.in(HumpUtil.humpToUnderline(MyBatisConstants.FIELD_ID),idList);
List<SysDictDetail> list = this.findList(queryWrapper);
boolean ret = super.deleteAll(models);
if(ret){
if(list != null && list.size() > 0){
List<DictModel> dictModels = Lists.newArrayListWithCapacity(list.size());
// 删除缓存
for (SysDictDetail sysDictDetail : list) {
DictModel dictModel = new DictModel();
dictModel.setTypeCode(sysDictDetail.getTypeCode());
dictModel.setDictName(sysDictDetail.getDictName());
dictModel.setDictValue(sysDictDetail.getDictValue());
// 删除缓存
DictUtil.del(dictModel);
dictModels.add(dictModel);
}
// 广播缓存数据 - 通知其他服务器同步数据
redisPlugin.sendMessage(
DictMsgFactory.createMsg(dictModels, CacheType.DELETE)
);
}
}
return ret;
}
/**
* ID
* @param parentId ID
* @return
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean delByParent(String parentId) {
if(StringUtils.isEmpty(parentId)) return false;
String key = HumpUtil.humpToUnderline("typeId");
QueryBuilder<SysDictDetail> queryBuilder = new GenQueryBuilder<>();
QueryWrapper<SysDictDetail> queryWrapper = queryBuilder.build();
queryWrapper.eq(key, parentId);
boolean removeFlag = super.remove(queryWrapper);
if(removeFlag){
SysDictModel sysDictModel = iDictService.get(parentId);
List<SysDictDetailModel> listByTypeCode = this.findListByTypeCode(sysDictModel.getTypeCode());
if(listByTypeCode != null && listByTypeCode.size() > 0){
List<DictModel> dictList = Lists.newArrayListWithCapacity(listByTypeCode.size());
for (SysDictDetailModel sysDictDetailModel : listByTypeCode) {
DictModel dictModel = new DictModel();
dictModel.setTypeCode(sysDictDetailModel.getTypeCode());
dictModel.setDictName(sysDictDetailModel.getDictName());
dictModel.setDictValue(sysDictDetailModel.getDictValue());
dictList.add(dictModel);
}
// 删除缓存
DictUtil.delAll(sysDictModel.getTypeCode());
// 广播缓存数据 - 通知其他服务器同步数据
redisPlugin.sendMessage(
DictMsgFactory.createMsg(dictList, CacheType.DELETE)
);
}
}
return removeFlag;
}
/**
*
*
* @param typeCode
* @return
*/
@Override
public List<SysDictDetailModel> findListByTypeCode(String typeCode) {
if(StringUtils.isEmpty(typeCode)) return null;
String key = HumpUtil.humpToUnderline("typeCode");
String deleted = HumpUtil.humpToUnderline("deleted");
QueryBuilder<SysDictDetail> queryBuilder = new GenQueryBuilder<>();
QueryWrapper<SysDictDetail> queryWrapper = queryBuilder.build();
queryWrapper.eq(key, typeCode);
queryWrapper.eq(deleted, '0');
List<SysDictDetail> list = this.findList(queryWrapper);
// 转化对象
return WrapperUtil.transformInstance(list, SysDictDetailModel.class);
}
}

@ -0,0 +1,136 @@
package org.opsli.modulars.system.dict.service.impl;
import org.apache.commons.lang3.StringUtils;
import org.opsli.api.wrapper.system.dict.SysDictDetailModel;
import org.opsli.api.wrapper.system.dict.SysDictModel;
import org.opsli.common.exception.ServiceException;
import org.opsli.common.utils.WrapperUtil;
import org.opsli.core.base.service.impl.CrudServiceImpl;
import org.opsli.modulars.system.SystemMsg;
import org.opsli.modulars.system.dict.entity.SysDict;
import org.opsli.modulars.system.dict.mapper.DictMapper;
import org.opsli.modulars.system.dict.service.IDictDetailService;
import org.opsli.modulars.system.dict.service.IDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.service
* @Author: Parker
* @CreateTime: 2020-09-16 17:34
* @Description:
*/
@Service
public class DictServiceImpl extends CrudServiceImpl<DictMapper, SysDictModel, SysDict> implements IDictService {
@Autowired(required = false)
private DictMapper mapper;
@Autowired
private IDictDetailService iDictDetailService;
@Override
public SysDictModel insert(SysDictModel model) {
if(model == null) return null;
SysDict entity = WrapperUtil.transformInstance(model, SysDict.class);
// 唯一验证
Integer count = mapper.uniqueVerificationByCode(entity);
if(count != null && count > 0){
// 重复
throw new ServiceException(SystemMsg.EXCEL_DICT_UNIQUE);
}
return super.insert(model);
}
@Transactional(rollbackFor = Exception.class)
@Override
public SysDictModel update(SysDictModel model) {
if(model == null) return null;
SysDict entity = WrapperUtil.transformInstance(model, SysDict.class);
// 唯一验证
Integer count = mapper.uniqueVerificationByCode(entity);
if(count != null && count > 0){
// 重复
throw new ServiceException(SystemMsg.EXCEL_DICT_UNIQUE);
}
SysDictModel updateRet = super.update(model);
// 字典主表修改 子表跟着联动 (验证是否改了编号)/ 或者修改不允许改编号
List<SysDictDetailModel> listByTypeCode = null;
if(StringUtils.isNotEmpty(model.getTypeCode())){
listByTypeCode = iDictDetailService.findListByTypeCode(model.getTypeCode());
}
if(listByTypeCode != null && listByTypeCode.size() > 0){
for (SysDictDetailModel sysDictDetailModel : listByTypeCode) {
sysDictDetailModel.setTypeCode(updateRet.getTypeCode());
iDictDetailService.update(sysDictDetailModel);
}
}
return updateRet;
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean delete(String id) {
// 删除字典明细表
iDictDetailService.delByParent(id);
// 删除自身数据
return super.delete(id);
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean delete(SysDictModel model) {
if(model == null || StringUtils.isEmpty(model.getId())){
return false;
}
// 删除字典明细表
iDictDetailService.delByParent(model.getId());
// 删除自身数据
return super.delete(model);
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean deleteAll(String[] ids) {
if(ids == null) return false;
// 删除字典明细表
for (String id : ids) {
iDictDetailService.delByParent(id);
}
// 删除自身数据
return super.deleteAll(ids);
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean deleteAll(Collection<SysDictModel> models) {
if(models == null || models.isEmpty()) return false;
// 删除字典明细表
for (SysDictModel model : models) {
if(model == null || StringUtils.isEmpty(model.getId())){
continue;
}
iDictDetailService.delByParent(model.getId());
}
// 删除自身数据
return super.deleteAll(models);
}
}

@ -0,0 +1,166 @@
package org.opsli.modulars.system.dict.web;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.web.system.dict.DictDetailApi;
import org.opsli.api.wrapper.system.dict.SysDictDetailModel;
import org.opsli.common.annotation.ApiRestController;
import org.opsli.common.utils.WrapperUtil;
import org.opsli.core.base.concroller.BaseRestController;
import org.opsli.core.persistence.Page;
import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.persistence.querybuilder.WebQueryBuilder;
import org.opsli.modulars.system.dict.entity.SysDictDetail;
import org.opsli.modulars.system.dict.service.IDictDetailService;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.web
* @Author: Parker
* @CreateTime: 2020-09-13 17:40
* @Description:
*/
@Slf4j
@ApiRestController("/dict/detail")
public class DictDetailRestController extends BaseRestController<SysDictDetailModel, SysDictDetail, IDictDetailService>
implements DictDetailApi {
/**
*
* @param model
* @return ResultVo
*/
@ApiOperation(value = "获得单条数据", notes = "获得单条数据 - ID")
@Override
public ResultVo<SysDictDetailModel> get(SysDictDetailModel model) {
return ResultVo.success(model);
}
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
*/
@ApiOperation(value = "获得分页数据", notes = "获得分页数据 - 查询构造器")
@Override
public ResultVo<?> findPage(Integer pageNo, Integer pageSize, HttpServletRequest request) {
QueryBuilder<SysDictDetail> queryBuilder = new WebQueryBuilder<>(SysDictDetail.class, request.getParameterMap());
Page<SysDictDetailModel, SysDictDetail> page = new Page<>(pageNo, pageSize);
page.setQueryWrapper(queryBuilder.build());
page = IService.findPage(page);
return ResultVo.success(page.getBootstrapData());
}
/**
*
* @param model
* @return ResultVo
*/
@ApiOperation(value = "新增数据", notes = "新增数据")
@Override
public ResultVo<?> insert(SysDictDetailModel model) {
// 调用新增方法
IService.insert(model);
return ResultVo.success("新增成功");
}
/**
*
* @param model
* @return ResultVo
*/
@ApiOperation(value = "修改数据", notes = "修改数据")
@Override
public ResultVo<?> update(SysDictDetailModel model) {
// 调用修改方法
IService.update(model);
return ResultVo.success("修改成功");
}
/**
*
* @param id ID
* @return ResultVo
*/
@ApiOperation(value = "删除数据", notes = "删除数据")
@Override
public ResultVo<?> del(String id){
IService.delete(id);
return ResultVo.success("删除对象成功");
}
/**
*
* @param ids ID
* @return ResultVo
*/
@ApiOperation(value = "删除全部数据", notes = "删除全部数据")
@Override
public ResultVo<?> delAll(String[] ids){
IService.deleteAll(ids);
return ResultVo.success("删除对象成功");
}
/**
* Excel
* @param request request
* @param response response
* @return ResultVo
*/
@ApiOperation(value = "导出Excel", notes = "导出Excel")
@Override
public ResultVo<?> exportExcel(HttpServletRequest request, HttpServletResponse response) {
QueryBuilder<SysDictDetail> queryBuilder = new WebQueryBuilder<>(SysDictDetail.class, request.getParameterMap());
return super.excelExport(DictDetailApi.TITLE, queryBuilder.build(), response);
}
/**
* Excel
* @param request request
* @return ResultVo
*/
@ApiOperation(value = "导入Excel", notes = "导入Excel")
@Override
public ResultVo<?> excelImport(MultipartHttpServletRequest request) {
return super.excelImport(request);
}
/**
* Excel
* @param response response
* @return ResultVo
*/
@ApiOperation(value = "导出Excel模版", notes = "导出Excel模版")
@Override
public ResultVo<?> importTemplate(HttpServletResponse response) {
return super.importTemplate(DictDetailApi.TITLE, response);
}
/**
*
*
* @param typeCode
* @return
*/
@ApiOperation(value = "根据字典类型编号 查询出所有字典", notes = "根据字典类型编号 查询出所有字典")
// 权限
@Override
public ResultVo<List<SysDictDetailModel>> findListByTypeCode(String typeCode) {
return ResultVo.success(IService.findListByTypeCode(typeCode));
}
}

@ -0,0 +1,153 @@
package org.opsli.modulars.system.dict.web;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.web.system.dict.DictApi;
import org.opsli.api.web.system.dict.DictDetailApi;
import org.opsli.api.wrapper.system.dict.SysDictModel;
import org.opsli.common.annotation.ApiRestController;
import org.opsli.core.base.concroller.BaseRestController;
import org.opsli.core.persistence.Page;
import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.persistence.querybuilder.WebQueryBuilder;
import org.opsli.modulars.system.dict.entity.SysDict;
import org.opsli.modulars.system.dict.service.IDictService;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.web
* @Author: Parker
* @CreateTime: 2020-09-13 17:40
* @Description:
*/
@Slf4j
@ApiRestController("/dict")
public class DictRestController extends BaseRestController<SysDictModel, SysDict, IDictService>
implements DictApi {
/**
*
* @param model
* @return ResultVo
*/
@ApiOperation(value = "获得单条数据", notes = "获得单条数据 - ID")
@Override
public ResultVo<SysDictModel> get(SysDictModel model) {
return ResultVo.success(model);
}
/**
*
* @param pageNo
* @param pageSize
* @param request request
* @return ResultVo
*/
@ApiOperation(value = "获得分页数据", notes = "获得分页数据 - 查询构造器")
@Override
public ResultVo<?> findPage(Integer pageNo, Integer pageSize, HttpServletRequest request) {
QueryBuilder<SysDict> queryBuilder = new WebQueryBuilder<>(SysDict.class, request.getParameterMap());
Page<SysDictModel, SysDict> page = new Page<>(pageNo, pageSize);
page.setQueryWrapper(queryBuilder.build());
page = IService.findPage(page);
return ResultVo.success(page.getBootstrapData());
}
/**
*
* @param model
* @return ResultVo
*/
@ApiOperation(value = "新增数据", notes = "新增数据")
@Override
public ResultVo<?> insert(SysDictModel model) {
// 调用新增方法
IService.insert(model);
return ResultVo.success("新增成功");
}
/**
*
* @param model
* @return ResultVo
*/
@ApiOperation(value = "修改数据", notes = "修改数据")
@Override
public ResultVo<?> update(SysDictModel model) {
// 调用修改方法
IService.update(model);
return ResultVo.success("修改成功");
}
/**
*
* @param id ID
* @return ResultVo
*/
@ApiOperation(value = "删除数据", notes = "删除数据")
@Override
public ResultVo<?> del(String id){
IService.delete(id);
return ResultVo.success("删除对象成功");
}
/**
*
* @param ids ID
* @return ResultVo
*/
@ApiOperation(value = "删除全部数据", notes = "删除全部数据")
@Override
public ResultVo<?> delAll(String[] ids){
IService.deleteAll(ids);
return ResultVo.success("删除对象成功");
}
/**
* Excel
* @param request request
* @param response response
* @return ResultVo
*/
@ApiOperation(value = "导出Excel", notes = "导出Excel")
@Override
public ResultVo<?> exportExcel(HttpServletRequest request, HttpServletResponse response) {
QueryBuilder<SysDict> queryBuilder = new WebQueryBuilder<>(SysDict.class, request.getParameterMap());
return super.excelExport(DictDetailApi.TITLE, queryBuilder.build(), response);
}
/**
* Excel
* @param request request
* @return ResultVo
*/
@ApiOperation(value = "导入Excel", notes = "导入Excel")
@Override
public ResultVo<?> excelImport(MultipartHttpServletRequest request) {
return super.excelImport(request);
}
/**
* Excel
* @param response response
* @return ResultVo
*/
@ApiOperation(value = "导出Excel模版", notes = "导出Excel模版")
@Override
public ResultVo<?> importTemplate(HttpServletResponse response) {
return super.importTemplate(DictDetailApi.TITLE, response);
}
}

@ -1,66 +0,0 @@
package org.opsli.modulars.test.entity;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.*;
import lombok.Data;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.opsli.plugins.excel.annotation.CellStyleFormat;
import java.io.Serializable;
/**
* Created Date by 2020/5/9 0009.
*
* Excel
* @author Parker
*/
@Data
@ContentRowHeight(16)
@HeadRowHeight(21)
@HeadFontStyle(fontName = "Arial",color = 9,fontHeightInPoints = 10)
@HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 23)
@ColumnWidth(22)
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
/** 名称 */
@ExcelProperty(value = "名称",index = 0)
@CellStyleFormat
private String name;
/** 编号 */
@ExcelProperty(value = "编号",index = 1)
@CellStyleFormat
private String code;
/** 年龄 */
@ExcelProperty(value = "年龄",index = 2)
@CellStyleFormat
private Integer age;
/** 性别 */
@ExcelProperty(value = "性别",index = 3)
@CellStyleFormat
private Integer sex;
/** 金额 */
// @ExcelProperty(value = "金额",index = 4)
// @CellStyleFormat
private Double amt;
/**
*
*/
public Test() {
}
public Test(String name, String code, Integer age, Integer sex, Double amt) {
this.name = name;
this.code = code;
this.age = age;
this.sex = sex;
this.amt = amt;
}
}

@ -1,20 +1,24 @@
package org.opsli.modulars.test.web;
import cn.hutool.core.thread.ThreadUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.web.test.TestApi;
import org.opsli.api.wrapper.system.dict.DictModel;
import org.opsli.api.wrapper.test.TestModel;
import org.opsli.common.annotation.ApiRestController;
import org.opsli.common.utils.WrapperUtil;
import org.opsli.core.base.concroller.BaseRestController;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.enums.CacheType;
import org.opsli.core.cache.pushsub.msgs.DictMsgFactory;
import org.opsli.core.persistence.Page;
import org.opsli.core.persistence.PageQueryBuilder;
import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.persistence.querybuilder.WebQueryBuilder;
import org.opsli.core.utils.DictUtil;
import org.opsli.modulars.test.entity.TestEntity;
import org.opsli.modulars.test.service.ITestService;
import org.opsli.plugins.mail.MailPlugin;
@ -24,6 +28,8 @@ import org.opsli.plugins.redis.RedisPlugin;
import org.opsli.plugins.redis.lock.RedisLock;
import org.opsli.plugins.redis.pushsub.entity.BaseSubMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
@ -77,8 +83,9 @@ public class TestRestRestController extends BaseRestController<TestModel, TestEn
@ApiOperation(value = "发送 Redis 订阅消息", notes = "发送 Redis 订阅消息")
@Override
public ResultVo<?> sendMsg(){
DictModel model = new DictModel();
BaseSubMessage msg = DictMsgFactory.createMsg("test", "aaa", 123213, CacheType.UPDATE);
BaseSubMessage msg = DictMsgFactory.createMsg(model, CacheType.UPDATE);
boolean ret = redisPlugin.sendMessage(msg);
if(ret){
@ -130,7 +137,7 @@ public class TestRestRestController extends BaseRestController<TestModel, TestEn
redisLockPlugins.unLock(redisLock);
ResultVo<RedisLock> success = ResultVo.success("获得锁成功!!!!!!",redisLock);
success.put(redisLock);
success.setData(redisLock);
return success;
}
@ -238,11 +245,13 @@ public class TestRestRestController extends BaseRestController<TestModel, TestEn
@ApiOperation(value = "查找一个集合", notes = "查找一个集合")
@Override
public ResultVo<List<TestModel>> findList() {
QueryWrapper<TestEntity> queryWrapper = new QueryWrapper<>();
List<TestEntity> list = IService.findList(queryWrapper);
List<TestModel> testModels = WrapperUtil.transformInstance(list, TestModel.class);
return ResultVo.success(testModels);
public ResultVo<List<TestModel>> findList(HttpServletRequest request) {
QueryBuilder<TestEntity> queryBuilder = new WebQueryBuilder<>(TestEntity.class, request.getParameterMap());
List<TestEntity> entitys = IService.findList(queryBuilder.build());
List<TestModel> models = WrapperUtil.transformInstance(entitys, TestModel.class);
return ResultVo.success(models);
}
@ApiOperation(value = "查找全部数据", notes = "查找全部数据")
@ -256,20 +265,20 @@ public class TestRestRestController extends BaseRestController<TestModel, TestEn
@ApiOperation(value = "查询分页", notes = "查询分页")
@Override
public ResultVo<?> findPage(Integer pageNo, Integer pageSize, HttpServletRequest request) {
PageQueryBuilder<TestModel,TestEntity> pageQueryBuilder = new PageQueryBuilder<>(
TestEntity.class, pageNo, pageSize, request.getParameterMap()
);
Page<TestModel, TestEntity> page = IService.findPage(pageQueryBuilder.builderPage());
QueryBuilder<TestEntity> queryBuilder = new WebQueryBuilder<>(TestEntity.class, request.getParameterMap());
Page<TestModel, TestEntity> page = new Page<>(pageNo, pageSize);
page.setQueryWrapper(queryBuilder.build());
page = IService.findPage(page);
return ResultVo.success(page.getBootstrapData());
}
@ApiOperation(value = "导出Excel", notes = "导出Excel")
@Override
public ResultVo<?> exportExcel(HttpServletRequest request, HttpServletResponse response) {
PageQueryBuilder<TestModel,TestEntity> pageQueryBuilder = new PageQueryBuilder<>(
TestEntity.class, request.getParameterMap()
);
return super.excelExport("测试", pageQueryBuilder.builderQueryWrapper(), response);
QueryBuilder<TestEntity> queryBuilder = new WebQueryBuilder<>(TestEntity.class, request.getParameterMap());
return super.excelExport("测试", queryBuilder.build(), response);
}
@ApiOperation(value = "导入Excel", notes = "导入Excel")
@ -284,4 +293,22 @@ public class TestRestRestController extends BaseRestController<TestModel, TestEn
return super.importTemplate("测试", response);
}
@ApiOperation(value = "获得字典 - By Name", notes = "获得字典 - By Name")
@GetMapping("/getDictByName")
public ResultVo<?> getDictByName(@RequestParam(name = "typeCode") String typeCode,
@RequestParam(name = "name") String name){
String value = DictUtil.getDictValueByName(typeCode, name, "我空了");
return ResultVo.success().setData(value);
}
@ApiOperation(value = "获得字典 - By Value", notes = "获得字典 - By Value")
@GetMapping("/getDictByValue")
public ResultVo<?> getDictByValue(@RequestParam(name = "typeCode") String typeCode,
@RequestParam(name = "value") String value){
String name = DictUtil.getDictNameByValue(typeCode, value, "我空了");
return ResultVo.success().setData(name);
}
}

@ -1,12 +1,19 @@
package org.opsli.modulars.test.web;
import io.swagger.annotations.ApiOperation;
import org.opsli.api.base.result.ResultVo;
import org.opsli.api.web.test.TestApi;
import org.opsli.api.wrapper.test.TestModel;
import org.opsli.common.annotation.ApiRestController;
import org.opsli.common.constants.CacheConstants;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.plugins.cache.EhCachePlugin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.ArrayList;
import java.util.List;
/**
* @BelongsProject: opsli-boot
@ -20,13 +27,22 @@ public class TestRestRestController2{
@Autowired
TestApi testApi;
@Autowired
EhCachePlugin ehCachePlugin;
@GetMapping("/insert2")
public ResultVo<TestModel> insert(){
for (int i = 0; i < 999; i++) {
testApi.insert(new TestModel());
@ApiOperation(value = "测试2", notes = "测试2")
@GetMapping("/getDictBy")
public ResultVo<?> t1(){
String id = "test";
List<TestModel> testModelList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
TestModel testModel = new TestModel();
testModel.setId(id+i);
testModel.setName("测试数据"+i);
testModelList.add(testModel);
CacheUtil.put(id+i,testModel);
}
return testApi.insert(new TestModel());
return ResultVo.success(testModelList);
}

@ -17,6 +17,7 @@
<!-- 模块 -->
<modules>
<module>opsli-modulars-test</module>
<module>opsli-modulars-system</module>
</modules>
<!-- 规定子类所引用的版本***** -->

@ -120,7 +120,7 @@ public final class ExcelUtil {
sheetName = "sheet1";
}
fileName = fileName+ DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
fileName = fileName+"-"+DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
OutputStream outputStream = getOutputStream(fileName, response, excelTypeEnum);
ExcelWriter excelWriter = EasyExcel.write(outputStream, classType).build();
WriteSheet writeSheet = EasyExcel.writerSheet(1, sheetName).build();

@ -174,6 +174,19 @@ public class RedisPlugin {
return redisTemplate.opsForValue().get(key);
}
/**
* -
*
* @param keys Redis
* @return
*/
public List<Object> getAll(Collection<String> keys) {
if(keys == null || keys.size() == 0){
return null;
}
return redisTemplate.opsForValue().multiGet(keys);
}
/**

@ -12,6 +12,8 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public class RedisLock {
private static final String LOCK_PREFIX = "opsli:lock:";
/** 锁名称 */
private String lockName;
@ -41,7 +43,7 @@ public class RedisLock {
*
*/
public RedisLock(String lockName, Long acquireTimeOut, Long lockTimeOut, String identifier) {
this.lockName = lockName;
this.lockName = LOCK_PREFIX + lockName;
this.acquireTimeOut = acquireTimeOut;
this.lockTimeOut = lockTimeOut;
this.identifier = identifier;
@ -69,7 +71,7 @@ public class RedisLock {
}
public RedisLock setLockName(String lockName) {
this.lockName = lockName;
this.lockName = LOCK_PREFIX + lockName;
return this;
}

@ -35,6 +35,12 @@
<!-- ———————————————————— 模块 - 开始 ———————————————————— -->
<!-- 系统模块 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-modulars-system</artifactId>
<version>${modulars.version}</version>
</dependency>
<!-- 引入测试业务模块 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>

@ -19,7 +19,7 @@
</resources>
</cache-template>
<!-- hotData 热点数据,它使用名为myDefaults的<cache-template>,并将其主键覆盖到更广泛的类型 -->
<!-- hotData 热点数据,它使用名为opsliDefaults的<cache-template>,并将其主键覆盖到更广泛的类型 -->
<cache alias="hotData" uses-template="opsliDefaults">
<!--缓存到期配置-->
<expiry>

Loading…
Cancel
Save