开发环境: IDEA 2022.1.4+ MyBatis
代码参考:
springboot启动后加载字典表数据供业务调用
参考
Spring-boot中的CommandLineRunner的作用 – 简书
https://www.cnblogs.com/yanxiaoguo/p/16167221.html
目录
2.2 新建Runner类实现CommandLineRunner接口
1. 概述
平常做PC端程序时候,在程序启动时候,都会去事先加载数据字典信息,想着SpringBoot也可以实现这块功能,特百度查询资料,可以使用CommandLineRunner来实现。
通过实现CommandLineRunner接口的run方法, 结合@Component、@Order的使用,可以来实现数据加载顺序。对于@Order的value属性(int类型),值越低优先级越高。
2. 实现步骤
效果: 我在服务启动时候,将用户信息加载到缓存中,当使用PostMan来调用获取用户信息时候,从缓存中直接获取.
此处SpringBoot+MyBatis的配置就暂不描述了。
2.1 新建一个缓存类 DictResourceCache
这个类主要有个静态的集合对象cache,
Map<String,List<?>>, key值代表字典名称,List<?>为对应的集合。也就是说,这个Map对象可以缓存多个数据字典的信息。 然后可以根据getDict()方法, 获取特定数据字典信息。
@Slf4j
public class DictResourceCache {
private static UserMapper userMapper;
private static Map<String, List<?>> cache= new HashMap<>();
/**
* 加载字典
*/
public static void load(){
cache.clear();
SqlSession sqlSession= null;
try{
sqlSession= MybatisUtils.getSqlSession();
//userMapper= sqlSession.getMapper(UserMapper.class);
userMapper= SpringUtils.getBean(UserMapper.class);
List<User> listUser= userMapper.getUserList();
cache.put("User", listUser);
} catch (Exception e){
e.printStackTrace();
}
}
/**
* 根据字典名 获取元素列表
* @param dicName
* @return
*/
public static List<?> getDict(String dicName){
List<?> list= cache.get(dicName);
if (CollectionUtils.isEmpty(list)){
return new ArrayList<>();
}
return cache.get(dicName);
}
}
2.2 新建Runner类实现CommandLineRunner接口
这个接口使用了@Component、@Order注解。 重写run()方法,调用缓存类的DictResourceCache的load()方法。
@Slf4j
@Component
@Order(2)
public class DictResourceRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
log.info("加载数据字典...");
DictResourceCache.load();
log.info("加载完毕...");
}
}
2.3 定义工具类 SpringUtils
这个我看的半明白, 与BeanFactory有关。通过@Component注解,将该类交由Spring管理.
@Component
public class SpringUtils implements BeanFactoryPostProcessor {
/**
* Spring应用上下文环境
*/
private static ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
SpringUtils.beanFactory= configurableListableBeanFactory;
}
public static <T> T getBean(String name) throws BeansException{
name= lowerCaseInit(name);
if(containsBean(name)){
return (T) beanFactory.getBean(name);
} else{
return null;
}
}
/**
* 获取
* @param cls
* @return
* @param <T>
* @throws BeansException
*/
public static <T> T getBean(Class<T> cls) throws BeansException{
T result= (T) beanFactory.getBean(cls);
return result;
}
/**
* 判断 BeanFactory是否包含bean对象
* @param name
* @return
*/
public static boolean containsBean(String name){
return beanFactory.containsBean(name);
}
/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。
* 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
* @param name
* @return
* @throws NoSuchBeanDefinitionException
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException{
return beanFactory.isSingleton(name);
}
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException{
return beanFactory.getType(name);
}
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException{
return beanFactory.getAliases(name);
}
/**
* 首字母小写
* @param name
* @return
*/
private static String lowerCaseInit(String name){
if(name.length()>0){
char c= name.charAt(0);
if(c>=65 && c<=90){
int i= c+ 32;
return ((char)i)+ name.substring(1);
} else{
return name;
}
} else{
return null;
}
}
}
2.4 controller接口
在接口处理中,直接从缓存集合中获取User的所有字典信息。
@GetMapping("/user/getUserList")
public Result<?> getUserList(){
return Result.ok(DictResourceCache.getDict("User"));
// System.out.println("info:>>>>>>>>>>>>>>>"+ info);
// List<User> userList= service.query();
// return Result.ok(userList);
}
2.5 PostMan测试
3. 结语
我简单理解为, @Component+@Order组合,Spring启动会自动去加载对应的类(实现CommandLineRunner接口),并执行run()方法。
SpringUtils看的半明白,我得多理解下。