举例
<el-form-item label="角色顺序" prop="roleSort">
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in statusOptions"
:key="dict.dictValue"
:label="dict.dictValue"
>{
{
dict.dictLabel}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="菜单权限">
status字段是从statusOptions
中获取的,该字段是在vue文件中,初始化完成的。
created() {
this.getList();
this.getDicts("sys_normal_disable").then(response => {
this.statusOptions = response.data;
});
},
this.getDicts
这个方法并没有导入到vue文件中,这个方法是如何被调用的?
其实,这个方法是被加载到全局环境中的,所有的vue文件,不需要引用,也可以调用。
main.js中
挂载了很多全局方法
import {
getDicts } from "@/api/system/dict/data";
import {
getConfigKey } from "@/api/system/config";
import {
parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
// 全局方法挂载
Vue.prototype.getDicts = getDicts
Vue.prototype.getConfigKey = getConfigKey
Vue.prototype.parseTime = parseTime
Vue.prototype.resetForm = resetForm
...以下内容省略...
获取字典数据,转换时间,充值表格,都在这里定义。
重点关注这个:import { getDicts } from "@/api/system/dict/data";
date.js
中定义了getDicts
方法
// 根据字典类型查询字典数据信息
export function getDicts(dictType) {
return request({
url: '/system/dict/data/type/' + dictType,
method: 'get'
})
}
继续跟进,跳到 SysDictDataController
,里面定义了具体的处理方法。
/**
* 根据字典类型查询字典数据信息
*/
@GetMapping(value = "/type/{dictType}")
public AjaxResult dictType(@PathVariable String dictType)
{
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
if (StringUtils.isNull(data))
{
data = new ArrayList<SysDictData>();
}
return AjaxResult.success(data);
}
跳转到具体的service实现类 SysDictTypeServiceImpl
@Override
public List<SysDictData> selectDictDataByType(String dictType)
{
List<SysDictData> dictDatas = DictUtils.getDictCache(dictType);
if (StringUtils.isNotEmpty(dictDatas))
{
return dictDatas;
}
dictDatas = dictDataMapper.selectDictDataByType(dictType);
if (StringUtils.isNotEmpty(dictDatas))
{
DictUtils.setDictCache(dictType, dictDatas);
return dictDatas;
}
return null;
}
DictUtils.getDictCache(dictType)
是从redis中获取缓存数据,这个方法如下:
/**
* 获取字典缓存
*
* @param key 参数键
* @return dictDatas 字典数据列表
*/
public static List<SysDictData> getDictCache(String key)
{
Object cacheObj = SpringUtils.getBean(RedisService.class).getCacheObject(getCacheKey(key));
if (StringUtils.isNotNull(cacheObj))
{
List<SysDictData> dictDatas = StringUtils.cast(cacheObj);
return dictDatas;
}
return null;
}
为什么redis里有缓存内?
那是因为在SysDictTypeServiceImpl
中定义了初始化方法
/**
* 项目启动时,初始化字典到缓存
*/
@PostConstruct
public void init()
{
loadingDictCache();
}
/**
* 加载字典缓存数据
*/
@Override
public void loadingDictCache()
{
List<SysDictType> dictTypeList = dictTypeMapper.selectDictTypeAll();
for (SysDictType dictType : dictTypeList)
{
List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType());
DictUtils.setDictCache(dictType.getDictType(), dictDatas);
}
}
@PostConstruct
注解:用来修饰一个 非静态
的,返回值为 void
,没有任何入参,不抛出任何异常的方法()。bean创建完成空对象,就开始进行@Autowire、@PostConstruct赋值(顺序执行,先执行@Autowire)。
dictTypeMapper.selectDictTypeAll()
执行的SQL语句:
<sql id="selectDictTypeVo">
select dict_id, dict_name, dict_type, status, create_by, create_time, remark
from sys_dict_type
</sql>
<select id="selectDictTypeAll" resultMap="SysDictTypeResult">
<include refid="selectDictTypeVo"/>
</select>
List dictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType());
这个方法是把遍历上面查出来的dict_type,再去查询各自对应的值,然后存入list中,最后把 dict_type当作 key,查出来的集合当作value,存入redis中。
SQL语句如下:
<sql id="selectDictDataVo">
select dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark
from sys_dict_data
</sql>
<select id="selectDictDataByType" parameterType="SysDictData" resultMap="SysDictDataResult">
<include refid="selectDictDataVo"/>
where status = '0' and dict_type = #{dictType} order by dict_sort asc
</select>
可以看到,sys_dict_type
和sys_dict_data
存在着外键关系,是一对多的关系。
我们也找到了 sys_normal_disable
对应的值。
也可以在缓存中查询出来:
你也许会问,为什么redis中的key前面有sys_dict:
前缀,它是哪里来的?
这个,我们要去
DictUtils.setDictCache(dictType.getDictType(), dictDatas);
DictUtils.java
/**
* 设置字典缓存
*
* @param key 参数键
* @param dictDatas 字典数据列表
*/
public static void setDictCache(String key, List<SysDictData> dictDatas)
{
SpringUtils.getBean(RedisService.class).setCacheObject(getCacheKey(key), dictDatas);
}
我们发现 setCacheObject中有个 setCacheObject(key)
方法,莫非是它导致的?
进去看看:
/**
* 设置cache key
*
* @param configKey 参数键
* @return 缓存键key
*/
public static String getCacheKey(String configKey)
{
return Constants.SYS_DICT_KEY + configKey;
}
咦,这里好像定义了一个常量,进去看看:
Constants.java
/**
* 字典管理 cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
至此,从缓存中读取数据的代码逻辑总算搞懂了。
那,如果缓存中没有读取到数据的代码逻辑是什么样子的呢?
<sql id="selectDictDataVo">
select dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark
from sys_dict_data
</sql>
<select id="selectDictDataByType" parameterType="SysDictData" resultMap="SysDictDataResult">
<include refid="selectDictDataVo"/>
where status = '0' and dict_type = #{
dictType} order by dict_sort asc
</select>
前台传入的 dictType = sys_normal_disable
后续java代码
dictDatas = dictDataMapper.selectDictDataByType(dictType);
if (StringUtils.isNotEmpty(dictDatas))
{
DictUtils.setDictCache(dictType, dictDatas);
return dictDatas;
}
return null;
依然判断dictDatas 是否为空,如果不为空,就将其存入缓存中,然后返回。
至此,所有的代码逻辑全部跑通。