xml文件
<root>
<lable>
<name>中心业务概览</name>
<url>
http://202.189.3.29:8642/MicroStrategy/servlet/mstrWeb?Server=WIN-OQRGOM8UCK1&Project=FXQ2&Port=0&evt=2048001&src=mstrWeb.2048001&documentID=38DFE98F4E39C8DF598EFEB85ED8C064&currentViewMedia=1&visMode=0&hiddensections=header,path,dockTop,dockLeft,footer
</url>
<depts>
<dept>FXQ013</dept>
<dept>FXQ003</dept>
</depts>
<menus>
<menu>lhfx</menu>
<menu>sbxsk</menu>
</menus>
</lable>
<lable>
<name>大额交易报告接收总量与趋势</name>
<url>
http://202.189.3.29:8642/MicroStrategy/servlet/mstrWeb?Server=WIN-OQRGOM8UCK1&Project=FXQ2&Port=0&evt=2048001&src=mstrWeb.2048001&documentID=B86F3F8246690F03B7EBF4B8FE90A249&currentViewMedia=1&visMode=0&hiddensections=header,path,dockTop,dockLeft,footer
</url>
<depts>
<dept>FXQ013</dept>
<dept>FXQ003</dept>
</depts>
<menus>
<menu>lhfx</menu>
<menu>sbxsk</menu>
</menus>
</lable>
</root>
第一版
静态块加载解析xml
/**
* 东华软件
*/
package com.dh.monitor.util.microstrategy;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.informix.util.stringUtil;
/**
* @author lidehu
* @date 2018年11月21日
* @description
*/
@Component
public class MicrostrategyUtils {
private static final Map<String, List<Map<String, String>>> map = new HashMap<>();
static {
parseXml();
}
/**
* 根据菜单和部门编码获取访问mstr对应的链接
*/
public static List<Map<String, String>> loadLable(String menu, String deptCode) {
return map.get(getKey(menu, deptCode));
}
/**
* 通过xml路径名解析xml文件并存在内存中
*/
private static void parseXml() {
SAXReader reader = new SAXReader();
try {
//解析xml文件
// String file = new MicrostrategyUtils().getClass().getClassLoader().getResource("config/microstrategy.xml").getFile();
String file = System.getProperty("user.dir")+File.separator+"config"+File.separator+ "config"+File.separator+"microstrategy.xml";
Document document = reader.read(new File(file));
Element root = document.getRootElement();
List<Element> elements = root.elements();
for(Element lable : elements) {
String name = lable.element("name").getStringValue().trim();
String url = lable.element("url").getStringValue().trim();
List<String> depts = new ArrayList<>();
List<String> menus = new ArrayList<>();
for(Element dept : lable.element("depts").elements())
depts.add(dept.getStringValue().trim());
for(Element menu : lable.element("menus").elements())
menus.add(menu.getStringValue().trim());
//分组并存入内存中
Map<String, String> loaclMap = new HashMap<>();
loaclMap.put("name", name);
loaclMap.put("url", url);
for(String dept : depts) {
for(String menu : menus) {
String key = getKey(menu, dept);
if(map.containsKey(key)) {
List<Map<String, String>> list = map.get(key);
list.add(loaclMap);
map.put(key, list);
} else {
List<Map<String, String>> list = new ArrayList<>();
list.add(loaclMap);
map.put(key, list);
}
}
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
private static String getKey(String menu, String dept) {
return menu+"/"+dept;
}
}
项目启动时执行parseXml方法,不能实现延迟加载。并且不能注入静态属性。因为静态块加载时间先于spring容器扫描bean。现在考虑用静态内部类单例模式实现延迟加载和属性注入。
第二版
/**
* 东华软件
*/
package com.dh.monitor.util.microstrategy;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.informix.util.stringUtil;
import net.bytebuddy.agent.builder.AgentBuilder.InitializationStrategy.SelfInjection.Lazy;
/**
* @author lidehu
* @date 2018年11月21日
* @description
*/
public class MicrostrategyUtils {
private static final Map<String, List<Map<String, String>>> map = new HashMap<>();
private static int cntInstance = 0;
private MicrostrategyUtils() {
synchronized(this) {
if(++cntInstance > 1) {
throw new RuntimeException("非法反射调用");
}
}
parseXml();
}
/*
* 静态内部类单例模式
* @author lidehu
* @date 2018年11月22日
*/
private static class LazyParseXml {
private static MicrostrategyUtils instance = new MicrostrategyUtils();
}
private static MicrostrategyUtils getInstacne() {
return LazyParseXml.instance;
}
// 通过xml路径名解析xml文件并存在内存中
private void parseXml() {
SAXReader reader = new SAXReader();
try {
//解析xml文件
String file = getClass().getClassLoader().getResource("config/microstrategy.xml").getFile();
// String file = System.getProperty("user.dir")+File.separator+ "config"+File.separator+"microstrategy.xml";
Document document = reader.read(new File(file));
Element root = document.getRootElement();
List<Element> elements = root.elements();
for(Element lable : elements) {
String name = lable.element("name").getStringValue().trim();
String url = lable.element("url").getStringValue().trim();
List<String> depts = new ArrayList<>();
List<String> menus = new ArrayList<>();
for(Element dept : lable.element("depts").elements())
depts.add(dept.getStringValue().trim());
for(Element menu : lable.element("menus").elements())
menus.add(menu.getStringValue().trim());
//分组并存入内存中
Map<String, String> loaclMap = new HashMap<>();
loaclMap.put("name", name);
loaclMap.put("url", url);
for(String dept : depts) {
for(String menu : menus) {
String key = getKey(menu, dept);
if(map.containsKey(key)) {
List<Map<String, String>> list = map.get(key);
list.add(loaclMap);
map.put(key, list);
} else {
List<Map<String, String>> list = new ArrayList<>();
list.add(loaclMap);
map.put(key, list);
}
}
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
private static String getKey(String menu, String dept) {
return menu+"/"+dept;
}
/**
* 根据菜单和部门编码获取访问mstr对应的链接
*/
public static List<Map<String, String>> loadLable(String menu, String deptCode) {
if(LazyParseXml.instance == null) {
getInstacne();
}
return map.get(getKey(menu, deptCode));
}
}
第二版实现了延迟加载,并考虑到非法反射调用私有构造器,和多线程非法反射调用。
运行时,因为一个大意class上的@Component没有去掉,结果进入我自定义的异常。发现spring在加载时竟然会反射调用私有构造器。然后测试了一下,果然是的。
去掉注解没有了。
但是项目通过jenkins构建后又踩一个坑,运行时程序出错,我的静态内部类找不到。
最后因为jenkins构建出错的原因,只能退回第一版,其实这里用延迟加载没有必要,因为加载后不用回收。
by the way:单例模式destory方法需要用到GC。
静态内部类保证线程安全请见:https://blog.csdn.net/mnb65482/article/details/80458571