2021-06-21

使用系统参数表,提升系统的灵活性

用好系统参数表,并实现共享,提高系统的灵活性。

1、使用系统参数表的好处

​ Spring Boot项目中常有一些相对稳定的参数设置项,其作用范围是系统级的或模块级的,这些参数称为系统参数。这些变量以参数形式进行配置,从而提高变动和扩展的灵活性,保持代码的稳定性。

​ 以数据库表形式存储的系统参数表比配置文件(.properties文件或.yaml文件)要更灵活,因为无需重启系统就可以动态更新。

​ 系统参数表可用于存储下列数据:

  • 表字段枚举值,如下列字段:
`question_type` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '题型,1-单选题,2-多选题,3-问答题',

​ 这个字段现在有3种取值,但是难保将来有扩展的可能,如:是非题、计算题、应用题等。

​ 因此将取值的枚举值用系统参数表来配置,可以提高系统扩展灵活性。

​ 另一方面,对于前端而言,就可以通过查询系统参数表数据,用于UI呈现,而不必硬编码。如前端需要用下拉框来显示所有可能的"题型",这个列表就可以查询系统参数表来获取。

​ 因此可以将所有字段枚举值纳入系统参数表管理。

  • 参数设置,如邮件参数,对接的第三方系统的URL等。

2、系统参数表的表结构

​ 系统参数表的表结构如下:

DROP TABLE IF EXISTS `sys_parameters`;CREATE TABLE `sys_parameters`( `class_id`  INT(11)  NOT NULL DEFAULT 0 COMMENT '参数大类id', `class_key`  VARCHAR(60) NOT NULL DEFAULT '' COMMENT '参数大类key', `class_name` VARCHAR(60) NOT NULL DEFAULT '' COMMENT '参数大类名称', `item_id`  INT(11)  NOT NULL DEFAULT 0 COMMENT '参数大类下子项id', `item_key`  VARCHAR(200) NOT NULL DEFAULT '' COMMENT '子项key', `item_value` VARCHAR(200) NOT NULL DEFAULT '' COMMENT '子项值', `item_desc`  VARCHAR(512) NOT NULL DEFAULT '' COMMENT '子项描述', -- 记录操作信息 `login_name` VARCHAR(80) NOT NULL DEFAULT '' COMMENT '操作人账号', `delete_flag` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '记录删除标记,1-已删除', `create_time` DATETIME NOT NULL DEFAULT NOW() COMMENT '创建时间', `update_time` DATETIME   DEFAULT NULL ON UPDATE NOW() COMMENT '更新时间', PRIMARY KEY (`class_id`, `item_id`)) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT '系统参数表';

​ 说明:

​ class_id字段只要确保一个参数大类(如一个枚举字段名)使用唯一值。使用class_key和item_key自动,便于提高记录数据和代码的可读性。class_key一般可以取字段名,但如果发生同名时,需要修改,确保不同表的同名字段,使用不同的class_key。对于枚举值类型,item_key可以取item_id相同的值,只是数据类型不同,此item_key转换成整型数,就是对应字段的值。

​ 这个表的数据一般可以由开发人员提供,包括初始或变动的SQL脚本,由DBA执行,项目无需为此开发界面来维护。

​ 下面是初始脚本示例:

INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)VALUES (11, 'receive_flag', '短信接收标志', 0, '0', '未接收', '');INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)VALUES (11, 'receive_flag', '短信接收标志', 1, '1', '已接收', '');INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)VALUES (11, 'receive_flag', '短信接收标志', 2, '2', '发送失败', '');INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)VALUES (12, 'question_type', '题型', 1, '1', '单选题', '');INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)VALUES (12, 'question_type', '题型', 2, '2', '多选题', '');INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)VALUES (12, 'question_type', '题型', 3, '3', '问答题', '');INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)VALUES (101, 'url_param', 'URL参数', 0, 'url_prefix', 'http://questinvest.abc.com:8880', 'url前缀部分');INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)VALUES (101, 'url_param', 'URL参数', 1, 'url_action', '/questInvest/show', '请求接口方法');

3、系统参数表在项目中的使用

​ 在Spring Boot项目中,系统参数表一般只需在应用启动时加载一次,并提供更新接口允许管理员来更新数据。下面详细说明使用方法。

3.1、Entity类

​ 先定义系统参数表的实体类,实体类为SysParameter,代码如下:

package com.abc.questInvest.entity;import javax.persistence.Column;import lombok.Data;/** * @className	: SysParameter * @description	: 系统参数信息对象类 * */@Datapublic class SysParameter {	//参数大类id	@Column(name = "class_id")	private Integer classId;		//参数大类key	@Column(name = "class_key")	private String classKey;	//参数大类名称	@Column(name = "class_name")	private String className;		//子项id	@Column(name = "item_id")	private Integer itemId;				//子项key	@Column(name = "item_key")	private String itemKey;			//子项值	@Column(name = "item_value")	private String itemValue;		//子项描述	@Column(name = "item_desc")	private String itemDesc;		//========记录操作信息================ // 操作人姓名 @Column(name = "login_name") private String loginName;   // 记录删除标记,保留 @Column(name = "delete_flag") private Byte deleteFlag;  // 创建时间 @Column(name = "create_time") private Date createTime; // 更新时间 @Column(name = "update_time") private Date updateTime;	}

3.2、Dao类

​ 数据访问类为SysParameterDao,代码如下:

package com.abc.questInvest.dao;import java.util.List;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Select;import com.abc.questInvest.entity.SysParameter;/** * @className	: SysParameterDao * @description	: sys_parameters表数据访问类 * */@Mapperpublic interface SysParameterDao {	//查询所有系统参数,按class_id,item_id排序	@Select("SELECT class_id,class_key,class_name,item_id,item_key,item_value,item_desc"			+ " FROM sys_parameters WHERE delete_flag = 0" 			+ " ORDER BY class_id,item_id") List<SysParameter> selectAll();}

​ SysParameterDao类,使用Mybatis,只需提供查询接口就行了,因为修改在数据库后台执行了。当然如果项目方认为有必要提供界面来维护该表,则可增加相应CRUD的接口。

3.3、Service类

​ 服务接口类为SysParameterService,代码如下:

package com.abc.questInvest.service;import java.util.List;import com.abc.questInvest.entity.SysParameter;/** * @className	: SysParameterService * @description	: 系统参数数据服务 * */public interface SysParameterService {	/**	 * 	 * @methodName		: loadData	 * @description		: 加载数据库中数据,允许重复调用	 * @return			: 成功返回true,否则返回false。	 *	 */		public boolean loadData();		/**	 * 	 * @methodName		: getParameterClass	 * @description		: 获取指定classKey的参数类别的子项列表	 * @param classKey	: 参数类别key	 * @return			: 指定classKey的参数类别的子项列表	 * @history		:	 * ------------------------------------------------------------------------------	 * date			version		modifier		remarks     	 * ------------------------------------------------------------------------------	 * 2021/06/02	1.0.0		sheng.zheng		初版	 *	 */	public List<SysParameter> getParameterClass(String classKey);		/**	 * 	 * @methodName		: getParameterItemByKey	 * @description		: 根据classKey和itemKey获取参数子项	 * @param classKey	: 参数类别key	 * @param itemKey	: 子项key	 * @return			: SysParameter对象	 *	 */	public SysParameter getParameterItemByKey(String classKey,String itemKey);		/**	 * 	 * @methodName		: getParameterItemByValue	 * @description		: 根据classKey和itemValue获取参数子项	 * @param classKey	: 参数类别key		 * @param itemValue	: 子项值	 * @return			: SysParameter对象	 *	 */	public SysParameter getParameterItemByValue(String classKey,String itemValue);}

​ SysParameterService类定义了下列接口方法:

  • loadData方法,用于初始加载数据和更新数据。
  • getParameterClass方法,获取指定classKey的类别的所有子项列表。此方法调用会非常频繁。
  • getParameterItemByKey方法,根据classKey和itemKey获取参数子项,用于根据枚举值显示物理含义。此方法调用会非常频繁。
  • getParameterItemByValue方法,根据classKey和itemValue获取参数子项,用于根据物理含义取得枚举值。此方法调用会非常频繁。

3.4、ServiceImpl类

​ 服务实现类为SysParameterServiceImpl,代码如下:

package com.abc.questInvest.service.impl;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.abc.questInvest.dao.SysParameterDao;import com.abc.questInvest.entity.SysParameter;import com.abc.questInvest.service.SysParameterService;import lombok.extern.slf4j.Slf4j;/** * @className	: SysParameterServiceImpl * @description	: SysParameterService实现类 * @summary		: 实现对系统参数的管理 * */@Slf4j@Servicepublic class SysParameterServiceImpl implements SysParameterService{	//sys_parameters表数据访问对象	@Autowired	private SysParameterDao sysParameterDao;		//管理全部的SysParameter表记录	private Map<String,Map<String,SysParameter>> sysParameterMap = new HashMap<String,Map<String,SysParameter>>();		/**	 * 	 * @methodName		: loadData	 * @description		: 加载数据库中数据 	 * @return			: 成功返回true,否则返回false。	 *	 */		@Override	public boolean loadData() {		try		{			//查询sys_parameters表,获取全部数据			List<SysParameter> sysParameterList = sysParameterDao.selectAll();						synchronized(sysParameterMap) {				//先清空map,便于刷新调用				sysParameterMap.clear();				//将查询结果放入map对象中,按每个类别组织				for(SysParameter item : sysParameterList) {					String classKey = item.getClassKey();					String itemKey = item.getItemKey();					Map<String,SysParameter> sysParameterClassMap = null;					if (sysParameterMap.containsKey(classKey)) {						//如果存在该类别,则获取对象						sysParameterClassMap = sysParameterMap.get(classKey);					}else {						//如果不存在该类别,则创建						sysParameterClassMap = new HashMap<String,SysParameter>();						//加入map中						sysParameterMap.put(classKey, sysParameterClassMap);					}					sysParameterClassMap.put(itemKey,item);				}			}		}catch(Exception e) {			log.error(e.getMessage());			e.printStackTrace();			return false;		}		return true;	}		/**	 * 	 * @methodName		: getParameterClass	 * @description		: 获取指定classKey的参数类别的子项列表	 * @param classKey	: 参数类别key	 * @return			: 指定classKey的参数类别的子项列表	 *	 */	@Override	public List<SysParameter> getParameterClass(String classKey){		List<SysParameter> sysParameterList = new ArrayList<SysParameter>();				//获取classKey对应的子map,将所有子项加入列表中		if (sysParameterMap.containsKey(classKey)) {			Map<String,SysParameter> sysParameterClassMap = sysParameterMap.get(classKey);			for(SysParameter item : sysParameterClassMap.values()) {				sysParameterList.add(item);			}		}				return sysParameterList;	}		/**	 * 	 * @methodName		: getParameterItemByKey	 * @description		: 根据classKey和itemKey获取参数子项	 * @param classKey	: 参数类别key	 * @param itemKey	: 子项key	 * @return			: SysParameter对象	 *	 */	@Override	public SysParameter getParameterItemByKey(String classKey,String itemKey) {		SysParameter sysParameter = null;				if (sysParameterMap.containsKey(classKey)) {			//如果classKey存在			Map<String,SysParameter> sysParameterClassMap = sysParameterMap.get(classKey);			if (sysParameterClassMap.containsKey(itemKey)) {				//如果itemKey存在				sysParameter = sysParameterClassMap.get(itemKey);			}		}				return sysParameter;	}		/**	 * 	 * @methodName		: getParameterItemByValue	 * @description		: 根据classKey和itemValue获取参数子项	 * @param classKey	: 参数类别key		 * @param itemValue	: 子项值	 * @return			: SysParameter对象	 *	 */	@Override	public SysParameter getParameterItemByValue(String classKey,String itemValue) {		SysParameter sysParameter = null;				if (sysParameterMap.containsKey(classKey)) {			//如果classKey存在			Map<String,SysParameter> sysParameterClassMap = sysParameterMap.get(classKey);			//遍历			for (Map.Entry<String,SysParameter> item : sysParameterClassMap.entrySet()) {				if(item.getValue().getItemValue().equals(itemValue)) {					//如果匹配值					sysParameter = item.getValue();					break;				}			}		}				return sysParameter;			}}

​ SysParameterServiceImpl类使用了Map<String,Map<String,SysParameter>>类型的属性变量sysParameterMap来管理全部的系统参数,外层Map管理classKey到Map<String,SysParameter>的映射关系,每一项为一个参数类别,而里层Map<String,SysParameter>,用于管理itemKey与SysParameter之间的映射关系,每一项为该类别下的一个子项。使用sysParameterMap属性的目的,是将所有系统参数都加载到内存中,从而无需频繁访问数据库。

​ loadData方法,用于初始加载数据和更新时刷新数据,为了防止更新时脏读数据,加了同步锁。这个方法调用不频繁。

3.5、全局配置服务类

​ 全局配置服务类用于管理全局配置参数,包括系统参数、权限树等。如果只有一种参数,可以不必有此类,因为这样加了一层壳。

​ 服务接口类为GlobalConfigService,代码如下:

package com.abc.questInvest.service;/** * @className	: GlobalConfigService * @description	: 全局变量管理类 * */public interface GlobalConfigService {		/**	 * 	 * @methodName		: loadData	 * @description		: 加载数据 	 * @return			: 成功返回true,否则返回false	 *	 */	public boolean loadData();			//获取SysParameterService对象	public SysParameterService getSysParameterService();		//获取其它配置数据服务对象	//public FunctionTreeService getFunctionTreeService();}

​ GlobalConfigService提供了下列接口方法:

  • loadData方法,加载配置对象数据,确定多个配置对象的加载次序。

  • getSysParameterService方法,获取系统参数服务类对象。

  • 获取其它可能的配置服务对象的方法。

​ 服务实现类为GlobalConfigServiceImpl,代码如下:

package com.abc.questInvest.service.impl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.abc.questInvest.service.FunctionTreeService;import com.abc.questInvest.service.GlobalConfigService;import com.abc.questInvest.service.RoleFuncRightsService;import com.abc.questInvest.service.SysParameterService;import com.abc.questInvest.service.TableCodeConfigService;/** * @className	: GlobalConfigServiceImpl * @description	: GlobalConfigService实现类 * */@Servicepublic class GlobalConfigServiceImpl implements GlobalConfigService{			//系统参数表数据服务对象	@Autowired	private SysParameterService sysParameterService;		//其它配置数据服务对象		/**	 * 	 * @methodName		: loadData	 * @description		: 加载数据 	 * @return			: 成功返回true,否则返回false	 *	 */	@Override	public boolean loadData() {		boolean bRet = false;						//加载sys_parameters表记录		bRet = sysParameterService.loadData();		if (!bRet) {			return bRet;		}				//加载其它配置数据						return bRet;	}			//获取SysParameterService对象	@Override	public SysParameterService getSysParameterService() {		return sysParameterService;	}		//获取其它配置数据服务对象方法	}

3.6、启动时加载

​ 全局配置服务类在应用启动时加载到Spring容器中,这样可实现共享,减少对数据库的访问压力。

​ 实现一个ApplicationListener类,代码如下:

package com.abc.questInvest;import javax.servlet.ServletContext;import org.springframework.context.ApplicationListener;import org.springframework.context.event.ContextRefreshedEvent;import org.springframework.stereotype.Component;import org.springframework.web.context.WebApplicationContext;import com.abc.questInvest.service.GlobalConfigService;/** * @className	: ApplicationStartup * @description	: 应用侦听器 * */@Componentpublic class ApplicationStartup implements ApplicationListener<ContextRefreshedEvent>{ //全局变量管理对象,此处不能自动注入 private GlobalConfigService globalConfigService = null;  @Override public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {  try { 	 if(contextRefreshedEvent.getApplicationContext().getParent() == null){  	 	//root application context 没有parent.				 	 	System.out.println("========定义全局变量=================="); 	 	// 将 ApplicationContext 转化为 WebApplicationContext 	  WebApplicationContext webApplicationContext = 	    (WebApplicationContext)contextRefreshedEvent.getApplicationContext(); 	  // 从 webApplicationContext 中获取 servletContext 	  ServletContext servletContext = webApplicationContext.getServletContext(); 	   	  //加载全局变量管理对象 	  globalConfigService = (GlobalConfigService)webApplicationContext.getBean(GlobalConfigService.class); 	  //加载数据 	  boolean bRet = globalConfigService.loadData(); 	  if (false == bRet) { 	  	System.out.println("加载全局变量失败"); 	  	return; 	  }   	  //====================================================================== 	  // servletContext设置值 	  servletContext.setAttribute("GLOBAL_CONFIG_SERVICE", globalConfigService);  	   	 } 	} catch (Exception e) { 	 e.printStackTrace(); 	}   }}

​ 注意,globalConfigService不能自动注入,否则得到空指针。通过下列代码来加载bean。

//加载全局变量管理对象 	  globalConfigService = (GlobalConfigService)webApplicationContext.getBean(GlobalConfigService.class);

​ 代码中,将globalConfigService对象作为全局变量加入ServletContext中,就可以实现共享了。

​ 在启动类中,加入该应用侦听器ApplicationStartup。

	public static void main(String[] args) { 	SpringApplication springApplication = new SpringApplication(QuestInvestApplication.class);  springApplication.addListeners(new ApplicationStartup());  springApplication.run(args); 	}

3.7、在服务实现类中访问系统参数

​ HttpServletRequest类型对象request在控制器方法中可以获取,可作为参数传入服务实现类的方法中。下面是服务实现类访问系统参数的示例代码:

		//获取ServletContext对象		ServletContext servletContext = request.getServletContext();		//获取全部数据服务对象		GlobalConfigService globalConfigService = (GlobalConfigService)servletContext.getAttribute("GLOBAL_CONFIG_SERVICE");		//获取系统参数url_prefix的值		String url_prefix = "";		SysParameter sysParameter = null;		sysParameter = globalConfigService.getSysParameterService()				.getParameterItemByKey("url_param", "url_prefix");		if (sysParameter != null) {			url_prefix = sysParameter.getItemValue();		}








原文转载:http://www.shaoqun.com/a/816627.html

跨境电商:https://www.ikjzd.com/

我想吃你的水蜜桃 一边吃早餐一边做:http://lady.shaoqun.com/a/247933.html

吧深一点老师今晚随你怎么弄 老师今天晚上让你桶个够:http://lady.shaoqun.com/m/a/247574.html

口述小姑两瓣湿乎乎:和姑姑发生了不该发生的关系:http://www.30bags.com/m/a/249622.html

两男一女口述在车里下面被添 女人自述炮约真实经历:http://lady.shaoqun.com/m/a/247996.html


用好系统参数表,并实现共享,提高系统的灵活性。1、使用系统参数表的好处​ SpringBoot项目中常有一些相对稳定的参数设置项,其作用范围是系统级的或模块级的,这些参数称为系统参数。这些变量以参数形式进行配置,从而提高变动和扩展的灵活性,保持代码的稳定性。​ 以数据库表形式存储的系统参数表比配置文件(.properties文件或.yaml文件)要更灵活,因为无需重启系统就可以动态更新。​
广告及促销:https://www.kjyunke.com/courses/492
男人爱㖭女人下边 被㖭下面是什么感觉:http://www.30bags.com/m/a/249751.html
口述实录:少妇实录:邻居用销魂的床技将我征服:http://www.30bags.com/m/a/249951.html
《性福中国蓝皮书》:职场男女中只有37%对"性生活"高度满意:http://www.30bags.com/a/444881.html
数据化管理:https://www.kjyunke.com/courses/494
蓄势沉淀,厚积薄发--跨境电商"两会"告诉你转型之路,敢问路在何方?:https://www.kjyunke.com/courses/496
2021年端午节放假安排时间表:http://www.30bags.com/a/430495.html
班比的屌丝男友求婚记(3/3):http://lady.shaoqun.com/a/64818.html
口述实录:我人生中第二次婚礼,引来了众人的嫉妒:http://lady.shaoqun.com/m/a/256398.html
无耻公公饥渴太久要我给他一次:http://lady.shaoqun.com/a/41187.html
尹涛与六个男人缠绵的情史,其中两个是郝蕾的前夫,李是的前男友:http://www.30bags.com/a/444879.html
芳官和秦钟一夜情?:http://www.30bags.com/a/444880.html

No comments:

Post a Comment