Detailed explanation of Spring Boot using system parameter table to improve system flexibility

  • 2021-10-15 10:46:50
  • OfStack

Directory 1. Benefits of using system parameter table 2. Table structure of system parameter table 3. Use of system parameter table in project 3.1, Entity class 3.2, Dao class 3.3, Service class 3.4, ServiceImpl class 3.5, global configuration service class 3.6, loading 3.7 at startup, accessing system parameters in service implementation class

1. Benefits of using system parameter tables

A system parameter table stored as a database table is more flexible than a configuration file (. properties file or. yaml file) because it can be dynamically updated without restarting the system.

The system parameter table can be used to store the following data:

Table field enumeration values, such as the following fields:


`question_type`   TINYINT(4)   NOT NULL DEFAULT 0 COMMENT ' Question type, 1- Single-choice questions, 2- Multiple-choice questions, 3- Question and answer ',

There are three kinds of values for this field now, but it is difficult to guarantee the possibility of expansion in the future, such as true or false questions, calculation questions, application questions and so on.

Therefore, the enumerated values of the values are configured with the system parameter table, which can improve the flexibility of system expansion.

On the other hand, for the front end, it is possible to query the system parameter table data for UI rendering without hard coding. If the front end needs to use a drop-down box to display all possible "questions", this list can be obtained by querying the system parameter table.

Therefore, all field enumeration values can be included in the system parameter table management.

Parameter settings, such as mail parameters, docking URL of the third party system, etc.

2. Table structure of system parameter table

The table structure of the system parameter table is as follows:


DROP TABLE IF EXISTS `sys_parameters`;
CREATE TABLE `sys_parameters`
(
  `class_id`      INT(11)      NOT NULL DEFAULT 0 COMMENT ' Parameter class id',
  `class_key`     VARCHAR(60)  NOT NULL DEFAULT '' COMMENT ' Parameter class key',
  `class_name`    VARCHAR(60)  NOT NULL DEFAULT '' COMMENT ' Parameter large class name ',
  `item_id`       INT(11)      NOT NULL DEFAULT 0 COMMENT ' Sub-item of parameter large class id',
  `item_key`      VARCHAR(200) NOT NULL DEFAULT '' COMMENT ' Subitem key',
  `item_value`    VARCHAR(200) NOT NULL DEFAULT '' COMMENT ' Subitem value ',
  `item_desc`     VARCHAR(512) NOT NULL DEFAULT '' COMMENT ' Subitem description ',

  --  Record operation information 
  `login_name` VARCHAR(80)  NOT NULL DEFAULT '' COMMENT ' Operator account number ',
  `delete_flag`   TINYINT(4)   NOT NULL DEFAULT 0 COMMENT ' Record deletion marks, 1- Deleted ',
  `create_time`   DATETIME  NOT NULL DEFAULT NOW() COMMENT ' Creation time ',
  `update_time`   DATETIME           DEFAULT NULL ON UPDATE NOW() COMMENT ' Update time ',
  PRIMARY KEY (`class_id`, `item_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT ' System parameter table ';

Description:

The class_id field simply ensures that a large class of parameters, such as an enumeration field name, uses only one value. class_key and item_key are used automatically to improve the readability of recorded data and code. class_key1 generally can take the field name, but if the same name occurs, it needs to be modified to ensure that different tables have the same name field and use different class_key. For enumeration value types, item_key can take the same value as item_id, but the data types are different. This item_key is converted into an integer, which is the value of the corresponding field.

Data 1 for this table can generally be provided by the developer, including initial or variant SQL scripts, executed by DBA, and the project does not need to maintain this development interface.

Here is an initial script example:


INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)
VALUES (11, 'receive_flag', ' SMS receiving flag ', 0, '0', ' Not received ', '');
INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)
VALUES (11, 'receive_flag', ' SMS receiving flag ', 1, '1', ' Received ', '');
INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)
VALUES (11, 'receive_flag', ' SMS receiving flag ', 2, '2', ' Send failed ', '');

INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)
VALUES (12, 'question_type', ' Question type ', 1, '1', ' Single-choice question ', '');
INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)
VALUES (12, 'question_type', ' Question type ', 2, '2', ' Multiple choice ', '');
INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)
VALUES (12, 'question_type', ' Question type ', 3, '3', ' Question and answer ', '');

INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)
VALUES (101, 'url_param', 'URL Parameter ', 0, 'url_prefix', 'http://questinvest.abc.com:8880', 'url Prefix part ');
INSERT INTO sys_parameters(class_id, class_key, class_name, item_id, item_key, item_value, item_desc)
VALUES (101, 'url_param', 'URL Parameter ', 1, 'url_action', '/questInvest/show', ' Request interface method ');

3. Use of system parameter table in project

In the Spring Boot project, System Parameter Table 1 generally only needs to be loaded once at application startup, and provides an update interface to allow administrators to update data. How to use it is described in detail below.

3.1, Entity class

First, define the entity class of the system parameter table. The entity class is SysParameter, and the code is as follows:


package com.abc.questInvest.entity;

import javax.persistence.Column;

import lombok.Data;

/**
 * @className	: SysParameter
 * @description	:  System parameter information object class 
 *
 */
@Data
public class SysParameter {
	// Parameter class id
	@Column(name = "class_id")
	private Integer classId;
	
	// Parameter class key
	@Column(name = "class_key")
	private String classKey;

	// Parameter large class name 
	@Column(name = "class_name")
	private String className;
	
	// Subitem id
	@Column(name = "item_id")
	private Integer itemId;	
		
	// Subitem key
	@Column(name = "item_key")
	private String itemKey;	
	
	// Subitem value 
	@Column(name = "item_value")
	private String itemValue;	

	// Subitem description 
	@Column(name = "item_desc")
	private String itemDesc;	

	//======== Record operation information ================
    //  Name of operator 
    @Column(name = "login_name")
    private String loginName;   
    
    //  Record deletion mark, keep 
    @Column(name = "delete_flag")
    private Byte deleteFlag;    

    //  Creation time 
    @Column(name = "create_time")
    private Date createTime;

    //  Update time 
    @Column(name = "update_time")
    private Date updateTime;	
}

3.2. Class Dao

The data access class is SysParameterDao, and the code is as follows:


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 Table data access class 
 *
 */
@Mapper
public interface SysParameterDao {

	// To query all system parameters, press class_id,item_id Sort 
	@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 class, using Mybatis, just provide the query interface, because the modification is executed in the background of the database. Of course, if the project side thinks it is necessary to provide an interface to maintain the table, it can add the interface of the corresponding CRUD.

3.3. Class Service

The service interface class is SysParameterService, and the code is as follows:


package com.abc.questInvest.service;

import java.util.List;

import com.abc.questInvest.entity.SysParameter;

/**
 * @className	: SysParameterService
 * @description	:  System parameter data service 
 *
 */
public interface SysParameterService {

	/**
	 * 
	 * @methodName		: loadData
	 * @description		:  Load data in the database, allowing repeated calls 
	 * @return			:  Successful return true Otherwise, return false . 
	 *
	 */	
	public boolean loadData();
	
	/**
	 * 
	 * @methodName		: getParameterClass
	 * @description		:  Gets the specified classKey List of subitems of the parameter category of 
	 * @param classKey	:  Parameter category key
	 * @return			:  Specify classKey List of subitems of the parameter category of 
	 *
	 */
	public List<SysParameter> getParameterClass(String classKey);
	
	/**
	 * 
	 * @methodName		: getParameterItemByKey
	 * @description		:  According to classKey And itemKey Get parameter subitems 
	 * @param classKey	:  Parameter category key
	 * @param itemKey	:  Subitem key
	 * @return			: SysParameter Object 
	 *
	 */
	public SysParameter getParameterItemByKey(String classKey,String itemKey);
	
	/**
	 * 
	 * @methodName		: getParameterItemByValue
	 * @description		:  According to classKey And itemValue Get parameter subitems 
	 * @param classKey	:  Parameter category key	
	 * @param itemValue	:  Subitem value 
	 * @return			: SysParameter Object 
	 *
	 */
	public SysParameter getParameterItemByValue(String classKey,String itemValue);
}

The SysParameterService class defines the following interface methods:

The loadData method is used to initially load data and update data. The getParameterClass method that gets a list of all the children of the category that specifies the classKey. This method will be called very frequently. The getParameterItemByKey method, based on classKey and itemKey, gets parameter subentries to display physical meanings based on enumerated values. This method will be called very frequently. The getParameterItemByValue method, which obtains parameter subentries based on classKey and itemValue to obtain enumerated values based on their physical meanings. This method will be called very frequently.

3.4, ServiceImpl Class

The service implementation class is SysParameterServiceImpl, and the code is as follows:


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 Implementation class 
 * @summary		:  Realize the management of system parameters 
 *
 */
@Slf4j
@Service
public class SysParameterServiceImpl implements SysParameterService{
	//sys_parameters Table data access object 
	@Autowired
	private SysParameterDao sysParameterDao;
	
	// Manage all SysParameter Table record 
	private Map<String,Map<String,SysParameter>> sysParameterMap = new HashMap<String,Map<String,SysParameter>>();
	
	/**
	 * 
	 * @methodName		: loadData
	 * @description		:  Load data in a database  
	 * @return			:  Successful return true Otherwise, return false . 
	 *
	 */	
	@Override
	public boolean loadData() {
		try
		{
			// Query sys_parameters Table to get all the data 
			List<SysParameter> sysParameterList = sysParameterDao.selectAll();
			
			synchronized(sysParameterMap) {
				// Empty first map Which is easy to refresh the call 
				sysParameterMap.clear();
				// Put the query results into the map Object, organized by each category 
				for(SysParameter item : sysParameterList) {
					String classKey = item.getClassKey();
					String itemKey = item.getItemKey();
					Map<String,SysParameter> sysParameterClassMap = null;
					if (sysParameterMap.containsKey(classKey)) {
						// Gets the object if the class exists 
						sysParameterClassMap = sysParameterMap.get(classKey);
					}else {
						// If the category does not exist, create a 
						sysParameterClassMap = new HashMap<String,SysParameter>();
						// Join map Medium 
						sysParameterMap.put(classKey, sysParameterClassMap);
					}
					sysParameterClassMap.put(itemKey,item);
				}
			}
		}catch(Exception e) {
			log.error(e.getMessage());
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * 
	 * @methodName		: getParameterClass
	 * @description		:  Gets the specified classKey List of subitems of the parameter category of 
	 * @param classKey	:  Parameter category key
	 * @return			:  Specify classKey List of subitems of the parameter category of 
	 *
	 */
	@Override
	public List<SysParameter> getParameterClass(String classKey){
		List<SysParameter> sysParameterList = new ArrayList<SysParameter>();
		
		// Get classKey Corresponding sub map Add all subitems to the list 
		if (sysParameterMap.containsKey(classKey)) {
			Map<String,SysParameter> sysParameterClassMap = sysParameterMap.get(classKey);
			for(SysParameter item : sysParameterClassMap.values()) {
				sysParameterList.add(item);
			}
		}
		
		return sysParameterList;
	}
	
	/**
	 * 
	 * @methodName		: getParameterItemByKey
	 * @description		:  According to classKey And itemKey Get parameter subitems 
	 * @param classKey	:  Parameter category key
	 * @param itemKey	:  Subitem key
	 * @return			: SysParameter Object 
	 *
	 */
	@Override
	public SysParameter getParameterItemByKey(String classKey,String itemKey) {
		SysParameter sysParameter = null;
		
		if (sysParameterMap.containsKey(classKey)) {
			// If classKey Existence 
			Map<String,SysParameter> sysParameterClassMap = sysParameterMap.get(classKey);
			if (sysParameterClassMap.containsKey(itemKey)) {
				// If itemKey Existence 
				sysParameter = sysParameterClassMap.get(itemKey);
			}
		}
		
		return sysParameter;
	}
	
	/**
	 * 
	 * @methodName		: getParameterItemByValue
	 * @description		:  According to classKey And itemValue Get parameter subitems 
	 * @param classKey	:  Parameter category key	
	 * @param itemValue	:  Subitem value 
	 * @return			: SysParameter Object 
	 *
	 */
	@Override
	public SysParameter getParameterItemByValue(String classKey,String itemValue) {
		SysParameter sysParameter = null;
		
		if (sysParameterMap.containsKey(classKey)) {
			// If classKey Existence 
			Map<String,SysParameter> sysParameterClassMap = sysParameterMap.get(classKey);
			// Traversal 
			for (Map.Entry<String,SysParameter> item : sysParameterClassMap.entrySet()) {
				if(item.getValue().getItemValue().equals(itemValue)) {
					// If the matching value 
					sysParameter = item.getValue();
					break;
				}
			}
		}
		
		return sysParameter;
		
	}
}

The SysParameterServiceImpl class uses Map < String,Map < String,SysParameter > > The attribute variable sysParameterMap of type manages all system parameters, and the outer Map manages classKey through Map < String,SysParameter > Each item is a parameter category, while the inner layer Map < String,SysParameter > Used to manage the mapping relationship between itemKey and SysParameter, with each item being a subitem under the category. The purpose of using the sysParameterMap property is to load all system parameters into memory without frequent database access.

loadData method for initial loading of data and updating of data, in order to prevent dirty reading of data, added synchronization lock. This method is called infrequently.

3.5. Global Configuration of Service Classes

The Global Configuration Service class is used to manage global configuration parameters, including system parameters, permission trees, and so on. If there is only one parameter, it is unnecessary to have this class, because it adds one shell.

The service interface class is GlobalConfigService, and the code is as follows:


package com.abc.questInvest.service;

/**
 * @className	: GlobalConfigService
 * @description	:  Global variable management class 
 *
 */
public interface GlobalConfigService {
	
	/**
	 * 
	 * @methodName		: loadData
	 * @description		:  Load data  
	 * @return			:  Successful return true Otherwise, return false
	 *
	 */
	public boolean loadData();
	
	
	// Get SysParameterService Object 
	public SysParameterService getSysParameterService();
	
	// Get other configuration data service objects 
	//public FunctionTreeService getFunctionTreeService();
}

GlobalConfigService provides the following interface methods:

An loadData method loads configuration object data and determines a loading order of a plurality of configuration objects. getSysParameterService method to get the system parameter service class object. Gets other possible ways to configure service objects.

The service implementation class is GlobalConfigServiceImpl, and the code is as follows:


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 Implementation class 
 *
 */
@Service
public class GlobalConfigServiceImpl implements GlobalConfigService{
		
	// System parameter table data service object 
	@Autowired
	private SysParameterService sysParameterService;
	
	// Other Configuration Data Service Objects 
	
	/**
	 * 
	 * @methodName		: loadData
	 * @description		:  Load data  
	 * @return			:  Successful return true Otherwise, return false
	 *
	 */
	@Override
	public boolean loadData() {
		boolean bRet = false;
				
		// Loading sys_parameters Table record 
		bRet = sysParameterService.loadData();
		if (!bRet) {
			return bRet;
		}
		
		// Load additional configuration data 
				
		return bRet;
	}
	
	
	// Get SysParameterService Object 
	@Override
	public SysParameterService getSysParameterService() {
		return sysParameterService;
	}
	
	// Get other configuration data service object methods 
	
}

3.6. Load at Startup

The global configuration service class is loaded into the Spring container when the application starts, which can realize sharing and reduce the access pressure to the database.

Implement an ApplicationListener class with the following code:


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	:  Application listener 
 *
 */
@Component
public class ApplicationStartup implements ApplicationListener<ContextRefreshedEvent>{
    // Global variable management object, which cannot be automatically injected here 
    private GlobalConfigService globalConfigService = null;
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        try {
    	    if(contextRefreshedEvent.getApplicationContext().getParent() == null){ 
    	    	//root application context  No parent.
				
    	    	System.out.println("======== Define global variables ==================");
    	    	//  Will  ApplicationContext  Convert to  WebApplicationContext
    	        WebApplicationContext webApplicationContext =
    	                (WebApplicationContext)contextRefreshedEvent.getApplicationContext();
    	        //  From  webApplicationContext  Get from   servletContext
    	        ServletContext servletContext = webApplicationContext.getServletContext();
    	        
    	        // Loading global variable management objects 
    	        globalConfigService = (GlobalConfigService)webApplicationContext.getBean(GlobalConfigService.class);
    	        // Load data 
    	        boolean bRet = globalConfigService.loadData();
    	        if (false == bRet) {
    	        	System.out.println(" Failed to load global variable ");
    	        	return;
    	        }        
    	        //======================================================================
    	        // servletContext Setting value 
    	        servletContext.setAttribute("GLOBAL_CONFIG_SERVICE", globalConfigService);  
    	        
    	    }
    	} catch (Exception e) {
    	    e.printStackTrace();
    	}        
    }
}

Note that globalConfigService cannot be injected automatically, otherwise a null pointer will be obtained. Load bean with the following code.


DROP TABLE IF EXISTS `sys_parameters`;
CREATE TABLE `sys_parameters`
(
  `class_id`      INT(11)      NOT NULL DEFAULT 0 COMMENT ' Parameter class id',
  `class_key`     VARCHAR(60)  NOT NULL DEFAULT '' COMMENT ' Parameter class key',
  `class_name`    VARCHAR(60)  NOT NULL DEFAULT '' COMMENT ' Parameter large class name ',
  `item_id`       INT(11)      NOT NULL DEFAULT 0 COMMENT ' Sub-item of parameter large class id',
  `item_key`      VARCHAR(200) NOT NULL DEFAULT '' COMMENT ' Subitem key',
  `item_value`    VARCHAR(200) NOT NULL DEFAULT '' COMMENT ' Subitem value ',
  `item_desc`     VARCHAR(512) NOT NULL DEFAULT '' COMMENT ' Subitem description ',

  --  Record operation information 
  `login_name` VARCHAR(80)  NOT NULL DEFAULT '' COMMENT ' Operator account number ',
  `delete_flag`   TINYINT(4)   NOT NULL DEFAULT 0 COMMENT ' Record deletion marks, 1- Deleted ',
  `create_time`   DATETIME  NOT NULL DEFAULT NOW() COMMENT ' Creation time ',
  `update_time`   DATETIME           DEFAULT NULL ON UPDATE NOW() COMMENT ' Update time ',
  PRIMARY KEY (`class_id`, `item_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT ' System parameter table ';
0

In the code, the globalConfigService object as a global variable to join the ServletContext, you can achieve sharing.

In the startup class, add the application listener ApplicationStartup.


DROP TABLE IF EXISTS `sys_parameters`;
CREATE TABLE `sys_parameters`
(
  `class_id`      INT(11)      NOT NULL DEFAULT 0 COMMENT ' Parameter class id',
  `class_key`     VARCHAR(60)  NOT NULL DEFAULT '' COMMENT ' Parameter class key',
  `class_name`    VARCHAR(60)  NOT NULL DEFAULT '' COMMENT ' Parameter large class name ',
  `item_id`       INT(11)      NOT NULL DEFAULT 0 COMMENT ' Sub-item of parameter large class id',
  `item_key`      VARCHAR(200) NOT NULL DEFAULT '' COMMENT ' Subitem key',
  `item_value`    VARCHAR(200) NOT NULL DEFAULT '' COMMENT ' Subitem value ',
  `item_desc`     VARCHAR(512) NOT NULL DEFAULT '' COMMENT ' Subitem description ',

  --  Record operation information 
  `login_name` VARCHAR(80)  NOT NULL DEFAULT '' COMMENT ' Operator account number ',
  `delete_flag`   TINYINT(4)   NOT NULL DEFAULT 0 COMMENT ' Record deletion marks, 1- Deleted ',
  `create_time`   DATETIME  NOT NULL DEFAULT NOW() COMMENT ' Creation time ',
  `update_time`   DATETIME           DEFAULT NULL ON UPDATE NOW() COMMENT ' Update time ',
  PRIMARY KEY (`class_id`, `item_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT ' System parameter table ';
1

3.7. Access system parameters in the service implementation class

The HttpServletRequest type object request is available in the controller method and can be passed as a parameter into the method of the service implementation class. The following is sample code for the service implementation class to access system parameters:


DROP TABLE IF EXISTS `sys_parameters`;
CREATE TABLE `sys_parameters`
(
  `class_id`      INT(11)      NOT NULL DEFAULT 0 COMMENT ' Parameter class id',
  `class_key`     VARCHAR(60)  NOT NULL DEFAULT '' COMMENT ' Parameter class key',
  `class_name`    VARCHAR(60)  NOT NULL DEFAULT '' COMMENT ' Parameter large class name ',
  `item_id`       INT(11)      NOT NULL DEFAULT 0 COMMENT ' Sub-item of parameter large class id',
  `item_key`      VARCHAR(200) NOT NULL DEFAULT '' COMMENT ' Subitem key',
  `item_value`    VARCHAR(200) NOT NULL DEFAULT '' COMMENT ' Subitem value ',
  `item_desc`     VARCHAR(512) NOT NULL DEFAULT '' COMMENT ' Subitem description ',

  --  Record operation information 
  `login_name` VARCHAR(80)  NOT NULL DEFAULT '' COMMENT ' Operator account number ',
  `delete_flag`   TINYINT(4)   NOT NULL DEFAULT 0 COMMENT ' Record deletion marks, 1- Deleted ',
  `create_time`   DATETIME  NOT NULL DEFAULT NOW() COMMENT ' Creation time ',
  `update_time`   DATETIME           DEFAULT NULL ON UPDATE NOW() COMMENT ' Update time ',
  PRIMARY KEY (`class_id`, `item_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT ' System parameter table ';
2

The above is the detailed explanation of Spring Boot using system parameter table to improve the flexibility of the system. For more information about Spring Boot using system parameter table to improve the flexibility of the system, please pay attention to other related articles on this site!


Related articles: