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

【SpringBoot】31 Session + Redis 实战

Gitee

https://gitee.com/Lin_DH/system

介绍

【SpringBoot】30 Cookie、Session、Token https://blog.csdn.net/weixin_44088274/article/details/144241595

背景

Spring Session 是 Spring 的一个子项目,它提供了一种管理用户会话信息的方法,无论是在单服务的应用程序中,还是在分布式系统中,都能运用。Spring Session 提供了一种机制,可以将应用服务器的会话(HttpSession)抽象化,使得开发者可以在不同的环境下使用系统的 API 来管理会话。

Spring Session

原理

Spring Session 使支持集群会话变得简单,无需绑定到特定应用程序容器的解决方案。

  • HttpSession:以通用的方式替代应用程序容器(如 Tomcat)中(Servlet 容器实现)的 HttpSession,实现了会话数据的外部存储,并支持在请求头(Header)中提供 sessionId,方便提供 RESTful API。
  • WebSocket:提供在接收 WebSocket 消息时保持 HttpSession 活跃的能力。
  • WebSession:允许以与应用程序容器无关的方式替换 Spring WebFlux 的 WebSession。
  • 配置类:提供了几个关键配置类,如 RedisHttpSessionConfiguration 和 SpringHttpSessionConfiguration,用于配置 Redis 作为会话数据的存储源。
  • SessionRepositoryFilter:SessionRepositoryFilter 是 Spring Session 的核心组件之一,它负责在请求处理之前和之后与会话存储进行交互,以确保会话数据的正确加载和保存。
    在这里插入图片描述

组成

Spring Session Core:提供核心的 Spring 会话功能和 Api。
Spring Session Data Redis:提供 SessionRepository 和 ReactiveSessionRepository 的实现,支持 Redis 和配置。
Spring Session JDBC:提供由关系型数据库和配置支持所支持的 SessionRepository 实现。
Spring Session Hazelcast:提供由 Hazelcast 和配置支持所支持的 SessionRepository 实现。

Redis 实现分布式 Session

在这里插入图片描述
在分布式系统中,通常会将 Session 存储在 Redis 中来实现分布式 Session,这样可以在多台服务器之间共享 Session 数据。实现分布式 Session 通常使用 Redis 的 Hash 结构。
1)用户登录:当用户登录成功后,服务端会生成一个唯一的 SessionId(通常是一串随机字符串,如 UUID)。
2)存储 Session:将用户的会话信息(如用户ID,权限信息等)与 SessionId 关联,并存储在 Redis 中,Redis 使用 Hash 结构来存储这些数据,其中 SessionID 作为 Hash 的 Key,用户的会话信息作为 Hash 的 Value。
3)设置 Cookie:将 SessionId 通过 Cookie 发送到客户端浏览器,客户端每次请求时都需要携带上 Cookie。
4)请求处理:在客户端每次发起请求时,服务端会检查 Cookie 中的 SessionId,服务端用该 SessionId 从 Redis 中检索对应的 Session 数据。
5)认证与授权:通过检索到的 Session 数据,服务端可以验证用户身份,并根据用户的会话信息进行授权。
Session 过期:设置 Session 过期时间,当用户长时间不活动或者显式退出登录时,服务端会从 Redis 中删除对应的 Session 数据。
在这里插入图片描述
在这里插入图片描述

代码实现

依赖

pom.xml

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- 实现对 Spring Session 使用 Redis 作为数据源的自动化配置 --><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency><!-- 实现对 Spring Data Redis 的自动化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><!-- 去掉对 Lettuce 的依赖,因为 Spring Boot 优先使用 Lettuce 作为 Redis 客户端 --><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><!-- 引入 Jedis 的依赖,这样 Spring Boot 实现对 Jedis 的自动化配置 --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>

配置

application.yml

spring:redis:host: localhostport: 6379
#    password:#Redis数据库号,默认为0database: 0    #连接超时时间,单位为毫秒    timeout: 10#对应 RedisProperties.Jedis 内部类jedis:pool:#连接池最大连接数,默认为8,使用负数表示没有限制max-active: 8 #默认连接池最大空闲的连接数,默认为8,使用负数表示没有限制max-idle: 8#默认连接池最小空闲的连接数,默认为0,允许设置0和正数min-idle: 0#连接池最大阻塞等待时间,单位为毫秒,默认为-1,表示不限制max-wait: -1

添加配置类

SessionConfiguration.java

package com.lm.system.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;/*** @author DUHAOLIN* @date 2024/11/22*/
@Configuration
@EnableRedisHttpSession // 自动化配置 Spring Session 使用 Redis 作为数据源
public class SessionConfiguration {@Bean(name = "springSessionDefaultRedisSerializer")public RedisSerializer<Object> springSessionDefaultRedisSerializer() {return RedisSerializer.json();}}

添加 @EnableRedisHttpSession 注解,开启自动化配置 Spring Session 使用 Redis 作为数据源。该注解有如下属性:

  • maxInactiveIntervalInSeconds:Session 不活跃后的过期时间,默认为 1800 秒。
  • redisNamespace:在 Redis Key 的统一前缀,默认为 “spring:session”。
  • redisFlushMode:Redis 会话刷新模式。目前有两种,默认为 RedisFlushMode.ON_SAVE。
  • RedisFlushMode.ON_SAVE:请求执行完成时,统一写入 Redis 存储。
  • RedisFlushMode.IMMEDIATE:每次修改 Session 时,立即写入 Redis 存储。
  • cleanupCron:清理 Redis Session 会话过期的任务执行 Cron 表达式,默认为 “0 * * * * *” 每分钟执行一次。虽说 Redis自带 Key 过期机制,但是默认该机制为惰性删除策略,实际过期的 Session 还保存在 Redis 的内存中。所以 Spring Session 通过定时任务,删除 Redis 中过期的 Session,使之尽快释放 Redis 的内存。
    在 springSessionDefaultRedisSerializer() 方法中,定义了一个 Bean 名字为 springSessionDefaultRedisSerializer 的 RedisSerializer Bean,采用 JSON 序列化方式。默认情况下采用 Java 自带的序列化方式,可读性较差,所以需要进行替换。

配置 Redis 序列化

RedisConfig.java

package com.lm.system.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/*** @author DUHAOLIN* @date 2024/11/13*/
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();    redisTemplate.setConnectionFactory(factory);//设置key序列化方式stringredisTemplate.setKeySerializer(new StringRedisSerializer());//设置value序列化方式json,使用GenericJackson2JsonRedisSerializer替代默认序列化redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.setHashKeySerializer(new StringRedisSerializer());    redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.afterPropertiesSet();    return redisTemplate;}}

测试

SessionController.java

package com.lm.system.controller;import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpSession;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;/*** @author DUHAOLIN* @date 2024/11/22*/
@RestController
@RequestMapping("session")
public class SessionController {@PostMapping("set")public void set(HttpSession session, @RequestParam("key") String key, @RequestParam("value") String value) {session.setAttribute(key, value);}@GetMapping("getAll")public Map<String, Object> getAll(HttpSession session) {Map<String, Object> resultMap = new HashMap<>();for(Enumeration<String> names = session.getAttributeNames(); names.hasMoreElements();) {String key = names.nextElement();Object value = session.getAttribute(key);resultMap.put(key, value);}return resultMap;}}

效果图

启动程序后,进行查询,未查询到 Session 数据。
在这里插入图片描述
客户端访问完,到 Redis 客户端进行查询,则能够查询到 Spring Session 保存到 Redis 的 Session 数据。
在这里插入图片描述
每个 Session 对应 Redis 中 两个键值对。

  • 头部:以 spring:session 开头,可以通过 @EnableRedisHttpSession 直接的 redisNamespace 属性进行配置。
  • 结尾:以对应 Session 的 sessionId 结尾。
  • 中间:中间分别是 session、expirations、sessions:expires 。
    从下图该 session 的内容可以看出,其是一个 Redis Hash 数据结构。
    在这里插入图片描述
    客户端发起 set 请求,设置 key 和 value。
    在这里插入图片描述
    此时再次在 Redis 客户端进行查询,则该 Session 信息已经发生改变。
    在这里插入图片描述

Redis 序列化

RedisSerializer

org.springframework.data.redis.serializer.RedisSerializer 接口,Redis 序列化接口,用于 Redis KEY 和 VALUE 的序列化。

RedisSerializer.java

public interface RedisSerializer<T> {@Nullablebyte[] serialize(@Nullable T t) throws SerializationException;@NullableT deserialize(@Nullable byte[] bytes) throws SerializationException;}

定义了对象 和二进制数组的转换。
Redis Client 传递给 Redis Server 是传递的 KEY 和 VALUE 都是二进制值数组。
RedisSerializer 的实现类:
在这里插入图片描述
主要分为四类:JDK 序列化方式、String 序列化方式、JSON 序列化方式、XML 序列化方式。

JDK序列化方式

介绍

org.springframework.data.redis.serializer.JdkSerializationRedisSerializer ,默认情况下,RedisTemplate 使用该数据列化方式。
RedisTemplate#afterPropertiesSet() 方法,在 RedisTemplate 未设置序列化的情况下,使用 JdkSerializationRedisSerializer 作为序列化实现。在 Spring Boot 自动化配置 RedisTemplate Bean 对象时,就未设置。
绝大情况下,不会使用该序列化,如下图所示,写入的 KEY 前会携带 16 进制字符,而通过该 KEY 获取的 VALUE 也携带有 16 进制字符,获取的结果不方便阅读。
在 ObjectOutputStream#writeString(String str,boolean unshared) 代码中,实际是:标志位 + 字符串长度 + 字符串内容。
注:测试之前如果前面配置了序列化(RedisConfig.java)需要先注释 @Configuration 注解。

测试代码

RedisTest.java

package com.lm.system;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import javax.annotation.Resource;/*** @author DUHAOLIN* @date 2024/11/29*/
@SpringBootTest
@RunWith(value = SpringJUnit4ClassRunner.class)
public class RedisTest {@Resourceprivate RedisTemplate redisTemplate;@Testpublic void test01() {redisTemplate.opsForValue().set("name", "Jack");}}

效果图

在这里插入图片描述

String序列化方式

org.springframework.data.redis.serializer.StringRedisSerializer,字符串和二进制数组的直接转换。

StringRedisSerializer.java

private final Charset charset;@Override
public String deserialize(@Nullable byte[] bytes) {return (bytes == null ? null : new String(bytes, charset));
}@Override
public byte[] serialize(@Nullable String string) {return (string == null ? null : string.getBytes(charset));
}

绝大多数情况下,KEY 和 VALUE 使用的此序列化方式。而 VALUE 的序列化和反序列化,需要开发人员自己在逻辑调用 JSON 方法来序列化。
org.springframework.data.redis.serializer.GenericToStringSerializer ,使用 Spring ConversionService 实现 对象和 String 的转换,从而 String 和二进制数组的转换。
序列化的过程,首先 对象通过 ConversionService 转换成 String ,然后 String 再序列化成二进制数组。

JSON 序列化方式

1)org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer,使用 Jackson 实现 JSON 的序列化方式是支持所有类。

GenericJackson2JsonRedisSerializer.java

public GenericJackson2JsonRedisSerializer(@Nullable String classPropertyTypeName) {this(new ObjectMapper());// simply setting {@code mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)} does not help here since we need// the type hint embedded for deserialization using the default typing feature.mapper.registerModule(new SimpleModule().addSerializer(new NullValueSerializer(classPropertyTypeName)));//<1>if (StringUtils.hasText(classPropertyTypeName)) {mapper.enableDefaultTypingAsProperty(DefaultTyping.NON_FINAL, classPropertyTypeName);//<2>} else {mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, As.PROPERTY);}
}

<1> 如果传入 classPropertyTypeName 属性,使用传入对象的 classPropertyTypeName 属性对应的值,作为默认类型(Default Typing)。
<2> 如果未传入 classPropertyTypeName 属性,则使用传入对象的类全名,作为默认类型(Default Typing)。
2)org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer,使用 Jackson 实现 JSON 的序列化方式,并且显示指定 类型。

Jackson2JsonRedisSerializer.java

public class Jackson2JsonRedisSerializer<T> implements RedisSerializer<T> {//...public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;/*** 指定类型,和 <T> 要一致。*/private final JavaType javaType;private ObjectMapper objectMapper = new ObjectMapper();}

Jackson2JsonRedisSerializer 序列化类里已经声明了类型,所以序列化的 JSON 字符串,无需在存储一个 @class 属性,用于存储类型。
3)com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer,使用 FastJSON 实现 JSON 的序列化方式,和 GenericJackson2JsonRedisSerializer 一致。
4)com.alibaba.fastjson.support.spring.FastJsonRedisSerializer,使用 FastJSON 实现 JSON 的序列化方式,和 Jackson2JsonRedisSerializer 一致。

XML序列化方式

org.springframework.data.redis.serializer.OxmSerializer,使用 Spring OXM 实现将对象和 String 的转换,从而 String 和二进制数组的转换。

参考链接

【Spring Boot 分布式 Session 入门】https://www.iocoder.cn/Spring-Boot/Distributed-Session/?self

相关文章:

【SpringBoot】31 Session + Redis 实战

Gitee https://gitee.com/Lin_DH/system 介绍 【SpringBoot】30 Cookie、Session、Token https://blog.csdn.net/weixin_44088274/article/details/144241595 背景 Spring Session 是 Spring 的一个子项目&#xff0c;它提供了一种管理用户会话信息的方法&#xff0c;无论…...

在Windows环境下的rknn-toolkit环境搭建

首先安装好conda&#xff0c;我是用的是anaconda&#xff0c;miniconda也可以。 下载rknn_toolkit的轮子。可以直接在瑞芯微的git仓库中下载&#xff0c;地址为&#xff1a;github.com/rockchip-linux/rknn-toolkit/releases。我这里下载的是1.7.5版本的。选择rknn-toolkit-v1.…...

Facebook广告突然无消耗?原因解析与解决方案。

在Facebook广告投放中&#xff0c;广告突然无消耗是很多广告主都会遇到的难题。这种情况不仅浪费时间&#xff0c;还可能导致营销活动停滞&#xff0c;影响业务发展。那么&#xff0c;广告无消耗的原因是什么&#xff1f;又该如何解决呢&#xff1f; 一、Facebook广告无消耗的…...

Rabbitmq 镜像队列

RabbitMQ 支持高可用性队列&#xff08;HA Queues&#xff09;&#xff0c;可以在多个节点之间复制队列&#xff0c;确保即使某个节点失败&#xff0c;消息仍然可用。将 RabbitMQ 部署为集群&#xff0c;确保高可用性和负载均衡。 RabbitMQ 的镜像队列集群&#xff08;Mirrore…...

TensorBoard

1、TensorFlow的TensorBoard TensorBoard是TensorFlow的一个组件&#xff0c;它提供了一个交互式的界面&#xff0c;用于可视化TensorFlow程序的训练过程和模型结构。 使用TensorBoard&#xff0c;你可以&#xff1a; 可视化训练过程中的各种指标&#xff0c;如损失函数、准…...

运维实战:K8s 上的 Doris 高可用集群最佳实践

今天我们将深入探讨&#xff1a;&#xff1a;如何在 K8s 集群上部署 Compute storage coupled&#xff08;存算耦合&#xff09; 模式的 Doris 高可用集群&#xff1f; 本文&#xff0c;我将为您提供一份全面的实战指南&#xff0c;逐步引导您完成以下关键任务&#xff1a; 配…...

2024.12.5——攻防世界Training-WWW-Robots攻防世界baby_web

2024.12.5—攻防世界Training-WWW-Robots 知识点&#xff1a;robots协议 dirsearch工具 本题与第一道Robots协议十分类似&#xff0c;不做wp解析 大致步骤&#xff1a; step 1 打开靶机&#xff0c;发现是robots协议相关 step 2 用dirsearch进行扫描目录 step 3 url传参r…...

当 Nginx 出现连接超时问题,如何排查?

文章目录 当 Nginx 出现连接超时问题&#xff0c;如何排查&#xff1f; 一、了解 Nginx 连接超时的基本概念二、可能导致 Nginx 连接超时的原因 &#xff08;一&#xff09;服务器负载过高&#xff08;二&#xff09;上游服务响应缓慢&#xff08;三&#xff09;网络问题&…...

vue2 项目中实现动态代理,服务器上通过nginx部署 实现动态代理

一、前言&&原理 前言&#xff1a;vue2 项目中&#xff0c;请求接口是从表格的当前获取的&#xff0c;也就是接口ip:端口号:路经不确定&#xff0c;要实现点击表格当前行请求对应的接口 实现原理&#xff1a;将实际要请求的ip等信息存在请求头中&#xff0c;用的时候再…...

基于SpringBoot+Vue的民宿山庄农家乐管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…...

【数据分享】1901-2023年我国省市县三级逐年最低气温数据(Shp/Excel格式)

之前我们分享过1901-2023年1km分辨率逐月最低气温栅格数据和Excel和Shp格式的省市县三级逐月最低气温数据&#xff0c;原始的逐月最低气温栅格数据来源于彭守璋学者在国家青藏高原科学数据中心平台上分享的数据&#xff01;基于逐月栅格数据我们采用求年平均值的方法得到逐年最…...

后端API接口设计标准(Java)

Controller 层&#xff08;API接口&#xff09; 无论是传统的三层架构还是现在的COLA架构&#xff0c;Controller 层依旧有一席之地&#xff0c;说明他的必要性&#xff1b;说它是配角是因为 Controller 层的代码一般是不负责具体的逻辑业务逻辑实现&#xff0c;但是它负责接收…...

网络安全法 -网络信息安全

第四章 网络信息安全 第四十条 网络运营者应当对其收集的用户信息严格保密&#xff0c;并建立健全用户信息保护制度。 第四十一条 网络运营者收集、使用个人信息&#xff0c;应当遵循合法、正当、必要的原则&#xff0c;公开收集、使用规则&#xff0c;明示收集、使用信息的…...

matlab figure函数 single 数据类型

1.matlab figure函数详细介绍 在MATLAB中&#xff0c;figure函数用于创建新的图形窗口或激活现有的图形窗口。以下是figure函数的详细介绍和用法&#xff1a; 基本用法 创建新图形窗口&#xff1a;不带任何参数调用figure会创建一个新的图形窗口&#xff0c;并将其设为当前活…...

endroid/qr-code生成二维码,中文乱码的解决方案

endroid/qr-code version:6.0.3 默认不支持中文&#xff1b; 1、https://fonts.google.com/noto/fonts&#xff0c;从这里下载字体&#xff1b; 2、下载简体中文&#xff1a;Noto Sans Simplified Chinese 3、下载后&#xff0c;把压缩包解压&#xff0c;把NotoSansSC-Regul…...

深度和法线纹理

屏幕后期处理效果的基本原理就是当游戏画面渲染完毕后通过获取到该画面的信息进行额外的效果处理 之前的边缘检测、高斯模糊、Bloom、运动模糊等效果都是基于获取当前屏幕图像中的像素信息进行后期处理的 如果仅仅根据像素信息来进行一些效果处理&#xff0c;存在以下问题&…...

监听H5页面在微信浏览器异常退出

参考文章 onBeforeUnmount(() > {unNormalExit(); });//---------------------------异常退出---------------------- function unNormalExit() {enterOrExitRoom({type: 37,roomId: roomId.value,userId: userId.value,nickName: name.value,loginUserType: 2, //0 专家 1…...

Linux 串口编程

目录 前言一、tty体系二、串口硬件基础知识三、Linux下的串口编程3.1 打开串口3.2 从串口读写数据,问题1、2的诞生3.3 关闭串口3.4 串口配置3.4.1 获取/设置串口的参数3.4.2 设置波特率3.4.3 设置控制模式标志3.4.4 设置本地模式标志3.4.5 设置输入模式标志3.4.6 设置输出模式标…...

Adminer源码编译 精简语言中英文和基本使用方法

Adminer是一个小而强悍的基于web的数据库管理工具&#xff0c; 官方默认支持几十种语言&#xff0c;但是对于中国的用户而言只需要有中文和英文就够了&#xff0c;其他语言基本无用。这就需要我们下载Adminer源码自己编译 Adminer.php , 如下图所示 adminer 中英文语言精简版本…...

go 中线程安全map

在 Go 语言中&#xff0c;官方包 sync.Map 确实提供了线程安全的映射数据结构。然而&#xff0c;正如你所提到的&#xff0c;使用 sync.Map 时&#xff0c;有时需要进行类型断言&#xff0c;这可能会让代码显得冗长或不直观。 如果你希望使用一个更加易用的线程安全映射&#…...

eslint 安装与使用-基础教程

中文官网 官方规则解析 规则参考 - ESLint - 插件化的 JavaScript 代码检查工具 eslint ESlint 是一个检查 JS,TS 语法的工具.能够与常用开发工具&#xff0c;例如 VS Code&#xff0c;进行集成并提供错误提示&#xff0c;和可能的修正方法 安装 安装eslint npm init esli…...

自然语言处理的未来愿景

自然语言处理的未来愿景 在这个信息爆炸的时代,计算机如何理解和生成我们日常使用的语言,已经成为一个引人注目的问题。你有没有想过,为什么智能助手能理解你的指令?又或者,为什么社交媒体上的推荐引擎能够精准地推荐你喜爱的内容?这背后,正是自然语言处理(NLP)在发挥…...

等保2.0三级测评华为华三交换机路由器

在使用本博客提供的学习笔记及相关内容时,请注意以下免责声明: 信息准确性:本博客的内容是基于作者的个人理解和经验,尽力确保信息的准确性和时效性,但不保证所有信息都完全正确或最新。 非专业建议:博客中的内容仅供参考,不能替代专业人士的意见和建议。在做出任何重要…...

BA和CS算法中的Levy飞行策略

Levy飞行策略通过模拟自然界中动物的长距离迁徙行为&#xff0c;指导粒子进行更大范围的搜索&#xff0c;有助于算法快速找到全局最优解。它是一种具有独特优势的随机行为策略&#xff0c;模拟随机游走或搜索过程中的步长和方向&#xff0c;其步长的概率分布为重尾分布&#xf…...

PHP:实现两张无关联表数据的联合分页处理方案

前言 在现代软件开发中&#xff0c;高效地处理数据是至关重要的环节。尤其是在使用 PHP 进行开发时&#xff0c;常常会遇到各种复杂的数据处理需求。其中&#xff0c;实现两张无关联表数据的联合分页处理就是一个具有挑战性的任务。这种需求在很多实际应用场景中都可能出现&am…...

【单元测试】单元测试介绍

1 单元测试基础 1.单元测试&#xff1a;单元测试又称模块测试&#xff0c;属于白盒测试&#xff0c;是最小单位的测试。模块分为程序模块和功能模块。功能模块指实现了一个完整功能的模块&#xff08;单元&#xff09;&#xff0c;一个完整的程序单元具备输入、加工和输出三个…...

PyQt事件机制及其应用

一、实例前置 一个小闹钟应用 创建主窗口类 首先我们创建了一个名为AlarmClock的类&#xff0c;它继承自QMainWindow。这个类将包含我们的GUI组件和逻辑。 from Alarm_clock import Ui_MainWindowclass AlarmClock(QMainWindow):def __init__(self):super().__init__()# 初始化…...

厦门凯酷全科技有限公司抖音电商服务的卓越典范

在短视频和直播带货迅速崛起的时代&#xff0c;厦门凯酷全科技有限公司&#xff08;以下简称“凯酷全科技”&#xff09;以其专业的服务、创新的精神以及对市场的深刻理解&#xff0c;在抖音电商领域中脱颖而出&#xff0c;成为众多品牌商家信赖的选择。本文将深入探讨凯酷全科…...

vue3水波柱状图 ,实现

效果图 //引用页面 <div style"height: 60px;background-color: #fff;border-radius: 5px;width: 40px;"><WavePercentage:percentage"progress"primary-color"#ffcb7c"secondary-color"#ffcb7c"/></div>import Wa…...

如何在两台 PostgreSQL 服务器之间使用逻辑复制槽进行数据复制

如何在两台 PostgreSQL 服务器之间使用逻辑复制槽进行数据复制 如何在两台 PostgreSQL 服务器之间使用逻辑复制槽进行数据复制环境准备1. 配置主服务器&#xff08;Publisher&#xff09;1.1 修改 postgresql.conf1.2 修改 pg_hba.conf1.3 重启 PostgreSQL 服务1.4 创建逻辑复制…...

湖南品牌网站建站可定制/本网站三天换一次域名

2019独角兽企业重金招聘Python工程师标准>>> hdfs优点&#xff1a; -高容错性&#xff1a;多副本&#xff1b;副本丢失后可以自动恢复-适合批处理&#xff1a;移动计算而非数据&#xff1b;数据位置暴露给计算框架-适合大数据库处理&#xff1a;TB,PB量级数据处理&a…...

网站首页样式/杭州网站关键词排名优化

配置办法https://blog.csdn.net/qq342643414/article/details/78364601 可能会遇到的问题https://www.cnblogs.com/chuijingjing/p/9880095.html转载于:https://www.cnblogs.com/helf/p/10709686.html...

网站做可信认证多少钱/国家高新技术企业查询

进程原语和线程原语是啥意思本文向您展示如何将WebSphere ESB StockQuote样本&#xff08;IBM Integration Designer随附&#xff09;中的资源转换为IBM Integration Bus资源。 StockQuote示例使用带有SOAP / JMS Web服务绑定的导出。 由StockQuote中介流记录输入的JMS消息&…...

自已建网站微信登录/app推广实名认证接单平台

windows 远程桌面连接使用性技术分享 1、mstsc的介绍&#xff1f; Mstsc (Microsoft terminal services client) Mstsc还有一种说法&#xff0c;Microsoft Telnet Screen Control &#xff0c;即“微软远程桌面控制”。 mstsc 与远程客户端之间是用Microsoft的远程桌面协议(…...

要修改wordpress目录下的文件权限/北京百度竞价托管公司

问题如题&#xff1a;安装方法参考 http://www.cnblogs.com/shengulong/p/7887586.html &#xff0c;安装完后&#xff0c;使用时出现如题的错误 解决办法&#xff1a; 1、zerorpc本身依赖很多三方包&#xff0c;请注意版本的兼容性&#xff0c;因此最佳方案是&#xff0c;把这…...

seo外贸网站建设/东营网站seo

最近&#xff0c;遇到一个问题&#xff0c;安装完成VMware 11之后&#xff0c; VMware Network Adapter VMnet1 没有生成&#xff0c;只有VMware Network Adapter VMnet8&#xff0c;上网找了一下&#xff0c;解决办法如下&#xff1a;编辑--虚拟机网络编辑器--还原默认设置&am…...