由于业务的原因,导致程序中有很多枚举,不便维护,故使用自定义的字典表
1.表的设计
主要有两张表:sys_dict_type 用于记录字典类型 ; sys_dict 用于记录字典数据
DDL:
CREATE TABLE `sys_dict_type` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`NAME_EN` varchar(255) DEFAULT NULL COMMENT '英文名称',
`NAME_CN` varchar(255) DEFAULT NULL COMMENT '中文名称',
`STATUS` tinyint(4) DEFAULT '1',
`SYSTEM_ID` tinyint(4) DEFAULT '1' COMMENT '1.卖家 2.买家 3.运营系统',
`CREATE_TIME` datetime DEFAULT CURRENT_TIMESTAMP,
`UPDATE_TIME` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;
CREATE TABLE `sys_dict` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`LABEL` varchar(255) DEFAULT NULL COMMENT '字典数据名称',
`DICT_TYPE_ID` bigint(20) DEFAULT NULL COMMENT '字典类型,与sys_dict_type关联',
`VALUE` tinyint(4) DEFAULT NULL COMMENT '字典数据值',
`SORT` int(255) DEFAULT NULL COMMENT '排序',
`STATUS` tinyint(4) DEFAULT '1',
`CREATE_TIME` datetime DEFAULT CURRENT_TIMESTAMP,
`UPDATE_TIME` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
2.web.xml配置监听器初始化数据
<!-- 加载字典表 -->
<listener>
<listener-class>cn.yanxiaohui.dict.DictInit</listener-class>
</listener>
3.初始化字典-自定义的DictInit类
package cn.yanxiaohui.dict;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import cn.yanxiaohui.vo.SysDictService;
import cn.yanxiaohui.vo.SysDict;
/**
* 加载字典表
* @author yanxh
*/
public class DictInit implements ServletContextListener {
/**
* 上下文对象
*/
private static WebApplicationContext wac;
/**
* 上下文销毁时执行方法
*/
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
/**
* 上下文初始时执行方法
*/
@Override
public void contextInitialized(ServletContextEvent sce) {
wac = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
SysDictService sysDictService = (SysDictService) wac.getBean("sysDictService");
Map<String, Object> params=new HashMap<String, Object>();
// 获取所有的字典数据
List<SysDict> list=sysDictService.getListByParams(params);
DictBean.setDicts(list);
}
/**
* 获取上下文对象方法
* @return 上下方对象
*/
public static ApplicationContext getApplicationContext(){
return wac;
}
}
DictBean是一个用于存放初始化数据的类
package cn.yanxiaohui.dict;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import cn.yanxiaohui.vo.SysDict;
/**
* 存放字典表数据
* @author yanxh
*/
public class DictBean implements Serializable {
private static List<SysDict> dicts=new ArrayList<SysDict>();
public static List<SysDict> getDicts() {
return dicts;
}
public static void setDicts(List<SysDict> dicts) {
DictBean.dicts = dicts;
}
}
4.自定义字典工具类
package cn.yanxiaohui.dict;
import cn.yanxiaohui.vo.SysDict;
import java.util.ArrayList;
import java.util.List;
/**
* 字典工具类
* @author yanxh
*
*/
public class DictUtil {
/**
* 通过字典类型的英文名称获取字典数据列表
* @param enName 字典类型的英文名称
* @return 字典数据列表
*/
public static List<LabelValue> getDictsByEnName(String enName){
List<SysDict> dicts=DictBean.getDicts();
List<LabelValue> labelValues=new ArrayList<LabelValue>();
for(SysDict dict:dicts){
if(enName.equals(dict.getNameEn())){
labelValues.add(new LabelValue(dict.getLabel(),dict.getValue().toString()));
}
}
return labelValues;
}
/**
* 通过字典类型的英文名称获取字典数据名称
* @param enName 字典类型的英文名称
* @param value 字典数据的值
* @return 字典数据名称
*/
public static String getLabelByEnNameAndValue(String enName,Byte value){
List<SysDict> dicts=DictBean.getDicts();
for(SysDict dict:dicts){
if(dict.getNameEn().equals(enName) && value==dict.getValue()){
return dict.getLabel();
}
}
return "";
}
/**
* 通过字典类型的中文名称获取字典数据名称
* @param cnName 字典类型的中文名称
* @param value 字典数据的值
* @return 字典数据名称
*/
public static String getLabelByCnNameAndValue(String cnName,Byte value){
List<SysDict> dicts=DictBean.getDicts();
for(SysDict dict:dicts){
if(dict.getNameEn().equals(cnName) && value==dict.getValue()){
return dict.getLabel();
}
}
return "";
}
/**
* 通过字典类型的英文名和字典数据名称获取字典数据的值
* @param enName 字典类型的英文名
* @param label 字典数据名称
* @return 字典数据的值
*/
public static Byte getIdByEnNameAndLabel(String enName,String label){
List<SysDict> dicts=DictBean.getDicts();
for(SysDict dict:dicts){
if(label.equals(dict.getLabel()) && enName.equals(dict.getNameEn())){
return dict.getValue();
}
}
return null;
}
/**
* 通过字典类型的中文名和字典数据名称获取字典数据的值
* @param cnName 字典类型的中文名
* @param label 字典数据名称
* @return 字典数据的值
*/
public static Byte getIdByCnNameAndLabel(String cnName,String label){
List<SysDict> dicts=DictBean.getDicts();
for(SysDict dict:dicts){
if(label.equals(dict.getLabel()) && cnName.equals(dict.getNameCn())){
return dict.getValue();
}
}
return null;
}
}
其中LabelValue类是自定义用于替换以前枚举功能的视图层实体类
package cn.yanxiaohui.vo.dict;
import java.io.Serializable;
public class LabelValue implements Serializable {
private static final long serialVersionUID = 3689355407466181430L;
/**
* The property which supplies the option label visible to the end user.
*/
private String label = null;
/**
* The property which supplies the value returned to the server.
*/
private String value = null;
/**
* Default constructor.
*/
public LabelValue() {
super();
}
/**
* Construct an instance with the supplied property values.
*
* @param label
* The label to be displayed to the user.
* @param value
* The value to be returned to the server.
*/
public LabelValue(String label, String value) {
this.label = label;
this.value = value;
}
// ------------------------------------------------------------- Properties
public String getLabel() {
return this.label;
}
public void setLabel(String label) {
this.label = label;
}
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
// --------------------------------------------------------- Public Methods
/**
* Compare LabelValueBeans based on the label, because that's the human
* viewable part of the object.
*
* @see Comparable
*/
public int compareTo(Object o) {
// Implicitly tests for the correct type, throwing
// ClassCastException as required by interface
String otherLabel = ((LabelValue) o).getLabel();
return this.getLabel().compareTo(otherLabel);
}
/**
* Return a string representation of this object.
*/
public String toString() {
StringBuffer sb = new StringBuffer("LabelValue[");
sb.append(this.label);
sb.append(", ");
sb.append(this.value);
sb.append("]");
return (sb.toString());
}
/**
* LabelValueBeans are equal if their values are both null or equal.
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof LabelValue)) {
return false;
}
LabelValue bean = (LabelValue) obj;
int nil = (this.getValue() == null) ? 1 : 0;
nil += (bean.getValue() == null) ? 1 : 0;
if (nil == 2) {
return true;
} else if (nil == 1) {
return false;
} else {
return this.getValue().equals(bean.getValue());
}
}
/**
* The hash code is based on the object's value.
*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return (this.getValue() == null) ? 17 : this.getValue().hashCode();
}
}
5.controller中将需要的字典放入到model中
// 放置用户类型的字典数据
model.addAttribute("userType", DictUtil.getDictsByEnName("userType"));
// 放置用户状态的字典数据
model.addAttribute("userStatus", DictUtil.getDictsByEnName("userStatus"));
6.定义用于视图数据获取的工具类(视图为velocity)
import org.apache.commons.lang3.StringUtils;
public class DictVelocity {
public String label(String enName,Integer value) {
String text="";
if(StringUtils.isNotBlank(enName) && value != null){
text=DictUtil.getLabelByEnNameAndValue(enName,value.byteValue());
}
return text;
}
public String label(String enName,Byte value) {
String text="";
if(StringUtils.isNotBlank(enName) && value != null){
text=DictUtil.getLabelByEnNameAndValue(enName,value);
}
return text;
}
}
在velocity的工具配置文件toolbox.xml中添加
<?xml version="1.0"?>
<toolbox>
<data type="string">
<key>version</key>
<value>1.3</value>
</data>
<tool>
<!-- 类型名称 -->
<key>dictShow</key>
<!-- 作用域 -->
<scope>request</scope>
<!-- 映射 -->
<class>cn.yanxiaohui.DictVelocity</class>
</tool>
</toolbox>
7.视图层遍历数据(以velocity为例)
对于可编辑的页面(如新增/修改等)其使用如下:
<select name="userType">
#foreach($type in $!userType)
<option value="$!{type.value}"
#if($!{user.type }==${type.value})
selected
#end>
$!{weight.label}
</option>
#end
</select>
对于不可编辑的页面(如详情/列表等)其使用如下:
用户类型:$dictShow.label('userType',$!{user.type})