短链接学习day2

news2024/11/28 12:43:05

用户敏感信息脱敏展示:

@RequestParam 和 @PathVariable的区别

注解是用于从request中接收请求的,两个都可以接收参数,关键点不同的是@RequestParam 是从request里面拿取值,而 @PathVariable 是从一个URI模板里面来填充。

@PathVariable:主要用于接收http://host:port/path/{参数值}数据。

@RequestParam:主要用于接收http://host:port/path?参数名=参数值数据,这里后面也可以不跟参数值。

BeanUtil.toBean()方法

在Hutool工具包中,BeanUtil类的toBean()方法用于将一个对象或Map转换成指定类型的JavaBean对象。我们先创建了一个数据源对象product,然后,通过调用BeanUtil.toBean()方法,将数据源对象product转换成目标类型 productVo的JavaBean对象vo。

需要注意的是,转换过程中,BeanUtil.toBean()方法通过反射机制创建了目标类型的实例,并将数据源对象的属性值复制到目标对象中。所以,需要保证数据源对象和目标类型的属性名称和类型保持一致,否则无法正确转换属性值。所以在创建ProductVo时,是继承于Product的。另外,还需要在项目中引入Hutool的相关依赖才能使用BeanUtil类的方法。

PhoneDesensitizationSerializer:
package com.nageoffer.shortlink.admin.common.serialize;

import cn.hutool.core.util.DesensitizedUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

/**
 * 手机号脱敏反序列化
 */
public class PhoneDesensitizationSerializer extends JsonSerializer<String> {

    @Override
    public void serialize(String phone, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        String phoneDesensitization = DesensitizedUtil.mobilePhone(phone);
        jsonGenerator.writeString(phoneDesensitization);
    }
}

UserRespDTO:

不知道为什么我都加了注解,也有文件,可是脱敏就是不生效,压根没走PhoneDesensitizationSerializer。

用户注册:

检查用户名是否存在:

  • 海量用户如果说查询的用户名存在或不存在,全部请求数据库,会将数据库直接打满。

方法1:将数据库已有的用户名全部放到缓存里。

该方案问题:

  • 是否要设置数据的有效期?只能设置为无无有效期,也就是永久数据。
  • 如果是永久不过期数据,占用 Redis 内存太高。

方法2:使用布隆过滤器。

布隆过滤器是一种数据结构,用于快速判断一个元素是否存在于一个集合中。具体来说,布隆过滤器包含一个位数组和一组哈希函数。位数组的初始值全部置为 0。在插入一个元素时,将该元素经过多个哈希函数映射到位数组上的多个位置,并将这些位置的值置为 1。

在查询一个元素是否存在时,会将该元素经过多个哈希函数映射到位数组上的多个位置,如果所有位置的值都为 1,则认为元素存在;如果存在任一位置的值为 0,则认为元素不存在。

优点:

  • 高效地判断一个元素是否属于一个大规模集合。
  • 节省内存。

缺点:

  • 可能存在一定的误判。
布隆过滤器误判理解
  • 布隆过滤器要设置初始容量。容量设置越大,冲突几率越低。
  • 布隆过滤器会设置预期的误判值。
误判能否接受

布隆过滤器的误判是否能够接受?

答:可以容忍。为什么?因为用户名不是特别重要的数据,如果说我设置用户名为 aaa,系统返回我不可用,那我大可以在 aaa 的基础上再加一个a,也就是 aaaa。

布隆过滤器的使用:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
spring:
  data:
    redis:
      host: 127.0.0.1
      port: 6379
      password: 123456

创建布隆过滤器实例:

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 布隆过滤器配置
 */
@Configuration
public class RBloomFilterConfiguration {

    /**
     * 防止用户注册查询数据库的布隆过滤器
     */
    @Bean
    public RBloomFilter<String> userRegisterCachePenetrationBloomFilter(RedissonClient redissonClient) {
        RBloomFilter<String> cachePenetrationBloomFilter = redissonClient.getBloomFilter("xxx");
        cachePenetrationBloomFilter.tryInit(0, 0);
        return cachePenetrationBloomFilter;
    }
}

tryInit 有两个核心参数:

  • expectedInsertions:预估布隆过滤器存储的元素长度。
  • falseProbability:运行的误判率。

错误率越低,位数组越长,布隆过滤器的内存占用越大。

错误率越低,散列 Hash 函数越多,计算耗时较长。

一个布隆过滤器占用大小的在线网站:Bloom Filter Calculator

使用布隆过滤器的两种场景:

  • 初始使用:注册用户时就向容器中新增数据,就不需要任务向容器存储数据了。
  • 使用过程中引入:读取数据源将目标数据刷到布隆过滤器。
private final RBloomFilter<String> userRegisterCachePenetrationBloomFilter;

/**
     * 查询用户名是否存在
     * @param username
     * @return 存在,true 不存在,false
     */
    @Override
    public Boolean hashUsername(String username) {
        return userRegisterCachePenetrationBloomFilter.contains(username);
    }
用户注册:

一定要记得写枚举的时候是用逗号分割。

redis使用:

由于很久没用过redis了,所以我忘记了怎么启动了。

可以参考这个文档,为了防止下一次找不到redis文件了,记得一定要配置环境变量。

redis的启动需要先打开redis-server.exe然后再用可视化工具连接即可。

如果redis没有密码,但是本地application.yml又配置了redis密码,就会导致报错:Factory method 'redisson' threw exception with message: Unable to connect to Redis server: 127.0.0.1/127.0.0.1:6379

Window下Redis的安装和部署详细图文教程(Redis的安装和可视化工具的使用)_redis安装-CSDN博客

自动填充字段

自动填充字段 | MyBatis-Plus

难点:

由于在注册时,将用户记录添加到数据库时,同时将用户名添加到布隆过滤器中。但是为了防止redis的主节点挂掉后,从节点变成主节点时,有些数据还没复制,就会导致脏数据,就会可能导致用户名重复,所以为了防止这个情况,我们需要将username设置为唯一索引,让数据库兜底。

如何防止恶意请求毫秒级触发大量请求去一个未注册的用户名?

因为用户名没注册,所以布隆过滤器不存在,代表着可以触发注册流程插入数据库。但是如果恶意请求短时间海量请求,这些请求都会落到数据库,造成数据库访问压力。这里通过分布式锁,锁定用户名进行串行执行,防止恶意请求利用未注册用户名将请求打到数据库。

用redisson实现分布式锁。

UserServiceImpl:

private final RedissonClient redissonClient;

/**
     * 注册用户
     *
     * @param requestParam
     */
    @Override
    public void register(UserRegisterReqDTO requestParam) {
        if(hashUsername(requestParam.getUsername())){
            throw new ClientException(UserErrorCodeEnum.USER_NAME_EXIST);
        }
        RLock lock = redissonClient.getLock(LOCK_USER_REGISTER_KEY+requestParam.getUsername());
        try{
            if(lock.tryLock()){
                int inserted=baseMapper.insert(BeanUtil.toBean(requestParam,UserDO.class));
                if(inserted<1){
                    throw new ClientException(UserErrorCodeEnum.USER_SAVE_ERROR);
                }
                userRegisterCachePenetrationBloomFilter.add(requestParam.getUsername());
                return;
            }
            throw new ClientException(UserErrorCodeEnum.USER_NAME_EXIST);
        }finally {
            lock.unlock();
        }
    }

/**
 * 短链接后管 Redis 缓存常量类
 * 类描述: RedisCacheConstant
 **/
public class RedisCacheConstant {
    public static final String LOCK_USER_REGISTER_KEY="short-link:lock_user-register:";
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1896964.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3033. 修改矩阵 Easy

给你一个下标从 0 开始、大小为 m x n 的整数矩阵 matrix &#xff0c;新建一个下标从 0 开始、名为 answer 的矩阵。使 answer 与 matrix 相等&#xff0c;接着将其中每个值为 -1 的元素替换为所在列的 最大 元素。 返回矩阵 answer 。 示例 1&#xff1a; 输入&#xff1a;…

达梦数据库小技巧

达梦数据库小技巧 一&#xff1a; 时间类型TIMESTAMP使用1.1 建表1.2 插入1.3按时间戳查询&#xff0c;返回某一列不重复的值 二&#xff1a;存储过程创建和调用2.1建表2.2 创建存储过程&#xff0c;循环100插入拼接字符串2.3调用存储过程 一&#xff1a; 时间类型TIMESTAMP使用…

Word取消自动编号

设置Word更正选项 1、 点击文件——word选项——校对——自动更正选项 2、点击自动更正——键入时自动套用格式——取消”自动编号”前面的勾选——点击确定即可

第十四届蓝桥杯省赛C++B组F题【岛屿个数】题解(AC)

题目大意 给定一个 01 地图&#xff0c;分别表示陆地和海&#xff0c;问地图中一共有多少块岛屿&#xff1f;另外&#xff0c;若一个岛屿在另一个岛屿的内部&#xff0c;则不统计。如下图中的大岛屿包含着内部的小岛屿&#xff0c;故内部小岛屿不计算&#xff0c;最终输出 1。…

10种有效提高电子设备可靠性的PCB散热技术

在现代电子领域&#xff0c;随着器件尺寸的不断缩小和性能的不断提高&#xff0c;热管理问题日益凸显&#xff0c;不容忽视。电子设备在运行过程中产生的热量&#xff0c;如果处理不当&#xff0c;散发不了&#xff0c;就会像潜移默化的威胁一样&#xff0c;悄无声息地危及设备…

交换数字00

题目链接 交换数字 题目描述 注意点 numbers.length 2-2147483647 < numbers[i] < 2147483647 解答思路 不适用临时变量&#xff0c;可以先将numbers[0]和numbers[1]的信息都存到某个位置&#xff08;可以相加可以相减或其他位操作&#xff09;&#xff0c;然后另一…

Matlab|基于改进鲸鱼优化算法的微网系统能量优化管理matlab-源码

目录 一、主要内容 二、部分代码 三、运行结果 四、下载链接 一、主要内容 该程序为《基于改进鲸鱼优化算法的微网系统能量优化管理》源码&#xff0c;主要内容如下&#xff1a; 针对包含多种可再生能源的冷热电联供型微网系统的能量优化问题&#xff0c;为了优化其运行过程…

7-google::protobuf::io命名空间下常用的C++ API----zero_copy_stream_impl.h

一、protobuf输入输出文件流C API总览 二、经常会用到的API

风电升压站3d动画演示定制确保每一名职工都能够安全、健康地工作

海上风电工程建设包括大量的吊装作业、架空作业、埋设作业以及电气作业&#xff0c;涉及面广&#xff0c;风险较高&#xff0c;因此在技能培训上需要格外重视&#xff0c;基于VR安全培训的广泛应用&#xff0c;企业逐渐开始引进VR虚拟仿真技术&#xff0c;利用视觉、听觉和亲身…

深度解读:Etched Sohu与Groq LPU芯片的区别

本文简单讲解一下Etched Sohu与Groq LPU两种芯片的区别。 设计理念的差异 首先&#xff0c;这两款产品在设计理念上完全是两条不同的路线。Etched Sohu芯片的设计理念是围绕Transformer模型进行优化。Transformer模型近年来在NLP任务中表现出色&#xff0c;Etched公司因此为其…

从数据到智能,英智私有大模型助力企业实现数智化发展

在数字化时代&#xff0c;数据已经成为企业最重要的资源。如何将这些数据转化为实际的业务价值&#xff0c;是每个企业面临的重要课题。英智利用业界领先的清洗、训练和微调技术&#xff0c;对企业数据进行深度挖掘和分析&#xff0c;定制符合企业业务场景的私有大模型&#xf…

#Vue 3 + ts + antd table表格的使用(嵌套 子表格版)

1. 嵌套子表格的使用 <template><a-table :columns"columns" :data-source"data" class"components-table-demo-nested"><template #bodyCell"{ column }"><template v-if"column.key operation">…

论文写作全攻略:Kimi辅助下的高效学术写作技巧

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 完成论文写作是一个多阶段的过程&#xff0c;涉及到不同的任务和技能。以下是按不同分类总结的向Kimi提问的prompt&#xff0c;以帮助你在论文写作过程中取得成功&#xff1a; 1. 选题与…

Redis 7.x 系列【19】管道

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 往返时间2. 管道技术3. 代码演示4. 其他批处理4.1 原生批处理命令4.2 事务4.3 脚本…

华大基因乌拉圭实验室启航:中国技术赋能拉美精准医学发展

乌拉圭作为加入“一带一路”倡议的国家&#xff0c;多年来&#xff0c;与中国在经贸、教育、文化和科技等多个关键领域的合作不断深化与拓展。随着“共建‘健康丝绸之路’倡议”的深化落实&#xff0c;中乌两国在医疗卫生领域的合作也迈入了新阶段。作为中国基因行业的奠基者&a…

大型能源电力集团需要什么样的总部数据下发系统?

能源电力集团的组织结构是一个复杂的系统&#xff0c;包括多个职能部门和子分公司。这些子分公司负责具体的电力生产、销售、运维等业务。这些部门和公司协同工作&#xff0c;确保电力生产的顺利进行&#xff0c;同时关注公司的长期发展、市场拓展、人力资源管理、财务管理和公…

C#实战|账号管理系统:通用登录窗体的实现。

哈喽,你好啊,我是雷工! 本节记录登录窗体的实现方法,比较有通用性,所有的项目登录窗体实现基本都是这个实现思路。 一通百通,以下为学习笔记。 01 登录窗体的逻辑 用户在登录窗输入账号和密码,如果输入账号和密码信息正确,点击【登录】按钮,则跳转显示主窗体,同时在固…

属性描述符初探——Vue实现数据劫持的基础

目录 属性描述符——Vue实现数据劫持的基础 一、属性描述符是什么&#xff1f; ​编辑 1.1、属性描述符示例 1.2、用属性描述符定义属性及获取对象的属性描述符 1.3、带有读取器和设置器的属性描述符 二、使用属性描述符的情景 2.1、封装和数据隐藏 使用getter和setter…

Node之Web服务

前言 本文将讲解node的web服务 通过讲解http请求&#xff0c;node创建web服务等知识点让你更加深入的理解web服务和node创建的web服务 HTTP请求是什么&#xff1f; HTTP请求是客户端&#xff08;通常是浏览器或其他应用程序&#xff09;与服务器之间进行通信的一种方式。 …

onclick和@click有什么区别,究竟哪个更好使?

哈喽小伙伴们大家好,我是爱学英语的程序员,今天来给大家分享一些关于vue中事件绑定相关的内容,希望对大家有所帮助. 场景是这样的:我要实现一个切换栏,默认激活的是第一个标签,当鼠标移动到第二个标签是,对应的内容让激活.起初,我第一时间想到的是用element plus的组件来实现这…