ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
@@ -82,7 +82,7 @@ if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) { return R.fail("æ°å¢åæ°'" + config.getConfigName() + "'失败ï¼åæ°é®åå·²åå¨"); } return toAjax(configService.insertConfig(config)); return R.ok(configService.insertConfig(config)); } /** @@ -95,7 +95,7 @@ if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) { return R.fail("ä¿®æ¹åæ°'" + config.getConfigName() + "'失败ï¼åæ°é®åå·²åå¨"); } return toAjax(configService.updateConfig(config)); return R.ok(configService.updateConfig(config)); } /** @@ -105,7 +105,7 @@ @Log(title = "åæ°ç®¡ç", businessType = BusinessType.UPDATE) @PutMapping("/updateByKey") public R<Void> updateByKey(@RequestBody SysConfig config) { return toAjax(configService.updateConfig(config)); return R.ok(configService.updateConfig(config)); } /** ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
@@ -86,7 +86,8 @@ @Log(title = "åå ¸æ°æ®", businessType = BusinessType.INSERT) @PostMapping public R<Void> add(@Validated @RequestBody SysDictData dict) { return toAjax(dictDataService.insertDictData(dict)); dictDataService.insertDictData(dict); return R.ok(); } /** @@ -96,7 +97,8 @@ @Log(title = "åå ¸æ°æ®", businessType = BusinessType.UPDATE) @PutMapping public R<Void> edit(@Validated @RequestBody SysDictData dict) { return toAjax(dictDataService.updateDictData(dict)); dictDataService.updateDictData(dict); return R.ok(); } /** ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
@@ -72,7 +72,8 @@ if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) { return R.fail("æ°å¢åå ¸'" + dict.getDictName() + "'失败ï¼åå ¸ç±»åå·²åå¨"); } return toAjax(dictTypeService.insertDictType(dict)); dictTypeService.insertDictType(dict); return R.ok(); } /** @@ -85,7 +86,8 @@ if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) { return R.fail("ä¿®æ¹åå ¸'" + dict.getDictName() + "'失败ï¼åå ¸ç±»åå·²åå¨"); } return toAjax(dictTypeService.updateDictType(dict)); dictTypeService.updateDictType(dict); return R.ok(); } /** ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java
@@ -20,4 +20,19 @@ */ String DEMO_CACHE = "demo:cache#60s#10m#20"; /** * ç³»ç»é ç½® */ String SYS_CONFIG = "sys_config"; /** * æ°æ®åå ¸ */ String SYS_DICT = "sys_dict"; /** * OSSé ç½® */ String SYS_OSS_CONFIG = "sys_oss_config"; } ruoyi-common/src/main/java/com/ruoyi/common/utils/cache/CacheUtils.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,60 @@ package com.ruoyi.common.utils.cache; import com.ruoyi.common.utils.spring.SpringUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.springframework.cache.CacheManager; /** * ç¼åæä½å·¥å ·ç±» {@link } * * @author Michelle.Chung * @date 2022/8/13 */ @NoArgsConstructor(access = AccessLevel.PRIVATE) @SuppressWarnings(value = {"unchecked", "rawtypes"}) public class CacheUtils { private static final CacheManager CACHE_MANAGER = SpringUtils.getBean(CacheManager.class); /** * è·åç¼åå¼ * * @param cacheNames ç¼åç»åç§° * @param key ç¼åkey */ public static Object get(String cacheNames, Object key) { return CACHE_MANAGER.getCache(cacheNames).get(key).get(); } /** * ä¿åç¼åå¼ * * @param cacheNames ç¼åç»åç§° * @param key ç¼åkey * @param value ç¼åå¼ */ public static void put(String cacheNames, Object key, Object value) { CACHE_MANAGER.getCache(cacheNames).put(key, value); } /** * å é¤ç¼åå¼ * * @param cacheNames ç¼åç»åç§° * @param key ç¼åkey */ public static void evict(String cacheNames, Object key) { CACHE_MANAGER.getCache(cacheNames).evict(key); } /** * æ¸ ç©ºç¼åå¼ * * @param cacheNames ç¼åç»åç§° */ public static void clear(String cacheNames) { CACHE_MANAGER.getCache(cacheNames).clear(); } } ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java
@@ -1,7 +1,9 @@ package com.ruoyi.oss.factory; import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.cache.CacheUtils; import com.ruoyi.common.utils.redis.RedisUtils; import com.ruoyi.oss.constant.OssConstant; import com.ruoyi.oss.core.OssClient; @@ -42,7 +44,7 @@ */ public static OssClient instance() { // è·åredis é»è®¤ç±»å String configKey = RedisUtils.getCacheObject(OssConstant.CACHE_CONFIG_KEY); String configKey = (String) CacheUtils.get(CacheNames.SYS_OSS_CONFIG, OssConstant.OSS_CONFIG_KEY); if (StringUtils.isEmpty(configKey)) { throw new OssException("æä»¶å卿å¡ç±»åæ æ³æ¾å°!"); } @@ -62,7 +64,7 @@ } private static void refresh(String configKey) { Object json = RedisUtils.getCacheObject(OssConstant.SYS_OSS_KEY + configKey); Object json = CacheUtils.get(CacheNames.SYS_OSS_CONFIG, configKey); OssProperties properties = JsonUtils.parseObject(json.toString(), OssProperties.class); if (properties == null) { throw new OssException("ç³»ç»å¼å¸¸, '" + configKey + "'é 置信æ¯ä¸åå¨!"); ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
@@ -53,7 +53,7 @@ * @param config åæ°é ç½®ä¿¡æ¯ * @return ç»æ */ int insertConfig(SysConfig config); String insertConfig(SysConfig config); /** * ä¿®æ¹åæ°é ç½® @@ -61,7 +61,7 @@ * @param config åæ°é ç½®ä¿¡æ¯ * @return ç»æ */ int updateConfig(SysConfig config); String updateConfig(SysConfig config); /** * æ¹éå é¤åæ°ä¿¡æ¯ @@ -92,7 +92,5 @@ * @return ç»æ */ String checkConfigKeyUnique(SysConfig config); SysConfig getOne(SysConfig config); } ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java
@@ -54,7 +54,7 @@ * @param dictData åå ¸æ°æ®ä¿¡æ¯ * @return ç»æ */ int insertDictData(SysDictData dictData); List<SysDictData> insertDictData(SysDictData dictData); /** * ä¿®æ¹ä¿ååå ¸æ°æ®ä¿¡æ¯ @@ -62,5 +62,5 @@ * @param dictData åå ¸æ°æ®ä¿¡æ¯ * @return ç»æ */ int updateDictData(SysDictData dictData); List<SysDictData> updateDictData(SysDictData dictData); } ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
@@ -84,7 +84,7 @@ * @param dictType åå ¸ç±»åä¿¡æ¯ * @return ç»æ */ int insertDictType(SysDictType dictType); List<SysDictData> insertDictType(SysDictType dictType); /** * ä¿®æ¹ä¿ååå ¸ç±»åä¿¡æ¯ @@ -92,7 +92,7 @@ * @param dictType åå ¸ç±»åä¿¡æ¯ * @return ç»æ */ int updateDictType(SysDictType dictType); List<SysDictData> updateDictType(SysDictType dictType); /** * æ ¡éªåå ¸ç±»åç§°æ¯å¦å¯ä¸ ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
@@ -5,22 +5,23 @@ import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.service.ConfigService; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.redis.RedisUtils; import com.ruoyi.common.utils.cache.CacheUtils; import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.mapper.SysConfigMapper; import com.ruoyi.system.service.ISysConfigService; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; @@ -66,16 +67,12 @@ * @param configKey åæ°key * @return åæ°é®å¼ */ @Cacheable(cacheNames = CacheNames.SYS_CONFIG, key = "#configKey") @Override public String selectConfigByKey(String configKey) { String configValue = RedisUtils.getCacheObject(getCacheKey(configKey)); if (StringUtils.isNotEmpty(configValue)) { return configValue; } SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>() .eq(SysConfig::getConfigKey, configKey)); if (ObjectUtil.isNotNull(retConfig)) { RedisUtils.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue()); return retConfig.getConfigValue(); } return StringUtils.EMPTY; @@ -119,13 +116,14 @@ * @param config åæ°é ç½®ä¿¡æ¯ * @return ç»æ */ @CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#config.configKey") @Override public int insertConfig(SysConfig config) { public String insertConfig(SysConfig config) { int row = baseMapper.insert(config); if (row > 0) { RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); return config.getConfigValue(); } return row; throw new ServiceException("æä½å¤±è´¥"); } /** @@ -134,8 +132,9 @@ * @param config åæ°é ç½®ä¿¡æ¯ * @return ç»æ */ @CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#config.configKey") @Override public int updateConfig(SysConfig config) { public String updateConfig(SysConfig config) { int row = 0; if (config.getConfigId() != null) { row = baseMapper.updateById(config); @@ -144,9 +143,9 @@ .eq(SysConfig::getConfigKey, config.getConfigKey())); } if (row > 0) { RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); return config.getConfigValue(); } return row; throw new ServiceException("æä½å¤±è´¥"); } /** @@ -161,7 +160,7 @@ if (StringUtils.equals(UserConstants.YES, config.getConfigType())) { throw new ServiceException(String.format("å ç½®åæ°ã%1$sãä¸è½å é¤ ", config.getConfigKey())); } RedisUtils.deleteObject(getCacheKey(config.getConfigKey())); CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey()); } baseMapper.deleteBatchIds(Arrays.asList(configIds)); } @@ -172,9 +171,8 @@ @Override public void loadingConfigCache() { List<SysConfig> configsList = selectConfigList(new SysConfig()); for (SysConfig config : configsList) { RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); } configsList.forEach(config -> CacheUtils.put(CacheNames.SYS_CONFIG, config.getConfigKey(), config.getConfigValue())); } /** @@ -182,8 +180,7 @@ */ @Override public void clearConfigCache() { Collection<String> keys = RedisUtils.keys(CacheConstants.SYS_CONFIG_KEY + "*"); RedisUtils.deleteObject(keys); CacheUtils.clear(CacheNames.SYS_CONFIG); } /** @@ -211,11 +208,6 @@ return UserConstants.UNIQUE; } @Override public SysConfig getOne(SysConfig config) { return baseMapper.selectOne(new LambdaQueryWrapper<>(config)); } /** * æ ¹æ®åæ° key è·ååæ°å¼ * @@ -227,13 +219,4 @@ return selectConfigByKey(configKey); } /** * 设置cache key * * @param configKey åæ°é® * @return ç¼åé®key */ private String getCacheKey(String configKey) { return CacheConstants.SYS_CONFIG_KEY + configKey; } } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
@@ -2,15 +2,17 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.entity.SysDictData; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.redis.RedisUtils; import com.ruoyi.common.utils.cache.CacheUtils; import com.ruoyi.system.mapper.SysDictDataMapper; import com.ruoyi.system.service.ISysDictDataService; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CachePut; import org.springframework.stereotype.Service; import java.util.List; @@ -89,8 +91,7 @@ for (Long dictCode : dictCodes) { SysDictData data = selectDictDataById(dictCode); baseMapper.deleteById(dictCode); List<SysDictData> dictDatas = baseMapper.selectDictDataByType(data.getDictType()); RedisUtils.setCacheObject(getCacheKey(data.getDictType()), dictDatas); CacheUtils.evict(CacheNames.SYS_DICT, data.getDictType()); } } @@ -100,14 +101,14 @@ * @param data åå ¸æ°æ®ä¿¡æ¯ * @return ç»æ */ @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#data.dictType") @Override public int insertDictData(SysDictData data) { public List<SysDictData> insertDictData(SysDictData data) { int row = baseMapper.insert(data); if (row > 0) { List<SysDictData> dictDatas = baseMapper.selectDictDataByType(data.getDictType()); RedisUtils.setCacheObject(getCacheKey(data.getDictType()), dictDatas); return baseMapper.selectDictDataByType(data.getDictType()); } return row; throw new ServiceException("æä½å¤±è´¥"); } /** @@ -116,23 +117,14 @@ * @param data åå ¸æ°æ®ä¿¡æ¯ * @return ç»æ */ @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#data.dictType") @Override public int updateDictData(SysDictData data) { public List<SysDictData> updateDictData(SysDictData data) { int row = baseMapper.updateById(data); if (row > 0) { List<SysDictData> dictDatas = baseMapper.selectDictDataByType(data.getDictType()); RedisUtils.setCacheObject(getCacheKey(data.getDictType()), dictDatas); return baseMapper.selectDictDataByType(data.getDictType()); } return row; throw new ServiceException("æä½å¤±è´¥"); } /** * 设置cache key * * @param configKey åæ°é® * @return ç¼åé®key */ String getCacheKey(String configKey) { return CacheConstants.SYS_DICT_KEY + configKey; } } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
@@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.entity.SysDictData; @@ -15,11 +15,13 @@ import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StreamUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.redis.RedisUtils; import com.ruoyi.common.utils.cache.CacheUtils; import com.ruoyi.system.mapper.SysDictDataMapper; import com.ruoyi.system.mapper.SysDictTypeMapper; import com.ruoyi.system.service.ISysDictTypeService; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -83,15 +85,11 @@ * @param dictType åå ¸ç±»å * @return åå ¸æ°æ®éåä¿¡æ¯ */ @Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType") @Override public List<SysDictData> selectDictDataByType(String dictType) { List<SysDictData> dictDatas = RedisUtils.getCacheObject(getCacheKey(dictType)); List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType); if (CollUtil.isNotEmpty(dictDatas)) { return dictDatas; } dictDatas = dictDataMapper.selectDictDataByType(dictType); if (CollUtil.isNotEmpty(dictDatas)) { RedisUtils.setCacheObject(getCacheKey(dictType), dictDatas); return dictDatas; } return null; @@ -132,7 +130,7 @@ .eq(SysDictData::getDictType, dictType.getDictType()))) { throw new ServiceException(String.format("%1$så·²åé ,ä¸è½å é¤", dictType.getDictName())); } RedisUtils.deleteObject(getCacheKey(dictType.getDictType())); CacheUtils.evict(CacheNames.SYS_DICT, dictType.getDictType()); } baseMapper.deleteBatchIds(Arrays.asList(dictIds)); } @@ -146,9 +144,8 @@ new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getStatus, UserConstants.DICT_NORMAL)); Map<String, List<SysDictData>> dictDataMap = StreamUtils.groupByKey(dictDataList, SysDictData::getDictType); dictDataMap.forEach((k,v) -> { String dictKey = getCacheKey(k); List<SysDictData> dictList = StreamUtils.sorted(v, Comparator.comparing(SysDictData::getDictSort)); RedisUtils.setCacheObject(dictKey, dictList); CacheUtils.put(CacheNames.SYS_DICT, k, dictList); }); } @@ -157,8 +154,7 @@ */ @Override public void clearDictCache() { Collection<String> keys = RedisUtils.keys(CacheConstants.SYS_DICT_KEY + "*"); RedisUtils.deleteObject(keys); CacheUtils.clear(CacheNames.SYS_DICT); } /** @@ -176,13 +172,14 @@ * @param dict åå ¸ç±»åä¿¡æ¯ * @return ç»æ */ @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#dict.dictType") @Override public int insertDictType(SysDictType dict) { public List<SysDictData> insertDictType(SysDictType dict) { int row = baseMapper.insert(dict); if (row > 0) { RedisUtils.setCacheObject(getCacheKey(dict.getDictType()), null); return new ArrayList<>(); } return row; throw new ServiceException("æä½å¤±è´¥"); } /** @@ -191,19 +188,20 @@ * @param dict åå ¸ç±»åä¿¡æ¯ * @return ç»æ */ @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#dict.dictType") @Override @Transactional(rollbackFor = Exception.class) public int updateDictType(SysDictType dict) { public List<SysDictData> updateDictType(SysDictType dict) { SysDictType oldDict = baseMapper.selectById(dict.getDictId()); dictDataMapper.update(null, new LambdaUpdateWrapper<SysDictData>() .set(SysDictData::getDictType, dict.getDictType()) .eq(SysDictData::getDictType, oldDict.getDictType())); int row = baseMapper.updateById(dict); if (row > 0) { List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dict.getDictType()); RedisUtils.setCacheObject(getCacheKey(dict.getDictType()), dictDatas); CacheUtils.evict(CacheNames.SYS_DICT, oldDict.getDictType()); return dictDataMapper.selectDictDataByType(dict.getDictType()); } return row; throw new ServiceException("æä½å¤±è´¥"); } /** @@ -287,13 +285,4 @@ return StringUtils.stripEnd(propertyString.toString(), separator); } /** * 设置cache key * * @param configKey åæ°é® * @return ç¼åé®key */ String getCacheKey(String configKey) { return CacheConstants.SYS_DICT_KEY + configKey; } } ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java
@@ -7,12 +7,14 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.cache.CacheUtils; import com.ruoyi.common.utils.redis.RedisUtils; import com.ruoyi.oss.constant.OssConstant; import com.ruoyi.oss.factory.OssFactory; @@ -53,7 +55,7 @@ for (SysOssConfig config : list) { String configKey = config.getConfigKey(); if ("0".equals(config.getStatus())) { RedisUtils.setCacheObject(OssConstant.CACHE_CONFIG_KEY, configKey); CacheUtils.put(CacheNames.SYS_OSS_CONFIG, OssConstant.OSS_CONFIG_KEY, configKey); } setConfigCache(true, config); } @@ -126,9 +128,8 @@ } boolean flag = baseMapper.deleteBatchIds(ids) > 0; if (flag) { list.forEach(sysOssConfig -> { RedisUtils.deleteObject(getCacheKey(sysOssConfig.getConfigKey())); }); list.forEach(sysOssConfig -> CacheUtils.evict(CacheNames.SYS_OSS_CONFIG, sysOssConfig.getConfigKey())); } return flag; } @@ -158,19 +159,9 @@ .set(SysOssConfig::getStatus, "1")); row += baseMapper.updateById(sysOssConfig); if (row > 0) { RedisUtils.setCacheObject(OssConstant.CACHE_CONFIG_KEY, sysOssConfig.getConfigKey()); CacheUtils.put(CacheNames.SYS_OSS_CONFIG, OssConstant.OSS_CONFIG_KEY, sysOssConfig.getConfigKey()); } return row; } /** * 设置cache key * * @param configKey åæ°é® * @return ç¼åé®key */ private String getCacheKey(String configKey) { return OssConstant.SYS_OSS_KEY + configKey; } /** @@ -182,9 +173,7 @@ */ private boolean setConfigCache(boolean flag, SysOssConfig config) { if (flag) { RedisUtils.setCacheObject( getCacheKey(config.getConfigKey()), JsonUtils.toJsonString(config)); CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); RedisUtils.publish(OssConstant.CACHE_CONFIG_KEY, config.getConfigKey(), msg -> { log.info("åå¸å·æ°OSSé ç½® => " + msg); });