开发环境: IDEA 2022.1.4+ MyBatis
代码参考:springboot启动后加载字典表数据供业务调用
参考
Spring-boot中的CommandLineRunner的作用 - 简书
https://www.cnblogs.com/yanxiaoguo/p/16167221.html
目录
1. 概述
2. 实现步骤
2.1 新建一个缓存类 DictResourceCache
2.2 新建Runner类实现CommandLineRunner接口
2.3 定义工具类 SpringUtils
2.4 controller接口
2.5 PostMan测试
3. 结语
平常做PC端程序时候,在程序启动时候,都会去事先加载数据字典信息,想着SpringBoot也可以实现这块功能,特百度查询资料,可以使用CommandLineRunner来实现。
通过实现CommandLineRunner接口的run方法, 结合@Component、@Order的使用,可以来实现数据加载顺序。对于@Order的value属性(int类型),值越低优先级越高。
效果: 我在服务启动时候,将用户信息加载到缓存中,当使用PostMan来调用获取用户信息时候,从缓存中直接获取.
此处SpringBoot+MyBatis的配置就暂不描述了。
这个类主要有个静态的集合对象cache,
Map
@Slf4j
public class DictResourceCache {private static UserMapper userMapper;private static Map> 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 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);}
}
这个接口使用了@Component、@Order注解。 重写run()方法,调用缓存类的DictResourceCache的load()方法。
@Slf4j
@Component
@Order(2)
public class DictResourceRunner implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {log.info("加载数据字典...");DictResourceCache.load();log.info("加载完毕...");}
}
这个我看的半明白, 与BeanFactory有关。通过@Component注解,将该类交由Spring管理.
@Component
public class SpringUtils implements BeanFactoryPostProcessor {/*** Spring应用上下文环境*/private static ConfigurableListableBeanFactory beanFactory;@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {SpringUtils.beanFactory= configurableListableBeanFactory;}public static T getBean(String name) throws BeansException{name= lowerCaseInit(name);if(containsBean(name)){return (T) beanFactory.getBean(name);} else{return null;}}/*** 获取* @param cls* @return* @param * @throws BeansException*/public static T getBean(Class 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;}}
}
在接口处理中,直接从缓存集合中获取User的所有字典信息。
@GetMapping("/user/getUserList")public Result> getUserList(){return Result.ok(DictResourceCache.getDict("User"));
// System.out.println("info:>>>>>>>>>>>>>>>"+ info);
// List userList= service.query();
// return Result.ok(userList);}
我简单理解为, @Component+@Order组合,Spring启动会自动去加载对应的类(实现CommandLineRunner接口),并执行run()方法。
SpringUtils看的半明白,我得多理解下。