SpringBoot 加载系统资源至缓存

  • Post author:
  • Post category:其他


开发环境: 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. 结语


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看的半明白,我得多理解下。



版权声明:本文为ceaningking原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。