feat: 静态字典和动态字典转换中文方法
This commit is contained in:
parent
dd0ce6a7d9
commit
a37c7248ab
@ -16,6 +16,8 @@ import com.yfd.platform.qgc_base.mapper.SdHbrvDicMapper;
|
|||||||
import com.yfd.platform.qgc_base.mapper.SdHydrobaseMapper;
|
import com.yfd.platform.qgc_base.mapper.SdHydrobaseMapper;
|
||||||
import com.yfd.platform.qgc_base.service.ISdHbrvDicService;
|
import com.yfd.platform.qgc_base.service.ISdHbrvDicService;
|
||||||
import com.yfd.platform.system.service.IAdminAuthService;
|
import com.yfd.platform.system.service.IAdminAuthService;
|
||||||
|
import com.yfd.platform.utils.CodeToNameMetadataBo;
|
||||||
|
import com.yfd.platform.utils.DictCodeToNameConverter;
|
||||||
import com.yfd.platform.utils.QgcQueryWrapperUtil;
|
import com.yfd.platform.utils.QgcQueryWrapperUtil;
|
||||||
import com.yfd.platform.utils.SecurityUtils;
|
import com.yfd.platform.utils.SecurityUtils;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
@ -51,6 +53,35 @@ public class SdHbrvDicServiceImpl extends ServiceImpl<SdHbrvDicMapper, SdHbrvDic
|
|||||||
private IAdminAuthService adminAuthService;
|
private IAdminAuthService adminAuthService;
|
||||||
|
|
||||||
private SdHbrvDicMapper hbrvDicMapper;
|
private SdHbrvDicMapper hbrvDicMapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DictCodeToNameConverter dictCodeToNameConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代码转名称元数据配置列表(静态初始化)
|
||||||
|
* <p>
|
||||||
|
* 每个模块的 ServiceImpl 中可按需定义自己的 codeToNameMetadataBoList,
|
||||||
|
* 在查询方法返回前调用 dictCodeToNameConverter.convertCodeToName(voList, codeToNameMetadataBoList)
|
||||||
|
* 即可自动将 code 字段转为对应的 name 字段。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 使用示例:
|
||||||
|
* // 在查询方法末尾调用:
|
||||||
|
* dictCodeToNameConverter.convertCodeToName(voList, CODE_TO_NAME_META_LIST);
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
private static final List<CodeToNameMetadataBo> CODE_TO_NAME_META_LIST = new ArrayList<>();
|
||||||
|
|
||||||
|
// static {
|
||||||
|
//
|
||||||
|
// CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("grd").modifyProperty("grdName").dictType("STATIC").dictSource("TEST").build());
|
||||||
|
// CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("baseid").modifyProperty("basename").dictType("DYNAMIC").dictSource("SD_HYDROBASE").codeColumn("BASEID").nameColumn("BASENAME").filter("NVL(IS_DELETED, 0) = 0 ").build());
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<SdHbrvDic> queryPageList(Page<SdHbrvDic> page, String hbrvnm, String baseid) {
|
public Page<SdHbrvDic> queryPageList(Page<SdHbrvDic> page, String hbrvnm, String baseid) {
|
||||||
return this.page(page, this.lambdaQuery()
|
return this.page(page, this.lambdaQuery()
|
||||||
|
|||||||
@ -0,0 +1,94 @@
|
|||||||
|
package com.yfd.platform.utils;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代码转名称元数据配置
|
||||||
|
* <p>
|
||||||
|
* 用于配置 VO 中某个 code 字段如何转换为对应的 name 字段,
|
||||||
|
* 支持静态字典(SYS_DICTIONARY / SYS_DICTIONARY_ITEMS)和动态字典(业务表)。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* 使用示例:
|
||||||
|
* // 静态字典:将 vo.typeCode 转为 vo.typeName,字典编码为 "PROJECT_TYPE"
|
||||||
|
* CodeToNameMetadataBo.builder()
|
||||||
|
* .codeProperty("typeCode")
|
||||||
|
* .modifyProperty("typeName")
|
||||||
|
* .dictType("STATIC")
|
||||||
|
* .dictSource("PROJECT_TYPE")
|
||||||
|
* .build();
|
||||||
|
*
|
||||||
|
* // 动态字典:将 vo.engCode 转为 vo.engName,查 SD_ENGINFO_B_H 表
|
||||||
|
* CodeToNameMetadataBo.builder()
|
||||||
|
* .codeProperty("engCode")
|
||||||
|
* .modifyProperty("engName")
|
||||||
|
* .dictType("DYNAMIC")
|
||||||
|
* .dictSource("SD_ENGINFO_B_H")
|
||||||
|
* .codeColumn("STCD")
|
||||||
|
* .nameColumn("ENNM")
|
||||||
|
* .filter("NVL(IS_DELETED, 0) = 0")
|
||||||
|
* .build();
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author Generated
|
||||||
|
* @since 2025-05-18
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CodeToNameMetadataBo implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码属性名(VO 中存放 code 的字段名)
|
||||||
|
*/
|
||||||
|
private String codeProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 名称属性名(VO 中需要设置 name 的字段名)
|
||||||
|
*/
|
||||||
|
private String modifyProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典类型:STATIC(静态字典)或 DYNAMIC(动态字典)
|
||||||
|
*/
|
||||||
|
private String dictType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典来源:
|
||||||
|
* - 静态字典:SYS_DICTIONARY 表中的 DICTCODE
|
||||||
|
* - 动态字典:业务表名
|
||||||
|
*/
|
||||||
|
private String dictSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态字典:表中编码列名(静态字典不需要)
|
||||||
|
*/
|
||||||
|
private String codeColumn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态字典:表中名称列名(静态字典不需要)
|
||||||
|
*/
|
||||||
|
private String nameColumn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 额外过滤条件(可选)
|
||||||
|
* - 静态字典:SYS_DICTIONARY_ITEMS 的额外 WHERE 条件
|
||||||
|
* - 动态字典:业务表的额外 WHERE 条件
|
||||||
|
*/
|
||||||
|
private String filter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否多选(code 值为逗号分隔的多个编码)
|
||||||
|
*/
|
||||||
|
@Builder.Default
|
||||||
|
private boolean isMulti = false;
|
||||||
|
}
|
||||||
@ -0,0 +1,350 @@
|
|||||||
|
package com.yfd.platform.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
|
||||||
|
import com.yfd.platform.system.domain.SysDictionary;
|
||||||
|
import com.yfd.platform.system.domain.SysDictionaryItems;
|
||||||
|
import com.yfd.platform.system.mapper.SysDictionaryItemsMapper;
|
||||||
|
import com.yfd.platform.system.mapper.SysDictionaryMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典代码转名称转换器
|
||||||
|
* <p>
|
||||||
|
* 支持静态字典(SYS_DICTIONARY / SYS_DICTIONARY_ITEMS)和动态字典(业务表查询),
|
||||||
|
* 将 VO 中的 code 字段值转换为对应的 name 字段值。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <h3>使用方式</h3>
|
||||||
|
* <pre>
|
||||||
|
* // 1. 在 ServiceImpl 中注入
|
||||||
|
* @Resource
|
||||||
|
* private DictCodeToNameConverter dictCodeToNameConverter;
|
||||||
|
*
|
||||||
|
* // 2. 定义元数据列表(通常放在 static 静态代码块中)
|
||||||
|
* private static final List<CodeToNameMetadataBo> CODE_TO_NAME_META_LIST = List.of(
|
||||||
|
* CodeToNameMetadataBo.builder()
|
||||||
|
* .codeProperty("stationType")
|
||||||
|
* .modifyProperty("stationTypeName")
|
||||||
|
* .dictType("STATIC")
|
||||||
|
* .dictSource("STATION_TYPE")
|
||||||
|
* .build(),
|
||||||
|
* CodeToNameMetadataBo.builder()
|
||||||
|
* .codeProperty("engCode")
|
||||||
|
* .modifyProperty("engName")
|
||||||
|
* .dictType("DYNAMIC")
|
||||||
|
* .dictSource("SD_ENGINFO_B_H")
|
||||||
|
* .codeColumn("STCD")
|
||||||
|
* .nameColumn("ENNM")
|
||||||
|
* .filter("NVL(IS_DELETED, 0) = 0")
|
||||||
|
* .build()
|
||||||
|
* );
|
||||||
|
*
|
||||||
|
* // 3. 在查询方法中调用转换
|
||||||
|
* public DataSourceResult<MyVo> queryList(DataSourceRequest request) {
|
||||||
|
* // ... 查询数据得到 voList ...
|
||||||
|
* dictCodeToNameConverter.convertCodeToName(voList, CODE_TO_NAME_META_LIST);
|
||||||
|
* // ... 返回结果 ...
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author Generated
|
||||||
|
* @since 2025-05-18
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class DictCodeToNameConverter {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SysDictionaryMapper sysDictionaryMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SysDictionaryItemsMapper sysDictionaryItemsMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private MicroservicDynamicSQLMapper<?> microservicDynamicSQLMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 静态字典缓存:dictCode -> Map<itemCode, dictName>
|
||||||
|
*/
|
||||||
|
private final Map<String, Map<String, String>> staticDictCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态字典缓存:缓存key -> Map<code, name>
|
||||||
|
*/
|
||||||
|
private final Map<String, Map<String, String>> dynamicDictCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量转换:根据元数据配置,将 VO 列表中的 code 字段转换为对应的 name 字段
|
||||||
|
*
|
||||||
|
* @param voList VO 对象列表
|
||||||
|
* @param metadataList 元数据配置列表
|
||||||
|
* @param <T> VO 类型
|
||||||
|
*/
|
||||||
|
public <T> void convertCodeToName(List<T> voList, List<CodeToNameMetadataBo> metadataList) {
|
||||||
|
if (voList == null || voList.isEmpty() || metadataList == null || metadataList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CodeToNameMetadataBo metadata : metadataList) {
|
||||||
|
try {
|
||||||
|
Map<String, String> codeNameMap = loadCodeNameMap(metadata);
|
||||||
|
if (codeNameMap.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
applyCodeToName(voList, metadata, codeNameMap);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("字典转换失败: codeProperty={}, dictSource={}", metadata.getCodeProperty(), metadata.getDictSource(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载静态字典映射
|
||||||
|
*
|
||||||
|
* @param dictCode 字典编码
|
||||||
|
* @return Map<itemCode, dictName>
|
||||||
|
*/
|
||||||
|
public Map<String, String> loadStaticDictMap(String dictCode) {
|
||||||
|
return staticDictCache.computeIfAbsent(dictCode, key -> {
|
||||||
|
Map<String, String> map = new LinkedHashMap<>();
|
||||||
|
try {
|
||||||
|
SysDictionary dict = sysDictionaryMapper.selectOne(
|
||||||
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysDictionary>()
|
||||||
|
.eq(SysDictionary::getDictCode, key)
|
||||||
|
);
|
||||||
|
if (dict == null) {
|
||||||
|
log.warn("静态字典未找到: dictCode={}", key);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
List<SysDictionaryItems> items = sysDictionaryItemsMapper.selectList(
|
||||||
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysDictionaryItems>()
|
||||||
|
.eq(SysDictionaryItems::getDictId, dict.getId())
|
||||||
|
.orderByAsc(SysDictionaryItems::getOrderNo)
|
||||||
|
);
|
||||||
|
for (SysDictionaryItems item : items) {
|
||||||
|
if (StrUtil.isNotBlank(item.getItemCode())) {
|
||||||
|
map.put(item.getItemCode(), StrUtil.nullToDefault(item.getDictName(), item.getItemCode()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("加载静态字典失败: dictCode={}", key, e);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载动态字典映射(从业务表查询)
|
||||||
|
*
|
||||||
|
* @param tableName 表名
|
||||||
|
* @param codeColumn 编码列名
|
||||||
|
* @param nameColumn 名称列名
|
||||||
|
* @param filter 额外过滤条件
|
||||||
|
* @return Map<code, name>
|
||||||
|
*/
|
||||||
|
public Map<String, String> loadDynamicDictMap(String tableName, String codeColumn, String nameColumn, String filter) {
|
||||||
|
String cacheKey = tableName + "|" + codeColumn + "|" + nameColumn + "|" + StrUtil.nullToDefault(filter, "");
|
||||||
|
return dynamicDictCache.computeIfAbsent(cacheKey, key -> {
|
||||||
|
Map<String, String> map = new LinkedHashMap<>();
|
||||||
|
try {
|
||||||
|
StringBuilder sql = new StringBuilder();
|
||||||
|
sql.append("SELECT ").append(codeColumn).append(" AS code, ")
|
||||||
|
.append(nameColumn).append(" AS name ")
|
||||||
|
.append("FROM ").append(tableName)
|
||||||
|
.append(" WHERE 1=1 ");
|
||||||
|
if (StrUtil.isNotBlank(filter)) {
|
||||||
|
sql.append("AND ").append(filter).append(" ");
|
||||||
|
}
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
List<Map<String, Object>> rows = microservicDynamicSQLMapper.getAllList(sql.toString(), params);
|
||||||
|
for (Map<String, Object> row : rows) {
|
||||||
|
String code = Objects.toString(row.get("CODE"), null);
|
||||||
|
String name = Objects.toString(row.get("NAME"), null);
|
||||||
|
if (StrUtil.isNotBlank(code)) {
|
||||||
|
map.put(code, StrUtil.nullToDefault(name, code));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("加载动态字典失败: tableName={}", tableName, e);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据元数据加载 code->name 映射
|
||||||
|
*/
|
||||||
|
private Map<String, String> loadCodeNameMap(CodeToNameMetadataBo metadata) {
|
||||||
|
if ("STATIC".equalsIgnoreCase(metadata.getDictType())) {
|
||||||
|
return loadStaticDictMap(metadata.getDictSource());
|
||||||
|
} else if ("DYNAMIC".equalsIgnoreCase(metadata.getDictType())) {
|
||||||
|
return loadDynamicDictMap(
|
||||||
|
metadata.getDictSource(),
|
||||||
|
metadata.getCodeColumn(),
|
||||||
|
metadata.getNameColumn(),
|
||||||
|
metadata.getFilter()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
log.warn("未知字典类型: dictType={}", metadata.getDictType());
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 code->name 映射应用到 VO 列表
|
||||||
|
*/
|
||||||
|
private <T> void applyCodeToName(List<T> voList, CodeToNameMetadataBo metadata, Map<String, String> codeNameMap) {
|
||||||
|
for (T vo : voList) {
|
||||||
|
try {
|
||||||
|
String codeValue = getFieldValue(vo, metadata.getCodeProperty());
|
||||||
|
if (StrUtil.isBlank(codeValue)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String nameValue;
|
||||||
|
if (metadata.isMulti()) {
|
||||||
|
// 多选:逗号分隔的多个code
|
||||||
|
nameValue = Arrays.stream(codeValue.split(","))
|
||||||
|
.map(String::trim)
|
||||||
|
.filter(StrUtil::isNotBlank)
|
||||||
|
.map(c -> codeNameMap.getOrDefault(c, c))
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
} else {
|
||||||
|
nameValue = codeNameMap.getOrDefault(codeValue.trim(), codeValue);
|
||||||
|
}
|
||||||
|
setFieldValue(vo, metadata.getModifyProperty(), nameValue);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("字段转换跳过: vo={}, codeProperty={}", vo.getClass().getSimpleName(), metadata.getCodeProperty(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除所有缓存
|
||||||
|
*/
|
||||||
|
public void clearCache() {
|
||||||
|
staticDictCache.clear();
|
||||||
|
dynamicDictCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除指定静态字典缓存
|
||||||
|
*/
|
||||||
|
public void clearStaticDictCache(String dictCode) {
|
||||||
|
staticDictCache.remove(dictCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除指定动态字典缓存
|
||||||
|
*/
|
||||||
|
public void clearDynamicDictCache(String tableName, String codeColumn, String nameColumn, String filter) {
|
||||||
|
String cacheKey = tableName + "|" + codeColumn + "|" + nameColumn + "|" + StrUtil.nullToDefault(filter, "");
|
||||||
|
dynamicDictCache.remove(cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 反射工具方法 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过反射获取对象的字段值(转为字符串),支持驼峰命名
|
||||||
|
*/
|
||||||
|
private <T> String getFieldValue(T obj, String fieldName) {
|
||||||
|
try {
|
||||||
|
Field field = findField(obj.getClass(), fieldName);
|
||||||
|
if (field == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
field.setAccessible(true);
|
||||||
|
Object value = field.get(obj);
|
||||||
|
return value != null ? value.toString() : null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过反射设置对象的字段值,支持驼峰命名
|
||||||
|
*/
|
||||||
|
private <T> void setFieldValue(T obj, String fieldName, String value) {
|
||||||
|
try {
|
||||||
|
Field field = findField(obj.getClass(), fieldName);
|
||||||
|
if (field == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(obj, value);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
// 忽略设置失败
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找字段(忽略大小写,支持驼峰和下划线变体),递归查找父类
|
||||||
|
*/
|
||||||
|
private Field findField(Class<?> clazz, String fieldName) {
|
||||||
|
if (clazz == null || clazz == Object.class) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 先精确匹配
|
||||||
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
|
if (field.getName().equals(fieldName)) {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 忽略大小写匹配
|
||||||
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
|
if (field.getName().equalsIgnoreCase(fieldName)) {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 驼峰-下划线互转匹配
|
||||||
|
String camelName = underlineToCamel(fieldName);
|
||||||
|
String underlineName = camelToUnderline(fieldName);
|
||||||
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
|
String fName = field.getName();
|
||||||
|
if (fName.equalsIgnoreCase(camelName) || fName.equalsIgnoreCase(underlineName)) {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return findField(clazz.getSuperclass(), fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String underlineToCamel(String str) {
|
||||||
|
if (StrUtil.isBlank(str) || !str.contains("_")) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
boolean upper = false;
|
||||||
|
for (char c : str.toCharArray()) {
|
||||||
|
if (c == '_') {
|
||||||
|
upper = true;
|
||||||
|
} else {
|
||||||
|
sb.append(upper ? Character.toUpperCase(c) : c);
|
||||||
|
upper = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String camelToUnderline(String str) {
|
||||||
|
if (StrUtil.isBlank(str)) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < str.length(); i++) {
|
||||||
|
char c = str.charAt(i);
|
||||||
|
if (Character.isUpperCase(c)) {
|
||||||
|
sb.append('_').append(Character.toLowerCase(c));
|
||||||
|
} else {
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user