百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Java开发中常见的几种替换字典值替换的方法,你会几招?

lipiwang 2024-11-01 14:12 7 浏览 0 评论

前提引入:「开发思路」Java 开发中你是如何处理字典值释义的?

业务场景:在后期的运维维护中,发现创建人在业务表中使用的不是 创建人ID 或 创建人名称,而是使用的是 账号名,而 账号名虽说是唯一的,但全是英文/拼音存储的不满足业务需求,业务需求是需要现在是用户的姓名,你说这……是不是很无语呢?

当然有人会说了,为了查询方便,插入的时候就应该改动过来,然后做一下数据梳理,将数据库的数据找个空闲时间讲创建人ID/创建人账号名处理成存为创建人名称,你说这是不是很好?好好好,当然好,但不是本文的讨论的重点哦

本文讨论重点:基于已运行的系统在查询的时候做一些处理的几种方法。如果有兴趣可以继续了解,欢迎评论探讨!

文章说明:文章只讨论实现思路,不做具体完整的实现案例展示。

零、数据库数据准备

(1)字典表(sys_dict)

CREATE TABLE `sys_dict` (
  `id` int(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `type` varchar(100) DEFAULT NULL,
  `description` varchar(100) DEFAULT NULL,
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `remarks` varchar(255) DEFAULT NULL,
  `system` char(1) DEFAULT '0',
  `del_flag` char(1) DEFAULT '0',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `sys_dict_del_flag` (`del_flag`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='字典表';

-- 添加测试数据
INSERT INTO pig.sys_dict (`type`,description,create_time,update_time,remarks,`system`,del_flag) VALUES
	 ('dict_type','字典类型','2019-05-16 14:16:20','2019-05-16 14:20:16','系统类不能修改','1','0'),
	 ('log_type','日志类型','2020-03-13 14:21:01','2020-03-13 14:21:01','0-正常 1 异常','1','0');

(2)字典值表(sys_dict_item)

CREATE TABLE `sys_dict_item` (
  `id` int(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `dict_id` int(11) NOT NULL,
  `value` varchar(100) DEFAULT NULL,
  `label` varchar(100) DEFAULT NULL,
  `type` varchar(100) DEFAULT NULL,
  `description` varchar(100) DEFAULT NULL,
  `sort` int(10) NOT NULL DEFAULT '0' COMMENT '排序(升序)',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `remarks` varchar(255) DEFAULT NULL,
  `del_flag` char(1) DEFAULT '0',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `sys_dict_value` (`value`) USING BTREE,
  KEY `sys_dict_label` (`label`) USING BTREE,
  KEY `sys_dict_del_flag` (`del_flag`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='字典项';

-- 添加测试数据字典值项目
INSERT INTO pig.sys_dict_item (dict_id,value,label,`type`,description,sort,create_time,update_time,remarks,del_flag) VALUES
	 (1,'1','系统类','dict_type','系统类字典',0,'2019-05-16 14:20:40','2019-05-16 14:20:40','不能修改删除','0'),
	 (1,'0','业务类','dict_type','业务类字典',0,'2019-05-16 14:20:59','2019-05-16 14:20:59','可以修改','0'),
	 (2,'0','正常','log_type','正常',0,'2020-03-13 14:23:22','2020-03-13 14:23:22','正常','0'),
	 (2,'9','异常','log_type','异常',1,'2020-03-13 14:23:35','2020-03-13 14:23:35','异常','0');

(3)业务表:系统日志

CREATE TABLE `sys_log` (
  `id` bigint(64) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `type` char(1) DEFAULT '1' COMMENT '日志类型',
  `title` varchar(255) DEFAULT '' COMMENT '日志标题',
  `service_id` varchar(32) DEFAULT NULL COMMENT '服务ID',
  `create_by` varchar(64) DEFAULT NULL COMMENT '创建者',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `remote_addr` varchar(255) DEFAULT NULL COMMENT '操作IP地址',
  `user_agent` varchar(1000) DEFAULT NULL COMMENT '用户代理',
  `request_uri` varchar(255) DEFAULT NULL COMMENT '请求URI',
  `method` varchar(10) DEFAULT NULL COMMENT '操作方式',
  `params` text COMMENT '操作提交的数据',
  `time` mediumtext COMMENT '执行时间',
  `del_flag` char(1) DEFAULT '0' COMMENT '删除标记',
  `exception` text COMMENT '异常信息',
  PRIMARY KEY (`id`),
  KEY `sys_log_create_by` (`create_by`),
  KEY `sys_log_request_uri` (`request_uri`),
  KEY `sys_log_type` (`type`),
  KEY `sys_log_create_date` (`create_time`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='日志表';

-- 测试业务日志表数据插入
INSERT INTO pig.sys_log (`type`,title,service_id,create_by,create_time,update_time,remote_addr,user_agent,request_uri,`method`,params,`time`,del_flag,`exception`) VALUES
	 ('0','添加角色','pig','admin','2021-06-04 10:43:05',NULL,'127.0.0.1','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 Edg/91.0.864.37','/role','POST','','6','0',NULL);

一、数据库SQL直接联查替换

-- 方式一,直接查询的时候处理
select 
	id 
	, (select label from sys_dict_item sdi where `type` = 'log_type' and sdi.value = sl.`type`) as logLabel
from sys_log sl ;

-- 方式二,关联查询1
select 
	sl.id
	, sdi.label as logLabel
from sys_log sl 
left join sys_dict_item sdi on sl.`type` = sdi.value and sdi.`type` = 'log_type' ;

-- 方式三:关联查询2
select id
	, sdit.label as logLabel
from sys_log sl 
left join (
	select value, label from sys_dict_item sdi where sdi.`type` = 'log_type'
) as sdit on sl.`type` = sdit.value

二、mybatis XML 文件 typyHandler 替换处理

自定义一个类型转换器,处理数据替换问题。

(1)创建一个自定义的TypeHandler

import org.apache.ibatis.type.BaseTypeHandler;  
import org.apache.ibatis.type.JdbcType;  
import java.sql.CallableStatement;  
import java.sql.PreparedStatement;  
import java.sql.ResultSet;  
import java.sql.SQLException;  
  
public class YesNoTypeHandler extends BaseTypeHandler<Boolean> {  
  
    // 从 ResultSet 读取数据并转换为 Java 类型  
    @Override  
    public Boolean getNullableResult(ResultSet rs, String columnName) throws SQLException {  
        String value = rs.getString(columnName);  
        return "Y".equalsIgnoreCase(value);  
    }  
  
    @Override  
    public Boolean getNullableResult(ResultSet rs, int columnIndex) throws SQLException {  
        String value = rs.getString(columnIndex);  
        return "Y".equalsIgnoreCase(value);  
    }  
  
    @Override  
    public Boolean getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {  
        String value = cs.getString(columnIndex);  
        return "Y".equalsIgnoreCase(value);  
    }  
  
    // 将 Java 类型转换为数据库类型  
    @Override  
    public void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType) throws SQLException {  
        ps.setString(i, parameter ? "Y" : "N");  
    }  
  
    // 指定该处理器处理的 Java 类型  
    @Override  
    public Class<Boolean> getRawType() {  
        return Boolean.class;  
    }  
  
    // 指定该处理器处理的 JDBC 类型(可选)  
    @Override  
    public JdbcType getJdbcType() {  
        return JdbcType.VARCHAR;  
    }  
}

(2)mybatis-config.xml 中配置 或者 SpringBoot 配置类型转换器存放目录包

<typeHandlers>  
    <typeHandler handler="com.example.YesNoTypeHandler" javaType="java.lang.Boolean" jdbcType="VARCHAR"/>  
</typeHandlers>
@MapperScan(basePackages = "com.example.mapper", typeHandlersPackage = "com.example.typehandler")  
@SpringBootApplication  
public class YourApplication {  
    // ...  
}

(3)XML 中对应字段配置

<resultMap id="yourResultMap" type="com.example.YourEntity">  
    <id property="id" column="id" />  
    <result property="isActive" column="active_flag" typeHandler="com.example.YesNoTypeHandler" />  
    <!-- 其他字段... -->  
</resultMap>

三、Spring Boot 内置 Jackson 序列化处理

(1)准备序列化处理类

import com.fasterxml.jackson.core.JsonGenerator;  
import com.fasterxml.jackson.databind.JsonSerializer;  
import com.fasterxml.jackson.databind.SerializerProvider;  
import java.io.IOException;  

@Component
@RequiredArgsConstructor // Lombok 的构造器注入
public class UserNameSensitiveDataSerializer extends JsonSerializer<String> {
    // 业务处理
    private final SysUserPlusService userPlusService;

    @Override  
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {  
        //if (isSensitiveData(value)) { // 假设这是一个检查数据是否敏感的方法  
        //    gen.writeString("***"); // 使用占位符替换敏感数据  
        //} else {  
        //    gen.writeString(value);  
        //}
        
        gen.writeString(this.handleUserName(s));// 需要处理替换的业务逻辑
    }  
  
    //private boolean isSensitiveData(String value) {  
    //    // 实现你的敏感数据检查逻辑  
    //    return false;  
    //}
    private String handleUserName(String userName) {
        return Optional.ofNullable(this.userPlusService.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, userName)))
                .orElse(new SysUser()).getName();
    }
}

(2)使用此序列化器

public class UserDTO {  
    // ... 其他字段 ...  
    @JsonSerialize(using = UserNameSensitiveDataSerializer.class)  
    private String password;  

    // ... getter和setter ...  
}

四、前端请求自动映射查询

前端读取所有的字典数据缓存于前端,然后需要的业务表格中,从缓存的数据获取匹配即可。(缓存的数据如果调整了,可以通过标记告知前端重新更新缓存数据。)

五、其他方法

  1. 使用AOP 框架(如 Spring AOP):
    1. 在数据序列化之前拦截它;
    2. 然后再 切面中检查数据并处理;
  2. 使用过滤器或者拦截器:
    1. 在Web应用程序中,使用过滤器或拦截器在响应发送到客户端之前拦截它。
    2. 修改响应体中的JSON数据,以替换(或删除敏感)信息。
  3. 使用 DTO 或者 对应每个接口需要处理的时候通过逻辑替换处理。(比如:先将所有的字典值数据存入缓存(redis/cache/memcache等)中,然后给个公共的查询替换方法,在每个业务接口中替换数据)

相关推荐

ubuntu单机安装open-falcon极度详细操作

备注:以下操作均由本人实际操作并得到验证,喜欢的同学可尝试操作安装。步骤一1.1环境准备(使用系统:ubuntu18.04)1.1.1安装redisubuntu下安装(参考借鉴:https://...

Linux搭建promtail、loki、grafana轻量日志监控系统

一:简介日志监控告警系统,较为主流的是ELK(Elasticsearch、Logstash和Kibana核心套件构成),虽然优点是功能丰富,允许复杂的操作。但是,这些方案往往规模复杂,资源占用高,...

一文搞懂,WAF阻止恶意攻击的8种方法

WAF(Web应用程序防火墙)是应用程序和互联网流量之间的第一道防线,它监视和过滤Internet流量以阻止不良流量和恶意请求,WAF是确保Web服务的可用性和完整性的重要安全解决方案。它...

14配置appvolume(ios14.6配置文件)

使用AppVolumes应用程序功能,您可以管理应用程序的整个生命周期,包括打包、更新和停用应用程序。您还可以自定义应用程序分配,以向最终用户提供应用程序的特定版本14.1安装appvolume...

目前流行的缺陷管理工具(缺陷管理方式存在的优缺点)

摘自:https://blog.csdn.net/jasonteststudy/article/details/7090127?utm_medium=distribute.pc_relevant.no...

开源数字货币交易所开发学习笔记(2)——SpringCloud

前言码云(Gitee)上开源数字货币交易所源码CoinExchange的整体架构用了SpringCloud,对于经验丰富的Java程序员来说,可能很简单,但是对于我这种入门级程序员,还是有学习的必要的...

开发JAX-RPC Web Services for WebSphere(下)

在开发JAX-RPCWebServicesforWebSphere(上)一文中,小编为大家介绍了如何创建一个Web服务项目、如何创建一个服务类和Web服务,以及部署项目等内容。接下来小编将为大...

CXF学习笔记1(cxf client)

webservice是发布服务的简单并实用的一种技术了,个人学习了CXF这个框架,也比较简单,发布了一些笔记,希望对笔友收藏并有些作用哦1.什么是webServicewebService让一个程序可...

分布式RPC最全详解(图文全面总结)

分布式通信RPC是非常重要的分布式系统组件,大厂经常考察的Dubbo等RPC框架,下面我就全面来详解分布式通信RPC@mikechen本篇已收于mikechen原创超30万字《阿里架构师进阶专题合集》...

Oracle WebLogic远程命令执行0day漏洞(CVE-2019-2725补丁绕过)预警

概述近日,奇安信天眼与安服团队通过数据监控发现,野外出现OracleWebLogic远程命令执行漏洞最新利用代码,此攻击利用绕过了厂商今年4月底所发布的最新安全补丁(CVE-2019-2725)。由...

Spring IoC Container 原理解析(spring中ioc三种实现原理)

IoC、DI基础概念关于IoC和DI大家都不陌生,我们直接上martinfowler的原文,里面已经有DI的例子和spring的使用示例《InversionofControlContainer...

Arthas线上服务器问题排查(arthas部署)

1Arthas(阿尔萨斯)能为你做什么?这个类从哪个jar包加载的?为什么会报各种类相关的Exception?我改的代码为什么没有执行到?难道是我没commit?分支搞错了?遇到问题无法在...

工具篇之IDEA功能插件HTTP_CLENT(idea2021插件)

工具描述:Java开发人员通用的开发者工具IDEA集成了HTTPClient功能,之后可以无需单独安装使用PostMan用来模拟http请求。创建方式:1)简易模式Tools->HTTPCl...

RPC、Web Service等几种远程监控通信方式对比

几种远程监控通信方式的介绍一.RPCRPC使用C/S方式,采用http协议,发送请求到服务器,等待服务器返回结果。这个请求包括一个参数集和一个文本集,通常形成“classname.meth...

《github精选系列》——SpringBoot 全家桶

1简单总结1SpringBoot全家桶简介2项目简介3子项目列表4环境5运行6后续计划7问题反馈gitee地址:https://gitee.com/yidao620/springbo...

取消回复欢迎 发表评论: