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

30分钟内搭建一个全能轻量级springboot 3.4 + 脚手架 <5> 5分钟集成好caffeine并使用注解操作缓存

快速导航

<1> 5分钟快速创建一个springboot web项目
<2> 5分钟集成好最新版本的开源swagger ui,并使用ui操作调用接口
<3> 5分钟集成好druid并使用druid自带监控工具监控sql请求
<4> 5分钟集成好mybatisplus并使用mybatisplus generator自动生成代码
<5> 5分钟集成好caffeine并使用注解操作缓存
<6> 5分钟集成好前端页面,使用vue开发前端

目录

  • 一、准备工作
    • 1.1 maven 安装caffeine和相关依赖
    • 1.2 配置caffeine
      • 1.2.1 javaconfig配置caffeine
      • 1.2.2 缓存代码编写
    • 1.3 注解说明
  • 二、测试
  • 三、注解操作缓存原理以及一些难点排查
    • 3.1 注解操作缓存原理
    • 3.2 难点排查
  • 总结

在 Spring Boot 中,注解操作缓存的原理基于 Spring 的缓存抽象 (Spring Cache Abstraction)。使用缓存注解时,Spring 会自动处理与缓存相关的逻辑,而开发者只需要专注于业务代码。常用的缓存注解有 @Cacheable、@CachePut 和 @CacheEvict。

一、准备工作

1.1 maven 安装caffeine和相关依赖

<dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>3.1.8</version> <!-- 确保版本兼容 -->
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>

1.2 配置caffeine

有两种配置方式

1.2.1 javaconfig配置caffeine

package com.example.demo.config;import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.List;
import java.util.concurrent.TimeUnit;@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic Caffeine<Object, Object> caffeineConfig() {return Caffeine.newBuilder().maximumSize(1000).expireAfterWrite(5, TimeUnit.MINUTES)
//                .weakKeys() // 很坑会,基本上很快就把key清理掉了,缓存再也命中不了.recordStats();}@Beanpublic CacheManager cacheManager(Caffeine<Object, Object> caffeine) {CaffeineCacheManager cacheManager = new CaffeineCacheManager();cacheManager.setCaffeine(caffeine);cacheManager.setCacheNames(List.of(new String[]{"users"}));return cacheManager;}}

1.2.2 缓存代码编写

TestController

package com.example.demo.web;import com.example.demo.entity.User;
import com.example.demo.service.IUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/test")
@Tag(name = "User API", description = "用户管理相关接口")
public class TestController {@Resourceprivate IUserService userService;@GetMapping("")@Operation(method = "test", summary = "测试接口")public String test(){return "test";}@GetMapping("/user")@Operation(method = "allUsers", summary = "获取所有用户")public List<User> allUsers(){return userService.list();}@GetMapping("/user/{id}")@Operation(method = "getUserCache", summary = "获取用户缓存")public void testGetUserCache(@PathVariable String id){User user = userService.getUserById(id);System.out.println(user);}}

UserServiceImpl

package com.example.demo.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.IUserService;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;/*** <p>* 测试用户 服务实现类* </p>** @author allens* @since 2025-01-15*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Cacheable(value = "users", key = "'user_' + #id", unless = "#result == null")public User getUserById(String id) {// 模拟数据库查询return this.getBaseMapper().selectById(id);}@CachePut(value = "users", key = "#id")public void updateUser(String id, String name) {// 模拟更新数据库并返回新值User user = this.getBaseMapper().selectById(id);user.setName(name);this.getBaseMapper().updateById(user);}@CacheEvict(value = "users", key = "#id")public void deleteUser(String id) {// 模拟删除数据库记录System.out.println("User with id " + id + " has been deleted from database and cache.");this.getBaseMapper().deleteById(id);}@CacheEvict(value = "users", allEntries = true)public void clearCache() {System.out.println("All user cache has been cleared.");}}

1.3 注解说明

请参考我的这篇文章 Springboot 注解使用详解

二、测试

在这里插入图片描述
点击发送请求,第一次执行了sql,第二次在方法体中打断点,发现没有进入。且日志未输出相关查询数据库操作。

在这里插入图片描述

三、注解操作缓存原理以及一些难点排查

3.1 注解操作缓存原理

在这里插入图片描述

工作原理总结:

1. 代理模式:Spring 使用动态代理或 CGLIB 代理来拦截带有缓存注解的方法调用。代理会在方法调用之前或之后进行缓存操作。

开启注解缓存是靠 @EnableCaching 来实现的,那么我们从这个注解开始入手:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CachingConfigurationSelector.class)
public @interface EnableCaching {/*** Indicate whether subclass-based (CGLIB) proxies are to be created as opposed* to standard Java interface-based proxies. The default is {@code false}. <strong>* Applicable only if {@link #mode()} is set to {@link AdviceMode#PROXY}</strong>.* <p>Note that setting this attribute to {@code true} will affect <em>all</em>* Spring-managed beans requiring proxying, not just those marked with {@code @Cacheable}.* For example, other beans marked with Spring's {@code @Transactional} annotation will* be upgraded to subclass proxying at the same time. This approach has no negative* impact in practice unless one is explicitly expecting one type of proxy vs another,* for example, in tests.*/boolean proxyTargetClass() default false;/*** Indicate how caching advice should be applied.* <p><b>The default is {@link AdviceMode#PROXY}.</b>* Please note that proxy mode allows for interception of calls through the proxy* only. Local calls within the same class cannot get intercepted that way;* a caching annotation on such a method within a local call will be ignored* since Spring's interceptor does not even kick in for such a runtime scenario.* For a more advanced mode of interception, consider switching this to* {@link AdviceMode#ASPECTJ}.*/AdviceMode mode() default AdviceMode.PROXY;/*** Indicate the ordering of the execution of the caching advisor* when multiple advices are applied at a specific joinpoint.* <p>The default is {@link Ordered#LOWEST_PRECEDENCE}.*/int order() default Ordered.LOWEST_PRECEDENCE;}

@Import(CachingConfigurationSelector.class) 我们进入CachingConfigurationSelector 看下:

在这里插入图片描述
点击进入ProxyCachingConfiguration

@Bean(name = CacheManagementConfigUtils.CACHE_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryCacheOperationSourceAdvisor cacheAdvisor(CacheOperationSource cacheOperationSource, CacheInterceptor cacheInterceptor) {BeanFactoryCacheOperationSourceAdvisor advisor = new BeanFactoryCacheOperationSourceAdvisor();advisor.setCacheOperationSource(cacheOperationSource);advisor.setAdvice(cacheInterceptor);if (this.enableCaching != null) {advisor.setOrder(this.enableCaching.<Integer>getNumber("order"));}return advisor;
}@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheOperationSource cacheOperationSource() {// Accept protected @Cacheable etc methods on CGLIB proxies, as of 6.0.return new AnnotationCacheOperationSource(false);
}@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheInterceptor cacheInterceptor(CacheOperationSource cacheOperationSource) {CacheInterceptor interceptor = new CacheInterceptor();interceptor.configure(this.errorHandler, this.keyGenerator, this.cacheResolver, this.cacheManager);interceptor.setCacheOperationSource(cacheOperationSource);return interceptor;
}

我们可以看到动态代理注入了一个interceptor,我们这个时候就可以猜测,所有的缓存操作都是在这个interceptor里边进行操作的(不熟悉动态代理原理的可以先去看下)。

public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable {@Override@Nullablepublic Object invoke(final MethodInvocation invocation) throws Throwable {Method method = invocation.getMethod();CacheOperationInvoker aopAllianceInvoker = () -> {try {return invocation.proceed();}catch (Throwable ex) {throw new CacheOperationInvoker.ThrowableWrapper(ex);}};Object target = invocation.getThis();Assert.state(target != null, "Target must not be null");try {return execute(aopAllianceInvoker, target, method, invocation.getArguments());}catch (CacheOperationInvoker.ThrowableWrapper th) {throw th.getOriginal();}}
}

再点击进入 CacheAspectSupport 发现有个方法叫execute,礼拜呢有一个findCachedValue方法,这个就是查询缓存有没有命中,如果有命中直接返回缓存,如果没命中那么就会执行员原服务方法获取数据。

@Nullable
private Object execute(CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {if (contexts.isSynchronized()) {// Special handling of synchronized invocationreturn executeSynchronized(invoker, method, contexts);}// Process any early evictionsprocessCacheEvicts(contexts.get(CacheEvictOperation.class), true,CacheOperationExpressionEvaluator.NO_RESULT);// Check if we have a cached value matching the conditionsObject cacheHit = findCachedValue(invoker, method, contexts); // 查询缓存if (cacheHit == null || cacheHit instanceof Cache.ValueWrapper) { // 判断是否命中缓存return evaluate(cacheHit, invoker, method, contexts);}return cacheHit;
}

CacheAspectSupport.findCachedValue

@Nullable
private Object findCachedValue(CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {for (CacheOperationContext context : contexts.get(CacheableOperation.class)) {if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) {Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT);Object cached = findInCaches(context, key, invoker, method, contexts); // 查找缓存if (cached != null) {if (logger.isTraceEnabled()) {logger.trace("Cache entry for key '" + key + "' found in cache(s) " + context.getCacheNames());}return cached;}else {if (logger.isTraceEnabled()) {logger.trace("No cache entry for key '" + key + "' in cache(s) " + context.getCacheNames());}}}}return null;
}

CacheAspectSupport.findInCaches

@Nullable
private Object findInCaches(CacheOperationContext context, Object key,CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {for (Cache cache : context.getCaches()) {if (CompletableFuture.class.isAssignableFrom(context.getMethod().getReturnType())) {CompletableFuture<?> result = doRetrieve(cache, key);  // 重试策略if (result != null) {return result.exceptionally(ex -> {getErrorHandler().handleCacheGetError((RuntimeException) ex, cache, key);return null;}).thenCompose(value -> (CompletableFuture<?>) evaluate((value != null ? CompletableFuture.completedFuture(unwrapCacheValue(value)) : null),invoker, method, contexts));}else {continue;}}if (this.reactiveCachingHandler != null) {Object returnValue = this.reactiveCachingHandler.findInCaches(context, cache, key, invoker, method, contexts);if (returnValue != ReactiveCachingHandler.NOT_HANDLED) {return returnValue;}}Cache.ValueWrapper result = doGet(cache, key);if (result != null) {return result;}}return null;
}

CacheAspectSupport.doGet 可以看到最终拿的就是我们在cache manager 里边配置的cache

@Nullable
protected Cache.ValueWrapper doGet(Cache cache, Object key) {try {return cache.get(key); }catch (RuntimeException ex) {getErrorHandler().handleCacheGetError(ex, cache, key);return null;  // If the exception is handled, return a cache miss}
}

2. 缓存管理:缓存的存储和取用是通过 Spring 的缓存抽象来管理的。缓存的实现可以是简单的内存缓存,也可以是分布式缓存,如 Redis 等。
3. 缓存策略:开发者可以通过注解设置不同的缓存策略,例如缓存的键、值、过期时间、条件等。

这种基于注解的缓存方式极大地简化了缓存操作,让开发者专注于业务逻辑的实现,而缓存的管理由 Spring 自动处理。

3.2 难点排查

在做demo的时候发现配置也没错,也没有说是通过本文件的方法去调用提供缓存的方法(这样不走代理,无法执行命中缓存操作),后来发现是weakkey导致的。假如说内存不够的情况下,key就会被直接清楚掉,而我电脑可分配内存很少。可能会频繁触发GC,导致cache key被清除掉了。不清楚weakReference作用的同学可以去看下我写的另一篇文章:
WeakReference浅析

@Bean
public Caffeine<Object, Object> caffeineConfig() {return Caffeine.newBuilder().maximumSize(1000).expireAfterWrite(5, TimeUnit.MINUTES)
//                .weakKeys() // 很坑会,基本上很快就把key清理掉了,缓存再也命中不了.recordStats();
}

总结

散会

相关文章:

30分钟内搭建一个全能轻量级springboot 3.4 + 脚手架 <5> 5分钟集成好caffeine并使用注解操作缓存

快速导航 <1> 5分钟快速创建一个springboot web项目 <2> 5分钟集成好最新版本的开源swagger ui&#xff0c;并使用ui操作调用接口 <3> 5分钟集成好druid并使用druid自带监控工具监控sql请求 <4> 5分钟集成好mybatisplus并使用mybatisplus generator自…...

【设计模式-结构型】装饰器模式

一、什么是装饰器模式 装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它的核心思想是在不改变原有对象结构的情况下&#xff0c;动态地给对象增加一些功能&#xff0c;从而达到扩展功能的目的。举个例子&#xff0c;今天在家妈妈给蒸馒…...

分布式数据存储基础与HDFS操作实践(副本)

以下为作者本人撰写的报告&#xff0c;步骤略有繁琐&#xff0c;不建议作为参考内容&#xff0c;可以适当浏览&#xff0c;进一步理解。 一、实验目的 1、理解分布式文件系统的基本概念和工作原理。 2、掌握Hadoop分布式文件系统&#xff08;HDFS&#xff09;的基本操作。 …...

Linux 进程前篇(冯诺依曼体系结构和操作系统)

目录 一.冯诺依曼体系结构 1.概念 2.硬件层面的数据流 3.总结加补充 二.操作系统 (Operating System) 1.概念 2.设计OS的目的 3.定位 4.操作系统的管理 5.计算机体系的层状结构 在我们认识进程之前&#xff0c;我们先了解什么是冯诺依曼体系结构 一.冯诺依曼体系结构…...

Springboot Redisson 分布式锁、缓存、消息队列、布隆过滤器

redisson-spring-boot-starter 是 Redisson 提供的 Spring Boot 集成包&#xff0c;旨在简化与 Redis 的交互&#xff0c;包括分布式锁、缓存、消息队列、布隆过滤器等功能的实现。 Maven 依赖 在 Spring Boot 项目中添加 redisson-spring-boot-starter 依赖&#xff1a; <…...

【C语言】_字符串拷贝函数strcpy

目录 1. 函数声明及功能 2. 使用示例 3. 注意事项 4. 模拟实现 4.1 第一版&#xff1a;基本功能判空const修饰 4.2 第二版&#xff1a;优化对于\0的单独拷贝 4.3 第三版&#xff1a;仿strcpy的char*返回值 1. 函数声明及功能 char * strcpy ( char * destination, cons…...

基于 Vue 的拖拽缩放卡片组件:实现思路、方法及使用指南

引言 在前端开发中&#xff0c;实现可交互的组件能够极大地提升用户体验。本文将介绍一个基于 Vue 封装的可缩放卡片组件&#xff0c;从实现思路、代码具体实现以及使用方法等方面进行详细阐述&#xff0c;帮助开发者更好地理解和运用这一组件。项目源码地址&#xff1a;https…...

nginx 实现 正向代理、反向代理 、SSL(证书配置)、负载均衡 、虚拟域名 ,使用其他中间件监控

我们可以详细地配置 Nginx 来实现正向代理、反向代理、SSL、负载均衡和虚拟域名。同时&#xff0c;我会介绍如何使用一些中间件来监控 Nginx 的状态和性能。 1. 安装 Nginx 如果你还没有安装 Nginx&#xff0c;可以通过以下命令进行安装&#xff08;以 Ubuntu 为例&#xff0…...

Kafka客户端-“远程主机强迫关闭了一个现有的连接”故障排查及解决

Kafka客户端-“远程主机强迫关闭了一个现有的连接”故障排查及解决 1. 故障现象 Kafka客户端发送数据时&#xff0c;出现“远程主机强迫关闭了一个现有的连接”错误&#xff0c;导致数据发送失败。错误信息如下&#xff1a; 2. 故障排查 【1】. 查看服务网络状态 出现故障…...

Node.js - Express框架

1. 介绍 Express 是一个基于 Node.js 的 Web 应用程序框架&#xff0c;主要用于快速、简便地构建 Web 应用程序 和 API。它是目前最流行的 Node.js Web 框架之一&#xff0c;具有轻量级、灵活和功能丰富的特点。 核心概念包括路由&#xff0c;中间件&#xff0c;请求与响应&a…...

AWS Lambda

AWS Lambda 是 Amazon Web Services&#xff08;AWS&#xff09;提供的无服务器计算服务&#xff0c;它让开发者能够运行代码而不需要管理服务器或基础设施。AWS Lambda 会自动处理代码的执行、扩展和计费&#xff0c;开发者只需关注编写和部署代码&#xff0c;而无需担心底层硬…...

mysql 如何快速删除表数据

在数据库管理中, 经常会遇到需要删除大量数据的情况. 对于 MySQL 数据库而言, 如何高效快速地删除数据是一个值得深入探讨的问题. 本文将详细介绍几种在 MySQL 中快速删除数据的方法及相关注意事项. delete 语句 delete 语句可以删除符合条件的指定数据, 但是在删除大量数据…...

物联网网关Web服务器--lighttpd服务器部署与应用测试

以下是在国产ARM处理器E2000飞腾派开发板上部署 lighttpd 并进行 CGI 应用开发的步骤&#xff1a; 1、lighttpd简介 Lighttpd 是一款轻量级的开源 Web 服务器软件&#xff0c;具有以下特点和功能&#xff1a; 特点 轻量级&#xff1a;Lighttpd 在设计上注重轻量级和高效性&a…...

vmware虚拟机配置ubuntu 18.04(20.04)静态IP地址

VMware版本 &#xff1a;VMware Workstation 17 Pro ubuntu版本&#xff1a;ubuntu-18.04.4-desktop-amd64 主机环境 win11 1. 修改 VMware虚拟网络编辑器 打开vmware&#xff0c;点击顶部的“编辑"菜单&#xff0c;打开 ”虚拟化网络编辑器“ 。 选择更改设置&#…...

智能家居篇 一、Win10 VM虚拟机安装 Home Assistant 手把手教学

智能家居篇 一、Win10 VM虚拟机安装 Home Assistant 手把手教学 文章目录 [智能家居篇]( )一、Win10 VM虚拟机安装 Home Assistant 手把手教学 前言一.下载Vm版本的HomeAsistant安装包 二.打开Vmware选择新建虚拟机1.选择自定义高级2.选择16.x及以上3.选择稍后安装4.根据官网的…...

Flutter插件制作、本地/远程依赖及缓存机制深入剖析(原创-附源码)

Flutter插件在开发Flutter项目的过程中扮演着重要的角色&#xff0c;我们从 ​​​​​​https://pub.dev 上下载添加到项目中的第三方库都是以包或者插件的形式引入到代码中的&#xff0c;这些第三方工具极大的提高了开发效率。 深入的了解插件的制作、发布、工作原理和缓存机…...

Python猜数小游戏

Python 实现的《猜数游戏》 介绍 本文将展示如何使用 Python 编写一个简单的《猜数游戏》。这个游戏将会生成一个1到10之间的随机数&#xff0c;用户有最多三次机会来猜测正确的数字。如果用户猜对了&#xff0c;游戏将结束并显示恭喜信息&#xff1b;如果没有猜对&#xff0…...

--- 用java实现一个计时器 ---

这里的计时器值得是当线程设定的时间过了之后&#xff0c;自动执行该线程的工作 设计 MyTimer 既然是要在指定的时间之后执行任务&#xff0c;那么传入的参数就应该有run方法&#xff08;需要执行的任务&#xff09;&#xff0c;time&#xff08;在多少时间之后执行&#xff…...

OPI4A,目标检测,口罩检测,mnn,YoloX

记得之前&#xff0c;使用了bubbling导师复现的python版yolox&#xff0c;训练了自建的口罩数据集&#xff0c;得到了h5文件&#xff0c;又转换成pb文件&#xff0c;再使用阿里巴巴的MNN&#xff0c;使用它的MNNConvert&#xff0c;转换成mnn文件 最终实现了&#xff0c;在树莓…...

C#与Vue2上传下载Excel文件

1、上传文件流程&#xff1a;先上传文件&#xff0c;上传成功&#xff0c;返回文件名与url&#xff0c;然后再次发起请求保存文件名和url到数据库 前端Vue2代码&#xff1a; 使用element的el-upload组件&#xff0c;action值为后端接收文件接口&#xff0c;headers携带session信…...

Linux(Centos7)安装Mysql/Redis/MinIO

安装Mysql 安装Redis 搜索Redis最先版本所在的在线安装yum库 查看以上两个组件是否是开机自启 安装MinIO 开源的对象存储服务&#xff0c;存储非结构化数据&#xff0c;兼容亚马逊S3协议。 minio --help #查询命令帮助minio --server --help #查询--server帮助minio serve…...

港科夜闻 | 香港科大与微软亚洲研究院签署战略合作备忘录,推动医学健康教育及科研协作...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大与微软亚洲研究院签署战略合作备忘录&#xff0c;推动医学健康教育及科研协作。根据备忘录&#xff0c;双方将结合各自于科研领域的优势&#xff0c;携手推动医学健康领域的交流与合作。合作方向将涵盖人才培训、…...

森林网络部署,工业4G路由器实现林区组网远程监控

在广袤无垠的林区&#xff0c;每一片树叶的摇曳、每一丝空气的流动&#xff0c;都关乎着生态的平衡与安宁。林区监控正以强大的力量&#xff0c;为这片绿色家园筑起一道坚固的防线。 工业 4G 路由器作为林区监控组网的守护者&#xff0c;凭借着卓越的通讯性能&#xff0c;突破…...

ASP.NET Core - 配置系统之自定义配置提供程序

ASP.NET Core - 配置系统之自定义配置提供程序 4. 自定义配置提供程序IConfigurationSourceIConfigurationProvider 4. 自定义配置提供程序 在 .NET Core 配置系统中封装一个配置提供程序关键在于提供相应的 IconfigurationSource 实现和 IConfigurationProvider 接口实现&…...

npm、yarn、pnpm包安装器差异性对比

特性npmyarnpnpm发布年份2010 年发布2016 年发布2017 年发布安装速度较慢&#xff08;旧版本&#xff09;&#xff0c;但自 npm 5 后有所改善较快&#xff0c;尤其是在缓存方面极快&#xff0c;使用硬链接和全局缓存来提高速度包管理模式扁平化依赖&#xff0c;可能会发生重复依…...

正点原子repo放到自己的git服务器

atk-rk3568_android11 导出project-objects对应仓库 .repo/repo/repo list -n > project-object.txt将project-object.txt格式化&#xff0c;并通过gitolite.conf创建对应仓库 atk-rk3568_android11_repo atk-rk3568_android11/RKTools atk-rk3568_android11_repo atk-…...

[MySQL | 二、基本数据类型]

基本数据类型 一、数值类型举例表结构1. 整数类型zerofill属性 与 int(n) 中 n 的关系 2.bit类型3. 小数类型float类型decimal类型 二、字符串类型1. char2. varchar如何选择定长或变长字符串&#xff1f; 3. 日期时间类型(date datetime timestamp)4. enum枚举类型5. set多选类…...

工作记录小点

postman问题 postman 返回404 可以先看看这个模块是否集成到pom文件中 postman 返回200不调debug 请求参数Json有错误请求方式不对Get/Post debug报错连接失败 host文件没copy同事的 2.对应组件的不同服务白名单没添加导致的 host文件刷新 进入 C:\windows\system32\drivers\e…...

在PyCharm中使用Anaconda中的虚拟环境

1、在File菜单中找到Settings 2、Settings中搜索interpreter&#xff0c;找到Python Interpreter&#xff0c;再点击Add 3、选择第一个local interpreter 4、如图&#xff1a; 5、找到anaconda安装位置中的envs文件夹&#xff0c;在里面选择需要添加的python环境&#xff0c;如…...

ansible基础

ansible 1.概述 ansible是基于python语言开发&#xff0c;配置管理和部署应用的工具。批量的配置&#xff0c;部署&#xff0c;管理“上千台”主机 &#xff08;实际一次100台左右&#xff09;&#xff0c;ansible只要在一台主机上就可以对其他主机进行操作。 &#xff08;1&…...