详解Spring Boot使用系统参数表提升系统的灵活性

网友投稿 216 2023-01-01

详解Spring Boot使用系统参数表提升系统的灵活性

目录一、使用系统参数表的好处二、系统参数表的表结构三、系统参数表在项目中的使用3.1、Entity类3.2、Dao类3.3、Service类3.4、ServiceImpl类3.5、全局配置服务类3.6、启动时加载3.7、在服务实现类中访问系统参数

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

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

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

表字段枚举值,如下列字段:

`question_type` TINYINT(4) NOT NULL DEFAULT 0 COMMENT '题型,1-单选题,2-多选题,3-问答题',

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

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

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

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

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

二、系统参数表的表结构

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

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', '请求接口方法');

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

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

3.1、Entity类

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

package com.abc.questInvest.entity;

import javax.persistence.Column;

import lombok.Datahttp://;

/**

* @className : SysParameter

* @description : 系统参数信息对象类

*

*/

@Data

public 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表数据访问类

*

*/

@Mapper

public 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 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 : gethttp://ParameterClass

* @description : 获取指定classKey的参数类别的子项列表

* @param classKey : 参数类别key

* @return : 指定classKey的参数类别的子项列表

*

*/

public List 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

@Service

public class SysParameterServiceImpl implements SysParameterService{

//sys_parameters表数据访问对象

@Autowired

private SysParameterDao sysParameterDao;

//管理全部的SysParameter表记录

private Map> sysParameterMap = new HashMap>();

/**

*

* @methodName : loadData

* @description : 加载数据库中数据

* @return : 成功返回true,否则返回false。

*

*/

@Override

public boolean loadData() {

try

{

//查询sys_parameters表,获取全部数据

List sysParameterList = sysParameterDao.selectAll();

synchronized(sysParameterMap) {

//先清空map,便于刷新调用

sysParameterMap.clear();

//将查询结果放入map对象中,按每个类别组织

for(SysParameter item : sysParameterList) {

String classKey = item.getClassKey();

String itemKey = item.getItemKey();

Map sysParameterClassMap = null;

if (sysParameterMap.containsKey(classKey)) {

//如果存在该类别,则获取对象

sysParameterClassMap = sysParameterMap.get(classKey);

}else {

//如果不存在该类别,则创建

sysParameterClassMap = new HashMap();

//加入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 getParameterClass(String classKey){

List sysParameterList = new ArrayList();

//获取classKey对应的子map,将所有子项加入列表中

if (sysParameterMap.containsKey(classKey)) {

Map 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 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 sysParameterClassMap = sysParameterMap.get(classKey);

//遍历

for (Map.Entry item : sysParameterClassMap.entrySet()) {

if(item.getValue().getItemValue().equals(itemValue)) {

//如果匹配值

sysParameter = item.getValue();

break;

}

}

}

return sysParameter;

}

}

​SysParameterServiceImpl类使用了Map>类型的属性变量sysParameterMap来管理全部的系统参数,外层MozUKOap管理classKey到Map的映射关系,每一项为一个参数类别,而里层Map,用于管理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实现类

*

*/

@Service

public 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 : 应用侦听器

*

*/

@Component

public class ApplicationStartup implements ApplicationListener{

//全局变量管理对象,此处不能自动注入

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();

}

以上就是详解Spring Boot使用系统参数表提升系统的灵活性的详细内容,更多关于Spring Boot使用系统参数表提升系统的灵活性的资料请关注我们其它相关文章!

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java并发编程必备之Future机制
下一篇:云南速通快递物流查询单号(云南全运通物流单号查询)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~