单例实现系统参数管理
2020-06-18 本文已影响0人
莫须有的呓语
简介:后台管理中的系统参数管理, 修改频率很低,存储于数据库中,接近key-value的形式,其他功能中需要使用其中的部分参数,如果每次都查询数据库会比较浪费。
- 本项目基于springboot+mybatis,数据库为mysql, 开发环境idea
- 此功能用的pom,配置文件就基础那些,不贴了。
- 在实际项目中还用来加载码表(一些不会经常改变的数据),所以有些地方可能看起来有点多余
一、数据库表
1. 创建数据库
DROP TABLE IF EXISTS `r_config_dic`;
CREATE TABLE `r_config_dic` (
`id` varchar(100) NOT NULL COMMENT '主键id',
`dic_sort` tinyint(4) DEFAULT NULL COMMENT '排序',
`dic_key` varchar(60) DEFAULT NULL COMMENT '关键字',
`dic_value` varchar(100) DEFAULT NULL COMMENT '值',
`dic_type` varchar(40) DEFAULT NULL COMMENT '类型',
`dic_desc` varchar(100) DEFAULT NULL COMMENT '名称/说明',
`dic_remark` varchar(40) DEFAULT NULL COMMENT '计量单位/其他备注信息',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统管理-参数管理表';
二、单例
1. 单例模式
单例模式|菜鸟教程
比较认真的朋友可以去看上面的链接,本案例使用内部静态类的实现方式
以下为个人懒汉式理解:
1.只生成唯一实例,只创建一次,不用频繁创建(不用频繁查询数据库)
2.整个程序运行时,不论何处调用其中的属性,获取到的值都一样
2. 单例代码
package com.admin.init;
//pojo类
import com.admin.pojo.ConfigDic;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author 莫须有
* @SinceDate 2020/06/05
* @Description 参数配置单例
*/
public class SingletonConfigDic {
private Map<String, Map<String, String>> map;
private Map<String, List<ConfigDic>> list;
private static class SingletonHolder {
private static final SingletonConfigDic INSTANCE = new SingletonConfigDic();
}
public static final SingletonConfigDic getInstance() {
return SingletonHolder.INSTANCE;
}
private SingletonConfigDic() {
map = new HashMap<>();
list = new HashMap<>();
}
public void putMap(String key, Map<String, String> value) {
map.put(key, value);
}
// 使用样例
// SingletonConfigDic.getInstance().getMap("dicType").get("dicKey")
public Map<String, String> getMap(String key) {
return map.get(key);
}
public Map<String, Map<String, String>> getMap() {
return map;
}
public void putList(String key, List<ConfigDic> value) {
list.put(key, value);
}
// 使用样例
// SingletonConfigDic.getInstance().getList("dicType")
public List<ConfigDic> getList(String key) {
return list.get(key);
}
public Map<String, List<ConfigDic>> getList() {
return list;
}
}
3. 初始化加载单例
package com.admin.init; //和单例放在一个包下了
import com.admin.pojo.ConfigDic; //pojo类
import com.admin.service.ConfigDicService; //service类
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 配置参数初始加载
*
* @author 莫须有
* @since 2020/06/05
**/
@Component
public class ConfigDictInit {
@Resource //和@Autowired功能相似
private ConfigDicService configDicService;
/**
* log日志,非必须
*/
private static final Logger logger = LogManager.getLogger(ConfigDictInit.class);
@PostConstruct
public void init(){
logger.info("初始执行加载参数数据...");
//数据库里读取参数类型
List<String> dictTypeList = configDicService.findDictTypeList();
for (String dictType : dictTypeList) {
//找到各参数类型下的参数,并以KV的形式放入自定义的map,Map<String, Map<String, String>>
//将实体类放入自定义的list,Map<String,List<ConfigDic>>
List<ConfigDic> dictList = configDicService.findDictByType(dictType);
Map<String, String> dictTypeMap = new HashMap<>(dictList.size());
for (ConfigDic configDic : dictList) {
dictTypeMap.put(configDic.getDicKey(), configDic.getDicValue());
}
SingletonConfigDic.getInstance().putMap(dictType, dictTypeMap);
SingletonConfigDic.getInstance().putList(dictType, dictList);
}
}
}
二、SSM三层结构
1. controller
package com.admin.api;
import com.admin.init.SingletonConfigDic;
import com.admin.pojo.ConfigDic;
import com.admin.service.ConfigDicService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* @author 莫须有
* @Classname ConfigDicController
* @Description 系统管理-参数管理的controller层
* @Date 2020/06/03
*/
@RestController
@RequestMapping("admin/configDic")
@Api(value = "ConfigDicController", description = "参数管理controller层")
public class ConfigDicController {
@Autowired
private ConfigDicService configDicService;
/**
* 根据类型获取字典类型
*/
@GetMapping(value = "/findConfigDicByType")
@ApiOperation(value = "根据类型获取参数")
public ResponseEntity findDictByType(String dicType) {
List<ConfigDic> dictByType = configDicService.findDictByType(dicType);
return ResponseEntity.ok(dictByType);
}
@PostMapping("/updateConfigDicList")
@ApiOperation(value = "修改参数")
public ResponseEntity updateConfigDicList(@RequestBody List<ConfigDic> configDicList) {
//修改后不需要重启服务就能刷新到单例中
//必须传type,key
Integer integer = configDicService.updateConfigDicList(configDicList);
return ResponseEntity.ok(integer);
}
}
2. service
package com.admin.service;
import com.admin.pojo.ConfigDic;
import java.util.List;
import java.util.Map;
/**
* @Author mxy
* @SinceDate 2020/06/03
* @Description 系统管理-参数管理
*/
public interface ConfigDicService {
/**
* 查询类型列表
*/
List<String> findDictTypeList();
/**
* 根据类型值查询字典值
*/
List<ConfigDic> findDictByType(String dType);
/**
* 修改配置参数
* @param configDicList
* @return
*/
int updateConfigDicList(List<ConfigDic> configDicList);
}
3. serviceImpl
package com.admin.service.impl;
import com.admin.init.SingletonConfigDic;
import com.admin.mapper.mysql.ConfigDicMapper;
import com.admin.pojo.ConfigDic;
import com.admin.service.ConfigDicService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author mxy
* @SinceDate 2020/06/03
* @Description 系统管理-参数管理
*/
@Service
public class ConfigDicServiceImpl implements ConfigDicService {
@Autowired
private ConfigDicMapper configDicMapper;
/**
* log日志
*/
private static final Logger logger = LogManager.getLogger(ConfigDicServiceImpl.class);
/**
* 查询字典表类型
*/
@Override
public List<String> findDictTypeList() {
return configDicMapper.selectDictTypeList();
}
/**
* 根据dic_type值查询字典值
*/
@Override
public List<ConfigDic> findDictByType(String dType) {
return configDicMapper.selectDictByType(dType);
}
@Transactional(rollbackFor = Exception.class)
@Override
public int updateConfigDicList(List<ConfigDic> configDicList) {
int rows=0;
for (ConfigDic configDic:configDicList) {
rows += configDicMapper.updateDict(configDic);
}
//重新加载单例中的数据
SingletonConfigDic.getInstance().getMap().clear();
SingletonConfigDic.getInstance().getList().clear();
logger.info("重新执行加载参数数据...");
List<String> dictTypeList = findDictTypeList();
for (String dictType : dictTypeList) {
List<ConfigDic> dictList = findDictByType(dictType);
Map<String, String> dictTypeMap = new HashMap<>(dictList.size());
for (ConfigDic configDic : dictList) {
dictTypeMap.put(configDic.getDicKey(), configDic.getDicValue());
}
SingletonConfigDic.getInstance().putMap(dictType, dictTypeMap);
SingletonConfigDic.getInstance().putList(dictType, dictList);
}
return rows;
}
}
4.mapper
package com.admin.mapper.mysql;
import com.admin.pojo.ConfigDic;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Author: mxy
* @Date: 2020/06/03
*/
@Component
public interface ConfigDicMapper {
/**
* 查询参数表类型
*/
List<String> selectDictTypeList();
/**
* 根据dic_type值查询字典值
*/
List<ConfigDic> selectDictByType(@Param("dType") String dType);
/**
* 更新参数表
* @param configDic
* @return
*/
int updateDict(ConfigDic configDic);
}
5. mapper的xml
<?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="com.admin.mapper.mysql.ConfigDicMapper">
<select id="selectDictTypeList" resultType="java.lang.String">
SELECT dic_type FROM r_config_dic GROUP BY dic_type
</select>
<select id="selectDictByType" resultType="com.bonc.industry.admin.pojo.ConfigDic">
SELECT * FROM r_config_dic
WHERE dic_type = #{dType}
ORDER BY dic_sort ASC
</select>
<update id="updateDict">
update r_config_dic
<set>
<if test="dicValue != null and dicValue != ''">dic_value=#{dicValue},</if>
<if test="dicDesc != null and dicDesc != ''">dic_desc=#{dicDesc},</if>
<if test="dicSort != null">dic_sort=#{dicSort},</if>
</set>
where dic_key=#{dicKey} and dic_type=#{dicType}
</update>
</mapper>
6. pojo(差点忘了)
package com.bonc.industry.admin.pojo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 系统管理-参数表
Data和Accessors是lombok的注解,可以了解一下,在pom里加上就好,可以省去get,set
* @author mxy
* @since 2020/06/03
*/
@Data
@Accessors(chain = true)
public class ConfigDic implements Serializable {
private static final long serialVersionUID=1L;
/**
* 主键id 主键uuid
*/
private String id;
/**
* 字典类型 字典类型
*/
private String dicType;
/**
* 字典key 字典key
*/
private String dicKey;
/**
* 字典值 字典值
*/
private String dicValue;
/**
* 描述 描述字段
*/
private String dicDesc;
/**
* 描述 描述字段
*/
private String dicRemark;
/**
* 排序字段、默认为0
*/
private Integer dicSort;
}
四、其他地方如何使用?
// 使用样例
SingletonConfigDic.getInstance().getMap("dicType").get("dicKey")
// 使用样例
SingletonConfigDic.getInstance().getList("dicType")