项目开发中数据字典设计实现缓存
数据字典的好处很多比如:
1、可以减少使用表,来专门记录类型。
2、类型使用key检索,或者报表统计分析,在一定程度上相比汉字来讲,效率好得多。
3、使用缓存的数据字典、也可以减少不少的io操作。
等等、、、、
首先,库表设计就智者见智了、不多说、爱怎么设计就怎么设计。
完整的数据字典设计 ,需要
1、生成select 自定义标签。
2、list页面,或者get页面, 一个key转 value的标签
使用自定义标签,搭配上缓存的数据字典是最方便、最完美的解决办法,
接下来,就直接贴代码了。
一、数据字典缓存配置:
1、数据字典缓存监听器(在web容器启动成功的时候、进行缓存)
web.xml
1 <listener> 2 <description>初始化数据字典</description> 3 <listener-class>com.hotent.core.web.listener.DictionaryCacheListener</listener-class> 4 </listener>
2、DictionaryCacheListener
1 package com.*****.core.web.listener; 2 import javax.servlet.ServletContextEvent; 4 import org.springframework.web.context.WebApplicationContext; 5 import org.springframework.web.context.support.WebApplicationContextUtils; 7 import com.*****.platform.service.system.DictionaryService; 8 9 public class DictionaryCacheListener implements javax.servlet.ServletContextListener { 10 11 @Override 12 public void contextDestroyed(ServletContextEvent arg0) { 14 }
16 @Override 17 public void contextInitialized(ServletContextEvent arg0) { 18 19 System.out.println("++++++++++++++++++ 数据字典已缓存 +++++++++++++++++++++"); 20 WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(arg0.getServletContext()); 21 DictionaryService dc = (DictionaryService) webApplicationContext.getBean("dictionaryService"); 22 dc.getCacheDic(); // 调用数据字典Manager的一个方法来缓存 24 } 25 26 }
3、保存缓存数据字典的BO //(也可以放在平台缓存的BO里面,那共用的缓存设计要考虑线程安全了,简单起见这么搞。)
import java.util.HashMap; import java.util.List; import java.util.Map; import com.hotent.platform.model.system.Dictionary; import com.hotent.platform.model.system.GlobalType; /** * 缓存数据字典 * @author miao * */ public class CacheDict { /** * 所有的数据字典类型 */ public static Map<String,GlobalType> allTypes = new HashMap<String, GlobalType>(); /** * 所有类型,对应的数据字典项 */ public static Map<String, List<Dictionary>> dictList = new HashMap<String,List<Dictionary>>(); /** * 类型与字典项 由List 转成Map(key,value) */ public static Map<String, Map<Long,String>> dictMap = new HashMap<String,Map<Long,String>>(); }
4、为缓存注入数据 。 提示一点:在更新、或者添加数据字典的时候,记得重新调用缓存的方法、更新数据
1 public void getCacheDic() { 2 //GlobalType 里面存储所有的各种类型:附件类型,数据字典类型,流程类型等等 3 List<GlobalType> globalTypes = globalTypeDao.getByCatKey(GlobalType.CAT_DIC); //eg:性别‘学历等 4 CacheDict.allTypes.clear(); 5 CacheDict.dictList.clear(); 6 CacheDict.dictMap.clear(); 7 8 for(GlobalType DicType : globalTypes){ 9 CacheDict.allTypes.put(DicType.getNodeKey(),DicType); 10 11 List<Dictionary> dictList = this.getByNodeKey(DicType.getNodeKey());//通过key 查找 所有数据项 12 13 CacheDict.dictList.put(DicType.getNodeKey(),dictList ); 14 15 //字典项转成key - value的形式 16 Map<Long, String> map = new HashMap<Long, String>(); 17 for(Dictionary dic : dictList){ 18 map.put(dic.getDicId(),dic.getItemName()); // key / name 19 } 20 CacheDict.dictMap.put(DicType.getNodeKey(),map); 21 } 22 System.out.println("+++++++++++++++++++++++++ "+globalTypes.size()+" +++++++++++++++++++++" ); 23 }
5、 生成select 框自定义标签
1 import java.io.IOException; 2 import java.util.List; 3 4 import javax.servlet.jsp.JspTagException; 5 import javax.servlet.jsp.JspWriter; 6 import javax.servlet.jsp.tagext.TagSupport; 7 8 import org.apache.commons.lang.StringUtils; 9 10 import com.hotent.core.cache.impl.CacheDict; 11 import com.hotent.platform.model.system.Dictionary; 12 13 14 /** 15 * 16 * 选择下拉框 17 * 18 * @author: miao 19 * @date: 日期:2013-9-25 23:14:26 20 * @version 1.0 21 */ 22 public class DictSelectTag extends TagSupport { 23 private String id; //EAMPLE:<select name="selectName" id = "" /> 24 private String name; 25 private String title; 26 private String value =""; //默认值 即是回显 ID 27 private String nodeKey; //数据字典节点 28 private String divClass; //DIV样式 29 private String labelClass; //Label样式 30 private boolean hasLabel = false; //是否显示label 31 private String clazz; 32 private String style; 33 private boolean required =false; // 如果必须选择、则添加required = true 34 35 public int doStartTag() throws JspTagException { 36 return EVAL_PAGE; 37 } 38 39 public int doEndTag() throws JspTagException { 40 try { 41 JspWriter out = this.pageContext.getOut(); 42 out.print(end().toString()); 43 } catch (IOException e) { 44 e.printStackTrace(); 45 } 46 return EVAL_PAGE; 47 } 48 49 50 public StringBuffer end() { 51 StringBuffer sb = new StringBuffer(); 52 try{ 53 if (StringUtils.isBlank(divClass)) { 54 divClass = ""; //默认form样式 55 } 56 if (StringUtils.isBlank(labelClass)){ 57 labelClass = ""; //默认label样式 58 } 59 /* ServletContext servletContext = pageContext.getServletContext(); 60 ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext); 61 ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); 62 DictionaryService dictioninaryService = (DictionaryService)context.getBean("dictionaryService"); 63 List<Dictionary> dictionary = dictioninaryService.getByNodeKey(this.getNodeKey()); 64 从applicationContext里面获取 service方法、获取数据字典、、 更新为从缓存对象中获取数据字典。 update time 2013-9-28 15:25:48 65 */ 66 List<Dictionary> dictionary = CacheDict.dictList.get(this.getNodeKey()); 67 if (hasLabel) { 68 sb.append("<div class=\""+divClass+"\">"); 69 sb.append("<label class=\""+labelClass+"\" >"); 70 } 71 if (dictionary == null) { 72 sb.append("<span color=\"red\"> 此nodekey 未查找到数据字典</span>"); 73 }else { 74 if (hasLabel) { 75 if (StringUtils.isBlank(this.title)) { 76 this.title ="选项"; 77 } 78 sb.append(this.title+":"); 79 sb.append("</label>"); 80 } 81 if(required) 82 sb.append("<select name=\""+name+"\" validate =\"{required:true}\" class=\""+this.getClazz()+"\" style=\""+this.getStyle()+"\"" ); 83 else 84 sb.append("<select name=\""+name+"\" class=\""+this.getClazz()+"\" style=\""+this.getStyle()+"\"" ); 85 if (!StringUtils.isBlank(this.id)) { 86 sb.append(" id=\""+id+"\""); 87 } 88 sb.append(">"); 89 // if(this.getValue().equals(""));{ 90 sb.append("<option value = \"\">请选择</option>"); // 91 for (Dictionary dic : dictionary) { 92 /* String v = this.getValue(); 93 Long i = dic.getDicId();*/ 94 if (dic.getDicId().toString().equals(this.getValue()) ) { 95 sb.append(" <option value=\""+dic.getDicId()+"\" selected=\"selected\">"); 96 }else { 97 sb.append(" <option value=\""+dic.getDicId()+"\">"); 98 } 99 sb.append(dic.getItemName()); 100 sb.append(" </option>"); 101 } 102 103 sb.append("</select>"); 104 if (hasLabel) { 105 sb.append("</div>"); 106 } 107 } 108 }catch (Exception e) { 109 e.printStackTrace(); 110 return sb.append("<span color=\"red\"> <h1>异常</h1>此nodekey: "+ this.nodeKey+" 查找数据库数据字典异常<br/>"+e.getMessage()+"</span>"); 111 } 112 return sb; 113 } 114 115 public String getValue() { 116 return value; 117 } 118 119 public void setValue(String value) { 120 this.value = value; 121 } 122 123 public String getId() { 124 return id; 125 } 126 127 public void setId(String id) { 128 this.id = id; 129 } 130 131 132 public String getDivClass() { 133 return divClass; 134 } 135 136 public void setDivClass(String divClass) { 137 this.divClass = divClass; 138 } 139 140 public String getLabelClass() { 141 return labelClass; 142 } 143 144 public void setLabelClass(String labelClass) { 145 this.labelClass = labelClass; 146 } 147 148 public String getTitle() { 149 return title; 150 } 151 152 public void setTitle(String title) { 153 this.title = title; 154 } 155 156 public String getNodeKey() { 157 return nodeKey; 158 } 159 160 public void setNodeKey(String nodeKey) { 161 this.nodeKey = nodeKey; 162 } 163 164 public boolean isHasLabel() { 165 return hasLabel; 166 } 167 168 public void setHasLabel(boolean hasLabel) { 169 this.hasLabel = hasLabel; 170 } 171 172 public String getName() { 173 return name; 174 } 175 176 public String getClazz() { 177 return clazz; 178 } 179 180 public boolean isRequired() { 181 return required; 182 } 183 184 public void setRequired(boolean required) { 185 this.required = required; 186 } 187 188 public void setClazz(String clazz) { 189 this.clazz = clazz; 190 } 191 192 public void setName(String name) { 193 this.name = name; 194 } 195 196 197 public String getStyle() { 198 return style; 199 } 200 201 public void setStyle(String style) { 202 this.style = style; 203 } 204 205 206 207 208 }
6、将数据字典通过key 转换成value
import java.io.IOException; import java.util.Map; import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; import com.hotent.core.cache.impl.CacheDict; public class DictKey2Value extends TagSupport { private Long key; private String nodeKey; public int doStartTag() throws JspTagException { return EVAL_PAGE; } public int doEndTag() throws JspTagException { try { JspWriter out = this.pageContext.getOut(); out.print(dictName().toString()); } catch (IOException e) { e.printStackTrace(); } return EVAL_PAGE; } public StringBuffer dictName() { StringBuffer sb = new StringBuffer(); Map map = CacheDict.dictMap.get(this.getNodeKey()); if(map == null) sb.append("未发现NodeKey"); else{ if(map.get(key)!=null) sb.append( map.get(key)); } return sb; } public String getNodeKey() { return nodeKey; } public void setNodeKey(String nodeKey) { this.nodeKey = nodeKey; } public Long getKey() { return key; } public void setKey(Long key) { this.key = key; } }
7、tag标签配置
1 <!-- 数据字典标签 --> 2 <tag> 3 <name>dict</name> 4 <description>数据字典</description> 5 <tag-class>com.hotent.core.web.tag.DictSelectTag</tag-class> 6 <body-content>JSP</body-content> 7 <display-name>数据字典选择控件</display-name> 8 <attribute> 9 <name>id</name> 10 <required>false</required> 11 <rtexprvalue>true</rtexprvalue> 12 </attribute> 13 <attribute> 14 <name>required</name> 15 <required>false</required> 16 <rtexprvalue>true</rtexprvalue> 17 </attribute> 18 <attribute> 19 <name>name</name> 20 <required>true</required> 21 <rtexprvalue>true</rtexprvalue> 22 </attribute> 23 <attribute> 24 <name>title</name> 25 <required>false</required> 26 <rtexprvalue>true</rtexprvalue> 27 </attribute> 28 <attribute> 29 <name>value</name> 30 <required>true</required> 31 <rtexprvalue>true</rtexprvalue> 32 </attribute> 33 <attribute> 34 <name>nodeKey</name> 35 <required>true</required> 36 <rtexprvalue>true</rtexprvalue> 37 <description>数据字典的节点key</description> 38 </attribute> 39 <attribute> 40 <name>divClass</name> 41 <required>false</required> 42 <rtexprvalue>true</rtexprvalue> 43 </attribute> 44 <attribute> 45 <name>labelClass</name> 46 <required>false</required> 47 <rtexprvalue>true</rtexprvalue> 48 </attribute> 49 <attribute> 50 <name>hasLabel</name> 51 <required>false</required> 52 <rtexprvalue>true</rtexprvalue> 53 </attribute> 54 <attribute> 55 <name>clazz</name> 56 <required>false</required> 57 <rtexprvalue>true</rtexprvalue> 58 </attribute> 59 <attribute> 60 <name>style</name> 61 <required>false</required> 62 <rtexprvalue>true</rtexprvalue> 63 </attribute> 64 </tag> 65 <tag> 66 <name>dicK2V</name> 67 <description>数据字典</description> 68 <tag-class>com.hotent.core.web.tag.DictK2V</tag-class> 69 <body-content>JSP</body-content> 70 <display-name>数据转换</display-name> 71 <attribute> 72 <name>key</name> 73 <required>true</required> 74 <rtexprvalue>true</rtexprvalue> 75 </attribute> 76 <attribute> 77 <name>nodeKey</name> 78 <required>true</required> 79 <rtexprvalue>true</rtexprvalue> 80 </attribute> 81 </tag>
看下页面使用效果:
<f:dict name="sex" nodeKey="sex" required="true" value="${user.sex}" clazz="class样式" style="width:150px !important" ></f:dict>
//生成标准的select标签、可以添加自己的样式等、
<f:dicK2V nodeKey="sex" key="${user.sex}"></f:dicK2V>
over,