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

Jedis(一)与Redis的关系

一、Jedis介绍:
1、背景:

Jedis是基于Java语言的Redis的客户端,Jedis = Java + Redis。Redis不仅可以使用命令来操作,现在基本上主流的语言都有API支持,比如Java、C#、C++、PHP、Node.js、Go等。在官方网站里有一些Java的客户端:Jedis、Redisson、Jredis、JDBC-Redis等,其中官方推荐使用Jedis和Redisson。简言之Jedis是Redis的Java版本API,通过使用Jedis可以操作Redis中的数据。

2、Jedis连接池介绍:

jedis连接资源的创建与销毁是很消耗程序性能,所以jedis为我们提供了jedis的连接池技术,jedis

连接池在创建时初始化一些连接对象存储到连接池中,使用jedis连接资源时不需要自己创建jedis对

象,而是从连接池中获取一个资源进行redis的操作。使用完毕后,不需要销毁该jedis连接资源,

而是将该资源归还给连接池,供其他请求使用。

二、Jedis API:
1、连接池API

JedisPoolConfig配置类

功能说明

JedisPoolConfig()

创建一个配置对象,使用无参构造方法就可以了

void setMaxTotal()

设置连接池最大的连接数

void setMaxWaitMillis()

设置得到连接对象Jedis最长等待时间

JedisPool连接池类

说明

JedisPool(配置对象,服务器名,端口号)

创建连接池

Jedis getResource()

从连接池中得到一个Jedis连接对象

void close()

连接池关闭方法,通常不关闭连接池

2、其他常用API: 

方法

功能

new Jedis(host, port)

创建Jedis的连接,参数:主机名,端口号

set(key,value)

添加一个字符串的键和值

get(key)

得到指定键的值

del(key)

删除指定键和值

hset(key,field,value)

添加一个hash类型的键-字段-值

hget(key,field)

通过hash键-字段得到它的值

lpush(key,values)

从左边添加一个list类型的键和元素

lpop(key)

从左边弹出一个元素

rpop(key)

从右边弹出一个元素

close()

关闭连接

三、SpringBoot集成Jedis: 

pom依赖:加上redis、jedis依赖

 <!-- redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>

实际应用一般采用Redis集群,这里重点看下集群模式下的集成方式。

1、Redis集群模式:
(1)配置文件:配置redis、jedis属性信息
#redis配置
my.redis.server.jedis.pool.maxTotal=500
my.redis.server.jedis.pool.maxIdle=10
my.redis.server.jedis.pool.maxWaitMillis=5000
my.redis.server.jedis.pool.min-idle=5
my.redis.server.timeout=5000 
#哨兵配置
my.redis.sentinel.nodes=xxx.xx.xxx.111:26379,xxx.xx.xxx.222:26379,xxx.xx.333:26379
my.redis.sentinel.password=wtyy
my.redis.sentinel.master-name=mymaster
my.redis.sentinel.database=10
my.redis.sentinel.pool.max-total=10
my.redis.sentinel.pool.max-idle=5
my.redis.sentinel.pool.min-idle=5
(2)Jedis连接池配置类,连接Redis:
@Configuration
public class JedisConfig {private Logger logger = LoggerFactory.getLogger(JedisConfig.class);@Value("${my.redis.server.jedis.pool.maxTotal}")private int maxTotal;@Value("${my.redis.server.jedis.pool.maxIdle}")private int maxIdle;@Value("${my.redis.server.jedis.pool.maxWaitMillis}")private int maxWaitMillis;@Value("${my.redis.server.timeout}")private int timeout;@Value("${my.redis.sentinel.nodes}")private String redisSentinelNodes;@Value("${my.redis.sentinel.pool.max-total}")private int redisSentinelMaxTotal;@Value("${my.redis.sentinel.pool.max-idle}")private int redisSentinelMaxIdle;@Value("${my.redis.sentinel.pool.min-idle}")private int redisSentinelMinIdle;@Value("${my.redis.sentinel.master-name}")private String redisSentinelMasterName;@Value("${my.redis.sentinel.password}")private String redisSentinelPassword;@Value("${my.redis.sentinel.database}")private int dataBase;@Bean(name = "jedisPool")public JedisSentinelPool jedisPool() {JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();jedisPoolConfig.setMaxTotal(maxTotal);jedisPoolConfig.setMaxIdle(maxIdle);jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);//sentinelString[] hosts = redisSentinelNodes.split(",");Set<String> sentinels = new HashSet<>(Arrays.asList(hosts));GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();poolConfig.setMaxTotal(redisSentinelMaxTotal);poolConfig.setMaxIdle(redisSentinelMaxIdle);poolConfig.setMinIdle(redisSentinelMinIdle);JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(redisSentinelMasterName,sentinels, jedisPoolConfig,timeout,redisSentinelPassword,dataBase);return  jedisSentinelPool;}
}
(3)Jedis工具类:
@SuppressWarnings("unused")
@Component
public class RedisClient {private static boolean BORROW = true; // 在borrow一个事例时是否提前进行validate操作private static Logger logger = Logger.getLogger(RedisClient.class);@Autowiredprivate JedisSentinelPool pool;/*** 获取连接*/public  synchronized Jedis getJedis() {try {if (pool != null) {return pool.getResource();} else {return null;}} catch (Exception e) {logger.info("连接池连接异常");return null;}}/*** @Description: 关闭连接* @param @param jedis* @return void 返回类型*/public static void getColse(Jedis jedis) {if (jedis != null) {jedis.close();}}/*** 格式化Key*/public static String format(String formatKey, String... keyValues) {if (keyValues == null || keyValues.length == 0) {return formatKey;}StringBuilder key = new StringBuilder();char[] chars = formatKey.toCharArray();int index = -1;boolean inmark = false;boolean firstinmark = false;for (int i = 0; i < chars.length; i++) {char ch = chars[i];if (ch == '{') {index++;inmark = true;firstinmark = true;} else if (ch == '}') {inmark = false;} else if (inmark) {if (firstinmark) {firstinmark = false;key.append(keyValues[index]);}} else {key.append(chars[i]);}}return key.toString();}/********************************** 针对key的操作 **************************************//*** 删除一个key** @param keyFormat*            key标识* @param keyValues*            key变量* @return 被删除的keys的数量*/public Long del(String keyFormat, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.del(key);} finally {if (jedis != null) {jedis.close();}}}/*** 查询一个key是否存在** @param keyFormat*            key标识* @param keyValues*            key变量* @return key是否存在。*/public boolean exists(String keyFormat, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.exists(key);} finally {if (jedis != null) {jedis.close();}}}/*** 设置一个key的过期的秒数** @param keyFormat*            key标识* @param seconds*            过期的秒数* @param keyValues*            key变量* @return 1表示设置成功, 0 表示设置失败或者无法被设置*/public Long expire(String keyFormat, int seconds, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.expire(key, seconds);} finally {if (jedis != null) {jedis.close();}}}/*** 设置一个UNIX时间戳的过期时间** @param keyFormat*            key标识* @param expireDate*            过期时间* @param keyValues*            key变量* @return 1表示设置成功, 0 表示设置失败或者无法被设置*/public Long expireAt(String keyFormat, Date expireDate, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.pexpireAt(key, expireDate.getTime());} finally {if (jedis != null) {jedis.close();}}}/*** 移除给定key的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。** @param keyFormat*            key标识* @param keyValues*            key变量* @return 当生存时间移除成功时,返回 1 . 如果 key 不存在或 key 没有设置生存时间,返回 0 .*/public Long persist(String keyFormat, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.persist(key);} finally {if (jedis != null) {jedis.close();}}}/*** 设置一个key的过期的毫秒数** <pre>* 这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像 EXPIRE 命令那样,以秒为单位。* </pre>** @param keyFormat*            key标识* @param milliSeconds*            过期的毫秒数* @param keyValues*            key变量* @return 设置成功,返回 1,不存在或设置失败,返回 0*/public Long pexpire(String keyFormat, long milliSeconds,String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.pexpire(key, milliSeconds);} finally {if (jedis != null) {jedis.close();}}}/*** 获取key的有效毫秒数** <pre>* 这个命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间,而不是像 TTL 命令那样,以秒为单位。* </pre>** @param keyFormat*            key标识* @param keyValues*            key变量* @return 当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。否则,以毫秒为单位,返回 key*         的剩余生存时间。*/public Long pttl(String keyFormat, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.pttl(key);} finally {if (jedis != null) {jedis.close();}}}/*** 获取key的有效时间(单位:秒)** <pre>* 以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。* </pre>** @param keyFormat*            key标识* @param keyValues*            key变量* @return 当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。否则,以秒为单位,返回 key*         的剩余生存时间。*/public Long ttl(String keyFormat, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.ttl(key);} finally {if (jedis != null) {jedis.close();}}}/********************************** 针对字符串(string)的操作 **************************************//*** 追加一个值到key上** <pre>* 如果 key 已经存在,并且值为字符串,那么这个命令会把 value 追加到原来值(value)的结尾。* 如果 key 不存在,那么它将首先创建一个空字符串的key,再执行追加操作,这种情况 APPEND 将类似于 SET 操作。* </pre>** @param keyFormat*            key标识* @param value*            要追加的值* @param keyValues*            key变量* @return 返回append后字符串值(value)的长度。*/public Long append(String keyFormat, String value, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.append(key, value);} finally {if (jedis != null) {jedis.close();}}}/*** 整数原子减1** <pre>* 对key对应的数字做减1操作。如果key不存在,那么在操作之前,这个key对应的值会被置为0。* 如果key有一个错误类型的value或者是一个不能表示成数字的字符串,就返回错误。* 这个操作最大支持在64位有符号的整型数字。* </pre>** @param keyFormat*            key标识* @param keyValues*            key变量* @return 数字:减小之后的value*/public Long decr(String keyFormat, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.decr(key);} finally {if (jedis != null) {jedis.close();}}}/*** 原子减指定的整数** <pre>* 将key对应的数字减decrement。如果key不存在,操作之前,key就会被置为0。* 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。* 这个操作最多支持64位有符号的正型数字。* </pre>** @param keyFormat*            key标识* @param integer*            要减小的数值* @param keyValues*            key变量* @return 返回一个数字:减少之后的value值。*/public Long decrby(String keyFormat, long integer, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.decrBy(key, integer);} finally {if (jedis != null) {jedis.close();}}}/*** @param keyFormat*            key标识* @param keyValues*            key变量* @return key对应的value,或者null(key不存在时)*/public String get(String keyFormat, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.get(key);} finally {if (jedis != null) {jedis.close();}}}/*** 设置一个key的value,并获取设置前的值** <pre>* 自动将key对应到value并且返回原来key对应的value。如果key存在但是对应的value不是字符串,就返回错误。* exp:* GETSET可以和INCR一起使用实现支持重置的计数功能。* 举个例子:每当有事件发生的时候,一段程序都会调用INCR给key mycounter加1,但是有时我们需要获取计数器的值,并且自动将其重置为0。* 这可以通过GETSET mycounter "0"来实现:* </pre>** @param keyFormat*            key标识* @param value*            要设置的值* @param keyValues*            key变量* @return 设置之前的值*/public String getSet(String keyFormat, String value, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.getSet(key, value);} finally {if (jedis != null) {jedis.close();}}}/*** 执行原子加1操作** <pre>* 对key对应的数字做加1操作。如果key不存在,那么在操作之前,这个key对应的值会被置为0。* 如果key有一个错误类型的value或者是一个不能表示成数字的字符串,就返回错误。这个操作最大支持在64位有符号的整型数字。* 提醒:这是一个string操作,因为Redis没有专用的数字类型。key对应的string都被解释成10进制64位有符号的整型来执行这个操作。* Redis会用相应的整数表示方法存储整数,所以对于表示数字的字符串,没必要为了用字符串表示整型存储做额外开销。* </pre>** @param keyFormat*            key标识* @param keyValues*            key变量* @return 增加之后的value*/public Long incr(String keyFormat, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.incr(key);} finally {if (jedis != null) {jedis.close();}}}/*** 执行原子加1操作,并且设置过期时间(单位:s)** <pre>* 本操作是在{@linkplain RedisClient#incr(String, String...)}之上增加了一个设置过期时间的操作* </pre>** @param keyFormat*            key标识* @param expireTime*            过期时间(单位:s)* @param keyValues*            key变量* @return 增加之后的value*/public Long incr(String keyFormat, int expireTime, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();long result = jedis.incr(key);jedis.expire(key, expireTime);return result;} finally {if (jedis != null) {jedis.close();}}}/*** 执行原子增加一个整数** <pre>* 将key对应的数字加increment。如果key不存在,操作之前,key就会被置为0。* 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。这个操作最多支持64位有符号的正型数字。* 查看方法{@linkplain RedisClient#incr(String, String...)}了解关于增减操作的额外信息。* </pre>** @param keyFormat*            key标识* @param increment*            要增加的数值* @param keyValues*            key变量* @return 增加后的value*/public Long incrBy(String keyFormat, long increment, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.incrBy(key, increment);} finally {if (jedis != null) {jedis.close();}}}/*** 执行原子增加一个浮点数** <pre>* 将key对应的数字加increment。如果key不存在,操作之前,key就会被置为0。* 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。* </pre>** @param keyFormat*            key标识* @param increment*            要增加的数值* @param keyValues*            key变量* @return 增加后的value*/public Double incrByFloat(String keyFormat, double increment,String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.incrByFloat(key, increment);} finally {if (jedis != null) {jedis.close();}}}/*** 设置一个key的value值** <pre>* 警告:如果key已经存在了,它会被覆盖,而不管它是什么类型。* </pre>** @param keyFormat*            key标识* @param value*            要设置的值* @param keyValues*            key变量** @return 总是"OK"*/public String set(String keyFormat, String value, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.set(key, value);} finally {if (jedis != null) {jedis.close();}}}/*** 设置key-value并设置过期时间(单位:秒)** <pre>* 设置key对应字符串value,并且设置key在给定的seconds时间之后超时过期。* 该命令相当于执行了{@link #set(String, String, String...) SET} + {@link #expire(String, int, String...) EXPIRE}.并且该操作是原子的* </pre>** @param keyFormat*            key标识* @param seconds*            超时时间(单位:s)* @param value*            设置的值* @param keyValues*            key变量* @return 状态码*/public String setex(String keyFormat, int seconds, String value,String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.setex(key, seconds, value);} finally {if (jedis != null) {jedis.close();}}}/*** 设置key-value并设置过期时间(单位:毫秒)** <pre>* 跟{@link #setex(String, int, String, String...)}效果差不多,唯一区别是超时时间是ms* </pre>** @param keyFormat*            key标识* @param milliseconds*            超时时间(单位:ms)* @param value*            设置的值* @param keyValues*            key变量* @return 状态码*/public String psetex(String keyFormat, int milliseconds, String value,String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.psetex(key, (long) milliseconds, value);} finally {if (jedis != null) {jedis.close();}}}/*** 设置的一个关键的价值,只有当该键不存在** <pre>* 如果key不存在,就设置key对应字符串value。在这种情况下,该命令和SET一样。* 当key已经存在时,就不做任何操作。SETNX是"SET if Not eXists"。* </pre>** @param keyFormat*            key标识* @param value*            设置的value* @param keyValues*            key变量* @return 1 如果key被set,0 如果key没有被set*/public Long setnx(String keyFormat, String value, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.setnx(key, value);} finally {if (jedis != null) {jedis.close();}}}/*** 设置hash里面一个字段的值** @param keyFormat*            key标识* @param field*            字段* @param value*            值* @param keyValues*            key变量* @return 含义如下:1如果field是一个新的字段 0如果field原来在map里面已经存在**/public Long hset(String keyFormat, String field, String value,String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.hset(key, field, value);} finally {if (jedis != null) {jedis.close();}}}/******************************* SET 操作 *************************//*** 添加一个元素到集合(set)里** <pre>* 添加一个指定的member元素到集合的 key中.* 如果已经在集合key中存在则忽略.如果集合key 不存在,则新建集合key,并添加member元素到集合key中.* 如果key 的类型不是集合则返回错误.* </pre>** @param keyFormat*            key标识* @param value*            元素* @param keyValues*            key变量* @return 返回新成功添加到集合里元素的数量,不包括已经存在于集合中的元素.*/public Long sadd(String keyFormat, String value, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.sadd(key, value);} finally {if (jedis != null) {jedis.close();}}}/*** 获取集合里面的元素数量** @param keyFormat*            key标识* @param keyValues*            key变量* @return 集合的基数(元素的数量),如果key不存在,则返回 0.*/public Long scard(String keyFormat, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.scard(key);} finally {if (jedis != null) {jedis.close();}}}/*** 获取集合里面的所有key** @param keyFormat*            key标识* @param keyValues*            key变量* @return 集合中的所有元素.*/public Set<String> smembers(String keyFormat, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.smembers(key);} finally {if (jedis != null) {jedis.close();}}}/*** 删除并获取一个集合里面的元素** <pre>* 移除并返回一个集合中的随机元素* 该命令与 {@link #srandmember(String, String...)}相似,不同的是srandmember命令返回一个随机元素但是不移除.* </pre>** @param keyFormat*            key标识* @param keyValues*            key变量* @return 被移除的元素, 当key不存在的时候返回 null .*/public String spop(String keyFormat, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.spop(key);} finally {if (jedis != null) {jedis.close();}}}/*** 从集合里删除一个元素** @param keyFormat*            key标识* @param member*            要删除的元素* @param keyValues*            key变量* @return 从集合中移除元素的个数,不包括不存在的成员.*/public Long srem(String keyFormat, String member, String... keyValues) {String key = format(keyFormat, keyValues);Jedis jedis = null;try {jedis = getJedis();return jedis.srem(key, member);} finally {if (jedis != null) {jedis.close();}}}/**省略 其他不常用操作**/}
2、Redis单机模式:

配置方式有两种:

(1)代码配置Redis连接:省略jedis的一些属性配置

my.redis.server.host=xxx.xx.xxx
my.redis.server.port=6379
my.redis.server.password = wtyy
my.redis.server.jedis.pool.maxTotal=500
my.redis.server.jedis.pool.maxIdle=10
my.redis.server.jedis.pool.maxWaitMillis=5000
my.redis.server.jedis.pool.min-idle=5
my.redis.server.timeout=5000 
@Configuration
public class JedisConfig {private Logger logger = LoggerFactory.getLogger(JedisConfig.class);@Value("${my.redis.server.host}")private String host;@Value("${my.redis.server.port}")private int port;@Value("${my.redis.server.password}")private String password;@Value("${my.redis.server.jedis.pool.maxTotal}")private int maxTotal;@Value("${my.redis.server.jedis.pool.maxIdle}")private int maxIdle;@Value("${my.redis.server.jedis.pool.maxWaitMillis}")private int maxWaitMillis;@Value("${my.redis.server.timeout}")private int timeout;@Bean(name = "jedisPool")public JedisPool jedisPool() {JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(maxTotal);config.setMaxIdle(maxIdle);config.setMaxWaitMillis(maxWaitMillis);return new JedisPool(config, host, port, timeout,password);}
}

(2)在配置文件中配置redis连接:不建议使用

spring.redis.database=1
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=500
spring.redis.pool.min-idle=0
spring.redis.timeout=0

相关文章:

Jedis(一)与Redis的关系

一、Jedis介绍&#xff1a; 1、背景&#xff1a; Jedis是基于Java语言的Redis的客户端&#xff0c;Jedis Java Redis。Redis不仅可以使用命令来操作&#xff0c;现在基本上主流的语言都有API支持&#xff0c;比如Java、C#、C、PHP、Node.js、Go等。在官方网站里有一些Java的…...

K8S--安装Nginx

原文网址&#xff1a;K8S--安装Nginx-CSDN博客 简介 本文介绍K8S安装Nginx的方法。 1.创建Nginx目录及配置文件 mkdir -p /work/devops/k8s/app/nginx/{config,html} 在config目录下创建nginx.conf配置文件&#xff0c;内容如下&#xff1a; # events必须要有 events {wo…...

[BUUCTF]-PWN:babyfengshui_33c3_2016解析

又是一道堆题&#xff0c;先看保护 关键信息是32位&#xff0c;没开pie 直接看ida 大致是alloc创建堆块&#xff0c;free释放堆块&#xff0c;show查看堆块内容&#xff0c;fill填充堆块内容 其他的都没啥关键的要讲&#xff0c;但alloc那里非常需要解析一下 解释如上图 再具…...

小程序系列--9.生命周期

1. 什么是生命周期&#xff1f; 2. 生命周期的分类 3. 什么是生命周期函数 4. 生命周期函数的分类 5. 应用的生命周期函数 6. 页面的生命周期函数...

SQL注入实战操作

一&#xff1a;SQl注入分类 按照注入的网页功能类型分类&#xff1a; 1、登入注入&#xff1a;表单&#xff0c;如登入表单&#xff0c;注册表单 2、cms注入&#xff1a;CMS逻辑:index.php首页展示内容&#xff0c;具有文章列表(链接具有文章id)、articles.php文 章详细页&a…...

Microsoft Remote Desktop for Mac(远程桌面连接)激活版

Microsoft Remote Desktop是一款由微软开发的远程桌面连接工具&#xff0c;它允许用户从另一台计算机或移动设备远程连接到Windows桌面或服务器。 以下是该软件的一些主要特点和功能&#xff1a; 跨平台支持&#xff1a;Microsoft Remote Desktop支持Windows、macOS、iOS和Andr…...

分布式日志

1 日志管理 1.1 日志管理方案 服务器数量较少时 直接登录到目标服务器捞日志查看 → 通过 rsyslog 或shell/python 等脚本实现日志搜集并集中保存到统一的日志服务器 服务器数量较多时 ELK 大型的日志系统&#xff0c;实现日志收集、日志存储、日志检索和分析 容器环境 …...

21.云原生之ArgoCD CICD实战(部分待补充)

云原生专栏大纲 文章目录 部署项目介绍项目结构介绍GitLab CI/CDGitLab CI/CD主要特点和功能 部署测试argocd的cd过程CICD工作流准备工作github中工作流文件创建gitlab中工作流文件创建【实操待补充】GitLab CI示例 数据加密之seale sealedBitnami Sealed Secrets介绍Bitnami …...

一文读懂JavaScript DOM节点操作(JavaScript DOM节点操作详解)

一、什么是节点 DOM模型是树状结构模型&#xff0c;二组成这棵树的就是一个个点&#xff0c;在网络术语中称之为节点。 节点是一个模型中最基本的组成单位。DOM模型是由一个个节点组成的&#xff0c;DOM节点也有其不同的类型。 二、节点类型 DOM节点分为5种类型&#xff1a;…...

【Linux】常见指令(一)

前言: Linux有许多的指令&#xff0c;通过学习这些指令&#xff0c;可以对目录及文件进行操作。 文章目录 一、基础指令1. ls—列出目录内容2. pwd—显示当前目录3. cd—切换目录重新认识指令4. touch—创建文件等5. mkdir—创建目录6. rmdir指令 && rm 指令7. man—显…...

C语言大师(8)异常处理

引言 异常处理是C编程中处理运行时错误的关键机制。它通过 try、catch 和 throw 关键字提供了一种强大的方法来处理程序执行中可能出现的异常情况。了解如何有效地使用这些机制对于编写健壮且可维护的程序至关重要。 1. 基本异常处理 在C中&#xff0c;try 块用于包围可能发生…...

网络防御保护——1.网络安全概述

一.网络安全概念 通信保密阶段 --- 计算机安全阶段 --- 信息系统安全 --- 网络空间安全 APT攻击 --- 高级持续性威胁 网络安全(网络空间安全--Cyberspace)从其本质上讲就是网络上的信息安全&#xff0c;指网络系统的硬件、软件及数据受到保护。不遭受破坏、更改、泄露&#xf…...

SpringBoot整合ElasticSearch实现分页查询

本文使用SpringBoot整合ElasticSearch实现分页查询 文章目录 环境准备 环境准备 还是继续使用spring-boot-starter-data-elasticsearch来实现分页查询操作...

[C++]使用yolov8的onnx模型仅用opencv和bytetrack实现目标追踪

【官方框架地址】 yolov8: https://github.com/ultralytics/ultralytics bytetrack: https://github.com/ifzhang/ByteTrack 【算法介绍】 随着人工智能技术的不断发展&#xff0c;目标追踪已成为计算机视觉领域的重要研究方向。Yolov8和ByTetrack作为当前先进的算法&…...

打造专业级ChatGPT风格聊天界面:SpringBoot与Vue实现动态打字机效果,附完整前后端源码

大家好&#xff0c;今天用SpringBoot、vue写了一个仿ChatGPT官网聊天的打字机效果。 所有代码地址:gitee代码地址 &#xff0c;包含前端和后端&#xff0c;可以直接运行 使用本技术实现的项目&#xff1a;aicnn.cn&#xff0c;欢迎大家体验 如果文章知识点有错误的地方&#xf…...

KMP-重复子字符串

Problem: 459. 重复的子字符串 文章目录 题目思路复杂度Code 题目 给定一个字符串str1, 判断其是否由重复的子串构成。 例子1&#xff1a;输入 str1‘ababab’ &#xff1b;输出 true 例子2&#xff1a;输入 str1‘ababac’ &#xff1b;输出 false 思路 重复子字符串组成的字…...

如何使用Markdown生成目录索引

一、Markdown生成目录索引怎么折叠 在Markdown中&#xff0c;可以使用[TOC]语法生成目录索引。 如果想要折叠目录&#xff0c;则需要使用一些插件&#xff0c;如Tocbot、jquery-tocify等。 例如&#xff0c;在使用Tocbot时&#xff0c;可以在Markdown文档中加入以下代码&…...

R语言【taxa】——as_taxon():转换为 taxon 对象

Package taxa version 0.4.2 Description 将其他对象转换为 taxon 向量。taxon 构造器可能将 基础向量转换为 taxon 向量。 Usage as_taxon(x, ...) Arguments 参数【x】&#xff1a;要转换为 taxon 向量的对象。 参数【...】&#xff1a;其余参数。 Examples x <- taxo…...

Android状态栏布局隐藏的方法

1.问题如下&#xff0c;安卓布局很不协调 2.先将ActionBar设置为NoActionBar 先打开styles.xml 3.使用工具类 package com.afison.newfault.utils;import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.graph…...

idea创建公用依赖包项目

创建parent项目 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...