springMVC
拦截器(Interceptor)和过滤器(Filter)的执行顺序和区别
拦截器是基于java的反射机制的,aop实现,可以在方法前后,而过滤器是基于函数回调,需要在web.xml中配置。
拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
拦截器可以多次被调用,还可以访问当前作用于的栈和对象,可以详细到每个方法,而过滤器器只能在请求的前后过滤
过滤器能够修改reques,而拦截器不行
Filter的执行顺序在Interceptor之前,具体的流程见下图
也就是
过滤器:能够拿到原始的http请求,但是拿不到你请求的控制器和请求控制器中的方法的信息
拦截器:可以拿到你请求的控制器和方法,拿不到请求方法的参数
Junit单元测试
Junit单元测试一、什么是单元测试?
在计算机编程中,单元测试(英语:Unit Testing)又称为模块测试, 是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。 程序单元是应用的最小可测试部件。简单来说,就是测试数据的稳定性是否达到程序的预期。
二、单元测试的重要性
谈到测试,我们为什么要对程序进行测试呢?测试会为程序带来什么好处呢?
首先,我们每个人都会犯错误。毕竟人嘛,没有完美的谁谁谁。在程序中犯错误就像生活中犯错一样,错误不是一天两天而形成的。当需要改的时候,也不是能花少的时间而改掉的。这里我谈到的程序中的错误,就是著名的Bug。
我们可能在不经意间写错,如果你到了最后阶段去检验项目成果时,发现会有错误,这时候我们很难找到Bug的源头在哪里。我们都知道,有可能一处出错会导致步步错的情况。
然而,测试就在我们的上述说法中,显得尤为重要。有了测试的概念,这时候当我们做完项目的一个小模块,我们先去测试一下这个小模块是否正确或达到预期,如果错误或者没有达到预期就需要反复修改,直到正确或达到预期。这里所说的也就是使用了单元测试。
当我们一块一块的做完并一块一块的测试 ...
spring核心知识点
说一下spring ioc的理解,原理和实现总ioc:控制反转。原来的对象是由使用者来控制的,有了spring,就直接把整个对象交给spring来帮我们管理。
DI:依赖注入。把对应的属性的值注入到具体的对象中,@autowired,populatebean完成属性值得注入
容器:存储对象,使用map结构存储,在spring中一般存在三级缓存,singletonOBjects存放文章的bean对象,在整个bean的生命周期中,从创建到使用到销毁都是由容器来管理的。
分IOC和DI举一个例子:有车,底盘,轮胎,在没有spring之前,我们相对这样的整体架构进行设计,一个常用的方法就是通过构造器注入,我们在创建一个底盘的时候,需要new一个轮子的对象,把这个对象的尺寸,材料设置好后,通过底盘的构造器放入底盘中。同样,我们在最终创建一个车的时候,需要先创建一个轮胎对象,在创建一个底盘对象,最后才能创建出我们想要的车的对象。然后spring就帮我解决了这样的而问题,你可以直接去创建一个车的对象,而具体的底盘和轮胎的对象注入,由spring自己来进行,你只需要在开始创建这样的bea ...
Spring注解驱动开发
Spring注解驱动开发转载博客:https://blog.csdn.net/weixin_48033662/article/details/120000961
Spring源码分析-1
Spring源码环境搭建下载gradleSpring版本用的Gradle(类似于maven但是比maven强大)进行执行和编译,所以需要下载gradle环境
https://gradle.org/releases/
本篇文章使用的6.82版本
https://downloads.gradle-dn.com/distributions/gradle-6.8.2-all.zip
配置环境变量下载完成后解压,就和配置java环境变量一样,配置系统环境变量
需要配置:GRADLE_HOME、PATH、GRADLE_USER_HOME
系统变量(s)中添加:
1GRADLE_HOME D:\Program Files (x86)\gradle-6.8.2
系统变量(s)中添加:
这里面的变量内容执行你想要存放gradle包的路径,我的是放到了d盘的一个文件夹下
1GRADLE_USER_HOME
系统变量(s)的path中添加:
1%GRADLE_HOME%/bin
配置下载加速
在gradle文件的init.d文件夹下添加init.gradle文件
内容为:
1234 ...
Spring源码分析-3
spring整体架构
基础接口Resource+ResourceLoader
Resource代表spring中的资源的高度抽象,spring中所有的加载最终都是由Resource来实现的,具体根据不同的需要实现不同的接口,可以来自于二进制文件,可以来自于网络、磁盘等等情况
通过Resource接口获取资源Resource接口的实现类有:
Resource接口继承了InputStreamSource 接口,InputStreamSource 接口中有一个方法:getInputStream(),所以汇总起来,Resource接口中共有以下方法:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475public class ResourceTest { /**使用ClassPathResource获取资源**/ @Test p ...
Spring源码分析-2
参考文章:https://blog.csdn.net/weixin_48033662/article/details/120000961
核心注解
注解
功能
@Bean
容器中注册组件
@Primary
同类组件如果有多个,标注主组件
@DependsOn
组件之间声明依赖关系
@Lazy
组件懒加载(最后使用的时候才创建)
@Scope
声明组件的作用范围(SCOPE_PROTOTYPE,SCOPE_SINGLETON)
@Configuration
声明这是一个配置类,替换以前配置文件
@Component
@Controller、@Service、@Repository
@Indexed
加速注解,所有标注了 @Indexed 的组件,直接会启动快速加载
@Order
数字越小优先级越高,越先工作
@ComponentScan
包扫描
@Conditional
条件注入
@Import
导入第三方jar包中的组件,或定制批量导入组件逻辑
@ImportResource
导入以前的xml配置文件,让其生效
@Profi ...
分布式id的生成方案
分布式id的生成方案ID是数据的唯一标识,传统的做法是利用UUID和数据库的自增ID,在互联网企业中,大部分公司使用的都是Mysql,并且因为需要事务支持,所以通常会使用Innodb存储引擎,UUID太长以及无序,所以并不适合在Innodb中来作为主键,自增ID比较合适,但是随着公司的业务发展,数据量将越来越大,需要对数据进行分表,而分表后,每个表中的数据都会按自己的节奏进行自增,很有可能出现ID冲突。这时就需要一个单独的机制来负责生成唯一ID,生成出来的ID也可以叫做分布式ID,或全局ID。下面来分析各个生成分布式ID的机制。
这篇文章并不会分析的特别详细,主要是做一些总结,以后再出一些详细某个方案的文章。
数据库自增ID第一种方案仍然还是基于数据库的自增ID,需要单独使用一个数据库实例,在这个实例中新建一个单独的表:
表结构如下:
12345678CREATE DATABASE `SEQID`;CREATE TABLE SEQID.SEQUENCE_ID ( id bigint(20) unsigned NOT NULL auto_increment, stub char( ...
无题
两军问题拜占庭将军问题
深究Spring中Bean的生命周期
深究Spring中Bean的生命周期前言这其实是一道面试题,是我在面试百度的时候被问到的,当时没有答出来(因为自己真的很菜),后来在网上寻找答案,看到也是一头雾水,直到看到了《Spring in action》这本书,书上有对Bean声明周期的大致解释,但是没有代码分析,所以就自己上网寻找资料,一定要把这个Bean生命周期弄明白!
网上大部分都是验证的Bean 在面试问的生命周期,其实查阅JDK还有一个完整的Bean生命周期,这同时也验证了书是具有片面性的,最fresh 的资料还是查阅原始JDK!!!
一、Bean 的完整生命周期在传统的Java应用中,bean的生命周期很简单,使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了。一旦bean不再被使用,则由Java自动进行垃圾回收。
相比之下,Spring管理Bean的生命周期就复杂多了,正确理解Bean 的生命周期非常重要,因为Spring对Bean的管理可扩展性非常强,下面展示了一个Bean的构造过程
Bean 的生命周期
如上图所示,Bean 的生命周期还是比较复杂的,下面来对上图每一个步骤做文 ...
分布式核心
微服务中核心问题解决方案分布式id,分布式锁,鉴权,事务等等
分布式id生成方案有哪些?UUID,数据库主键自增,Redis自增ID,雪花算法。
描述
优点
缺点
数据库主键自增
MySQL数据库设置主键且主键自动增长
1. INT和BIGINT类型占用空间较小;2. 主键自动增长,IO写入连续性好;3. 数字类型查询速度优于字符串
1. 并发性能不高,受限于数据库性能;2. 分库分表,需要改造,复杂;3. 自增:数据和数据量泄露
UUID
UUID是通用唯一标识码的缩写,其目的是让分布式系统中的所有元素都有唯一的辨识信息,而不需要通过中央控制器来指定唯一标识。
1. 降低全局节点的压力,使得主键生成速度更快;2. 生成的主键全局唯一;3. 跨服务器合并数据方便。
1. UUID占用16个字符,空间占用较多;2. 不是递增有序的数字,数据写入IO随机性很大,且索引效率下降(mysql的B+树索引机制)
号段模式
量获取多个ID并缓存在本地,集群中每个mysql使用不同的自增步长
1. 不依赖数据库,即使数据库挂了,还能坚持一段时间2.
1. 重启后,会 ...
zookeeper分布式锁
背景为了保证数据的一致性,在一些业务处理中都会选择加锁来保证数据的一致性。在单机模式下我们通常选择使用synchronized等这种JAVA提供好的jvm锁来实现,但是在集群和分布式情况下,这种jvm级别的锁式无法满足我们的需求,因为一个服务部署在多台服务器上,这些服务器上的jvm是无法通讯的,所以我们需要一种方案来解决分布式情况下数据一致性。
在互联网公司,基本上企业内部都会有自己的一套分布式锁开发框架
前言分布式锁一般有三种实现方式:
数据库乐观锁
基于redis实现分布式锁
基于zooKeeper实习哪分布式锁
本次讲着重介绍zooKeeper实现分布式锁,和与数据库和redis实习分布式锁的对比。
核心zookeeper的分布式锁主要是依据临时节点和事件监听机制来完成的
curator框架实现zookeeper分布式锁前提:需要搭建起zookeeper基础架构,并且使用gateway网关做负载均衡
12345<dependency> <groupId>org.apache.curator</groupId> <artif ...
分布式事务之seata
分布式事务之seata分布式事务基础事务概念事务指的就是一个操作单元,在这个操作单元中的所有操作最终要保持一致的行为,要么所有操作都被撤销。
事务可以看做是一次大的操作,它由不同的小操作组成,这些操作要么全部成功,要么全部失败。
例如
转账:包含转出和转入操作
网购:包含下单、扣减库存、支付操作
四个特性
原子性(Atomicity):操作这些指令时,要么全部执行成功,要么全部不执行。只要其中一个指令执行失败,所有的指令都执行失败,数据进行回滚,回到执行指令前的数据状态。要么全部执行,要么全部不执行
一致性(Consistency):事务的执行使数据从一个状态转换为另一个状态,数据库的完整性约束没有被破坏。能量守恒,总量不变
eg: 拿转账来说,假设用户A和用户B两者的钱加起来一共是2000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是2000,这就是事务的一致性。
隔离性(Isolation):隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。信 ...
redis核心问题
redis核心问题redis线程,高并发下的缓存穿透、击穿、血崩、缓存淘汰策略、持久化机制,redis的分布式锁
01.说一下在你项目中的redis的应用场景1,5大value类型 :根据我的redis课有场景的介绍
2,基本上就是缓存~!
3,为的是服务无状态,延申思考,看你的项目有哪些数据结构或对象,再单机里需要单机锁,在多机需要分布式锁,抽出来放入redis中;
4,无锁化
02.redis是单线程还是多线程1, 无论什么版本,工作线程就是一个
2, 6.x高版本出现了IO多线程
3,使用上来说,没有变化
4, [去学一下系统IO课],你要真正的理解面向IO模型编程的时候,有内核的事,从内核把数据搬运到程序里这是第一步,然后,搬运回来的数据做的计算是第二步,netty
5,单线程,满足redis的串行原子,只不过IO多线程后,把输入/输出放到更多的线程里去并行,好处如下: 1,执行时间短,更快; 2,更好的压榨系统及硬件的资源(网卡能够高效的使用);
*,客户端被读取的顺序不能被保障哪个顺序是可以被保障的: 在一个连接里,socket里
6.x以前
缓存不严谨,尽量去分 ...