init: 后台代码初始化

dev
slyao 1 month ago
parent a68ce86c55
commit 2af5798c04

@ -0,0 +1,14 @@
<?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>jeecg-system-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.7.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-system-local-api</artifactId>
</project>

@ -0,0 +1,547 @@
package org.jeecg.common.system.api;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.api.dto.DataLogDTO;
import org.jeecg.common.api.dto.OnlineAuthDTO;
import org.jeecg.common.api.dto.message.*;
import org.jeecg.common.constant.enums.EmailTemplateEnum;
import org.jeecg.common.system.vo.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @Description API
* @Author scott
* @Date 2019-4-20
* @Version V1.0
*/
public interface ISysBaseAPI extends CommonAPI {
//=======OLD 系统消息推送接口============================
/**
* 1
* @param message 使 category()2
*/
void sendSysAnnouncement(MessageDTO message);
/**
* 2
* @param message 使
*/
void sendBusAnnouncement(BusMessageDTO message);
/**
* 3
* @param message 使
*/
void sendTemplateAnnouncement(TemplateMessageDTO message);
/**
* 4
* @param message 使
*/
void sendBusTemplateAnnouncement(BusTemplateMessageDTO message);
/**
* 5
* @param templateDTO 使
* @return
*/
String parseTemplateByCode(TemplateDTO templateDTO);
//=======OLD 系统消息推送接口============================
//=======TY NEW 自定义消息推送接口,邮件、钉钉、企业微信、系统消息============================
/**
* NEW:
* @param message
*/
void sendTemplateMessage(MessageDTO message);
/**
* NEW
* @param templateCode
* @return
*/
String getTemplateContent(String templateCode);
//=======TY NEW 自定义消息推送接口,邮件、钉钉、企业微信、系统消息============================
/**
* 6id
* @param id
* @return
*/
LoginUser getUserById(String id);
/**
* 7
* @param username
* @return
*/
List<String> getRolesByUsername(String username);
/**
* 7
* @param userId
* @return
*/
List<String> getRolesByUserId(String userId);
/**
* 8
* @param username
* @return id
*/
List<String> getDepartIdsByUsername(String username);
/**
* 8
* @param userId
* @return id
*/
List<String> getDepartIdsByUserId(String userId);
/**
* 8.2 ID
* @param username
* @return parentIds
*/
Set<String> getDepartParentIdsByUsername(String username);
/**
* 8.2 ID
* @param depIds
* @return parentIds
*/
Set<String> getDepartParentIdsByDepIds(Set<String> depIds);
/**
* 9 name
* @param username
* @return name
*/
List<String> getDepartNamesByUsername(String username);
/** 11create_time
* @return List<DictModel>
*/
public List<DictModel> queryAllDict();
/**
* 12
* @return
*/
public List<SysCategoryModel> queryAllSysCategory();
/**
* 14 id -->value,departName -->text
* @return
*/
public List<DictModel> queryAllDepartBackDictModel();
/**
* 15id
* @param busType
* @param busId
*/
public void updateSysAnnounReadFlag(String busType, String busId);
/**
* 16
* @param table
* @param text
* @param code
* @param filterSql
* @return
*/
public List<DictModel> queryFilterTableDictInfo(String table, String text, String code, String filterSql);
/**
* 17table text code textvalue
* @param table
* @param text
* @param code
* @param keyArray
* @return
*/
@Deprecated
public List<String> queryTableDictByKeys(String table, String text, String code, String[] keyArray);
/**
* 18 ComboModel
* @return
*/
public List<ComboModel> queryAllUserBackCombo();
/**
* 19 JSONObject
* @param userIds id
* @param pageNo
* @param pageSize
* @return
*/
public JSONObject queryAllUser(String userIds, Integer pageNo, Integer pageSize);
/**
* 20
* @return
*/
public List<ComboModel> queryAllRole();
/**
* 21
* @param roleIds
* @return
*/
public List<ComboModel> queryAllRole(String[] roleIds );
/**
* 22Id
* @param username
* @return
*/
public List<String> getRoleIdsByUsername(String username);
/**
* 23id
* @param orgCode
* @return
*/
public String getDepartIdsByOrgCode(String orgCode);
/**
* 24
* @return
*/
public List<SysDepartModel> getAllSysDepart();
/**
* 25
* @param departId
* @return
*/
DictModel getParentDepartId(String departId);
/**
* 26Id
* @param deptId
* @return
*/
public List<String> getDeptHeadByDepId(String deptId);
/**
* 27
* @param userIds
* @param cmd
*/
public void sendWebSocketMsg(String[] userIds, String cmd);
/**
* 28id
* @param userIds id
* @return
*/
public List<UserAccountInfo> queryAllUserByIds(String[] userIds);
/**
* 29
* userIds
* @return
* @param userId
*/
void meetingSignWebsocket(String userId);
/**
* 30name
* @param userNames
* @return
*/
List<UserAccountInfo> queryUserByNames(String[] userNames);
/**
*
* @param superQuery
* @param matchType
* @return
*/
List<JSONObject> queryUserBySuperQuery(String superQuery,String matchType);
/**
* ID
* @param id
* @return
*/
JSONObject queryUserById(String id);
/**
*
* @param superQuery
* @param matchType
* @return
*/
List<JSONObject> queryDeptBySuperQuery(String superQuery,String matchType);
/**
*
* @param superQuery
* @param matchType
* @return
*/
List<JSONObject> queryRoleBySuperQuery(String superQuery,String matchType);
/**
* IDID
* @param tenantId ID
* @return List<String>
*/
List<String> selectUserIdByTenantId(String tenantId);
/**
* 31
* @param username
* @return
*/
Set<String> getUserRoleSet(String username);
/**
* 31
* @param useId
* @return
*/
Set<String> getUserRoleSetById(String useId);
/**
* 32
* @param userId
* @return
*/
Set<String> getUserPermissionSet(String userId);
/**
* 33online访
* @param onlineAuthDTO
* @return
*/
boolean hasOnlineAuth(OnlineAuthDTO onlineAuthDTO);
/**
* 34id
* @param id id
* @return SysDepartModel
*/
SysDepartModel selectAllById(String id);
/**
* 35idids
* @param userId
* @return
*/
List<String> queryDeptUsersByUserId(String userId);
/**
* 36()
* @param usernames
* @return
*/
List<JSONObject> queryUsersByUsernames(String usernames);
/**
* 37ID()
* @param ids
* @return
*/
List<JSONObject> queryUsersByIds(String ids);
/**
* 38()
* @param orgCodes
* @return
*/
List<JSONObject> queryDepartsByOrgcodes(String orgCodes);
/**
* 39id()
* @param ids
* @return
*/
List<JSONObject> queryDepartsByIds(String ids);
/**
* 40
* @param email
* @param title
* @param content
*/
void sendEmailMsg(String email,String title,String content);
/**
* 40
*
* @param email
* @param title
* @param emailTemplateEnum
* @param params
*/
void sendHtmlTemplateEmail(String email, String title, EmailTemplateEnum emailTemplateEnum, JSONObject params);
/**
* 41
* @param orgCode
* @return List<Map>
*/
List<Map> getDeptUserByOrgCode(String orgCode);
/**
*
* @param ids id
* @return List<String>
*/
List<String> loadCategoryDictItem(String ids);
/**
*
*
* @param names
*/
List<String> loadCategoryDictItemByNames(String names, boolean delNotExist);
/**
* codetext
*
* @param dictCode tableName,text,code
* @param keys key
* @return
*/
List<String> loadDictItem(String dictCode, String keys);
/**
*
*
* @param originalAppId ID
* @param appId ID
* @param tenantId ID
* @return Map<String, String> Map<, >
*/
Map<String, String> copyLowAppDict(String originalAppId, String appId, String tenantId);
/**
* code
*
* @param dictCode tableName,text,code
* @param dictCode key
* @return
*/
List<DictModel> getDictItems(String dictCode);
/**
* code
* @param dictCodeList
* @return key = dictCode value=
*/
Map<String, List<DictModel>> getManyDictItems(List<String> dictCodeList);
/**
* JSearchSelectTag
*
*
* @param dictCode codetable,text,code
* @param keyword
* @param pageSize
* @return
*/
List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageNo, Integer pageSize);
/**
*
* @param dataLogDto
*/
void saveDataLog(DataLogDTO dataLogDto);
/**
*
* @param loginUser
*/
void updateAvatar(LoginUser loginUser);
/**
* app websocket
* @param userId
*/
void sendAppChatSocket(String userId);
/**
* idcode
* @param id
* @return
*/
String getRoleCodeById(String id);
/**
* roleCode
*
* @param roleCodes
* @return
*/
List<DictModel> queryRoleDictByCode(String roleCodes);
/**
* IDID
* @param deptIds
* @return
*/
List<String> queryUserIdsByDeptIds(List<String> deptIds);
/**
* ID
* @param deptIds
* @return
*/
List<String> queryUserAccountsByDeptIds(List<String> deptIds);
/**
* ID
* @param roleCodes
* @return
*/
List<String> queryUserIdsByRoleds(List<String> roleCodes);
/**
* IDID
* @param positionIds
* @return
*/
List<String> queryUserIdsByPositionIds(List<String> positionIds);
/**
*
*
* @param orgCode
* @return
*/
public List<String> getUserAccountsByDepCode(String orgCode);
/**
* sql
*
* @param selectSql
* @return
*/
boolean dictTableWhiteListCheckBySql(String selectSql);
/**
*
*
* @param tableOrDictCode dictCode
* @param fields dictCodenull
* @return
*/
boolean dictTableWhiteListCheckByDict(String tableOrDictCode, String... fields);
}

@ -0,0 +1,26 @@
<?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>jeecg-module-system</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.7.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-system-api</artifactId>
<packaging>pom</packaging>
<modules>
<module>jeecg-system-local-api</module>
</modules>
<dependencies>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base-core</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,4 @@
*.js linguist-language=Java
*.css linguist-language=Java
*.html linguist-language=Java
*.vue linguist-language=Java

@ -0,0 +1,48 @@
<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>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-module-system</artifactId>
<version>3.7.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-system-biz</artifactId>
<dependencies>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-system-local-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>hibernate-re</artifactId>
</dependency>
<!-- 企业微信/钉钉 api -->
<dependency>
<groupId>org.jeecgframework</groupId>
<artifactId>weixin4j</artifactId>
</dependency>
<!-- 积木报表 -->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-nosql-starter</artifactId>
</dependency>
<!-- 积木BI -->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimubi-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,279 @@
package org.jeecg.config.firewall.SqlInjection.impl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.exception.JeecgSqlInjectionException;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.util.sqlparse.JSqlParserUtils;
import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo;
import org.jeecg.config.JeecgBaseConfig;
import org.jeecg.config.firewall.SqlInjection.IDictTableWhiteListHandler;
import org.jeecg.config.firewall.interceptor.LowCodeModeInterceptor;
import org.jeecg.modules.system.entity.SysTableWhiteList;
import org.jeecg.modules.system.security.DictQueryBlackListHandler;
import org.jeecg.modules.system.service.ISysTableWhiteListService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.net.URLDecoder;
import java.util.*;
/**
*
*/
@Slf4j
@Component("dictTableWhiteListHandlerImpl")
public class DictTableWhiteListHandlerImpl implements IDictTableWhiteListHandler {
/**
* key-
* value-
* --
* whiteTablesRuleMap.put("sys_user", "*") sys_user
* whiteTablesRuleMap.put("sys_user", "username,password") sys_userusernamepassword
*/
private static final Map<String, String> whiteTablesRuleMap = new HashMap<>();
/**
* LowCode dev
*/
private static Boolean LOW_CODE_IS_DEV = null;
@Autowired
private ISysTableWhiteListService sysTableWhiteListService;
@Autowired
private JeecgBaseConfig jeecgBaseConfig;
/**
* whiteTablesRuleMap
*/
private void init() {
// 如果当前为dev模式则每次都查询数据库防止缓存
if (this.isDev()) {
DictTableWhiteListHandlerImpl.whiteTablesRuleMap.clear();
}
// 如果map为空则从数据库中查询
if (DictTableWhiteListHandlerImpl.whiteTablesRuleMap.isEmpty()) {
Map<String, String> ruleMap = sysTableWhiteListService.getAllConfigMap();
log.info("表字典白名单初始化完成:{}", ruleMap);
DictTableWhiteListHandlerImpl.whiteTablesRuleMap.putAll(ruleMap);
}
}
@Override
public boolean isPassBySql(String sql) {
Map<String, SelectSqlInfo> parsedMap = null;
try {
parsedMap = JSqlParserUtils.parseAllSelectTable(sql);
} catch (Exception e) {
log.warn("校验sql语句解析报错{}", e.getMessage());
}
// 如果sql有问题则肯定执行不了所以直接返回true
if (parsedMap == null) {
return true;
}
log.info("获取select sql信息 {} ", parsedMap);
// 遍历当前sql中的所有表名如果有其中一个表或表的字段不在白名单中则不通过
for (Map.Entry<String, SelectSqlInfo> entry : parsedMap.entrySet()) {
SelectSqlInfo sqlInfo = entry.getValue();
if (sqlInfo.isSelectAll()) {
log.warn("查询语句中包含 * 字段,暂时先通过");
continue;
}
Set<String> queryFields = sqlInfo.getAllRealSelectFields();
// 校验表名和字段是否允许查询
String tableName = entry.getKey();
if (!this.checkWhiteList(tableName, queryFields)) {
return false;
}
}
return true;
}
@Override
public boolean isPassByDict(String dictCodeString) {
if (oConvertUtils.isEmpty(dictCodeString)) {
return true;
}
try {
// 针对转义字符进行解码
dictCodeString = URLDecoder.decode(dictCodeString, "UTF-8");
} catch (Exception e) {
log.warn(e.getMessage());
//this.throwException("字典code解码失败可能是使用了非法字符请检查");
}
dictCodeString = dictCodeString.trim();
String[] arr = dictCodeString.split(SymbolConstant.COMMA);
// 获取表名
String tableName = this.getTableName(arr[0]);
// 获取查询字段
arr = Arrays.copyOfRange(arr, 1, arr.length);
// distinct的作用是去重相当于 Set<String>
String[] fields = Arrays.stream(arr).map(String::trim).distinct().toArray(String[]::new);
// 校验表名和字段是否允许查询
return this.isPassByDict(tableName, fields);
}
@Override
public boolean isPassByDict(String tableName, String... fields) {
if (oConvertUtils.isEmpty(tableName)) {
return true;
}
if (fields == null || fields.length == 0) {
fields = new String[]{"*"};
}
String sql = "select " + String.join(",", fields) + " from " + tableName;
log.info("字典拼接的查询SQL{}", sql);
try {
// 进行SQL解析
JSqlParserUtils.parseSelectSqlInfo(sql);
} catch (Exception e) {
// 如果SQL解析失败则通过字段名和表名进行校验
return checkWhiteList(tableName, new HashSet<>(Arrays.asList(fields)));
}
// 通过SQL解析进行校验可防止SQL注入
return this.isPassBySql(sql);
}
/**
*
*
* @param tableName
* @param queryFields
* @return
*/
public boolean checkWhiteList(String tableName, Set<String> queryFields) {
this.init();
// 1、判断“表名”是否通过校验如果为空则未通过校验
if (oConvertUtils.isEmpty(tableName)) {
log.error("白名单校验:表名为空");
this.throwException();
}
// 统一转成小写
tableName = tableName.toLowerCase();
String allowFieldStr = DictTableWhiteListHandlerImpl.whiteTablesRuleMap.get(tableName);
log.info("checkWhiteList tableName: {}", tableName);
if (oConvertUtils.isEmpty(allowFieldStr)) {
// 如果是dev模式自动向数据库里添加数据
if (this.isDev()) {
this.autoAddWhiteList(tableName, String.join(",", queryFields));
allowFieldStr = DictTableWhiteListHandlerImpl.whiteTablesRuleMap.get(tableName);
} else {
// prod模式下直接抛出异常
log.error("白名单校验:表\"{}\"未通过校验", tableName);
this.throwException();
}
}
// 2、判断“字段名”是否通过校验
// 统一转成小写
allowFieldStr = allowFieldStr.toLowerCase();
Set<String> allowFields = new HashSet<>(Arrays.asList(allowFieldStr.split(",")));
// 需要合并的字段
Set<String> waitMergerFields = new HashSet<>();
for (String field : queryFields) {
if(oConvertUtils.isEmpty(field)){
continue;
}
// 统一转成小写
field = field.toLowerCase();
// 如果允许的字段里不包含查询的字段,则直接抛出异常
if (!allowFields.contains(field)) {
// 如果是dev模式记录需要合并的字段
if (this.isDev()) {
waitMergerFields.add(field);
} else {
log.error("白名单校验:字段 {} 不在 {} 范围内,拒绝访问!", field, allowFields);
this.throwException();
}
}
}
// 自动向数据库中合并未通过的字段
if (!waitMergerFields.isEmpty()) {
this.autoAddWhiteList(tableName, String.join(",", waitMergerFields));
}
log.info("白名单校验:查询表\"{}\",查询字段 {} 通过校验", tableName, queryFields);
return true;
}
/**
*
*
* @param tableName
* @param allowFieldStr
*/
private void autoAddWhiteList(String tableName, String allowFieldStr) {
try {
SysTableWhiteList entity = sysTableWhiteListService.autoAdd(tableName, allowFieldStr);
DictTableWhiteListHandlerImpl.whiteTablesRuleMap.put(tableName, entity.getFieldName());
log.warn("表\"{}\"未通过校验,且当前为 dev 模式,已自动向数据库中增加白名单数据。查询字段:{}", tableName, allowFieldStr);
} catch (Exception e) {
log.error("表\"{}\"未通过校验,且当前为 dev 模式,但自动向数据库中增加白名单数据失败,请排查后重试。错误原因:{}", tableName, e.getMessage(), e);
this.throwException();
}
}
/**
* LowCode dev
*/
private boolean isDev() {
if (DictTableWhiteListHandlerImpl.LOW_CODE_IS_DEV == null) {
if (this.jeecgBaseConfig.getFirewall() != null) {
String lowCodeMode = this.jeecgBaseConfig.getFirewall().getLowCodeMode();
DictTableWhiteListHandlerImpl.LOW_CODE_IS_DEV = LowCodeModeInterceptor.LOW_CODE_MODE_DEV.equals(lowCodeMode);
} else {
// 如果没有 firewall 配置,则默认为 false
DictTableWhiteListHandlerImpl.LOW_CODE_IS_DEV = false;
}
}
return DictTableWhiteListHandlerImpl.LOW_CODE_IS_DEV;
}
@Override
public boolean clear() {
DictTableWhiteListHandlerImpl.whiteTablesRuleMap.clear();
return true;
}
/**
* wheretable name
*
* @param str
* @see DictQueryBlackListHandler#getTableName(String)
*/
@SuppressWarnings("JavadocReference")
private String getTableName(String str) {
String[] arr = str.split("\\s+(?i)where\\s+");
String tableName = arr[0].trim();
//【20230814】解决使用参数tableName=sys_user t&复测,漏洞仍然存在
if (tableName.contains(".")) {
tableName = tableName.substring(tableName.indexOf(".") + 1, tableName.length()).trim();
}
if (tableName.contains(" ")) {
tableName = tableName.substring(0, tableName.indexOf(" ")).trim();
}
//【issues/4393】 sys_user , (sys_user), sys_user%20, %60sys_user%60
String reg = "\\s+|\\(|\\)|`";
return tableName.replaceAll(reg, "");
}
private void throwException() throws JeecgSqlInjectionException {
this.throwException(this.getErrorMsg());
}
private void throwException(String message) throws JeecgSqlInjectionException {
if (oConvertUtils.isEmpty(message)) {
message = this.getErrorMsg();
}
log.error(message);
throw new JeecgSqlInjectionException(message);
}
@Override
public String getErrorMsg() {
return "白名单校验未通过!";
}
}

@ -0,0 +1,54 @@
package org.jeecg.config.init;
import com.alibaba.druid.filter.config.ConfigTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecgframework.codegenerate.database.CodegenDatasourceConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description: ,DB
* onlineDB使jeecg_database.properties;
* 使GUIjeecg_database.properties
* ${spring.datasource.dynamic.datasource.master.url:}
* @author: scott
* @date: 20210218 16:30
*
*
* org/jeecg/interceptor/OnlineRepairCodeGenerateDbConfig.java
* @ConditionalOnMissingClass("org.jeecg.config.init.CodeGenerateDbConfig")
*/
@Slf4j
@Configuration
public class CodeGenerateDbConfig {
@Value("${spring.datasource.dynamic.datasource.master.url:}")
private String url;
@Value("${spring.datasource.dynamic.datasource.master.username:}")
private String username;
@Value("${spring.datasource.dynamic.datasource.master.password:}")
private String password;
@Value("${spring.datasource.dynamic.datasource.master.driver-class-name:}")
private String driverClassName;
@Value("${spring.datasource.dynamic.datasource.master.druid.public-key:}")
private String publicKey;
@Bean
public CodeGenerateDbConfig initCodeGenerateDbConfig() {
if(StringUtils.isNotBlank(url)){
if(StringUtils.isNotBlank(publicKey)){
try {
password = ConfigTools.decrypt(publicKey, password);
} catch (Exception e) {
e.printStackTrace();
log.error(" 代码生成器数据库连接,数据库密码解密失败!");
}
}
CodegenDatasourceConfig.initDbConfig(driverClassName,url, username, password);
log.info(" Init CodeGenerate Config [ Get Db Config From application.yml ] ");
}
return null;
}
}

@ -0,0 +1,66 @@
package org.jeecg.config.init;
import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Component;
import java.io.File;
import java.net.URL;
import java.nio.charset.StandardCharsets;
/**
*
* <p>
* JAR
* @author zhang
*/
@Slf4j
@Component
public class CodeTemplateInitListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
try {
log.info(" Init Code Generate Template [ 检测如果是JAR启动环境Copy模板到config目录 ] ");
this.initJarConfigCodeGeneratorTemplate();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* ::Jar::
*
*/
private void initJarConfigCodeGeneratorTemplate() throws Exception {
//1.获取jar同级下的config路径
String configPath = System.getProperty("user.dir") + File.separator + "config" + File.separator;
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("classpath*:jeecg/code-template-online/**/*");
for (Resource re : resources) {
URL url = re.getURL();
String filepath = url.getPath();
//System.out.println("native url= " + filepath);
filepath = java.net.URLDecoder.decode(filepath, "utf-8");
//System.out.println("decode url= " + filepath);
//2.在config下创建jeecg/code-template-online/*模板
String createFilePath = configPath + filepath.substring(filepath.indexOf("jeecg/code-template-online"));
// 非jar模式不生成模板
// 不生成目录,只生成具体模板文件
if (!filepath.contains(".jar!/BOOT-INF/lib/") || !createFilePath.contains(".")) {
continue;
}
if (!FileUtil.exist(createFilePath)) {
log.info("create file codeTemplate = " + createFilePath);
FileUtil.writeString(IOUtils.toString(url, StandardCharsets.UTF_8), createFilePath, "UTF-8");
}
}
}
}

@ -0,0 +1,42 @@
package org.jeecg.config.init;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.config.JeecgCloudCondition;
import org.jeecg.modules.system.service.ISysGatewayRouteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
/**
* @desc:
* @author: flyme
*/
@Slf4j
@Component
@Conditional(JeecgCloudCondition.class)
public class SystemInitListener implements ApplicationListener<ApplicationReadyEvent>, Ordered {
@Autowired
private ISysGatewayRouteService sysGatewayRouteService;
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
log.info(" 服务已启动,初始化路由配置 ###################");
String context = "AnnotationConfigServletWebServerApplicationContext";
if (applicationReadyEvent.getApplicationContext().getDisplayName().indexOf(context) > -1) {
sysGatewayRouteService.addRoute2Redis(CacheConstant.GATEWAY_ROUTES);
}
}
@Override
public int getOrder() {
return 1;
}
}

@ -0,0 +1,33 @@
package org.jeecg.config.init;
import org.apache.catalina.Context;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description: TomcatFactoryConfig
* @author: scott
* @date: 20210125 11:40
*/
@Configuration
public class TomcatFactoryConfig {
/**
* tomcat-embed-jasperjar
*/
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
}
};
factory.addConnectorCustomizers(connector -> {
connector.setProperty("relaxedPathChars", "[]{}");
connector.setProperty("relaxedQueryChars", "[]{}");
});
return factory;
}
}

@ -0,0 +1,124 @@
package org.jeecg.config.jimureport;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.LogDTO;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.drag.service.IOnlDragExternalService;
import org.jeecg.modules.drag.vo.DragDictModel;
import org.jeecg.modules.drag.vo.DragLogDTO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description:
* @Author: lsq
* @Date:2023-01-09
* @Version:V1.0
*/
@Slf4j
@Service("onlDragExternalServiceImpl")
public class JimuDragExternalServiceImpl implements IOnlDragExternalService {
@Autowired
@Lazy
private BaseCommonService baseCommonService;
@Autowired
@Lazy
private ISysBaseAPI sysBaseApi;
/**
* code
* @param codeList
* @return key = dictCode value=
*/
@Override
public Map<String, List<DragDictModel>> getManyDictItems(List<String> codeList, List<JSONObject> tableDictList) {
Map<String, List<DragDictModel>> manyDragDictItems = new HashMap<>();
if(!CollectionUtils.isEmpty(codeList)){
Map<String, List<DictModel>> dictItemsMap = sysBaseApi.getManyDictItems(codeList);
dictItemsMap.forEach((k,v)->{
List<DragDictModel> dictItems = new ArrayList<>();
v.forEach(dictItem->{
DragDictModel dictModel = new DragDictModel();
BeanUtils.copyProperties(dictItem,dictModel);
dictItems.add(dictModel);
});
manyDragDictItems.put(k,dictItems);
});
}
if(!CollectionUtils.isEmpty(tableDictList)){
tableDictList.forEach(item->{
List<DragDictModel> dictItems = new ArrayList<>();
JSONObject object = JSONObject.parseObject(item.toString());
String dictField = object.getString("dictField");
String dictTable = object.getString("dictTable");
String dictText = object.getString("dictText");
String fieldName = object.getString("fieldName");
List<DictModel> dictItemsList = sysBaseApi.queryTableDictItemsByCode(dictTable,dictText,dictField);
dictItemsList.forEach(dictItem->{
DragDictModel dictModel = new DragDictModel();
BeanUtils.copyProperties(dictItem,dictModel);
dictItems.add(dictModel);
});
manyDragDictItems.put(fieldName,dictItems);
});
}
return manyDragDictItems;
}
/**
*
* @param dictCode
* @return
*/
@Override
public List<DragDictModel> getDictItems(String dictCode) {
List<DragDictModel> dictItems = new ArrayList<>();
if(oConvertUtils.isNotEmpty(dictCode)){
List<DictModel> dictItemsList = sysBaseApi.getDictItems(dictCode);
dictItemsList.forEach(dictItem->{
DragDictModel dictModel = new DragDictModel();
BeanUtils.copyProperties(dictItem,dictModel);
dictItems.add(dictModel);
});
}
return dictItems;
}
/**
*
* @param dragLogDTO
*/
@Override
public void addLog(DragLogDTO dragLogDTO) {
if(oConvertUtils.isNotEmpty(dragLogDTO)){
LogDTO dto = new LogDTO();
BeanUtils.copyProperties(dragLogDTO,dto);
baseCommonService.addLog(dto);
}
}
/**
*
* @param logMsg
* @param logType
* @param operateType
*/
@Override
public void addLog(String logMsg, int logType, int operateType) {
baseCommonService.addLog(logMsg,logType,operateType);
}
}

@ -0,0 +1,111 @@
package org.jeecg.config.jimureport;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.TokenUtils;
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
import org.jeecg.modules.system.service.impl.SysBaseApiImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* ()
* * 1.token
* * 2.
* @author: jeecg-boot
*/
@Slf4j
@Component
public class JimuReportTokenService implements JmReportTokenServiceI {
@Autowired
private SysBaseApiImpl sysBaseApi;
@Autowired
@Lazy
private RedisUtil redisUtil;
@Override
public String getToken(HttpServletRequest request) {
try {
return TokenUtils.getTokenByRequest(request);
} catch (Exception e) {
return null;
}
}
@Override
public String getUsername(String token) {
return JwtUtil.getUsername(token);
}
@Override
public String[] getRoles(String token) {
String username = JwtUtil.getUsername(token);
Set roles = sysBaseApi.getUserRoleSet(username);
if(CollectionUtils.isEmpty(roles)){
return null;
}
return (String[]) roles.toArray(new String[roles.size()]);
}
@Override
public Boolean verifyToken(String token) {
return TokenUtils.verifyToken(token, sysBaseApi, redisUtil);
}
@Override
public Map<String, Object> getUserInfo(String token) {
Map<String, Object> map = new HashMap(5);
String username = JwtUtil.getUsername(token);
//此处通过token只能拿到一个信息 用户账号 后面的就是根据账号获取其他信息 查询数据或是走redis 用户根据自身业务可自定义
SysUserCacheInfo userInfo = null;
try {
userInfo = sysBaseApi.getCacheUser(username);
} catch (Exception e) {
log.error("获取用户信息异常:"+ e.getMessage());
return map;
}
//设置账号名
map.put(SYS_USER_CODE, userInfo.getSysUserCode());
//设置部门编码
map.put(SYS_ORG_CODE, userInfo.getSysOrgCode());
// 将所有信息存放至map 解析sql/api会根据map的键值解析
return map;
}
/**
* jeecgboot
* @param token
* @return
*/
@Override
public String[] getPermissions(String token) {
// 获取用户信息
String username = JwtUtil.getUsername(token);
SysUserCacheInfo userInfo = null;
try {
userInfo = sysBaseApi.getCacheUser(username);
} catch (Exception e) {
log.error("获取用户信息异常:"+ e.getMessage());
}
if(userInfo == null){
return null;
}
// 查询权限
Set<String> userPermissions = sysBaseApi.getUserPermissionSet(userInfo.getSysUserId());
if(CollectionUtils.isEmpty(userPermissions)){
return null;
}
return userPermissions.toArray(new String[0]);
}
}

@ -0,0 +1,27 @@
package org.jeecg.modules.aop;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.ModuleType;
import java.lang.annotation.*;
/**
*
*
* @Author scott
* @email jeecgos@163.com
* @Date 2019114
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TenantLog {
/**
* 1234
*
* @return
*/
int value() default 0;
}

@ -0,0 +1,100 @@
package org.jeecg.modules.aop;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.api.dto.LogDTO;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.entity.SysTenantPack;
import org.jeecg.modules.system.entity.SysTenantPackUser;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Date;
/**
* @Author taoYan
* @Date 2023/2/16 14:27
**/
@Aspect
@Component
public class TenantPackUserLogAspect {
@Resource
private BaseCommonService baseCommonService;
@Pointcut("@annotation(org.jeecg.modules.aop.TenantLog)")
public void tenantLogPointCut() {
}
@Around("tenantLogPointCut()")
public Object aroundMethod(ProceedingJoinPoint joinPoint)throws Throwable {
//System.out.println("环绕通知>>>>>>>>>");
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
TenantLog log = method.getAnnotation(TenantLog.class);
if(log != null){
int opType = log.value();
Integer logType = null;
String content = null;
Integer tenantId = null;
//获取参数
Object[] args = joinPoint.getArgs();
if(args.length>0){
for(Object obj: args){
if(obj instanceof SysTenantPack){
// logType=3 租户操作日志
logType = CommonConstant.LOG_TYPE_3;
SysTenantPack pack = (SysTenantPack)obj;
if(opType==2){
content = "创建了角色权限 "+ pack.getPackName();
}
tenantId = pack.getTenantId();
break;
}else if(obj instanceof SysTenantPackUser){
logType = CommonConstant.LOG_TYPE_3;
SysTenantPackUser packUser = (SysTenantPackUser)obj;
if(opType==2){
content = "将 "+packUser.getRealname()+" 添加到角色 "+ packUser.getPackName();
}else if(opType==4){
content = "移除了 "+packUser.getPackName()+" 成员 "+ packUser.getRealname();
}
tenantId = packUser.getTenantId();
}
}
}
if(logType!=null){
LogDTO dto = new LogDTO();
dto.setLogType(logType);
dto.setLogContent(content);
dto.setOperateType(opType);
dto.setTenantId(tenantId);
//获取登录用户信息
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
if(sysUser!=null){
dto.setUserid(sysUser.getUsername());
dto.setUsername(sysUser.getRealname());
}
dto.setCreateTime(new Date());
//保存系统日志
baseCommonService.addLog(dto);
}
}
return joinPoint.proceed();
}
@AfterThrowing("tenantLogPointCut()")
public void afterThrowing()throws Throwable{
System.out.println("异常通知");
}
}

@ -0,0 +1,980 @@
package org.jeecg.modules.api.controller;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.DataLogDTO;
import org.jeecg.common.api.dto.OnlineAuthDTO;
import org.jeecg.common.api.dto.message.*;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.desensitization.util.SensitiveInfoUtil;
import org.jeecg.common.system.vo.*;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.system.service.impl.SysBaseApiImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* system
* @author: jeecg-boot
*/
@Slf4j
@RestController
@RequestMapping("/sys/api")
public class SystemApiController {
@Autowired
private SysBaseApiImpl sysBaseApi;
@Autowired
private ISysUserService sysUserService;
/**
*
* @param message 使 category()2
*/
@PostMapping("/sendSysAnnouncement")
public void sendSysAnnouncement(@RequestBody MessageDTO message){
sysBaseApi.sendSysAnnouncement(message);
}
/**
*
* @param message 使
*/
@PostMapping("/sendBusAnnouncement")
public void sendBusAnnouncement(@RequestBody BusMessageDTO message){
sysBaseApi.sendBusAnnouncement(message);
}
/**
*
* @param message 使
*/
@PostMapping("/sendTemplateAnnouncement")
public void sendTemplateAnnouncement(@RequestBody TemplateMessageDTO message){
sysBaseApi.sendTemplateAnnouncement(message);
}
/**
*
* @param message 使
*/
@PostMapping("/sendBusTemplateAnnouncement")
public void sendBusTemplateAnnouncement(@RequestBody BusTemplateMessageDTO message){
sysBaseApi.sendBusTemplateAnnouncement(message);
}
/**
*
* @param templateDTO 使
* @return
*/
@PostMapping("/parseTemplateByCode")
public String parseTemplateByCode(@RequestBody TemplateDTO templateDTO){
return sysBaseApi.parseTemplateByCode(templateDTO);
}
/**
* busTypebusId
*/
@GetMapping("/updateSysAnnounReadFlag")
public void updateSysAnnounReadFlag(@RequestParam("busType") String busType, @RequestParam("busId")String busId){
sysBaseApi.updateSysAnnounReadFlag(busType, busId);
}
/**
*
* @param username
* @return
*/
@GetMapping("/getUserByName")
public LoginUser getUserByName(@RequestParam("username") String username){
LoginUser loginUser = sysBaseApi.getUserByName(username);
//用户信息加密
try {
SensitiveInfoUtil.handlerObject(loginUser, true);
} catch (IllegalAccessException e) {
log.error(e.getMessage(), e);
}
return loginUser;
}
/**
* ID
* @param username
* @return
*/
@GetMapping("/getUserIdByName")
public String getUserIdByName(@RequestParam("username") String username){
String userId = sysBaseApi.getUserIdByName(username);
return userId;
}
/**
* id
* @param id
* @return
*/
@GetMapping("/getUserById")
LoginUser getUserById(@RequestParam("id") String id){
LoginUser loginUser = sysBaseApi.getUserById(id);
//用户信息加密
try {
SensitiveInfoUtil.handlerObject(loginUser, true);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return loginUser;
}
/**
*
* @param username
* @return
*/
@GetMapping("/getRolesByUsername")
List<String> getRolesByUsername(@RequestParam("username") String username){
return sysBaseApi.getRolesByUsername(username);
}
/**
*
* @param userId
* @return
*/
@GetMapping("/getRolesByUserId")
List<String> getRolesByUserId(@RequestParam("userId") String userId){
return sysBaseApi.getRolesByUserId(userId);
}
/**
*
* @param username
* @return id
*/
@GetMapping("/getDepartIdsByUsername")
List<String> getDepartIdsByUsername(@RequestParam("username") String username){
return sysBaseApi.getDepartIdsByUsername(username);
}
/**
*
* @param userId
* @return id
*/
@GetMapping("/getDepartIdsByUserId")
List<String> getDepartIdsByUserId(@RequestParam("userId") String userId){
return sysBaseApi.getDepartIdsByUserId(userId);
}
/**
* ID
* @param username
* @return id
*/
@GetMapping("/getDepartParentIdsByUsername")
Set<String> getDepartParentIdsByUsername(@RequestParam("username") String username){
return sysBaseApi.getDepartParentIdsByUsername(username);
}
/**
* ID
* @param depIds
* @return id
*/
@GetMapping("/getDepartParentIdsByDepIds")
Set<String> getDepartParentIdsByDepIds(@RequestParam("depIds") Set<String> depIds){
return sysBaseApi.getDepartParentIdsByDepIds(depIds);
}
/**
* name
* @param username
* @return name
*/
@GetMapping("/getDepartNamesByUsername")
List<String> getDepartNamesByUsername(@RequestParam("username") String username){
return sysBaseApi.getDepartNamesByUsername(username);
}
/**
*
* @param code
* @return
*/
@GetMapping("/queryDictItemsByCode")
List<DictModel> queryDictItemsByCode(@RequestParam("code") String code){
return sysBaseApi.queryDictItemsByCode(code);
}
/**
*
* @param code
* @return
*/
@GetMapping("/queryEnableDictItemsByCode")
List<DictModel> queryEnableDictItemsByCode(@RequestParam("code") String code){
return sysBaseApi.queryEnableDictItemsByCode(code);
}
/** 查询所有的父级字典按照create_time排序 */
@GetMapping("/queryAllDict")
List<DictModel> queryAllDict(){
// try{
// //睡10秒gateway网关5秒超时会触发熔断降级操作
// Thread.sleep(10000);
// }catch (Exception e){
// e.printStackTrace();
// }
log.info("--我是jeecg-system服务节点微服务接口queryAllDict被调用--");
return sysBaseApi.queryAllDict();
}
/**
*
* @return
*/
@GetMapping("/queryAllSysCategory")
List<SysCategoryModel> queryAllSysCategory(){
return sysBaseApi.queryAllSysCategory();
}
/**
* id -->value,departName -->text
* @return
*/
@GetMapping("/queryAllDepartBackDictModel")
List<DictModel> queryAllDepartBackDictModel(){
return sysBaseApi.queryAllDepartBackDictModel();
}
/**
*
* roleIds
* @return
*/
@GetMapping("/queryAllRole")
public List<ComboModel> queryAllRole(@RequestParam(name = "roleIds",required = false)String[] roleIds){
if(roleIds==null || roleIds.length==0){
return sysBaseApi.queryAllRole();
}else{
return sysBaseApi.queryAllRole(roleIds);
}
}
/**
* Id
* @param username
* @return
*/
@GetMapping("/getRoleIdsByUsername")
public List<String> getRoleIdsByUsername(@RequestParam("username")String username){
return sysBaseApi.getRoleIdsByUsername(username);
}
/**
* id
* @param orgCode
* @return
*/
@GetMapping("/getDepartIdsByOrgCode")
public String getDepartIdsByOrgCode(@RequestParam("orgCode")String orgCode){
return sysBaseApi.getDepartIdsByOrgCode(orgCode);
}
/**
*
* @return
*/
@GetMapping("/getAllSysDepart")
public List<SysDepartModel> getAllSysDepart(){
return sysBaseApi.getAllSysDepart();
}
/**
* id DynamicDataSourceModel
*
* @param dbSourceId
* @return
*/
@GetMapping("/getDynamicDbSourceById")
DynamicDataSourceModel getDynamicDbSourceById(@RequestParam("dbSourceId")String dbSourceId){
return sysBaseApi.getDynamicDbSourceById(dbSourceId);
}
/**
* Id
* @param deptId
* @return
*/
@GetMapping("/getDeptHeadByDepId")
public List<String> getDeptHeadByDepId(@RequestParam("deptId") String deptId){
return sysBaseApi.getDeptHeadByDepId(deptId);
}
/**
*
* @param departId
* @return
*/
@GetMapping("/getParentDepartId")
public DictModel getParentDepartId(@RequestParam("departId")String departId){
return sysBaseApi.getParentDepartId(departId);
}
/**
* code DynamicDataSourceModel
*
* @param dbSourceCode
* @return
*/
@GetMapping("/getDynamicDbSourceByCode")
public DynamicDataSourceModel getDynamicDbSourceByCode(@RequestParam("dbSourceCode") String dbSourceCode){
return sysBaseApi.getDynamicDbSourceByCode(dbSourceCode);
}
/**
*
* @param userIds
* @param cmd
*/
@GetMapping("/sendWebSocketMsg")
public void sendWebSocketMsg(String[] userIds, String cmd){
sysBaseApi.sendWebSocketMsg(userIds, cmd);
}
/**
* id
* userIds
* @return
*/
@GetMapping("/queryAllUserByIds")
public List<UserAccountInfo> queryAllUserByIds(@RequestParam("userIds") String[] userIds){
return sysBaseApi.queryAllUserByIds(userIds);
}
/**
* ComboModel
* @return
*/
@GetMapping("/queryAllUserBackCombo")
public List<ComboModel> queryAllUserBackCombo(){
return sysBaseApi.queryAllUserBackCombo();
}
/**
* JSONObject
* @return
*/
@GetMapping("/queryAllUser")
public JSONObject queryAllUser(@RequestParam(name="userIds",required=false)String userIds, @RequestParam(name="pageNo",required=false) Integer pageNo,@RequestParam(name="pageSize",required=false) Integer pageSize){
return sysBaseApi.queryAllUser(userIds, pageNo, pageSize);
}
/**
*
* userIds
* @return
* @param userId
*/
@GetMapping("/meetingSignWebsocket")
public void meetingSignWebsocket(@RequestParam("userId")String userId){
sysBaseApi.meetingSignWebsocket(userId);
}
/**
* name
* userNames
* @return
*/
@GetMapping("/queryUserByNames")
public List<UserAccountInfo> queryUserByNames(@RequestParam("userNames")String[] userNames){
return sysBaseApi.queryUserByNames(userNames);
}
/**
*
* @param username
* @return
*/
@GetMapping("/getUserRoleSet")
public Set<String> getUserRoleSet(@RequestParam("username")String username){
return sysBaseApi.getUserRoleSet(username);
}
/**
*
* @param userId
* @return
*/
@GetMapping("/getUserRoleSetById")
public Set<String> getUserRoleSetById(@RequestParam("userId")String userId){
return sysBaseApi.getUserRoleSetById(userId);
}
/**
*
* @param userId ID
* @return
*/
@GetMapping("/getUserPermissionSet")
public Set<String> getUserPermissionSet(@RequestParam("userId") String userId){
return sysBaseApi.getUserPermissionSet(userId);
}
//-----
/**
* online访
* @param onlineAuthDTO
* @return
*/
@PostMapping("/hasOnlineAuth")
public boolean hasOnlineAuth(@RequestBody OnlineAuthDTO onlineAuthDTO){
return sysBaseApi.hasOnlineAuth(onlineAuthDTO);
}
/**
*
* @param username
* @return
*/
@GetMapping("/queryUserRoles")
public Set<String> queryUserRoles(@RequestParam("username") String username){
return sysUserService.getUserRolesSet(username);
}
/**
*
* @param userId
* @return
*/
@GetMapping("/queryUserRolesById")
public Set<String> queryUserRolesById(@RequestParam("userId") String userId){
return sysUserService.getUserRoleSetById(userId);
}
/**
*
* @param userId
* @return
*/
@GetMapping("/queryUserAuths")
public Set<String> queryUserAuths(@RequestParam("userId") String userId){
return sysUserService.getUserPermissionsSet(userId);
}
/**
* id
*/
@GetMapping("/selectAllById")
public SysDepartModel selectAllById(@RequestParam("id") String id){
return sysBaseApi.selectAllById(id);
}
/**
* idids
* @param userId
* @return
*/
@GetMapping("/queryDeptUsersByUserId")
public List<String> queryDeptUsersByUserId(@RequestParam("userId") String userId){
return sysBaseApi.queryDeptUsersByUserId(userId);
}
/**
*
* @return
*/
@GetMapping("/queryPermissionDataRule")
public List<SysPermissionDataRuleModel> queryPermissionDataRule(@RequestParam("component") String component, @RequestParam("requestPath")String requestPath, @RequestParam("username") String username){
return sysBaseApi.queryPermissionDataRule(component, requestPath, username);
}
/**
*
* @param username
* @return
*/
@GetMapping("/getCacheUser")
public SysUserCacheInfo getCacheUser(@RequestParam("username") String username){
return sysBaseApi.getCacheUser(username);
}
/**
*
* @param code
* @param key
* @return
*/
@GetMapping("/translateDict")
public String translateDict(@RequestParam("code") String code, @RequestParam("key") String key){
return sysBaseApi.translateDict(code, key);
}
/**
* 36()
* @param usernames
* @return
*/
@RequestMapping("/queryUsersByUsernames")
List<JSONObject> queryUsersByUsernames(@RequestParam("usernames") String usernames){
return this.sysBaseApi.queryUsersByUsernames(usernames);
}
/**
* 37id()
* @param ids
* @return
*/
@RequestMapping("/queryUsersByIds")
List<JSONObject> queryUsersByIds(@RequestParam("ids") String ids){
return this.sysBaseApi.queryUsersByIds(ids);
}
/**
* 38()
* @param orgCodes
* @return
*/
@GetMapping("/queryDepartsByOrgcodes")
List<JSONObject> queryDepartsByOrgcodes(@RequestParam("orgCodes") String orgCodes){
return this.sysBaseApi.queryDepartsByOrgcodes(orgCodes);
}
/**
* 39ID()
* @param ids
* @return
*/
@GetMapping("/queryDepartsByIds")
List<JSONObject> queryDepartsByIds(@RequestParam("ids") String ids){
return this.sysBaseApi.queryDepartsByIds(ids);
}
/**
* 40
* @param email
* @param title
* @param content
*/
@GetMapping("/sendEmailMsg")
public void sendEmailMsg(@RequestParam("email")String email,@RequestParam("title")String title,@RequestParam("content")String content){
this.sysBaseApi.sendEmailMsg(email,title,content);
};
/**
* 41
* @param orgCode
*/
@GetMapping("/getDeptUserByOrgCode")
List<Map> getDeptUserByOrgCode(@RequestParam("orgCode")String orgCode){
return this.sysBaseApi.getDeptUserByOrgCode(orgCode);
}
/**
*
*
* @param ids id
* @return
*/
@GetMapping("/loadCategoryDictItem")
public List<String> loadCategoryDictItem(@RequestParam("ids") String ids) {
return sysBaseApi.loadCategoryDictItem(ids);
}
/**
*
*
* @param names
* @return
*/
@GetMapping("/loadCategoryDictItemByNames")
List<String> loadCategoryDictItemByNames(@RequestParam("names") String names, @RequestParam("delNotExist") boolean delNotExist) {
return sysBaseApi.loadCategoryDictItemByNames(names, delNotExist);
}
/**
* codetext
*
* @param dictCode tableName,text,code
* @param keys key
* @return
*/
@GetMapping("/loadDictItem")
public List<String> loadDictItem(@RequestParam("dictCode") String dictCode, @RequestParam("keys") String keys) {
return sysBaseApi.loadDictItem(dictCode, keys);
}
/**
*
*
* @param originalAppId ID
* @param appId ID
* @param tenantId ID
* @return Map<String, String> Map<, >
*/
@GetMapping("/copyLowAppDict")
Map<String, String> copyLowAppDict(@RequestParam("originalAppId") String originalAppId, @RequestParam("appId") String appId, @RequestParam("tenantId") String tenantId) {
return sysBaseApi.copyLowAppDict(originalAppId, appId, tenantId);
}
/**
* code
*
* @param dictCode tableName,text,code
* @param dictCode key
* @return
*/
@GetMapping("/getDictItems")
public List<DictModel> getDictItems(@RequestParam("dictCode") String dictCode) {
return sysBaseApi.getDictItems(dictCode);
}
/**
* code
*
* @param dictCodeList
* @return key = dictCode value=
*/
@RequestMapping("/getManyDictItems")
public Map<String, List<DictModel>> getManyDictItems(@RequestParam("dictCodeList") List<String> dictCodeList) {
return sysBaseApi.getManyDictItems(dictCodeList);
}
/**
*
*
*
* @param dictCode codetable,text,code
* @param keyword
* @return
*/
@GetMapping("/loadDictItemByKeyword")
public List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode,
@RequestParam("keyword") String keyword,
@RequestParam(value = "pageNo", defaultValue = "1", required = false) Integer pageNo,
@RequestParam(value = "pageSize", required = false) Integer pageSize) {
return sysBaseApi.loadDictItemByKeyword(dictCode, keyword,pageNo, pageSize);
}
/**
* 48 dictCode
* @param dictCodes
* @param keys
* @return
*/
@GetMapping("/translateManyDict")
public Map<String, List<DictModel>> translateManyDict(@RequestParam("dictCodes") String dictCodes, @RequestParam("keys") String keys){
return this.sysBaseApi.translateManyDict(dictCodes, keys);
}
/**
*
* @param tableFilterSql where
* @param text
* @param code
* @return
*/
@GetMapping("/queryTableDictItemsByCode")
List<DictModel> queryTableDictItemsByCode(@RequestParam("tableFilterSql") String tableFilterSql, @RequestParam("text") String text, @RequestParam("code") String code){
return sysBaseApi.queryTableDictItemsByCode(tableFilterSql, text, code);
}
/**
*
* @param table
* @param text
* @param code
* @param filterSql
* @return
*/
@GetMapping("/queryFilterTableDictInfo")
List<DictModel> queryFilterTableDictInfo(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("filterSql") String filterSql){
return sysBaseApi.queryFilterTableDictInfo(table, text, code, filterSql);
}
/**
*
* table text code textvalue
* @param table
* @param text
* @param code
* @param keyArray
* @return
*/
@Deprecated
@GetMapping("/queryTableDictByKeys")
public List<String> queryTableDictByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keyArray") String[] keyArray){
return sysBaseApi.queryTableDictByKeys(table, text, code, keyArray);
}
/**
*
* @param table
* @param text
* @param code
* @param key
* @return
*/
@GetMapping("/translateDictFromTable")
public String translateDictFromTable(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("key") String key){
return sysBaseApi.translateDictFromTable(table, text, code, key);
}
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
/**
*
* 49
*
* @param table
* @param text
* @param code
* @param keys
* @param ds
* @return
*/
@GetMapping("/translateDictFromTableByKeys")
public List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys, @RequestParam("ds") String ds) {
return this.sysBaseApi.translateDictFromTableByKeys(table, text, code, keys, ds);
}
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
/**
*
* @param message
*/
@PostMapping("/sendTemplateMessage")
public void sendTemplateMessage(@RequestBody MessageDTO message){
sysBaseApi.sendTemplateMessage(message);
}
/**
*
* @param code
* @return
*/
@GetMapping("/getTemplateContent")
public String getTemplateContent(@RequestParam("code") String code){
return this.sysBaseApi.getTemplateContent(code);
}
/**
*
* @param dataLogDto
*/
@PostMapping("/saveDataLog")
public void saveDataLog(@RequestBody DataLogDTO dataLogDto){
this.sysBaseApi.saveDataLog(dataLogDto);
}
/**
*
* @param loginUser
* @return
*/
@PutMapping("/updateAvatar")
public void updateAvatar(@RequestBody LoginUser loginUser){
this.sysBaseApi.updateAvatar(loginUser);
}
/**
* app websocket
* @param userId
* @return
*/
@GetMapping("/sendAppChatSocket")
public void sendAppChatSocket(@RequestParam(name="userId") String userId){
this.sysBaseApi.sendAppChatSocket(userId);
}
/**
* roleCode
*
* @param roleCodes
* @return
*/
@GetMapping("/queryRoleDictByCode")
public List<DictModel> queryRoleDictByCode(@RequestParam(name = "roleCodes") String roleCodes) {
return this.sysBaseApi.queryRoleDictByCode(roleCodes);
}
/**
*
* @param id
* @return
*/
@GetMapping("/getRoleCode")
public String getRoleCode(@RequestParam("id") String id){
return this.sysBaseApi.getRoleCodeById(id);
}
/**
* VUEN-2584issuesql
*
* @param e
* @return
*/
@ExceptionHandler(java.sql.SQLException.class)
public Result<?> handleSQLException(Exception e){
String msg = e.getMessage();
String extractvalue = "extractvalue";
String updatexml = "updatexml";
if(msg!=null && (msg.toLowerCase().indexOf(extractvalue)>=0 || msg.toLowerCase().indexOf(updatexml)>=0)){
return Result.error("校验失败sql解析异常");
}
return Result.error("校验失败sql解析异常" + msg);
}
/**
*
* @param superQuery
* @param matchType
* @return
*/
@GetMapping("/queryUserBySuperQuery")
public List<JSONObject> queryUserBySuperQuery(@RequestParam("superQuery") String superQuery, @RequestParam("matchType") String matchType) {
return sysBaseApi.queryUserBySuperQuery(superQuery,matchType);
}
/**
* id
* @param id
* @return
*/
@GetMapping("/queryUserById")
public JSONObject queryUserById(@RequestParam("id") String id) {
return sysBaseApi.queryUserById(id);
}
/**
*
* @param superQuery
* @param matchType
* @return
*/
@GetMapping("/queryDeptBySuperQuery")
public List<JSONObject> queryDeptBySuperQuery(@RequestParam("superQuery") String superQuery, @RequestParam("matchType") String matchType) {
return sysBaseApi.queryDeptBySuperQuery(superQuery,matchType);
}
/**
*
* @param superQuery
* @param matchType
* @return
*/
@GetMapping("/queryRoleBySuperQuery")
public List<JSONObject> queryRoleBySuperQuery(@RequestParam("superQuery") String superQuery, @RequestParam("matchType") String matchType) {
return sysBaseApi.queryRoleBySuperQuery(superQuery,matchType);
}
/**
* IDID
* @param tenantId ID
* @return List<String>
*/
@GetMapping("/selectUserIdByTenantId")
public List<String> selectUserIdByTenantId(@RequestParam("tenantId") String tenantId) {
return sysBaseApi.selectUserIdByTenantId(tenantId);
}
/**
* IDID
* @param deptIds
* @return
*/
@GetMapping("/queryUserIdsByDeptIds")
public List<String> queryUserIdsByDeptIds(@RequestParam("deptIds") List<String> deptIds){
return sysBaseApi.queryUserIdsByDeptIds(deptIds);
}
/**
* IDID
* @param deptIds
* @return
*/
@GetMapping("/queryUserAccountsByDeptIds")
public List<String> queryUserAccountsByDeptIds(@RequestParam("deptIds") List<String> deptIds){
return sysBaseApi.queryUserAccountsByDeptIds(deptIds);
}
/**
* ID
* @param roleCodes
* @return
*/
@GetMapping("/queryUserIdsByRoleds")
public List<String> queryUserIdsByRoleds(@RequestParam("roleCodes") List<String> roleCodes){
return sysBaseApi.queryUserIdsByRoleds(roleCodes);
}
/**
* IDID
* @param positionIds
* @return
*/
@GetMapping("/queryUserIdsByPositionIds")
public List<String> queryUserIdsByPositionIds(@RequestParam("positionIds") List<String> positionIds){
return sysBaseApi.queryUserIdsByPositionIds(positionIds);
}
/**
*
*
* @param orgCode
* @return
*/
@GetMapping("/getUserAccountsByDepCode")
public List<String> getUserAccountsByDepCode(@RequestParam("orgCode") String orgCode){
return sysBaseApi.getUserAccountsByDepCode(orgCode);
}
/**
* sql
*
* @param selectSql
* @return
*/
@GetMapping("/dictTableWhiteListCheckBySql")
public boolean dictTableWhiteListCheckBySql(@RequestParam("selectSql") String selectSql) {
return sysBaseApi.dictTableWhiteListCheckBySql(selectSql);
}
/**
*
*
* @param tableOrDictCode dictCode
* @param fields dictCodenull
* @return
*/
@GetMapping("/dictTableWhiteListCheckByDict")
public boolean dictTableWhiteListCheckByDict(
@RequestParam("tableOrDictCode") String tableOrDictCode,
@RequestParam(value = "fields", required = false) String... fields
) {
return sysBaseApi.dictTableWhiteListCheckByDict(tableOrDictCode, fields);
}
}

@ -0,0 +1,111 @@
package org.jeecg.modules.cas.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.cas.util.CasServiceUtil;
import org.jeecg.modules.cas.util.XmlUtils;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
/**
* <p>
* CAS
* </p>
*
* @Author zhoujf
* @since 2018-12-20
*/
@Slf4j
@RestController
@RequestMapping("/sys/cas/client")
public class CasClientController {
@Autowired
private ISysUserService sysUserService;
@Autowired
private ISysDepartService sysDepartService;
@Autowired
private RedisUtil redisUtil;
@Value("${cas.prefixUrl}")
private String prefixUrl;
@GetMapping("/validateLogin")
public Object validateLogin(@RequestParam(name="ticket") String ticket,
@RequestParam(name="service") String service,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
Result<JSONObject> result = new Result<JSONObject>();
log.info("Rest api login.");
try {
String validateUrl = prefixUrl+"/p3/serviceValidate";
String res = CasServiceUtil.getStValidate(validateUrl, ticket, service);
log.info("res."+res);
final String error = XmlUtils.getTextForElement(res, "authenticationFailure");
if(StringUtils.isNotEmpty(error)) {
throw new Exception(error);
}
final String principal = XmlUtils.getTextForElement(res, "user");
if (StringUtils.isEmpty(principal)) {
throw new Exception("No principal was found in the response from the CAS server.");
}
log.info("-------token----username---"+principal);
//1. 校验用户是否有效
SysUser sysUser = sysUserService.getUserByName(principal);
result = sysUserService.checkUserIsEffective(sysUser);
if(!result.isSuccess()) {
return result;
}
String token = JwtUtil.sign(sysUser.getUsername(), sysUser.getPassword());
// 设置超时时间
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);
//获取用户部门信息
JSONObject obj = new JSONObject();
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
obj.put("departs", departs);
if (departs == null || departs.size() == 0) {
obj.put("multi_depart", 0);
} else if (departs.size() == 1) {
sysUserService.updateUserDepart(principal, departs.get(0).getOrgCode(),null);
obj.put("multi_depart", 1);
} else {
obj.put("multi_depart", 2);
}
obj.put("token", token);
obj.put("userInfo", sysUser);
result.setResult(obj);
result.success("登录成功");
} catch (Exception e) {
//e.printStackTrace();
result.error500(e.getMessage());
}
return new HttpEntity<>(result);
}
}

@ -0,0 +1,107 @@
package org.jeecg.modules.cas.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
/**
* @Description: CasServiceUtil
* @author: jeecg-boot
*/
public class CasServiceUtil {
public static void main(String[] args) {
String serviceUrl = "https://cas.8f8.com.cn:8443/cas/p3/serviceValidate";
String service = "http://localhost:3003/user/login";
String ticket = "ST-5-1g-9cNES6KXNRwq-GuRET103sm0-DESKTOP-VKLS8B3";
String res = getStValidate(serviceUrl,ticket, service);
System.out.println("---------res-----"+res);
}
/**
* ST
*/
public static String getStValidate(String url, String st, String service){
try {
url = url+"?service="+service+"&ticket="+st;
CloseableHttpClient httpclient = createHttpClientWithNoSsl();
HttpGet httpget = new HttpGet(url);
HttpResponse response = httpclient.execute(httpget);
String res = readResponse(response);
return res == null ? null : (res == "" ? null : res);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* response body
*
* @param response
* @return
* @throws IOException
*/
private static String readResponse(HttpResponse response) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String result = new String();
String line;
while ((line = in.readLine()) != null) {
result += line;
}
return result;
}
/**
* https SSL
*
* @param cookieStore Cookies
* @return
* @throws Exception
*/
private static CloseableHttpClient createHttpClientWithNoSsl() throws Exception {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
// don't check
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
// don't check
}
}
};
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, trustAllCerts, null);
LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(ctx);
return HttpClients.custom()
.setSSLSocketFactory(sslSocketFactory)
.build();
}
}

@ -0,0 +1,304 @@
package org.jeecg.modules.cas.util;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.jeecg.common.constant.CommonConstant;
import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import lombok.extern.slf4j.Slf4j;
/**
* cas,STxml
* @author: jeecg-boot
*/
@Slf4j
public final class XmlUtils {
/**
* attributes
*/
private static final String ATTRIBUTES = "attributes";
/**
* Creates a new namespace-aware DOM document object by parsing the given XML.
*
* @param xml XML content.
*
* @return DOM document.
*/
public static Document newDocument(final String xml) {
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final Map<String, Boolean> features = new HashMap(5);
features.put(XMLConstants.FEATURE_SECURE_PROCESSING, true);
features.put("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
for (final Map.Entry<String, Boolean> entry : features.entrySet()) {
try {
factory.setFeature(entry.getKey(), entry.getValue());
} catch (ParserConfigurationException e) {
log.warn("Failed setting XML feature {}: {}", entry.getKey(), e);
}
}
factory.setNamespaceAware(true);
try {
return factory.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
} catch (Exception e) {
throw new RuntimeException("XML parsing error: " + e);
}
}
/**
* Get an instance of an XML reader from the XMLReaderFactory.
*
* @return the XMLReader.
*/
public static XMLReader getXmlReader() {
try {
final XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
reader.setFeature("http://xml.org/sax/features/namespaces", true);
reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
return reader;
} catch (final Exception e) {
throw new RuntimeException("Unable to create XMLReader", e);
}
}
/**
* Retrieve the text for a group of elements. Each text element is an entry
* in a list.
* <p>This method is currently optimized for the use case of two elements in a list.
*
* @param xmlAsString the xml response
* @param element the element to look for
* @return the list of text from the elements.
*/
public static List<String> getTextForElements(final String xmlAsString, final String element) {
final List<String> elements = new ArrayList<String>(2);
final XMLReader reader = getXmlReader();
final DefaultHandler handler = new DefaultHandler() {
private boolean foundElement = false;
private StringBuilder buffer = new StringBuilder();
@Override
public void startElement(final String uri, final String localName, final String qName,
final Attributes attributes) throws SAXException {
if (localName.equals(element)) {
this.foundElement = true;
}
}
@Override
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
if (localName.equals(element)) {
this.foundElement = false;
elements.add(this.buffer.toString());
this.buffer = new StringBuilder();
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (this.foundElement) {
this.buffer.append(ch, start, length);
}
}
};
reader.setContentHandler(handler);
reader.setErrorHandler(handler);
try {
reader.parse(new InputSource(new StringReader(xmlAsString)));
} catch (final Exception e) {
log.error(e.getMessage(), e);
return null;
}
return elements;
}
/**
* Retrieve the text for a specific element (when we know there is only
* one).
*
* @param xmlAsString the xml response
* @param element the element to look for
* @return the text value of the element.
*/
public static String getTextForElement(final String xmlAsString, final String element) {
final XMLReader reader = getXmlReader();
final StringBuilder builder = new StringBuilder();
final DefaultHandler handler = new DefaultHandler() {
private boolean foundElement = false;
@Override
public void startElement(final String uri, final String localName, final String qName,
final Attributes attributes) throws SAXException {
if (localName.equals(element)) {
this.foundElement = true;
}
}
@Override
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
if (localName.equals(element)) {
this.foundElement = false;
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (this.foundElement) {
builder.append(ch, start, length);
}
}
};
reader.setContentHandler(handler);
reader.setErrorHandler(handler);
try {
reader.parse(new InputSource(new StringReader(xmlAsString)));
} catch (final Exception e) {
log.error(e.getMessage(), e);
return null;
}
return builder.toString();
}
public static Map<String, Object> extractCustomAttributes(final String xml) {
final SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(false);
try {
final SAXParser saxParser = spf.newSAXParser();
final XMLReader xmlReader = saxParser.getXMLReader();
final CustomAttributeHandler handler = new CustomAttributeHandler();
xmlReader.setContentHandler(handler);
xmlReader.parse(new InputSource(new StringReader(xml)));
return handler.getAttributes();
} catch (final Exception e) {
log.error(e.getMessage(), e);
return Collections.emptyMap();
}
}
private static class CustomAttributeHandler extends DefaultHandler {
private Map<String, Object> attributes;
private boolean foundAttributes;
private String currentAttribute;
private StringBuilder value;
@Override
public void startDocument() throws SAXException {
this.attributes = new HashMap(5);
}
@Override
public void startElement(final String nameSpaceUri, final String localName, final String qName,
final Attributes attributes) throws SAXException {
if (ATTRIBUTES.equals(localName)) {
this.foundAttributes = true;
} else if (this.foundAttributes) {
this.value = new StringBuilder();
this.currentAttribute = localName;
}
}
@Override
public void characters(final char[] chars, final int start, final int length) throws SAXException {
if (this.currentAttribute != null) {
value.append(chars, start, length);
}
}
@Override
public void endElement(final String nameSpaceUri, final String localName, final String qName)
throws SAXException {
if (ATTRIBUTES.equals(localName)) {
this.foundAttributes = false;
this.currentAttribute = null;
} else if (this.foundAttributes) {
final Object o = this.attributes.get(this.currentAttribute);
if (o == null) {
this.attributes.put(this.currentAttribute, this.value.toString());
} else {
final List<Object> items;
if (o instanceof List) {
items = (List<Object>) o;
} else {
items = new LinkedList<Object>();
items.add(o);
this.attributes.put(this.currentAttribute, items);
}
items.add(this.value.toString());
}
}
}
public Map<String, Object> getAttributes() {
return this.attributes;
}
}
public static void main(String[] args) {
String result = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>\r\n" +
" <cas:authenticationSuccess>\r\n" +
" <cas:user>admin</cas:user>\r\n" +
" <cas:attributes>\r\n" +
" <cas:credentialType>UsernamePasswordCredential</cas:credentialType>\r\n" +
" <cas:isFromNewLogin>true</cas:isFromNewLogin>\r\n" +
" <cas:authenticationDate>2019-08-01T19:33:21.527+08:00[Asia/Shanghai]</cas:authenticationDate>\r\n" +
" <cas:authenticationMethod>RestAuthenticationHandler</cas:authenticationMethod>\r\n" +
" <cas:successfulAuthenticationHandlers>RestAuthenticationHandler</cas:successfulAuthenticationHandlers>\r\n" +
" <cas:longTermAuthenticationRequestTokenUsed>false</cas:longTermAuthenticationRequestTokenUsed>\r\n" +
" </cas:attributes>\r\n" +
" </cas:authenticationSuccess>\r\n" +
"</cas:serviceResponse>";
String errorRes = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>\r\n" +
" <cas:authenticationFailure code=\"INVALID_TICKET\">未能够识别出目标 &#39;ST-5-1g-9cNES6KXNRwq-GuRET103sm0-DESKTOP-VKLS8B3&#39;票根</cas:authenticationFailure>\r\n" +
"</cas:serviceResponse>";
String error = XmlUtils.getTextForElement(errorRes, "authenticationFailure");
System.out.println("------"+error);
String error2 = XmlUtils.getTextForElement(result, "authenticationFailure");
System.out.println("------"+error2);
String principal = XmlUtils.getTextForElement(result, "user");
System.out.println("---principal---"+principal);
Map<String, Object> attributes = XmlUtils.extractCustomAttributes(result);
System.out.println("---attributes---"+attributes);
}
}

@ -0,0 +1,145 @@
package org.jeecg.modules.message.controller;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.message.entity.SysMessage;
import org.jeecg.modules.message.service.ISysMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
/**
* @Description:
* @author: jeecg-boot
* @date: 2019-04-09
* @version: V1.0
*/
@Slf4j
@RestController
@RequestMapping("/sys/message/sysMessage")
public class SysMessageController extends JeecgController<SysMessage, ISysMessageService> {
@Autowired
private ISysMessageService sysMessageService;
/**
*
*
* @param sysMessage
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@GetMapping(value = "/list")
public Result<?> queryPageList(SysMessage sysMessage, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
QueryWrapper<SysMessage> queryWrapper = QueryGenerator.initQueryWrapper(sysMessage, req.getParameterMap());
Page<SysMessage> page = new Page<SysMessage>(pageNo, pageSize);
IPage<SysMessage> pageList = sysMessageService.page(page, queryWrapper);
return Result.ok(pageList);
}
/**
*
*
* @param sysMessage
* @return
*/
@PostMapping(value = "/add")
public Result<?> add(@RequestBody SysMessage sysMessage) {
sysMessageService.save(sysMessage);
return Result.ok("添加成功!");
}
/**
*
*
* @param sysMessage
* @return
*/
@PutMapping(value = "/edit")
public Result<?> edit(@RequestBody SysMessage sysMessage) {
sysMessageService.updateById(sysMessage);
return Result.ok("修改成功!");
}
/**
* id
*
* @param id
* @return
*/
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
sysMessageService.removeById(id);
return Result.ok("删除成功!");
}
/**
*
*
* @param ids
* @return
*/
@DeleteMapping(value = "/deleteBatch")
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.sysMessageService.removeByIds(Arrays.asList(ids.split(",")));
return Result.ok("批量删除成功!");
}
/**
* id
*
* @param id
* @return
*/
@GetMapping(value = "/queryById")
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
SysMessage sysMessage = sysMessageService.getById(id);
return Result.ok(sysMessage);
}
/**
* excel
*
* @param request
*/
@GetMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, SysMessage sysMessage) {
return super.exportXls(request,sysMessage,SysMessage.class, "推送消息模板");
}
/**
* excel
*
* @param request
* @param response
* @return
*/
@PostMapping(value = "/importExcel")
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, SysMessage.class);
}
}

@ -0,0 +1,180 @@
package org.jeecg.modules.message.controller;
import java.util.Arrays;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.message.entity.MsgParams;
import org.jeecg.modules.message.entity.SysMessageTemplate;
import org.jeecg.modules.message.service.ISysMessageTemplateService;
import org.jeecg.modules.message.util.PushMsgUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
/**
* @Description:
* @Author: jeecg-boot
* @Sate: 2019-04-09
* @Version: V1.0
*/
@Slf4j
@RestController
@RequestMapping("/sys/message/sysMessageTemplate")
public class SysMessageTemplateController extends JeecgController<SysMessageTemplate, ISysMessageTemplateService> {
@Autowired
private ISysMessageTemplateService sysMessageTemplateService;
@Autowired
private PushMsgUtil pushMsgUtil;
@Autowired
private ISysBaseAPI sysBaseApi;
/**
*
*
* @param sysMessageTemplate
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@GetMapping(value = "/list")
public Result<?> queryPageList(SysMessageTemplate sysMessageTemplate, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
QueryWrapper<SysMessageTemplate> queryWrapper = QueryGenerator.initQueryWrapper(sysMessageTemplate, req.getParameterMap());
Page<SysMessageTemplate> page = new Page<SysMessageTemplate>(pageNo, pageSize);
IPage<SysMessageTemplate> pageList = sysMessageTemplateService.page(page, queryWrapper);
return Result.ok(pageList);
}
/**
*
*
* @param sysMessageTemplate
* @return
*/
@PostMapping(value = "/add")
public Result<?> add(@RequestBody SysMessageTemplate sysMessageTemplate) {
sysMessageTemplateService.save(sysMessageTemplate);
return Result.ok("添加成功!");
}
/**
*
*
* @param sysMessageTemplate
* @return
*/
@PutMapping(value = "/edit")
public Result<?> edit(@RequestBody SysMessageTemplate sysMessageTemplate) {
sysMessageTemplateService.updateById(sysMessageTemplate);
return Result.ok("更新成功!");
}
/**
* id
*
* @param id
* @return
*/
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
sysMessageTemplateService.removeById(id);
return Result.ok("删除成功!");
}
/**
*
*
* @param ids
* @return
*/
@DeleteMapping(value = "/deleteBatch")
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.sysMessageTemplateService.removeByIds(Arrays.asList(ids.split(",")));
return Result.ok("批量删除成功!");
}
/**
* id
*
* @param id
* @return
*/
@GetMapping(value = "/queryById")
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
SysMessageTemplate sysMessageTemplate = sysMessageTemplateService.getById(id);
return Result.ok(sysMessageTemplate);
}
/**
* excel
*
* @param request
*/
@GetMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request,SysMessageTemplate sysMessageTemplate) {
return super.exportXls(request, sysMessageTemplate, SysMessageTemplate.class,"推送消息模板");
}
/**
* excel
*
* @param request
* @param response
* @return
*/
@PostMapping(value = "/importExcel")
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, SysMessageTemplate.class);
}
/**
*
*/
@PostMapping(value = "/sendMsg")
public Result<SysMessageTemplate> sendMessage(@RequestBody MsgParams msgParams) {
Result<SysMessageTemplate> result = new Result<SysMessageTemplate>();
try {
MessageDTO md = new MessageDTO();
md.setToAll(false);
md.setTitle("消息发送测试");
md.setTemplateCode(msgParams.getTemplateCode());
md.setToUser(msgParams.getReceiver());
md.setType(msgParams.getMsgType());
String testData = msgParams.getTestData();
if(oConvertUtils.isNotEmpty(testData)){
Map<String, Object> data = JSON.parseObject(testData, Map.class);
md.setData(data);
}
sysBaseApi.sendTemplateMessage(md);
return result.success("消息发送成功!");
} catch (Exception e) {
log.error("发送消息出错:" + e.getMessage(), e);
return result.error500("发送消息出错!");
}
}
}

@ -0,0 +1,53 @@
package org.jeecg.modules.message.controller;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.WebsocketConst;
import org.jeecg.modules.message.websocket.WebSocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
/**
* @Description: TestSocketController
* @author: jeecg-boot
*/
@RestController
@RequestMapping("/sys/socketTest")
public class TestSocketController {
@Autowired
private WebSocket webSocket;
@PostMapping("/sendAll")
public Result<String> sendAll(@RequestBody JSONObject jsonObject) {
Result<String> result = new Result<String>();
String message = jsonObject.getString("message");
JSONObject obj = new JSONObject();
obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_TOPIC);
obj.put(WebsocketConst.MSG_ID, "M0001");
obj.put(WebsocketConst.MSG_TXT, message);
webSocket.sendMessage(obj.toJSONString());
result.setResult("群发!");
return result;
}
@PostMapping("/sendUser")
public Result<String> sendUser(@RequestBody JSONObject jsonObject) {
Result<String> result = new Result<String>();
String userId = jsonObject.getString("userId");
String message = jsonObject.getString("message");
JSONObject obj = new JSONObject();
obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
obj.put(WebsocketConst.MSG_USER_ID, userId);
obj.put(WebsocketConst.MSG_ID, "M0001");
obj.put(WebsocketConst.MSG_TXT, message);
webSocket.sendMessage(userId, obj.toJSONString());
result.setResult("单发");
return result;
}
}

@ -0,0 +1,35 @@
package org.jeecg.modules.message.entity;
import java.io.Serializable;
import lombok.Data;
/**
*
* @author: jeecg-boot
*/
@Data
public class MsgParams implements Serializable {
private static final long serialVersionUID = 1L;
/**
*
*/
private String msgType;
/**
*
*/
private String receiver;
/**
*
*/
private String templateCode;
/**
*
*/
private String testData;
}

@ -0,0 +1,62 @@
package org.jeecg.modules.message.entity;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecg.common.system.base.entity.JeecgEntity;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @Description:
* @Author: jeecg-boot
* @Date: 2019-04-09
* @Version: V1.0
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_sms")
public class SysMessage extends JeecgEntity {
/**推送内容*/
@Excel(name = "推送内容", width = 15)
private java.lang.String esContent;
/**推送所需参数Json格式*/
@Excel(name = "推送所需参数Json格式", width = 15)
private java.lang.String esParam;
/**接收人*/
@Excel(name = "接收人", width = 15)
private java.lang.String esReceiver;
/**推送失败原因*/
@Excel(name = "推送失败原因", width = 15)
private java.lang.String esResult;
/**发送次数*/
@Excel(name = "发送次数", width = 15)
private java.lang.Integer esSendNum;
/**推送状态 0未推送 1推送成功 2推送失败*/
@Excel(name = "推送状态 0未推送 1推送成功 2推送失败", width = 15)
@Dict(dicCode = "msgSendStatus")
private java.lang.String esSendStatus;
/**推送时间*/
@Excel(name = "推送时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private java.util.Date esSendTime;
/**消息标题*/
@Excel(name = "消息标题", width = 15)
private java.lang.String esTitle;
/**
* MessageTypeEnum
*/
@Excel(name = "推送方式", width = 15)
@Dict(dicCode = "messageType")
private java.lang.String esType;
/**备注*/
@Excel(name = "备注", width = 15)
private java.lang.String remark;
}

@ -0,0 +1,43 @@
package org.jeecg.modules.message.entity;
import org.jeecg.common.system.base.entity.JeecgEntity;
import org.jeecgframework.poi.excel.annotation.Excel;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @Description:
* @Author: jeecg-boot
* @Date: 2019-04-09
* @Version: V1.0
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_sms_template")
public class SysMessageTemplate extends JeecgEntity{
/**模板CODE*/
@Excel(name = "模板CODE", width = 15)
private java.lang.String templateCode;
/**模板标题*/
@Excel(name = "模板标题", width = 30)
private java.lang.String templateName;
/**模板内容*/
@Excel(name = "模板内容", width = 50)
private java.lang.String templateContent;
/**模板测试json*/
@Excel(name = "模板测试json", width = 15)
private java.lang.String templateTestJson;
/**模板类型*/
@Excel(name = "模板类型", width = 15)
private java.lang.String templateType;
/**已经应用/未应用 1是0否*/
@Excel(name = "应用状态", width = 15)
private String useStatus;
}

@ -0,0 +1,135 @@
package org.jeecg.modules.message.enums;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.enums.MessageTypeEnum;
import org.jeecg.common.system.annotation.EnumDict;
import org.jeecg.common.system.vo.DictModel;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* vue3
*
* @Author taoYan
* @Date 2022/8/19 20:41
**/
@Slf4j
@EnumDict("rangeDate")
public enum RangeDateEnum {
JT("jt", "今天"),
ZT("zt", "昨天"),
QT("qt", "前天"),
BZ("bz","本周"),
SZ("sz", "上周"),
BY("by", "本月"),
SY("sy", "上月"),
SEVENDAYS("7day", "7日"),
ZDY("zdy", "自定义日期");
String key;
String title;
RangeDateEnum(String key, String title){
this.key = key;
this.title = title;
}
/**
*
* @return
*/
public static List<DictModel> getDictList(){
List<DictModel> list = new ArrayList<>();
DictModel dictModel = null;
for(RangeDateEnum e: RangeDateEnum.values()){
dictModel = new DictModel();
dictModel.setValue(e.key);
dictModel.setText(e.title);
list.add(dictModel);
}
return list;
}
/**
* key
* @param key
* @return
*/
public static Date[] getRangeArray(String key){
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
Date[] array = new Date[2];
boolean flag = false;
if(JT.key.equals(key)){
//今天
} else if(ZT.key.equals(key)){
//昨天
calendar1.add(Calendar.DAY_OF_YEAR, -1);
calendar2.add(Calendar.DAY_OF_YEAR, -1);
} else if(QT.key.equals(key)){
//前天
calendar1.add(Calendar.DAY_OF_YEAR, -2);
calendar2.add(Calendar.DAY_OF_YEAR, -2);
} else if(BZ.key.equals(key)){
//本周
calendar1.set(Calendar.DAY_OF_WEEK, 2);
calendar2.add(Calendar.WEEK_OF_MONTH,1);
calendar2.add(Calendar.DAY_OF_WEEK,-1);
} else if(SZ.key.equals(key)){
//本周一减一周
calendar1.set(Calendar.DAY_OF_WEEK, 2);
calendar1.add(Calendar.WEEK_OF_MONTH, -1);
// 本周一减一天
calendar2.set(Calendar.DAY_OF_WEEK, 2);
calendar2.add(Calendar.DAY_OF_WEEK,-1);
} else if(BY.key.equals(key)){
//本月
calendar1.set(Calendar.DAY_OF_MONTH, 1);
calendar2.set(Calendar.DAY_OF_MONTH, 1);
calendar2.add(Calendar.MONTH, 1);
calendar2.add(Calendar.DAY_OF_MONTH, -1);
} else if(SY.key.equals(key)){
//本月第一天减一月
calendar1.set(Calendar.DAY_OF_MONTH, 1);
calendar1.add(Calendar.MONTH, -1);
//本月第一天减一天
calendar2.set(Calendar.DAY_OF_MONTH, 1);
calendar2.add(Calendar.DAY_OF_MONTH, -1);
} else if (SEVENDAYS.key.equals(key)){
//七日第一天
calendar1.setTime(new Date());
calendar1.add(Calendar.DATE, -7);
}else{
flag = true;
}
if(flag){
return null;
}
// 开始时间00:00:00 结束时间23:59:59
calendar1.set(Calendar.HOUR, 0);
calendar1.set(Calendar.MINUTE, 0);
calendar1.set(Calendar.SECOND, 0);
calendar1.set(Calendar.MILLISECOND, 0);
calendar2.set(Calendar.HOUR, 23);
calendar2.set(Calendar.MINUTE, 59);
calendar2.set(Calendar.SECOND, 59);
calendar2.set(Calendar.MILLISECOND, 999);
array[0] = calendar1.getTime();
array[1] = calendar2.getTime();
return array;
}
public String getKey(){
return this.key;
}
}

@ -0,0 +1,26 @@
package org.jeecg.modules.message.handle;
import org.jeecg.common.api.dto.message.MessageDTO;
/**
* @Description:
* @author: jeecg-boot
*/
public interface ISendMsgHandle {
/**
*
* @param esReceiver
* @param esTitle
* @param esContent
*/
void sendMsg(String esReceiver, String esTitle, String esContent);
/**
*
* @param messageDTO
*/
default void sendMessage(MessageDTO messageDTO){
}
}

@ -0,0 +1,26 @@
package org.jeecg.modules.message.handle.enums;
/**
*
* @author: jeecg-boot
*/
public enum SendMsgStatusEnum {
//推送状态 0未推送 1推送成功 2推送失败
WAIT("0"), SUCCESS("1"), FAIL("2");
private String code;
private SendMsgStatusEnum(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public void setStatusCode(String code) {
this.code = code;
}
}

@ -0,0 +1,64 @@
package org.jeecg.modules.message.handle.enums;
import org.jeecg.common.util.oConvertUtils;
/**
*
* @author: jeecg-boot
*/
public enum SendMsgTypeEnum {
/**
*
*/
SMS("1", "org.jeecg.modules.message.handle.impl.SmsSendMsgHandle"),
/**
*
*/
EMAIL("2", "org.jeecg.modules.message.handle.impl.EmailSendMsgHandle"),
/**
*
*/
WX("3","org.jeecg.modules.message.handle.impl.WxSendMsgHandle"),
/**
*
*/
SYSTEM_MESSAGE("4","org.jeecg.modules.message.handle.impl.SystemSendMsgHandle");
private String type;
private String implClass;
private SendMsgTypeEnum(String type, String implClass) {
this.type = type;
this.implClass = implClass;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getImplClass() {
return implClass;
}
public void setImplClass(String implClass) {
this.implClass = implClass;
}
public static SendMsgTypeEnum getByType(String type) {
if (oConvertUtils.isEmpty(type)) {
return null;
}
for (SendMsgTypeEnum val : values()) {
if (val.getType().equals(type)) {
return val;
}
}
return null;
}
}

@ -0,0 +1,37 @@
package org.jeecg.modules.message.handle.impl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.modules.message.handle.ISendMsgHandle;
import org.jeecg.modules.system.service.impl.ThirdAppDingtalkServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @Description:
* @author: jeecg-boot
*/
@Slf4j
@Component("ddSendMsgHandle")
public class DdSendMsgHandle implements ISendMsgHandle {
@Autowired
private ThirdAppDingtalkServiceImpl dingtalkService;
@Override
public void sendMsg(String esReceiver, String esTitle, String esContent) {
log.info("发微信消息模板");
MessageDTO messageDTO = new MessageDTO();
messageDTO.setToUser(esReceiver);
messageDTO.setTitle(esTitle);
messageDTO.setContent(esContent);
messageDTO.setToAll(false);
sendMessage(messageDTO);
}
@Override
public void sendMessage(MessageDTO messageDTO) {
dingtalkService.sendMessage(messageDTO, true);
}
}

@ -0,0 +1,270 @@
package org.jeecg.modules.message.handle.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.enums.MessageTypeEnum;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.StaticConfig;
import org.jeecg.modules.message.entity.SysMessage;
import org.jeecg.modules.message.handle.ISendMsgHandle;
import org.jeecg.modules.message.mapper.SysMessageMapper;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Set;
/**
* @Description:
* @author: jeecg-boot
*/
@Slf4j
@Component("emailSendMsgHandle")
public class EmailSendMsgHandle implements ISendMsgHandle {
static String emailFrom;
public static void setEmailFrom(String emailFrom) {
EmailSendMsgHandle.emailFrom = emailFrom;
}
@Autowired
SysUserMapper sysUserMapper;
@Autowired
private RedisUtil redisUtil;
@Autowired
private SysMessageMapper sysMessageMapper;
/**
*
*/
private static final String realNameExp = "{REALNAME}";
@Override
public void sendMsg(String esReceiver, String esTitle, String esContent) {
JavaMailSender mailSender = (JavaMailSender) SpringContextUtils.getBean("mailSender");
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = null;
//update-begin-authortaoyan date:20200811 for:配置类数据获取
if(oConvertUtils.isEmpty(emailFrom)){
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
setEmailFrom(staticConfig.getEmailFrom());
}
//update-end-authortaoyan date:20200811 for:配置类数据获取
try {
helper = new MimeMessageHelper(message, true);
// 设置发送方邮箱地址
helper.setFrom(emailFrom);
helper.setTo(esReceiver);
helper.setSubject(esTitle);
helper.setText(esContent, true);
mailSender.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
}
@Override
public void sendMessage(MessageDTO messageDTO) {
String content = messageDTO.getContent();
String title = messageDTO.getTitle();
//update-begin---author:wangshuai---date:2024-11-20---for:【QQYUN-8523】敲敲云发邮件通知不稳定---
boolean timeJobSendEmail = this.isTimeJobSendEmail(messageDTO.getToUser(), title, content);
if(timeJobSendEmail){
return;
}
//update-end---author:wangshuai---date:2024-11-20---for:【QQYUN-8523】敲敲云发邮件通知不稳定---
this.sendEmailMessage(messageDTO);
}
/**
*
*
* @param messageDTO
*/
public void sendEmailMessage(MessageDTO messageDTO) {
String[] arr = messageDTO.getToUser().split(",");
LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<SysUser>().in(SysUser::getUsername, arr);
List<SysUser> list = sysUserMapper.selectList(query);
String content = messageDTO.getContent();
String title = messageDTO.getTitle();
for(SysUser user: list){
String email = user.getEmail();
if (ObjectUtils.isEmpty(email)) {
continue;
}
content=replaceContent(user,content);
log.info("邮件内容:"+ content);
sendMsg(email, title, content);
}
//update-begin-author:taoyan date:2023-6-20 for: QQYUN-5557【简流】通知节点 发送邮箱 表单上有一个邮箱字段,流程中,邮件发送节点,邮件接收人 不可选择邮箱
Set<String> toEmailList = messageDTO.getToEmailList();
if(toEmailList!=null && toEmailList.size()>0){
for(String email: toEmailList){
if (ObjectUtils.isEmpty(email)) {
continue;
}
log.info("邮件内容:"+ content);
sendMsg(email, title, content);
}
}
//update-end-author:taoyan date:2023-6-20 for: QQYUN-5557【简流】通知节点 发送邮箱 表单上有一个邮箱字段,流程中,邮件发送节点,邮件接收人 不可选择邮箱
//发送给抄送人
sendMessageToCopyUser(messageDTO);
}
/**
*
* @param messageDTO
*/
public void sendMessageToCopyUser(MessageDTO messageDTO) {
String copyToUser = messageDTO.getCopyToUser();
if(ObjectUtils.isNotEmpty(copyToUser)) {
LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<SysUser>().in(SysUser::getUsername, copyToUser.split(","));
List<SysUser> list = sysUserMapper.selectList(query);
String content = messageDTO.getContent();
String title = messageDTO.getTitle();
for (SysUser user : list) {
String email = user.getEmail();
if (ObjectUtils.isEmpty(email)) {
continue;
}
content=replaceContent(user,content);
log.info("邮件内容:" + content);
//update-begin-author:taoyan date:2023-6-20 for: QQYUN-5557【简流】通知节点 发送邮箱 表单上有一个邮箱字段,流程中,邮件发送节点,邮件接收人 不可选择邮箱
sendEmail(email, content, title);
}
Set<String> ccEmailList = messageDTO.getCcEmailList();
if(ccEmailList!=null && ccEmailList.size()>0){
for(String email: ccEmailList){
if (ObjectUtils.isEmpty(email)) {
continue;
}
log.info("邮件内容:"+ content);
sendEmail(email, content, title);
}
}
}
}
/**
*
* @param email
* @param content
* @param title
*/
private void sendEmail(String email, String content, String title){
JavaMailSender mailSender = (JavaMailSender) SpringContextUtils.getBean("mailSender");
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = null;
if (oConvertUtils.isEmpty(emailFrom)) {
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
setEmailFrom(staticConfig.getEmailFrom());
}
try {
helper = new MimeMessageHelper(message, true);
// 设置发送方邮箱地址
helper.setFrom(emailFrom);
helper.setTo(email);
//设置抄送人
helper.setCc(email);
helper.setSubject(title);
helper.setText(content, true);
mailSender.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
}
//update-end-author:taoyan date:2023-6-20 for: QQYUN-5557【简流】通知节点 发送邮箱 表单上有一个邮箱字段,流程中,邮件发送节点,邮件接收人 不可选择邮箱
/**
*
* @param user
* @param content
* @return
*/
private String replaceContent(SysUser user,String content){
if (content.indexOf(realNameExp) > 0) {
content = content.replace("$"+realNameExp,user.getRealname()).replace(realNameExp, user.getRealname());
}
if (content.indexOf(CommonConstant.LOGIN_TOKEN) > 0) {
String token = getToken(user);
try {
content = content.replace(CommonConstant.LOGIN_TOKEN, URLEncoder.encode(token, "UTF-8"));
} catch (UnsupportedEncodingException e) {
log.error("邮件消息token编码失败", e.getMessage());
}
}
return content;
}
/**
* token
* @param user
* @return
*/
private String getToken(SysUser user) {
// 生成token
String token = JwtUtil.sign(user.getUsername(), user.getPassword());
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
// 设置超时时间 1个小时
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 1 / 1000);
return token;
}
/**
*
* @param toUser
* @param title
* @param content
* @return
*/
private boolean isTimeJobSendEmail(String toUser, String title, String content) {
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
Boolean timeJobSend = staticConfig.getTimeJobSend();
if(null != timeJobSend && timeJobSend){
this.addSysSmsSend(toUser,title,content);
return true;
}
return false;
}
/**
*
*/
private void addSysSmsSend(String toUser, String title, String content) {
SysMessage sysMessage = new SysMessage();
sysMessage.setEsTitle(title);
sysMessage.setEsContent(content);
sysMessage.setEsReceiver(toUser);
sysMessage.setEsSendStatus("0");
sysMessage.setEsSendNum(0);
sysMessage.setEsType(MessageTypeEnum.YJ.getType());
sysMessageMapper.insert(sysMessage);
}
}

@ -0,0 +1,37 @@
package org.jeecg.modules.message.handle.impl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.modules.message.handle.ISendMsgHandle;
import org.jeecg.modules.system.service.impl.ThirdAppWechatEnterpriseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @Description:
* @author: jeecg-boot
*/
@Slf4j
@Component("qywxSendMsgHandle")
public class QywxSendMsgHandle implements ISendMsgHandle {
@Autowired
private ThirdAppWechatEnterpriseServiceImpl wechatEnterpriseService;
@Override
public void sendMsg(String esReceiver, String esTitle, String esContent) {
log.info("发微信消息模板");
MessageDTO messageDTO = new MessageDTO();
messageDTO.setToUser(esReceiver);
messageDTO.setTitle(esTitle);
messageDTO.setContent(esContent);
messageDTO.setToAll(false);
sendMessage(messageDTO);
}
@Override
public void sendMessage(MessageDTO messageDTO) {
wechatEnterpriseService.sendMessage(messageDTO, true);
}
}

@ -0,0 +1,19 @@
package org.jeecg.modules.message.handle.impl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.message.handle.ISendMsgHandle;
/**
* @Description:
* @author: jeecg-boot
*/
@Slf4j
public class SmsSendMsgHandle implements ISendMsgHandle {
@Override
public void sendMsg(String esReceiver, String esTitle, String esContent) {
// TODO Auto-generated method stub
log.info("发短信");
}
}

@ -0,0 +1,137 @@
package org.jeecg.modules.message.handle.impl;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.WebsocketConst;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.constant.enums.Vue3MessageHrefEnum;
import org.jeecg.modules.message.handle.ISendMsgHandle;
import org.jeecg.modules.message.websocket.WebSocket;
import org.jeecg.modules.system.entity.SysAnnouncement;
import org.jeecg.modules.system.entity.SysAnnouncementSend;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysAnnouncementMapper;
import org.jeecg.modules.system.mapper.SysAnnouncementSendMapper;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
/**
* @Description:
* @Author: wangshuai
* @Date: 2022322 18:48:20
*/
@Component("systemSendMsgHandle")
public class SystemSendMsgHandle implements ISendMsgHandle {
public static final String FROM_USER="system";
@Resource
private SysAnnouncementMapper sysAnnouncementMapper;
@Resource
private SysUserMapper userMapper;
@Resource
private SysAnnouncementSendMapper sysAnnouncementSendMapper;
@Resource
private WebSocket webSocket;
/**
* 3
* @param esReceiver
* @param esTitle
* @param esContent
*/
@Override
public void sendMsg(String esReceiver, String esTitle, String esContent) {
if(oConvertUtils.isEmpty(esReceiver)){
throw new JeecgBootException("被发送人不能为空");
}
ISysBaseAPI sysBaseApi = SpringContextUtils.getBean(ISysBaseAPI.class);
MessageDTO messageDTO = new MessageDTO(FROM_USER,esReceiver,esTitle,esContent);
sysBaseApi.sendSysAnnouncement(messageDTO);
}
/**
*
* @param messageDTO
*/
@Override
public void sendMessage(MessageDTO messageDTO) {
//原方法不支持 sysBaseApi.sendSysAnnouncement(messageDTO); 有企业微信消息逻辑,
String title = messageDTO.getTitle();
String content = messageDTO.getContent();
String fromUser = messageDTO.getFromUser();
Map<String,Object> data = messageDTO.getData();
String[] arr = messageDTO.getToUser().split(",");
for(String username: arr){
doSend(title, content, fromUser, username, data);
}
}
private void doSend(String title, String msgContent, String fromUser, String toUser, Map<String, Object> data){
SysAnnouncement announcement = new SysAnnouncement();
if(data!=null){
//摘要信息
Object msgAbstract = data.get(CommonConstant.NOTICE_MSG_SUMMARY);
if(msgAbstract!=null){
announcement.setMsgAbstract(msgAbstract.toString());
}
// 任务节点ID
Object taskId = data.get(CommonConstant.NOTICE_MSG_BUS_ID);
if(taskId!=null){
announcement.setBusId(taskId.toString());
announcement.setBusType(Vue3MessageHrefEnum.BPM_TASK.getBusType());
}
// 流程内消息节点 发消息会传一个busType
Object busType = data.get(CommonConstant.NOTICE_MSG_BUS_TYPE);
if(busType!=null){
announcement.setBusType(busType.toString());
}
}
announcement.setTitile(title);
announcement.setMsgContent(msgContent);
announcement.setSender(fromUser);
announcement.setPriority(CommonConstant.PRIORITY_M);
announcement.setMsgType(CommonConstant.MSG_TYPE_UESR);
announcement.setSendStatus(CommonConstant.HAS_SEND);
announcement.setSendTime(new Date());
//系统消息
announcement.setMsgCategory("2");
announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
sysAnnouncementMapper.insert(announcement);
// 2.插入用户通告阅读标记表记录
String userId = toUser;
String[] userIds = userId.split(",");
String anntId = announcement.getId();
for(int i=0;i<userIds.length;i++) {
if(oConvertUtils.isNotEmpty(userIds[i])) {
SysUser sysUser = userMapper.getUserByName(userIds[i]);
if(sysUser==null) {
continue;
}
SysAnnouncementSend announcementSend = new SysAnnouncementSend();
announcementSend.setAnntId(anntId);
announcementSend.setUserId(sysUser.getId());
announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
sysAnnouncementSendMapper.insert(announcementSend);
JSONObject obj = new JSONObject();
obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
obj.put(WebsocketConst.MSG_USER_ID, sysUser.getId());
obj.put(WebsocketConst.MSG_ID, announcement.getId());
obj.put(WebsocketConst.MSG_TXT, announcement.getTitile());
webSocket.sendMessage(sysUser.getId(), obj.toJSONString());
}
}
}
}

@ -0,0 +1,19 @@
package org.jeecg.modules.message.handle.impl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.message.handle.ISendMsgHandle;
/**
* @Description:
* @author: jeecg-boot
*/
@Slf4j
public class WxSendMsgHandle implements ISendMsgHandle {
@Override
public void sendMsg(String esReceiver, String esTitle, String esContent) {
// TODO Auto-generated method stub
log.info("发微信消息模板");
}
}

@ -0,0 +1,73 @@
package org.jeecg.modules.message.job;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.dto.message.MessageDTO;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.message.entity.SysMessage;
import org.jeecg.modules.message.handle.enums.SendMsgStatusEnum;
import org.jeecg.modules.message.service.ISysMessageService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
/**
*
* @author: jeecg-boot
*/
@Slf4j
public class SendMsgJob implements Job {
@Autowired
private ISysMessageService sysMessageService;
@Autowired
private ISysBaseAPI sysBaseAPI;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info(String.format(" Jeecg-Boot 发送消息任务 SendMsgJob ! 时间:" + DateUtils.getTimestamp()));
// 1.读取消息中心数据,只查询未发送的和发送失败不超过次数的
QueryWrapper<SysMessage> queryWrapper = new QueryWrapper<SysMessage>();
queryWrapper.eq("es_send_status", SendMsgStatusEnum.WAIT.getCode())
.or(i -> i.eq("es_send_status", SendMsgStatusEnum.FAIL.getCode()).lt("es_send_num", 6));
List<SysMessage> sysMessages = sysMessageService.list(queryWrapper);
System.out.println(sysMessages);
// 2.根据不同的类型走不通的发送实现类
for (SysMessage sysMessage : sysMessages) {
//update-begin-author:taoyan date:2022-7-8 for: 模板消息发送测试调用方法修改
Integer sendNum = sysMessage.getEsSendNum();
try {
MessageDTO md = new MessageDTO();
md.setTitle(sysMessage.getEsTitle());
md.setContent(sysMessage.getEsContent());
md.setToUser(sysMessage.getEsReceiver());
md.setType(sysMessage.getEsType());
md.setToAll(false);
//update-begin---author:wangshuai---date:2024-11-12---for:【QQYUN-8523】敲敲云发邮件通知不稳定---
md.setIsTimeJob(true);
//update-end---author:wangshuai---date:2024-11-12---for:【QQYUN-8523】敲敲云发邮件通知不稳定---
sysBaseAPI.sendTemplateMessage(md);
//发送消息成功
sysMessage.setEsSendStatus(SendMsgStatusEnum.SUCCESS.getCode());
//update-end-author:taoyan date:2022-7-8 for: 模板消息发送测试调用方法修改
} catch (Exception e) {
e.printStackTrace();
// 发送消息出现异常
sysMessage.setEsSendStatus(SendMsgStatusEnum.FAIL.getCode());
}
sysMessage.setEsSendNum(++sendNum);
// 发送结果回写到数据库
sysMessageService.updateById(sysMessage);
}
}
}

@ -0,0 +1,17 @@
package org.jeecg.modules.message.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.message.entity.SysMessage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @Description:
* @Author: jeecg-boot
* @Date: 2019-04-09
* @Version: V1.0
*/
public interface SysMessageMapper extends BaseMapper<SysMessage> {
}

@ -0,0 +1,24 @@
package org.jeecg.modules.message.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
import org.jeecg.modules.message.entity.SysMessageTemplate;
import java.util.List;
/**
* @Description:
* @Author: jeecg-boot
* @Date: 2019-04-09
* @Version: V1.0
*/
public interface SysMessageTemplateMapper extends BaseMapper<SysMessageTemplate> {
/**
* CODE
* @param code CODE
* @return List<SysMessageTemplate>
*/
@Select("SELECT * FROM SYS_SMS_TEMPLATE WHERE TEMPLATE_CODE = #{code}")
List<SysMessageTemplate> selectByCode(String code);
}

@ -0,0 +1,5 @@
<?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.jeecg.modules.message.mapper.SysMessageMapper">
</mapper>

@ -0,0 +1,5 @@
<?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.jeecg.modules.message.mapper.SysMessageTemplateMapper">
</mapper>

@ -0,0 +1,14 @@
package org.jeecg.modules.message.service;
import org.jeecg.common.system.base.service.JeecgService;
import org.jeecg.modules.message.entity.SysMessage;
/**
* @Description:
* @Author: jeecg-boot
* @Date: 2019-04-09
* @Version: V1.0
*/
public interface ISysMessageService extends JeecgService<SysMessage> {
}

@ -0,0 +1,22 @@
package org.jeecg.modules.message.service;
import java.util.List;
import org.jeecg.common.system.base.service.JeecgService;
import org.jeecg.modules.message.entity.SysMessageTemplate;
/**
* @Description:
* @Author: jeecg-boot
* @Date: 2019-04-09
* @Version: V1.0
*/
public interface ISysMessageTemplateService extends JeecgService<SysMessageTemplate> {
/**
* CODE
* @param code CODE
* @return
*/
List<SysMessageTemplate> selectByCode(String code);
}

@ -0,0 +1,18 @@
package org.jeecg.modules.message.service.impl;
import org.jeecg.common.system.base.service.impl.JeecgServiceImpl;
import org.jeecg.modules.message.entity.SysMessage;
import org.jeecg.modules.message.mapper.SysMessageMapper;
import org.jeecg.modules.message.service.ISysMessageService;
import org.springframework.stereotype.Service;
/**
* @Description:
* @Author: jeecg-boot
* @Date: 2019-04-09
* @Version: V1.0
*/
@Service
public class SysMessageServiceImpl extends JeecgServiceImpl<SysMessageMapper, SysMessage> implements ISysMessageService {
}

@ -0,0 +1,28 @@
package org.jeecg.modules.message.service.impl;
import org.jeecg.common.system.base.service.impl.JeecgServiceImpl;
import org.jeecg.modules.message.entity.SysMessageTemplate;
import org.jeecg.modules.message.mapper.SysMessageTemplateMapper;
import org.jeecg.modules.message.service.ISysMessageTemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Description:
* @Author: jeecg-boot
* @Date: 2019-04-09
* @Version: V1.0
*/
@Service
public class SysMessageTemplateServiceImpl extends JeecgServiceImpl<SysMessageTemplateMapper, SysMessageTemplate> implements ISysMessageTemplateService {
@Autowired
private SysMessageTemplateMapper sysMessageTemplateMapper;
@Override
public List<SysMessageTemplate> selectByCode(String code) {
return sysMessageTemplateMapper.selectByCode(code);
}
}

@ -0,0 +1,81 @@
package org.jeecg.modules.message.util;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.jeecg.modules.message.entity.SysMessage;
import org.jeecg.modules.message.entity.SysMessageTemplate;
import org.jeecg.modules.message.handle.enums.SendMsgStatusEnum;
import org.jeecg.modules.message.service.ISysMessageService;
import org.jeecg.modules.message.service.ISysMessageTemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
*
* @author: jeecg-boot
*/
@Component
public class PushMsgUtil {
@Autowired
private ISysMessageService sysMessageService;
@Autowired
private ISysMessageTemplateService sysMessageTemplateService;
@Autowired
private Configuration freemarkerConfig;
/**
* @param msgType 1 2 3
* @param templateCode
* @param map
* @param sentTo
*/
public boolean sendMessage(String msgType, String templateCode, Map<String, String> map, String sentTo) {
List<SysMessageTemplate> sysSmsTemplates = sysMessageTemplateService.selectByCode(templateCode);
SysMessage sysMessage = new SysMessage();
if (sysSmsTemplates.size() > 0) {
SysMessageTemplate sysSmsTemplate = sysSmsTemplates.get(0);
sysMessage.setEsType(msgType);
sysMessage.setEsReceiver(sentTo);
//模板标题
String title = sysSmsTemplate.getTemplateName();
//模板内容
String content = sysSmsTemplate.getTemplateContent();
StringWriter stringWriter = new StringWriter();
Template template = null;
try {
template = new Template("SysMessageTemplate", content, freemarkerConfig);
template.process(map, stringWriter);
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (TemplateException e) {
e.printStackTrace();
return false;
}
content = stringWriter.toString();
sysMessage.setEsTitle(title);
sysMessage.setEsContent(content);
sysMessage.setEsParam(JSONObject.toJSONString(map));
sysMessage.setEsSendTime(new Date());
sysMessage.setEsSendStatus(SendMsgStatusEnum.WAIT.getCode());
sysMessage.setEsSendNum(0);
if(sysMessageService.save(sysMessage)) {
return true;
}
}
return false;
}
}

@ -0,0 +1,40 @@
package org.jeecg.modules.message.websocket;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.constant.CommonSendStatus;
import org.jeecg.common.modules.redis.listener.JeecgRedisListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* (redis)
* redisredisws
* @author: jeecg-boot
*/
@Slf4j
@Component(WebSocket.REDIS_TOPIC_NAME)
public class SocketHandler implements JeecgRedisListener {
@Autowired
private WebSocket webSocket;
@Override
public void onMessage(BaseMap map) {
log.debug("【Redis发布订阅模式】redis Listener: {},参数:{}",WebSocket.REDIS_TOPIC_NAME, map.toString());
String userId = map.get("userId");
String message = map.get("message");
if (ObjectUtil.isNotEmpty(userId)) {
//pc端消息推送具体人
webSocket.pushMessage(userId, message);
//app端消息推送具体人
webSocket.pushMessage(userId+CommonSendStatus.APP_SESSION_SUFFIX, message);
} else {
//推送全部
webSocket.pushMessage(message);
}
}
}

@ -0,0 +1,186 @@
package org.jeecg.modules.message.websocket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.base.BaseMap;
import org.jeecg.common.constant.WebsocketConst;
import org.jeecg.common.modules.redis.client.JeecgRedisClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
/**
* @Author scott
* @Date 2019/11/29 9:41
* @Description: 访URL
*/
@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {
/**线程安全Map*/
private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();
/**
* Redis
*/
public static final String REDIS_TOPIC_NAME = "socketHandler";
//避免初次调用出现空指针的情况
private static JeecgRedisClient jeecgRedisClient;
@Autowired
private void setJeecgRedisClient(JeecgRedisClient jeecgRedisClient){
WebSocket.jeecgRedisClient = jeecgRedisClient;
}
//==========【websocket接受、推送消息等方法 —— 具体服务节点推送ws消息】========================================================================================
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId) {
try {
sessionPool.put(userId, session);
log.debug("【系统 WebSocket】有新的连接总数为:" + sessionPool.size());
} catch (Exception e) {
}
}
@OnClose
public void onClose(@PathParam("userId") String userId) {
try {
sessionPool.remove(userId);
log.debug("【系统 WebSocket】连接断开总数为:" + sessionPool.size());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* ws
*
* @param userId
* @param message
*/
public void pushMessage(String userId, String message) {
for (Map.Entry<String, Session> item : sessionPool.entrySet()) {
//userId key值= {用户id + "_"+ 登录token的md5串}
//TODO vue2未改key新规则暂时不影响逻辑
if (item.getKey().contains(userId)) {
Session session = item.getValue();
try {
//update-begin-author:taoyan date:20211012 for: websocket报错 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU
synchronized (session){
log.debug("【系统 WebSocket】推送单人消息:" + message);
session.getBasicRemote().sendText(message);
}
//update-end-author:taoyan date:20211012 for: websocket报错 https://gitee.com/jeecg/jeecg-boot/issues/I4C0MU
} catch (Exception e) {
log.error(e.getMessage(),e);
}
}
}
}
/**
* ws
*/
public void pushMessage(String message) {
try {
for (Map.Entry<String, Session> item : sessionPool.entrySet()) {
try {
item.getValue().getAsyncRemote().sendText(message);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
log.debug("【系统 WebSocket】群发消息:" + message);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
* ws
*/
@OnMessage
public void onMessage(String message, @PathParam(value = "userId") String userId) {
if(!"ping".equals(message) && !WebsocketConst.CMD_CHECK.equals(message)){
log.debug("【系统 WebSocket】收到客户端消息:" + message);
}else{
log.debug("【系统 WebSocket】收到客户端消息:" + message);
//update-begin---author:wangshuai---date:2024-05-07---for:【issues/1161】前端websocket因心跳导致监听不起作用---
this.sendMessage(userId, "ping");
//update-end---author:wangshuai---date:2024-05-07---for:【issues/1161】前端websocket因心跳导致监听不起作用---
}
// //------------------------------------------------------------------------------
// JSONObject obj = new JSONObject();
// //业务类型
// obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_CHECK);
// //消息内容
// obj.put(WebsocketConst.MSG_TXT, "心跳响应");
// this.pushMessage(userId, obj.toJSONString());
// //------------------------------------------------------------------------------
}
/**
*
*
* @param session
* @param t
*/
@OnError
public void onError(Session session, Throwable t) {
log.warn("【系统 WebSocket】消息出现错误");
t.printStackTrace();
}
//==========【系统 WebSocket接受、推送消息等方法 —— 具体服务节点推送ws消息】========================================================================================
//==========【采用redis发布订阅模式——推送消息】========================================================================================
/**
* redis
*
* @param message
*/
public void sendMessage(String message) {
//log.debug("【系统 WebSocket】广播消息:" + message);
BaseMap baseMap = new BaseMap();
baseMap.put("userId", "");
baseMap.put("message", message);
jeecgRedisClient.sendMessage(WebSocket.REDIS_TOPIC_NAME, baseMap);
}
/**
* redis
*
* @param userId
* @param message
*/
public void sendMessage(String userId, String message) {
BaseMap baseMap = new BaseMap();
baseMap.put("userId", userId);
baseMap.put("message", message);
jeecgRedisClient.sendMessage(WebSocket.REDIS_TOPIC_NAME, baseMap);
}
/**
* () redis
*
* @param userIds
* @param message
*/
public void sendMessage(String[] userIds, String message) {
for (String userId : userIds) {
sendMessage(userId, message);
}
}
//=======【采用redis发布订阅模式——推送消息】==========================================================================================
}

@ -0,0 +1,38 @@
package org.jeecg.modules.monitor.actuator;
import org.jeecg.modules.monitor.actuator.httptrace.CustomInMemoryHttpTraceRepository;
import org.springframework.boot.actuate.autoconfigure.trace.http.HttpTraceAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.trace.http.HttpTraceProperties;
import org.springframework.boot.actuate.trace.http.HttpTraceRepository;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*
*
* @Author: chenrui
* @Date: 2024/5/13 17:20
*/
@Configuration
@EnableConfigurationProperties(HttpTraceProperties.class)
@AutoConfigureBefore(HttpTraceAutoConfiguration.class)
public class CustomActuatorConfig {
/**
*
* @return
* @author chenrui
* @date 2024/5/14 14:52
*/
@Bean
@ConditionalOnProperty(prefix = "management.trace.http", name = "enabled", matchIfMissing = true)
@ConditionalOnMissingBean(HttpTraceRepository.class)
public CustomInMemoryHttpTraceRepository traceRepository() {
return new CustomInMemoryHttpTraceRepository();
}
}

@ -0,0 +1,44 @@
package org.jeecg.modules.monitor.actuator.httptrace;
import lombok.Getter;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.boot.actuate.trace.http.HttpTrace;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.List;
import static org.springframework.boot.actuate.endpoint.annotation.Selector.Match.ALL_REMAINING;
/**
* @Description: ENDPOINT: (),responseCode
* @Author: chenrui
* @Date: 2024/5/13 17:02
*/
@Component
@Endpoint(id = "jeecghttptrace")
public class CustomHttpTraceEndpoint{
private final CustomInMemoryHttpTraceRepository repository;
public CustomHttpTraceEndpoint(CustomInMemoryHttpTraceRepository repository) {
Assert.notNull(repository, "Repository must not be null");
this.repository = repository;
}
@ReadOperation
public HttpTraceDescriptor traces(@Selector(match = ALL_REMAINING) String query) {
return new CustomHttpTraceEndpoint.HttpTraceDescriptor(this.repository.findAll(query));
}
@Getter
public static final class HttpTraceDescriptor {
private final List<HttpTrace> traces;
private HttpTraceDescriptor(List<HttpTrace> traces) {
this.traces = traces;
}
}
}

@ -0,0 +1,94 @@
package org.jeecg.modules.monitor.actuator.httptrace;
import org.springframework.boot.actuate.trace.http.HttpTrace;
import org.springframework.boot.actuate.trace.http.InMemoryHttpTraceRepository;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @Description:
* @Author: chenrui
* @Date: 2024/5/13 17:02
*/
public class CustomInMemoryHttpTraceRepository extends InMemoryHttpTraceRepository {
@Override
public List<HttpTrace> findAll() {
return super.findAll();
}
public List<HttpTrace> findAll(String query) {
List<HttpTrace> allTrace = super.findAll();
if (null != allTrace && !allTrace.isEmpty()) {
Stream<HttpTrace> stream = allTrace.stream();
String[] params = query.split(",");
stream = filter(params, stream);
stream = sort(params, stream);
allTrace = stream.collect(Collectors.toList());
}
return allTrace;
}
private Stream<HttpTrace> sort(String[] params, Stream<HttpTrace> stream) {
if (params.length < 2) {
return stream;
}
String sortBy = params[1];
String order;
if (params.length > 2) {
order = params[2];
} else {
order = "desc";
}
return stream.sorted((o1, o2) -> {
int i = 0;
if("timeTaken".equalsIgnoreCase(sortBy)) {
i = o1.getTimeTaken().compareTo(o2.getTimeTaken());
}else if("timestamp".equalsIgnoreCase(sortBy)){
i = o1.getTimestamp().compareTo(o2.getTimestamp());
}
if("desc".equalsIgnoreCase(order)){
i *=-1;
}
return i;
});
}
private static Stream<HttpTrace> filter(String[] params, Stream<HttpTrace> stream) {
if (params.length == 0) {
return stream;
}
String statusQuery = params[0];
if (null != statusQuery && !statusQuery.isEmpty()) {
statusQuery = statusQuery.toLowerCase().trim();
switch (statusQuery) {
case "error":
stream = stream.filter(httpTrace -> {
int status = httpTrace.getResponse().getStatus();
return status >= 404 && status < 501;
});
break;
case "warn":
stream = stream.filter(httpTrace -> {
int status = httpTrace.getResponse().getStatus();
return status >= 201 && status < 404;
});
break;
case "success":
stream = stream.filter(httpTrace -> {
int status = httpTrace.getResponse().getStatus();
return status == 200;
});
break;
case "all":
default:
break;
}
return stream;
}
return stream;
}
}

@ -0,0 +1,56 @@
package org.jeecg.modules.monitor.controller;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.util.HashMap;
import java.util.Map;
/**
* @Description:
* @author: chenrui
*/
@Slf4j
@RestController
@RequestMapping("/sys/actuator/memory")
public class ActuatorMemoryController {
/**
*
* @return
*/
@GetMapping("/info")
public Result<?> getRedisInfo() {
Runtime runtime = Runtime.getRuntime();
Map<String,Number> result = new HashMap<>();
result.put("memory.runtime.total", runtime.totalMemory());
result.put("memory.runtime.used", runtime.freeMemory());
result.put("memory.runtime.max", runtime.totalMemory() - runtime.freeMemory());
result.put("memory.runtime.free", runtime.maxMemory() - runtime.totalMemory() + runtime.freeMemory());
result.put("memory.runtime.usage", NumberUtil.div(runtime.totalMemory() - runtime.freeMemory(), runtime.totalMemory()));
//update-begin---author:chenrui ---date:20240705 for[TV360X-1695]内存信息-立即更新 功能报错 #6635------------
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
if (operatingSystemMXBean instanceof com.sun.management.OperatingSystemMXBean) {
com.sun.management.OperatingSystemMXBean opBean = (com.sun.management.OperatingSystemMXBean) operatingSystemMXBean;
// JSONObject operatingSystemJson = JSONObject.parseObject(JSONObject.toJSONString(operatingSystemMXBean));
long totalPhysicalMemory = opBean.getTotalPhysicalMemorySize();
long freePhysicalMemory = opBean.getFreePhysicalMemorySize();
long usedPhysicalMemory = totalPhysicalMemory - freePhysicalMemory;
result.put("memory.physical.total", totalPhysicalMemory);
result.put("memory.physical.used", freePhysicalMemory);
result.put("memory.physical.free", usedPhysicalMemory);
result.put("memory.physical.usage", NumberUtil.div(usedPhysicalMemory, totalPhysicalMemory));
}
//update-end---author:chenrui ---date:20240705 for[TV360X-1695]内存信息-立即更新 功能报错 #6635------------
return Result.ok(result);
}
}

@ -0,0 +1,138 @@
package org.jeecg.modules.monitor.controller;
import com.alibaba.fastjson.JSONArray;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.monitor.domain.RedisInfo;
import org.jeecg.modules.monitor.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description: ActuatorRedisController
* @author: jeecg-boot
*/
@Slf4j
@RestController
@RequestMapping("/sys/actuator/redis")
public class ActuatorRedisController {
@Autowired
private RedisService redisService;
/**
* Redis
* @return
* @throws Exception
*/
@GetMapping("/info")
public Result<?> getRedisInfo() throws Exception {
List<RedisInfo> infoList = this.redisService.getRedisInfo();
//log.info(infoList.toString());
return Result.ok(infoList);
}
//update-begin---author:chenrui ---date:20240514 for[QQYUN-9247]系统监控功能优化------------
/**
* Redis()
* @return
* @throws Exception
* @author chenrui
* @date 2024/5/14 14:56
*/
@GetMapping(value = "/metrics/history")
public Result<?> getMetricsHistory() throws Exception {
Map<String,List<Map<String,Object>>> metricsHistory = this.redisService.getMetricsHistory();
return Result.OK(metricsHistory);
}
//update-end---author:chenrui ---date:20240514 for[QQYUN-9247]系统监控功能优化------------
@GetMapping("/keysSize")
public Map<String, Object> getKeysSize() throws Exception {
return redisService.getKeysSize();
}
/**
* redis key for
* @return
* @throws Exception
*/
@GetMapping("/keysSizeForReport")
public Map<String, JSONArray> getKeysSizeReport() throws Exception {
return redisService.getMapForReport("1");
}
/**
* redis for
*
* @return
* @throws Exception
*/
@GetMapping("/memoryForReport")
public Map<String, JSONArray> memoryForReport() throws Exception {
return redisService.getMapForReport("2");
}
/**
* redis for
* @return
* @throws Exception
*/
@GetMapping("/infoForReport")
public Map<String, JSONArray> infoForReport() throws Exception {
return redisService.getMapForReport("3");
}
@GetMapping("/memoryInfo")
public Map<String, Object> getMemoryInfo() throws Exception {
return redisService.getMemoryInfo();
}
//update-begin--Author:zhangweijian Date:20190425 for获取磁盘信息
/**
* @
* @param request
* @param response
* @return
*/
@GetMapping("/queryDiskInfo")
public Result<List<Map<String,Object>>> queryDiskInfo(HttpServletRequest request, HttpServletResponse response){
Result<List<Map<String,Object>>> res = new Result<>();
try {
// 当前文件系统类
FileSystemView fsv = FileSystemView.getFileSystemView();
// 列出所有windows 磁盘
File[] fs = File.listRoots();
log.info("查询磁盘信息:"+fs.length+"个");
List<Map<String,Object>> list = new ArrayList<>();
for (int i = 0; i < fs.length; i++) {
if(fs[i].getTotalSpace()==0) {
continue;
}
Map<String,Object> map = new HashMap(5);
map.put("name", fsv.getSystemDisplayName(fs[i]));
map.put("max", fs[i].getTotalSpace());
map.put("rest", fs[i].getFreeSpace());
map.put("restPPT", (fs[i].getTotalSpace()-fs[i].getFreeSpace())*100/fs[i].getTotalSpace());
list.add(map);
log.info(map.toString());
}
res.setResult(list);
res.success("查询成功");
} catch (Exception e) {
res.error500("查询失败"+e.getMessage());
}
return res;
}
//update-end--Author:zhangweijian Date:20190425 for获取磁盘信息
}

@ -0,0 +1,141 @@
package org.jeecg.modules.monitor.domain;
import java.util.HashMap;
import java.util.Map;
/**
* @Description: redis
* @author: jeecg-boot
*/
public class RedisInfo {
private static Map<String, String> map = new HashMap(5);
static {
map.put("redis_version", "Redis 服务器版本");
map.put("redis_git_sha1", "Git SHA1");
map.put("redis_git_dirty", "Git dirty flag");
map.put("os", "Redis 服务器的宿主操作系统");
map.put("arch_bits", " 架构32 或 64 位)");
map.put("multiplexing_api", "Redis 所使用的事件处理机制");
map.put("gcc_version", "编译 Redis 时所使用的 GCC 版本");
map.put("process_id", "服务器进程的 PID");
map.put("run_id", "Redis 服务器的随机标识符(用于 Sentinel 和集群)");
map.put("tcp_port", "TCP/IP 监听端口");
map.put("uptime_in_seconds", "自 Redis 服务器启动以来,经过的秒数");
map.put("uptime_in_days", "自 Redis 服务器启动以来,经过的天数");
map.put("lru_clock", " 以分钟为单位进行自增的时钟,用于 LRU 管理");
map.put("connected_clients", "已连接客户端的数量(不包括通过从属服务器连接的客户端)");
map.put("client_longest_output_list", "当前连接的客户端当中,最长的输出列表");
map.put("client_longest_input_buf", "当前连接的客户端当中,最大输入缓存");
map.put("blocked_clients", "正在等待阻塞命令BLPOP、BRPOP、BRPOPLPUSH的客户端的数量");
map.put("used_memory", "由 Redis 分配器分配的内存总量以字节byte为单位");
map.put("used_memory_human", "以人类可读的格式返回 Redis 分配的内存总量");
map.put("used_memory_rss", "从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小)。这个值和 top 、 ps 等命令的输出一致");
map.put("used_memory_peak", " Redis 的内存消耗峰值(以字节为单位)");
map.put("used_memory_peak_human", "以人类可读的格式返回 Redis 的内存消耗峰值");
map.put("used_memory_lua", "Lua 引擎所使用的内存大小(以字节为单位)");
map.put("mem_fragmentation_ratio", "sed_memory_rss 和 used_memory 之间的比率");
map.put("mem_allocator", "在编译时指定的, Redis 所使用的内存分配器。可以是 libc 、 jemalloc 或者 tcmalloc");
map.put("redis_build_id", "redis_build_id");
map.put("redis_mode", "运行模式单机standalone或者集群cluster");
map.put("atomicvar_api", "atomicvar_api");
map.put("hz", "redis内部调度进行关闭timeout的客户端删除过期key等等频率程序规定serverCron每秒运行10次。");
map.put("executable", "server脚本目录");
map.put("config_file", "配置文件目录");
map.put("client_biggest_input_buf", "当前连接的客户端当中最大输入缓存用client list命令观察qbuf和qbuf-free两个字段最大值");
map.put("used_memory_rss_human", "以人类可读的方式返回 Redis 已分配的内存总量");
map.put("used_memory_peak_perc", "内存使用率峰值");
map.put("total_system_memory", "系统总内存");
map.put("total_system_memory_human", "以人类可读的方式返回系统总内存");
map.put("used_memory_lua_human", "以人类可读的方式返回Lua 引擎所使用的内存大小");
map.put("maxmemory", "最大内存限制0表示无限制");
map.put("maxmemory_human", "以人类可读的方式返回最大限制内存");
map.put("maxmemory_policy", "超过内存限制后的处理策略");
map.put("loading", "服务器是否正在载入持久化文件");
map.put("rdb_changes_since_last_save", "离最近一次成功生成rdb文件写入命令的个数即有多少个写入命令没有持久化");
map.put("rdb_bgsave_in_progress", "服务器是否正在创建rdb文件");
map.put("rdb_last_save_time", "离最近一次成功创建rdb文件的时间戳。当前时间戳 - rdb_last_save_time=多少秒未成功生成rdb文件");
map.put("rdb_last_bgsave_status", "最近一次rdb持久化是否成功");
map.put("rdb_last_bgsave_time_sec", "最近一次成功生成rdb文件耗时秒数");
map.put("rdb_current_bgsave_time_sec", "如果服务器正在创建rdb文件那么这个域记录的就是当前的创建操作已经耗费的秒数");
map.put("aof_enabled", "是否开启了aof");
map.put("aof_rewrite_in_progress", "标识aof的rewrite操作是否在进行中");
map.put("aof_rewrite_scheduled", "rewrite任务计划当客户端发送bgrewriteaof指令如果当前rewrite子进程正在执行那么将客户端请求的bgrewriteaof变为计划任务待aof子进程结束后执行rewrite ");
map.put("aof_last_rewrite_time_sec", "最近一次aof rewrite耗费的时长");
map.put("aof_current_rewrite_time_sec", "如果rewrite操作正在进行则记录所使用的时间单位秒");
map.put("aof_last_bgrewrite_status", "上次bgrewrite aof操作的状态");
map.put("aof_last_write_status", "上次aof写入状态");
map.put("total_commands_processed", "redis处理的命令数");
map.put("total_connections_received", "新创建连接个数,如果新创建连接过多,过度地创建和销毁连接对性能有影响,说明短连接严重或连接池使用有问题,需调研代码的连接设置");
map.put("instantaneous_ops_per_sec", "redis当前的qpsredis内部较实时的每秒执行的命令数");
map.put("total_net_input_bytes", "redis网络入口流量字节数");
map.put("total_net_output_bytes", "redis网络出口流量字节数");
map.put("instantaneous_input_kbps", "redis网络入口kps");
map.put("instantaneous_output_kbps", "redis网络出口kps");
map.put("rejected_connections", "拒绝的连接个数redis连接个数达到maxclients限制拒绝新连接的个数");
map.put("sync_full", "主从完全同步成功次数");
map.put("sync_partial_ok", "主从部分同步成功次数");
map.put("sync_partial_err", "主从部分同步失败次数");
map.put("expired_keys", "运行以来过期的key的数量");
map.put("evicted_keys", "运行以来剔除(超过了maxmemory后)的key的数量");
map.put("keyspace_hits", "命中次数");
map.put("keyspace_misses", "没命中次数");
map.put("pubsub_channels", "当前使用中的频道数量");
map.put("pubsub_patterns", "当前使用的模式的数量");
map.put("latest_fork_usec", "最近一次fork操作阻塞redis进程的耗时数单位微秒");
map.put("role", "实例的角色是master or slave");
map.put("connected_slaves", "连接的slave实例个数");
map.put("master_repl_offset", "主从同步偏移量,此值如果和上面的offset相同说明主从一致没延迟");
map.put("repl_backlog_active", "复制积压缓冲区是否开启");
map.put("repl_backlog_size", "复制积压缓冲大小");
map.put("repl_backlog_first_byte_offset", "复制缓冲区里偏移量的大小");
map.put("repl_backlog_histlen", "此值等于 master_repl_offset - repl_backlog_first_byte_offset,该值不会超过repl_backlog_size的大小");
map.put("used_cpu_sys", "将所有redis主进程在核心态所占用的CPU时求和累计起来");
map.put("used_cpu_user", "将所有redis主进程在用户态所占用的CPU时求和累计起来");
map.put("used_cpu_sys_children", "将后台进程在核心态所占用的CPU时求和累计起来");
map.put("used_cpu_user_children", "将后台进程在用户态所占用的CPU时求和累计起来");
map.put("cluster_enabled", "实例是否启用集群模式");
map.put("db0", "db0的key的数量,以及带有生存期的key的数,平均存活时间");
}
private String key;
private String value;
private String description;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
this.description = map.get(this.key);
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "RedisInfo{" + "key='" + key + '\'' + ", value='" + value + '\'' + ", desctiption='" + description + '\'' + '}';
}
}

@ -0,0 +1,14 @@
package org.jeecg.modules.monitor.exception;
/**
* Redis
* @author: jeecg-boot
*/
public class RedisConnectException extends Exception {
private static final long serialVersionUID = 1639374111871115063L;
public RedisConnectException(String message) {
super(message);
}
}

@ -0,0 +1,55 @@
package org.jeecg.modules.monitor.service;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.alibaba.fastjson.JSONArray;
import org.jeecg.modules.monitor.domain.RedisInfo;
import org.jeecg.modules.monitor.exception.RedisConnectException;
/**
* @Description: redisservice
* @author: jeecg-boot
*/
public interface RedisService {
/**
* redis
*
* @return List
* @throws RedisConnectException
*/
List<RedisInfo> getRedisInfo() throws RedisConnectException;
/**
* redis key
*
* @return Map
* @throws RedisConnectException
*/
Map<String, Object> getKeysSize() throws RedisConnectException;
/**
* redis
*
* @return Map
* @throws RedisConnectException
*/
Map<String, Object> getMemoryInfo() throws RedisConnectException;
/**
* redis
* @param type
* @return Map
* @throws RedisConnectException
*/
Map<String, JSONArray> getMapForReport(String type) throws RedisConnectException ;
/**
*
* @return
* @author chenrui
* @date 2024/5/14 14:57
*/
Map<String, List<Map<String, Object>>> getMetricsHistory();
}

@ -0,0 +1,29 @@
package org.jeecg.modules.monitor.service.impl;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
/**
* :
*
* @author:
* @email: 503378406@qq.com
* @date: 2019-06-29
*/
@Component
public class MailHealthIndicator implements HealthIndicator {
@Override public Health health() {
int errorCode = check();
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode) .build();
}
return Health.up().build();
}
int check(){
//可以实现自定义的数据库检测逻辑
return 0;
}
}

@ -0,0 +1,174 @@
package org.jeecg.modules.monitor.service.impl;
import java.util.*;
import javax.annotation.Resource;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.monitor.domain.RedisInfo;
import org.jeecg.modules.monitor.exception.RedisConnectException;
import org.jeecg.modules.monitor.service.RedisService;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
/**
* Redis
*
* @Author MrBird
*/
@Service("redisService")
@Slf4j
public class RedisServiceImpl implements RedisService {
@Resource
private RedisConnectionFactory redisConnectionFactory;
/**
* redis
*/
private static final String REDIS_MESSAGE = "3";
/**
* redis
*/
private static final Map<String,List<Map<String, Object>>> REDIS_METRICS = new HashMap<>(2);
/**
* Redis
*/
@Override
public List<RedisInfo> getRedisInfo() throws RedisConnectException {
Properties info = redisConnectionFactory.getConnection().info();
List<RedisInfo> infoList = new ArrayList<>();
RedisInfo redisInfo = null;
for (Map.Entry<Object, Object> entry : info.entrySet()) {
redisInfo = new RedisInfo();
redisInfo.setKey(oConvertUtils.getString(entry.getKey()));
redisInfo.setValue(oConvertUtils.getString(entry.getValue()));
infoList.add(redisInfo);
}
return infoList;
}
@Override
public Map<String, Object> getKeysSize() throws RedisConnectException {
Long dbSize = redisConnectionFactory.getConnection().dbSize();
Map<String, Object> map = new HashMap(5);
map.put("create_time", System.currentTimeMillis());
map.put("dbSize", dbSize);
log.debug("--getKeysSize--: " + map.toString());
return map;
}
@Override
public Map<String, Object> getMemoryInfo() throws RedisConnectException {
Map<String, Object> map = null;
Properties info = redisConnectionFactory.getConnection().info();
for (Map.Entry<Object, Object> entry : info.entrySet()) {
String key = oConvertUtils.getString(entry.getKey());
if ("used_memory".equals(key)) {
map = new HashMap(5);
map.put("used_memory", entry.getValue());
map.put("create_time", System.currentTimeMillis());
}
}
log.debug("--getMemoryInfo--: " + map.toString());
return map;
}
/**
* redisfor
* @param type 1redis key 2 3redis
* @return
* @throws RedisConnectException
*/
@Override
public Map<String, JSONArray> getMapForReport(String type) throws RedisConnectException {
Map<String,JSONArray> mapJson=new HashMap(5);
JSONArray json = new JSONArray();
if(REDIS_MESSAGE.equals(type)){
List<RedisInfo> redisInfo = getRedisInfo();
for(RedisInfo info:redisInfo){
Map<String, Object> map= Maps.newHashMap();
BeanMap beanMap = BeanMap.create(info);
for (Object key : beanMap.keySet()) {
map.put(key+"", beanMap.get(key));
}
json.add(map);
}
mapJson.put("data",json);
return mapJson;
}
int length = 5;
for(int i = 0; i < length; i++){
JSONObject jo = new JSONObject();
Map<String, Object> map;
if("1".equals(type)){
map= getKeysSize();
jo.put("value",map.get("dbSize"));
}else{
map = getMemoryInfo();
Integer usedMemory = Integer.valueOf(map.get("used_memory").toString());
jo.put("value",usedMemory/1000);
}
String createTime = DateUtil.formatTime(DateUtil.date((Long) map.get("create_time")-(4-i)*1000));
jo.put("name",createTime);
json.add(jo);
}
mapJson.put("data",json);
return mapJson;
}
//update-begin---author:chenrui ---date:20240514 for[QQYUN-9247]系统监控功能优化------------
/**
*
* @return
* @author chenrui
* @date 2024/5/14 14:57
*/
@Override
public Map<String, List<Map<String, Object>>> getMetricsHistory() {
return REDIS_METRICS;
}
/**
* redis <br/>
* 60s,,keysize
* @throws RedisConnectException
* @author chenrui
* @date 2024/5/14 14:09
*/
@Scheduled(fixedRate = 60000)
public void recordCustomMetric() throws RedisConnectException {
List<Map<String, Object>> list= new ArrayList<>();
if(REDIS_METRICS.containsKey("dbSize")){
list = REDIS_METRICS.get("dbSize");
}else{
REDIS_METRICS.put("dbSize",list);
}
if(list.size()>60){
list.remove(0);
}
list.add(getKeysSize());
list= new ArrayList<>();
if(REDIS_METRICS.containsKey("memory")){
list = REDIS_METRICS.get("memory");
}else{
REDIS_METRICS.put("memory",list);
}
if(list.size()>60){
list.remove(0);
}
list.add(getMemoryInfo());
}
//update-end---author:chenrui ---date:20240514 for[QQYUN-9247]系统监控功能优化------------
}

@ -0,0 +1,46 @@
//package org.jeecg.modules.ngalain.aop;
//
//import javax.servlet.http.HttpServletRequest;
//
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.annotation.Around;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.annotation.Pointcut;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.web.context.request.RequestAttributes;
//import org.springframework.web.context.request.RequestContextHolder;
//import org.springframework.web.context.request.ServletRequestAttributes;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;;
//
//
//// 暂时注释掉,提高系统性能
////@Aspect //定义一个切面
////@Configuration
//public class LogRecordAspect {
//private static final Logger logger = LoggerFactory.getLogger(LogRecordAspect.class);
//
// // 定义切点Pointcut
// @Pointcut("execution(public * org.jeecg.modules.*.*.*Controller.*(..))")
// public void excudeService() {
// }
//
// @Around("excudeService()")
// public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
// RequestAttributes ra = RequestContextHolder.getRequestAttributes();
// ServletRequestAttributes sra = (ServletRequestAttributes) ra;
// HttpServletRequest request = sra.getRequest();
//
// String url = request.getRequestURL().toString();
// String method = request.getMethod();
// String uri = request.getRequestURI();
// String queryString = request.getQueryString();
// logger.info("请求开始, 各个参数, url: {}, method: {}, uri: {}, params: {}", url, method, uri, queryString);
//
// // result的值就是被拦截方法的返回值
// Object result = pjp.proceed();
//
// logger.info("请求结束controller的返回值是 " + result);
// return result;
// }
//}

@ -0,0 +1,86 @@
//package org.jeecg.modules.ngalain.controller;
//
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Map;
//
//import javax.servlet.http.HttpServletRequest;
//
//import org.apache.shiro.SecurityUtils;
//import org.jeecg.common.api.vo.Result;
//import org.jeecg.common.system.vo.DictModel;
//import org.jeecg.common.system.vo.LoginUser;
//import org.jeecg.modules.ngalain.service.NgAlainService;
//import org.jeecg.modules.system.service.ISysDictService;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.web.bind.annotation.PathVariable;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RequestMethod;
//import org.springframework.web.bind.annotation.ResponseBody;
//import org.springframework.web.bind.annotation.RestController;
//
//import com.alibaba.fastjson.JSONObject;
//
//import lombok.extern.slf4j.Slf4j;
//
//@Slf4j
//@RestController
//@RequestMapping("/sys/ng-alain")
//public class NgAlainController {
// @Autowired
// private NgAlainService ngAlainService;
// @Autowired
// private ISysDictService sysDictService;
//
// @RequestMapping(value = "/getAppData")
// @ResponseBody
// public JSONObject getAppData(HttpServletRequest request) throws Exception {
// String token=request.getHeader("X-Access-Token");
// JSONObject j = new JSONObject();
// LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
// JSONObject userObjcet = new JSONObject();
// userObjcet.put("name", user.getUsername());
// userObjcet.put("avatar", user.getAvatar());
// userObjcet.put("email", user.getEmail());
// userObjcet.put("token", token);
// j.put("user", userObjcet);
// j.put("menu",ngAlainService.getMenu(user.getUsername()));
// JSONObject app = new JSONObject();
// app.put("name", "jeecg-boot-angular");
// app.put("description", "jeecg+ng-alain整合版本");
// j.put("app", app);
// return j;
// }
//
// @RequestMapping(value = "/getDictItems/{dictCode}", method = RequestMethod.GET)
// public Object getDictItems(@PathVariable String dictCode) {
// log.info(" dictCode : "+ dictCode);
// Result<List<DictModel>> result = new Result<List<DictModel>>();
// List<DictModel> ls = null;
// try {
// ls = sysDictService.queryDictItemsByCode(dictCode);
// result.setSuccess(true);
// result.setResult(ls);
// } catch (Exception e) {
// log.error(e.getMessage(),e);
// result.error500("操作失败");
// return result;
// }
// List<JSONObject> dictlist=new ArrayList<>();
// for (DictModel l : ls) {
// JSONObject dict=new JSONObject();
// try {
// dict.put("value",Integer.parseInt(l.getValue()));
// } catch (NumberFormatException e) {
// dict.put("value",l.getValue());
// }
// dict.put("label",l.getText());
// dictlist.add(dict);
// }
// return dictlist;
// }
// @RequestMapping(value = "/getDictItemsByTable/{table}/{key}/{value}", method = RequestMethod.GET)
// public Object getDictItemsByTable(@PathVariable String table,@PathVariable String key,@PathVariable String value) {
// return this.ngAlainService.getDictByTable(table,key,value);
// }
//}

@ -0,0 +1,37 @@
//package org.jeecg.modules.ngalain.service;
//
//import com.alibaba.fastjson.JSONArray;
//
//import java.util.List;
//import java.util.Map;
//
///**
// * @Description: NgAlainService接口
// * @author: jeecg-boot
// */
//public interface NgAlainService {
// /**
// * 菜单
// * @param id
// * @return JSONArray
// * @throws Exception
// */
// public JSONArray getMenu(String id) throws Exception;
//
// /**
// * jeecg菜单
// * @param id
// * @return JSONArray
// * @throws Exception
// */
// public JSONArray getJeecgMenu(String id) throws Exception;
//
// /**
// * 获取字典值
// * @param table
// * @param key
// * @param value
// * @return List<Map<String, String>>
// */
// public List<Map<String, String>> getDictByTable(String table, String key, String value);
//}

@ -0,0 +1,187 @@
//package org.jeecg.modules.ngalain.service.impl;
//
//import com.alibaba.fastjson.JSONArray;
//import com.alibaba.fastjson.JSONObject;
//import org.jeecg.common.constant.CommonConstant;
//import org.jeecg.common.constant.SymbolConstant;
//import org.jeecg.common.util.oConvertUtils;
//import org.jeecg.modules.ngalain.service.NgAlainService;
//import org.jeecg.modules.system.entity.SysPermission;
//import org.jeecg.modules.system.mapper.SysDictMapper;
//import org.jeecg.modules.system.service.ISysPermissionService;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//
//import java.util.Base64;
//import java.util.List;
//import java.util.Map;
//
///**
// * @Description: NgAlainServiceImpl 实现类
// * @author: jeecg-boot
// */
//@Service("ngAlainService")
//public class NgAlainServiceImpl implements NgAlainService {
// @Autowired
// private ISysPermissionService sysPermissionService;
// @Autowired
// private SysDictMapper mapper;
// @Override
// public JSONArray getMenu(String id) throws Exception {
// return getJeecgMenu(id);
// }
// @Override
// public JSONArray getJeecgMenu(String id) throws Exception {
// List<SysPermission> metaList = sysPermissionService.queryByUser(id);
// JSONArray jsonArray = new JSONArray();
// getPermissionJsonArray(jsonArray, metaList, null);
// JSONArray menulist= parseNgAlain(jsonArray);
// JSONObject jeecgMenu = new JSONObject();
// jeecgMenu.put("text", "jeecg菜单");
// jeecgMenu.put("group",true);
// jeecgMenu.put("children", menulist);
// JSONArray jeecgMenuList=new JSONArray();
// jeecgMenuList.add(jeecgMenu);
// return jeecgMenuList;
// }
//
// @Override
// public List<Map<String, String>> getDictByTable(String table, String key, String value) {
// return this.mapper.getDictByTableNgAlain(table,key,value);
// }
//
// private JSONArray parseNgAlain(JSONArray jsonArray) {
// JSONArray menulist=new JSONArray();
// for (Object object : jsonArray) {
// JSONObject jsonObject= (JSONObject) object;
// String path= (String) jsonObject.get("path");
// JSONObject meta= (JSONObject) jsonObject.get("meta");
// JSONObject menu=new JSONObject();
// menu.put("text",meta.get("title"));
// menu.put("reuse",true);
// if (jsonObject.get("children")!=null){
// JSONArray child= parseNgAlain((JSONArray) jsonObject.get("children"));
// menu.put("children",child);
// JSONObject icon=new JSONObject();
// icon.put("type", "icon");
// icon.put("value", meta.get("icon"));
// menu.put("icon",icon);
// }else {
// menu.put("link",path);
// }
// menulist.add(menu);
// }
// return menulist;
// }
//
// /**
// * 获取菜单JSON数组
// * @param jsonArray
// * @param metaList
// * @param parentJson
// */
// private void getPermissionJsonArray(JSONArray jsonArray,List<SysPermission> metaList,JSONObject parentJson) {
// for (SysPermission permission : metaList) {
// if(permission.getMenuType()==null) {
// continue;
// }
// String tempPid = permission.getParentId();
// JSONObject json = getPermissionJsonObject(permission);
// if(parentJson==null && oConvertUtils.isEmpty(tempPid)) {
// jsonArray.add(json);
// if(!permission.isLeaf()) {
// getPermissionJsonArray(jsonArray, metaList, json);
// }
// }else if(parentJson!=null && oConvertUtils.isNotEmpty(tempPid) && tempPid.equals(parentJson.getString("id"))){
// if(permission.getMenuType()==0) {
// JSONObject metaJson = parentJson.getJSONObject("meta");
// if(metaJson.containsKey("permissionList")) {
// metaJson.getJSONArray("permissionList").add(json);
// }else {
// JSONArray permissionList = new JSONArray();
// permissionList.add(json);
// metaJson.put("permissionList", permissionList);
// }
//
// }else if(permission.getMenuType()==1) {
// if(parentJson.containsKey("children")) {
// parentJson.getJSONArray("children").add(json);
// }else {
// JSONArray children = new JSONArray();
// children.add(json);
// parentJson.put("children", children);
// }
//
// if(!permission.isLeaf()) {
// getPermissionJsonArray(jsonArray, metaList, json);
// }
// }
// }
//
//
// }
// }
// private JSONObject getPermissionJsonObject(SysPermission permission) {
// JSONObject json = new JSONObject();
// //类型(0一级菜单 1子菜单 2按钮)
// if(CommonConstant.MENU_TYPE_2.equals(permission.getMenuType())) {
// json.put("action", permission.getPerms());
// json.put("describe", permission.getName());
// }else if(CommonConstant.MENU_TYPE_0.equals(permission.getMenuType()) || CommonConstant.MENU_TYPE_1.equals(permission.getMenuType())) {
// json.put("id", permission.getId());
// boolean flag = permission.getUrl()!=null&&(permission.getUrl().startsWith(CommonConstant.HTTP_PROTOCOL)||permission.getUrl().startsWith(CommonConstant.HTTPS_PROTOCOL));
// if(flag) {
// String url= new String(Base64.getUrlEncoder().encode(permission.getUrl().getBytes()));
// json.put("path", "/sys/link/" +url.replaceAll("=",""));
// }else {
// json.put("path", permission.getUrl());
// }
//
// //重要规则路由name (通过URL生成路由name,路由name供前端开发页面跳转使用)
// json.put("name", urlToRouteName(permission.getUrl()));
//
// //是否隐藏路由,默认都是显示的
// if(permission.isHidden()) {
// json.put("hidden",true);
// }
// //聚合路由
// if(permission.isAlwaysShow()) {
// json.put("alwaysShow",true);
// }
// json.put("component", permission.getComponent());
// JSONObject meta = new JSONObject();
// meta.put("title", permission.getName());
// if(oConvertUtils.isEmpty(permission.getParentId())) {
// //一级菜单跳转地址
// json.put("redirect",permission.getRedirect());
// meta.put("icon", oConvertUtils.getString(permission.getIcon(), ""));
// }else {
// meta.put("icon", oConvertUtils.getString(permission.getIcon(), ""));
// }
// if(flag) {
// meta.put("url", permission.getUrl());
// }
// json.put("meta", meta);
// }
//
// return json;
// }
// /**
// * 通过URL生成路由name去掉URL前缀斜杠替换内容中的斜杠/’为-
// * 举例: URL = /isystem/role
// * RouteName = isystem-role
// * @return
// */
// private String urlToRouteName(String url) {
// if(oConvertUtils.isNotEmpty(url)) {
// if(url.startsWith(SymbolConstant.SINGLE_SLASH)) {
// url = url.substring(1);
// }
// url = url.replace("/", "-");
// return url;
// }else {
// return null;
// }
// }
//}

@ -0,0 +1,112 @@
package org.jeecg.modules.openapi.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.openapi.entity.OpenApiAuth;
import org.jeecg.modules.openapi.generator.AKSKGenerator;
import org.jeecg.modules.openapi.service.OpenApiAuthService;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
/**
* @date 2024/12/10 9:54
*/
@RestController
@RequestMapping("/openapi/auth")
public class OpenApiAuthController extends JeecgController<OpenApiAuth, OpenApiAuthService> {
/**
*
*
* @param openApiAuth
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@GetMapping(value = "/list")
public Result<?> queryPageList(OpenApiAuth openApiAuth, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
QueryWrapper<OpenApiAuth> queryWrapper = QueryGenerator.initQueryWrapper(openApiAuth, req.getParameterMap());
Page<OpenApiAuth> page = new Page<>(pageNo, pageSize);
IPage<OpenApiAuth> pageList = service.page(page, queryWrapper);
return Result.ok(pageList);
}
/**
*
*
* @param openApiAuth
* @return
*/
@PostMapping(value = "/add")
public Result<?> add(@RequestBody OpenApiAuth openApiAuth) {
service.save(openApiAuth);
return Result.ok("添加成功!");
}
/**
*
*
* @param openApiAuth
* @return
*/
@PutMapping(value = "/edit")
public Result<?> edit(@RequestBody OpenApiAuth openApiAuth) {
service.updateById(openApiAuth);
return Result.ok("修改成功!");
}
/**
* id
*
* @param id
* @return
*/
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
service.removeById(id);
return Result.ok("删除成功!");
}
/**
*
*
* @param ids
* @return
*/
@DeleteMapping(value = "/deleteBatch")
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.service.removeByIds(Arrays.asList(ids.split(",")));
return Result.ok("批量删除成功!");
}
/**
* id
*
* @param id
* @return
*/
@GetMapping(value = "/queryById")
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
OpenApiAuth openApiAuth = service.getById(id);
return Result.ok(openApiAuth);
}
/**
* AKSK
* @return
*/
@GetMapping("genAKSK")
public Result<String[]> genAKSK() {
return Result.ok(AKSKGenerator.genAKSKPair());
}
}

@ -0,0 +1,392 @@
package org.jeecg.modules.openapi.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.classmate.TypeResolver;
import com.google.common.collect.Lists;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.modules.openapi.entity.OpenApi;
import org.jeecg.modules.openapi.entity.OpenApiAuth;
import org.jeecg.modules.openapi.entity.OpenApiHeader;
import org.jeecg.modules.openapi.entity.OpenApiParam;
import org.jeecg.modules.openapi.generator.PathGenerator;
import org.jeecg.modules.openapi.service.OpenApiAuthService;
import org.jeecg.modules.openapi.service.OpenApiHeaderService;
import org.jeecg.modules.openapi.service.OpenApiParamService;
import org.jeecg.modules.openapi.service.OpenApiService;
import org.jeecg.modules.openapi.swagger.*;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import springfox.documentation.spring.web.DocumentationCache;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
/**
* @date 2024/12/10 9:11
*/
@RestController
@RequestMapping("/openapi")
public class OpenApiController extends JeecgController<OpenApi, OpenApiService> {
@Autowired
private RestTemplate restTemplate;
@Autowired
private OpenApiParamService openApiParamService;
@Autowired
private OpenApiHeaderService openApiHeaderService;
@Autowired
private DocumentationCache documentationCache;
@Autowired
private TypeResolver typeResolver;
@Autowired
private ISysUserService sysUserService;
@Autowired
private OpenApiAuthService openApiAuthService;
/**
*
*
* @param openApi
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@GetMapping(value = "/list")
public Result<?> queryPageList(OpenApi openApi, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
QueryWrapper<OpenApi> queryWrapper = QueryGenerator.initQueryWrapper(openApi, req.getParameterMap());
Page<OpenApi> page = new Page<>(pageNo, pageSize);
IPage<OpenApi> pageList = service.page(page, queryWrapper);
for (OpenApi api : pageList.getRecords()) {
api.setParams(openApiParamService.findByApiId(api.getId()));
api.setHeaders(openApiHeaderService.findByApiId(api.getId()));
}
return Result.ok(pageList);
}
/**
*
*
* @param openApi
* @return
*/
@PostMapping(value = "/add")
public Result<?> add(@RequestBody OpenApi openApi) {
if (service.save(openApi)) {
if (!CollectionUtils.isEmpty(openApi.getHeaders())) {
openApiHeaderService.saveBatch(openApi.getHeaders());
}
if (!CollectionUtils.isEmpty(openApi.getParams())) {
openApiParamService.saveBatch(openApi.getParams());
}
}
return Result.ok("添加成功!");
}
/**
*
*
* @param openApi
* @return
*/
@PutMapping(value = "/edit")
public Result<?> edit(@RequestBody OpenApi openApi) {
if (service.updateById(openApi)) {
openApiHeaderService.deleteByApiId(openApi.getId());
openApiParamService.deleteByApiId(openApi.getId());
if (!CollectionUtils.isEmpty(openApi.getHeaders())) {
openApiHeaderService.saveBatch(openApi.getHeaders());
}
if (!CollectionUtils.isEmpty(openApi.getParams())) {
openApiParamService.saveBatch(openApi.getParams());
}
}
return Result.ok("修改成功!");
}
/**
* id
*
* @param id
* @return
*/
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
service.removeById(id);
return Result.ok("删除成功!");
}
/**
*
*
* @param ids
* @return
*/
@DeleteMapping(value = "/deleteBatch")
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.service.removeByIds(Arrays.asList(ids.split(",")));
return Result.ok("批量删除成功!");
}
/**
* id
*
* @param id
* @return
*/
@GetMapping(value = "/queryById")
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
OpenApi OpenApi = service.getById(id);
return Result.ok(OpenApi);
}
/**
*
* @param path
* @return
*/
@RequestMapping(value = "/call/{path}", method = {RequestMethod.GET,RequestMethod.POST})
public Result<?> call(@PathVariable String path, @RequestBody(required = false) String json, HttpServletRequest request) {
OpenApi openApi = service.findByPath(path);
if (Objects.isNull(openApi)) {
Map<String, Object> result = new HashMap<>();
result.put("code", 404);
result.put("data", null);
return Result.error("失败", result);
}
List<OpenApiHeader> headers = openApiHeaderService.findByApiId(openApi.getId());
String url = openApi.getOriginUrl();
String method = openApi.getRequestMethod();
HttpHeaders httpHeaders = new HttpHeaders();
for (OpenApiHeader header : headers) {
httpHeaders.put(header.getHeaderKey(), Lists.newArrayList(request.getHeader(header.getHeaderKey())));
}
String appkey = request.getHeader("appkey");
OpenApiAuth openApiAuth = openApiAuthService.getByAppkey(appkey);
SysUser systemUser = sysUserService.getById(openApiAuth.getSystemUserId());
String token = JwtUtil.sign(systemUser.getUsername(), systemUser.getPassword());
httpHeaders.put("X-Access-Token", Lists.newArrayList(token));
HttpEntity<String> httpEntity = new HttpEntity<>(json, httpHeaders);
return restTemplate.exchange(url, HttpMethod.resolve(method), httpEntity, Result.class, request.getParameterMap()).getBody();
}
@GetMapping("/json")
public SwaggerModel swaggerModel() {
SwaggerModel swaggerModel = new SwaggerModel();
swaggerModel.setSwagger("2.0");
swaggerModel.setInfo(swaggerInfo());
swaggerModel.setHost("jeecg.com");
swaggerModel.setBasePath("/jeecg-boot");
swaggerModel.setSchemes(Lists.newArrayList("http", "https"));
SwaggerTag swaggerTag = new SwaggerTag();
swaggerTag.setName("openapi");
swaggerModel.setTags(Lists.newArrayList(swaggerTag));
pathsAndDefinitions(swaggerModel);
return swaggerModel;
}
private void pathsAndDefinitions(SwaggerModel swaggerModel) {
Map<String, Map<String, SwaggerOperation>> paths = new HashMap<>();
Map<String, SwaggerDefinition> definitions = new HashMap<>();
List<OpenApi> openapis = service.list();
for (OpenApi openApi : openapis) {
Map<String, SwaggerOperation> operations = new HashMap<>();
SwaggerOperation operation = new SwaggerOperation();
operation.setTags(Lists.newArrayList("openapi"));
operation.setSummary(openApi.getName());
operation.setDescription(openApi.getName());
operation.setOperationId(openApi.getRequestUrl()+"Using"+openApi.getRequestMethod());
operation.setProduces(Lists.newArrayList("application/json"));
parameters(operation, openApi);
// body入参
if (StringUtils.hasText(openApi.getBody())) {
SwaggerDefinition definition = new SwaggerDefinition();
definition.setType("object");
Map<String, SwaggerDefinitionProperties> definitionProperties = new HashMap<>();
definition.setProperties(definitionProperties);
JSONObject jsonObject = JSONObject.parseObject(openApi.getBody());
for (Map.Entry<String, Object> properties : jsonObject.entrySet()) {
SwaggerDefinitionProperties swaggerDefinitionProperties = new SwaggerDefinitionProperties();
swaggerDefinitionProperties.setType("string");
swaggerDefinitionProperties.setDescription(properties.getValue()+"");
definitionProperties.put(properties.getKey(), swaggerDefinitionProperties);
}
// body的definition构建完成
definitions.put(openApi.getRequestUrl()+"Using"+openApi.getRequestMethod()+"body", definition);
SwaggerOperationParameter bodyParameter = new SwaggerOperationParameter();
bodyParameter.setDescription(openApi.getName() + " body");
bodyParameter.setIn("body");
bodyParameter.setName(openApi.getName() + " body");
bodyParameter.setRequired(true);
Map<String, String> bodySchema = new HashMap<>();
bodySchema.put("$ref", "#/definitions/" + openApi.getRequestUrl()+"Using"+openApi.getRequestMethod()+"body");
bodyParameter.setSchema(bodySchema);
// 构建参数构建完成
operation.getParameters().add(bodyParameter);
}
// 响应
Map<String, SwaggerOperationResponse> responses = new HashMap<>();
SwaggerOperationResponse resp200 = new SwaggerOperationResponse();
resp200.setDescription("OK");
Map<String, String> respSchema = new HashMap<>();
respSchema.put("$ref", "#/definitions/OpenApiResult");
resp200.setSchema(respSchema);
responses.put("200", resp200);
Map<String, String> emptySchema = new HashMap<>();
SwaggerOperationResponse resp201 = new SwaggerOperationResponse();
resp201.setDescription("Created");
resp201.setSchema(emptySchema);
responses.put("201", resp201);
SwaggerOperationResponse resp401 = new SwaggerOperationResponse();
resp401.setDescription("Unauthorized");
resp401.setSchema(emptySchema);
responses.put("401", resp401);
SwaggerOperationResponse resp403 = new SwaggerOperationResponse();
resp403.setDescription("Forbidden");
resp403.setSchema(emptySchema);
responses.put("403", resp403);
SwaggerOperationResponse resp404 = new SwaggerOperationResponse();
resp404.setDescription("Not Found");
resp404.setSchema(emptySchema);
responses.put("404", resp404);
// 构建响应definition
SwaggerDefinition respDefinition = new SwaggerDefinition();
respDefinition.setType("object");
Map<String, SwaggerDefinitionProperties> definitionProperties = new HashMap<>();
respDefinition.setProperties(definitionProperties);
SwaggerDefinitionProperties codeProperties = new SwaggerDefinitionProperties();
codeProperties.setType("integer");
codeProperties.setDescription("返回代码");
definitionProperties.put("code", codeProperties);
SwaggerDefinitionProperties messageProperties = new SwaggerDefinitionProperties();
messageProperties.setType("string");
messageProperties.setDescription("返回处理消息");
definitionProperties.put("message", messageProperties);
SwaggerDefinitionProperties resultProperties = new SwaggerDefinitionProperties();
resultProperties.setType("object");
resultProperties.setDescription("返回数据对象");
definitionProperties.put("result", resultProperties);
SwaggerDefinitionProperties successProperties = new SwaggerDefinitionProperties();
successProperties.setType("boolean");
successProperties.setDescription("成功标志");
definitionProperties.put("success", successProperties);
SwaggerDefinitionProperties timestampProperties = new SwaggerDefinitionProperties();
timestampProperties.setType("integer");
timestampProperties.setDescription("时间戳");
definitionProperties.put("timestamp", timestampProperties);
definitions.put("OpenApiResult", respDefinition);
operation.setResponses(responses);
operations.put(openApi.getRequestMethod().toLowerCase(), operation);
paths.put("/openapi/call/"+openApi.getRequestUrl(), operations);
}
swaggerModel.setDefinitions(definitions);
swaggerModel.setPaths(paths);
}
private void parameters(SwaggerOperation operation, OpenApi openApi) {
List<SwaggerOperationParameter> parameters = new ArrayList<>();
for (OpenApiParam openApiParam : openApiParamService.findByApiId(openApi.getId())) {
SwaggerOperationParameter parameter = new SwaggerOperationParameter();
parameter.setIn("path");
parameter.setName(openApiParam.getParamKey());
parameter.setRequired(openApiParam.getRequired() == 1);
parameter.setDescription(openApiParam.getNote());
parameters.add(parameter);
}
for (OpenApiHeader openApiHeader : openApiHeaderService.findByApiId(openApi.getId())) {
SwaggerOperationParameter parameter = new SwaggerOperationParameter();
parameter.setIn("header");
parameter.setName(openApiHeader.getHeaderKey());
parameter.setRequired(openApiHeader.getRequired() == 1);
parameter.setDescription(openApiHeader.getNote());
parameters.add(parameter);
}
operation.setParameters(parameters);
}
private SwaggerInfo swaggerInfo() {
SwaggerInfo info = new SwaggerInfo();
info.setDescription("OpenAPI 接口列表");
info.setVersion("3.7.1");
info.setTitle("OpenAPI 接口列表");
info.setTermsOfService("https://jeecg.com");
SwaggerInfoContact contact = new SwaggerInfoContact();
contact.setName("jeecg@qq.com");
info.setContact(contact);
SwaggerInfoLicense license = new SwaggerInfoLicense();
license.setName("Apache 2.0");
license.setUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
info.setLicense(license);
return info;
}
/**
*
* @return
*/
@GetMapping("genPath")
public Result<String> genPath() {
Result<String> r = new Result<String>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setResult(PathGenerator.genPath());
return r;
}
}

@ -0,0 +1,26 @@
package org.jeecg.modules.openapi.controller;
import org.jeecg.common.api.vo.Result;
import org.jeecg.config.shiro.IgnoreAuth;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* @date 2024/12/20 14:04
*/
@RestController
@RequestMapping("/openapi/demo")
public class OpenApiIndexController {
@GetMapping("index")
@IgnoreAuth
public Result<Map<String, String>> index() {
Map<String, String> result = new HashMap<>();
result.put("first", "Hello World");
return Result.ok(result);
}
}

@ -0,0 +1,20 @@
package org.jeecg.modules.openapi.controller;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.modules.openapi.entity.OpenApiPermission;
import org.jeecg.modules.openapi.service.OpenApiPermissionService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/openapi/permission")
public class OpenApiPermissionController extends JeecgController<OpenApiPermission, OpenApiPermissionService> {
@PostMapping("add")
public Result add(@RequestBody OpenApiPermission openApiPermission) {
return Result.ok(service.save(openApiPermission));
}
}

@ -0,0 +1,102 @@
package org.jeecg.modules.openapi.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.openapi.entity.OpenApiRecord;
import org.jeecg.modules.openapi.service.OpenApiRecordService;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
/**
* @date 2024/12/10 9:57
*/
@RestController
@RequestMapping("/openapi/record")
public class OpenApiRecordController extends JeecgController<OpenApiRecord, OpenApiRecordService> {
/**
*
*
* @param openApiRecord
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@GetMapping(value = "/list")
public Result<?> queryPageList(OpenApiRecord openApiRecord, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
QueryWrapper<OpenApiRecord> queryWrapper = QueryGenerator.initQueryWrapper(openApiRecord, req.getParameterMap());
Page<OpenApiRecord> page = new Page<>(pageNo, pageSize);
IPage<OpenApiRecord> pageList = service.page(page, queryWrapper);
return Result.ok(pageList);
}
/**
*
*
* @param openApiRecord
* @return
*/
@PostMapping(value = "/add")
public Result<?> add(@RequestBody OpenApiRecord openApiRecord) {
service.save(openApiRecord);
return Result.ok("添加成功!");
}
/**
*
*
* @param openApiRecord
* @return
*/
@PutMapping(value = "/edit")
public Result<?> edit(@RequestBody OpenApiRecord openApiRecord) {
service.updateById(openApiRecord);
return Result.ok("修改成功!");
}
/**
* id
*
* @param id
* @return
*/
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
service.removeById(id);
return Result.ok("删除成功!");
}
/**
*
*
* @param ids
* @return
*/
@DeleteMapping(value = "/deleteBatch")
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.service.removeByIds(Arrays.asList(ids.split(",")));
return Result.ok("批量删除成功!");
}
/**
* id
*
* @param id
* @return
*/
@GetMapping(value = "/queryById")
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
OpenApiRecord openApiRecord = service.getById(id);
return Result.ok(openApiRecord);
}
}

@ -0,0 +1,103 @@
package org.jeecg.modules.openapi.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
*
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class OpenApi implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
*
*/
private String name;
/**
* POSTGET
*/
private String requestMethod;
/**
*
*/
private String requestUrl;
/**
* IP
*/
private String blackList;
/**
*
*/
@TableField(exist = false)
private List<OpenApiHeader> headers;
/**
*
*/
@TableField(exist = false)
private List<OpenApiParam> params;
/**
* json
*/
private String body;
/**
*
*/
private String originUrl;
/**
* (1 2
*/
private Integer status;
/**
* 01
*/
@TableLogic
private Integer delFlag;
/**
*
*/
private String createBy;
/**
*
*/
private Date createTime;
/**
*
*/
private String updateBy;
/**
*
*/
private Date updateTime;
}

@ -0,0 +1,68 @@
package org.jeecg.modules.openapi.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
*
* @date 2024/12/10 9:38
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class OpenApiAuth implements Serializable {
private static final long serialVersionUID = -5933153354153738498L;
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
*
*/
private String name;
/**
* access key
*/
private String ak;
/**
* secret key
*/
private String sk;
/**
* ID
*/
private String systemUserId;
/**
*
*/
private String createBy;
/**
*
*/
private Date createTime;
/**
*
*/
private String updateBy;
/**
*
*/
private Date updateTime;
}

@ -0,0 +1,51 @@
package org.jeecg.modules.openapi.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
*
* @date 2024/12/10 14:37
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class OpenApiHeader implements Serializable {
private static final long serialVersionUID = 5032708503120184683L;
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* ID
*/
private String apiId;
/**
* key
*/
private String headerKey;
/**
* (0:1)
*/
private Integer required;
/**
*
*/
private String defaultValue;
/**
*
*/
private String note;
}

@ -0,0 +1,50 @@
package org.jeecg.modules.openapi.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* query
* @date 2024/12/10 14:37
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class OpenApiParam implements Serializable {
private static final long serialVersionUID = -6174831468578022357L;
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* ID
*/
private String apiId;
/**
* key
*/
private String paramKey;
/**
* (0:1)
*/
private Integer required;
/**
*
*/
private String defaultValue;
/**
*
*/
private String note;
}

@ -0,0 +1,55 @@
package org.jeecg.modules.openapi.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
*
* @date 2024/12/19 17:41
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class OpenApiPermission implements Serializable {
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* ID
*/
private String apiId;
/**
* ID
*/
private String apiAuthId;
/**
*
*/
private String createBy;
/**
*
*/
private Date createTime;
/**
*
*/
private String updateBy;
/**
*
*/
private Date updateTime;
}

@ -0,0 +1,52 @@
package org.jeecg.modules.openapi.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
*
* @date 2024/12/10 9:41
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class OpenApiRecord implements Serializable {
private static final long serialVersionUID = -5870384488947863579L;
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* ID
*/
private String apiId;
/**
* ID
*/
private String callAuthId;
/**
*
*/
private Date callTime;
/**
*
*/
private Long usedTime;
/**
*
*/
private Date responseTime;
}

@ -0,0 +1,204 @@
package org.jeecg.modules.openapi.filter;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.openapi.entity.OpenApi;
import org.jeecg.modules.openapi.entity.OpenApiAuth;
import org.jeecg.modules.openapi.entity.OpenApiPermission;
import org.jeecg.modules.openapi.entity.OpenApiRecord;
import org.jeecg.modules.openapi.service.OpenApiAuthService;
import org.jeecg.modules.openapi.service.OpenApiPermissionService;
import org.jeecg.modules.openapi.service.OpenApiRecordService;
import org.jeecg.modules.openapi.service.OpenApiService;
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* @date 2024/12/19 16:55
*/
@Slf4j
public class ApiAuthFilter implements Filter {
private OpenApiRecordService openApiRecordService;
private OpenApiAuthService openApiAuthService;
private OpenApiPermissionService openApiPermissionService;
private OpenApiService openApiService;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
long startTime = System.currentTimeMillis();
Date callTime = new Date();
HttpServletRequest request = (HttpServletRequest)servletRequest;
String ip = request.getRemoteAddr();
String appkey = request.getHeader("appkey");
String signature = request.getHeader("signature");
String timestamp = request.getHeader("timestamp");
OpenApi openApi = findOpenApi(request);
// IP 黑名单核验
checkBlackList(openApi, ip);
// 签名核验
checkSignValid(appkey, signature, timestamp);
OpenApiAuth openApiAuth = openApiAuthService.getByAppkey(appkey);
// 认证信息核验
checkSignature(appkey, signature, timestamp, openApiAuth);
// 业务核验
checkPermission(openApi, openApiAuth);
filterChain.doFilter(servletRequest, servletResponse);
long endTime = System.currentTimeMillis();
OpenApiRecord record = new OpenApiRecord();
record.setApiId(openApi.getId());
record.setCallAuthId(openApiAuth.getId());
record.setCallTime(callTime);
record.setUsedTime(endTime - startTime);
record.setResponseTime(new Date());
openApiRecordService.save(record);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
ServletContext servletContext = filterConfig.getServletContext();
WebApplicationContext applicationContext = (WebApplicationContext)servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
this.openApiService = applicationContext.getBean(OpenApiService.class);
this.openApiRecordService = applicationContext.getBean(OpenApiRecordService.class);
this.openApiAuthService = applicationContext.getBean(OpenApiAuthService.class);
this.openApiPermissionService = applicationContext.getBean(OpenApiPermissionService.class);
}
/**
* IP
* @param openApi
* @param ip
*/
protected void checkBlackList(OpenApi openApi, String ip) {
if (!StringUtils.hasText(openApi.getBlackList())) {
return;
}
List<String> blackList = Arrays.asList(openApi.getBlackList().split(","));
if (blackList.contains(ip)) {
throw new JeecgBootException("目标接口限制IP[" + ip + "]进行访问IP已记录请停止访问");
}
}
/**
*
* @param appkey
* @param signature
* @param timestamp
* @return
*/
protected void checkSignValid(String appkey, String signature, String timestamp) {
if (!StringUtils.hasText(appkey)) {
throw new JeecgBootException("appkey为空");
}
if (!StringUtils.hasText(signature)) {
throw new JeecgBootException("signature为空");
}
if (!StringUtils.hasText(timestamp)) {
throw new JeecgBootException("timastamp时间戳为空");
}
if (!timestamp.matches("[0-9]*")) {
throw new JeecgBootException("timastamp时间戳不合法");
}
if (System.currentTimeMillis() - Long.parseLong(timestamp) > 5 * 60 * 1000) {
throw new JeecgBootException("signature签名已过期(超过五分钟)");
}
}
/**
*
* @param appKey
* @param signature
* @param timestamp
* @param openApiAuth
* @return
* @throws Exception
*/
protected void checkSignature(String appKey, String signature, String timestamp, OpenApiAuth openApiAuth) {
if(openApiAuth==null){
throw new JeecgBootException("不存在认证信息");
}
if(!appKey.equals(openApiAuth.getAk())){
throw new JeecgBootException("appkey错误");
}
if (!signature.equals(md5(appKey + openApiAuth.getSk() + timestamp))) {
throw new JeecgBootException("signature签名错误");
}
}
protected void checkPermission(OpenApi openApi, OpenApiAuth openApiAuth) {
List<OpenApiPermission> permissionList = openApiPermissionService.findByAuthId(openApiAuth.getId());
boolean hasPermission = false;
for (OpenApiPermission permission : permissionList) {
if (permission.getApiId().equals(openApi.getId())) {
hasPermission = true;
break;
}
}
if (!hasPermission) {
throw new JeecgBootException("该appKey未授权当前接口");
}
}
/**
* @return String
* @Title: MD5
* @Description: MD5
*/
protected static String md5(String sourceStr) {
String result = "";
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(sourceStr.getBytes("utf-8"));
byte[] hash = md.digest();
int i;
StringBuffer buf = new StringBuffer(32);
for (int offset = 0; offset < hash.length; offset++) {
i = hash[offset];
if (i < 0) {
i += 256;
}
if (i < 16) {
buf.append("0");
}
buf.append(Integer.toHexString(i));
}
result = buf.toString();
} catch (Exception e) {
log.error("sign签名错误", e);
}
return result;
}
protected OpenApi findOpenApi(HttpServletRequest request) {
String uri = request.getRequestURI();
String path = uri.substring(uri.lastIndexOf("/") + 1);
return openApiService.findByPath(path);
}
public static void main(String[] args) {
long timestamp = System.currentTimeMillis();
System.out.println("timestamp:" + timestamp);
System.out.println("signature:" + md5("ak-eAU25mrMxhtaZsyS" + "rjxMqB6YyUXpSHAz4DCIz8vZ5aozQQiV" + timestamp));
}
}

@ -0,0 +1,25 @@
package org.jeecg.modules.openapi.filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @date 2024/12/19 17:09
*/
@Configuration
public class ApiFilterConfig {
/**
*
* @Description: api
*/
@Bean
public FilterRegistrationBean<ApiAuthFilter> authFilter() {
FilterRegistrationBean<ApiAuthFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new ApiAuthFilter());
registration.setName("apiAuthFilter");
registration.addUrlPatterns("/openapi/call/*");
return registration;
}
}

@ -0,0 +1,36 @@
package org.jeecg.modules.openapi.generator;
import java.security.SecureRandom;
/**
* AK/SK
*/
public class AKSKGenerator {
private static final String CHAR_POOL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
private static final int AK_LENGTH = 16; // Adjust as per requirements
private static final int SK_LENGTH = 32;
public static String[] genAKSKPair() {
return new String[]{genAK(), genSK()};
}
public static String genAK() {
return "ak-" + generateRandomString(AK_LENGTH);
}
public static String genSK() {
return generateRandomString(SK_LENGTH);
}
private static String generateRandomString(int length) {
SecureRandom random = new SecureRandom();
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
sb.append(CHAR_POOL.charAt(random.nextInt(CHAR_POOL.length())));
}
return sb.toString();
}
}

@ -0,0 +1,28 @@
package org.jeecg.modules.openapi.generator;
import lombok.experimental.UtilityClass;
import java.util.Random;
/**
* @date 2024/12/10 10:00
*/
@UtilityClass
public class PathGenerator {
// Base62字符集
private static final String BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
/**
*
* @return
*/
public static String genPath() {
StringBuilder result = new StringBuilder();
Random random = new Random();
for (int i=0; i<8; i++) {
result.append(BASE62.charAt(random.nextInt(62)));
}
return result.toString();
}
}

@ -0,0 +1,12 @@
package org.jeecg.modules.openapi.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.openapi.entity.OpenApiAuth;
/**
* @date 2024/12/10 9:49
*/
@Mapper
public interface OpenApiAuthMapper extends BaseMapper<OpenApiAuth> {
}

@ -0,0 +1,12 @@
package org.jeecg.modules.openapi.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.openapi.entity.OpenApiHeader;
/**
* @date 2024/12/10 14:47
*/
@Mapper
public interface OpenApiHeaderMapper extends BaseMapper<OpenApiHeader> {
}

@ -0,0 +1,9 @@
package org.jeecg.modules.openapi.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.openapi.entity.OpenApi;
@Mapper
public interface OpenApiMapper extends BaseMapper<OpenApi> {
}

@ -0,0 +1,12 @@
package org.jeecg.modules.openapi.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.openapi.entity.OpenApiParam;
/**
* @date 2024/12/10 14:48
*/
@Mapper
public interface OpenApiParamMapper extends BaseMapper<OpenApiParam> {
}

@ -0,0 +1,12 @@
package org.jeecg.modules.openapi.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.openapi.entity.OpenApiPermission;
/**
* @date 2024/12/19 17:43
*/
@Mapper
public interface OpenApiPermissionMapper extends BaseMapper<OpenApiPermission> {
}

@ -0,0 +1,12 @@
package org.jeecg.modules.openapi.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.jeecg.modules.openapi.entity.OpenApiRecord;
/**
* @date 2024/12/10 9:50
*/
@Mapper
public interface OpenApiRecordMapper extends BaseMapper<OpenApiRecord> {
}

@ -0,0 +1,11 @@
package org.jeecg.modules.openapi.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.openapi.entity.OpenApiAuth;
/**
* @date 2024/12/10 9:50
*/
public interface OpenApiAuthService extends IService<OpenApiAuth> {
OpenApiAuth getByAppkey(String appkey);
}

@ -0,0 +1,16 @@
package org.jeecg.modules.openapi.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.openapi.entity.OpenApiHeader;
import java.util.List;
/**
* @date 2024/12/10 14:48
*/
public interface OpenApiHeaderService extends IService<OpenApiHeader> {
boolean deleteByApiId(String apiId);
List<OpenApiHeader> findByApiId(String apiId);
}

@ -0,0 +1,15 @@
package org.jeecg.modules.openapi.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.openapi.entity.OpenApiParam;
import java.util.List;
/**
* @date 2024/12/10 14:49
*/
public interface OpenApiParamService extends IService<OpenApiParam> {
boolean deleteByApiId(String apiId);
List<OpenApiParam> findByApiId(String apiId);
}

@ -0,0 +1,13 @@
package org.jeecg.modules.openapi.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.openapi.entity.OpenApiPermission;
import java.util.List;
/**
* @date 2024/12/19 17:44
*/
public interface OpenApiPermissionService extends IService<OpenApiPermission> {
List<OpenApiPermission> findByAuthId(String authId);
}

@ -0,0 +1,10 @@
package org.jeecg.modules.openapi.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.openapi.entity.OpenApiRecord;
/**
* @date 2024/12/10 9:51
*/
public interface OpenApiRecordService extends IService<OpenApiRecord> {
}

@ -0,0 +1,8 @@
package org.jeecg.modules.openapi.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.openapi.entity.OpenApi;
public interface OpenApiService extends IService<OpenApi> {
OpenApi findByPath(String path);
}

@ -0,0 +1,19 @@
package org.jeecg.modules.openapi.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.openapi.entity.OpenApiAuth;
import org.jeecg.modules.openapi.mapper.OpenApiAuthMapper;
import org.jeecg.modules.openapi.service.OpenApiAuthService;
import org.springframework.stereotype.Service;
/**
* @date 2024/12/10 9:51
*/
@Service
public class OpenApiAuthServiceImpl extends ServiceImpl<OpenApiAuthMapper, OpenApiAuth> implements OpenApiAuthService {
@Override
public OpenApiAuth getByAppkey(String appkey) {
return baseMapper.selectOne(Wrappers.lambdaUpdate(OpenApiAuth.class).eq(OpenApiAuth::getAk, appkey), false);
}
}

@ -0,0 +1,26 @@
package org.jeecg.modules.openapi.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.openapi.entity.OpenApiHeader;
import org.jeecg.modules.openapi.mapper.OpenApiHeaderMapper;
import org.jeecg.modules.openapi.service.OpenApiHeaderService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @date 2024/12/10 14:49
*/
@Service
public class OpenApiHeaderServiceImpl extends ServiceImpl<OpenApiHeaderMapper, OpenApiHeader> implements OpenApiHeaderService {
@Override
public boolean deleteByApiId(String apiId) {
return baseMapper.delete(Wrappers.lambdaUpdate(OpenApiHeader.class).eq(OpenApiHeader::getApiId, apiId)) > 0;
}
@Override
public List<OpenApiHeader> findByApiId(String apiId) {
return baseMapper.selectList(Wrappers.lambdaQuery(OpenApiHeader.class).eq(OpenApiHeader::getApiId, apiId));
}
}

@ -0,0 +1,27 @@
package org.jeecg.modules.openapi.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.openapi.entity.OpenApiParam;
import org.jeecg.modules.openapi.mapper.OpenApiParamMapper;
import org.jeecg.modules.openapi.service.OpenApiParamService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @date 2024/12/10 14:50
*/
@Service
public class OpenApiParamServiceImpl extends ServiceImpl<OpenApiParamMapper, OpenApiParam> implements OpenApiParamService {
@Override
public boolean deleteByApiId(String apiId) {
return baseMapper.delete(Wrappers.lambdaUpdate(OpenApiParam.class).eq(OpenApiParam::getApiId, apiId)) > 0;
}
@Override
public List<OpenApiParam> findByApiId(String apiId) {
return baseMapper.selectList(Wrappers.lambdaQuery(OpenApiParam.class).eq(OpenApiParam::getApiId, apiId));
}
}

@ -0,0 +1,22 @@
package org.jeecg.modules.openapi.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.openapi.entity.OpenApiPermission;
import org.jeecg.modules.openapi.mapper.OpenApiPermissionMapper;
import org.jeecg.modules.openapi.service.OpenApiPermissionService;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
/**
* @date 2024/12/19 17:44
*/
@Service
public class OpenApiPermissionServiceImpl extends ServiceImpl<OpenApiPermissionMapper, OpenApiPermission> implements OpenApiPermissionService {
@Override
public List<OpenApiPermission> findByAuthId(String authId) {
return baseMapper.selectList(Wrappers.lambdaQuery(OpenApiPermission.class).eq(OpenApiPermission::getApiAuthId, authId));
}
}

@ -0,0 +1,14 @@
package org.jeecg.modules.openapi.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.openapi.entity.OpenApiRecord;
import org.jeecg.modules.openapi.mapper.OpenApiRecordMapper;
import org.jeecg.modules.openapi.service.OpenApiRecordService;
import org.springframework.stereotype.Service;
/**
* @date 2024/12/10 9:53
*/
@Service
public class OpenApiRecordServiceImpl extends ServiceImpl<OpenApiRecordMapper, OpenApiRecord> implements OpenApiRecordService {
}

@ -0,0 +1,16 @@
package org.jeecg.modules.openapi.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.openapi.entity.OpenApi;
import org.jeecg.modules.openapi.mapper.OpenApiMapper;
import org.jeecg.modules.openapi.service.OpenApiService;
import org.springframework.stereotype.Service;
@Service
public class OpenApiServiceImpl extends ServiceImpl<OpenApiMapper, OpenApi> implements OpenApiService {
@Override
public OpenApi findByPath(String path) {
return baseMapper.selectOne(Wrappers.lambdaQuery(OpenApi.class).eq(OpenApi::getRequestUrl, path), false);
}
}

@ -0,0 +1,14 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
import java.util.Map;
/**
* @date 2025/1/26 11:17
*/
@Data
public class SwaggerDefinition {
private String type;
private Map<String, SwaggerDefinitionProperties> properties;
}

@ -0,0 +1,13 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
/**
* @date 2025/1/26 13:54
*/
@Data
public class SwaggerDefinitionProperties {
private String type;
private String example;
private String description;
}

@ -0,0 +1,16 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
/**
* @date 2025/1/26 11:05
*/
@Data
public class SwaggerInfo {
private String description;
private String version;
private String title;
private String termsOfService;
private SwaggerInfoContact contact;
private SwaggerInfoLicense license;
}

@ -0,0 +1,11 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
/**
* @date 2025/1/26 11:08
*/
@Data
public class SwaggerInfoContact {
private String name;
}

@ -0,0 +1,12 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
/**
* @date 2025/1/26 11:09
*/
@Data
public class SwaggerInfoLicense {
private String name;
private String url;
}

@ -0,0 +1,21 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* @date 2025/1/26 11:05
*/
@Data
public class SwaggerModel {
private String swagger;
private SwaggerInfo info;
private String host;
private String basePath;
private List<SwaggerTag> tags;
private List<String> schemes;
private Map<String, Map<String, SwaggerOperation>> paths;
private Map<String, SwaggerDefinition> definitions;
}

@ -0,0 +1,20 @@
package org.jeecg.modules.openapi.swagger;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* @date 2025/1/26 11:16
*/
@Data
public class SwaggerOperation {
private List<String> tags;
private String summary;
private String description;
private String operationId;
private List<String> produces;
private List<SwaggerOperationParameter> parameters;
private Map<String, SwaggerOperationResponse> responses;
}

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

Loading…
Cancel
Save