版權聲明:本文為博主原創文章,轉載請注明出處,歡迎使勁噴
一、為啥用枚舉&為啥要對枚舉進行治理
1.先來說說為啥用枚舉
表中某個字段標識了這條記錄的狀態,我們往往使用一些code值來標識,例如01成功,00失敗。
多狀態共性的東西可以常量保存,例如
class Constants{
public static final String success = "01"; public static final String failure= "00"; }
然而,在一些大型項目中,表的數量極多,一些表中需要維護的狀態也極多,如果都在如上的Constants中維護,試想如果添加一個狀態值,那么需要在整個篇幅中找到對應的塊,然后去新增值;修改呢?同樣麻煩!!!
所以我們使用枚舉,每個枚舉類就只負責對一個狀態做維護,這樣我們方便增刪改。例如:
/**
* Created by Bright on 2017/3/13.
*
* @author :
*/
public enum Payment {
Payment_WX("010000","微信支付"), Payment_ZFB("010001","支付寶支付"), Payment_YL("010002","銀聯支付"); public static Map<String,String> map = new HashMap<String, String>(); static{ Payment[] values = Payment.values(); if(values.length > 0){ for(Payment product : values){ map.put(product.getCode(),product.getName()); } } } Payment(String code, String name){ this.code = code; this.name = name; } private String code; private String name; public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
2.為啥要用java反射處理枚舉呢?
我們之前看到了,使用Constants很方便,可以直接通過這個類的靜態字段拿到值。當我們使用枚舉時,當枚舉類逐漸增多時,我們會發現,不同的地方我們需要獲取不同的類,然后再通過不同的枚舉獲取到不同的值。這又勢必是個頭痛的事情。
那么我們想到了改進的方法:
改進一:把每個枚舉類中放個map,把其code和name值映射進去,然后調用時通過靜態map對象,把code值作為key傳入,勢必能獲取到對應的描述。(如上段代碼的map值)
然而,這個改進后,我們依舊需要找到這個類,然后去使用它的靜態map,能不能只通過一個類進行統一治理呢?
改進二:通過一個類,把所有枚舉在該類中注冊,然后通過該類直接獲取到相應的枚舉值及name描述。
二、枚舉治理的實現
1.先弄清我們使用枚舉的場景
1.1通過枚舉類中枚舉名獲取到枚舉的code值(使用上面的枚舉值定義)
例如:{"Payment_WX":"010000","Payment_YL":"010002","Payment_ZFB":"010001"}
if(param.equals(Payment.Payment_WX.getCode()){}
1.2通過枚舉類中枚舉的code值獲取到對應的name描述(使用上面的枚舉值定義)
例如:{"010002":"銀聯支付","010001":"支付寶支付","010000":"微信支付"}
Payment.map.get(Payment.Payment_WX.getCode());
2.枚舉治理工具類的實現
/**
* Created by Bright on 2017/3/13.
*
* @author :
*/
public class VelocityEnumTools {
public static final Logger logger = LoggerFactory.getLogger(VelocityEnumTools.class); //通過枚舉獲取枚舉code值,例如:{"Payment_WX":"010000","Payment_YL":"010002","Payment_ZFB":"010001"} public static Map<String,Map<String,String>> mapKeyCode = new HashMap<String, Map<String, String>>(); //通過code值獲取枚舉name,例如:{"010002":"銀聯支付","010001":"支付寶支付","010000":"微信支付"} public static Map<String, Map<String, String>> mapCodeName = new HashMap<String, Map<String, String>>(); /** * 需要在頁面控制的enum,如Payment類似添加即可 */ static { //通過枚舉獲取code值 mapKeyCode.put(Payment.class.getSimpleName(), getEnumMap(Payment.class)); //通過code值獲取枚舉name mapCodeName.put(Payment.class.getSimpleName(),getEnumCodeMap(Payment.class)); } /** * 通過枚舉獲取code值 * @param enumKey * @return */ public static Map<String, String> getKeyCodeMapperInstance(String enumKey) { return mapKeyCode.get(enumKey); } /** * 通過code值獲取枚舉name * @param enumKey * @return */ public static Map<String, String> getCodeNameMapperInstance(String enumKey) { return mapCodeName.get(enumKey); } public static <T> Map<String, String> getEnumMap(Class<T> clazz) { Map<String, String> map = new HashMap<String, String>(); try { if (clazz.isEnum()) { Object[] enumConstants = clazz.getEnumConstants(); for (int i = 0; i < enumConstants.length; i++) { T t = (T) enumConstants[i]; Field code = t.getClass().getDeclaredField("code"); code.setAccessible(true); map.put(t.getClass().getDeclaredFields()[i].getName(), (String) code.get(t)); } } } catch (NoSuchFieldException e) { logger.error("枚舉工具啟動報錯:{}", e); } catch (IllegalAccessException e) { logger.error("枚舉工具啟動報錯:{}", e); } return map; } private static <T> Map<String,String> getEnumCodeMap(Class<T> clazz) { Map<String, String> map = new HashMap<String, String>(); try { if (clazz.isEnum()) { Object[] enumConstants = clazz.getEnumConstants(); for (int i = 0; i < enumConstants.length; i++) { T t = (T) enumConstants[i]; Field code = t.getClass().getDeclaredField("code"); Field name = t.getClass().getDeclaredField("name"); code.setAccessible(true); name.setAccessible(true); map.put((String) code.get(t),(String) name.get(t)); } } } catch (NoSuchFieldException e) { logger.error("枚舉工具啟動報錯:{}", e); } catch (IllegalAccessException e) { logger.error("枚舉工具啟動報錯:{}", e); } return map; } public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Map<String, String> enumMap = getEnumMap(Payment.class); System.out.println(JSON.toJSONString(enumMap));//{"Payment_WX":"010000","Payment_YL":"010002","Payment_ZFB":"010001"} Map<String, String> enumCodeMap = getEnumCodeMap(Payment.class); System.out.println(JSON.toJSONString(enumCodeMap));//{"010002":"銀聯支付","010001":"支付寶支付","010000":"微信支付"} } }
三、枚舉治理的擴展-velocity中使用枚舉
1.為什么會在velocity中使用枚舉
當涉及與前端的交互時,我們可能需要從前端把三種支付方式對應的code值傳到后台。
此時,如果在頁面上直接寫010000這樣的值,那么頁面的邏輯就很不直觀了,今天寫的時候你還能認知,為了防止自己忘了,除了加注釋別無辦法。
故,為了解決后台可用,且前端頁面直觀,所以我們希望嘗試在頁面上直接用枚舉來解決問題。
2.看看頁面如何處理(velocity頁面中)
#set($payment=$enumTool.getCodeNameMapperInstance("Payment"))//直接寫明要獲取的枚舉類型名稱
#if($payment.get("Payment_WX") == $param.code)//通過枚舉值獲取其code值 //做微信支付頁面邏輯 #end
2.velocity中配置velocity-tools
<?xml version="1.0" encoding="UTF-8"?> <toolbox> <tool> <key>enumTool</key> <class>com.bright.core.enumconstant.VelocityEnumTools</class> </tool> <tool> <key>stringTool</key> <class>org.apache.commons.lang.StringUtils</class> </tool> <tool> <key>dateTool</key> <class>org.apache.velocity.tools.generic.DateTool</class> </tool> </toolbox>
這樣就可以簡單的在頁面中應用我們枚舉治理工具了。
例如:通過code值獲取到相應描述
$enumTool.getCodeNameMapperInstance("Payment").get($item.orderLoanStatus)//顯示“微信支付”
通過枚舉獲取到對應的code值
#set($payment=$enumTool.getCodeNameMapperInstance("Payment"))//拿到了Payment的map
$payment.get("Payment_WX")
就此,我們可以實現系統的中的枚舉治理,並且可在前端頁面靈活應用。