当前位置: 首页 > news >正文

编码技巧——基于RedisTemplate的RedisClient实现、操作Lua脚本

1. 背景

在新公司的脚手架中开发,需要用到redis,发现没有封装好一套能集成各种常用命令、包括Lua脚本的方便使用的RedisTemplateClient,于是自己来实现下;

springboot整合redis之后,提供了操作redis的简便方式,可以通过通用对象RedisTemplate方式操作String,Hash,List,Set SortSet五大数据类型;

本次的实现就是基于Spring的RedisTemplate做的二次封装;

2. 代码

(1)RedisTemplate配置类

配置的关键是序列化器的配置;未配置好序列化器,会导致例如时间类、Json格式放入缓存中时,实际存放的值与预期不符,或是在获取值时出现预期之外的错误;

推荐下方的配置写法;

/*** Redis配置类*/
@Configuration
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties(MyRedisCacheProperties.class)
@AutoConfigureBefore(RedisAutoConfiguration.class)
@ConditionalOnProperty(prefix = "my.project.cache", name = "enabled", havingValue = "true", matchIfMissing = true)
public class RedisCacheAutoConfiguration {/*** 配置RedisTemplate** @param factory Redis连接工厂* @return RedisTemplate<String, Object>*/@Bean@ConditionalOnMissingBean@ConditionalOnProperty(name = "spring.cache.type", havingValue = "redis")public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {// 创建一个模板类RedisTemplate<String, Object> template = new RedisTemplate<>();// 将刚才的redis连接工厂设置到模板类中template.setConnectionFactory(factory);// 设置key的序列化器template.setKeySerializer(new StringRedisSerializer());// 设置value的序列化器// 使用Jackson 2,将对象序列化为JSONJackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = this.getJackson2JsonRedisSerializer();template.setValueSerializer(jackson2JsonRedisSerializer);template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(jackson2JsonRedisSerializer);return template;}/*** 获取Jackson2Json序列器** @return Jackson2JsonRedisSerializer*/protected Jackson2JsonRedisSerializer<Object> getJackson2JsonRedisSerializer() {// 使用Jackson 2,将对象序列化为JSONJackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =new Jackson2JsonRedisSerializer<>(Object.class);jackson2JsonRedisSerializer.setObjectMapper(this.getObjectMapper());return jackson2JsonRedisSerializer;}/*** 获取JSON对象映射器** @return ObjectMapper*/protected ObjectMapper getObjectMapper() {// json转对象类,不设置默认的会将json转HashMapObjectMapper objectMapper = JacksonUtils.newObjectMapper();// 设置序列化时,保留对象的全类名,这样反序列化时就不用指定类型了objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.WRAPPER_ARRAY);return objectMapper;}}

(2)RedisClient的二次封装

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;/*** redisTemplate工具类 提供安全的redis操作命令*/
@Slf4j
@Service
public class RedisService {private static final RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();private static final RedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);@Resourceprivate RedisTemplate<String, String> redisTemplate;// =============================common============================/*** 指定缓存失效时间** @param key     键* @param seconds 时间(秒)*/public void expire(String key, long seconds) {if (seconds > 0) {redisTemplate.expire(key, seconds, TimeUnit.SECONDS);} else {throw new IllegalArgumentException("设置的redis过期时间应大于0! [badParam=" + seconds + "]");}}/*** 根据key 获取过期时间** @param key 键 不能为null* @return 时间(秒) 返回0代表为永久有效*/public long ttl(String key) {return Objects.requireNonNull(redisTemplate.getExpire(key, TimeUnit.SECONDS));}/*** 判断key是否存在** @param key 键* @return true 存在 false不存在*/public boolean hasKey(String key) {return Boolean.TRUE.equals(redisTemplate.hasKey(key));}/*** 删除key** @param key 可以传一个值 或多个*/public void del(String... key) {if (key != null && key.length > 0) {if (key.length == 1) {redisTemplate.delete(key[0]);log.warn("删除redisKey成功 [key={}]", key[0]);} else {List<String> keys = Arrays.asList(key);redisTemplate.delete(keys);log.warn("批量删除redisKey成功 [keys={}]", JSON.toJSONString(keys));}}}// ============================Lua=============================/*** 执行lua脚本 脚本返回值必须为number** @param luaScript* @param keys* @param args      为空时传Collections.emptyList()* @return*/@SuppressWarnings({"rawtypes", "unchecked"})public Long evalLua(String luaScript, List<String> keys, List<String> args) {// 利用泛型擦除RedisScript script = new DefaultRedisScript<>(luaScript, Long.class);Object execute = redisTemplate.execute(script, stringRedisSerializer, fastJsonRedisSerializer, keys, args.toArray());return (Long) execute;}/*** 执行lua脚本 脚本返回值必须为jsonString** @param luaScript* @param keys* @param args      为空时传Collections.emptyList()* @return 返回类型*/@SuppressWarnings({"rawtypes", "unchecked"})public String evalLuaForJsonVal(String luaScript, List<String> keys, List<String> args) {// 利用泛型擦除RedisScript script = new DefaultRedisScript<>(luaScript, String.class);Object execute = redisTemplate.execute(script, stringRedisSerializer, fastJsonRedisSerializer, keys, args.toArray());return String.valueOf(execute);}/*** 执行lua脚本 脚本返回值必须为string 注意使用tostring函数或数值常量加单引号如'const'** @param luaScript* @param keys* @param args      为空时传Collections.emptyList()* @return 返回类型*/@SuppressWarnings({"rawtypes", "unchecked"})public String evalLuaForStringVal(String luaScript, List<String> keys, List<String> args) {// 利用泛型擦除RedisScript script = new DefaultRedisScript<>(luaScript, String.class);Object execute = redisTemplate.execute(script, stringRedisSerializer, stringRedisSerializer, keys, args.toArray());return String.valueOf(execute);}// ============================String=============================/*** 普通缓存获取** @param key 键* @return 值*/public String get(String key) {return key == null ? null : redisTemplate.opsForValue().get(key);}/*** 普通缓存放入** @param key   键* @param value 值* @return true成功 false失败*/public void set(String key, String value) {redisTemplate.opsForValue().set(key, value);}/*** 普通缓存放入并设置时间** @param key     键* @param value   值* @param seconds 时间(秒) time要大于0 如果time小于等于0 将设置无限期* @return true成功 false 失败*/public void setExpire(String key, String value, long seconds) {if (seconds > 0) {redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);} else {set(key, value);}}/*** 递增** @param key   键* @param delta 要增加几(大于0)* @return 递增后的结果*/public long incr(String key, long delta) {if (delta < 0) {throw new IllegalArgumentException("incr递增因子必须大于0");}return Objects.requireNonNull(redisTemplate.opsForValue().increment(key, delta));}/*** 递减** @param key   键* @param delta 要减少几(小于0)* @return 递减后的结果*/public long decr(String key, long delta) {if (delta < 0) {throw new IllegalArgumentException("decr递减因子必须大于0");}return Objects.requireNonNull(redisTemplate.opsForValue().increment(key, -delta));}// ================================Hash=================================/*** HashGet** @param key     键 不能为null* @param hashKey 项 不能为null*/public Object hget(String key, String hashKey) {return redisTemplate.opsForHash().get(key, hashKey);}/*** 获取hashKey对应的所有键值** @param key 键* @return 对应的多个键值*/public Map<Object, Object> hmget(String key) {return redisTemplate.opsForHash().entries(key);}/*** HashSet** @param key 键* @param map 对应多个键值*/public void hmset(String key, Map<String, Object> map) {redisTemplate.opsForHash().putAll(key, map);}/*** HashSet 并设置时间 不保证原子性** @param key     键* @param map     对应多个键值* @param seconds 时间(秒)*/public void hmsetExpire(String key, Map<String, Object> map, long seconds) {redisTemplate.opsForHash().putAll(key, map);if (seconds > 0) {expire(key, seconds);}}/*** 向一张hash表中放入数据,hash如果不存在将创建hash** @param key   键* @param item  项* @param value 值*/public void hset(String key, String item, Object value) {redisTemplate.opsForHash().put(key, item, value);}/*** 向一张hash表中放入数据,hash如果不存在将创建hash 不保证原子性 原子性使用Lua脚本** @param key   键* @param item  项* @param value 值* @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间*/public void hsetExpire(String key, String item, Object value, long time) {redisTemplate.opsForHash().put(key, item, value);if (time > 0) {expire(key, time);}}/*** 删除hash表中的值** @param key     键 不能为null* @param hashKey 项 可以使多个 不能为null*/public void hdel(String key, Object... hashKey) {redisTemplate.opsForHash().delete(key, hashKey);}/*** 判断hash表中是否有该项的值** @param key     键 不能为null* @param hashKey 项 不能为null* @return true 存在 false不存在*/public boolean hHasKey(String key, String hashKey) {return redisTemplate.opsForHash().hasKey(key, hashKey);}/*** hash递增 如果不存在,就会创建一个 并把新增后的值返回** @param key   键* @param item  项* @param delta 要增加几(大于0)*/public double hincr(String key, String item, long delta) {if (delta < 0) {throw new IllegalArgumentException("hincr递增因子必须大于0");}return redisTemplate.opsForHash().increment(key, item, delta);}/*** hash递减** @param key   键* @param item  项* @param delta 要减少记(小于0)*/public double hdecr(String key, String item, long delta) {if (delta < 0) {throw new IllegalArgumentException("hdecr递减因子必须大于0");}return redisTemplate.opsForHash().increment(key, item, -delta);}// ============================set=============================/*** 根据key获取Set中的所有值** @param key 键*/public Set<String> sGet(String key) {return redisTemplate.opsForSet().members(key);}/*** 根据value从一个set中查询,是否存在** @param key   键* @param value 值* @return true 存在 false不存在*/public boolean sHasKey(String key, Object value) {return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, value));}private String[] toStringArray(List<Object> values) {List<String> collect = values.stream().map(String::valueOf).collect(Collectors.toList());String[] valStrArray = new String[collect.size()];for (int i = 0; i < valStrArray.length; i++) {valStrArray[i] = collect.get(i);}return valStrArray;}/*** 将数据放入set缓存** @param key    键* @param values 值 可以是多个* @return 成功个数*/public long sSet(String key, List<Object> values) {return Objects.requireNonNull(redisTemplate.opsForSet().add(key, toStringArray(values)));}/*** 将set数据放入缓存** @param key     键* @param seconds 时间(秒)* @param values  值 可以是多个* @return 成功个数*/public long sSetAndTime(String key, long seconds, List<Object> values) {long count = Objects.requireNonNull(redisTemplate.opsForSet().add(key, toStringArray(values)));if (seconds > 0)expire(key, seconds);return count;}/*** 获取set缓存的长度** @param key 键*/public long sGetSetSize(String key) {return Objects.requireNonNull(redisTemplate.opsForSet().size(key));}/*** 移除值为value的** @param key    键* @param values 值 可以是多个* @return 移除的个数*/public long setRemove(String key, List<Object> values) {return Objects.requireNonNull(redisTemplate.opsForSet().remove(key, values));}// ===============================list=================================/*** 获取list缓存的内容** @param key   键* @param start 开始* @param end   结束 0 到 -1代表所有值*/public List<String> lrange(String key, long start, long end) {return redisTemplate.opsForList().range(key, start, end);}/*** 获取list缓存的长度** @param key 键*/public long lsize(String key) {return Objects.requireNonNull(redisTemplate.opsForList().size(key));}/*** 通过索引 获取list中的值** @param key   键* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推*/public String lGetIndex(String key, long index) {return redisTemplate.opsForList().index(key, index);}/*** item放入list缓存** @param key   键* @param value 值*/public void ladd(String key, String value) {redisTemplate.opsForList().rightPush(key, value);}/*** 将list放入缓存** @param key   键* @param value 值* @return*/public long lpush(String key, List<String> value) {return Objects.requireNonNull(redisTemplate.opsForList().rightPushAll(key, value));}/*** 根据索引修改list中的某条数据** @param key       键* @param index     索引* @param updateVal 值* @return*/public void lUpdateIndex(String key, long index, String updateVal) {redisTemplate.opsForList().set(key, index, updateVal);}}

注意操作Lua脚本时,一般脚本预期的返回值是数值型;如果需要返回字符串或Json字符串,需要特殊指定返回类型和序列化器;如下:

    // ============================Lua=============================/*** 执行lua脚本 脚本返回值必须为number** @param luaScript* @param keys* @param args      为空时传Collections.emptyList()* @return*/@SuppressWarnings({"rawtypes", "unchecked"})public Long evalLua(String luaScript, List<String> keys, List<String> args) {// 利用泛型擦除RedisScript script = new DefaultRedisScript<>(luaScript, Long.class);Object execute = redisTemplate.execute(script, stringRedisSerializer, fastJsonRedisSerializer, keys, args.toArray());return (Long) execute;}/*** 执行lua脚本 脚本返回值必须为jsonString** @param luaScript* @param keys* @param args      为空时传Collections.emptyList()* @return 返回类型*/@SuppressWarnings({"rawtypes", "unchecked"})public String evalLuaForJsonVal(String luaScript, List<String> keys, List<String> args) {// 利用泛型擦除RedisScript script = new DefaultRedisScript<>(luaScript, String.class);Object execute = redisTemplate.execute(script, stringRedisSerializer, fastJsonRedisSerializer, keys, args.toArray());return String.valueOf(execute);}/*** 执行lua脚本 脚本返回值必须为string 注意使用tostring函数或数值常量加单引号如'const'** @param luaScript* @param keys* @param args      为空时传Collections.emptyList()* @return 返回类型*/@SuppressWarnings({"rawtypes", "unchecked"})public String evalLuaForStringVal(String luaScript, List<String> keys, List<String> args) {// 利用泛型擦除RedisScript script = new DefaultRedisScript<>(luaScript, String.class);Object execute = redisTemplate.execute(script, stringRedisSerializer, stringRedisSerializer, keys, args.toArray());return String.valueOf(execute);}

(3)Lua脚本相关

可参考之前的文章编码技巧——Lua脚本的应用,这里再次附上代码;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Properties;/*** 文件加载类*/
@Slf4j
public class FileLoaderUtils {/*** 读文件文本到String 根目录为resource** @param fileName* @return*/public static String loadFile2String(String fileName) {ClassLoader loader = Thread.currentThread().getContextClassLoader();URL url = loader.getResource(fileName);if (url == null) {log.error("Cannot_locate_" + fileName + "_as_a_classpath_resource.");throw new RuntimeException("Cannot_locate_" + fileName + "_as_a_classpath_resource.");}try {return IOUtils.toString(url, StandardCharsets.UTF_8);} catch (IOException e) {log.error("读取文件内容为String失败! [fileName={}]", fileName, e);throw new RuntimeException("读取文件内容为String失败! [fileName=" + fileName + "]");}}/*** 读文件文本到Property 根目录为resource** @param fileName* @return*/public static Properties loadFile2Property(String fileName) {ClassLoader loader = Thread.currentThread().getContextClassLoader();InputStream in = loader.getResourceAsStream(fileName);Properties properties = new Properties();try {properties.load(in);if (in != null) {in.close();}} catch (IOException e) {log.error("读取文件内容到Properties失败! [fileName={}]", fileName, e);throw new RuntimeException("读取文件内容到Properties失败! [fileName=" + fileName + "]");}return properties;}}
/*** LuaScript注册类*/
public class LuaScript {// 常用原子操作private static final String INCR_EXPIRE;private static final String DECR_EXPIRE;private static final String SETNX_EXPIRE;private static final String HSET_EXPIRE;private static final String INCRBY_EXPIRE;private static final String SET_EXPIRE;static {DECR_EXPIRE = FileLoaderUtils.loadFile2String("lua/decr_expire.lua");INCR_EXPIRE = FileLoaderUtils.loadFile2String("lua/incr_expire.lua");SETNX_EXPIRE = FileLoaderUtils.loadFile2String("lua/setnx_expire.lua");HSET_EXPIRE = FileLoaderUtils.loadFile2String("lua/hset_expire.lua");INCRBY_EXPIRE = FileLoaderUtils.loadFile2String("lua/incrby_expire.lua");SET_EXPIRE = FileLoaderUtils.loadFile2String("lua/set_expire.lua");}public static String incrExpireScript() {return INCR_EXPIRE;}public static String decrExpireScript() {return DECR_EXPIRE;}public static String setnxExpireScript() {return SETNX_EXPIRE;}public static String hsetExpireScript() {return HSET_EXPIRE;}public static String incrbyExpireScript() {return INCRBY_EXPIRE;}public static String setExpireScript() {return SET_EXPIRE;}}

以上,希望能帮到你;

参考:

Springboot整合Redis使用RedisTemplate操作redis五大类型用法详解

RedisTemplate执行lua脚本抛出异常IllegalStateException - 简书

相关文章:

编码技巧——基于RedisTemplate的RedisClient实现、操作Lua脚本

1. 背景 在新公司的脚手架中开发&#xff0c;需要用到redis&#xff0c;发现没有封装好一套能集成各种常用命令、包括Lua脚本的方便使用的RedisTemplateClient&#xff0c;于是自己来实现下&#xff1b; springboot整合redis之后&#xff0c;提供了操作redis的简便方式&#…...

Asp .Net Core 系列:Asp .Net Core 集成 Panda.DynamicWebApi

文章目录 简介Asp .Net Core 集成 Panda.DynamicWebApi配置原理什么是POCO Controller&#xff1f;POCO控制器原理ControllerFeatureProvider实现自定义判断规则IApplicationModelConventionPanda.DynamicWebApi中的实现ConfigureApiExplorer()ConfigureSelector()ConfigurePar…...

【PTA浙大版《C语言程序设计(第4版)》|编程题】习题7-3 判断上三角矩阵(附测试点)

目录 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 代码呈现 测试点 上三角矩阵指主对角线以下的元素都为0的矩阵&#xff1b;主对角线为从矩阵的左上角至右下角的连线。 本题要求编写程序&#xff0c;判断一个给定的方阵是否…...

JVM 性能调优 - 参数调优(3)

查看 JVM 内存的占用情况 编写代码 package com.test;public class PrintMemoryDemo {public static void main(String[] args) {// 堆内存总量long totalMemory Runtime.getRuntime().totalMemory();// jvm 试图使用的最大堆内存long maxMemory Runtime.getRuntime().maxM…...

Django(十)

1. Ajax请求 浏览器向网站发送请求时&#xff1a;URL 和 表单的形式提交。 GETPOST 特点&#xff1a;页面刷新。 除此之外&#xff0c;也可以基于Ajax向后台发送请求&#xff08;偷偷的发送请求&#xff09;。 依赖jQuery编写ajax代码 $.ajax({url:"发送的地址"…...

OpenHarmony开源鸿蒙开发之旅

文章目录 一、op系统架构二、op系统构建1. op源代码目录2. op系统构建3. op开发环境搭建 三、op系统的子系统四、op系统芯片移植五、op系统启动流程六、op系统组件七、驱动框架 一、op系统架构 二、op系统构建 1. op源代码目录 2. op系统构建 3. op开发环境搭建 三、op系统…...

SpringBoot之整合PageHelper分页插件

SpringBoot之整合PageHelper分页插件 文章目录 SpringBoot之整合PageHelper分页插件1. 引入坐标2. application.yml配置3. 基本使用4. 对多个查询执行分页1. 默认第一个Select语句会执行分页2. 让Pagehelper也能执行多个分页的方法3. 完整案例 详细配置请查看官网或MyBatis分页…...

Android java基础_类的封装

一.面向对象编程的引入 写一个简单的程序输出张三&#xff0c;李四的名字 class Person {String name;String getName() {return "guangdong "name;} };public class Oop {public static void main(String args[]) {Person p1 new Person();p1.name "zhangs…...

Vue-57、Vue技术路由的参数如何传递

query参数传递 1、传递参数 <!-- 跳转路由并携带query参数&#xff0c;to的字符串写法--> <router-link :to"/home/message/detail?id${p.id}&title${p.title}"> {{p.title}} </router-link><!-- 跳转路由…...

《MySQL 简易速速上手小册》第1章:MySQL 基础和安装(2024 最新版)

文章目录 1.1 MySQL 概览&#xff1a;版本、特性和生态系统1.1.1 基础知识1.1.2 重点案例&#xff1a;使用 Python 实现 MySQL 数据的 CRUD 操作1.1.3 拓展案例 1&#xff1a;使用 Python 实现 MySQL 数据备份**1.1.4 拓展案例 2&#xff1a;使用 Python 分析 MySQL 数据 1.2 安…...

Linux 软件管理(YUM RPM)

1 YUM yum&#xff08;全称为 Yellow dog Updater, Modified&#xff09;是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器。基于RPM包管理&#xff0c;能够从指定的服务器自动处理依赖性关系&#xff0c;并且一次安装所有依赖的软件包&#xff0c;无须繁琐地一次次…...

【Makefile语法 05】动静态库编译链接

目录 一、多文件项目源代码 二、静态库编译链接 三、动态库编译链接 一、多文件项目源代码 // include/add.hpp#pragma once int add(int a, int b); // include/sub.hpp#pragma once int sub(int a, int b); // src/add.cpp#include "add.hpp"int add(int a, …...

JS - 处理元素滚动

业务功能中时常有元素滚动的功能&#xff0c;现在就总结一下一些常用的事件。 一、定位滚动元素 做一切滚动操作之前都应该先定位到滚动元素&#xff0c;再做其他操作&#xff0c;如滚动顶部&#xff0c;获取滚动距离、禁止滚动等。 把以下代码复制粘贴到浏览器 Console 面板…...

JavaScript滚动事件

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 滚动是网页交互不可或缺的一部分。监听页面和元素的滚动事件,可以帮助…...

4.0 Zookeeper Java 客户端搭建

本教程使用的 IDE 为 IntelliJ IDEA&#xff0c;创建一个 maven 工程&#xff0c;命名为 zookeeper-demo&#xff0c;并且引入如下依赖&#xff0c;可以自行在maven中央仓库选择合适的版本&#xff0c;介绍原生 API 和 Curator 两种方式。 IntelliJ IDEA 相关介绍&#xff1a;…...

C#既然数组长度不可改变,那么如何动态调整集合类型数组大小,以便添加或删除元素?

目录 1.使用动态数组&#xff08;ArrayList&#xff09;&#xff1a; 2.使用 jagged array&#xff08;不规则数组&#xff09;&#xff1a; 3.使用 List &#xff1a; 4.使用数组复制&#xff1a; 在C#中&#xff0c;数组的长度是固定的&#xff0c;一旦声明和初始化&…...

3.1 Verilog 连续赋值

关键词&#xff1a;assign&#xff0c; 全加器 连续赋值语句是 Verilog 数据流建模的基本语句&#xff0c;用于对 wire 型变量进行赋值。&#xff1a; 格式如下 assign LHS_target RHS_expression &#xff1b; LHS&#xff08;left hand side&#xff09; 指赋值操作…...

【http】2、http request header Origin 属性、跨域 CORS、同源、nginx 反向代理、预检请求

文章目录 一、Origin 含义二、跨源资源共享&#xff1a;**Cross-Origin Resource Sharing** CORS2.1 跨域的定义2.2 功能概述2.3 场景示例2.3.1 简单请求2.3.2 Preflighted requests&#xff1a;预检请求 2.4 header2.4.1 http request header2.4.1.1 Origin2.4.1.2 Access-Con…...

LangChain pdf的读取以及向量数据库的使用

以下使用了3399.pdf&#xff0c; Rockchip RK3399 TRM Part1 import ChatGLM from langchain.chains import LLMChain from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain.chains import Simp…...

VUE学习——事件修饰符

阻止默认事件 <template><a click"onClickHandle" href"https://www.baidu.com">baidu</a><a click.prevent"onClickHandle" href"https://www.baidu.com">baidu</a> </template> <script>…...

开放平台技术架构设计与实现的实战总结

开放平台是企业向外部开发者提供API接口和服务的平台&#xff0c;促进生态系统的建设和业务拓展。本文将介绍开放平台技术架构的设计原则和实现方法&#xff0c;帮助读者了解如何构建一个稳健、安全且易于扩展的开放平台。 1. 什么是开放平台&#xff1f; - 解释了开放平台…...

飞桨自然语言处理框架 paddlenlp的 trainer

飞桨&#xff08;PaddlePaddle&#xff09;的NLP库PaddleNLP中的Trainer类是一个用于训练和评估模型的简单但功能完整的循环。它被优化用于与PaddleNLP一起使用。Trainer类简化了训练过程&#xff0c;提供了自动的批处理、模型保存、日志记录等特性。 以下是Trainer类的主要参数…...

SQL世界之命令语句Ⅲ

目录 一、SQL JOIN 1.JOIN 和 Key 2.使用 JOIN 3.不同的 SQL JOIN 二、SQL INNER JOIN 关键字 1.SQL INNER JOIN 关键字 2.INNER JOIN 关键字语法 3.内连接&#xff08;INNER JOIN&#xff09;实例 三、SQL LEFT JOIN 关键字 1.SQL LEFT JOIN 关键字 2.LEFT JOIN 关…...

Snoop Version 2 Packet Capture File Format

RFC1761 - Snoop Version 2 Packet Capture File Format, FEBRUARY 1995 本备忘录的状态 本备忘录为互联网社区提供帮助信息。 本备忘录不作为任何类型的互联网标准。 本备忘录的分发不受限制。 Status of this Memo This memo provides information for the Internet communit…...

扩展说明: 指令微调 Llama 2

这篇博客是一篇来自 Meta AI&#xff0c;关于指令微调 Llama 2 的扩展说明。旨在聚焦构建指令数据集&#xff0c;有了它&#xff0c;我们则可以使用自己的指令来微调 Llama 2 基础模型。 目标是构建一个能够基于输入内容来生成指令的模型。这么做背后的逻辑是&#xff0c;模型如…...

VUE 全局设置防重复点击

请求后端防止重复点击&#xff0c;用户点击加入遮罩层&#xff0c;请求完毕关闭遮罩层 我们利用请求拦截器&#xff0c;在用户点击的时候&#xff0c;弹出遮罩层 本文采用i18n国际化 element plus UI&#xff0c;提取你想要的&#xff0c;这里不做简化 完整代码如下&#xf…...

备战蓝桥杯---动态规划(基础1)

先看几道比较简单的题&#xff1a; 直接f[i][j]f[i-1][j]f[i][j-1]即可&#xff08;注意有马的地方赋值为0&#xff09; 下面是递推循环方式实现的AC代码&#xff1a; #include<bits/stdc.h> using namespace std; #define int long long int a[30][30]; int n,m,x,y; …...

CVE-2018-19518 漏洞复现

CVE-2018-19518 漏洞介绍 IMAP协议&#xff08;因特网消息访问协议&#xff09;它的主要作用是邮件客户端可以通过这种协议从邮件服务器上获取邮件的信息&#xff0c;下载邮件等。它运行在TCP/IP协议之上&#xff0c;使用的端口是143。在php中调用的是imap_open函数。 PHP 的…...

Python爬虫实战:抓取猫眼电影排行榜top100#4

爬虫专栏系列&#xff1a;http://t.csdnimg.cn/Oiun0 抓取猫眼电影排行 本节中&#xff0c;我们利用 requests 库和正则表达式来抓取猫眼电影 TOP100 的相关内容。requests 比 urllib 使用更加方便&#xff0c;而且目前我们还没有系统学习 HTML 解析库&#xff0c;所以这里就…...

Fiddler抓包工具之fiddler界面工具栏介绍

Fiddler界面工具栏介绍 &#xff08;1&#xff09;WinConfig&#xff1a;windows 使用了一种叫做“AppContainer”的隔离技术&#xff0c;使得一些流量无法正常捕获&#xff0c;在 fiddler中点击 WinConfig 按钮可以解除这个诅咒&#xff0c;这个与菜单栏 Tools→Win8 Loopback…...

LabVIEW工业监控系统

LabVIEW工业监控系统 介绍了一个基于LabVIEW软件开发的工业监控系统。系统通过虚拟测控技术和先进的数据处理能力&#xff0c;实现对工业过程的高效监控&#xff0c;提升系统的自动化和智能化水平&#xff0c;从而满足现代工业对高效率、高稳定性和低成本的需求。 随着工业自…...

Linux 文件连接:符号链接与硬链接

Linux 文件连接&#xff1a;符号链接与硬链接 介绍 在 Linux 系统中&#xff0c;文件连接是一个强大的概念&#xff0c;它允许我们在文件系统中创建引用&#xff0c;从而使得文件和目录之间产生联系。在本文中&#xff0c;我们将深入探讨两种主要类型的文件连接&#xff1a;符…...

数据分类分级

一段时间没写文章了&#xff0c;最近做政府数据治理方面的项目&#xff0c;数据治理一个重要的内容是数据安全&#xff0c;会涉及数据的分类分级&#xff0c;是数据治理的基础。 随着“十四五”规划推行&#xff0c;数据要素概念与意识全面铺开&#xff0c;国家、政府机构、企业…...

第三十天| 51. N皇后

Leetcode 51. N皇后 题目链接&#xff1a;51 N皇后 题干&#xff1a;按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整…...

pythn-scipy 查漏补缺

1. 2. 3. 4. 5. 6. 7. 8. 9. 偏度 skewness&#xff0c;峰度 kurtosis...

【JavaScript 漫游】【013】Date 对象知识点摘录

文章简介 本文为【JavaScript 漫游】专栏的第 013 篇文章&#xff0c;记录了 JS 语言中 Date 对象的重要知识点。 普通函数的用法构造函数的用法日期的运算静态方法&#xff0c;包括&#xff1a;Date.now()、Date.parse() 和 Date.UTC()实例方法&#xff0c;包括&#xff1a;…...

vue.config.js和webpack.config.js区别

webpack.config.js和vue.config.js的区别 webpack.config.js是webpack的配置文件&#xff0c;所有使用webpack作为打包工具的项目都可以使用&#xff0c;vue的项目可以使用&#xff0c;react的项目也可以使用。 vue.config.js是vue项目的配置文件&#xff0c;专用于vue项目。…...

H12-821_73

73.某台路由器Router LSA如图所示&#xff0c;下列说法中错误的是&#xff1f; A.本路由器的Router ID为10.0.12.1 B.本路由器为DR C.本路由器已建立邻接关系 D.本路由器支持外部路由引入 答案&#xff1a;B 注释&#xff1a; LSA中的链路信息Link ID&#xff0c;Data&#xf…...

postman执行批量测试

1.背景 有许多的人常常需要使用第三方系统进行重复的数据查询&#xff0c;本文介绍使用PostMan的方式对数据进行批量的查询&#xff0c;减少重复的劳动。 2.工具下载 3.初入门 一、如图示进行点击&#xff0c;创建collection 二、输入对应的名称 三、创建Request并进行查…...

蓝桥杯基础知识8 list

蓝桥杯基础知识8 list 01 list 的定义和结构 lits使用频率较低&#xff0c;是一种双向链表容器&#xff0c;是标准模板库&#xff08;STL&#xff09;提供的一种序列容器&#xff0c;lsit容器以节点&#xff08;node&#xff09;的形式存储元素&#xff0c;使用指针将这些节点链…...

【DDD】学习笔记-理解领域模型

Eric Evans 的领域驱动设计是对软件设计领域的一次重新审视&#xff0c;是在面向对象语言大行其道时对数据建模的“拨乱反正”。Eric 强调了模型的重要性&#xff0c;例如他在书中总结了模型在领域驱动设计中的作用包括&#xff1a; 模型和设计的核心互相影响模型是团队所有成…...

v-if 和v-show 的区别

第074个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使用&#xff0c;computed&a…...

LabVIEW网络测控系统

LabVIEW网络测控系统 介绍了基于LabVIEW的网络测控系统的开发与应用&#xff0c;通过网络技术实现了远程的数据采集、监控和控制。系统采用LabVIEW软件与网络通信技术相结合&#xff0c;提高了系统的灵活性和扩展性&#xff0c;适用于各种工业和科研领域的远程测控需求。 随着…...

攻防世界 CTF Web方向 引导模式-难度1 —— 11-20题 wp精讲

PHP2 题目描述: 暂无 根据dirsearch的结果&#xff0c;只有index.php存在&#xff0c;里面也什么都没有 index.phps存在源码泄露&#xff0c;访问index.phps 由获取的代码可知&#xff0c;需要url解码(urldecode )后验证id为admin则通过 网页工具不能直接对字母进行url编码 …...

华为Eth-Trunk级联堆叠接入IPTV网络部署案例

Eth-Trunk级联堆叠接入IPTV网络部署案例 组网图形 图2 Eth-Trunk级联堆叠IPTV基本组网图 方案简介配置注意事项组网需求数据规划配置思路操作步骤配置文件 方案简介 随着IPTV业务的迅速发展&#xff0c;IPTV平台承载的用户也越来越多&#xff0c;用户对IPTV直播业务的可靠性…...

idea: 无法创建Java Class文件(SpringBoot)已解决

第一&#xff1a;点击file-->project Sructure... 第二步&#xff1a;点击Moudules 选择自己需要创建java的文件夹&#xff08;我这里选择的是main&#xff09;右键点击Sources&#xff0c;然后点击OK即可 然后就可以创建java类了...

ChinaXiv:中科院科技论文预发布平台

文章目录 Main彩蛋 Main 主页&#xff1a;https://chinaxiv.org/home.htm 彩蛋...

【人工智能】Fine-tuning 微调:解析深度学习中的利器(7)

在深度学习领域&#xff0c;Fine-tuning 微调是一项重要而强大的技术&#xff0c;它为我们提供了在特定任务上充分利用预训练模型的途径。本文将深入讨论 Fine-tuning 的定义、原理、实际操作以及其在不同场景中的应用&#xff0c;最后简要探讨Fine-tuning 的整体架构。 1. Fi…...

黄金交易策略(Nerve Nnife):大K线对技术指标的影响

我们使用heiken ashi smoothed来做敏感指标&#xff08;大趋势借助其转向趋势预判&#xff0c;但不是马上转变&#xff09;&#xff0c;has默认使用6根k线的移动平均值来做计算的。若在6根k线规范内有一个突变的行情&#xff08;k线很长&#xff09;&#xff0c;那么整个行情的…...

django中实现数据迁移

在Django中&#xff0c;数据迁移&#xff08;data migrations&#xff09;通常指的是将模型&#xff08;models&#xff09;中的数据从一个状态迁移到另一个状态。这可以涉及很多操作&#xff0c;比如添加新字段、删除字段、更新字段的数据类型&#xff0c;或者更改表之间的关系…...