一、数据库基础
1、平均值用什么,分组用什么
统计平均值:avg , 分组:group by,通常与聚合函数一起使用,例如 COUNT()
、SUM()
、AVG()
、MAX()
和 MIN()
。
2、两个相同列的结果集求并集用什么
union 并集(自动去重) , union all(允许重复并集)
3、完整查询SQL中的关键字的定义顺序?
SELECT 列名 FROM 表1 JOIN 表2 ON 条件 WHERE 条件 GROUP BY 列名 HAVING 条件 ORDER BY 列名 LIMIT
4、完整的多表JOIN查询,SQL中关键字的执行顺序?
FROM --> ON --> JOIN --> WHERE --> GROUP BY --> HAVING --> SELECT ---> DISTINCT ---> ORDER BY --> LIMIT
二、Spring
**1、**介绍一下Spring?
Spring是一个开源的轻量级控制反转和面向切面编程 的容器框架。轻量级是说它开发使用简单,功能强大。控制反转是指将对象的创建,初始化,销毁等工作,以及依赖关系维护交给ioc容器,方便解耦合,降低维护难度。面向切面编程是指将相同的逻辑++横向抽取++ 出来,可以对一些通用业务如事务,日志进行++集中管理++。
2、说下Spring框架的组成?
-
CoreContain核心容器模块:
-
Spring Core:提供了框架的基本功能,包括++依赖注入(DI)和控制反转(IOC)容器++
-
spring-beans:提供 BeanFactory,负责Bean工厂中Bean的装配,所谓Bean工厂即是创建对象的工厂,Bean的装配也就是对象的创建工作;
-
context**:** ++Spring的IOC容器++,负责管理Spring应用中的所有bean的生命周期和配置,提供国际化,事件传播,资源加载等功能
-
spring-ExpressionLanguage(SpEl ):提供表达式语言
-
-
Web模块
-
Web**:**提供面向web的基本功能和面向web的应用上下文
-
Spring Web-MVC:也称为Web-Servlet,为web应用提供模型视图控制(MVC)
-
Spring Web-Socket:提供Socket通信, 在 web 应用程序中提供++客户端和服务器++端之间通信的方式
-
Spring Web-Portlet:模块提供了用于Portlet环境的MVC实现
-
-
数据/集成模块
-
spring JDBC:对JDBC的数据访问进行了封装和简化
-
ORM:为对象-关系映射提供交互层,支持数据集成框架的封装
-
OXM:提供对Object/XML映射实现的抽象层,它的作用是在Java对象和XML文档之间来回转换;
-
JMS:提供了Java消息服务(JMS)的支持
-
Transaction:事务模块,支持用于实现特殊接口类以及所有 POJO 类(简单的Java对象)的编程和声明式的事务管理
-
-
其他模块
-
Spring AOP:提供了面向切面编程的实现,让你可以在你的应用程序中使用切面编程
-
Aspects:模块提供了与AspectJ的集成,是一个功能强大的AOP框架
-
Instrumentation:提供了class instrumentation 的支持和类加载器classloader的实现
-
Messaging:为 STOMP 提供支持
-
Test:支持使用JUnit和TestNG对Spring组件进行测试
-
**3、**什么是Spirng的IOC?
1)IOC控制反转 ,把对象的创建,属性设置,初始化,销毁等工作交给Spirng的IOC容器去管理,解放程序员的劳动力。
2)对象被注册到Spring的IOC容器中,使用的时候从容器中获取即可,非常方便。
3)它通过依赖注入,将需要的外部资源注入到组件中,使用IOC使得对象之间的耦合度降低,资源变得容易管理,从而使得代码更加优雅
谁控制谁?控制什么?
传统的面向对象思想对于构造对象最简单的方法无非就是在对象内部通过new对对象进行创建,是程序主动去创建依赖对象。
但IOC不同,IOC是专门有一个容器来创建、初始化这些对象,这些对象被称为Bean。谁控制谁? 是++IOC容器控制住了对象++ ,控制了什么? ++控制了bean的生命周期++。
4、你对AOP的理解?
AOP,Aspect Oriented Programming 英文首字母缩写,意为面向切面编程,是Spring的核心思想之一。AOP是++对OOP(面向对象编程)的一种补充++ ,能够做到很多面向对象无法做到的事情,比如需要在所有方法执行前开启事务,打印日志,如果使用面向对象来编程,将会产生大量重复代码,而使用AOP,可以++将那些与业务无关,却为业务模块所共同调用的逻辑封装起来++,一次解决这些问题。而这些重复的代码,一般统称为横切逻辑代码
使用AOP,在不改变原有业务逻辑的情况下,实现++解耦合++,避免横切逻辑代码重复
AOP的使用场景包括++日志记录,性能统计,安全控制,事务处理,异常处理++等等
它是基于++动态代理++实现的,分为JDK动态代理和CGLIB动态代理。JDK动态代理只支持实现了接口的类 ,CGLIB支持没有实现接口的类。Spring默认使用JDK动态代理,如果被代理类没有实现接口,会选择CGLIB动态代理
5、Spring的Bean懒加载和非懒加载有什么区别?
懒加载:需要使用对象的时候才创建,节省资源,但不利于提前发现错误
非懒加载,也叫迫切加载,++容器启动时就创建对象++,消耗资源,但有利于提前发现错误
spring中默认是迫切加载,即在项目启动时,spring会扫描符合条件的所有bean并将其初始化,如果需要懒加载,可以使用@Lazy注释或者xml中配置属性default-lazy-init="true"
6、Spring的依赖注入方式有哪些?
方式一:++setter++ 方式注入,通过++反射++ 调用++无参构造++方法生成对象,再通过对应的setter方法注入配置的值,支持注解和xml两种实现方式
方式二:++构造器++ 方式注入,通过++反射++ 调用++有参构造++方法生成对象,支持注解和xml两种实现方式,注解实现方式:@Autowired,它是默认按类型匹配的、@Resource,它是默认按名字匹配的(如果同时指定了name和type属性,容器会按照匹配规则来查找依赖对象;如果只指定了其中一个属性,容器会按照指定的属性来查找依赖对象;如果没有指定任何属性,容器会按照默认的规则来查找依赖对象)
其他注解:@Bean,@Component
、@Service
、@Repository
、@Controller
7、说一下定义切面相关的注解?
@Aspect:定义切面类
@Pointcut:定义切点 = cn.xx.service.*
@Before:前置通知,在目标方法运行之前运行
@After:后置通知,在目标方法运行结束之后运行(无论方法正常结束还是异常结束)
@AfterReturning:返回通知,在目标方法正常返回之后运行
@AfterThrowing:异常通知,在目标方法出现异常以后运行
@Around:动态代理,手动推进目标方法运行,用于定义环绕通知,可以在目标方法执行前后执行自定义逻辑,并且可以控制目标方法的执行
8、Bean的四种注册方式?
方式一:普通注册方式,直接通过class注册
方式二:简单静态工厂方式注册。通过在一个类中定义一个静态方法来创建Bean。这种方法适用于那些不需要依赖注入的简单对象的创建。
方式三:简单实例工厂方式注册。与静态工厂方式类似,但工厂类的方法不是静态的。这种方式更灵活,因为工厂类可以依赖于其他Beans进行实例化。
方式四:FactoryBean方式注册。通过实现FactoryBean
接口的类来创建Bean。FactoryBean
接口的实现类需要重写getObject
方法以返回实际的对象实例,而getObjectType
方法返回该对象的类型。
9、注册Bean的注解有哪些?
@Controller/@RestController 一般用于定义控制层的类
注:@Controller通过页面模板引擎将数据渲染成HTML页面返回给用;
@RestController处理请求并返回数据(通常是JSON或XML格式)
@Service 一般用于定义服务层的类
@Repository 一般用于定义持久层类
@Component 定义一般类
@Configuration 定义配置类
10、IOC的启动流程有了解过吗?
当Spring启动时,IOC容器会加载Spring的配置文件,包括XML配置或者注解,然后解析这些Bean并把相关定义信息封装成BeanDefinition对象,通过Bean注册器BeanDefinitionRegistry注册到IOC容器,也就是一个ConcurrentHashMap中
此时会找出所有的单例且非惰性加载的bean,根据其BeanDefinition进行Bean的实例化,它会判断如果bean中有方法覆盖,就使用JDK反射创建Bean,否则使用CGLIB方式生成代理。然后把实例化好的Bean缓存到一个ConcurrentHashMap中
11、Bean的生命周期讲一下?
从宏观的角度来说就是:实例化 ,属性注入,初始化,使用,销毁。更细的生命周期如下
-
实例化:如果是单例且迫切加载的bean,在Spring容器启动时就会根据BeanDefinition进行实例化,如果时设置了懒加载或者多例模式的bean,在用的时候才会实例化
-
属性赋值:通过BeanDeifinition找到当前Bean所依赖的其他Bean,如果容器中有就直接拿过来,如果没有就根据创建流程去创建依赖的bean,然后通过反射给依赖的字段注入值
-
然后会调用BeanPostProcessor的前置处理器,对于@Autowired和@Transcational就是基于BeanPostProcessor来实现的。
-
接着会看Bean是否实现InitializingBean ,如果有会触发其afterPropertiesSet方法的调用
-
接着是调用我们自定义的bean的init-method方法,此时会调用执行
-
然后是调用BeanPostProcessor的后置处理
-
容器正常关闭,Bean进行销毁,会先调用实现了DisposableBean的destory方法。
-
接着调用我们指定的bean的destroy-method方法,此时会调用执行
12、单例多例的区别?
单例和多例属于++对象模式++,单例模式指对象在整个系统中只存在一份,多例模式则可以有多个实例。
在spring的ioc容器中的bean默认都是单例的,如果需要使用多例,可以通过修改scope属性:scope="prototype"
如果一个bean是单例模式的,在处理多次请求的时候,在ioc容器中只实例化一个bean,这个对象会被保存在一个map中,当有请求来的时候,会先从map中查看,如果有就直接使用这个对象,没有才会实例化新的对象。
如果是多例(prototype)模式的bean,每次请求来的时候,会直接实例化新的bean,没有map缓存的过程。
13、Spring的Bean被指定为prototype以及singleton有什么区别?
这两者分别指的是多例和单例模式,singleton即单例模式,指对象在整个系统中只存在一份;prototype即多例模式系统中可以有多个实例。
如果一个bean是单例模式的,在处理多次请求的时候,在ioc容器中只实例化一个bean,这个对象会被保存在一个map中,当有请求来的时候,会先从map中查看,如果有就直接使用这个对象,没有才会实例化新的对象。
如果是多例模式的bean,每次请求来的时候,会直接实例化新的bean,没有map缓存的过程。
在spring的ioc容器中的bean默认都是单例的,如果需要使用多例,可以指定scope属性:scope="prototype"
14、BeanFactory和ApplicationContext有什么区别?
BeanFactory接口是++IOC容器的核心接口++,定义了管理bean的最基本方法,比如实例化,配置,管理,获取bean的方法
ApplicationContext接口是B++eanFactory接口的子接口++,除了继承BeanFactory中所有管理bean的方法,还拥有环境、国际化、资源、事件等服务相关的接口
BeanFactory是延迟加载,ApplicationContext是迫切加载
15、BeanFactory和FactoryBean的区别?
BeanFactory接口是IOC容器的核心接口,定义了管理bean的最基本方法,比如实例化,配置,管理,获取bean的方法
FactoryBean是IOC容器创建bean的一种形式,可以通过实现此接口来创建实例化过程比较复杂的bean
16、IOC容器是如何保证Bean的单例的?
IOC容器会将单例模式的bean放入一个ConcurrentHashMap中,需要这个bean时直接到这个map中获取,如果没有找到才会实例化这个bean。而ConcurrentHashMap本身时线程安全的,也就保证了Bean是单例的
17、Spring如何解决Bean的循环依赖?
循环依赖分为三种,构造器注入循环依赖 ,setter方式注入循环依赖,多例模式Bean的循环依赖。而Spring解决了单例bean的setter注入循环依赖(另外两种不能解决)
setter循环依赖的解决主要使用了三级缓存:
-
一级缓存,用来缓存已经实例化好的bean,即单例Bean缓存池
-
二级缓存,用来缓存正在创建的bean
-
三级缓存,用来缓存创建bean的实例工厂ObjectFactory
假设有两个bean,A依赖B,B依赖A
当实例化好A,在属性注入环境,发现A依赖了B,会先将正在创建的A的实例工厂ObjectFactory放入三级缓存,然后去创建B的实例。
走Bean的实例化流程创建B,在B的属注入环节发现,B依赖了A,这个时候就会去三级缓存中,找到A的创建工厂ObjectFactory获取A的实例,并注入到B中。此时B就初始化好了,然后将B实例放入一级缓存。最后将B实例注入到A中,A也就创建好了
在getBean的时候,如果单例Bean缓存池没有Bean,就会走二级缓存尝试获取,如果也没有,就会走三级缓存拿到Bean的ObjectFacory创建Bean,然后把Bean放入二级缓存。
18、Springbean的作用域?
Spring框架提供了多种Bean作用域,这些作用域定义了Bean的实例化方式以及它们在Spring容器中的生命周期。以下是Spring中常见的Bean作用域及其特性的概述:
1)singleton(单例)作用域
- 定义:在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例。这是Spring的默认作用域。
- 使用场景:通常用于无状态的Bean,即不需要更新其对象状态的Bean。
- 特性:在IoC容器中只存在一个实例,无论是通过
applicationContext.getBean()
方法获取还是通过@Autowired
注入,都是同一个对象。
2)Prototype(原型)作用域
- 定义:每次对该作用域下的Bean的请求都会创建新的实例。
- 使用场景:需要创建多个实例的场景,如每次请求都需要一个新的资源或配置。
- 特性:每次请求都会创建一个新的Bean实例,适用于需要多个独立实例的场景。
3)Request(请求)作用域
- 定义:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例。
- 使用场景:Web应用中,每个HTTP请求需要一个独立的Bean实例。
- 特性:仅在当前HTTP请求内有效,请求结束后实例将被销毁。
4)Session(会话)作用域
- 定义:对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。
- 使用场景:在Web应用中,每个用户会话需要一个独立的Bean实例。
- 特性:在同一个HTTP Session内共享一个Bean实例,不同的Session使用不同的Bean实例。
5)Application(应用)作用域
- 定义:在整个Web应用生命周期内,使用application定义的Bean只有一个实例。
- 使用场景:需要在整个应用范围内共享数据或资源的场景。
- 特性:适用于在整个应用范围内只需要一个实例的情况。
选择合适的Bean作用域取决于应用的具体需求和设计。例如,对于无状态的Service层组件,通常使用singleton作用域;而对于需要为每个用户会话或请求创建独立实例的组件,则应使用session或request作用域。选择合适的作用域有助于优化资源利用、提高系统的可维护性和性能
19、Spring构造器注入能循环依赖吗?
构造注入不能解决循环依赖的原因是:如果A的构造其中依赖了B,B的构造器中又依赖了A,在getSingleton中三级缓存需要调用getObject()构造器,来构造提早暴露但未设置属性的bean,此时就会产生无限递归创建
多例模式下Bean是不做缓存的,所以就没法暴露ObjectFactory,也就没办法解决循环依赖。
20、说几个Spring的IOC的容器工厂类?
BeanFactory:IOC容器顶层接口,提供了Bean获取的基础方法
DefaultListableBeanFactory:是整个 bean 加载的核心部分,Spring 注册及加载Bean 的默认实现
ApplicationContext:除了实现IOC基本功能外,还扩展了国际化支持,资源访问,事件发布
ClasspathXmlApplicationContext:从classpath中获取XML配置
21、你知道Spring的AOP主要基于什么设计模式实现吗?
AOP的实现原理是基于++动态代理++,动态代理就是在运行时期动态的为原生类生成代理类以达到代码增强的目的,且代理类是持有原生类的,可以在代理类中调用原生类以及做一些增强业务。
动态代理分为JDK动态代理和CGLIB代理,CGLIB代理需要导入相关的jar包,两者的区别是JDK动态代理要求目标类需要实现至少一个接口。而CGLIB则是基于继承进行代理,原生类可以不实现任何接口
Spring中默认采用JDK动态代理,如果原生类没有实现任何接口,Spring会选择CGLIB代理,或者你可以在配置文件中强制指定使用CGLIB代理
22、你知道@Autowaire自动注入的实现原理吗?
自动注入是通过BeanPostProcessor 后置处理器AutowiredAnnotationBeanPostProcessor完成的,在Bean实例化过程中,触发了AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法的调用执行,它就会扫描当前类中是否有@Autowired注解,然后得到自动注入依赖的bean的类型,并去容器中得到依赖的bean实例,如果没有就走Bean的实例化流程创建依赖的Bean,然后反射进行字段赋值。
23、你知道@Transcational注解的实现原理吗?
分为两个动作把,第一个是解析@Transcational注解,在Sping中有个后置处理器InfrastructureAdvisorAutoProxyCreator,在Bean的初始化过程中,它负责解析标记了@Transcational注解的类,生成代理。还创建了 TransactionAttributeSource ,它是对事务注解的封装,以及 TransactionInterceptor 事务拦截器。
在执行业务方法的时候,代码会进入事务拦截器TransactionInterceptor去执行事务相关的代码,TransactionInterceptor主要是通过调用TranscationManagerment的事务API,而TranscationManagerment又是调用connection的事务API完成事务操作。
三、Javaweb基础
1、常见Http状态码?
200 成功返回状态
301 永久重定向,被请求的资源永久移动到新位置
302 临时重定向,被请求的资源临时移动到新的位置,项目中使用了oauth2,对目标资源访问无权限时就会见到,它是会重定向到授权地址
401 无权限访问
403 禁止访问,服务器已经接收到请求,但拒绝执行
404 找不到该资源
500 服务器内部错误 zuul找不到服务名就会见到
503 服务器内部错误 服务器维护或者过载
504 网关超时
2、Servlet的生命周期?
Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:
-
Servlet 初始化调用 init () 方法。
-
Servlet 调用 service() 方法来处理客户端的请求。
-
Servlet 销毁调用 destroy() 方法。
-
最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
3、什么是过滤器?怎么创建一个过滤器?
过滤器:在请求发送之后,处理之前对请求的一次拦截,可以更改请求状态或者参数值等。
创建过滤器:实现filter接口,重写doFilter方法,最后在web.xml中配置过滤器
4、讲一下Session的工作原理?
服务端的session id会自动写入客户端的cookie中,每次请求客户端会自动把cookie带入后台,后台自动根据cookie中的sessionid就能找到session
5、Session和cookie有什么区别?
session和cookie都是为了弥补http协议的无状态特性,解决会话问题
session是以ConcurrentHashMap结构存储在服务器端,同时生成一个sessionid返回客户端并存放到cookie中
cookie是将数据存储在客户浏览器端
session占用服务器的性能,但安全性较高,使用cookie减轻服务器的压力,但有被用户篡改风险因此安全性较低
6、说说preparedStatement和Statement的区别?
statement的sql语句使用字符串拼接,很容易出错;statement不对sql语句作处理,直接交给数据库;有sql注入风险
preparedStatement使用?作为占位符,不容易出错易于维护;preparedStatement支持预编译,事先将编译好的sql语句放到数据库端,相当于缓存,因此效率更高;没有sql注入风险
7、请求转发和重定向的区别?
|-----------|------------------------------|------------------------------|
| | 转发 | 重定向 |
| | 一次请求,可以共享同一组request和response | 多次请求,不能共享同一组request和response |
| 地址栏是否变化 | 不会 | 会 |
| 是否可以到外部应用 | 不能 | 可以 |
| 使用场景 | 需要数据共享、访问内部资源(WEB-INF),使用转发 | 如果需要跨域到外部资源,必须使用重定向 |
8、get和post请求的区别?
1)最直观的区别,get把参数包含在url中,post是把参数放到request body中
2)post相对于get更安全,post发送的数据更大,get有url的长度限制
3)get只能发送ASCII字符,post可以发送更多的数据类型
4)在restful中,一般用户查询搜索数据用get,添加或者修改数据用post
9、JSP的原理?
jsp的本质就是servlet,每个JSP文件都会被编译成一个Servlet去执行,在该Servlet会对JSP中的动态内容进行替换,静态部分是标准的html,动态部分是java程序。
10、拦截器和过滤器的区别?
作用范围:过滤器作用于整个应用,包括静态资源,而拦截器通常只作用于请求处理(控制器层)。
配置方式:过滤器是Java EE标准,配置在web.xml或通过@WebFilter注解;拦截器由框架提供,配置在框架的配置文件中。
生命周期管理:过滤器由Servlet容器管理,拦截器由框架管理。
四、SpringMVC部分
1、SpringMVC怎么样设定重定向和转发的?
重定向是指将用户从当前请求重新定向到一个视图页面,或者是一个handler处理请求,以前的request域中信息全部失效,同时地址栏会发生变化,它是++客户端行为++
转发是指将用户从当前请求转发给另一个视图页面或者handler处理请求,以前的request域可以共享,地址栏不会发生变化,它是++服务器行为++
springmvc默认是使用转发方式跳转的,且会默认经过视图解析器,我们也可以通过指定,转发时在返回值前面加"forward:",重定向时在返回值前面加"redirect:",且此时就不会再经过视图解析器了
2、SpringMVC如何对时间格式的参数进行格式化?
第一种需求,后台接收前台页面返回的string类型时间,要转换成的Date类型数据,可以使用@DateTimeFormat注解来接收参数
第二种需求,后台将Date类型数据返回给前台页面,默认是返回时间戳,如果想要优雅的格式,可以在模型的Date字段或get方法上使用@JsonFormat注解
3、SpringMVC常用的注解有哪些?
@Controller:用来标识一个类是控制器类
@RequestMapping:用来映射请求路径和参数
@ResponseBody:将返回值放到responsebody中,通常返回json或者xml格式数据
@RequestBody:将前台请求参数转换成对象
@PathVariable:接收路径参数,通常用在restful接口中
@RestController:@Controller和@ResponseBody的组合注解
@ControllerAdvice:运用aop的思想,对全局做一些处理,比如结合@ExceptionHandler做全局异常捕获
4、如何定义SpringMVC的拦截器?
SpringMVC 的拦截器主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、判断登录等功能上
第1步,定义拦截器:可以实现 HandlerInterceptor 接口来自定义拦截器,接口定义了三个方法,preHandler方法是在++请求到达处理器之前++ 执行,postHandler方法是在++请求经过处理器之后、解析视图之前++ 执行,afterCompletion方法是在++视图渲染之后、返回客户端之前执行++
第2步,配置拦截器:在springmvc的配置文件xml中,配置所有拦截路径,以及需要放行的路径
5、HandlerInterceptor和HandlerInterceptorAdapter的区别?
HandlerInterceptor是接口,我们可以实现该接口来定义拦截器
HandlerInterceptorAdapter是抽象类,它实现了HandlerInterceptor接口的子接口AsyncHandlerInterceptor,我们可以继承该类来定义拦截器,它简化拦截器的实现,默认preHandler返回true
6、SpringMVC的执行原理?
1)Http请求:客户端请求提交到前端控制器DispatcherServlet
2)寻找处理器:由DispatcherServlet调用处理器映射器HandlerMapping,根据url找到对应的Handler
3)调用处理器:DispatcherServlet指定处理器适配器HandlerAdapter去调用Handler
4)调用业务处理和返回结果:Handler调用业务逻辑处理完成后,返回ModelAndView
5)处理视图映射并返回模型: DispatcherServlet查询一个或多个ViewResoler-视图解析器,找到ModelAndView指定的视图
6)Http响应:将结果显示到客户端
7、SpringMVC的Controller是单例还是多例,有没有并发安全问题,如何解决?
在spring中,bean默认都是单例的,controller也是交给spring容器管理的一个bean,因此它也是单例的。
单例的好处是减少了创建对象和垃圾回收的时间,节省了内存资源,但同时单例会造成线程不安全的问题,因为当所有请求访问同一个controller实例,controller中的成员变量是所有线程公用的,某个线程如果修改了这个变量,别的请求再来拿这个变量就变成修改后的值了
要解决这个问题,最直接有效的方式就是不要在controller中定义成员变量,如果你非要定义成员变量,两种方式
第一种,可以给controller上加注解@Scope("prototype"),将controller设置为多例模式,每次请求都重新实例化一个controller
第二种,使用ThreadLocal变量,让每一个线程都有自己独立的变量
8、RequestMapping 和 GetMapping有什么区别?
@Getmapping是一个组合注解,即是@RequestMapping(method = RequestMethod.GET)的缩写,意思是只接收get请求的方法
@Requestmapping如果没有指定请求方式,可以接收get,put等各种类型的请求
五、SpringBoot部分
1、相比Spring,Spring Boot有哪些优点?
Springboot是一个基于spring的框架,对spring做了大量简化,使开发流程更快,更高效
它大量简化maven依赖,管理了大量的基础依赖
基于注解配置(JavaConfig),无需xml配置
内嵌Tomcat,部署流程简单
打包和部署更加灵活,允许独立运行
2、SpringBoot如何做全局异常处理?
可以使用@ControllerAdvice注解,编写一个全局异常处理类,再自定义一个方法使用@ExceptionHandler来捕获具体的异常并作相应的处理。
通常情况下后台向前台返回结果时,会把结果封装成包含有错误码,错误信息以及数据本身的json数据,因此我们可以使用自定义异常类,自定义枚举错误码,在捕获全局异常后,向前台返回一个包含错误码的信息
3、@SpringBootApplication注解的含义?
@SpringBootApplication是SprnigBoot项目的核心注解,目的是++开启自动配置++ ,并表示该类为++主启动类++。它包含三个子标签
-
@ComponentScan注解:开启ioc自动扫描注解,默认扫描当前包及其子包中@Controller, @Service等,并把这些bean加载到ioc器中
-
@EnableAutoConfiguration注解:启用springboot自动配置,自动所有扫描classpath目录下面所有jar中的spring.factories文件,实现配置类批量注册
-
@SpringBootConfiguration注解:标志该类为springboot配置类
4、spring-boot-starter-parent的作用?
这是SpringBoot的父工程,它的作用是帮我们管理了很多的基础jar包,同时它继承了spring-boot-dependencies,在spring-boot-dependencies项目中通过<dependencyManagement>管理了大量的依赖,同时通过<properties>维护了这些依赖的版本号
但是在项目中,还需要通过<dependencies> 去导入具体的依赖才能使用
5、spring-boot-starter-web的作用?
的作用是简化和加速基于 Spring Web(Spring MVC)框架的 Web 应用开发。它集成了构建 Web 应用所需的常用依赖和配置,包含了springweb 集成了日志,tomcat,springmvc,json支持等等,使得开发者可以快速创建 RESTful Web 服务或传统的 Web 应用程序,而无需手动配置复杂的依赖和组件。通过引入这个 Starter 依赖,开发者可以轻松启动一个完整的 Spring Web 应用项目。
6、SpringBoot中如何读取配置?
方式一:使用@Value读取配置文件
方式二:使用@ConfigurationProperties读取配置文件
7、SpringBoot中日志的level有哪些?
日志级别从低到高分别为:
TRACE < DEBUG <INFO <WARN < ERROR
如果设置为 WARN,则低于 WARN的信息都不会输出
Spring中默认使用INFO级别输出到控制台
8、SpringBoot中如何管理事务?
事务(transaction)是指业务逻辑上对数据库进行的一系列持久化操作,要么全部成功,要么全部失败。
在Springboot中,可以通过xml配置和注解配置
xml方式通过配置DataSourceTransactionManager和TransactionManager实现
注解方式配置通过在主启动类上加上@EnableTransactionManagement开启事务管理器,在具体的实现层service类上加上@Transactional 实现事务
9、SpringBoot自动配置原理?
在启动类上我们会打上: @SpringBootApplication 注解,它是一个组合标签,包括:
-
SpringBootConfuration ,本质是一个 Configuration ,代表Spring的配置类。
-
IOC自动扫描的注解@ComponentScan 会去扫描类上是否有:@Component ,@Respository ,@Service @Controller ,如果有,就会把这个类自动注册到Spring容器中。
-
EnableAutoConfiguration :就是启动SpringBoot自动配置的注解
在 @EnableAutoConfiguration 注解中,注册了一个选择器,其中有一个方法会去返回很多的自动配置的的全限定名,这些类会自动注册到Spring容器中,
++那它是怎么去找到这些所谓的自动配置类的呢?++
他会通过Spring的SPI接口,也就是通过一个SpringFactoryLoader去扫描 classpath中的所有的jar包中的 MET-INF/spring.factories 中的自动配置类,比如: DispatchServlert就对应了DispatchServlertAutoConfiguration自动配置类 , 它通过@Bean+方法的方式注册了一个 DispatchServlert 到Spring容器中了
10、SpringBoot启动流程?
1)开启秒表计时**。**记录应用启动的总耗时
2)starting监听器。这些监听器用于监听应用程序的启动过程,可以在不同的生命周期阶段执行特定操作
3)处理应用参数
4)加载环境对象
5)打印横幅
6)创建Spring容器对象:AnnotationConfigApplicationContext
7)容器刷新的前置工作
8)刷新容器 ,这里会执行spring的ioc属性容器的refrsh方法,Bean的加载,初始化等都在这个里面,Tomcat的启动也在这个方法里面。
9)刷新容器后置工作
10)秒表停止
11)started事件。通常用于通知监听器
12)调用runner
13)Running 监听器