Spring常见面试题
什么是 Spring 框架?Spring 框架有哪些主要模块?
Spring是一个轻量级的JavaEE解决方案,整合众多优秀的设计模式。
spring框架主要包括7个模块:
- Spring AOP 面向切面编程
- Spring ORM Hibernate|mybatis|JDO
- Spring Core 提供bean工厂 IOC
- Spring Dao JDBC支持
- Spring Context 提供了关于UI支持,邮件支持等
- Spring Web 提供了web的一些工具类的支持
- Spring MVC 提供了web mvc , webviews , jsp ,pdf ,export
使用 Spring 框架能带来哪些好处?
- 轻量:Spring 是轻量的,基本的版本大约 2MB
- 非入侵:Spring是一种非侵入式框架,它可以使应用程序代码对框架的依赖最小化。
- 解耦:Spring 通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们
- 容器:Spring 包含并管理应用中对象的生命周期和配置
- 支持AOP:Spring 支持面向切面的编程,并且把应用业务逻辑和系统服务分开
- 支持声明式事务处理:只需要通过配置就可以完成对事务的管理,而无须手动编程。
- 方便集成各种优秀框架:Spring不排斥各种优秀的开源框架,其内部Spring ORM提供了对各种优秀框架(如Hibernate、MyBatis等)的直接支持。
什么是控制反转(IOC)?什么是依赖注入?
将创建对象的权利由手动创建转换为Spring容器自动创建,管理和装配。将对象之间的依赖关系通过配置的方式注入到另一个对象中的过程。
请解释下 Spring 框架中的 IoC?
IOC 意为控制反转,普通javaEE创建对象是通过在程序中通过new创建,但是在Spring中,只需将设计好的类通过配置文件或注解的方式设定好,即可由Spring自动创建,对象的控制权由程序转移到了Spring,Spring通过工厂+反射生成对象,将对象放置在IOC容器中。
BeanFactory 和 ApplicationContext 有什么区别?
BeanFactory是Spring的顶级接口,只提供了最基础的容器功能。通过BeanFactory装载Bean是延时创建。
ApplicationContext是BeanFactory的高级实现,其中增加了许多资源加载,国际化,AOP,消息发送响应机制。通过ApplicationContext装载Bean是在Spring启动时立即创建。
Spring 有几种配置方式?
三种方式:xml,注解,java方式(配置类 @Bean)
如何用基于 XML 配置的方式配置 Spring?
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService" class="sun.service.ServiceImpl.UserServiceImpl"></bean> </beans>
如何用基于 Java 配置的方式配置 Spring?
@Configuration public class AppConfig{ @Bean public MyService myService() { return new MyServiceImpl(); } }
怎样用注解的方式配置 Spring?
1、在Spring配置文件中开启注解配置。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
</beans>
2、通过@Component(与@Service,@Controller,@Repository等价)注册到Spring容器,用@Autowired配合@Qualifier,或者@Resource,@Value 等注解进行注入。
<context:annotation-config>
和 <context:component-scan>
的区别?
<context:annotation-config>
是用于激活那些已经在spring容器里注册过的bean。
<context:component-scan>
除了具有<context:annotation-config>
的功能之外,<context:component-scan>
还可以在指定的package下扫描以及注册javabean 。
请解释 Spring Bean 的生命周期?
- 首先是实例化、属性赋值、初始化、销毁这 4 个大阶段;
- 再是初始化的具体操作,有 Aware 接口的依赖注入、BeanPostProcessor 在初始化前后的处理以及 InitializingBean 和 init-method 的初始化操作;
- 销毁的具体操作,有注册相关销毁回调接口,最后通过DisposableBean 和 destory-method 进行销毁。
Spring Bean 的作用域之间有什么区别?
Spring的 bean有5种作用域分别是:singleton、prototype、request、session和globalSession
singleton
全局只有一个实例
prototype
每次调用产生一个新的实例
在web使用的时候还有三个作用域,但是必须在web.xml中注册一个RequestContextListener , 目的是为了设置每次请求开始和结束都可以使spring得到相应的事件。
request
每次请求产生一个bean
session
每个用户session可以产生一个新的bean,不同用户之间的bean互相不影响
globalSession
作用和session类似,只是使用portlet的时候使用。
什么是 Spring inner beans?
在Spring 框架中,无论何时bean 被使用时,当仅被调用了一个属性。一个明智的做法是将这个bean声明为内部bean。内部bean 可以用setter 注入“属性”和构造方法注入“构造参数”的方式来实现。比如,在我们的应用程序中,一个Customer 类引用了一个Person 类,我们的要做的是创建一个Person的实例,然后在Customer 内部使用。
public class Customer{ private Person person; } public class Person{ private String name; private String address; private int age; }
<bean id="CustomerBean" class="com.leon.common.Customer"> <property name="person"> <bean class="com.leon.common.Person"> <property name="name" value="lokesh" /> <property name="address" value="India" /> <property name="age" value="34" /> </bean> </property> </bean>
Spring 框架中的单例 Beans 是线程安全的么?
prototype:每次请求都会创建新的Bean,线程之间不存在Bean的共享,因此是线程安全的。
singleton: 由于全局只有一个Bean,因此可能会出现线程安全问题。但是由于单例Bean,大都是无状态的Bean,也就是不会对Bean成员执行查询以外的操作,因此不会出现线程安全问题。
请举例说明如何在 Spring 中注入一个 Java Collection?
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService3" class="sun.service.ServiceImpl.UserServiceImpl3"> <property name="strings"> <array> <value>kelvin</value> <value>jack</value> <value>tony</value> </array> </property> <property name="set"> <set> <value>kelvin</value> <value>jack</value> <value>tony</value> </set> </property> <property name="list"> <list> <value>kelvin</value> <value>jack</value> <value>tony</value> </list> </property> <property name="map"> <map> <entry key="kelvin" value="23"></entry> <entry key="jack" value="21"></entry> <entry key="tony"> <value>46</value> </entry> </map> </property> </bean> </beans>
如何向 Spring Bean 中注入一个 Java.util.Properties?
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService3" class="sun.service.ServiceImpl.UserServiceImpl3"> <property name="prop"> <props> <prop key="kelvin">23</prop> <prop key="jack">45</prop> <prop key="tony">32</prop> </props> </property>
</bean> </beans>
请解释 Spring Bean 的自动装配?
是什么?
spring中提供了向Bean中自动注入依赖的功能,这个过程就是自动装配,当向bean中注入的内容非常多的时候,自动注入依赖的功能将极大的节省注入程序的时间。
有哪些类型?
基于xml:在<bean>标签内通过autowire=byType byName constructor 决定注入类型判断方式
<bean id="userDao“ class="com.spring.springioc.dao.impl.UserDaoImpl”/> <!--byType根据类型自动装配userDao--> <bean id="userService" autowire="byType" class="com.spring.springioc.service.impl.UserServiceImpl"/>
<bean id="userDao" class="com.spring.springioc.dao.impl.UserDaoImpl"/> <!--这个bean是userDao类型的,但不是要注入的类型--> <bean id="userDao2" autowire-candidate="false" class="com.spring.springioc.dao.impl.userDaoImpl"/> <bean id="userService" autowire="byType" class="com.spring.springioc.service.impl.userSericeImpl"/>
基于注解:@Autowired @Qualifier @Resource @Value
请解释自动装配模式的区别?
- no: 这是Spring框架的默认设置,在该设置下自动装配是关闭的,开发者需要自行在bean定义中用标签明确的设置依赖关系。
- byName: 该选项可以根据bean名称设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
- byType: 该选项可以根据bean类型设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的类型自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
- constructor: 造器的自动装配和byType模式类似,但是仅仅适用于与有构造器相同参数的bean,如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
- autodetect: 该模式自动探测使用构造器自动装配或者byType自动装配。首先,首先会尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在bean内部没有找到相应的构造器或者是无参构造器,容器就会自动选择byTpe的自动装配方式。
如何开启基于注解的自动装配?
- 引入配置文件中的
<bean>
下引入<context:annotation-config>
<beans> <context:annotation-config /> </beans>
- 在bean配置文件中直接引入
AutowiredAnnotationBeanPostProcessor
<beans> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> </beans>
请举例解释@Required 注解?请举例解释@Autowired 注解?请举例说明@Qualifier 注解?
@Required
检查属性是否被正确设置。
RequiredAnnotationBeanPostProcessor 是 Spring 中的后置处理用来验证被 @Required 注解的 bean 属性是否被正确的设置了。在使用 RequiredAnnotationBeanPostProcesso 来验证 bean 属性之前,首先要在 IoC 容器中对 其进行注册:
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotatio nBeanPostProcessor" />
但是如果没有属性被用 @Required 注解过的话,后置处理器会抛出一个 BeanInitializationException 异常。
@Autowired
@Autowired 注解对自动装配何时何处被实现提供了更多细粒度的控制。@Autowired 注解可 以像@Required 注解、构造器一样被用于在 bean 的设值方法上自动装配 bean 的属性,一个参数或者带有任意名称或带有多个参数的方法。
比如,可以在设值方法上使用@Autowired 注解来替代配置文件中的 元 素。当 Spring 容器在 setter 方法上找到@Autowired 注解时,会尝试用 byType 自动装配。
当然我们也可以在构造方法上使用@Autowired 注解。带有@Autowired 注解的构造方法意味着 在创建一个 bean 时将会被自动装配,即便在配置文件中使用 元素。
@Qualifier
@Qualifier 注解意味着可以在被标注 bean 的字段上可以自动装配。通常和@Autowired配合使用
构造方法注入和设值注入有什么区别?
设值注入的优势:
- 设值注入写法直观便于理解,使各种关系清晰明了。
- 设值注入可以避免因复杂的依赖实例化时所造成的性能问题。
- 设值注入的灵活性较强。
构造方法注入的优势:
- 构造方法注入可以决定依赖关系的注入顺序,有限依赖的优先注入。
- 对于依赖关系无需变化的Bean,构造方法注入使所有的依赖关系全部在构造器内设定,可避免后续代码对依赖关系的破坏。
- 构造方法注入中只有组建的创建者才能改变组建的依赖关系,更符合高内聚原则。
建议:
采用设值注入为主,构造注入为辅的注入策略。依赖关系无需变化时,尽量采用构造注入,而其它的依赖关系的注入,则考虑设值注入。
Spring 框架中有哪些不同类型的事件?
- 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
- 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
- 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
- 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
- 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。
FileSystemResource 和 ClassPathResource 有何区别?
在FileSystemResource 中需要给出spring-config.xml文件在你项目中的相对路径或者绝对路径。在ClassPathResource中spring会在ClassPath中自动搜寻配置文件,所以要把ClassPathResource 文件放在ClassPath下。
如果将spring-config.xml保存在了src文件夹下的话,只需给出配置文件的名称即可,因为src文件夹是默认。
简而言之,ClassPathResource在环境变量中读取配置文件,FileSystemResource在配置文件中读取配置文件。
Spring 框架中都用到了哪些设计模式?
- 代理模式—在AOP被用的比较多。
- 单例模式—在spring配置文件中定义的bean默认为单例模式。
- 原型模式—在spring的scope配置中配置prototype即为原型模式。原型模式相当于new,每次调用会产生新的对象。
- 工厂模式—BeanFactory用来创建对象的实例。
- 模板方法—用来解决代码重复的问题。
- 职责链模式—AOP底层拦截器链设计模式就是职责链模式。
什么是Spring AOP?
与OOP对比,面向切面,传统的OOP开发中的代码逻辑是至上而下的过程中会长生一些横切性问题,这些横切性的问题和我们的主业务逻辑关系不会散落在代码的各个地方,造成难以维护,AOP的编程思想就是把业务逻辑和横切的问题进行分离,从而达到解耦的目的,使代码的重用性和开发效率高(目的是重用代码,把公共的代码抽取出来)
AOP的应用场景有哪些呢?
- 日志记录
- 权限验证。
- 效率检查(个人在代码上,喜欢用注解+切面,实现校验,redis分布式锁等功能)。
- 声明式事务(spring 的声明式事务就是用AOP实现的)。
springAop的底层是怎样实现的?
- JDK动态代理。
- CGLIB代理。
spring AOP 代理是什么?默认使用jdk动态代理还是cglib?
AOP代理是一个由AOP框架创建用于在运行时实现切面的对象。默认使用要看条件,如果实现了接口的类,是使用jdk。如果没实现接口,就使用cglib。。
是编译时期进行织入,还是运行期进行织入?
运行期织入,生成字节码,再加载到虚拟机中,JDK是利用反射原理,CGLIB使用了ASM原理。
初始化时期织入还是获取对象时织入?
初始化的时候,已经将目标对象进行代理,放入到spring 容器中。
spring AOP 和 AspectJ的关系?
两者都是为了实现AOP这个目的而出现的技术,spring aop 参考 AspectJ编程风格。
简述一下Spring AOP的设计原理?
主要的分代理的创建和代理的调用两部分。
1)代理的创建
创建代理工厂:拦截器数组,目标对象接口数组,目标对象。
创建代理工厂时,默认会在拦截器数组尾部再增加一个默认拦截器 —— 用于最终的调用目标方法。
当调用 getProxy 方法的时候,会根据接口数量大余 0 条件返回一个代理对象(JDK or Cglib)。
注意:创建代理对象时,同时会创建一个外层拦截器,这个拦截器就是 Spring 内核的拦截器,用于控制整个 AOP 的流程。
2)代理的调用
当对代理对象进行调用时,就会触发外层拦截器。
外层拦截器根据代理配置信息,创建内层拦截器链。创建的过程中,会根据表达式判断当前拦截是否匹配这个拦截器。而这个拦截器链设计模式就是职责链模式。
当整个链条执行到最后时,就会触发创建代理时那个尾部的默认拦截器,从而调用目标方法,最后返回。
AOP有哪些可用的实现?
基于Java的主要AOP实现有:
AspectJ
Spring AOP
JBoss AOP
Spring中有哪些通知类型(advice)?
Before(前置通知): 连接点之前执行,除非抛异常,否则没有能力中断执行流(@Before 注解)
After(后置通知): 无论连接点是通过什么方式退出的(正常返回或者抛出异常)都会在结束后执行这些Advice(@After 注解)
After Retuning(返回通知): 在连接点正常结束之后(没有抛出异常正常返回)执行的Advice(@AfterReturning 注解)
After Throwing(异常通知): 如果方法通过抛出异常来退出的话,这个Advice就会被执行(@AfterThrowing 注解)
Around(环绕通知): 围绕连接点执行的Advice,就你一个方法调用(相对于合并前置后置)( @Around 注解)
在Spring AOP中关注点和横切关注点有什么不同?
关注点:我们在应用的模块中实现以解决特定业务问题的方法。比如库存管理、航运管理、用户管理等。
横切关注点:它是一个贯穿整个应用程序的关注点。像事务管理、权限、日志、安全等。
AOP中的名词定义?
-
切面(Aspect):指的就是通用功能的代码实现,比如我们上面演示的时间记录切面,日志切面,它们都是普通的Java类:
TimeRecordingAspect
和LogAspect
。 -
目标对象(Target):要被织入切面的对象,例子中的
CtripBookingService
,有了AOP,它们可以专注于核心业务逻辑代码了! -
切入点(Pointcut):定义通知应该切入到什么地方,Spring支持的切入点就是方法调用,切入点的定义可以使用正则表达式,用以描述什么类型的方法调用。
@Pointcut
就是用来定义切入点的。 -
通知(Advice):切面是一个类,而通知就是类里的方法以及这个方法如何织入到目标方法的方式(用
@AfterReturning
和@Around
标注的方法)。我们的例子中只展示了两类通知,根据织入到目标方法方式的不同,一共可以分为5种:- 前置通知(Before)
- 后置通知(AfterReturning)
- 异常通知(AfterThrowing)
- 最终通知(After)
- 环绕通知(Around)
- 织入(Weaving):AOP实现的过程,即将切面应用到目标对象,从而创建一个新的代理对象的过程,对于Spring来说,就是初始化Context中的对象时,完成织入操作。
spring的声明式事务是什么?该怎么配置?
spring的声明式事务是spring提供的一种事务处理机制,通过配置和aop织入的方式实现了事务,极大的简化了事务的开发。
1、配置dataSource。
2、配置事务管理器transactionManager。
3、配置事务通知advice。
4、配置事务织入<aop:config><aop:pointcut><aop:advisor>。
spring如何开启注解配置事务?
1.在spring的配置文件中引入<tx:>命名空间。
2.在配置文件中定义事务管理器。
3.开启spring提供的注解驱动(<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />)。
4.然后在dao层需要的类或接口前边加上注解。
5.设置事务属性。
@Transactional(
readOnly = false,
timeout = -1,
isolation = Isolation.DEFAULT,
rollbackFor = {ArithmeticException.class, IOException.class},
noRollbackFor = {},
propagation = Propagation.REQUIRES_NEW
)
propagation(事务传播特性)是什么?有哪几种配置?
在声明式事务中,要配置一个切面,就要用到propagation(事务传播特性),表示这些方法该怎么使用事务,一共有7种配置,默认是REQUIRED。
REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。
Isolation(事务隔离级别)有哪些?
1. Read uncommitted
无法保证并发事务出现的问题
2. Read committed(只能读取已提交的数据,可避免脏读)
一事务未提交时,不能去读取数据
3. Repeatable read(可避免脏读、不可重复读)
一事务未提交时,不能去读取数据
一事务在读取数据时,另一事物不能去修改数据
4. Serializable (事务串行化顺序执行)
不会出现并行事务,效率低下,一般不使用
什么是Spring的MVC框架?
spring mvc是一个基于mvc的轻量级web框架,它是spring框架的一个模块,无需整合,通过模型-视图-控制器分离实现解耦,用通过控制反转把业务对象和控制逻辑清晰地隔离。
SpringMvc的优点?
(1)可以支持各种视图技术而不仅仅局限于JSP:
(2)与Spring框架集成(如loC容器、AOP等):
(3)清晰的角色分配:前端控制器(dispatcherServlet),请求到处理器映射器(handlerMapping),处理器适配器(HandlerAdapter),视图解析器(ViewResolver)
(4)支特各种请求资源的映射策略。
Spring MVC的请求流程?
第一步:发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求HandlerMapping查找Handler,可以根据xml配置、注解进行查找
第三步:处理器映射器HandlerMapping向前端控制器返回Handler
第四步:前端控制器调用处理器适配器去执行Handler
第五步:处理器适配器去执行Handler
第六步:Handler执行完成给适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView。(ModelAndView是springmvc框架的一个底层对象,包括 Model和view)
第八步:前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)
第九步:视图解析器向前端控制器返回View
第十步:前端控制器进行视图渲染。视图渲染将模型数据(在ModelAndView对象中)填充到request域
第十一步:前端控制器向用户响应结果。
注解的处理器映射器和适配器是哪个?
注解映射器:RequestMappingHandlerMapping。
注解适配器:RequestMappingHandlerAdapter。
SpringMVC的主要组件?
(1)前端控制器DispatcherServlet(不需要程序员开发)
作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet就减少了其它组件之间的耦合度。
(2)处理器映射器HandierMapping(不需要程序员开发)
作用:根据请求的URL来查找Handler
(3)外理器适配器HandlerAdapter
注意:在编写Handler的时候要按照HandierAdapter要求的规刚去编写,这样活配服HandlerAdapter才可以正确的去执行Handler.
(4)外理器Handler(需要程序员开发)
(5)视图解析器ViewResolver(不需要程序品开发)
作用:进行视图的解析,根据视图逻辑名解析成直正的视图(view)
(6)视图View(需要程序员开发jsp)
View是一个接口。它的实现英支持不同的视图类型。
什么是DispatcherServiet?
Spring的MVC框架是围绕DispatcherServiet来设计的,它用来处理所有的HTTP请求和响应,接收请求、响应结果,相当于转发器,有了DispatcherServlet就减少了其它组件之间的耦合度。
什么是SpringMVC框架的控制器?
控制器提供一个访问应用程序的行为,此行为通常通过服务接口实现。控制器解析用户输入并将其转换为一个由视图呈现给用户的模型。Spring用一个非常抽象的方式实现了一个控制层,允许用户创建多种用途的控制器。。
SpringMVC的控制器是不是单例模式,如果是有什么问题,怎么解决?
默认是单例模式,
所以在多线程访问的时候有线程安全问题,
解决方案是不要用同步,在控制器里面不能写字段
为什么设计成单例模式?
①性能 (不用每次请求都创建对象)
②不需要多例(不要在控制器类中定义成员变量)。
注解原理是什么?
注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象。通过代理对象调用自定义注解的方法,会最终调用AnnotationinvocationHandler的invoke方法。
SpringMVC常用的注解有哪些?
@Controller
在SpringMVC中,controller主要负责处理前端控制器(DispatcherServlet )发过来的请求,经过业务逻辑层处理之后封装层一个model,并将其返回给view进行展示。
@RestController
功能类似@Controller,但是返回的是json格式数据。
@RequestMapping
用来处理请求地址映射的注解,它可以用于类上,也可以用于方法上。用于类上表示类中的方法都是以该地址作为父路径;用于方法上则表示请求该方法的路径。
该注解有6个属性,一般在项目中比较常用的有三个属性:value、method 和 produces。
value 属性:指定请求的实际地址,value 可以省略不写;
method 属性:指定请求的类型,主要有 GET、PUT、POST、DELETE,默认为 GET。等价于@GetMapping、@PostMapping……
produces 属性:指定返回内容类型,如 produces = “application/json; charset=UTF-8”。
@PathVariable
@PathVariable 注解主要用来获取 URL 参数,Spring Boot 支持 Restfull 风格的 URL,比如一个 GET 请求携带一个参数 id,我们将 id 作为参数接收,可以使用 @PathVariable 注解。如下:
**这里需要注意一个问题,如果想要 URL 中占位符中的 id 值直接赋值到参数 id 中,需要保证 URL 中的参数和方法接收参数一致,否则将无法接收。如果不一致的话,其实也可以解决,需要用@PathVariable 中的 value 属性来指定对应关系。**如下:
@RequestParam
@RequestParam 注解顾名思义,也是获取请求参数的,上面我们介绍了 @PathValiable 注解也是获取请求参数的,那么 @RequestParam 和 @PathVariable 有什么不同呢?
@PathValiable 是从 URL 模板中获取参数值, 即这种风格的 URL:
@RequestParam 是从 Request 里获取参数值,即这种风格的 URL:
对于@RequestParam 注解代码测试如下:
同样的@RequestParam 注解的value 属性是比较常用的,其作用和@PathVariable注解的value属性是一样的。此外@RequestParam 注解还有两个属性比较常用:
required 属性:true 表示该参数必须要传,否则就会报 404 错误,false 表示可有可无。
defaultValue 属性:默认值,表示请求中没有同名参数时的默认值。
@RequestBody
@RequestBody 注解用于接收前端传来的实体,接收参数也是对应的实体,比如前端通过 JSON 提交传来两个参数 username 和 password,此时我们需要在后端封装一个实体来接收。在传递的参数比较多的情况下,使用 @RequestBody 接收会非常方便。
SpingMVC中的控制器的注解一般用哪个,有没有别的注解可以替代?
一般用@Controller注解,可以使用@RestController,@RestController注解相当于@Controller+@ResponseBody。
SpringMvc中函数的返回值?
1. ModelAndView
以前前后端不分的情况下,ModelAndView 应该是最最常见的返回值类型了,现在前后端分离后,后端都是以返回 JSON 数据为主了。
后端返回 ModelAndView 这个比较容易理解,开发者可以在 ModelAndView 对象中指定视图名称,然后也可以绑定数据。
2. String
当 SpringMVC 方法的返回值为 String 类型时,也有几种不同情况。
2.1 逻辑视图名
返回 String 最常见的是逻辑视图名,这种时候一般利用默认的参数 Model 来传递数据,像下面这样 :
此时返回的 hello
就是逻辑视图名,之后会经过视图解析器解析,相当于"localhost:8080/hello.jsp",需要携带的数据放在 model 中。
2.2 重定向
也可以重定向:"redirect:/aa/index"
2.3 forward 转发
也可以 forward 转发:
2.4 真的是 String
当然,如果你真的想返回一个 String ,此时只要在方法上加上 @ResponseBody 注解即可,或者 组合注解 @RestController(等价于@Controller+@ResponseBody)
4. JSON
返回 JSON 算是最最常见的了,现在前后端分离的趋势下,大部分后端只需要返回 JSON 即可,那么常见的 List 集合、Map,实体类等都可以返回,这些数据配置使用Jackson 或者 fastJson,就可以自动返回 JSON 了
SpringMvc中的转发和重定向?
转发: return:“hello”
重定向 :return:“redirect:hello.jsp”
SpringMvc的工作流程图?
springboot的启动流程及其自动配置原理?
启动:
每个SpringBoot程序都有一个主入口,也就是main方法,main里面调用SpringApplication.run()启动整个spring-boot程序,
该方法所在类需要使用@SpringBootApplication注解,@SpringBootApplication中含有三个主要注解:
@SpringBootConfiguration:相当于@Configuration,表明该类为配置类
@ComponentScan:组件扫描,可自动发现和装配Bean,默认扫描SpringApplication的run方法里的Booter.class所在的包路径下文件,所以最好将该启动类放到根包路径下
@EnableAutoConfiguration:启用SpringBoot 的自动配置机制,其中@EnableAutoConfiguration的注解有:
@Import({AutoConfigurationImportSelector.class});其AutoConfigurationImportSelector实现了ImportSelector接口中的selectImports()方法;该方法主要用于获取所有符合条件的类的全限定类名,会再SpringBoot启动的时候把spring.factories(文件都是配置类全路径名称)这些配置类加载到 IoC 容器中。
进入run方法
6.最后调用refreshContext(context)方法。然后返回。
什么是 Spring Boot?
Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。
Spring Boot 有哪些优点?
Spring Boot 主要有如下优点:
- 容易上手,提升开发效率,为 Spring 开发提供一个更快、更广泛的入门体验。
- 开箱即用,远离繁琐的配置。
- 提供了一系列大型项目通用的非业务性功能,例如:内嵌服务器、安全管理、运行数据监控、运行状况检查和外部化配置等。
- 没有代码生成,也不需要XML配置。
- 避免大量的 Maven 导入和各种版本冲突。
Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:
- @SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。
- @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。
- @ComponentScan:Spring组件扫描。
Spring Boot 自动配置原理是什么?
注解 @EnableAutoConfiguration, @Configuration, @ConditionalOnClass 就是自动配置的核心,
@EnableAutoConfiguration 给容器导入META-INF/spring.factories 里定义的自动配置类。
@ConditionalOnClass 筛选有效的自动配置类。
每一个自动配置类结合对应的 xxxProperties.java 读取配置文件进行自动配置功能
Spring Boot有哪几种配置?
1)properties文件;
2)YAML文件;
什么是 YAML?
YAML 是一种具有分层配置结构的配置文件。与properties文件相比,如果我们想要在配置文件中添加复杂的属性,YAML 文件就更加结构化,而且更少混淆。
YAML 配置的优势在哪里 ?
- 配置有序,在一些特殊的场景下,配置有序很关键
- 支持数组,数组中的元素可以是基本数据类型也可以是对象
- 简洁
Spring Boot 是否可以使用 XML 配置 ?
Spring Boot 推荐使用 Java 配置而非 XML 配置,但是 Spring Boot 中也可以使用 XML 配置,通过 @ImportResource 注解可以引入一个 XML 配置。
如何在自定义端口上运行 Spring Boot 应用程序?
为了在自定义端口上运行 Spring Boot 应用程序,您可以在application.properties 中指定端口。server.port = 8090
如何实现 Spring Boot 应用程序的安全性?
可以使用 spring-boot-starter-security 或者Shiro依赖。
比较一下 Spring Security 和 Shiro 各自的优缺点 ?
- Spring Security 是重量级;Shiro 则是轻量级
- Spring Security 概念复杂,配置繁琐;Shiro 概念简单、配置简单
- Spring Security 功能强大;Shiro 功能简单
什么是 RabbitMQ?
RabbitMQ是支持持久化消息队列的消息中间件。应用在上下游的层次级业务逻辑中,上级业务逻辑相当于生产者发布消息,下级业务逻辑相当于消费者接受到消息并且消费消息。
什么是 Apache Kafka?
Apache Kafka 是一个分布式发布 - 订阅消息系统。它是一个可扩展的,容错的发布 - 订阅消息系统,它使我们能够构建分布式应用程序。这是一个 Apache 顶级项目。Kafka 适合离线和在线消息消费。
Spring Boot 中的 starter 到底是什么 ?
首先,这个 Starter 并非什么新的技术点,基本上还是基于 Spring 已有功能来实现的。首先它提供了一个自动化配置类,一般命名为 XXXAutoConfiguration ,在这个配置类中通过条件注解来决定一个配置是否生效(条件注解就是 Spring 中原本就有的),然后它还会提供一系列的默认配置,也允许开发者根据实际情况自定义相关配置,然后通过类型安全的属性注入将这些配置属性注入进来,新注入的属性会代替掉默认属性。正因为如此,很多第三方框架,我们只需要引入依赖就可以直接使用了。当然,开发者也可以自定义 Starter
开启 Spring Boot 特性有哪几种方式?
1)继承spring-boot-starter-parent项目
2)导入spring-boot-dependencies项目依赖
Spring Boot 打成的 jar 和普通的 jar 有什么区别 ?
Spring Boot 项目最终打包成的 jar 是可执行 jar ,这种 jar 可以直接通过 java -jar xxx.jar 命令来运行,这种 jar 不可以作为普通的 jar 被其他项目依赖,即使依赖了也无法使用其中的类。
Spring Boot 的 jar 无法被其他项目依赖,主要还是他和普通 jar 的结构不同。普通的 jar 包,解压后直接就是包名,包里就是我们的代码,而 Spring Boot 打包成的可执行 jar 解压后,在 \BOOT-INF\classes 目录下才是我们的代码,因此无法被直接引用。如果非要引用,可以在 pom.xml 文件中增加配置,将 Spring Boot 项目打包成两个 jar ,一个可执行,一个可引用。
运行 Spring Boot 有哪几种方式?
1)打包用命令或者放到容器中运行
2)用 Maven/ Gradle 插件运行
3)直接执行 main 方法运行
Spring Boot 需要独立的容器运行吗?
可以不需要,内置了 Tomcat/ Jetty 等容器。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
1111111111111111?
。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?