spring、springBoot、mybatis

目录

spring

FactoryBean 和 BeanFactory有什么区别?

BeanFactory 是 Bean 的工厂, ApplicationContext 的父类,IOC 容器的核心,负责生产和管理 Bean 对象

FactoryBean 是 Bean,可以通过实现 FactoryBean 接口定制实例化 Bean 的逻辑,通过代理一个Bean对象,对方法前后做一些操作。

什么是IOC(控制反转)

浅谈IOC

软件系统在没有引入IOC容器之前,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B。控制权都在自己手上。

软件系统在引入IOC容器之后,这种情形就完全改变了,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。

IOC容器相当于第三方,让每一个对象之间没有了耦合关系,每个对象的工作全部依靠“第三方”了,全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合在一起发挥作用。

软件系统在没有引入IOC容器之前,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。
在这里插入图片描述

软件系统在引入IOC容器之后,这种情形就完全改变了,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。
在这里插入图片描述

当去掉IOC容器的时候,对象之间已经没有了耦合关系,彼此毫无联系,这样的话,当你在实现A的时候,根本无须再去考虑B、C和D了,对象之间的依赖关系已经降低到了最低程度。
在这里插入图片描述

对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。

既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”

答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。

缺点:

  • 第一、软件系统中由于引入了第三方IOC容器,生成对象的步骤变得有些复杂,本来是两者之间的事情,又凭空多出一道手续
  • 由于IOC容器生成对象是通过反射方式,在运行效率上有一定的损耗。如果你要追求运行效率的话,就必须对此进行权衡。

所谓依赖注入(Dependency Injection),即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。

AOP

面向切面编程,将系统按照功能分类,每一个类别就是一个“切面”

所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。

AOP(Aspect-Oriented Programming),一般称为面向切面编程,作为面向对象的一种补充用于将那些与业务无关,但却对多个对象产生影响的公共行为抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理等。

Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接口,那么Spring AOP会使用JDK Proxy,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候Spring AOP会使用Cglib生成一个被代理对象的子类来作为代理,如下图所示:
在这里插入图片描述
使用 AOP 之后我们可以把一些通用功能抽象出来,在需要用到的地方直接使用即可,这样大大简化了代码量。我们需要增加新功能时也方便,这样也提高了系统扩展性。日志功能==、事务管理等等场景都用到了 AOP 。

面向对象:事物的抽象、降低耦合,提高维护性

面向对象的底层其实还是面向过程,把面向过程抽象成类,然后封装,方便我们我们使用的就是面向对象了。

面向对象的三大特性:
1、封装
隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。
2、继承
提高代码复用性;继承是多态的前提。
3、多态
父类可以指向子类或具体实现类的实例对象。提高了程序的拓展性。

细说Spring——AOP详解(AOP概览)

spring的4种依赖注入

1、构造方法注入

构造方法注入是指在构造方法中注入属性或者对象来实现依赖注入,注入完成后直接通过this.username获取到值。

public class UserDaoImpl {

    private String username;

    public UserDaoImpl(String username) {
        this.username = username;
    }
}

2、set方法注入

set方法注入就是通过在类中实现get、set方法来实现属性或者对象的依赖注入,注入完成后直接通过getUsername()获取到值。

public class UserDaoImpl {

    private String username;


    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

3、自动装配

Spring提供了自动装配的功能,简化了我们的配置,自动装配默认是不打开的,常用的方式有两种:

byName:通过参数名自动装配

id为userService的的autowire被设置为byName后,IOC容器会通过名字来自动装配,发现UserService类中有个叫userDao的属性,然后看看IOC容器中有没有id为userDao的,如果有就装配进去。

<bean id="userDao" class="com.example.UserDao"></bean>
<bean id="userService" class="com.example.UserService" autowire="byName"/>

byType:通过参数类型自动装配

4、注解

@Autowired注解可以实现自动装配,只要在对应的属性上标记该注解,但是@Autowired注解只按照byType注入。

public class UserController {
@Autowired
private IUserService userService;
}

@Resource注解可以实现自动装配,它有两个重要属性name和type,name属性解析为bean的名字,type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

@Autowired注解和@Resource注解的作用相同,只不过==@Autowired按照byType注入==,如果@Autowired想使用名称可以结合@Qualifier注解进行使用。

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

声明 Spring Bean 的作用域,使用方法:

@Bean
@Scope("singleton")
public Person personSingleton() {
    return new Person();
}
  • singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
  • prototype : 每次请求都会创建一个新的 bean 实例。
  • request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
  • session : 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。

Spring 中的 Bean 是线程安全的吗?

Spring 中的 Bean 默认是单例模式,Spring 框架并没有对单例 Bean 进行多线程的封装处理,因此默认的情况 Bean 并非是安全的,

  • 最简单保证 Bean 安全的举措就是设置 Bean 的作用域为 Prototype(原型)模式,这样每次请求都会新建一个 Bean。
  • 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。

说一下 Spring 中 Bean 的生命周期?

在这里插入图片描述

  1. 实例化 Bean:对于 BeanFactory 容器,当客户向容器请求一个尚未初始化的 Bean 时,或初始化 Bean 的时候需要注入另一个尚未初始化的依赖时,容器就会调用 createBean 进行实例化。对于 ApplicationContext容器,当容器启动结束后,通过获取BeanDefinition 对象中的信息,实例化所有的 Bean;
  2. 设置对象属性(依赖注入):实例化后的对象被封装在 BeanWrapper对象中,紧接着 Spring 根据 BeanDefinition 中的信息以及通过BeanWrapper 提供的设置属性的接口完成依赖注入;
  3. 处理 Aware 接口
  4. BeanPostProcessor:如果想对 Bean 进行一些自定义的处理,么可以让 Bean 实现了 BeanPostProcessor 接口
  5. InitializingBean 与 init-method:如果 Bean 在 Spring 配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法;
  6. 如果这个 Bean 实现了 BeanPostProcessor 接口,将会调用postProcessAfterInitialization(Object obj, String s) 方法;由于这个方法是在 Bean 初始化结束时调用的,因而可以被应用于内存或缓存技术;

在这里插入图片描述

@Autowired

自动导入对象到类中,被注入进的类同样要被 Spring 容器管理比如:Service 类注入到 Controller 类中。

@Service
public class UserService {
  ......
}

@RestController
@RequestMapping("/users")
public class UserController {
   @Autowired
   private UserService userService;
   ......
}

我们一般使用 @Autowired 注解让 Spring 容器帮我们自动装配 bean要想把类标识成可用于 @Autowired 注解自动装配的 bean 的类, 可以采用以下注解实现:

  • @Component :通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。
  • @Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。
  • @Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。
  • @Controller : 对应 Spring MVC 控制层,主要用于接受用户请求并调用 Service 层返回数据给前端页面。

@RestController

@RestController注解是@Controller和@ResponseBody的合集,表示这是个控制器 bean,并且是将函数的返回值直 接填入 HTTP 响应体中,是 REST 风格的控制器。

@Configuration

一般用来声明配置类,可以使用 @Component注解替代,不过使用@Configuration注解声明配置类更加语义化。

@PathVariable 和 @RequestParam

@PathVariable用于获取路径参数,@RequestParam用于获取查询参数。

如果我们请求的 url 是:/klasses/{123456}/teachers?type=web

那么我们服务获取到的数据就是:klassId=123456,type=web。

@RequestBody

用于读取 Request 请求(可能是 POST,PUT,DELETE,GET 请求)的 body 部分并且Content-Type 为 application/json 格式的数据,接收到数据之后会自动将数据绑定到 Java 对象上去。

@value(常用)

使用 @Value("${property}") 读取比较简单的配置信息:

@Value("${wuhan2020}")
String wuhan2020;

Spring 有哪些优点?

  1. 降低了代码耦合性,通过 Spring 提供的 IoC 容器,我们可以将对象之间的依赖关系交由 Spring进行控制,避免硬编码所造成的过度程序耦合;
  2. Spring 对很多难用的 Java EE API(如JDBC、JavaMail、远程调用等)提供了一层封装,通过 Spring 的简易封装,让这些 Java EE API 的使用难度大为降低。
  3. 方便集成各种优秀的框架;
  4. 方便程序测试,在 Spring 里,测试变得非常简单,例如:Spring 对 Junit的支持,可以通过注解方便的测试 Spring 程序;

Spring、SpringBoot、SpringCloud 的区别是什么?

  • Spring Framework 简称 Spring,是整个 Spring 生态的基础。
  • Spring Boot 是一个快速开发框架,让开发者可以迅速搭建一套基于Spring 的应用程序,并且将常用的 Spring 模块以及第三方模块,如MyBatis、Hibernate 等都做了很好的集成,只需要简单的配置即可使用,不需要任何的 XML 配置文件,真正做到了开箱即用,同时默认支持 JSON格式的数据,使用 Spring Boot 进行前后端分离开发也非常便捷。
  • Spring Cloud 是一套整合了分布式应用常用模块的框架,使得开发者可以快速实现微服务应用。

Spring 中都是用了哪些设计模式?

  • 工厂模式:通过 BeanFactory、ApplicationContext 来创建 bean (创建对象的实例)都是属于工厂模式;
  • 单例模式:创建 bean 对象设置作用域时,就可以声明 Singleton(单例模式)。Bean默认为单例模式
  • 观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新,如Spring中listener的实现–ApplicationListener。
  • 代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
  • 策略模式:在创建代理类时,如果代理的是接口使用的是 JDK 自身的动态代理,如果不是接口使用的是 CGLIB 实现动态代理。

Spring 如何解决循环依赖?

@Service
publicclass TestService1 {

    @Autowired
    private TestService2 testService2;

    @Async
    public void test1() {
    }
}
@Service
publicclass TestService2 {

    @Autowired
    private TestService1 testService1;

    public void test2() {
    }
}

首先,Spring 解决循环依赖有两个前提条件:

  • 不全是构造器方式的循环依赖
  • 必须是单例

基于上面的问题,我们知道Bean的生命周期,本质上解决循环依赖的问题就是三级缓存,通过三级缓存提前拿到未初始化的对象。

  • 第一级缓存:用来保存实例化、初始化都完成的对象
  • 第二级缓存:用来保存实例化完成,但是未初始化完成的对象
  • 第三级缓存:用来保存一个对象工厂,提供一个匿名内部类,用于创建二级缓存中的对象

创建对象A,实例化的时候把A对象工厂放入三级缓存,A注入的时候,发现依赖B,转而去实例化B。

再创建B,注入时发现依赖A,依次从一级缓存到三级缓存查询A,从三级缓存通过对象工厂拿到A,二就会进入二级缓存,此时B已经实例化好了,B就进入一级缓存。

继续创建A,顺利从一级缓存拿到实例化且初始化完成的对象B,A就会创建完成,删除二级缓存的A,同时把A放入到一级缓存。

Spring支持的事务管理类型,

编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。

声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需用注解和XML配置来管理事务。

spring 事务实现方式有哪些?

Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。

spring 的事务隔离?

spring 有五大隔离级别,默认值为 ISOLATION_DEFAULT

  • ISOLATION_DEFAULT:用底层数据库的设置隔离级别,数据库设置的是什么我就用什么;
  • ISOLATION_READ_UNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读);
  • ISOLATION_READ_COMMITTED:提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读),SQL server 的默认级别;
  • ISOLATION_REPEATABLE_READ:可重复读,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读),MySQL 的默认级别;
  • ISOLATION_SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。

脏读 :表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。

不可重复读 :是指在一个事务内,多次读同一数据。

幻读 :指同一个事务内多次查询返回的结果集不一样。比如同一个事务 A 第一次查询时候有 n 条记录,但是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。

Spring MVC

Spring MVC 的执行流程

前端控制器(DispatcherServlet) 接收请求,通过映射从 IoC 容器中获取对应的 Controller 对象和 Method 方法,在方法中进行业务逻辑处理组装数据,组装完数据把数据发给视图解析器,视图解析器根据数据和页面信息生成最终的页面,然后再返回给客户端。

  • 客户端发送请求至前端控制器(DispatcherServlet)

  • 前端控制器根据请求路径,进入对应的处理器

  • 处理器调用相应的业务方法

  • 处理器获取到相应的业务数据

  • 处理器把组装好的数据交还给前端控制器

  • 前端控制器将获取的 ModelAndView 对象传给视图解析器
    (ViewResolver)

  • 前端控制器获取到解析好的页面数据

  • 前端控制器将解析好的页面返回给客户端
    在这里插入图片描述
    Spring MVC 的核心组件

  • DispatcherServlet:核心处理器(也叫前端控制器),负责调度其他组件的执行,可降低不同组件之间的耦合性,是整个 Spring MVC 的核心模块。接收请求、响应结果,相当于转发器

  • HandlerMapping:DispatcherServlet 是通过 HandlerMapping 将请求映射到不同的 Handler。根据请求的URL来查找Handler

  • HandlerInterceptor:处理器拦截器,是一个接口,如果我们需要做一些拦截处理,可以来实现这个接口。

  • ModelAndView:装载了模型数据和视图信息,作为 Handler 的处理结果,返回给 DispatcherServlet。

  • ViewResolver:视图解析器,DispatcherServlet 通过它将逻辑视图解析成物理视图,最终将渲染结果响应给客户端。

POJO 和 JavaBean 有什么区别?

JavaBean 是 Java 语言中的一种可重用组件,JavaBean 的构造函数和行为必须符合特定的约定:这个类必须有一个公共的缺省构造函数;这个类的属性使用 getter/setter 来访问,其他方法遵从标准命名规范;这个类应是可序列化的。

当一个 POJO 可序列化,有一个无参的构造函数,它就是一个JavaBean。

服务器运行跨域

在后端通过 (CORS,Cross-origin resource sharing) 来解决跨域问题,实现WebMvcConfigurer接口然后重写addCorsMappings方法解决跨域问题。

  @Configuration
    public class MyConfiguration {
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurer() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    //  设置允许跨域的请求规则
                    registry.addMapping("/api/**");
                }
            };
        }
    }

@RequestMapping 注解的常用属性有哪些?

用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。

  • value:指定 URL 请求的实际地址,用法:
    @RequestMapping(value="/index");

  • method:指定请求的 method 类型,如 GET/POST/PUT/DELETE 等,用法:
    @RequestMapping(value="/list",method=RequestMethod.POST);

  • params:指定请求参数中必须包含的参数名称,如果不存在该名称,则无
    法调用此方法,用法:
    @RequestMapping(value="/list",params={“name”,“age”})。

forward 和 redirect 有什么区别?

  • forward 表示请求转发,请求转发是服务器的行为;redirect 表示重定向,重定向是客户端行为
  • forward 是服务器请求资源,服务器直接访问把请求的资源转发给浏览器,浏览器根本不知道服务器的内容是从哪来的,因此它的地址栏还是原来的地址redirect 是服务端发送一个状态码告诉浏览器重新请求新的地址,因此地址栏显示的是新的 URL;
  • 从效率来说,forward 比 redirect 效率更高。
    在这里插入图片描述

Spring MVC 的常用注解有哪些?

  • @Controller:用于标记某个类为控制器;
  • @ResponseBody :标识返回的数据不是 html 标签的页面,而是某种格式的数据,如 JSON、XML 等;
  • @RestController:相当于 @Controller 加 @ResponseBody 的组合效果;
  • @Component:标识为 Spring 的组件;
  • @Configuration:用于定义配置类;
  • @RequestMapping:用于映射请求地址的注解;
  • @Autowired:自动装配对象;

Spring MVC 有几种获取 request 的方式?

从请求参数中获取

@RequestMapping("/index")
@ResponseBody
public void index(HttpServletRequest request){
// do something
}

通过自动注入的方式

@Controller
public class HomeController{
@Autowired
private HttpServletRequest request; //  自动注入 request  对象
// do something
}

springBoot

Spring Boot 面试,一个问题就干趴下了!

Spring Boot 的核心思想是约定优于配置,让开发人员不需要配置任何 XML 文件,就可以像Maven 整合 Jar 包一样,整合并使用所有框架。

Spring Boot 项目优势如下

  • 配置变得简单,提供了丰富的 Starters,集成主流开源产品往往只需要简单的配置即可;
  • 开发变得简单,提供了丰富的解决方案,快速集成各种解决方案提升开发效率;

RequestMapping 和 GetMapping 有什么不同?

  • RequestMapping 可以支持 GET、POST、PUT 请求;
  • GetMapping 是一个组合注解,相当于 @RequestMapping(method =RequestMethod.GET)。

如何理解 Spring Boot 中的 Stater?

Stater 可以理解为启动器,它是方便开发者快速集成其他框架到 Spring 中的一种技术。比如,spring-boot-starter-web:Web 开发支持,mybatis-spring-boot-starter:MyBatis 框架支持

Spring Boot 在启动的时候会干这几件事情:

  • Spring Boot 在启动时会去依赖的 Starter 包中寻找 resources/META-INF/spring.factories 文件,然后根据文件中配置的 Jar 包去扫描项目所依赖的 Jar 包。
  • 根据 spring.factories 配置加载 AutoConfigure 类
  • 根据 @Conditional 注解的条件,进行自动配置并将 Bean 注入 Spring Context

其实就是 Spring Boot 在启动的时候,按照约定去读取 Spring Boot Starter 的配置信息,再根据配置信息对资源进行初始化,并注入到 Spring 容器中。这样 Spring Boot 启动完毕后,就已经准备好了一切资源,使用过程中直接注入对应 Bean 资源即可

SpringBoot 自动装配原理

1、什么是自动装配

Spring Boot 中,我们直接引入一个 starter 即可。比如你想要在项目中使用 redis 的话,直接在项目中引入对应的 starter 即可。在业务层可以直接使用@Autowired 来注入RedisTemplate实例,这就说明 IOC 容器中已经存在了 RedisTemplate。这就是Springboot的自动装配机制。

案例中,并没有事先通过 XML 形式或者注解的形式把 RedisTemplate 注入到 IOC 容器中,

2、SpringBoot 是如何实现自动装配的?

springBoot 的核心注解 SpringBootApplication 。

在这里插入图片描述
1、@SpringBootConfiguration:标记当前类为配置类
@EnableAutoConfiguration:开启自动配置
@ComponentScan:扫描主类所在的同级包以及下级包里的Bean
最重要的是@EnableAutoConfiguration:是springboot实现自动化配置的核心注解,通过这个注解把spring应用所需的bean注入容器中

在这里插入图片描述
@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的配置都加载到当前SpringBoot创建并使用的IoC容器中;

通过@Import(AutoConfigurationImportSelector.class)导入的配置功能,AutoConfigurationImportSelector类中的方法,
SpringFactoriesLoader.loadFactoryNames()可以得到需要配置的class的类名集合,这个集合就是所有需要进行自动配置的类,但是 是否配置的关键在于META-INF/spring.factories文件中是否存在该配置信息。


SpringFactoriesLoader.loadFactoryNames()
扫描所有jar包类路径下 META‐INF/spring.factories
把扫描到的这些文件的内容包装成properties对象
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中

2、@ComponentScan:由于@Service,@Repository, @Controller用来定义一个bean,@ComponentScan注解就是用来自动扫描被这些注解标识的类,最终生成ioc容器里的bean.

3、@Retention(RetentionPolicy.RUNTIME):该注解保留到哪个阶段。RUNTIME、SOURCE、CLASS

4、@SpringBootConfiguration:这个注解的作用与
@Configuration作用相同,都是用来声明当前类是一个配置类.可以通过@Bean注解生成IOC容器管理的bean。然后可以在其它类中注入使用(@Autowired)

自动配置类其实就是通过@Conditional按需加载的配置类,想要其生效必须引入spring-boot-starter-xxx包实现起步依赖
@Conditional中
matches方法就像正则的那个类一样…应该是true注入,false不注入

spring boot run 方法

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

maven冲突

使用exclusions标签来去掉某个dependency依赖中的某一个jar包或一堆jar包,exclusion中的jar包或者依赖的相关jar包都会被忽略,从而在两个dependency都依赖某个jar包时,可以保证只使用其中的一个。

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.8.3.2</version>
    <exclusions>
        <exclusion>
            <artifactId>guava</artifactId>
            <groupId>com.google.guava</groupId>
        </exclusion>
        <exclusion>
            <artifactId>spring</artifactId>
            <groupId>org.springframework</groupId>
        </exclusion>    
    </exclusions>
</dependency>

MyBatis

MyBatis 重要组件

  • Mapper 配置:用于组织具体的查询业务和映射数据库的字段关系,可以使用 XML 格式或 Java 注解格式来实现(sql语句);
  • Mapper 接口:数据操作接口也就是通常说的 DAO 接口,要和 Mapper配置文件中的方法一一对应
  • Executor:MyBatis 中所有的 Mapper 语句的执行都是通过 Executor 执行的;
  • SqlSession:类似于 JDBC 中的 Connection,可以用 SqlSession 实例来直接执行被映射的 SQL 语句;
  • SqlSessionFactory:SqlSessionFactory 是创建 SqlSession 的工厂,可以通过 SqlSession openSession() 方法创建 SqlSession 对象。

MyBatis 执行流程

MyBatis 首先加载 Mapper 配置和SQL 映射文件,通过创建会话工厂得到 SqlSession 对象,再执行 SQL 语句并返回操作信息。

在这里插入图片描述

  1. 首先加载 Mapper 配置的 SQL 映射文件,或者是注解的相关 SQL 内容。
  2. 创建会话工厂,MyBatis 通过读取配置文件的信息来构造出会话工厂(SqlSessionFactory)。
  3. 创建会话,根据会话工厂,MyBatis 就可以通过它来创建会话对象(SqlSession),会话对象是一个接口,该接口中包含了对数据库操作的增、删、改、查方法
  4. 创建执行器,因为会话对象本身不能直接操作数据库,所以它使用了一个叫做数据库执行器(Executor)的接口来帮它执行操作。
    5.封装 SQL 对象,在这一步,执行器将待处理的 SQL 信息封装到一个对象中(MappedStatement),该对象包括 SQL 语句、输入参数映射信息(Java 简单类型、HashMap 或 POJO)和输出结果映射信息(Java 简单类型、HashMap 或 POJO)。
  5. 操作数据库,拥有了执行器和 SQL 信息封装对象就使用它们访问数据库了,最后再返回操作结果,结束流程。

#{}和${}的区别是什么?

传参:可以通过@Param(“key”)为Map集合指定键的名字

  • Student getStudentById(@Param(“sid”) String sid, @Param(“sname”)String sname);

取参:

  • #{}是 sql 的参数占位符,MyBatis 会将 sql 中的#{}替换为?号,防止SQL注入。使用#{}传值时,如果传值的类型是String,传过来的值会自动加上单引号
  • ${}是 Properties 文件中的变量占位符,它可以用于标签属性值和 sql 内部,属于静态文本替换,是直接拼接到sql语句中

Dao 接口里的方法,参数不同时,方法能重载吗?

Dao 接口里的方法可以重载,但是Mybatis的XML里面的ID不允许重复。

Mybatis 的 Dao 接口可以有多个重载方法,但是多个接口对应的映射必须只有一个,否则启动会报错。

Dao 接口的工作原理是 JDK 动态代理,MyBatis 运行时会使用 JDK 动态代理为 Dao 接口生成代理 proxy 对象,代理对象 proxy 会拦截接口方法,转而执行MappedStatement所代表的 sql,然后将 sql 执行结果返回

MyBatis 是如何进行分页的?分页插件的原理是什么?

MyBatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页,可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

分页插件的基本原理是使用 MyBatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql

select t._ from (select \* from student)t limit 0,10

limit start(页码)、pageSize(每页显示的条数)

limit (start-1)*pageSize,pageSize

查询第10条到第20条的数据的sql是:select * from table limit 10,10; ->对应我们的需求就是查询第二页的数据:select * from table limit (2-1)*10,10;

MyBatis 动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?

MyBatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能,MyBatis 提供了 9 种动态 sql 标签

trim|where|set|foreach|if|choose|when|otherwise|bind。

tomcat

tomcat 有哪几种Connector 运行模式(优化)?

  • BIO:同步并阻塞 一个线程处理一个请求。缺点:并发量高时,线程数较多,浪费资源。Tomcat7或以下,在Linux系统中默认使用这种方式。
  • NIO:同步非阻塞IO
    利用Java的异步IO处理,可以通过少量的线程处理大量的请求,可以复用同一个线程处理多个connection(多路复用)。
  • AIO方式:异步非阻塞IO(Java NIO2又叫AIO) 主要与NIO的区别主要是操作系统的底层区别.可以做个比喻:比作快递,NIO就是网购后要自己到官网查下快递是否已经到了(可能是多次),然后自己去取快递;AIO就是快递员送货上门了(不用关注快递进度)。

springSecurity

认证、授权区别

Authentication(认证) 是验证您的身份的凭据(例如用户名/用户 ID 和密码),通过这个凭据,系统存在你这个用户

Authorization(授权) 发生在 Authentication(认证) 之后。比如有些特定资源只能具有特定权限的人才能访问比如 admin,有些对系统资源操作比如删除、添加、更新只能特定人才具有。

如何使用 Session-Cookie 方案进行身份验证?

用户成功登陆系统,然后返回给客户端具有 SessionID 的 Cookie
当用户向后端发起请求的时候会把 SessionID 带上,这样后端就知道你的身份状态了。

多服务器节点下 Session-Cookie 方案如何做?

假如我们部署了两份相同的服务 A,B,用户第一次登陆的时候 ,Nginx 通过负载均衡机制将用户请求转发到 A 服务器,此时用户的 Session 信息保存在 A 服务器。结果,用户第二次访问的时候 Nginx 将请求路由到 B 服务器,由于 B 服务器没有保存 用户的 Session 信息,导致用户需要重新进行登陆。

解决方案:

1、某个用户的所有请求都通过特性的哈希策略分配给同一个服务器处理。这样的话,每个服务器都保存了一部分用户的 Session 信息。服务器宕机,其保存的所有 Session 信息就完全丢失了。

2、每一个服务器保存的 Session 信息都是互相同步的,也就是说每一个服务器都保存了全量的Session信息 每当一个服务器的 Session 信息发生变化,我们就将其同步到其他服务器。这种方案成本太大,并且,节点越多时,同步成本也越高。

为什么 Cookie 无法防止 CSRF 攻击,而 Token 可以?

CSRF(Cross Site Request Forgery)一般被翻译为 跨站请求伪造。

Session 认证中 Cookie 中的 SessionId 是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。

但是,我们使用 Token 的话就不会存在这个问题,在我们登录成功获得 Token 之后,一般会选择存放在 localStorage (浏览器本地存储)中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 Token,这样就不会出现 CSRF 漏洞的问题。因为,即使有个你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 Token 的,所以这个请求将是非法的。

什么是 Token?什么是 JWT?

我们知道 Session 信息需要保存一份在服务器端。这种方式会带来一些麻烦,比如需要我们保证保存 Session 信息服务器的可用性、不适合移动端(依赖 Cookie)等等。

JWT (JSON Web Token) 就是这种方式的实现,通过这种方式服务器端就不需要保存 Session 数据了,只用在客户端保存服务端返回给客户的 Token 就可以了,扩展性得到提升。

JWT 本质上就一段签名的 JSON 格式的数据。由于它是带有签名的,因此接收者便可以验证它的真实性。

JWT 由 3 部分构成:

  • Header : 描述 JWT 的元数据,定义了生成签名的算法以及 Token 的类型
  • Payload : 用来存放实际需要传递的数据
  • Signature(签名) :服务器通过Payload、Header和一个密钥(secret)使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成。

如何基于 Token 进行身份验证?

  • 用户向服务器发送用户名和密码用于登陆系统。
  • 身份验证服务响应并返回了签名的 JWT,上面包含了用户是谁的内容。
  • 用户以后每次向后端发请求都在 Header 中带上 JWT。
  • 服务端检查 JWT 并从中获取用户相关信息。

什么是 OAuth 2.0?

OAuth 是一个行业的标准授权协议,主要用来授权第三方应用获取有限的权限。

OAuth 2.0 比较常用的场景就是第三方登录,当你的网站接入了第三方登录的时候一般就是使用的 OAuth 2.0 协议。

微信开放平台

必须是在微信客户端,引导微信用户访问下面文档指定的url。我们可以修改的仅仅是接口中重定向redirect_uri部分,可以重定向到我们自己开发的页面中。获取code

APPID:唯一标识,开发者ID

APPSECRET:开发者密码,

access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。access_token的有效期目前为2个小时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

德玛西亚!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值