博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Web项目启动加载数据至内存--SpringApplicationListener实现
阅读量:5890 次
发布时间:2019-06-19

本文共 9503 字,大约阅读时间需要 31 分钟。

需求:

    1.项目开发中会有一些平凡使用的数据需要加载到内存中;以减少数据库交互次数.降低服务器和数据库压力.

思路:

    1.在系统启动时,将监听web容器创建完成事件;
    2.创建一个用于存储相关数据的Dic类;
    3.在监听到容器创建完成后,将为Dic类中的静态变量赋值;
    4.这样就可以在应用中随意使用Dic类中的数据;

优劣势:

    1.减少web服务与数据库的交互次数,减轻双方压力;
    2.web服务启动时间将会被延长;

环境:

    
import org.springframework.context.ApplicationListener;
    
import org.springframework.context.event.ContextRefreshedEvent;

过程:

    1.创建一个类实现接口
ApplicationListener<ContextRefreshedEvent>,并将这个类用@component标签扫描入Spring的对象管理池;
@Componentpublic class AppSpringEventListener implements ApplicationListener
{ @Override public void onApplicationEvent(ContextRefreshedEvent arg0) { //spring会调用两次这个方法,因为启动时会创建了两个容器(root application context 和projectName-servlet context), //我们只在root上下文创建成功后执行这个方法,初始化参数 if(arg0.getApplicationContext().getParent()==null){ //初始化数据字典 DictionariesHelper.getInstance().init(); //初始化省市县字典 RegionHelper.getInstance().init(); } }}
getParent
 
    2.在DictionariesHelper类中定义静态变量用于存储字典信息,在RegionHelper中定义静态变量用于存储省市县信息;
@Componentpublic class DictionariesHelper {	private static final Logger log = LoggerFactory.getLogger(DictionariesHelper.class);	//按层级存储字典信息	private static Map
dataDictionaries = new LinkedHashMap
(); //存储所有字典信息 private static Map
dataAllMap = new LinkedHashMap
(); private static DictionariesHelper dictionariesHelper; //service组件 private static DataDictionariesServise dataDictionariesServise; //私有化构造函数 private DictionariesHelper(){} public static DictionariesHelper getInstance(){ if(DictionariesHelper.dictionariesHelper==null){ DictionariesHelper.dictionariesHelper = new DictionariesHelper(); } return DictionariesHelper.dictionariesHelper; } /** * 初始化数据字典 */ public void init(){ if(DictionariesHelper.dataDictionaries.size()==0){ initDataDictionaries(); } } /** * 重载数据字典 */ public void reLoad() { // TODO Auto-generated method stub DictionariesHelper.dataDictionaries.clear(); DictionariesHelper.dataAllMap.clear(); init(); } /** * 初始化数据字典 */ private void initDataDictionaries(){ log.info("--------------数据字典初始化开始---------------"); //获取系统当前时间 Long startTime = System.currentTimeMillis(); List
> typeList = dataDictionariesServise.queryDataType(); for(Map
typeMap:typeList){ LinkedHashMap
paraMap = new LinkedHashMap
(); paraMap.put("OBJTYPE", typeMap.get("OBJTYPE")); paraMap.put("OBJNAME", typeMap.get("OBJNAME")); paraMap.put("OBJTYPECODE", typeMap.get("CONTYPEID")); List
> dataList = dataDictionariesServise.queryDataByType(typeMap); for(Map
dataMap:dataList){ //加载所有数据至dataAllMap DictionariesHelper.dataAllMap.put((String)dataMap.get("CONCODE"),(String)dataMap.get("CONNAME")); } DictionariesHelper.dataDictionaries.put(typeMap.get("OBJTYPE"), dataList); } log.info("--------------数据字典完成初始化,共用时"+(System.currentTimeMillis()-startTime)+"ms---------------"); } /** * 获取所有字典数据 */ public static Map
getDataDictionaries(){ return DictionariesHelper.dataDictionaries; } /** * 根据类型获取下设的字典数据 * @param type 类型编码(T_COMMON_TYPE表中的OBJTYPE字段) * @return map:key为code,value为name */ public static List getDicListByType(String type){ return (List)DictionariesHelper.dataDictionaries.get(type); } /** * 根据key获取value * @param code 编码(T_COMMON_INFO中的CONCODE) * @return 值(T_COMMON_INFO中的CONNAME) */ public static String getDicValueByCode(String code){ return DictionariesHelper.dataAllMap.get(code); } @Autowired(required = true) public void setDataDictionariesServise(DataDictionariesServise dataDictionariesServise){ DictionariesHelper.dataDictionariesServise = dataDictionariesServise; }}
DictionariesHelper
 
@Component
public class RegionHelper {	private static final Logger log = LoggerFactory.getLogger(RegionHelper.class);	private static Map
regionDictionaries = new LinkedHashMap
(); private static RegionHelper regionHelper; //service组件 private static DataDictionariesServise dataDictionariesServise; private static List
> zTreeDatalist = new ArrayList
>(); //省市县级别 public static Integer province = 1; public static Integer city = 2; public static Integer town = 3; public static RegionHelper getInstance(){ if(RegionHelper.regionHelper==null){ RegionHelper.regionHelper = new RegionHelper(); } return RegionHelper.regionHelper; } /** * 初始化省市县字典 */ public void init(){ if(RegionHelper.regionDictionaries.size()==0){ initRegionDictionaries(); } } /** * 重载省市县字典 */ public void reLoad(){ RegionHelper.regionDictionaries.clear(); init(); } /** * 初始化省市县字典 */ private void initRegionDictionaries() { log.info("--------------省市县字典初始化开始---------------"); //获取系统当前时间 Long startTime = System.currentTimeMillis(); List
> list= dataDictionariesServise.queryRegion(); for(Map
map:list){ //根据map构造字典 loadRegionData(map); } log.info("--------------省市县字典完成初始化,共用时"+(System.currentTimeMillis()-startTime)+"ms---------------"); } /** * 根据编码获取这个区划的Map,其中AREALIST是下设区县 * @param regionCode 需要的省市县 * @return 区划Map */ public static Map
getRegionMapByRegionCode(String regionCode){ Integer level = RegionHelper.getRegionLevelByCode(regionCode); if(level==RegionHelper.province){ return (Map
)RegionHelper.regionDictionaries.get(regionCode); }else if(level==RegionHelper.city){ return (Map
)((Map
)(((Map
)RegionHelper.regionDictionaries.get(regionCode.substring(0,2)+"0000")).get("AREALIST"))).get(regionCode); }else if(level==RegionHelper.town){ return (Map
)((Map
)((Map
)((Map
)(((Map
)RegionHelper.regionDictionaries.get(regionCode.substring(0,2)+"0000")).get("AREALIST"))).get(regionCode.substring(0,4)+"00")).get("AREALIST")).get(regionCode); }else{ return null; } } /** * 根据编码获取这个区划的下设区域,数据符合zTree简单数据格式 * @param regionCode 需要的省市县编码 * @return 符合zTree简单数据格式的json字符串 */ public static String getRegionZTreeDataByRegionCode(String regionCode){ RegionHelper.zTreeDatalist.clear(); return JSONArray.toJSONString(RegionHelper.getRegionZTreeListByMap(RegionHelper.getRegionMapByRegionCode(regionCode))); } private static List
> getRegionZTreeListByMap(Map
map) { Map
resultMap = new LinkedHashMap
(); resultMap.put("id", map.get("CODE")); resultMap.put("name", map.get("NAME")); resultMap.put("pId", map.get("SUPERIOR")); boolean isAdd = true; if((Map
)map.get("AREALIST")!=null&&((Map
)map.get("AREALIST")).size()>0){ resultMap.put("isParent",true); RegionHelper.zTreeDatalist.add(resultMap); isAdd = false; Iterator iter = ((Map
)map.get("AREALIST")).keySet().iterator(); while(iter.hasNext()){ RegionHelper.getRegionZTreeListByMap((Map
)((Map
)map.get("AREALIST")).get(iter.next())); } }else{ resultMap.put("isParent",false); } if(isAdd){ RegionHelper.zTreeDatalist.add(resultMap); } //数组反转 //Collections.reverse(RegionHelper.zTreeDatalist); return RegionHelper.zTreeDatalist; } /** * @param regionCode 地区编码 * @return 省市县级别:1代表省;2代表市3代表县 */ public static Integer getRegionLevelByCode(String regionCode){ Integer i = Integer.parseInt(regionCode); if(i%100==0){ if(i%10000==0){ return RegionHelper.province; }else { return RegionHelper.city; } }else{ return RegionHelper.town; } } private Boolean loadRegionData(Map
map) { //加载省 if(RegionHelper.regionDictionaries.get(map.get("PROCODE"))==null){ Map
dataMap = new LinkedHashMap
(); dataMap.put("CODE", map.get("PROCODE")); dataMap.put("NAME", map.get("PRONAME")); dataMap.put("AREALIST",new LinkedHashMap
()); RegionHelper.regionDictionaries.put(map.get("PROCODE"), dataMap); } if(map.get("PROCODE")==null){ return true; } //加载市 Map
obj = (Map
)(((Map
)RegionHelper.regionDictionaries.get(map.get("PROCODE"))).get("AREALIST")); if(obj.get(map.get("CITYCODE"))==null&&map.get("CITYCODE")!=null){ Map
dataMap = new LinkedHashMap
(); dataMap.put("CODE", map.get("CITYCODE")); dataMap.put("NAME", map.get("CITYNAME")); dataMap.put("SUPERIOR", map.get("PROCODE")); dataMap.put("AREALIST",new LinkedHashMap
()); obj.put(map.get("CITYCODE"), dataMap); } if(map.get("CITYCODE")==null){ return true; } //加载县 obj = (Map
)((Map
)((Map
)(((Map
)RegionHelper.regionDictionaries.get(map.get("PROCODE"))).get("AREALIST"))).get(map.get("CITYCODE"))).get("AREALIST"); if(obj.get("TOWNCODE")==null&&map.get("TOWNCODE")!=null){ Map
dataMap = new LinkedHashMap
(); dataMap.put("CODE", map.get("TOWNCODE")); dataMap.put("NAME", map.get("TOWNNAME")); dataMap.put("SUPERIOR", map.get("CITYCODE")); obj.put(map.get("TOWNCODE"), dataMap); } return true; } @Autowired(required = true) public void setDataDictionariesServise(DataDictionariesServise dataDictionariesServise){ RegionHelper.dataDictionariesServise = dataDictionariesServise; } }
getRegionZTreeDataByRegionCode
  
//调用省市县内存数据
String ztreeData = RegionHelper.getRegionZTreeDataByRegionCode("XXX");//调用字典内存数据List dicList = DictionariesHelper.getDicListByType("xxx");
 

原理:

    1.Spring会在web容器创建完成时调用SpringApplicationListener接口中的onApplicationEvent方法,所以我们自定义类实现
SpringApplicationListener接口,重写onApplicationEvent方法.以便spring在容器完成创建事件后调用我的实现类,运行自定义方法.

总结:

    1.使用@Component标注两个工具类是为了可以使用@Autowired标签帮助我将service对象注入对象中;
    2.不能在在声明service对象的属性名上直接使用@Autowired标签,那样的话值注不进去还spring报错(不清楚为什么).所以我写了set方法用于注入service;
    3.在两个Helper类中,我用于存储数据的都是LinkedHashMap,而不是HashMap,因为,字典和省市县在读取数据时很多时候都会排序的寻求.而HashMap是无序的.这样就算我在SQL中将数据排序.当放入Map中时又变成无序的了.而LinkedHashMap会记录数据进入的循序.这样的话就可以满足我排序的要求;
    4.在
SpringApplicationListener中的onApplicationEvent方法中我做了一个if判断,是因为Spring在启动中会在两个容器创建时(root application context和projectName-servlet context).其中projectName-servlet context是root application context的子容器.所以,我们判断当当前容器的父容器是空时(也就是root application context),才执行我们的初始化方法.
 
 
 
 

转载于:https://www.cnblogs.com/CoderGuokai/p/7884746.html

你可能感兴趣的文章
阿里春节大数据:河南人最爱玩云南人最爱飞
查看>>
React页面隐藏#
查看>>
[译]Serilog Tutorial
查看>>
H264系列(9):H264中的时间戳(DTS和PTS)
查看>>
SUSE Linux源代码编译安装MySQL 5.6
查看>>
RT-thread内核之空闲线程
查看>>
<Netty>(十八)(中级篇)心跳连接准备之获得电脑的相关信息
查看>>
zk常见面试题
查看>>
Asp.Net初学小结 判断数组中是否有重复的数据
查看>>
Vista的MBR磁盘签名(Disk Signature) (转帖)
查看>>
关于前后端分离的一些资料 (转)
查看>>
python3 urllib和requests模块
查看>>
基于RabbitMQ.Client组件实现RabbitMQ可复用的 ConnectionPool(连接池)
查看>>
flume的安装部署
查看>>
洛谷P1337 [JSOI2004]平衡点 / 吊打XXX(模拟退火)
查看>>
ITSA(IT Strategy and Architecture)方法介绍
查看>>
PhpStorm 安装ApiDebugger
查看>>
欧拉角与万向节死锁
查看>>
[LeetCode] Swim in Rising Water 在上升的水中游泳
查看>>
简单网络搭建与测试 mininet
查看>>