6 Commits

Author SHA1 Message Date
AprilWind
5d69832423 update 优化以逗号拼接元素 2025-08-06 11:43:37 +08:00
AprilWind
0c1e39ea14 update 优化以逗号拼接元素 2025-08-06 11:18:06 +08:00
AprilWind
a39bc870d1 update 优化发布流程定义抛出异常
- StringUtils.join 默认会跳过 null,不会抛异常
2025-08-06 10:51:51 +08:00
AprilWind
7357912681 update 新增支持占位符格式的 ServiceException 构造方法
- 新增 ServiceException(String message, Object... args) 构造器,内部使用 Hutool StrFormatter.format 格式化消息
- 解决日志打印和异常抛出信息格式不统一的问题,统一使用 {} 占位符
- 优化异常消息书写,简化拼接,提升代码可读性和维护性
2025-08-06 10:43:41 +08:00
疯狂的狮子Li
901992674e add 增加赞助商 2025-08-06 10:21:12 +08:00
疯狂的狮子Li
7ceb85ffa0 add 增加赞助商 2025-08-06 10:08:22 +08:00
19 changed files with 50 additions and 41 deletions

View File

@@ -38,8 +38,9 @@ CCFlow 驰聘低代码-流程-表单 - https://gitee.com/opencc/RuoYi-JFlow <br>
<font color="red">**启山商城系统 多租户商城源码可免费商用可二次开发 - https://www.73app.cn/** </font><br> <font color="red">**启山商城系统 多租户商城源码可免费商用可二次开发 - https://www.73app.cn/** </font><br>
Mall4J 高质量Java商城系统 - https://www.mall4j.com/cn/?statId=11 <br> Mall4J 高质量Java商城系统 - https://www.mall4j.com/cn/?statId=11 <br>
aizuda flowlong 工作流 - https://gitee.com/aizuda/flowlong <br> aizuda flowlong 工作流 - https://gitee.com/aizuda/flowlong <br>
Ruoyi-Plus-Uniapp - https://ruoyi.plus <br>
[如何成为赞助商 加群联系作者详谈](https://plus-doc.dromara.org/#/common/add_group) [如何成为赞助商 加群联系作者详谈 每日PV2500-3000 IP1700-2500](https://plus-doc.dromara.org/#/common/add_group)
# 本框架与RuoYi的功能差异 # 本框架与RuoYi的功能差异

View File

@@ -1,11 +1,15 @@
package org.dromara.common.core.exception; package org.dromara.common.core.exception;
import lombok.*; import cn.hutool.core.text.StrFormatter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.io.Serial; import java.io.Serial;
/** /**
* 业务异常 * 业务异常(支持占位符 {}
* *
* @author ruoyi * @author ruoyi
*/ */
@@ -42,6 +46,10 @@ public final class ServiceException extends RuntimeException {
this.code = code; this.code = code;
} }
public ServiceException(String message, Object... args) {
this.message = StrFormatter.format(message, args);
}
@Override @Override
public String getMessage() { public String getMessage() {
return message; return message;

View File

@@ -293,7 +293,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
// 校验时间跨度不超过最大限制 // 校验时间跨度不超过最大限制
if (diff > maxValue) { if (diff > maxValue) {
throw new ServiceException("最大时间跨度为 " + maxValue + " " + unit.toString().toLowerCase()); throw new ServiceException("最大时间跨度为 {} {}", maxValue, unit.toString().toLowerCase());
} }
} }

View File

@@ -115,7 +115,7 @@ public class ServletUtils extends JakartaServletUtil {
public static Map<String, String> getParamMap(ServletRequest request) { public static Map<String, String> getParamMap(ServletRequest request) {
Map<String, String> params = new HashMap<>(); Map<String, String> params = new HashMap<>();
for (Map.Entry<String, String[]> entry : getParams(request).entrySet()) { for (Map.Entry<String, String[]> entry : getParams(request).entrySet()) {
params.put(entry.getKey(), StringUtils.join(entry.getValue(), StringUtils.SEPARATOR)); params.put(entry.getKey(), StringUtils.joinComma(entry.getValue()));
} }
return params; return params;
} }

View File

@@ -361,5 +361,24 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
return input; return input;
} }
} }
/**
* 将可迭代对象中的元素使用逗号拼接成字符串
*
* @param iterable 可迭代对象,如 List、Set 等
* @return 拼接后的字符串
*/
public static String joinComma(Iterable<?> iterable) {
return StringUtils.join(iterable, SEPARATOR);
}
/**
* 将数组中的元素使用逗号拼接成字符串
*
* @param array 任意类型的数组
* @return 拼接后的字符串
*/
public static String joinComma(Object[] array) {
return StringUtils.join(array, SEPARATOR);
}
} }

View File

@@ -104,7 +104,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
if (StringUtils.isNotBlank(dictType)) { if (StringUtils.isNotBlank(dictType)) {
// 如果传递了字典名,则依据字典建立下拉 // 如果传递了字典名,则依据字典建立下拉
Collection<String> values = Optional.ofNullable(dictService.getAllDictByDictType(dictType)) Collection<String> values = Optional.ofNullable(dictService.getAllDictByDictType(dictType))
.orElseThrow(() -> new ServiceException(String.format("字典 %s 不存在", dictType))) .orElseThrow(() -> new ServiceException("字典 {} 不存在", dictType))
.values(); .values();
options = new ArrayList<>(values); options = new ArrayList<>(values);
} else if (StringUtils.isNotBlank(converterExp)) { } else if (StringUtils.isNotBlank(converterExp)) {

View File

@@ -1,6 +1,5 @@
package org.dromara.common.mybatis.handler; package org.dromara.common.mybatis.handler;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@@ -10,7 +9,6 @@ import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression; import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import org.apache.ibatis.io.Resources;
import org.dromara.common.core.domain.dto.RoleDTO; import org.dromara.common.core.domain.dto.RoleDTO;
import org.dromara.common.core.domain.model.LoginUser; import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
@@ -22,22 +20,13 @@ import org.dromara.common.mybatis.annotation.DataPermission;
import org.dromara.common.mybatis.enums.DataScopeType; import org.dromara.common.mybatis.enums.DataScopeType;
import org.dromara.common.mybatis.helper.DataPermissionHelper; import org.dromara.common.mybatis.helper.DataPermissionHelper;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.expression.BeanFactoryResolver; import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.expression.*; import org.springframework.expression.*;
import org.springframework.expression.common.TemplateParserContext; import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.ClassUtils;
import java.lang.reflect.Method;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function; import java.util.function.Function;
/** /**

View File

@@ -37,7 +37,7 @@ public class SysTenantPackageBo extends BaseEntity {
/** /**
* 关联菜单id * 关联菜单id
*/ */
@AutoMapping(target = "menuIds", expression = "java(org.dromara.common.core.utils.StringUtils.join(source.getMenuIds(), \",\"))") @AutoMapping(target = "menuIds", expression = "java(org.dromara.common.core.utils.StringUtils.joinComma(source.getMenuIds()))")
private Long[] menuIds; private Long[] menuIds;
/** /**

View File

@@ -112,7 +112,7 @@ public class SysClientServiceImpl implements ISysClientService {
@Override @Override
public Boolean updateByBo(SysClientBo bo) { public Boolean updateByBo(SysClientBo bo) {
SysClient update = MapstructUtils.convert(bo, SysClient.class); SysClient update = MapstructUtils.convert(bo, SysClient.class);
update.setGrantType(String.join(",", bo.getGrantTypeList())); update.setGrantType(StringUtils.joinComma(bo.getGrantTypeList()));
return baseMapper.updateById(update) > 0; return baseMapper.updateById(update) > 0;
} }

View File

@@ -172,7 +172,7 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
List<SysConfig> list = baseMapper.selectByIds(configIds); List<SysConfig> list = baseMapper.selectByIds(configIds);
list.forEach(config -> { list.forEach(config -> {
if (StringUtils.equals(SystemConstants.YES, config.getConfigType())) { if (StringUtils.equals(SystemConstants.YES, config.getConfigType())) {
throw new ServiceException(String.format("内置参数【%s】不能删除", config.getConfigKey())); throw new ServiceException("内置参数【{}】不能删除", config.getConfigKey());
} }
CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey()); CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey());
}); });

View File

@@ -192,7 +192,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
list.add(vo.getDeptName()); list.add(vo.getDeptName());
} }
} }
return String.join(StringUtils.SEPARATOR, list); return StringUtils.joinComma(list);
} }
/** /**

View File

@@ -143,7 +143,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService
boolean assigned = dictDataMapper.exists(new LambdaQueryWrapper<SysDictData>() boolean assigned = dictDataMapper.exists(new LambdaQueryWrapper<SysDictData>()
.eq(SysDictData::getDictType, x.getDictType())); .eq(SysDictData::getDictType, x.getDictType()));
if (assigned) { if (assigned) {
throw new ServiceException(String.format("%1$s已分配,不能删除", x.getDictName())); throw new ServiceException("{}已分配,不能删除", x.getDictName());
} }
}); });
baseMapper.deleteByIds(dictIds); baseMapper.deleteByIds(dictIds);

View File

@@ -120,7 +120,7 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService {
private void validEntityBeforeSave(SysOssConfig entity) { private void validEntityBeforeSave(SysOssConfig entity) {
if (StringUtils.isNotEmpty(entity.getConfigKey()) if (StringUtils.isNotEmpty(entity.getConfigKey())
&& !checkConfigKeyUnique(entity)) { && !checkConfigKeyUnique(entity)) {
throw new ServiceException("操作配置'" + entity.getConfigKey() + "'失败, 配置key已存在!"); throw new ServiceException("操作配置'{}'失败, 配置key已存在!", entity.getConfigKey());
} }
} }

View File

@@ -116,7 +116,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
} }
} }
} }
return String.join(StringUtils.SEPARATOR, list); return StringUtils.joinComma(list);
} }
@Override @Override

View File

@@ -225,7 +225,7 @@ public class SysPostServiceImpl implements ISysPostService, PostService {
List<SysPost> list = baseMapper.selectByIds(postIds); List<SysPost> list = baseMapper.selectByIds(postIds);
for (SysPost post : list) { for (SysPost post : list) {
if (this.countUserPostById(post.getPostId()) > 0) { if (this.countUserPostById(post.getPostId()) > 0) {
throw new ServiceException(String.format("%1$s已分配,不能删除!", post.getPostName())); throw new ServiceException("{}已分配,不能删除!", post.getPostName());
} }
} }
return baseMapper.deleteByIds(postIds); return baseMapper.deleteByIds(postIds);

View File

@@ -88,11 +88,7 @@ public class SysTenantPackageServiceImpl implements ISysTenantPackageService {
SysTenantPackage add = MapstructUtils.convert(bo, SysTenantPackage.class); SysTenantPackage add = MapstructUtils.convert(bo, SysTenantPackage.class);
// 保存菜单id // 保存菜单id
List<Long> menuIds = Arrays.asList(bo.getMenuIds()); List<Long> menuIds = Arrays.asList(bo.getMenuIds());
if (CollUtil.isNotEmpty(menuIds)) { add.setMenuIds(CollUtil.isNotEmpty(menuIds) ? StringUtils.joinComma(menuIds) : "");
add.setMenuIds(StringUtils.join(menuIds, ", "));
} else {
add.setMenuIds("");
}
boolean flag = baseMapper.insert(add) > 0; boolean flag = baseMapper.insert(add) > 0;
if (flag) { if (flag) {
bo.setPackageId(add.getPackageId()); bo.setPackageId(add.getPackageId());
@@ -109,11 +105,7 @@ public class SysTenantPackageServiceImpl implements ISysTenantPackageService {
SysTenantPackage update = MapstructUtils.convert(bo, SysTenantPackage.class); SysTenantPackage update = MapstructUtils.convert(bo, SysTenantPackage.class);
// 保存菜单id // 保存菜单id
List<Long> menuIds = Arrays.asList(bo.getMenuIds()); List<Long> menuIds = Arrays.asList(bo.getMenuIds());
if (CollUtil.isNotEmpty(menuIds)) { update.setMenuIds(CollUtil.isNotEmpty(menuIds) ? StringUtils.joinComma(menuIds) : "");
update.setMenuIds(StringUtils.join(menuIds, ", "));
} else {
update.setMenuIds("");
}
return baseMapper.updateById(update) > 0; return baseMapper.updateById(update) > 0;
} }

View File

@@ -354,7 +354,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
// 防止错误更新后导致的数据误删除 // 防止错误更新后导致的数据误删除
int flag = baseMapper.updateById(sysUser); int flag = baseMapper.updateById(sysUser);
if (flag < 1) { if (flag < 1) {
throw new ServiceException("修改用户" + user.getUserName() + "信息失败"); throw new ServiceException("修改用户{}信息失败", user.getUserName());
} }
return flag; return flag;
} }
@@ -622,7 +622,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService {
list.add(nickname); list.add(nickname);
} }
} }
return String.join(StringUtils.SEPARATOR, list); return StringUtils.joinComma(list);
} }
/** /**

View File

@@ -128,7 +128,7 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
} }
} }
if (CollUtil.isNotEmpty(errorMsg)) { if (CollUtil.isNotEmpty(errorMsg)) {
throw new ServiceException("节点【" + StringUtils.join(errorMsg, ",") + "】未配置办理人!"); throw new ServiceException("节点【{}】未配置办理人!", StringUtils.joinComma(errorMsg));
} }
} }
return defService.publish(id); return defService.publish(id);
@@ -188,7 +188,7 @@ public class FlwDefinitionServiceImpl implements IFlwDefinitionService {
if (CollUtil.isNotEmpty(flowDefinitions)) { if (CollUtil.isNotEmpty(flowDefinitions)) {
String join = StreamUtils.join(flowDefinitions, FlowDefinition::getFlowCode); String join = StreamUtils.join(flowDefinitions, FlowDefinition::getFlowCode);
log.info("流程定义【{}】已被使用不可被删除!", join); log.info("流程定义【{}】已被使用不可被删除!", join);
throw new ServiceException("流程定义【" + join + "】已被使用不可被删除!"); throw new ServiceException("流程定义【{}】已被使用不可被删除!", join);
} }
} }
try { try {

View File

@@ -260,7 +260,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
List<String> variableUserIds = Arrays.asList(userIds.split(StringUtils.SEPARATOR)); List<String> variableUserIds = Arrays.asList(userIds.split(StringUtils.SEPARATOR));
hashSet.addAll(popUserIds); hashSet.addAll(popUserIds);
hashSet.addAll(variableUserIds); hashSet.addAll(variableUserIds);
map.put(entry.getKey(), String.join(StringUtils.SEPARATOR, hashSet)); map.put(entry.getKey(), StringUtils.joinComma(hashSet));
} }
} else { } else {
map.put(entry.getKey(), entry.getValue()); map.put(entry.getKey(), entry.getValue());
@@ -587,7 +587,7 @@ public class FlwTaskServiceImpl implements IFlwTaskService {
for (FlowNode flowNode : nextFlowNodes) { for (FlowNode flowNode : nextFlowNodes) {
Task first = StreamUtils.findFirst(buildNextTaskList, t -> t.getNodeCode().equals(flowNode.getNodeCode())); Task first = StreamUtils.findFirst(buildNextTaskList, t -> t.getNodeCode().equals(flowNode.getNodeCode()));
if (ObjectUtil.isNotNull(first) && CollUtil.isNotEmpty(first.getPermissionList())) { if (ObjectUtil.isNotNull(first) && CollUtil.isNotEmpty(first.getPermissionList())) {
List<UserDTO> users = flwTaskAssigneeService.fetchUsersByStorageIds(String.join(StringUtils.SEPARATOR, first.getPermissionList())); List<UserDTO> users = flwTaskAssigneeService.fetchUsersByStorageIds(StringUtils.joinComma(first.getPermissionList()));
if (CollUtil.isNotEmpty(users)) { if (CollUtil.isNotEmpty(users)) {
flowNode.setPermissionFlag(StreamUtils.join(users, e -> Convert.toStr(e.getUserId()))); flowNode.setPermissionFlag(StreamUtils.join(users, e -> Convert.toStr(e.getUserId())));
} }