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

Java技术整理(5)—— Spring篇

Spring是一个全面的全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是 Spring 仍然可以和其他的框架无缝整合。

1、Spring的核心组件

(1)数据层: JDBC、ORM、OXM、JMS、Transations
(2)Web层: Web、Servlet、Portlet、Struts
(3)中间层: AOP、Aspects、Instrumentation
(4)核心容器: Beans、Core、Context、Expression Language
(5)测试层: Test

2、Spring IOC 原理

(1)概念: Spring通过一个配置文件描述Bean及Bean之间的依赖关系,利用Java语言的反射功能实例化 Bean并建立Bean之间的依赖关系。Spring的IOC容器在完成这些底层工作的基础上,还提供 了 Bean实例缓存、生命周期管理、Bean实例代理、事件发布、资源装载等高级服务。

(2)Spring容器高层视图

  • Spring启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的Bean配置注册表
  • 根据这张注册表实例化Bean,并将Bean实例存入Bean缓存池
  • 应用程序读取Bean缓存池中的Bean实例

(3)IOC容器实现

IOC容器依赖于BeanFactory,是Spring框架的基础程序,所以开发者操作的是ApplicationContext而非底层的BeanFactory。

Bean注册表

首先,Spring配置文件中的每一个节点元素在Spring容器中都通过一个 BeanDefinition 对象表示,它表述了 Bean 的配置信息,而BeanDefinitionRegistry 接口提供了向容器手动注册 BeanDefinition 对象的方法。

获取Bean实例对象

BeanFactory 提供的最主要方法就是getBean(String beanName)方法,调用该方法能从容器中返回一个特定名称的Bean。

访问容器中关于Bean的基本信息——ListableBeanFactory

BeanFactory 的子类 ListableBeanFactory,提供了访问容器内关于Bean 的基本信息,如Bean的个数,获取某一类型Bean的配置名、查看容器中是否包含某一Bean等方法。

父子级容器——HierarchicalBeanFactory

父子级联IOC容器实现的接口是HierarchicalBeanFactory,子容器可以通过接口方法访问父容器,由此建立的IOC级联容器体系中,子容器可以访问父容器,而父容器无法访问子容器。

Spring利用父子级联容器实现了很多功能,例如 SpringMVC中,View层的Bean位于一个子容器中,而Service层和Dao层的Bean位于父容器中,这样View层的Bean就可以引用Service层和Dao层的Bean了

拓展接口 —— ConfigurableBeanFactory

这是一个BeanFactory子类系列十分重要的接口,它增强了IOC的可定制性,它定义了设置类加载器、属性编辑器、容器初始化后置处理器等方法

自动装配——AutowireCapableBeanFactory

这个接口定义了容器中的Bean按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法。

注册单例Bean——SingletonBeanRegistry

这个接口定义了允许在运行期间向容器注册单例Bean的方法。

对于单例Bean对象来说,BeanFactory会缓存Bean实例,所以第二次调用getBean()获取Bean对象时会直接从IOC容器的缓存中获取Bean实例。

Spring 在 DefaultSingletenBeanFactory 类中提供了用于缓存单例Bean 缓存器,这个缓存器使用HashMap实现,单例Bena以beanName作为key进行存储。

BeanFactory依赖日志框架

在初始化 BeanFactory 时,必须提供一种日志框架,例如使用Log4j,这样启动Spring容器时才不会报错。

BeanFactory提供给开发者的操作类——ApplicationContext

ApplicationContext 继承于 HierarchicalBeanFactory 和 ListableBeanFactory 接口,并由此拓展出其它功能接口:

  • ClassPathXmlApplicationContext: 默认从类路径加载配置文件
  • FileSystemXmlApplicationContext: 默认从文件系统中装载配置文件
  • ApplicationEventPublisher: 让容器拥有发布应用上下文事件的功能,包括启动容器事件、关闭容器事件等
  • MessageSource: 为应用提供 il8n 国际化消息访问的功能
  • ResourcePatternResolver: 通过带前缀的Ant风格的资源文件路径装载Spring配置条件
  • LifeCycle: 这个接口是Spring 2.0 时加入的,提供了start 和 stop 方法,主要用来控制异步处理过程,在具体使用中,该接口会被ApplicaitonContext和Bean实例同时实现,ApplicationContext 会将 start 和 stop 状态发布给所有实现了接口的Bean,以达到管理和控制JMX、任务调度的目的
  • ConfigurableApplicationContext: 扩展了ApplicationContext,主要是新增了两个方法:refresh() 和 close(),让ApplicationContext拥有了启动、刷新、关闭应用上下文的功能。

WebApplicationContext

WebApplicationContext是专门为Web应用准备的,它允许从相对于Web根目录的路径中装载配置文件完成初始化工作,从WebApplicationContext中可以获得ServletContext的引用,整个Web应用上下文对象将作为属性放置到ServletContext 中,以便Web应用环境可以访问Spring应用上下文。

(4)Spring Bean的作用域

Spring 3.0 定义了五种Bean的作用域:单例、原型、请求、会话、全局会话

  • singleton(单例模式,多线程不安全): Spring IOC容器只存在一个共享的 Bean 实例,无论有多少个 Bean 引用它,始终指向同一个对象,但这种模式在多线程环境下是不安全的。
  • prototype(原型模式): Spring 每一次尝试获取原型模式的Bean对象时,容器都将创建一个新的Bean提供给Spring。
  • request(请求模式): 一次HTTP请求,Spring创建一次新的Bean提供使用,其生命周期随请求状态的销毁而销毁。
  • session(会话模式): 一次Http Session 中,容器返回的是同一个实例,当重新开启一次Http Session,容器会重新创建一个Bean实例提供使用,请求结束,实例销毁。
  • global session(全局会话模式): 在一个全局Http Session中,容器返回同一个Bean实例,仅在protlet context时使用。

(5)Spring Bean的生命周期

SpringBean的生命周期:实例化 —— 属性赋值 —— 初始化 —— 销毁

实例化: 实例化一个Bean,也就是我们常说的new

属性赋值

  • IOC 依赖注入: 按照Spring Context对Bean实例进行配置
  • setBeanName的实现: 若Bean实现了BeanNameAware接口,调用setBeanName(String beanId)方法
  • setBeanFactory的实现: 若Bean实现了BeanFactoryAware接口,调用setBeanFactory(BeanFacrtory beanFactory)方法
  • setApplicationContext的实现: 若Bean实现了ApplicationContextAware接口,调用setApplicationContext(ApplicationContext applicationContext)方法,可以实现设置BeanFactory方法,并比BeanFactoryAware更加优秀
  • postProcessBeforelnitialization的实现: 若Bean实现了BeanPostProcessor接口,将调用postProcessBeforelnitialization(Object obj, String s)方法,BeanPostProcessor经常用于Bean内容的修改,并且Bean初始化结束后也会调用这个方法,也可以应用于内存或缓存技术。

初始化

  • init-method: 若Bean在配置文件中定义了初始化方法,则在初始化阶段会自动调用配置的初始化方法。
  • postProcessAfterInitialization的实现: 若Bean实现了BeanPostProcessor接口,调用postProcessAfterInitialization(Object obj, String s)方法。

销毁

  • destroy 过期自动清理阶段: 当Bean不再需要时,会经历清理阶段,若 Bean 实现了 DisposableBean 接口,则调用destroy()方法进行销毁。
  • destroy-method 自配置清理: 若Bean的配置文件中设置了destroy方法时,则自动调用自定义的destroy方法

(6)Spring 依赖注入的方式

Spring 提供的依赖注入的方式:构造器注入、set方法注入、静态工厂注入、实例工厂注入

构造器注入案例

public CatDaoImpl(String message){this.message = message;
}<bean id="CatDaoImpl" class="class.CatDaoImpl"><constructor-arg value="message"></constructor-arg>
</bean>

setter方法注入

public class Id{private int id;public int getId(){return id;}public void setId(int id){this.id = id;}
}<bean id="id" class="com.Id"><property name="id" value="123"></property>
</bean>

静态工厂注入

// 对外提供的静态工厂
public class DaoFactory{public static final FactoryDao getStaticFactoryDaoImpl(){return new StaticFactoryDaoImpl;}	
}//使用静态工厂的类
public class SpringAction{//注入对象private DaoFactory staticFactoryDao;//注入对象的set方法public void setStaticFactoryDao(FactoryDao staticFactoryDao){this.staticFactoryDao = staticFactoryDao;}
}//给调用类注入静态工厂
<bean name="springAction" class="com.SpringAction"><property name="staticFactoryDao" ref="staticFatoryDao"></property>
</bean>//给静态工厂中的成员注入
<bean name="staticFatoryDao" class="com.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>

实例工厂注入

//创建一个实例工厂
public class DaoFactory{public DaoFactory getFactoryDaoImpl(){return new FactoryDaoImpl();	}
}//调用类使用实例工厂
public class SpringAction{private DaoFactory daoFactory;public void setDaoFactory(DaoFactory daoFactory){this.daoFactory = daoFactory;}
}//为调用类注入实例工厂Bean对象
<bean name="springAction" class="SpringAction"><property name="daoFactory" ref="daoFactory"></property>
</bean>//管理实例工厂,先声明注入的类,再配置实例工厂的成员
<bean name="daoFactory" class="com.DaoFactory"></bean>
<bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>

(7)自动装配的实现方式

Spring装配包括手动装配和自动装配,手动装配是基于 xml 装配、构造方法、setter方法等。

自动装配一共有5种实现方式:

  • no: 默认不自动装配,通过显式的 ref 属性进行装配
  • byName: 通过参数名自动装配,Spring在配置文件中检测到Autowired属性被设置为byName,容器自动按照beanName进行注入
  • byType: 通过参数类型自动装配,Spring在配置文件中检测到Autowired属性被设置为byType,容器自动按照type进行注入,若有多个匹配对象,则抛出错误
  • constructor: 类似于byType,但必须提供构造器参数,若没有确定参数的构造器参数类型,则抛出异常
  • autodetect: 首先尝试使用 构造器参数 装配,若无法工作则使用byType方式

3、Spring AOP 的原理

(1)概念: AOP是一种“横切”技术,将多个类的公共模块抽取到一个模块中,并将其命名为**“Aspect”**,即切面。
(2)AOP的两个部分: 核心关注点、横切关注点

  • 核心关注点: 业务处理的主要流程
  • 横切关注点: 一切与业务代码无相关的代码

(3)AOP的应用场景:

  • Authentication: 权限
  • Caching: 缓存
  • Context passing: 内容传递
  • Error handling: 错误处理
  • Lazy loading: 懒加载
  • Debugging: 调试
  • logging, tracing, profiling and monitoring: 记录跟踪 优化 校准
  • Performance optimization: 性能优化
  • Persistence: 持久化
  • Resource pooling: 资源池
  • Synchronization: 同步
  • Transactions: 事务

(4)AOP的核心概念:

  • 切面(Aspect): 类是对物体特征的抽象,切面是对横切关注点的抽象
  • 横切关注点: 对哪些对象进行拦截、如何处理,这些关注点都是横切关注点
  • 连接点(JoinPoint): 被拦截到的点,因为Spirng只支持方法类型的连接点,所以Spirng中连接点就是被拦截方法,实际上连接点还可以是字段、构造方法
  • 切入点(PointCut): 对连接点进行拦截的定义
  • 通知(Advice): 所谓的通知就是拦截到连接点后要执行的代码,分为前置、后置、异常、最终、环绕通知等类型
  • 目标对象: 代理的目标对象
  • 织入(weave): 将切面应用到目标对象并导致代理对象创建的过程
  • 引入(introduction): 不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

(5)AOP的代理方式

Spring 提供了两种AOP的代理方式:JDK接口动态代理、CGLib动态代理

JDK接口动态代理:

  • 被代理类实现InvocationHandler,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态地将横切逻辑和业务逻辑编织在一起
  • 代理类通过InvocationHandler接口动态创建一个实例,生成目标类的代理对象

GCLib动态代理:

GCLib的全称是Code Generation Library,是一个高性能、高质量的代码生成类库,可以在运行期间动态扩展Java类和实现Java接口,CGLib封装了ASM,可以在运行期间生成新的class,对比JDK动态代理,CGLib可以动态代理未实现接口的类。

(6)AOP的实现原理

@Aspect
public class TransactionDemo {@Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))") public void point(){}@Before(value="point()")public void before(){System.out.println("transaction begin");}@AfterReturning(value = "point()")public void after(){System.out.println("transaction commit");}@Around("point()")public void around(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("transaction begin");joinPoint.proceed();System.out.println("transaction commit");}
}

4、Spring MVC 的原理

MVC指的是Modal(模型),View(视图),Controller(控制器),Spring MVC框架是围绕 DispatcherServlet 而设计的,这个Servlet会将请求分发到各个控制器,并支持可配置的处理器映射、视图渲染、本地化、时区与主题渲染等,甚至还能支持文件上传。

(1)浏览器请求的全过程:

  • 浏览器发送HTTP请求,DispatcherServlet接收
  • DispatcherServlet轮询处理器,通过HandlerMapping进行查找适用的Controller
  • 当HandlerMapping查找到处理器后,DispatcherServlet调用处理器,将请求发送给Controller
  • Controller调用Service层业务逻辑,获取返回值后分发到ModalAndView对象
  • DispatcherServlet监听ModalAndView响应结果
  • DispatcherServlet得到结果后分发给Model对象,并轮询视图映射ViewResolver,查找到指定的视图
  • Modal将结果反应到视图,View向浏览器发送响应体

(2)MVC常用注解

组件注解: @Controller、@RestController、@Component、@Repository、@Service
请求注解: @RequestMapping、@Autowired、@PathVariable、@RequestParam、@RequestHeader


5、MyBatis缓存

MyBatis拥有两级缓存,默认情况下开启一级缓存,二级缓存由开发者手动开启。

一级缓存是会话级别的缓存,当同一会话调用同一个SQL时,优先从缓存中读取数据。
二级缓存是映射级别的缓存,不同的SQL会话可以共享该缓存

(1)一级缓存的原理

当用户线程第一次发出查询sql,sql的查询结果会写入到sqlSession的一级缓存中,缓存使用的是Map结构,其中key = mapperID + offset + limit + SQL + 所有入参,value = 用户信息,当同一个sqlSession再次发出同一个sql请求,就从缓存中取出数据,若两次查询中间发生更新操作,则本sqlSession中的一级缓存区域全部清空,所以第二次请求会从数据库中查询,并写入到新的缓存中去。

(2)二级缓存的原理

二级缓存的范围是mapper同命名空间的mapper,mapper以命名空间为单位创建缓存数据结构,结构是 map,通过 CacheExecutor 实现的。

CacheExecutor是Executor的代理对象,所有的查询操作,在CacheExecutor都会先查询缓存,再查询数据库。

(3)如何配置二级缓存

  • MyBatis 全局配置中启用二级缓存配置
  • 对应的mapper配置cache节点
  • 对应的select查询节点添加useCache=true

相关文章:

Java技术整理(5)—— Spring篇

Spring是一个全面的全面的、企业应用开发一站式的解决方案&#xff0c;贯穿表现层、业务层、持久层。但是 Spring 仍然可以和其他的框架无缝整合。 1、Spring的核心组件 &#xff08;1&#xff09;数据层&#xff1a; JDBC、ORM、OXM、JMS、Transations &#xff08;2&#x…...

07-MySQL-基础篇-函数

函数之字符串函数 前言函数字符串函数数值函数日期函数流程函数 前言 本篇来学习下MySQL中的函数–字符串函数。 函数 函数&#xff1a;是指一段可以直接被另一段程序调用的程序或代码MySQL中的函数主要分为以下四类&#xff1a; 字符串函数、数值函数、日期函数、流程函数。…...

不同路径 II——力扣63

class Solution {public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int n=...

NLP文本分类

NLP文本分类 落地实战五大利器&#xff01;_kaiyuan_sjtu的博客-CSDN博客https://zhuanlan.zhihu.com/p/432619164 https://github.com/alibaba/EasyNLP/blob/master/README.cn.md...

进程和线程的联系与区别

文章目录 一、进程和线程的联系二、进程和线程的区别 一、进程和线程的联系 操作系统中可以有很多进程&#xff0c;每个进程都有自己独立的资源&#xff1b;一个进程中可以有很多线程&#xff0c;系统中的每个线程都能独立调度&#xff0c;同一个进程中的各个线程共享内存/硬盘…...

分支和循环语句(2)(C语言)

目录 do...while()循环 do语句的语法 do语句的特点 do while循环中的break和continue 练习 goto语句 do...while()循环 do语句的语法 do 循环语句; while(表达式); do语句的特点 循环至少执行一次&#xff0c;使用的场景有限&#xff0c;所以不是经常使用。 #inc…...

Flutter: A RenderFlex overflowed by 42 pixels on the bottom.

Flutter&#xff1a;渲染活动底部上方溢出了42个像素 Flutter 控件超出异常&#xff1a;A RenderFlex overflowed by 42 pixels on the bottom. 解决方案 1.Scaffold内添加 resizeToAvoidBottomInset 属性&#xff0c;缺点是软键盘下面的控件被挡住 Scaffold( resizeToAvoidBot…...

第三章,矩阵,07-用初等变换求逆矩阵、矩阵的LU分解

第三章&#xff0c;矩阵&#xff0c;07-用初等变换求逆矩阵、矩阵的LU分解 一个基本的方法求 A − 1 B A^{-1}B A−1BLU分解例1&#xff0c;求矩阵A的LU分解&#xff1a;例12&#xff0c;LU分解解线性方程组&#xff1a; 玩转线性代数(19)初等矩阵与初等变换的相关应用的笔记&a…...

STM32F429IGT6使用CubeMX配置SPI通信(W25Q256芯片)

1、硬件电路 需要系统性的看一下W25Q256芯片手册 2、设置RCC&#xff0c;选择高速外部时钟HSE,时钟设置为180MHz 3、配置SPI 4、生成工程配置 5、相关代码 #define sFLASH_ID 0XEF4019 // W25Q256#define SPI_FLASH_PageSize 256 #define SPI_FLASH_PerWritePageSize 256#def…...

C++11异步与通信之 packaged_task

概念简介 packaged_task 用于包装可调用目标(Callable)为一个对象,如lambda&#xff0c;普通函数&#xff0c;小括号重载等&#xff0c;用于异步调用。 其返回值或所抛异常被存储于能通过 std::future 对象访问的共享状态中&#xff0c;和promise类似。 将函数的调用与函数返…...

磁盘的管理

一、磁盘的分区 查看磁盘 lsblk fdisk -l 2、分区 没有e扩展&#xff0c;则都是主分区&#xff0c;已经有三个主分区了&#xff0c;剩下的全设置为扩展 查看分区结果&#xff1a; 二、格式化 三、挂载...

数据结构:完全二叉树的性质

完全二叉树的性质&#xff1a; 具有 n n n个结点的完全二叉树的深度为 [ l o g 2 n ] 1 ( [ x ] 表示不大于 x 的最大整数 ) [log_2n]1([x]表示不大于x的最大整数) [log2​n]1([x]表示不大于x的最大整数) 对于任意一个结点 &#xff08; 1 < i < n &#xff09; &…...

【数据结构】‘双向链表’冲冲冲

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …...

Linux 编译CEF源码详细记录

Linux CEF&#xff08;Chromium Embedded Framework&#xff09;源码下载编译 背景 由于CEF默认的二进制分发包不支持音视频播放&#xff0c;需要自行编译源码&#xff0c;将ffmpeg开关打开才能支持。这里介绍的是Linux平台下的CEF源码下载编译过程。 Windows平台参考&#…...

LeetCode 2810. Faulty Keyboard【模拟,双端队列,字符串】简单

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

两个数组的交集-C语言/Java

描述 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序。&#xff08;1 < nums1.length, nums2.length < 1000&#xff0c;0 < nums1[i], nums2[i] < 1000&#xff09; 示例1 输入…...

Arduino+esp32学习笔记

学习目标&#xff1a; 使用Arduino配置好蓝牙或者wifi模块 学习使用python配置好蓝牙或者wifi模块 学习内容&#xff08;笔记&#xff09;&#xff1a; 一、 Arduino语法基础 Arduino语法是基于C的语法,C又是c基础上增加了面向对象思想等进阶语言。那就只记录没见过的。 单多…...

计算机网络-专业术语

计算机网络-专业术语 实体 实体:任何可发送或接收信息的硬件或软件进程 对等实体:收发双方相同层次中的实体 协议 控制两个对等实体进行逻辑通信的规则的集合 协议三要素 语法 定义所交换的信息的格式 是用户数据与控制信息的结构和格式 语义 定义收发双方所需要完成的操作…...

E. Maximum Monogonosity

You are given an array aa of length nn and an array bb of length nn. The cost of a segment [l,r][l,r], 1≤l≤r≤n1≤l≤r≤n, is defined as |bl−ar||br−al||bl−ar||br−al|. Recall that two segments [l1,r1][l1,r1], 1≤l1≤r1≤n1≤l1≤r1≤n, and [l2,r2][l2,…...

已解决Excel file format cannot be determined, you must specify an engine manually

问题 我使用以下语句时出现错误 data pd.read_excel(temp_inputc.csv, headerNone)出现错误&#xff1a; Excel file format cannot be determined, you must specify an engine manually有很多人说添加engine&#xff0c;但接下来会出现这个错误&#xff1a; File is not…...

抖音无水印下载神器:3分钟掌握批量下载技巧,轻松保存高清视频素材

抖音无水印下载神器&#xff1a;3分钟掌握批量下载技巧&#xff0c;轻松保存高清视频素材 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and …...

RAG基本流程

RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09;是一种将外部知识检索与大语言模型&#xff08;LLM&#xff09;生成能力相结合的技术&#xff0c;用于提升回答的准确性、减少“幻觉”&#xff08;Hallucination&#xff09;&#xff0c;并…...

终极指南:用Ryujinx在PC上免费畅玩Switch游戏的完整教程

终极指南&#xff1a;用Ryujinx在PC上免费畅玩Switch游戏的完整教程 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx 想在电脑上体验《塞尔达传说&#xff1a;旷野之息》的广阔世界&…...

Windows 系统 Miniconda的安装和使用

&#x1f4e5; 第一步&#xff1a;下载与安装首先&#xff0c;从官网下载安装程序&#xff0c;然后按以下步骤操作。1. 下载安装程序访问 Miniconda 官方下载页面。选择 Windows 64-bit 版本的安装程序&#xff08;文件名类似 Miniconda3-latest-Windows-x86_64.exe&#xff09…...

Postman接口测试黑马点评项目:手把手教你搞定登录鉴权与Stream订单流

Postman接口测试黑马点评项目&#xff1a;手把手教你搞定登录鉴权与Stream订单流 在当今互联网应用中&#xff0c;接口测试已成为保障系统稳定性的关键环节。黑马点评&#xff08;hm-dianping&#xff09;作为一款基于Redis的实战项目&#xff0c;其独特的JWT鉴权机制和Redis S…...

100个小工具挑战 #002 | 做了个能直接编辑树形视图的 JSON 格式化工具

起因 今年给自己定了个目标&#xff1a;做 100 个小工具页面。 不是为了流量&#xff0c;就是想把平时开发中遇到的痛点一个个解决掉。这是第 2 个。 第 1 个是发票批量识别工具&#xff0c;这次做的是 JSON 格式化。 为什么要自己做&#xff0c;不用现成的&#xff1f; 用…...

Python实战:不用NumPy也能搞定高斯拟合?手写算法全解析

Python实战&#xff1a;不用NumPy也能搞定高斯拟合&#xff1f;手写算法全解析 高斯分布&#xff08;正态分布&#xff09;在数据分析和信号处理中无处不在&#xff0c;但大多数教程都直接调用NumPy或SciPy的现成函数。今天我们要做点不一样的——仅用Python标准库和基础数学知…...

告别system_profiler:在Mac终端里用neofetch一键获取清晰美观的硬件信息

告别system_profiler&#xff1a;在Mac终端里用neofetch一键获取清晰美观的硬件信息 每次打开Mac终端输入system_profiler&#xff0c;面对瀑布般倾泻而下的纯文本信息&#xff0c;你是否也感到一阵眩晕&#xff1f;作为开发者或运维人员&#xff0c;我们经常需要快速获取系统配…...

Vue2项目里集成AntV X6画布,我踩过的这些坑你千万别再踩了

Vue2项目集成AntV X6的实战避坑指南 去年接手一个流程图编辑器需求时&#xff0c;我毫不犹豫选择了AntV X6——这个阿里系出品的专业级图编辑引擎。但在Vue2项目中的实际集成过程&#xff0c;远比官方文档展示的Demo复杂得多。从画布缩放与页面布局的冲突&#xff0c;到右键菜单…...

C语言编程实战:从入门到精通的50道经典大题解析

1. C语言编程实战入门指南 刚接触C语言时&#xff0c;很多初学者会被指针、内存管理等概念吓到。其实C语言就像搭积木&#xff0c;掌握基础语法后就能构建复杂程序。我们先从最简单的"Hello World"开始&#xff1a; #include <stdio.h> int main() {printf(&qu…...