常量(数据字典)通过注解形式实现

注解形式实现

1.创建注解
/**
 * @author LiuB~
 * @Note 该注解为转化常量属性的值修改为常量的Name
 *
 * **/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Constant {
    /** 表名 **/
    String table_name();
    /** 列名 **/
    String field_name();

}
2.常量表sql
CREATE TABLE `bd_constant` (
  `id` varchar(36) NOT NULL COMMENT '表主键IDPK',
  `table_name` varchar(64) NOT NULL COMMENT '表名',
  `field_name` varchar(64) NOT NULL COMMENT '列名',
  `display_name` varchar(256) NOT NULL COMMENT '显示名称',
  `column_value` varchar(256) NOT NULL COMMENT '列值',
  `column_desc` varchar(256) DEFAULT NULL COMMENT '列说明',
  `order_num` int(11) NOT NULL DEFAULT '1' COMMENT '显示序号(升序)',
  `group_id` varchar(36) NOT NULL COMMENT '集团ID,引用自表:sys_group.id',
  `com_id` varchar(36) NOT NULL COMMENT '公司ID,引用自表:sys_company.id',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `create_user_id` varchar(36) DEFAULT NULL COMMENT '创建人id,引用自表:sys_employee.id',
  `create_user_name` varchar(64) DEFAULT NULL COMMENT '创建人姓名冗余',
  `modify_time` datetime DEFAULT NULL COMMENT '最后修改时间,用来控制是否被其他人修改过',
  `modify_user_id` varchar(36) DEFAULT NULL COMMENT '最后修改人id,引用自表:sys_employee.id',
  `modify_user_name` varchar(64) DEFAULT NULL COMMENT '最后修改人姓名冗余',
  `enabled` bit(1) NOT NULL DEFAULT b'1' COMMENT '启用标记(0停用,1启用)',
  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '删除标记(0未删除,1已删除)',
  `remark` varchar(256) DEFAULT NULL COMMENT '备注',
  `vdef1` varchar(256) DEFAULT NULL COMMENT '自定义字段',
  `vdef2` varchar(256) DEFAULT NULL COMMENT '自定义字段',
  `vdef3` varchar(256) DEFAULT NULL COMMENT '自定义字段',
  `vdef4` varchar(256) DEFAULT NULL COMMENT '自定义字段',
  `vdef5` varchar(256) DEFAULT NULL COMMENT '自定义字段',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='常量库';



3.注解的实现类
package com.yonan.bd.utils;

import com.alibaba.fastjson.JSON;
import com.yonan.bd.po.ConstantPO;
import com.yonan.bd.service.ConstantService;
import com.yonan.bd.vo.ConstantVO;
import com.yonan.common.annotations.Constant;
import com.yonan.common.utils.redis.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;


/**
 * @author LiuB~
 * 所有带上@Consant注解的常量转换
 **/

@Service
public class ConstantConversion {

    @Autowired
    ConstantService constantService;

    @Autowired
    RedisUtils redisUtils;

    /**
     *  想办法把数据加入缓存中(Redis)
     * 
     * 单个数据转换方法
     **/
    public void convertSingle(Object obj) {
        try {
            //取redis缓存中的数据
            Map<Object, Object> map = getConstantByRedisCache();
            if (null==map||map.size()<1){
                setConstantByRedis();
                map=getConstantByRedisCache();
            }
            if (null==map||map.size()<1){
                return;
            }
            Class<?> objClass = obj.getClass();
            List<Field> fieldsList = new ArrayList<Field>();
            while (objClass != null) {  // 遍历所有父类字节码对象
                Field[] declaredFields = objClass.getDeclaredFields();
                fieldsList.addAll(Arrays.asList(declaredFields));  //将`Filed[]`数组转换为`List<>`然后再将其拼接至`ArrayList`上
                objClass = objClass.getSuperclass();  // 获得父类的字节码对象
            }
            for (Field declaredField : fieldsList) {
                //被注解的属性名称(调用set方法)
                //循环该类下的所有属性包括父类看是否有Constant注解
                Constant annotation = declaredField.getAnnotation(Constant.class);
                if (null != annotation) {
                    //获取注解上原有字段的值
                    String objectMethod = getObjectMethod(obj, annotation.field_name());
                    //做拼接去查map
                    String key=annotation.table_name()+annotation.field_name()+objectMethod;
                    //由于取出来的数据无法直接转对象,所以先转成jsonString再转对象
                    ConstantVO constantVO = JSON.parseObject(JSON.toJSONString(map.get(key)), ConstantVO.class);
                    if (null != constantVO){
                        String display_name = constantVO.getDisplay_name();
                        setObjectMethod(obj,declaredField.getName(),display_name);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            e.getMessage();
        }
    }

    /**
     * 多条数据转换 for循环单个
     * **/
    public <T> void convertSingleList(List<T> list) {
        for (Object o : list) {
            convertSingle(o);
        }
    }


    /**
     * 获取属性值的get方法 return String
     **/
    public static String getObjectMethod(Object obj, String attribute_name) throws Exception {
        String getterName = "get" + firstCharToUpper(attribute_name);
        //获取该属性get方法取到的值
        Method method = obj.getClass().getMethod(getterName);
        return (String) method.invoke(obj);
    }

    /**
     * 塞入属性值的set方法
     **/
    public static void setObjectMethod(Object obj,String attribute_name,String set_value) throws Exception{
        String setterName ="set" +firstCharToUpper(attribute_name);
        Method declaredMethod = obj.getClass().getMethod(setterName,String.class);
        declaredMethod.invoke(obj, set_value);
    }

    /**
     * 首字母变成大写(string-->String)
     *
     * @param str
     * @return
     */
    public static String firstCharToUpper(String str) {
        if (str == null || str.equals(""))
            return str;
        char f = str.charAt(0);
        str = String.valueOf(f).toUpperCase() + str.substring(1);
        return str;
    }

    /**
     * 1.该怎么把数据库查出来的数据缓存到redis当中  √
     * 2.把map缓存到redis中后再取出来的过程是否正确,会不会出现乱码的现象  √
     * 3.怎么解决实际和缓存不同步的问题  通过在调用新增或者修改接口时更新redis缓存中的数据
     * **/
    public void setConstantByRedis(){
        //查询数据库信息
        List<ConstantPO> list = constantService.list();
        List<ConstantVO> constantVOS = constantService.poToVo(list);
        //为了防止在hm取值时因为时间出现异常
        for (ConstantVO constantVO : constantVOS) {
            constantVO.setCreate_time(null);
            constantVO.setModify_time(null);
        }
        Map<String, Object> map = constantService.listToMapByAdd(constantVOS);
        //调用redis工具类中的方法保存数据
        redisUtils.hmset("constant",map);
    }

    public Map<Object, Object> getConstantByRedisCache() {
        return redisUtils.hmget("constant");
    }

}


4.只需要在新创建的字段上加上注解就行,例如:
    @TableField(exist = false)
    @Constant(table_name = "bd_employee",field_name ="married")
    private String married_name;



5.redis工具类
涉及到RedisUtils的到Redis工具类中查看



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为您解答关于Java自定义字典类、自定义注解和反射注入字典值到实体类的问题。 首先,自定义字典类是一种将一些常量或者枚举类型的值封装在一起的方式。可以让代码更加易读、易维护。比如,我们可以定义一个字典类,用来存储一些常量值,如: ``` public class GenderDict { public static final Integer MALE = 1; public static final Integer FEMALE = 2; } ``` 接下来,我们可以使用自定义注解来标记需要注入字典值的实体类的属性上。比如,我们可以定义一个注解类,如: ``` @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Dictionary { String value(); } ``` 在该注解类中,我们使用@Retention和@Target注解来指定注解的保留策略和作用范围。同时,我们还可以使用value属性来指定注解的值,即该属性需要注入的字典值的名称。 最后,我们可以使用反射机制,在运行时动态地将字典值注入到实体类中。具体的实现方式如下: ``` public class DictionaryInjector { public static void injectDictionary(Object obj) throws IllegalAccessException { Class<?> clazz = obj.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(Dictionary.class)) { Dictionary dict = field.getAnnotation(Dictionary.class); String dictName = dict.value(); String dictValue = getDictValue(dictName); field.setAccessible(true); field.set(obj, dictValue); } } } private static String getDictValue(String dictName) { // 从字典类中获取对应的字典值 // 这里可以使用反射或者其他方式来实现 return GenderDict.MALE.equals(dictName) ? "男" : "女"; } } ``` 在上述代码中,我们首先使用Class对象获取实体类的所有属性,然后通过判断该属性是否被@Dictionary注解标记来确定是否需要注入字典值。如果需要注入,则从注解中获取字典值的名称,然后通过反射机制将字典值注入到实体类的属性中。 最后,我们可以在代码中使用如下方式来注入字典值: ``` public class User { @Dictionary("gender") private String gender; // getters and setters } public class Main { public static void main(String[] args) throws IllegalAccessException { User user = new User(); DictionaryInjector.injectDictionary(user); System.out.println(user.getGender()); // 输出 "男" } } ``` 在上述代码中,我们首先定义了一个User类,并在其中使用@Dictionary注解标记了gender属性。然后,在Main类中,我们创建了一个User对象,并调用DictionaryInjector类的injectDictionary方法来注入字典值。最后,我们通过调用User对象的getGender方法来获取注入后的字典值。 希望这能够帮助您解决问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值