spring Cache + Redis 开发数据字典以及自定义标签
一、数据库表结构
1、 分类表:dict_type
2、 子项表:dict_entry
二、页面维护功能示意图:
1、 分类管理 点击子项管理进入子项管理页面
2、子项管理
三、数据字典添加到缓存:
数据字典为了读取效率高效,减少与数据库的交互,通常会把数据字典所有数据添加到缓存当中,如果是一台服务器部署,只需放到本机中就可以,如果需要部署到多台服务器分布式部署的话需要把数据字典同步到Redis服务器中。
1、 springboot 在dictTypeService中把数据字典放到本机缓存中
对数据字典进行增删改查时需要调用refreshDictCache()方法来刷新缓存,保证缓存中数据为最新数据
2、 如果使用springboot + Redis做缓存的使用的方法,在dictTypeService中把数据字典放到Redis服务器中
@Cacheable(value="dictEntry", key="T(String).valueOf('dictEntryMap')")
使用此注解调用此方法时,系统会先从Redis服务器获取数据字典,如果取不到数据,系统会再去数据库读取。
@CacheEvict(value="dictEntry", key="T(String).valueOf('dictTypeNameMap')")
方法使用此注解,对数据字典进行增删改查时,系统会自动同步到Redis服务器,保证数据库数据与redis数据保持一致。
三、把数据字典做成自定义标签
1、 创建辅助类(自定义标签调用)
package com.hydwltech.iems.epum.common.utils; import java.util.ArrayList;
import java.util.List; import org.apache.commons.lang.StringUtils; import com.hydwltech.iems.epum.entity.dict.DictEntryOV;
import com.hydwltech.iems.epum.service.dict.DictTypeService; /**
* 数据字典工具类
**/
public class DictUtil {
private static DictTypeService getDictTypeService() {
return SpringWebContextUtil.getApplicationContext().getBean(DictTypeService.class);
} /**
* 根据类型编码获取子项列表
*
* @param dictTypeCode 类型编码
* @return List<{@link DictEntryOV}}> 子项数据对象
*/
@SuppressWarnings("unchecked")
public static List<DictEntryOV> getDictEntryList(String dictTypeCode) {
return (List<DictEntryOV>) getDictTypeService().getDictEntryMap().get(dictTypeCode);
} /**
* 根据类型编码和子项编码获得子项名称
*
* @param dictTypeCode 类型编码
* @param dictEntryCode 子项编码
* @return String 子项名称
*/
public static String getDictEntryName(String dictTypeCode, String dictEntryCode) {
if (StringUtils.isBlank(dictTypeCode)) {
return null;
}
if (StringUtils.isBlank(dictEntryCode)) {
return null;
}
List<DictEntryOV> ovlist = (List<DictEntryOV>) getDictTypeService().getDictEntryMap().get(dictTypeCode);
String entryCode = null;
if (isInteger(dictEntryCode)) {
List<String> nameMapKeys = new ArrayList<String>();
for (DictEntryOV dictOv : ovlist) {
String[] names = dictOv.getDictEntryCode().split(",");
boolean namesIsInt = true;
for (int i = 0; i < names.length; i++) {
if (!isInteger(names[i])) {
namesIsInt = false;
break;
}
}
if (namesIsInt) {
nameMapKeys.add(dictOv.getDictEntryCode());
}
} for (String parm : nameMapKeys) {
if (parm.split(",").length == 1) {
int parm1 = Integer.parseInt(parm.split(",")[0]);
if (Integer.parseInt(dictEntryCode) == parm1) {
entryCode = parm;
}
} else if (parm.split(",").length == 2) {
int parm1 = Integer.parseInt(parm.split(",")[0]);
int parm2 = Integer.parseInt(parm.split(",")[1]);
if (Integer.parseInt(dictEntryCode) >= parm1 && Integer.parseInt(dictEntryCode) <= parm2) {
entryCode = parm;
}
}
}
} else {
entryCode = dictEntryCode;
} String entryName = null;
if (StringUtils.isNotBlank(entryCode)) {
for (DictEntryOV dictEntryOV : ovlist) {
if (entryCode.equals(dictEntryOV.getDictEntryCode())) {
entryName = dictEntryOV.getDictEntryName();
}
}
} return entryName;
} /**
* 根据类型编码和子项编码获得子项对象
*
* @param dictTypeCode 类型编码
* @param dictEntryCode 子项编码
* @return DictEntryOV 子项名称
*/
public static DictEntryOV getDictEntry(String dictTypeCode, String dictEntryCode) {
if (StringUtils.isBlank(dictTypeCode)) {
return null;
}
if (StringUtils.isBlank(dictEntryCode)) {
return null;
}
List<DictEntryOV> ovlist = (List<DictEntryOV>) getDictTypeService().getDictEntryMap().get(dictTypeCode);
DictEntryOV entryOv = null;
for (DictEntryOV dictEntryOV : ovlist) {
if (dictEntryCode.equals(dictEntryOV.getDictEntryCode())) {
entryOv = dictEntryOV;
}
}
return entryOv;
} /**
* 根据类型编码和子项编码获得子项名称
*
* @param dictTypeCodeAndEntryCode 类型编码和子项编码合成字符串两个变量已逗号隔开
* @return String 子项名称
*/
public static String getDictEntryNameByCodes(String dictTypeCodeAndEntryCode) {
if (StringUtils.isBlank(dictTypeCodeAndEntryCode)) {
return null;
}
String[] params = dictTypeCodeAndEntryCode.split(",");
String dictTypeCode = params[0];
String dictEntryCode = params[1];
List<DictEntryOV> ovlist = (List<DictEntryOV>) getDictTypeService().getDictEntryMap().get(dictTypeCode);
String entryName = null;
for (DictEntryOV dictEntryOV : ovlist) {
if (dictEntryCode.equals(dictEntryOV.getDictEntryCode())) {
entryName = dictEntryOV.getDictEntryName();
}
}
return entryName;
} /**
* 根据类型编码获得类型名称
*
* @param dictTypeCode 类型编码
* @return String 子项名称
*/
public static String getDictTypeName(String dictTypeCode) {
if (StringUtils.isBlank(dictTypeCode)) {
return null;
}
String type = (String) getDictTypeService().getDictTypeNameMap().get(dictTypeCode);
return type; } /**
* 根据类型编码和子项名称获得子项类型编码
*
* @param dictTypeCode 类型编码
* @param dictEntryName 子项名称
* @return String 子项编码
*/
public static String getDictEntryCodeByEntryName(String dictTypeCode, String dictEntryName) {
if (StringUtils.isBlank(dictTypeCode)) {
return null;
}
if (StringUtils.isBlank(dictEntryName)) {
return null;
}
List<DictEntryOV> ovlist = (List<DictEntryOV>) getDictTypeService().getDictEntryMap().get(dictTypeCode);
String entryCode = null;
for (DictEntryOV ov : ovlist) {
if (dictEntryName.equals(ov.getDictEntryName())) {
entryCode = ov.getDictEntryCode();
}
}
return entryCode;
} /** 验证是否是整数 */
private static boolean isInteger(String param) {
try {
Integer.valueOf(param);
return true;
} catch (Exception e) {
// TODO: handle exception
}
return false;
}
}
2、 自定义JSTL标签类
(1)需要定义几个标签,就写几个独立的标签类
(2)定义标签类,在页面输出下拉菜单数据
package com.hydwltech.iems.epum.common.utils.tag; import java.util.List; import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport; import com.hydwltech.iems.epum.common.utils.DictUtil;
import com.hydwltech.iems.epum.entity.dict.DictEntryOV; public class ValueDictEntryListUtil extends TagSupport{ /**
*
*/
private static final long serialVersionUID = 1L; private String var; @Override
public int doStartTag() throws JspException {
try {
StringBuffer strBuffer = new StringBuffer();
List<DictEntryOV> ovList = DictUtil.getDictEntryList(var);
for (int i = 0; i < ovList.size(); i++) {
strBuffer.append("<li>");
strBuffer.append("<a href=\"###\" value="+ovList.get(i).getDictEntryCode()+">" + ovList.get(i).getDictEntryName() + "</a>");
strBuffer.append("</li>");
}
pageContext.getOut().print(strBuffer.toString());
} catch (Exception e) {
// TODO: handle exception
}
return EVAL_BODY_INCLUDE;
} public String getVar() {
return var;
} public void setVar(String var) {
this.var = var;
}
}
(3)、创建tld文件
在WEB-INF下创建tld文件 dict.tld
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>1.0</tlib-version><!-- 标签库版本 -->
<jsp-version>1.2</jsp-version> <!-- 标签库要求的JSP规范版本 -->
<short-name>dict</short-name> <!-- JSP页面编写工具可以用来创建助记名的可选名字 -->
<!--
为自定义标签库设置一个uri,uri以/开头,/后面的内容随便写,如这里的/gacl ,
在Jsp页面中引用标签库时,需要通过uri找到标签库
在Jsp页面中就要这样引入标签库:
<%@taglib uri="/security/encrypt" prefix="encrypt"%>
-->
<!-- <uri>/security/encrypt</uri> -->
<tag>
<name>entry</name>
<tag-class>com.hydwltech.iems.epum.common.utils.tag.ValueDictEntryNameUtil</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>typeCode</name>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>entryCode</name>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag> <tag>
<name>type</name>
<tag-class>com.hydwltech.iems.epum.common.utils.tag.ValueDictTypeNameUtil</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>var</name>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag> <tag>
<name>select</name>
<tag-class>com.hydwltech.iems.epum.common.utils.tag.ValueDictEntryListUtil</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>var</name>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
(4)、JSP页面调用标签
A、导入自定义标签
<%@ taglib prefix="dict" uri="/WEB-INF/tag/dict.tld"%>
B、下拉菜单调用此标签
<dict:select var="equipEablePatrol"/>
效果如下图:
除了下拉菜单标签,还可以根据自己的需求开发其他自定义标签。
四、相关技术链接
关于自定义标签转自:https://blog.csdn.net/bilahepan/article/details/54801540
关于Springboot + cacheable + Redis转自:https://blog.csdn.net/moshowgame/article/details/80792774
spring Cache + Redis 开发数据字典以及自定义标签的更多相关文章
- Spring事务(二)事务自定义标签
摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.注册 InfrastructureAdvisorAutoPr ...
- spring cache redis
一.使用开源包(spring-data-redis) 1.引入jar包 <dependency> <groupId>org.springframework.data& ...
- spring Cache /Redis 缓存 + Spring 的集成示例
spring Cache https://www.ibm.com/developerworks/cn/opensource/os-cn-spring-cache/ spring+redis 缓存 ht ...
- Spring Cache Redis结合遇到的坑
业务上需要把一些数据放到redis里面,但是系统逻辑代码差不多编写完成了,怎么整?用Spring Cache啊,对既有业务逻辑侵袭极小. 于是尝试调查了一下,遇到一些问题分享一下(本文使用Spring ...
- 【快学SpringBoot】Spring Cache+Redis实现高可用缓存解决方案
前言 之前已经写过一篇文章介绍SpringBoot整合Spring Cache,SpringBoot默认使用的是ConcurrentMapCacheManager,在实际项目中,我们需要一个高可用的. ...
- 使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的解决
应用场景 我们希望通过缓存来减少对关系型数据库的查询次数,减轻数据库压力.在执行DAO类的select***(), query***()方法时,先从Redis中查询有没有缓存数据,如果有则直接从Red ...
- javaweb学习总结(二十三)——jsp自定义标签开发入门
一.自定义标签的作用 自定义标签主要用于移除Jsp页面中的java代码. 二.自定义标签开发和使用 2.1.自定义标签开发步骤 1.编写一个实现Tag接口的Java类(标签处理器类) 1 packag ...
- javaweb(二十三)——jsp自定义标签开发入门
一.自定义标签的作用 自定义标签主要用于移除Jsp页面中的java代码. 二.自定义标签开发和使用 2.1.自定义标签开发步骤 1.编写一个实现Tag接口的Java类(标签处理器类) 1 packag ...
- Spring整合Redis&JSON序列化&Spring/Web项目部署相关
几种JSON框架用法和效率对比: https://blog.csdn.net/sisyphus_z/article/details/53333925 https://blog.csdn.net/wei ...
随机推荐
- wpf中datagrid绑定数据源发生改变
1.若datagrid绑定的数据源是同一个的话,即使里面的数据不同.页面也不会刷新,则需要重置数据源,再绑定.处理如下: datagrid1.ItemsSource=ListModule; 若List ...
- python--面向对象:多态与封装
一.多态 :python 天生支持多态多态指的是一类事物有多种形态 eg:文件有多种形态:文本文件,可执行文件鸭子类型:python中崇尚鸭子类型,不崇尚根据继承所得来的相似 优点 : 松耦合 每个相 ...
- Web开发常规调试方法与常见问题分析
一.Web项目基本原理 现在的web项目大都已经前后端独立开发与部署. 前后端独立开发,一般是前端与后端通过web接口(常见的有RESTful与websocket)文档进行交流.前端开发人员先更具业务 ...
- Vue双向数据绑定原理深度解析
首先,什么是双向数据绑定?Vue是三大MVVM框架之一,数据绑定简单来说,就是当数据发生变化时,相应的视图会进行更新,当视图更新时,数据也会跟着变化. 在分析其原理和代码的时候,大家首先了解如下几个j ...
- 对象拷贝extend
如果想要把某个对象拷贝(合并)给另外一个对象使用,此时可以使用$.extend()方法 语法: $.extend([deep],target,object1,[objectN]); 1.deep:如果 ...
- SpringMVC和spring常见面试题总结
1.什么是Spring MVC ?简单介绍下你对springMVC的理解? Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,C ...
- 「题解」:毛一琛/$cow$ $subsets$
问题 A: 毛一琛/$cow$ $subsets$ 时间限制: 1 Sec 内存限制: 512 MB 题面 题面谢绝公开. 题解 题名貌似是个大神??看起来像是签到题然后就死了. 首先$O(3^n) ...
- NX二次开发-UFUN创建B面UF_MODL_create_bsurf
NX9+VS2012 #include <uf.h> #include <uf_modl.h> //创建一个B面 ;//U方向极数 ;//V方向极数 ;//U方向规则 ;//V ...
- 执行SQL语句---SELECT
1.通常从MySQL数据库中检索数据有4个步骤: (1)发出查询: 用mysql_query发出查询. (2)检索数据: 用mysql_store_result/mysql_use_result (3 ...
- hexo next主题深度优化(四),自定义一个share功能,share.js。
文章目录 背景: 开始: 引入资源: 代码 关键的一步 附:方便学习的小demo 一次成功后还出现上面的bug 结束 2018.12.23发现bug(读者可忽略) 个人博客:https://mmmmm ...