由于业务的原因,导致程序中有很多枚举,不便维护,故使用自定义的字典表

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})