ღゝ◡╹)ノ❤️

集中一点,登峰造极!

  menu
137 文章
0 浏览
2 当前访客
ღゝ◡╹)ノ❤️

框架

mybatis

Mybatis有二级缓存,为什么还用Redis

Mybaties得一级缓存作用域是session,commit就会失效。

二级缓存的作用域是sessionfactory,该缓存是以namespace为单位的。不同的namespace下的操作互不影响。

所有对数据表的改变操作都会刷新缓存。但是一般不要用二 级缓存,例如在UserMapper.xml有多数针对user表的操作。但是在另一个XXXMapper.xml中,还有针对user单表的操作。这会导致user在两个命名空间下的数据不一致。
如果在UserMapper.xml中做了刷新缓存的操作,在XXXMapper.xml中缓存仍然有效,如果有针对user的单表查询,使用缓存的结果可能会不正确,读到脏数据。
Redis 很好的解决了这个问题,而且此之一、二级缓存的好处很多 ,Redis 可以搭建在其他服务器上,缓存容可扩展。Redis 可以灵活的使用在需要缓存的数据上,比如一些热点数据,统计点赞啊

自动装配原理

@SpringBootApplication注解会引用开启自动配置的注解@EnableAutoConfiguration,@EnableAutoConfiguration注解import注解AutoConfigurationImportSelector类,这个类中有一个process方法扫描META-INF/spring.factories,然后过滤用到的配置类,然后将配置类加载到IOC容器。

SPI

SPI 全称为Service Provider Interface,是一种服务发现机制 。 SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。 这样可以在运行时,动态为接口替换实现类。 正因此特性,我们可以很容易的通过SPI 机制为我们的程序提供拓展功能。

如何设计一个良好的接口?

  1. 职责原则:明确该接口要做什么服务
  2. 单一性原则:在明确接口职责的情况下,尽量做到接口单一,即一个接口只做一件事。
  3. 设置路径规则
  4. http请求方式
  5. 域名
  6. 跨域请求
  7. 适度过滤信息,分页查询
  8. 设置返回的数据格式
  9. 安全性 接口的并发量,接口防攻击
  10. 可扩展性原则。
  11. 定义返回码

过滤器(filter)

过滤器处于客户端与Web资源(Servlet、JSP、HTML)之间,客户端与Web资源之间的请求和响应都要通过过滤器进行过滤。举例:在过滤器中定义了禁止访问192.10.10.1这个地址,那么当客户端发出访问192.10.10.1的请求时,经过过滤器后,客户端得到的响应是出现该IP禁止访问的提示。在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符

源码:tomcat对FilterChain的实现是ApplicationFilterChain,其中有一个局部变量filters,里面包含了项目创建的过滤器,然后,有个pos指针代表执行到哪个过滤器,然后开始执行第一个filter的dofiter,然后dofilter继续执行其他的过滤器,等到执行到最后一个fiter之后在执行servlet。

拦截器(interceptor)

拦截器是一种面向方面/切面编程(AOP Aspect-Oriented Programming),而面向切面就是将多个模块的通用服务进行分离,如权限管理、日志服务,他们在多个模块中都会用到,就可以将其各自封装为一个可重用模块。而这些通用服务的具体实现是通过拦截器来完成,比如用户客户端访问一些保密模块都应先通过权限审查的拦截器来进行权限审查,确定用户是否具有该项操作的权限后方能向下执行。在面向切面编程的就是在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法,比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。

拦截器与过滤器的区别

1、拦截器是基于java的反射机制的,而过滤器是基于函数回调(职责链)

2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器

3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用

4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能

5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

执行顺序 :过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。个人认为过滤是一个横向的过程,首先把客户端提交的内容进行过滤(例如未登录用户不能访问内部页面的处理);过滤通过后,拦截器将检查用户提交数据的验证,做一些前期的数据处理,接着把处理后的数据发给对应的Action;Action处理完成返回后,拦截器还可以做其他过程(还没想到要做啥),再向上返回到过滤器的后续操作。

使用Spring框架的好处是什么?

轻量:Spring 是轻量的,基本的版本大约2MB
控制反转:Spring通过控制反转实现了松散耦合,不使用Spring,如果需要获取对象,需要使用new关键字进行获取,使用Spring可以使用@Autowaird或者@Resouce进行获取,而且生成的对象默认是单例模式,避免了堆内存的浪费,也能帮我们自动注入对象所需的依赖,使我们不需要关心对象所需要的依赖。
面向切面的编程(AOP): Spring支 持面向切面的编程,可以把应用业务逻辑和配置服务分开,使用AOP可以用来进行日志收集,鉴权,参数和结果的处理。
容器: Spring 包含并管理应用中对象的生命周期和配置
MVC框架: Spring的WEB框架是个精心设计的框架,是Web框架的一个很好的替代品
事务管理: Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)
异常处理: Spring 提供方便的API把具体技术相关的异常(比如由JDBC, Hibernate or JDO抛出的)转化为一致的unchecked 异常。

IOC的优点

  • 降低耦合度,做某一个功能的时候尽量调用接口的方法,而不是调用具体的实现方法。这样在调用这个功能的时候可以指定不同的实现类。
  • 自动注入依赖,不用关心使用对象需要哪些依赖
  • 默认创建的是单例,可以节省内存。

区分BeanFactory和ApplicationContext?

BeanFactory:它使用懒加载 不支持国际化 不支持基于依赖的注解
ApplicationContext:它使用即时加载 它自己创建和管理资源对象 支持国际化 支持基于依赖的注解 它使用语法显式提供资源对象

BeanFactory和ApplicationContext的优缺点分析:

BeanFactory的优缺点:
优点:应用启动的时候占用资源很少,对资源要求较高的应用,比较有优势;

缺点:运行速度会相对来说慢一些。 而且有可能会出现空指针异常的错误,而且通过Bean工厂创建的Bean生命周期会简单一些。

ApplicationContext的优缺点:
优点:所有的Bean在启动的时候都进行了加载,系统运行的速度快;在系统启动的时候,可以发现系统中的配置问题。
缺点:把费时的操作放到系统启动中完成,所有的对象都可以预加载,缺点就是内存占用较大。

Spring中的bean的作用域有哪些?

singleton:唯一bean 实例,Spring 中的bean默认都是单例的。
prototype:每次请求都会创建一个新的 bean实例。
request:每一-次HTTP请求都会产生一 个新的bean,该bean仅在当前HTTP request内有效。
session:在一个HTTP Session中,一个Bean定义对应一一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。

Bean生命周期

image.png

主要把握创建过程和销毁过程这两个大的方面;
创建过程:首先实例化Bean,并设置Bean的属性,根据其实现的Aware接口(主要是BeanFactoryAware接口,BeanFactoryAware, ApplicationContextAware) 设置依赖信息,接下来调用BeanPostProcess的postProcessBeforelnitialization方法,完成initial前的自定义逻辑; afterPropertiesSet方法做- 些属性被设定后的自定义的事情;调用Bean自身定义的init方法,去做一些初始化相关的工作;然后再调用postProcessAfterlnitialization去做一 些bean初始化之后的自定义工作。这四个方法的调用有点类似AOP。
此时,Bean初始化完成,可以使用这个Bean了。
销毁过程:如果实现了DisposableBean的destroy方法,则调用它,如果实现了自定义的销毁
方法,则调用之。

Spring怎么解决循环依赖问题?

spring对循环依赖的处理有三种情况:
①构造器的循环依赖:这种依赖spring是处理不了的, 直接抛出
BeanCurrentlyInCreationException异常。
②单例模式下的setter循环依赖:通过“三级缓存处理循环依赖。
③非单例循环依赖:无法处理。

spring事务定义的传播规则

PROPAGATION_ REQUIRED: 支持当前事务,如果当前没有事务,就新建一个事务。 这是最常见的选择。
PROPAGATION_ SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_ MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_ REQUIRES_ NEW:新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_ NOT_ SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_ NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_ NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_ REQUIRED类似的操作。

SpringMVC工作原理?

image.png

流程说明(重要) :
1.客户端(浏览器)发送请求,直接请求到DispatcherServlet 。
2. DispatcherServlet根据请求信息调用HandlerMapping ,解析请求对应的Handler 。
3.解析到对应的Handler ( 也就是我们平常说的Controller 控制器)后,开始由HandlerAdapter适配器处理。
4. HandlerAdapter 会根据Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑。
5.处理器处理完业务后,会返回一个ModelAndView 对象,Model 是返回的数据对象,View是个逻辑上的View 。
6. ViewResolver 会根据逻辑View 查找实际的View
7. DispaterServlet把返回的Model 传给View (视图渲染) 。
8.把View 返回给请求者(浏览器)

为什么要用SpringBoot?

在使用Spring框架进行开发的过程中,需要配置很多Spring框架包的依赖,如spring-core、spring-bean、spring-context等 ,而这些配置通常都是重复添加的,而且需要做很多框架使用及环境参数的重复配置,如开启注解、配置日志等。Spring Boot致力于弱化这些不必要的操作,提供默认配置,当然这些默认配置是可以按需修改的,快速搭建、开发和运行Spring应用。

以下是使用SpringBoot的一些好处:

  • 自动配置,使用基于类路径和应用程序上下文的智能默认值,当然也可以根据需要重写它们以满足开发人员的需求。
  • 创建Spring Boot Starter项目时,可以选择选择需要的功能, Spring Boot将为你管理依赖关系。
  • SpringBoot项目可以打包成jar文件。 可以使用Java-jar命令从命令行将应用程序作为独立的Java应用程序运行。
  • 在开发web应用程序时,springboot会配置一 个嵌入式Tomcat服务器,以便它可以作为独立的应用程序运行。(Tomcat是默认的, 当然你也可以配置Jetty或Undertow)
  • SpringBoot包括许多有用的非功能特性(例如安全和健康检查)。

Spring Boot的核心注解是哪个?它主要由哪几个注解组成的?

启动类上面的注解是@SpringBootApplication,它也是Spring Boot的核心注解,主要组合包含了以下3个注解:
@SpringBootConfiguration:组合了@Configuration 注解,实现配置文件的功能。
@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude ={DataSourceAutoConfiguration.class })。
@ComponentScan: Spring组件扫描。

你如何理解Spring Boot中的Starters?

Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成Spring及其他技术,而不需要到处找示例代码和依赖包。如你想使用Spring JPA访问数据库,只要加入spring-boot-starter-data-jpa启动器依赖就能使用了。Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖。

Spring Boot Starter的工作原理是什么?

Spring Boot在启动的时候会干这几件事情:
Spring Boot在启动时会去依赖的Starter 包中寻找resources/ME TA-INF/spring.factories文件,然后根据文件中配置的Jar包去扫描项目所依赖的Jar包。根据spring.factories配置加载AutoConfigure类根据@Conditional注解的条件,进行自动配置并将Bean注入Spring Context
总结一下:其实就是Spring Boot在启动的时候,按照约定去读取Spring Boot Starter的配置信息,再根据配置信息对资源进行初始化,并注入到Spring容器中。这样Spring Boot启动完毕后,就已经准备好了一切资源,使用过程中直接注入对应Bean资源即可。

MyBatis是什么?

  • Mybatis是一 个半ORM (对象关系映射)框架,它内部封装了JDBC,加载驱动、创建连接、创建statement等 繁杂的过程,开发者开发时只需要关注如何编写SQL语句,可以严格控制sq执行性能,灵活度高。
  • 作为一个半ORM框架,MyBatis 可以使用XML或注解来配置和映射原生信息,将POJO映射成数据库中的记录,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。
  • 通过xml文件或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sq|的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sq到返回result的过程) 。
  • 由于MyBatis专注于SQL本身,灵活度高,所以比较适合对性能的要求很高,或者需求变
    化较多的项目,如互联网项目。

MyBatis编程步骤是什么样的?

1、创建SqlSessionFactory
2、通过SqlSessionFactory创建SqlSession
3、通过sq|session执行数据库操作
4、调用session.commit( )提交事务
5、调用session.close()关闭会话

#{}和${}的区别?

  • #{}是占位符,预编译处理; ${}是拼接符, 字符串替换,没有预编译处理。
  • Mybatis在处理#{}时, #{}传入参数是以字符串传入, 会将SQL中的#扑替换为?号,调用
    PreparedStatement的set方法来赋值。
  • Mybatis在处理时,是原值传入,就是把${}替换成变量的值,相当于JDBC中的Statement编译
  • 变量替换后,#(}对应的变量自动加上单引号“;变量替换后,${} 对应的变量不会加上单
    引号”$
  • #{}可以有效的防止SQL注入,提高系统安全性;
  • #{}的变量替换是在DBMS中;#{}的变量替换是在DBMS中; ${} 的变量替换是在DBMS外。

SpringBoot启动流程

1,创建一个ApplicationContext实例,即IOC容器

2,将主类(被注解@SpringBootApplication修饰的类)注册到IOC容器中。

3,递归加载并处理所有的配置类。

4,实例化所有的单例Bean

5,启动web服务器

加载配置类的方式

  • @ComponetScan

image.png

  • @Import

image.png

MQ对比

image.png

RabbitMq怎么保证可靠性

生产者->MQ

使用发送方确认机制 。也就是MQ再接受成功之后会调用消费者的confim方法,如果消息一直没被接受,可以重新发送。

exchange->Queue

retun方法类似confim

Queue->消费者

死信队列,ack机制

也可以在生产者发送数据的时候插入一条数据,当消费者成功消费的时候将数据修改成完成状态,然后再定时扫描失败的数据重新发送。

如何保证幂等性?

如果是查询不用管,修改可以根据id修改,实在不行可以先在Redis中插入一条数据,然后消费成功可以删除。

如何解决消费挤压问题

增加消费端的数量,服务降级。


标题:框架
作者:哇哇哇哇
地址:https://wuxiangshi.vip/articles/2022/02/18/1645169635165.html