新增参数配置模块

v1.4.1
hiparker 4 years ago
parent fc83a6dcef
commit 01de876b14

@ -205,19 +205,6 @@
│ │ │ │ │ ├── listener Excel插件 - 监听器 │ │ │ │ │ ├── listener Excel插件 - 监听器
│ │ │ │ │ └── msg Excel插件 - 信息 │ │ │ │ │ └── msg Excel插件 - 信息
│ │ │ │ │ │ │ │ │ │
│ ├── opsli-plugins-mail 邮件插件
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── java
│ │ │ │ │ └── org
│ │ │ │ │ └── opsli
│ │ │ │ │ └── plugins
│ │ │ │ │ └── mail
│ │ │ │ │ ├── exception 邮件插件 - 异常类
│ │ │ │ │ ├── handler 邮件插件 - 处理类
│ │ │ │ │ ├── model 邮件插件 - 模型
│ │ │ │ │ └── msg 邮件插件 - 信息
│ │ │ │ │
│ └── opsli-plugins-redis Redis缓存插件(一级缓存) │ └── opsli-plugins-redis Redis缓存插件(一级缓存)
│ │ ├── src │ │ ├── src
│ │ │ ├── main │ │ │ ├── main

@ -21,7 +21,7 @@ SET FOREIGN_KEY_CHECKS = 0;
ALTER TABLE `sys_user` CHANGE COLUMN `locked` `enable` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '' AFTER `secret_key`; ALTER TABLE `sys_user` CHANGE COLUMN `locked` `enable` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '' AFTER `secret_key`;
-- --
ALTER TABLE `sys_tenant` CHANGE COLUMN `iz_usable` `enable` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT ' 01' AFTER `tenant_name`; ALTER TABLE `sys_tenant` CHANGE COLUMN `iz_usable` `enable` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT ' 01' AFTER `tenant_name`;
-- --
-- ---------------------------- -- ----------------------------
@ -39,8 +39,8 @@ CREATE TABLE `sys_menu` (
`component` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '', `component` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '',
`redirect` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '', `redirect` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '',
`sort_no` int(11) NOT NULL COMMENT '', `sort_no` int(11) NOT NULL COMMENT '',
`always_show` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT ' 01', `always_show` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT ' 01',
`hidden` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT ' 01', `hidden` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT ' 01',
`deleted` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '', `deleted` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '',
`version` int(11) NOT NULL COMMENT '', `version` int(11) NOT NULL COMMENT '',
`create_by` bigint(19) NOT NULL COMMENT '', `create_by` bigint(19) NOT NULL COMMENT '',

File diff suppressed because it is too large Load Diff

@ -67,8 +67,8 @@ public class DictDetailModel extends ApiWrapper {
@ValidationArgsLenMax(120) @ValidationArgsLenMax(120)
private String dictValue; private String dictValue;
/** 是否内置数据 0是 1否*/ /** 是否内置数据 0否 1是*/
@ApiModelProperty(value = "是否内置数据 0是 1否") @ApiModelProperty(value = "是否内置数据 0否 1是")
@ExcelProperty(value = "是否内置数据", order = 2) @ExcelProperty(value = "是否内置数据", order = 2)
@ExcelInfo(dictType = "no_yes") @ExcelInfo(dictType = "no_yes")
@ValidationArgs({ValiArgsType.IS_NOT_NULL}) @ValidationArgs({ValiArgsType.IS_NOT_NULL})

@ -54,8 +54,8 @@ public class DictModel extends ApiWrapper {
@ValidationArgsLenMax(120) @ValidationArgsLenMax(120)
private String typeName; private String typeName;
/** 是否内置数据 0是 1否*/ /** 是否内置数据 0否 1是*/
@ApiModelProperty(value = "是否内置数据 0是 1否") @ApiModelProperty(value = "是否内置数据 0否 1是")
@ExcelProperty(value = "是否内置数据", order = 3) @ExcelProperty(value = "是否内置数据", order = 3)
@ExcelInfo(dictType = "no_yes") @ExcelInfo(dictType = "no_yes")
@ValidationArgs(ValiArgsType.IS_NOT_NULL) @ValidationArgs(ValiArgsType.IS_NOT_NULL)

@ -50,25 +50,34 @@ public class OptionsModel extends ApiWrapper {
@ValidationArgsLenMax(100) @ValidationArgsLenMax(100)
private String optionCode; private String optionCode;
/** 参数名称 */ /** 参数名称 */
@ApiModelProperty(value = "参数名称") @ApiModelProperty(value = "参数名称")
@ExcelProperty(value = "参数名称", order = 2) @ExcelProperty(value = "参数名称", order = 2)
@ExcelInfo @ExcelInfo
@ValidationArgs({ValiArgsType.IS_NOT_NULL, ValiArgsType.IS_GENERAL_WITH_CHINESE})
@ValidationArgsLenMax(200) @ValidationArgsLenMax(200)
private String optionName; private String optionName;
/** 参数值 */ /** 参数值 */
@ApiModelProperty(value = "参数值") @ApiModelProperty(value = "参数值")
@ExcelProperty(value = "参数值", order = 3) @ExcelProperty(value = "参数值", order = 3)
@ExcelInfo @ExcelInfo
@ValidationArgsLenMax(500) @ValidationArgs({ValiArgsType.IS_NOT_NULL})
@ValidationArgsLenMax(10000)
private String optionValue; private String optionValue;
/** 是否内置数据 0否 1是*/
@ApiModelProperty(value = "是否内置数据 0否 1是")
@ExcelProperty(value = "是否内置数据", order = 4)
@ExcelInfo(dictType = "no_yes")
@ValidationArgsLenMax(1)
private String izLock;
/** 备注 */
@ApiModelProperty(value = "备注")
@ExcelProperty(value = "备注", order = 5)
@ExcelInfo
@ValidationArgsLenMax(255)
private String remark;
} }

@ -55,8 +55,8 @@ public class RoleModel extends ApiWrapper {
@ValidationArgsLenMax(50) @ValidationArgsLenMax(50)
private String roleName; private String roleName;
/** 是否内置数据 0是 1否*/ /** 是否内置数据 0否 1是*/
@ApiModelProperty(value = "是否内置数据 0是 1否") @ApiModelProperty(value = "是否内置数据 0否 1是")
@ExcelProperty(value = "是否内置数据", order = 3) @ExcelProperty(value = "是否内置数据", order = 3)
@ExcelInfo(dictType = "no_yes") @ExcelInfo(dictType = "no_yes")
@ValidationArgs({ValiArgsType.IS_NOT_NULL}) @ValidationArgs({ValiArgsType.IS_NOT_NULL})

@ -45,7 +45,7 @@ public class TenantModel extends ApiWrapper {
@ValidationArgsLenMax(50) @ValidationArgsLenMax(50)
private String tenantName; private String tenantName;
/** 是否启用 0是 1否*/ /** 是否启用 0否 1是*/
@ApiModelProperty(value = "是否启用") @ApiModelProperty(value = "是否启用")
@ExcelProperty(value = "是否启用", order = 2) @ExcelProperty(value = "是否启用", order = 2)
@ExcelInfo(dictType = "no_yes") @ExcelInfo(dictType = "no_yes")

@ -20,8 +20,6 @@ public class ApplicationReadyEventListener implements ApplicationListener<Applic
@Override @Override
public void onApplicationEvent(ApplicationReadyEvent event) { public void onApplicationEvent(ApplicationReadyEvent event) {
event.getApplicationContext(); event.getApplicationContext();
// 加载配置参数
OptionsUtil.loadAllOption();
// 输出启动日志 // 输出启动日志
StartPrint.getInstance().successPrint(); StartPrint.getInstance().successPrint();
} }

@ -133,83 +133,6 @@ public class OptionsUtil {
return model; return model;
} }
/**
*
* @return Map
*/
public static Map<String, OptionsModel> findAllOptions(){
List<OptionsModel> optionsModels;
Map<String, OptionsModel> optionsModelMap;
// 处理集合数据
optionsModels = handleOptionsList(
CacheUtil.getHashAll(PREFIX_CODE));
// 转换对象
optionsModelMap = convertOptionsMap(optionsModels);
if(CollUtil.isNotEmpty(optionsModelMap)){
return optionsModelMap;
}
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_CODE);
if(hasNilFlag){
return optionsModelMap;
}
try {
// 分布式加锁
if(!DistributedLockUtil.lock(PREFIX_CODE)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return optionsModelMap;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
// 处理集合数据
optionsModels = handleOptionsList(
CacheUtil.getHashAll(PREFIX_CODE));
// 转换对象
optionsModelMap = convertOptionsMap(optionsModels);
if(CollUtil.isNotEmpty(optionsModelMap)){
return optionsModelMap;
}
// 数据库查询数据
ResultVo<List<OptionsModel>> optionsApiAll = optionsApi.findAll();
if(optionsApiAll.isSuccess()){
// 处理数据
optionsModelMap = convertOptionsMap(optionsApiAll.getData());
if(CollUtil.isNotEmpty(optionsModelMap)){
// 保存至缓存
for (Map.Entry<String, OptionsModel> entry : optionsModelMap.entrySet()) {
String optionCode = entry.getKey();
OptionsModel model = entry.getValue();
CacheUtil.putHash(PREFIX_CODE, optionCode, model);
}
// 返回数据
return optionsModelMap;
}
}
}catch (Exception e){
log.error(e.getMessage(),e);
return optionsModelMap;
}finally {
// 释放锁
DistributedLockUtil.unlock(PREFIX_CODE);
}
// 如果值还是 为空 则赋默认值
if(CollUtil.isEmpty(optionsModelMap)){
// 加入缓存防穿透
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(PREFIX_CODE);
}
return optionsModelMap;
}
// ============== 刷新缓存 ============== // ============== 刷新缓存 ==============
/** /**
@ -255,47 +178,6 @@ public class OptionsUtil {
return count == 0; return count == 0;
} }
/**
*
* @return boolean
*/
public static boolean loadAllOption(){
try {
// 分布式加锁
if(!DistributedLockUtil.lock(PREFIX_CODE)){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return false;
}
// 数据库查询数据
ResultVo<List<OptionsModel>> optionsApiAll = optionsApi.findAll();
if(optionsApiAll.isSuccess()){
// 处理数据
Map<String, OptionsModel> optionsModelMap = convertOptionsMap(optionsApiAll.getData());
if(CollUtil.isNotEmpty(optionsModelMap)){
// 保存至缓存
for (Map.Entry<String, OptionsModel> entry : optionsModelMap.entrySet()) {
String optionCode = entry.getKey();
OptionsModel model = entry.getValue();
CacheUtil.putHash(PREFIX_CODE, optionCode, model);
}
// 返回数据
return true;
}
}
}catch (Exception e){
log.error(e.getMessage(),e);
return false;
}finally {
// 释放锁
DistributedLockUtil.unlock(PREFIX_CODE);
}
return false;
}
/** /**
* *
* @param optionsMap List * @param optionsMap List

@ -17,7 +17,6 @@ opsli:
- sys_user_org_ref - sys_user_org_ref
- sys_area - sys_area
- sys_org - sys_org
- sys_options
# 排除字段 # 排除字段

@ -100,6 +100,7 @@ public enum SystemMsg implements BaseMsg {
*/ */
EXCEPTION_OPTIONS_UNIQUE(20700,"参数编号重复,该角色已存在"), EXCEPTION_OPTIONS_UNIQUE(20700,"参数编号重复,该角色已存在"),
EXCEPTION_OPTIONS_UPDATE(20701,"更新异常"), EXCEPTION_OPTIONS_UPDATE(20701,"更新异常"),
EXCEPTION_OPTIONS_LOCKED(20702,"内置数据不可变更"),
/** /**

@ -41,7 +41,7 @@ public class SysDict extends BaseEntity {
/** 字典类型名称 */ /** 字典类型名称 */
private String typeName; private String typeName;
/** 是否内置数据 0是 1否*/ /** 是否内置数据 0否 1是*/
private String izLock; private String izLock;
/** 备注 */ /** 备注 */

@ -46,7 +46,7 @@ public class SysDictDetail extends BaseEntity {
/** 字典值 */ /** 字典值 */
private String dictValue; private String dictValue;
/** 是否内置数据 0是 1否*/ /** 是否内置数据 0否 1是*/
private String izLock; private String izLock;
/** 排序 */ /** 排序 */

@ -45,6 +45,13 @@ public class SysOptions extends BaseEntity {
/** 参数值 */ /** 参数值 */
private String optionValue; private String optionValue;
/** 是否内置数据 0否 1是*/
private String izLock;
/** 备注 */
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String remark;
// ======================================== // ========================================

@ -26,9 +26,7 @@ import org.opsli.modulars.system.options.entity.SysOptions;
/** /**
* @BelongsProject: opsli-boot * @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.system.options.mapper * @BelongsPackage: org.opsli.modulars.system.options.mapper
* @Author: Parker * @Author: Parker
* @CreateTime: 2021-02-07 18:24:38 * @CreateTime: 2021-02-07 18:24:38
* @Description: Mapper * @Description: Mapper

@ -29,9 +29,7 @@ import java.util.Map;
/** /**
* @BelongsProject: opsli-boot * @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.system.options.service * @BelongsPackage: org.opsli.modulars.system.options.service
* @Author: Parker * @Author: Parker
* @CreateTime: 2021-02-07 18:24:38 * @CreateTime: 2021-02-07 18:24:38
* @Description: Service * @Description: Service

@ -25,10 +25,12 @@ import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.opsli.api.wrapper.system.options.OptionsModel; import org.opsli.api.wrapper.system.options.OptionsModel;
import org.opsli.common.constants.MyBatisConstants; import org.opsli.common.constants.MyBatisConstants;
import org.opsli.common.enums.DictType;
import org.opsli.common.exception.ServiceException; import org.opsli.common.exception.ServiceException;
import org.opsli.core.base.service.impl.CrudServiceImpl; import org.opsli.core.base.service.impl.CrudServiceImpl;
import org.opsli.core.msg.CoreMsg; import org.opsli.core.msg.CoreMsg;
import org.opsli.core.utils.OptionsUtil; import org.opsli.core.utils.OptionsUtil;
import org.opsli.core.utils.ValidationUtil;
import org.opsli.modulars.system.SystemMsg; import org.opsli.modulars.system.SystemMsg;
import org.opsli.modulars.system.options.entity.SysOptions; import org.opsli.modulars.system.options.entity.SysOptions;
import org.opsli.modulars.system.options.mapper.SysOptionsMapper; import org.opsli.modulars.system.options.mapper.SysOptionsMapper;
@ -44,9 +46,7 @@ import java.util.Map;
/** /**
* @BelongsProject: opsli-boot * @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.system.options.service.impl * @BelongsPackage: org.opsli.modulars.system.options.service.impl
* @Author: Parker * @Author: Parker
* @CreateTime: 2021-02-07 18:24:38 * @CreateTime: 2021-02-07 18:24:38
* @Description: Service Impl * @Description: Service Impl
@ -65,6 +65,9 @@ public class SysOptionsServiceImpl extends CrudServiceImpl<SysOptionsMapper, Sys
return null; return null;
} }
// 验证数据
ValidationUtil.verify(model);
// 唯一验证 // 唯一验证
Integer count = this.uniqueVerificationByCode(model); Integer count = this.uniqueVerificationByCode(model);
if(count != null && count > 0){ if(count != null && count > 0){
@ -72,6 +75,16 @@ public class SysOptionsServiceImpl extends CrudServiceImpl<SysOptionsMapper, Sys
throw new ServiceException(SystemMsg.EXCEPTION_OPTIONS_UNIQUE); throw new ServiceException(SystemMsg.EXCEPTION_OPTIONS_UNIQUE);
} }
if (!model.getIzApi()){
// 强制为不内置
model.setIzLock(DictType.NO_YES_NO.getValue());
}
// 如果参数名称为空 则 默认为Code
if(StringUtils.isEmpty(model.getOptionName())){
model.setOptionName(model.getOptionCode());
}
return super.insert(model); return super.insert(model);
} }
@ -82,6 +95,25 @@ public class SysOptionsServiceImpl extends CrudServiceImpl<SysOptionsMapper, Sys
return null; return null;
} }
// 验证数据
ValidationUtil.verify(model);
// 验证是否是内置数据
OptionsModel optionsModel = this.get(model);
if(optionsModel == null){
return null;
}
if (!model.getIzApi()){
if(DictType.NO_YES_YES.getValue().equals(optionsModel.getIzLock())){
// 内置数据不可变更
throw new ServiceException(SystemMsg.EXCEPTION_OPTIONS_LOCKED);
}
// 强制为不内置
model.setIzLock(DictType.NO_YES_NO.getValue());
}
// 唯一验证 // 唯一验证
Integer count = this.uniqueVerificationByCode(model); Integer count = this.uniqueVerificationByCode(model);
if(count != null && count > 0){ if(count != null && count > 0){
@ -89,8 +121,18 @@ public class SysOptionsServiceImpl extends CrudServiceImpl<SysOptionsMapper, Sys
throw new ServiceException(SystemMsg.EXCEPTION_OPTIONS_UNIQUE); throw new ServiceException(SystemMsg.EXCEPTION_OPTIONS_UNIQUE);
} }
String optionCode = model.getOptionCode();
// 参数编号不可修改
model.setOptionCode(null);
// 如果参数名称为空 则 默认为Code
if(StringUtils.isEmpty(model.getOptionName())){
model.setOptionName(model.getOptionCode());
}
model = super.update(model); model = super.update(model);
if(model != null){ if(model != null){
model.setOptionCode(optionCode);
// 清除缓存 // 清除缓存
this.clearCache(Collections.singletonList(model)); this.clearCache(Collections.singletonList(model));
} }
@ -127,16 +169,31 @@ public class SysOptionsServiceImpl extends CrudServiceImpl<SysOptionsMapper, Sys
OptionsModel optionsModel = resourceDataDict.get(key); OptionsModel optionsModel = resourceDataDict.get(key);
if(optionsModel == null){ if(optionsModel == null){
// 更新异常 optionsModel = new OptionsModel();
throw new ServiceException(SystemMsg.EXCEPTION_OPTIONS_UPDATE); // 新增参数
// 设置值
optionsModel.setIzApi(true);
optionsModel.setOptionCode(key);
optionsModel.setOptionValue(value);
optionsModel.setVersion(0);
// 强制设置为内置数据
optionsModel.setIzLock(DictType.NO_YES_YES.getValue());
// 更新
this.insert(optionsModel);
}else {
// 修改参数
// 设置值
optionsModel.setIzApi(true);
optionsModel.setOptionValue(value);
// 强制设置为内置数据
optionsModel.setIzLock(DictType.NO_YES_YES.getValue());
// 更新
this.update(optionsModel);
} }
// 设置值
optionsModel.setOptionValue(value);
optionsModel.setVersion(null);
// 更新
this.update(optionsModel);
} }
} }
@ -144,6 +201,16 @@ public class SysOptionsServiceImpl extends CrudServiceImpl<SysOptionsMapper, Sys
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public boolean delete(String id) { public boolean delete(String id) {
OptionsModel model = super.get(id); OptionsModel model = super.get(id);
if(model == null){
return false;
}
// 验证是否是内置数据
if(DictType.NO_YES_YES.getValue().equals(model.getIzLock())){
// 内置数据不可变更
throw new ServiceException(SystemMsg.EXCEPTION_OPTIONS_LOCKED);
}
boolean ret = super.delete(id); boolean ret = super.delete(id);
if(ret){ if(ret){
@ -162,6 +229,14 @@ public class SysOptionsServiceImpl extends CrudServiceImpl<SysOptionsMapper, Sys
super.findList(queryWrapper) super.findList(queryWrapper)
); );
// 验证是否是内置数据
for (OptionsModel model : modelList) {
if(DictType.NO_YES_YES.getValue().equals(model.getIzLock())){
// 内置数据不可变更
throw new ServiceException(SystemMsg.EXCEPTION_OPTIONS_LOCKED);
}
}
// 清除缓存 // 清除缓存
this.clearCache(modelList); this.clearCache(modelList);

@ -31,6 +31,7 @@ import org.opsli.common.annotation.ApiRestController;
import org.opsli.common.annotation.EnableLog; import org.opsli.common.annotation.EnableLog;
import org.opsli.common.annotation.RequiresPermissionsCus; import org.opsli.common.annotation.RequiresPermissionsCus;
import org.opsli.common.enums.CryptoAsymmetricType; import org.opsli.common.enums.CryptoAsymmetricType;
import org.opsli.common.enums.DictType;
import org.opsli.common.utils.WrapperUtil; import org.opsli.common.utils.WrapperUtil;
import org.opsli.core.base.controller.BaseRestController; import org.opsli.core.base.controller.BaseRestController;
import org.opsli.core.persistence.Page; import org.opsli.core.persistence.Page;
@ -93,8 +94,13 @@ public class SysOptionsRestController extends BaseRestController<SysOptions, Opt
public ResultVo<?> findPage(Integer pageNo, Integer pageSize, HttpServletRequest request) { public ResultVo<?> findPage(Integer pageNo, Integer pageSize, HttpServletRequest request) {
QueryBuilder<SysOptions> queryBuilder = new WebQueryBuilder<>(entityClazz, request.getParameterMap()); QueryBuilder<SysOptions> queryBuilder = new WebQueryBuilder<>(entityClazz, request.getParameterMap());
// 查询不是内置的数据
QueryWrapper<SysOptions> queryWrapper = queryBuilder.build();
queryWrapper.eq("iz_lock", DictType.NO_YES_NO.getValue());
Page<SysOptions, OptionsModel> page = new Page<>(pageNo, pageSize); Page<SysOptions, OptionsModel> page = new Page<>(pageNo, pageSize);
page.setQueryWrapper(queryBuilder.build()); page.setQueryWrapper(queryWrapper);
page = IService.findPage(page); page = IService.findPage(page);
return ResultVo.success(page.getPageData()); return ResultVo.success(page.getPageData());
@ -269,8 +275,11 @@ public class SysOptionsRestController extends BaseRestController<SysOptions, Opt
*/ */
@Override @Override
public ResultVo<Map<String, OptionsModel>> findAllOptions() { public ResultVo<Map<String, OptionsModel>> findAllOptions() {
QueryWrapper<SysOptions> queryWrapper = new QueryWrapper<>();
// 查询内置数据
queryWrapper.eq("iz_lock", DictType.NO_YES_YES.getValue());
// 数据库查询数据 // 数据库查询数据
List<SysOptions> allList = IService.findAllList(); List<SysOptions> allList = IService.findList(queryWrapper);
return ResultVo.success( return ResultVo.success(
OptionsUtil.convertOptionsMap( OptionsUtil.convertOptionsMap(
WrapperUtil.transformInstance(allList, OptionsModel.class)) WrapperUtil.transformInstance(allList, OptionsModel.class))

@ -41,7 +41,7 @@ public class SysRole extends BaseEntity {
/** 角色名称 */ /** 角色名称 */
private String roleName; private String roleName;
/** 是否内置数据 0是 1否*/ /** 是否内置数据 0否 1是*/
private String izLock; private String izLock;
/** 备注 */ /** 备注 */

@ -37,7 +37,7 @@ public class SysTenant extends BaseEntity {
/** 租户名称 */ /** 租户名称 */
private String tenantName; private String tenantName;
/** 是否启用 0是 1否*/ /** 是否启用 0否 1是*/
private String enable; private String enable;
/** 备注 */ /** 备注 */

@ -0,0 +1,71 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.modulars.tools.email.service;
import java.util.Collection;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.system.service
* @Author: Parker
* @CreateTime: 2020-09-17 13:07
* @Description:
*/
public interface IEmailService {
/**
*
* @param to
* @param subject
* @param content
* @return String
*/
String send(String to, String subject, String content);
/**
*
* @param tos ()
* @param subject
* @param content
* @return String
*/
String send(Collection<String> tos, String subject, String content);
/**
*
* @param to
* @param subject
* @param content
* @param isHtml Html
* @return String
*/
String send(String to, String subject, String content, boolean isHtml);
/**
*
* @param tos
* @param subject
* @param content
* @param isHtml Html
* @return String
*/
String send(Collection<String> tos, String subject, String content, boolean isHtml);
}

@ -14,11 +14,6 @@
<version>${project.parent.version}</version> <version>${project.parent.version}</version>
<dependencies> <dependencies>
<!-- 引入邮件插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-mail</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -1,343 +0,0 @@
package org.opsli.modulars.test.web;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReflectUtil;
import io.swagger.annotations.ApiOperation;
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.DictWrapper;
import org.opsli.api.wrapper.test.TestModel;
import org.opsli.common.utils.WrapperUtil;
import org.opsli.core.base.controller.BaseRestController;
import org.opsli.core.cache.pushsub.enums.CacheHandleType;
import org.opsli.core.cache.pushsub.msgs.DictMsgFactory;
import org.opsli.core.persistence.Page;
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;
import org.opsli.plugins.mail.model.MailModel;
import org.opsli.plugins.redis.RedisLockPlugins;
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;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.modulars.test.web
* @Author: Parker
* @CreateTime: 2020-09-13 17:40
* @Description:
*/
@Slf4j
//@ApiRestController("/test")
public class TestRestRestController extends BaseRestController<TestEntity, TestModel, ITestService>
implements TestApi {
private Random random = new Random();
@Autowired
private MailPlugin mailPlugin;
@Autowired
private RedisPlugin redisPlugin;
@Autowired
private RedisLockPlugins redisLockPlugins;
@ApiOperation(value = "发送邮件", notes = "发送邮件")
@Override
public ResultVo<?> sendMail(){
MailModel mailModel = new MailModel();
mailModel.setTo("meet.carina@foxmail.com");
mailModel.setSubject("测试邮件功能");
mailModel.setContent("<h1>这是哪里呢?</h1><br><font color='red'>lalalalalalallalalalalal!!!!</font>");
mailPlugin.send(mailModel);
return ResultVo.success("发送邮件成功!!!!!!");
}
/**
* Redis
* @return
*/
@ApiOperation(value = "发送 Redis 订阅消息", notes = "发送 Redis 订阅消息")
@Override
public ResultVo<?> sendMsg(){
DictWrapper model = new DictWrapper();
BaseSubMessage msg = DictMsgFactory.createMsg(model, CacheHandleType.UPDATE);
boolean ret = redisPlugin.sendMessage(msg);
if(ret){
return ResultVo.success("发送订阅消息成功!!!!!!");
}
return ResultVo.error("发送订阅消息失败!!!!!!");
}
/**
* Redis
* @return
*/
@ApiOperation(value = "发送 Redis 测试", notes = "发送 Redis 测试")
@Override
public ResultVo<?> redisTest(){
boolean ret = redisPlugin.put("opsli:test", "12315");
if(ret){
Object o = redisPlugin.get("opsli:test");
return ResultVo.success(o);
}
return ResultVo.error("发送订阅消息失败!!!!!!");
}
/**
* Redis
* @return
*/
@ApiOperation(value = "发起 Redis 分布式锁", notes = "发起 Redis 分布式锁")
@Override
public ResultVo<RedisLock> testLock(){
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName("aaabbb")
.setAcquireTimeOut(2000L)
.setLockTimeOut(10000L);
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
ResultVo<RedisLock> error = ResultVo.error(500,"获得锁失败!!!!!!",redisLock);
return error;
}
// 睡眠 模拟线程执行过程
ThreadUtil.sleep(60, TimeUnit.SECONDS);
redisLockPlugins.unLock(redisLock);
ResultVo<RedisLock> success = ResultVo.success("获得锁成功!!!!!!",redisLock);
success.setData(redisLock);
return success;
}
/**
*
* @return
*/
@ApiOperation(value = "新增数据", notes = "新增数据")
@Override
public ResultVo<TestModel> insert(TestModel model){
// 转化对象 处理 ApiModel 与 本地对象
model.setName("测试名称"+random.nextInt());
model.setRemark("测试备注"+random.nextInt());
// 调用新增方法
TestModel insert = IService.insert(model);
return ResultVo.success("新增成功",insert);
}
/**
*
* @return
*/
@ApiOperation(value = "修改数据", notes = "修改数据")
@Override
public ResultVo<TestModel> update(TestModel model){
// 转化对象 处理 ApiModel 与 本地对象
if(StringUtils.isEmpty(model.getId())){
model.setId(String.valueOf(random.nextLong()));
}
model.setName("修改名称"+random.nextInt());
model.setRemark("修改备注"+random.nextInt());
// 不需要做 锁状态处理,需要判断是否成功 能往下走的只能是成功
TestModel update = IService.update(model);
return ResultVo.success("修改成功",update);
}
/**
*
* @return
*/
@ApiOperation(value = "查看对象", notes = "查看对象")
@Override
public ResultVo<TestModel> get(TestModel model){
return ResultVo.success(model);
}
/**
*
* @return
*/
@ApiOperation(value = "删除对象", notes = "删除对象")
@Override
public ResultVo<?> del(String id){
TestEntity testEntity1 = new TestEntity();
testEntity1.setId(id);
String[] ids = {id};
List<TestEntity> idList = new ArrayList<>();
idList.add(testEntity1);
//count = IService.delete(id);
//count = IService.delete(testEntity1);
//count = IService.deleteAll(idList);
IService.deleteAll(ids);
return ResultVo.error("删除对象成功");
}
/**
*
* @return
*/
@ApiOperation(value = "删除全部对象", notes = "删除全部对象")
@Override
public ResultVo<?> delAll(){
//IService.
int count = 0;
//count = IService.delete(id);
//count = IService.delete(testEntity1);
//count = IService.deleteAll(ids);
//count = IService.deleteAll(idList);
return ResultVo.error("删除对象成功");
}
@ApiOperation(value = "查找一个集合", notes = "查找一个集合")
@Override
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 = "查找全部数据")
@Override
public ResultVo<List<TestModel>> findAllList() {
List<TestEntity> list = IService.findAllList();
List<TestModel> testModels = WrapperUtil.transformInstance(list, TestModel.class);
return ResultVo.success(testModels);
}
@ApiOperation(value = "查询分页", notes = "查询分页")
@Override
public ResultVo<?> findPage(Integer pageNo, Integer pageSize, HttpServletRequest request) {
QueryBuilder<TestEntity> queryBuilder = new WebQueryBuilder<>(TestEntity.class, request.getParameterMap());
Page<TestEntity,TestModel> page = new Page<>(pageNo, pageSize);
page.setQueryWrapper(queryBuilder.build());
page = IService.findPage(page);
return ResultVo.success(page.getPageData());
}
@ApiOperation(value = "导出Excel", notes = "导出Excel")
@Override
public void exportExcel(HttpServletRequest request, HttpServletResponse response) {
// 当前方法
Method method = ReflectUtil.getMethodByName(this.getClass(), "exportExcel");
QueryBuilder<TestEntity> queryBuilder = new WebQueryBuilder<>(entityClazz, request.getParameterMap());
super.excelExport("测试", queryBuilder.build(), response, method);
}
@ApiOperation(value = "导入Excel", notes = "导入Excel")
@Override
public ResultVo<?> importExcel(MultipartHttpServletRequest request) {
return super.importExcel(request);
}
@ApiOperation(value = "导出Excel模版", notes = "导出Excel模版")
@Override
public void importTemplate(HttpServletResponse response) {
// 当前方法
Method method = ReflectUtil.getMethodByName(this.getClass(), "importTemplate");
super.importTemplate("测试", response, method);
}
/**
*
* @return
*/
@ApiOperation(value = "批量插入1000个随机新增数据", notes = "批量插入1000个随机新增数据")
@GetMapping("/insertAll")
public ResultVo<Boolean> insertAll(){
List<DictWrapper> testType = DictUtil.getDictList("testType");
List<TestModel> datas = new ArrayList<>();
// 转化对象 处理 ApiModel 与 本地对象
for (int i = 0; i < 1000; i++) {
int randomNum = RandomUtil.randomInt(0, testType.size());
TestModel model = new TestModel();
model.setName("测试名称"+random.nextInt());
model.setType(testType.get(randomNum).getDictValue());
model.setRemark("测试备注"+random.nextInt());
datas.add(model);
}
// 调用新增方法
boolean b = IService.insertBatch(datas);
return ResultVo.success("新增成功",b);
}
@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);
}
}

@ -28,12 +28,7 @@
<!-- 模块版本 ${modulars.version}--> <!-- 模块版本 ${modulars.version}-->
<dependencies> <dependencies>
<!-- 引入邮件插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-mail</artifactId>
<version>${plugins.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

@ -1,24 +0,0 @@
<?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-plugins</artifactId>
<groupId>org.opsliframework.boot</groupId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>opsli-plugins-mail</artifactId>
<version>${project.parent.version}</version>
<dependencies>
<!-- 邮件服务 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies>
</project>

@ -1,35 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.plugins.mail;
import org.opsli.plugins.mail.model.MailModel;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.mail.handler
* @Author: Parker
* @CreateTime: 2020-09-13 18:51
* @Description:
*/
public interface MailPlugin {
/**
*
* @param mailModel
*/
void send(MailModel mailModel);
}

@ -1,37 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.plugins.mail.exception;
import org.opsli.common.base.msg.BaseMsg;
import org.opsli.common.exception.ServiceException;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.mail.exception
* @Author: Parker
* @CreateTime: 2020-09-13 18:44
* @Description:
*/
public class MailPluginException extends ServiceException {
public MailPluginException(Integer code, String errorMessage) {
super(code, errorMessage);
}
public MailPluginException(BaseMsg msg) {
super(msg);
}
}

@ -1,78 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.plugins.mail.handler;
import cn.hutool.core.lang.Validator;
import lombok.extern.slf4j.Slf4j;
import org.opsli.common.exception.EmptyException;
import org.opsli.plugins.mail.MailPlugin;
import org.opsli.plugins.mail.exception.MailPluginException;
import org.opsli.plugins.mail.model.MailModel;
import org.opsli.plugins.mail.msg.MailMsg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import javax.mail.internet.MimeMessage;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.mail.handler
* @Author: Parker
* @CreateTime: 2020-09-13 18:52
* @Description:
*/
@Slf4j
@Service
public class MailPlugInImpl implements MailPlugin {
@Value("${spring.mail.username}")
private String username;
@Autowired
private JavaMailSender javaMailSender;
@Override
public void send(MailModel mailModel) {
try {
MimeMessage message= javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message,true);
helper.setFrom(username);
helper.setTo(mailModel.getTo());
helper.setSubject(mailModel.getSubject());
helper.setText(mailModel.getContent(),true);
javaMailSender.send(message);
} catch (Exception e) {
log.error("邮件发送异常:{}",e.getMessage());
throw new MailPluginException(MailMsg.EXCEPTION_UNKNOWN);
}
log.info("邮件发送 - 发送至:{} - 主题:{}", mailModel.getTo(),mailModel.getSubject());
}
/**
*
*/
private void validationMailModel(MailModel mailModel) {
if(Validator.isEmpty(mailModel) ||
Validator.isEmpty(mailModel.getTo()) ||
Validator.isEmpty(mailModel.getSubject()) ||
Validator.isEmpty(mailModel.getContent())){
throw new EmptyException();
}
}
}

@ -1,41 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.plugins.mail.model;
import lombok.Data;
import lombok.ToString;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.mail.model
* @Author: Parker
* @CreateTime: 2020-09-13 18:46
* @Description:
*/
@Data
@ToString
public class MailModel {
/** 收件人 */
private String to;
/** 邮件主题 */
private String subject;
/** 邮件内容 */
private String content;
}

@ -1,51 +0,0 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.plugins.mail.msg;
import org.opsli.common.base.msg.BaseMsg;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.plugins.mail.msg
* @Author: Parker
* @CreateTime: 2020-09-13 19:54
* @Description:
*/
public enum MailMsg implements BaseMsg {
/** 未知消息异常 */
EXCEPTION_UNKNOWN(90200,"邮件发送失败"),
;
private final int code;
private final String message;
MailMsg(int code,String message){
this.code = code;
this.message = message;
}
@Override
public Integer getCode() {
return this.code;
}
@Override
public String getMessage() {
return this.message;
}
}

@ -16,7 +16,6 @@
<!-- 插件 --> <!-- 插件 -->
<modules> <modules>
<module>opsli-plugins-mail</module>
<module>opsli-plugins-redis</module> <module>opsli-plugins-redis</module>
<module>opsli-plugins-ehcache</module> <module>opsli-plugins-ehcache</module>
<module>opsli-plugins-excel</module> <module>opsli-plugins-excel</module>

@ -50,21 +50,6 @@ spring:
# #
#main: #main:
# allow-bean-definition-overriding: true # allow-bean-definition-overriding: true
# 邮件设置
mail:
host: smtp.qq.com
username: meet.parker@foxmail.com
password: pamjnijkjkqdbbea
properties:
mail:
smpt:
# 认证
auth: true
starttls:
enable: true
required: true
# 默认编码
default-encoding: UTF-8
# 缓存配置项 # 缓存配置项
cache-conf: cache-conf:

@ -89,6 +89,7 @@
<commons.io.version>2.8.0</commons.io.version> <commons.io.version>2.8.0</commons.io.version>
<commons.lang3.version>3.11</commons.lang3.version> <commons.lang3.version>3.11</commons.lang3.version>
<snakeyaml.version>1.27</snakeyaml.version> <snakeyaml.version>1.27</snakeyaml.version>
<email.version>1.6.2</email.version>
<!-- 需要使用着两个版本 来引入对应的模块和插件 --> <!-- 需要使用着两个版本 来引入对应的模块和插件 -->
<!-- 插件版本 --> <!-- 插件版本 -->
@ -318,6 +319,12 @@
<version>${snakeyaml.version}</version> <version>${snakeyaml.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>${email.version}</version>
</dependency>
<!-- ———————————————————— 集成工具 - 结束 ———————————————————— --> <!-- ———————————————————— 集成工具 - 结束 ———————————————————— -->
</dependencies> </dependencies>

Loading…
Cancel
Save