Spring面试题

一、spring基础

1.什么是 Spring?它有哪些主要的功能和特点?

  • Spring 是一个开源的企业级应用程序框架,最初是为了解决企业级开发中复杂性和耦合性而创建的。Spring 框架可以帮助开发人员快速构建复杂的企业级应用程序,它提供了一组强大的功能和工具,以增强开发人员的生产力和代码的可维护性。

1.1Spring 框架的主要功能和特点包括:

  • IOC(Inversion of Control)控制反转: IOC 是 Spring 框架的核心,它通过依赖注入(Dependency Injection)实现了对象之间的解耦。通过将对象之间的依赖关系交给 Spring 容器来管理,开发人员可以将精力集中在业务逻辑的实现上,而不是关注对象之间的创建和管理。

  • AOP(Aspect Oriented Programming)面向切面编程: AOP 是 Spring 框架的另一个重要特点,它允许开发人员在不改变原有业务逻辑的情况下,通过定义切面来增强系统的功能和性能。将与核心业务无关的代码独立抽取出来,形成一个独立的组件,然后以横向交叉的方式应用到业务流程当中的过程被称为AOP。

  • MVC(Model-View-Controller)架构: Spring 框架提供了一个强大的 MVC 框架,它可以帮助开发人员快速构建 Web 应用程序。Spring MVC 采用了标准的 MVC 架构模式,将应用程序分成模型、视图和控制器三层,开发人员可以更好地组织代码、实现业务逻辑和展示数据。

  • JDBC 和 ORM 支持: Spring 框架提供了对 JDBC 和 ORM 框架的支持,可以帮助开发人员更好地管理数据库和持久化数据。Spring 框架提供了一组简单易用的 API 和工具,可以帮助开发人员轻松地访问数据库、执行 SQL 查询、实现事务管理等。

  • 集成第三方框架和组件: Spring 框架可以集成许多其他的开源框架和组件,如 Hibernate、MyBatis、Struts、JSF、Quartz 等,可以帮助开发人员更好地实现业务逻辑和增强系统的功能。

  • 总之,Spring 框架是一个功能强大、灵活、可扩展和易于使用的框架,它可以帮助开发人员快速构建复杂的企业级应用程序,并提高代码的可维护性和可读性。

2.Spring 的核心模块有哪些?它们分别用来做什么?

  • Spring 框架的核心模块包括:

  • 1.Spring Core: Spring Core 是 Spring 框架的核心模块,它提供了 IoC(Inversion of Control)容器的实现和基本的依赖注入功能。通过 Spring Core,开发人员可以将对象之间的依赖关系交给 Spring 容器来管理,从而实现代码的松耦合和更好的可维护性。

  • 2.Spring Context: Spring Context 是建立在 Spring Core 基础之上的模块,它提供了更丰富的功能和特性,如国际化支持、事件处理、资源加载、环境配置等。通过 Spring Context,开发人员可以更方便地访问容器中的 bean,以及在应用程序中使用 Spring 框架的各种特性和工具。

  • 3.Spring AOP: Spring AOP 是 Spring 框架的另一个核心模块,它提供了面向切面编程(Aspect Oriented Programming)的支持。通过 Spring AOP,开发人员可以将系统中的横切关注点(如事务管理、日志记录、安全控制等)从主要业务逻辑中分离出来,从而提高系统的可维护性和可扩展性。

  • 4.Spring DAO: Spring DAO 是 Spring 框架提供的数据访问对象(Data Access Object)模块,它提供了对 JDBC 和 ORM 框架的支持。通过 Spring DAO,开发人员可以更方便地访问和操作数据库,实现数据持久化和事务管理。

  • 5.Spring ORM: Spring ORM 是 Spring 框架提供的对象关系映射(Object Relational Mapping)模块,它提供了对 ORM 框架的支持,如 Hibernate、MyBatis 等。通过 Spring ORM,开发人员可以更方便地使用 ORM 框架,简化持久化操作的编写和维护。

  • 6.Spring Web: Spring Web 是 Spring 框架提供的 Web 开发模块,它提供了对 Spring MVC、WebSocket、REST 等的支持。通过 Spring Web,开发人员可以更方便地开发 Web 应用程序,实现请求处理、视图渲染、路由控制等功能。

  • 总之,Spring 框架的核心模块提供了丰富的功能和特性,可以帮助开发人员更方便地构建复杂的企业级应用程序。开发人员可以根据实际需求选择适当的模块和工具来使用,从而提高开发效率和代码质量。

3.什么是控制反转(IoC)和依赖注入(DI)?它们有什么作用?

  • 控制反转(Inversion of Control,IoC)和依赖注入(Dependency Injection,DI)是 Spring 框架的两个核心概念。

  • 控制反转(IoC) 是一种设计模式,它将对象之间的依赖关系交给容器来管理,而不是由对象自己来创建和维护。这样做的好处是降低了对象之间的耦合度,提高了代码的可维护性和可测试性。

  • 依赖注入(DI) 是 IoC 的一种实现方式,它是指容器在创建对象时,自动将依赖对象注入到对象中,从而完成依赖关系的建立。在 Spring 框架中,依赖注入可以通过构造方法注入、Setter 方法注入、注解注入等方式来实现。

  • IoC 和 DI 的作用是:

  • 1.降低代码的耦合度: 通过将对象之间的依赖关系交给容器来管理,可以将对象之间的耦合度降到最低,从而提高了代码的可维护性和可扩展性。

  • 2.提高代码的可测试性: 在面向对象编程中,对象之间的依赖关系往往会影响到代码的测试和调试。通过 IoC 和 DI,可以将依赖关系解耦,使得代码的测试和调试更加容易和灵活。

  • 3.提高代码的重用性: 通过将对象的创建和依赖关系的管理交给容器来处理,可以使得代码更加简洁和灵活,从而提高了代码的重用性和可读性。

  • 总之,IoC 和 DI 是 Spring 框架的核心概念,也是面向对象编程中的重要思想。通过使用 IoC 和 DI,开发人员可以更加方便地管理对象之间的依赖关系,提高代码的可维护性、可测试性和可扩展性。

4.Spring 的 DI 有哪几种方式?它们的优缺点是什么?

  • Spring 的 DI(依赖注入)主要有三种方式:

  • 1.构造函数注入(Constructor Injection): 通过构造函数将依赖的对象注入到目标对象中。

  • 2.Setter 方法注入(Setter Injection): 通过 Setter 方法将依赖的对象注入到目标对象中。

  • 3.字段注入(Field Injection): 通过直接注入属性值或使用 @Autowired 注解注入依赖对象。

  • 它们的优缺点如下:

  • 1.构造函数注入的优点是能够保证目标对象在创建时就已经注入了所有的依赖对象,从而保证对象的完整性和稳定性;缺点是代码量较多,当依赖对象过多时,构造函数的参数列表会变得很长。

  • 2.Setter 方法注入的优点是可以很方便地注入依赖对象,代码量相对较少,适合对目标对象进行动态修改;缺点是如果某个依赖对象没有被注入,会导致目标对象无法正常工作。

  • 3.字段注入的优点是代码量最少,适合简单场景;缺点是没有明确的注入时机,容易出现空指针异常等问题,而且使用注解方式容易使得代码耦合度变高。

  • 总的来说,构造函数注入和 Setter 方法注入是比较常用的方式,构造函数注入适合依赖关系比较复杂的场景,而 Setter 方法注入则适合依赖对象较少、对象需要动态修改的场景。字段注入虽然代码量最少,但是容易出现问题,一般不推荐使用。

5.什么是面向切面编程(AOP)?Spring 是如何支持 AOP 的?

  • 面向切面编程(Aspect-Oriented Programming,AOP)是一种编程范式,它主要是针对业务逻辑中的横切关注点进行抽象和封装,从而使得这些横切关注点可以被重复使用和管理。AOP 可以将通用的横切关注点从业务逻辑中剥离出来,形成一个独立的模块,从而提高代码的重用性、可维护性和可扩展性。

  • 在 Spring 框架中,支持 AOP 的主要功能是通过 Spring AOP 模块来实现的。Spring AOP 基于代理模式和注解机制实现,它可以在不修改原有代码的情况下,将通用的横切关注点织入到业务逻辑中。

  • 具体来说,Spring AOP 支持以下几种通知类型:

  • 前置通知(Before Advice): 在目标方法执行之前执行的通知。

  • 后置通知(After Advice): 在目标方法执行之后执行的通知,无论方法是正常返回还是抛出异常,该通知都会执行。

  • 返回通知(After Returning Advice): 在目标方法正常返回时执行的通知。

  • 异常通知(After Throwing Advice): 在目标方法抛出异常时执行的通知。

  • 环绕通知(Around Advice): 在目标方法执行之前和之后都可以执行的通知,可以控制目标方法的执行过程。

  • Spring AOP 还支持切点(Pointcut)和切面(Aspect)的概念。切点用于定义哪些方法需要被织入通知,切面则是将通知和切点结合起来,形成一个完整的 AOP 实现。

  • 总之,Spring AOP 是 Spring 框架中的一个重要功能模块,它通过代理模式和注解机制实现了 AOP 的主要功能,可以提高代码的重用性、可维护性和可扩展性,从而简化了开发人员的工作。

6.Spring 中的 Bean 是什么?它们的作用是什么?Bean 的生命周期是怎样的?

  • 在 Spring 框架中,Bean 是指在 Spring 容器中被管理的对象。Bean 可以是任何 Java 对象,包括 POJO(Plain Old Java Object,普通的 Java 对象)、JavaBean、EJB(Enterprise JavaBean,企业级 JavaBean)等。

  • Bean 的作用是提供一种对象实例化和管理的机制,使得开发人员可以更加灵活和方便地使用对象,而不必关心对象的创建和销毁过程。

  • Bean 的生命周期可以分为以下几个阶段:

  • 1.实例化: Spring 容器根据配置文件中的定义,使用反射机制创建一个 Bean 的实例。

  • 2.属性注入: Spring 容器通过调用 Bean 的 set 方法或者直接访问 Bean 的属性,将配置文件中定义的属性值注入到 Bean 实例中。

  • 3.初始化: 在 Bean 实例创建完成并注入属性之后,Spring 容器会调用 Bean 的初始化方法,以便让开发人员进行一些自定义的初始化操作。

  • 4.使用: Bean 初始化完成后,就可以在应用程序中使用该 Bean 了。

  • 5.销毁: 当应用程序关闭或者 Spring 容器销毁时,会调用 Bean 的销毁方法,以便让开发人员进行一些自定义的清理操作。

  • Spring 中的 Bean 的生命周期可以通过 BeanPostProcessor 和 BeanFactoryPostProcessor 接口来进行自定义处理。BeanPostProcessor 接口可以在 Bean 的初始化前后进行一些自定义处理,而 BeanFactoryPostProcessor 接口可以在 Bean 工厂实例化 Bean 之前对 Bean 的定义进行一些修改。

  • 总之,Spring 中的 Bean 是指在 Spring 容器中被管理的对象,它们提供了一种对象实例化和管理的机制,简化了开发人员的工作。Bean 的生命周期可以通过 BeanPostProcessor 和 BeanFactoryPostProcessor 接口来进行自定义处理。

7.Spring 中的 Bean 作用域有哪些?各自的作用是什么?

  • Spring 中的 Bean 作用域决定了 Bean 实例的创建和销毁方式,Spring 提供了以下五种 Bean 作用域:

  • 1.singleton: 单例模式,即在整个应用程序中只创建一个 Bean 实例,Spring 容器会在启动时创建该 Bean 实例并在应用程序关闭时销毁该 Bean 实例。

  • 2.prototype: 原型模式,即每次从容器中获取 Bean 实例时都会创建一个新的实例,Spring 容器不会对该 Bean 实例进行管理,由开发人员负责 Bean 的生命周期。

  • 3.request: 每个 HTTP 请求创建一个 Bean 实例,即同一个 HTTP 请求中多次获取该 Bean 实例会返回同一个对象,不同的 HTTP 请求会创建不同的 Bean 实例。该作用域只在 Web 应用程序上下文中有效。

  • 4.session: 每个 HTTP Session 创建一个 Bean 实例,即同一个 HTTP Session 中多次获取该 Bean 实例会返回同一个对象,不同的 HTTP Session 会创建不同的 Bean 实例。该作用域只在 Web 应用程序上下文中有效。

  • 5.global session: 该作用域只在基于 Portlet 的 Web 应用程序上下文中有效,它表示一个全局的 Portlet Session,每个 Portlet Session 创建一个 Bean 实例,即同一个 Portlet Session 中多次获取该 Bean 实例会返回同一个对象,不同的 Portlet Session 会创建不同的 Bean 实例。

  • 不同作用域的 Bean 实例对应不同的使用场景,例如单例模式的 Bean 实例通常用于那些状态不会发生改变的对象,而原型模式的 Bean 实例则适用于那些需要频繁创建和销毁的对象。在 Web 应用程序中,request、session 和 global session 作用域的 Bean 实例可以实现在不同的用户请求之间共享数据的目的。

8.Spring 中的 ApplicationContext 和 BeanFactory 有什么区别?它们之间的关系是什么?

  • ApplicationContext 和 BeanFactory 都是 Spring 框架中用于管理 Bean 的容器,它们之间的关系是 ApplicationContext 是 BeanFactory 的子接口,ApplicationContext 继承了 BeanFactory 的所有功能,并且提供了更多的功能。

  • 具体来说,BeanFactory 是 Spring 框架中最基本的容器,它负责管理 Bean 的生命周期和依赖关系,但是它的功能比较简单,只有在第一次使用时才会初始化 Bean,这样可能导致在应用程序运行过程中出现 Bean 实例化速度过慢的问题。

  • 相比之下,ApplicationContext 是一个更高级的容器,它在 BeanFactory 的基础上提供了更多的功能,例如国际化支持、事件传播、Bean 生命周期管理等。ApplicationContext 可以预先初始化所有的 Bean,以提高应用程序的启动速度,并且它支持多种方式的配置文件,例如 XML 文件、Java 配置文件、注解等。

  • 因此,一般情况下,推荐使用 ApplicationContext 作为 Spring 应用程序的容器,除非应用程序需要更细粒度的控制,才会使用 BeanFactory。

ApplicationContext 示例:


    @Configuration
    public class MyApp {
        public static void main(String[] args) {
            ApplicationContext context = new AnnotationConfigApplicationContext(MyApp.class);
            MyBean myBean = context.getBean(MyBean.class);
            myBean.sayHello();
        }
    
        @Bean
        public MyBean myBean() {
            MyBean bean = new MyBean();
            bean.setMessage("Hello Spring!");
            return bean;
        }
    }

    public class MyBean {
        private String message;
    
        public void setMessage(String message) {
            this.message = message;
        }
    
        public void sayHello() {
            System.out.println(message);
        }
    }

在这个示例中,我们使用注解方式配置 Spring ApplicationContext,即使用 @Configuration 注解将 MyApp 类标记为配置类,然后使用 @Bean 注解将 MyBean 类标记为 Bean,并将其实例化并设置 message 属性值。在 main 方法中,我们使用 ApplicationContext 获取 MyBean 的实例,并调用 sayHello 方法输出 message 属性值。

BeanFactory 示例:

    @Configuration
    public class MyApp {
        public static void main(String[] args) {
            BeanFactory factory = new AnnotationConfigApplicationContext(MyApp.class);
            MyBean myBean = factory.getBean(MyBean.class);
            myBean.sayHello();
        }
    
        @Bean
        public static PropertySourcesPlaceholderConfigurer properties() {
            PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
            configurer.setLocation(new ClassPathResource("application.properties"));
            return configurer;
        }
    }

    public class MyBean {
        @Value("${message}")
        private String message;
    
        public void sayHello() {
            System.out.println(message);
        }
    }

在这个示例中,我们使用注解方式配置 Spring BeanFactory,即使用 @Configuration 注解将 MyApp 类标记为配置类,并使用 @Value 注解将 message 属性值注入到 MyBean 实例中。同时,我们还使用 PropertySourcesPlaceholderConfigurer 将 application.properties 文件中的属性值加载到 Spring 的环境变量中。在 main 方法中,我们使用 BeanFactory 获取 MyBean 的实例,并调用 sayHello 方法输出 message 属性值。

需要注意的是,使用注解方式配置 Spring ApplicationContext 和 BeanFactory 通常需要在启动类中加上 @ComponentScan 注解来扫描并自动装配 Bean。这里的示例代码未涉及到自动装配,仅供参考。

9.Spring 中的注解有哪些?它们各自的作用是什么?

  • 1.@Component: 用于标注一个类为组件,通常是业务逻辑类。

  • 2.@Service: 用于标注一个类为服务,通常是业务逻辑类,它比 @Component 更加具体。

  • 3.@Repository: 用于标注一个类为数据访问组件,通常是 DAO 类。

  • 4.@Controller: 用于标注一个类为控制器,通常是 Spring MVC 的控制器类。

  • 5.@RestController: 用于标注一个类为 RESTful 风格的控制器,它会自动将方法返回的数据转换为 JSON 或 XML 格式的响应。

  • 6.@Autowired: 用于自动装配一个 Bean 实例,它可以标注在构造方法、属性、方法、参数上,Spring 容器会自动搜索匹配的 Bean 并注入。

  • 7.@Qualifier: 与 @Autowired 配合使用,用于指定 Bean 的名称,当容器中存在多个类型相同的 Bean 时,可以使用该注解指定具体的 Bean。

  • 8.@Value: 用于注入属性值,支持 SpEL 表达式。

  • 9.@Configuration: 用于标注一个类为配置类,通常与 @Bean 注解一起使用,用于配置 Bean 实例。

  • 10.@Bean: 用于声明一个 Bean 实例,通常与 @Configuration 注解一起使用,用于配置 Bean 实例的创建和属性注入。

  • 11.@Scope: 用于指定 Bean 的作用域,支持 singleton、prototype、request、session 和 global session 五种作用域。

  • 12.@PostConstruct: 用于标注一个方法,在 Bean 创建完成后自动调用该方法。

  • 13.@PreDestroy: 用于标注一个方法,在 Bean 销毁之前自动调用该方法。

  • 14.@Transactional: 用于标注一个方法或类为事务方法,Spring 将自动管理该方法的事务。

10.如何在 Spring 中进行单元测试?Spring Test 模块中有哪些常用的注解和类?

  • 在 Spring 中进行单元测试可以使用 Spring Test 模块来简化测试过程。Spring Test 模块提供了一系列注解和类,方便测试 Spring 应用程序的各个层次。

  • 以下是 Spring Test 模块中常用的注解和类:

  • 1.@RunWith(SpringRunner.class): 用于指定运行测试的类,通常与@SpringBootTest 或 @ContextConfiguration 一起使用。

  • 2.@SpringBootTest: 用于启动整个 Spring 应用程序上下文,并自动装配所需的 Bean。

  • 3.@ContextConfiguration: 用于指定测试时需要加载的 Spring 配置文件或类。

  • 4.@Autowired: 用于自动装配 Bean。

  • 5.@MockBean: 用于创建一个 Mock 对象,并将其注入到 Spring 应用程序上下文中。

  • 6.@Test: JUnit 的测试方法注解。

  • 7.@Transactional: 用于开启事务,以便测试中的操作能够回滚。

11.Spring 支持哪些类型的事务管理器?它们之间的区别是什么?

  • 1.DataSourceTransactionManager: 用于管理 JDBC 数据源事务。

  • 2.JpaTransactionManager: 用于管理 JPA 实体管理器的事务。

  • 3.HibernateTransactionManager: 用于管理 Hibernate SessionFactory 的事务。

  • 4.JtaTransactionManager: 用于管理 JTA 分布式事务。

  • 这些事务管理器之间的区别在于它们管理的数据访问技术不同,而且对于不同的数据访问技术,Spring 提供了特定的事务管理器来处理事务。例如,DataSourceTransactionManager 是用于管理 JDBC 数据源事务的事务管理器,它与 JPA 或 Hibernate 不兼容。如果应用程序同时使用了多种数据访问技术,可以选择 JtaTransactionManager 来管理分布式事务。

  • 除了这些内置的事务管理器外,Spring 还支持自定义事务管理器。我们可以实现 PlatformTransactionManager 接口,然后将其注册到 Spring 应用程序上下文中,以便在事务管理时使用。

  • 需要注意的是,不同的事务管理器在配置上可能存在一些差异,比如需要指定数据源或实体管理器等。同时,不同的事务管理器还可能支持不同的事务隔离级别和传播行为。因此,在选择事务管理器时,需要根据应用程序的需求选择适当的事务管理器,并仔细查阅其文档以了解其详细的配置和使用方式。

12.Spring 中如何处理异常?它有哪些常用的异常处理机制?

  • 1.使用 try-catch 块处理异常: 在 Spring 应用程序中使用 try-catch 块处理异常与普通的 Java 应用程序中处理异常的方式相同。我们可以在方法中使用 try-catch 块捕获异常,然后根据需要处理它们。这种方式非常简单,但也非常繁琐,需要在每个可能抛出异常的方法中添加 try-catch 块。

  • 2.使用 Spring 的异常层次结构: Spring 提供了一个完整的异常层次结构,它包含了许多常见的异常类型。这些异常类型继承自 Spring 的通用异常类,可以通过捕获通用异常类来捕获所有 Spring 异常。此外,Spring 还提供了一些异常处理器,可以在应用程序中统一处理异常,而不需要在每个方法中使用 try-catch 块。这种方式可以提高代码的可读性和可维护性。

  • 3.使用 Spring AOP 实现异常处理: Spring AOP 可以用于在应用程序中捕获异常,并在出现异常时执行指定的操作。通过在代码中声明切点和通知,可以将异常处理逻辑与应用程序的业务逻辑分离。这种方式可以在保持代码清晰和可读的同时,实现对异常的统一处理。

  • 在 Spring 中常用的异常处理机制包括:

  • 1.@ExceptionHandler 注解: 使用 @ExceptionHandler 注解可以在控制器层面处理异常。当控制器方法抛出指定类型的异常时,Spring 会自动调用带有 @ExceptionHandler 注解的方法,从而处理异常。

  • 2.@ControllerAdvice 注解: 使用 @ControllerAdvice 注解可以在全局范围内处理异常。通过在应用程序中创建一个或多个带有 @ControllerAdvice 注解的类,可以捕获所有控制器层面抛出的异常,并对它们进行统一处理。

  • 3.SimpleMappingExceptionResolver 类: SimpleMappingExceptionResolver 类可以用于在应用程序中处理异常。它可以将指定的异常类型映射到指定的视图,从而实现异常处理和错误页面显示。

  • 需要注意的是,Spring 的异常处理机制并不会取代 Java 的异常处理机制。它只是为 Java 异常机制提供了更加方便的使用方式,使得异常处理更加简单和灵活。

13.Spring 中的资源访问和处理有哪些方式?它们各自的作用是什么?

  • Classpath 资源访问:可以通过使用 ClassPathResource 类或者 @Value 注解来获取 classpath 中的资源。例如:
Resource resource = new ClassPathResource("config.properties");
@Value("classpath:config.properties")
private Resource configFile;
  •  文件系统资源访问:可以通过使用 FileSystemResource 类来获取文件系统中的资源。例如:
Resource resource = new 
FileSystemResource("/path/to/file.txt");
  • 3.URL 资源访问:可以通过使用 UrlResource 类来获取 URL 中的资源。例如:
Resource resource = new UrlResource("http://example.com/image.png");
  • 4.ServletContext 资源访问:可以通过使用 ServletContextResource 类来获取 Web 应用程序上下文中的资源。例如:
Resource resource = new ServletContextResource(servletContext, "/WEB-INF/config.xml");
  • 5.资源加载器(ResourceLoader):可以通过在应用程序中注入 ResourceLoader Bean 来获取资源,同时支持 classpath、文件系统、URL 和 ServletContext 资源访问。例如:
@Autowired 
private ResourceLoader resourceLoader; 

public void loadResource() { Resource resource = resourceLoader.getResource("classpath:config.properties"); 
// ... 
}
  • 6.资源访问器(ResourcePatternResolver):可以通过在应用程序中注入 ResourcePatternResolver Bean 来根据指定的模式获取多个资源,例如使用通配符进行匹配。例如:
@Autowired
private ResourcePatternResolver resourcePatternResolver;

public void loadResources() throws IOException {
    Resource[] resources = resourcePatternResolver.getResources("classpath:config/*.xml");
    // ...
}

这些资源访问和处理方式可以用于加载和处理配置文件、图片、文本文件等各种类型的资源。

14.Spring 中如何使用国际化资源和消息?它有哪些实现方式?

在 Spring 中,可以通过国际化资源和消息实现应用程序的国际化,以便让应用程序支持多种语言和地区。Spring 提供了多种实现方式,常用的包括:

  • 1.基于 Java Properties 文件的实现方式: 可以将不同语言或地区的文本信息保存在不同的 Java Properties 文件中,然后在应用程序中使用 ResourceBundle 类或者 MessageSource 接口来加载并获取资源信息。例如:

    // 使用 ResourceBundle 加载资源
    ResourceBundle bundle = ResourceBundle.getBundle("messages", Locale.US);
    String message = bundle.getString("greeting");

    // 使用 MessageSource 加载资源
    @Autowired
    private MessageSource messageSource;

    public void showMessage() {
        String message = messageSource.getMessage("greeting", null, Locale.US);
        // ...
    }
  • 2.基于 XML 文件的实现方式: 可以将不同语言或地区的文本信息保存在不同的 XML 文件中,然后在应用程序中使用 ResourceBundleMessageSource 或者 ReloadableResourceBundleMessageSource 类来加载并获取资源信息。例如:
   // 使用 ResourceBundleMessageSource 加载资源
    @Autowired
    private ResourceBundleMessageSource messageSource;

    public void showMessage() {
        String message = messageSource.getMessage("greeting", null, Locale.US);
        // ...
    }

    // 使用 ReloadableResourceBundleMessageSource 加载资源
    @Autowired
    private ReloadableResourceBundleMessageSource messageSource;

    public void showMessage() {
         String message = messageSource.getMessage("greeting", null, Locale.US);
        // ...
    }
  • 3.基于数据库的实现方式: 可以将不同语言或地区的文本信息保存在数据库中,然后在应用程序中使用 MessageSource 接口的实现类来加载并获取资源信息。例如:
    @Autowired
    private MessageSource messageSource;

    public void showMessage() {
        String message = messageSource.getMessage("greeting", null, Locale.US);
        // ...
    }

 以上三种实现方式都可以实现应用程序的国际化,选择哪种方式主要根据实际需求和情况来定

15.Spring 中的事件机制是什么?它的作用是什么?如何使用它实现事件监听和发布?

Spring 中的事件机制是一种基于观察者模式的实现,通过监听事件的发布和处理,来实现不同组件之间的解耦。事件机制的作用是允许不同组件之间通过事件来进行通信,实现组件之间的松耦合。

在 Spring 中,事件机制的实现依赖于两个核心接口:ApplicationEventPublisher 和 ApplicationListener。其中,ApplicationEventPublisher 接口定义了事件发布的方法,而 ApplicationListener 接口则定义了事件监听的方法。具体实现步骤如下:

  • 1.定义事件类: 通常需要继承 ApplicationEvent 类,可以在事件类中定义一些与事件相关的数据,例如:

    public class MyEvent extends ApplicationEvent {
        private String message;

        public MyEvent(Object source, String message) {
            super(source);
            this.message = message;
        }

        public String getMessage() {
            return message;
        }
    }
  • 2.发布事件: 可以通过调用 ApplicationEventPublisher 的 publishEvent() 方法来发布事件,例如:
   @Autowired
    private ApplicationEventPublisher eventPublisher;

    public void doSomething() {
        MyEvent event = new MyEvent(this, "Hello, world!");
        eventPublisher.publishEvent(event);
    }
  • 监听事件: 需要实现 ApplicationListener 接口,并实现其 onApplicationEvent() 方法来处理事件,例如
  public class MyEventListener implements ApplicationListener {
        @Override
        public void onApplicationEvent(MyEvent event) {
            String message = event.getMessage();
            // 处理事件
        }
    }
  • 注册监听器: 可以通过在 Spring 容器中配置监听器来实现事件的监听,例如:
 @Configuration
    public class MyConfig {
        @Bean
        public MyEventListener myEventListener() {
            return new MyEventListener();
        }
    }

在上述代码中,MyConfig 类是一个配置类,通过在其中定义 myEventListener() 方法,并将其声明为一个 Bean,从而将 MyEventListener 监听器注册到 Spring 容器中。这样,在应用程序运行时,当 MyEvent 事件被发布时,Spring 就会自动将事件发送给注册的监听器 MyEventListener。

通过上述步骤,就可以使用 Spring 的事件机制来实现事件的监听和发布。此外,Spring 还提供了一些其他的工具和接口,例如 ApplicationEventMulticaster 接口和 SimpleApplicationEventMulticaster 类,可以帮助更方便地实现事件的发布和监听。

16.动态代理底层原理

16.1 JDK动态代理

  • 通过实现接口,获取到接口中的所有方法

  • 通过Proxy创建代理类实例

  • 通过反射机制,获取到各个方法对象

  • 调用InvocationHandler接口中invoke方法,从而实现业务增强

2.2 CGLIB 动态代理

  • 通过继承的方式去获取到目标对象的方法

  • 然后通过传递方法拦截器Methodlnterceptor实现方法拦截,在这里做具体增强

  • 再调用生成的代理类对象具体执行重写的方法,直接去调用方法拦截器里面的intercept方法

  • 前后再加上增强操作,从而实现了不修改目标代码实现业务增强

17.AOP相关名词解释

  • 连接点(JoinPoint):可织入切面的位置,方法执行前后,异常抛出之后,描述的是位置
  • 切入点(Pointcut):真正织入切面的方法,本质上是方法(一个切点对应多个连接点)
  • 通知(Advice):存放需要增强功能的共性代码,就叫通知
  • 切面(Aspect):通知是需要增强的功能存在多个,切入点是需要增强的方法也存在多个,需要去给切入点和通知做关联,知道哪个切入点对应哪个通知,这种描述关系就叫切面
  • 通知类:存放通知(方法)的类

18.Bean的生命周期

  • bean 对象创建(调用无参构造器)

  • 设置属性通过 setter 方法

  • init 方法前调用 bean 的前置处理器

  • bean 的 init 方法

  • bean 的后置处理器

  • 对象可以正常使用

  • destroy 销毁方法

  • ioc 容器关闭

  • jvm 虚拟机的退出

二、SpringMVC相关面试题

1.什么是 Spring MVC?它的作用是什么?

Spring MVC 是一个基于 Java 的 Web 应用开发框架,它是 Spring Framework 的一部分。它采用了 Model-View-Controller(MVC)设计模式,将 Web 应用程序分解为三个组成部分:模型(Model)、视图(View)和控制器(Controller)。下面分别介绍 Spring MVC 的三个组成部分:

  • 1. 模型(Model): 模型表示应用程序中的数据和业务逻辑。它封装了应用程序中的业务逻辑,提供了数据的访问和处理方法。在 Spring MVC 中,模型通常由 JavaBean 或 POJO(Plain Old Java Object)表示。

  • 2. 视图(View): 视图是用户界面的呈现方式。它负责将模型中的数据呈现给用户。在 Spring MVC 中,视图可以是 JSP(JavaServer Pages)、HTML、XML、PDF 或 Excel 等。

  • 3. 控制器(Controller): 控制器是应用程序的中心处理器。它处理请求并将其转发给适当的处理程序(Handler)。在 Spring MVC 中,控制器由一个 Java 类表示,它通过注解或 XML 配置文件将请求映射到处理程序。控制器还可以处理表单提交、请求参数解析、异常处理等功能。

  • Spring MVC 的作用是将请求和响应与业务逻辑代码分离开来,使得代码的组织更加清晰和易于维护。它可以帮助开发人员更轻松地创建高度可测试、可维护和可扩展的 Web 应用程序。同时,Spring MVC 还提供了很多其他的功能,如表单验证、数据绑定、资源处理和异常处理等,使得开发人员能够更快速地构建出功能强大的 Web 应用程序。

2.Spring MVC 的架构是怎样的?它是如何处理请求和响应的?

2.1Spring MVC 的架构可以分为以下几个部分:

  • 1.前端控制器(Front Controller): DispatcherServlet 是 Spring MVC 的前端控制器,它是整个 MVC 请求处理流程的入口,负责接收并分派请求给合适的处理器。

  • 2.处理器映射器(Handler Mapping): 处理器映射器负责将请求映射到合适的处理器(Controller)上。

  • 3.处理器适配器(Handler Adapter): 处理器适配器负责将不同类型的处理器(Controller)适配到统一的处理器执行接口(HandlerExecutionChain)上。

  • 4.视图解析器(View Resolver): 视图解析器负责将视图逻辑名称解析为实际的视图(View)对象,视图对象用于将模型(Model)数据呈现给用户。

  • 5.视图(View): 视图是模型数据的可视化呈现,它负责将模型数据渲染成 HTML、XML 或其他格式的响应内容。

2.2 Spring MVC 的请求处理流程如下:

  • 1. 用户发送 HTTP 请求到 DispatcherServlet。

  • 2. DispatcherServlet 接收请求,并将其发送给处理器映射器(Handler Mapping)。

  • 3. 处理器映射器根据请求 URL 查找合适的处理器(Controller)。

  • 4. 处理器适配器(Handler Adapter)将处理器包装为处理器执行链(HandlerExecutionChain),并返回给 DispatcherServlet。

  • 5. DispatcherServlet 调用处理器执行链(HandlerExecutionChain),并将请求对象和响应对象传递给处理器。

  • 6. 处理器执行处理逻辑,并将模型数据添加到模型(Model)中。

  • 7. 处理器返回一个视图逻辑名称,DispatcherServlet 根据视图逻辑名称查找视图解析器(View Resolver)获取实际的视图对象。

  • 8. DispatcherServlet 调用视图对象的渲染方法,将模型数据渲染成 HTML、XML 或其他格式的响应内容。

  • 9. DispatcherServlet 将响应内容返回给用户。

+-----------------+     +-------------+     +---------------+
|   客户端发送请求   |-->--|   服务器接收请求   |-->--|  DispatcherServlet  |
+-----------------+     +-------------+     +---------------+
                                          |
                                          |
                                          V
                                   +-----------+
                                   |  HandlerMapping  |
                                   +-----------+
                                          |
                                          |
                                          V
                              +---------------------+
                              |  HandlerExecutionChain  |
                              +---------------------+
                                          |
                                          |
                                          V
                               +------------------+
                               |   HandlerAdapter   |
                               +------------------+
                                          |
                                          |
                                          V
                              +------------------+
                              |    ModelAndView    |
                              +------------------+
                                          |
                                          |
                                          V
                                 +--------------+
                                 |  ViewResolver  |
                                 +--------------+
                                          |
                                          |
                                          V
                                  +--------+
                                  |   View   |
                                  +--------+
                                          |
                                          |
                                          V
                                 +-----------+
                                 |   客户端收到响应   |
                                 +-----------+

3.Spring MVC 的核心组件有哪些?它们各自的作用是什么?

Spring MVC 的核心组件包括以下几个:

  • 1.DispatcherServlet: Spring MVC 的前端控制器,它接收所有的请求并分派到相应的处理器。

  • 2.HandlerMapping: 负责将请求 URL 映射到相应的处理器(Controller)上。

  • 3.HandlerAdapter: 将不同类型的处理器适配到统一的处理器执行接口上。

  • 4.HandlerInterceptor: 拦截器,可以在请求处理之前和之后执行一些额外的逻辑,比如安全检查、日志记录等。

  • 5.ViewResolver: 将视图逻辑名称解析为实际的视图对象。

  • 6.View: 视图对象,负责将模型数据渲染成 HTML、XML 或其他格式的响应内容。

  • 7.Model: 模型对象,负责封装视图所需要的数据。

  • 8.ModelAndView: 包含模型数据和视图名称的对象,用于在处理器和视图之间传递数据。
    以上每个组件的作用如下:

  • 1.DispatcherServlet: 负责接收请求并分派给相应的处理器,是整个 Spring MVC 请求处理流程的入口。

  • 2.HandlerMapping: 负责将请求 URL 映射到相应的处理器上,是实现请求路由功能的核心组件。

  • 3.HandlerAdapter: 负责将不同类型的处理器适配到统一的处理器执行接口上,是实现处理器执行功能的核心组件。

  • 4.HandlerInterceptor: 拦截器,可以在请求处理之前和之后执行一些额外的逻辑,比如安全检查、日志记录等。

  • 5.ViewResolver: 将视图逻辑名称解析为实际的视图对象,是实现视图解析功能的核心组件。

  • 6.View: 视图对象,负责将模型数据渲染成 HTML、XML 或其他格式的响应内容,是实现视图呈现功能的核心组件。

  • 7.Model: 模型对象,负责封装视图所需要的数据,是实现数据传递功能的核心组件。

  • 8.ModelAndView: 包含模型数据和视图名称的对象,用于在处理器和视图之间传递数据,是实现数据和视图之间传递功能的核心组件。

  • 需要注意的是,以上每个组件都可以自定义实现,因此在实际开发中可以根据需要进行相应的调整和定制。

5.Spring MVC 中如何实现请求参数的绑定和校验?

Spring MVC 提供了多种方式来实现请求参数的绑定和校验,主要包括:

  • 1.表单数据绑定: Spring MVC 可以自动将表单数据绑定到指定的 JavaBean 中,只需在处理方法中添加一个带有 JavaBean 参数的方法即可。例如:


    @RequestMapping("/saveUser")
    public String saveUser(User user) {
        // 处理表单数据
        return "success";
    }

在上述代码中,当请求 /saveUser 路径时,Spring MVC 会自动将请求参数绑定到 User 对象中。

  • 2.URL 路径变量绑定: Spring MVC 可以将 URL 路径中的变量绑定到指定的方法参数中,只需在 @PathVariable 注解中指定变量名即可。例如


    @RequestMapping("/users/{userId}")
    public String getUserById(@PathVariable("userId") Long userId, Model model) {
        // 处理请求数据
        return "user";
    }

 在上述代码中,当请求 /users/1 路径时,Spring MVC 会将路径中的 userId 变量绑定到 getUserById 方法的 userId 参数中,并将处理结果返回到 user 视图中。

  • 3.请求参数校验: Spring MVC 可以通过使用 JSR 303 标准提供的校验注解,来对请求参数进行校验。只需在 JavaBean 的属性上添加相应的注解即可。例如:

   public class User {
        @NotBlank(message = "用户名不能为空")
        private String username;
        @NotBlank(message = "密码不能为空")
        private String password;
        // ...
    }

    @RequestMapping("/saveUser")
    public String saveUser(@Valid User user, BindingResult result) {
        if (result.hasErrors()) {
            // 处理校验错误
        } else {
            // 处理表单数据
        }
        return "success";
    }

在上述代码中,@Valid 注解用于告诉 Spring MVC 对 User 对象进行校验,校验结果存储在 BindingResult 对象中。如果存在校验错误,可以通过 result.hasErrors() 方法判断,并对错误进行处理。

总的来说,Spring MVC 提供了丰富的请求参数绑定和校验功能,可以根据具体的业务需求选择适合的方式。

6.Spring MVC 中如何实现数据格式的转换和格式化?

在 Spring MVC 中,可以通过以下方式实现数据格式的转换和格式化:

  • 1.自定义 Converter 和 Formatter

Spring MVC 提供了 Converter 和 Formatter 接口,可以自定义转换器和格式化器来满足业务需求。Converter 接口用于实现类型之间的转换,Formatter 接口用于实现字符串和特定类型之间的转换。

例如,定义一个自定义的 Converter,将字符串转换为 Date 类型:

  public class StringToDateConverter implements Converter {
        private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        @Override
        public Date convert(String source) {
            try {
                return sdf.parse(source);
            } catch (ParseException e) {
                e.printStackTrace();
                return null;
            }
        }
    }

 然后在 Spring MVC 配置文件中注册该 Converter:


     
         
     
  • 2.使用注解实现格式化

Spring MVC 提供了多个注解,可以用于对请求参数进行格式化。例如:

  • @DateTimeFormat: 将字符串格式的日期转换为 Java 的日期对象。
@RequestMapping("/saveUser")
public String saveUser(@RequestParam("birthDate") @DateTimeFormat(pattern="yyyy-MM-dd")                     
   Date birthDate) {
   // 处理数据
   return "success";
}
  • @NumberFormat: 将字符串格式的数字转换为指定类型的数字。
@RequestMapping("/saveUser")
    public String saveUser(@RequestParam("price") @NumberFormat(pattern="#,###.##") BigDecimal price) {
        // 处理数据
        return "success";
    }
  • @InitBinder: 用于将自定义的格式化器注册到 Spring MVC 中。

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        CustomDateEditor editor = new CustomDateEditor(sdf, true);
        binder.registerCustomEditor(Date.class, editor);
    }

在上述代码中,使用 @InitBinder 注解指定了一个自定义的日期格式化器,将日期字符串转换为 Date 类型的对象。

总的来说,Spring MVC 提供了多种方式来实现数据格式的转换和格式化,开发者可以根据具体的业务需求选择适合的方式。

7.Spring MVC 中的视图解析器是什么?它的作用是什么?

Spring MVC 中的视图解析器是一个用于将逻辑视图名称解析为实际视图的组件。它的作用是将控制器返回的逻辑视图名称解析成实际的视图对象,并渲染成最终的页面。

7.1 Spring MVC 中的视图解析器通常由两个组件组成:

  • 1.ViewResolver 接口: 用于将逻辑视图名称解析为实际的视图对象。

  • 2.View 接口: 用于渲染视图,通常会将模型数据填充到视图中,并将视图输出到客户端。

7.2 Spring MVC 默认提供了以下几种视图解析器:

  • 1.InternalResourceViewResolver: 用于解析 JSP 视图。

  • 2.ResourceBundleViewResolver: 用于解析属性文件中定义的视图。

  • 3.XmlViewResolver: 用于解析 XML 文件中定义的视图。

  • 4.FreeMarkerViewResolver: 用于解析 FreeMarker 模板视图。

8.Spring MVC 中如何实现异常处理?有哪些常用的异常处理机制?

  • 1.使用 @ExceptionHandler 注解,可以在控制器中针对特定的异常进行捕获和处理。
  • 2.实现 HandlerExceptionResolver 接口,可以自定义异常处理器来实现更加复杂的异常处理逻辑。
  • 除了以上两种方式,还可以使用 Spring 的 AOP 模块来实现异常处理。例如,使用 @AfterThrowing 注解捕获异常,并在通知方法中进行处理 

8.2 常用的异常处理机制包括:

  • @ExceptionHandler 注解: 在控制器中针对特定的异常进行捕获和处理。

  • HandlerExceptionResolver 接口: 自定义异常处理器来实现更加复杂的异常处理逻辑。

  • SimpleMappingExceptionResolver: 通过配置映射来实现异常处理。

  • ResponseEntityExceptionHandler: 针对 RESTful 接口的异常处理机制。

总的来说,Spring MVC 提供了多种方式来实现异常处理,开发者可以根据具体的业务需求选择适合的方式。

9.Spring MVC 中如何实现拦截器和过滤器?它们之间有什么区别?

  • 在 Spring MVC 中,拦截器(Interceptor)和过滤器(Filter)都是用于处理请求和响应的中间件组件。虽然它们在功能上有些相似,但是在实现上有一些区别。

  • 拦截器是 Spring MVC 框架中的组件,需要通过配置才能生效,通常用于处理请求前、请求后、响应前和响应后的逻辑。而过滤器是 Servlet 规范中定义的组件,不需要通过配置即可生效,通常用于处理请求和响应的头信息、编码、跨域等问题。

  • 拦截器是基于 Spring MVC 的 HandlerMapping 和 HandlerExecutionChain 进行处理的,可以在处理器方法(Controller)调用前、调用后以及视图渲染前、渲染后执行一些通用的操作,比如权限校验、日志记录、参数验证等。而过滤器是基于 Servlet 规范中的 FilterChain 进行处理的,只能在请求到达 Servlet 之前和 Servlet 响应结束后进行处理,无法获取处理器方法的信息。

  • 下面是 Spring MVC 中实现拦截器的示例代码:

 public class CharsetEncodingFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // 初始化操作
        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            chain.doFilter(request, response);
        }

        @Override
        public void destroy() {
            // 资源回收操作
        }
    }

上述代码中,实现了 Servlet 规范中的 Filter 接口,并在其中定义了 doFilter 方法,用于处理请求和响应的编码问题。可以通过在 web.xml 文件中配置 filter 元素将过滤器注册到应用

10.Spring MVC 中如何实现文件上传和下载?

Spring MVC提供了一种方便的方式来处理文件上传和下载。在Spring MVC中实现文件上传和下载需要使用MultipartResolver解析请求中的文件内容,以及使用ResponseEntity将文件作为响应返回给客户端。

10.1文件上传

要实现文件上传,需要使用org.springframework.web.multipart.MultipartFile类将上传的文件包装成对象,并将其作为方法的参数。Spring MVC中提供了两种方式来实现文件上传:

  • 1.使用Servlet API

使用Servlet API需要在Controller方法的参数中声明HttpServletRequest和HttpServletResponse类型的参数,并通过HttpServletRequest的getPart方法获取到上传的文件,然后将其保存到指定的目录中。

  • 2.使用Spring提供的MultipartFile

使用Spring提供的MultipartFile需要在Controller方法的参数中声明MultipartFile类型的参数,然后通过调用MultipartFile的transferTo方法将文件保存到指定的目录中。

10.2文件下载

  • 要实现文件下载,需要在Controller方法中创建一个File对象,将其包装成Resource对象,然后将Resource对象作为响应返回给客户端。

11.Spring MVC 中如何实现 RESTful 风格的 API?

Spring MVC天生支持RESTful风格的API设计,通过使用不同的HTTP方法和URI路径,可以定义不同的操作,例如获取资源、添加资源、更新资源和删除资源等。

下面是一些实现RESTful API的最佳实践:

  • 1.使用HTTP动词表示操作类型

  • 使用HTTP动词来表示对资源的不同操作,例如:

    • GET:用于获取资源

    • POST:用于添加资源

    • PUT:用于更新资源

    • DELETE:用于删除资源

  • 2.使用URI表示资源

  • URI用于标识不同的资源,例如:

    • /users:用于获取所有用户

    • /users/{id}:用于获取指定ID的用户

    • /users/{id}/orders:用于获取指定用户的订单列表

  • 3.使用HTTP状态码表示操作结果

  • 使用HTTP状态码来表示不同的操作结果,例如:

    • 200 OK:表示成功获取资源

    • 201 Created:表示成功创建资源

    • 204 No Content:表示成功更新或删除资源

    • 400 Bad Request:表示请求错误,例如参数不正确

    • 404 Not Found:表示资源不存在

  • 4.使用HTTP头部信息传递额外信息

    • 使用HTTP头部信息来传递额外的请求或响应信息,例如:

    • Accept:用于指定请求的MIME类型

    • Content-Type:用于指定响应的MIME类型

    • Authorization:用于进行身份验证

12.Spring MVC 中的消息转换器是什么?它有哪些常用的实现方式?

Spring MVC 中的消息转换器(Message Converter)是用于在 HTTP 请求和响应中将 Java 对象转换为相应的数据格式(如 JSON、XML、HTML、PDF 等)或者将数据格式转换为 Java 对象的组件。它是 Spring MVC 框架中的一个核心组件,负责处理请求和响应之间的转换工作。

  • Spring MVC 中常用的消息转换器包括:

  • 1.MappingJackson2HttpMessageConverter: 用于将 Java 对象转换为 JSON 数据格式,或者将 JSON 数据格式转换为 Java 对象。它依赖于 Jackson 库,可以处理包括日期、枚举等在内的各种类型,并支持 JSONP、CORS 等功能。

  • 2.StringHttpMessageConverter: 用于将文本数据转换为字符串,或者将字符串转换为文本数据。它支持各种 MIME 类型,如 text/plain、text/html、application/xml、application/json 等。

  • 3.ByteArrayHttpMessageConverter: 用于将字节数组转换为二进制数据,或者将二进制数据转换为字节数组。它支持各种 MIME 类型,如 application/octet-stream、image/jpeg、image/png 等。

  • 4.FormHttpMessageConverter: 用于将表单数据转换为 MultiValueMap 对象,或者将 MultiValueMap 对象转换为表单数据。它支持 application/x-www-form-urlencoded 和 multipart/form-data 两种 MIME 类型。

  • 5.MappingJackson2XmlHttpMessageConverter: 用于将 Java 对象转换为 XML 数据格式,或者将 XML 数据格式转换为 Java 对象。它依赖于 Jackson-dataformat-xml 库,支持 XML 命名空间、CDATA 等功能。

  • 除了以上常用的消息转换器之外,Spring MVC 还支持自定义消息转换器,开发者可以根据自己的需求实现自己的消息转换器,并注册到 Spring MVC 的配置中。

13.Spring MVC 中如何使用 Spring Security 实现安全控制?它有哪些常用的安全机制?

  • Spring Security 是 Spring 框架中用于实现安全控制的模块,它基于 Servlet 过滤器、Spring AOP 和 Spring 配置等技术,提供了一套全面的安全机制,可以帮助开发者实现各种复杂的安全控制需求,如认证、授权、会话管理、密码管理等。

  • 在 Spring MVC 中使用 Spring Security 实现安全控制,通常需要进行以下步骤:

  • 1.添加 Spring Security 依赖,在 pom.xml 文件中添加 Spring Security 的依赖

  • 2.配置 Spring Security,在 Spring MVC 的配置文件中添加 Spring Security 的配置

13.1常用的 Spring Security 安全机制包括:

  • 1.认证(Authentication): 即验证用户身份的过程。Spring Security 支持多种认证方式,如基于表单的认证、基于 HTTP Basic 的认证、基于 HTTP Digest 的认证、基于 LDAP 的认证等。

  • 2.授权(Authorization): 即授予用户对系统资源的访问权限的过程。Spring Security 支持基于角色、基于权限、基于表达式等多种授权方式。

  • 3.安全拦截器(Filter): Spring Security 通过安全拦截器来保护系统资源,它负责拦截用户请求并进行安全控制。安全拦截器可以通过 XML 配置或 Java 配置进行定义和配置。

  • 4.表达式控制(Expression-Based Access Control): Spring Security 支持使用表达式来控制系统资源的访问权限,可以在控制器方法上使用 @PreAuthorize 和 @PostAuthorize 注解来实现。

  • 5.注销(Logout): 即让用户从系统中退出的过程。Spring Security 提供了相应的注销功能,可以在 XML 配置或 Java 配置中进行配置。

  • 6.会话管理(Session Management): Spring Security 支持对用户会话进行管理,包括基于时间的过期控制、基于并发数的控制、基于 CSRF 攻击的防护等。

14.Spring MVC 中的 CSRF 攻击是什么?如何防止它?

CSRF(Cross-Site Request Forgery)攻击,又称跨站请求伪造攻击,指攻击者通过构造特定的请求,欺骗用户在已经登录的情况下对指定的网站发起请求,从而在用户不知情的情况下完成非法操作,如转账、删除等操作。

  • 为了防止CSRF攻击,Spring MVC提供了以下几种方式:

  • 1.添加CSRF Token: 在表单提交时,将一个随机生成的Token加入到表单参数中,同时将该Token存储在session中。当表单提交后,后端通过比较session中的Token和表单参数中的Token是否一致来确定请求的合法性。这种方式需要在前端表单中添加Token的hidden字段,并在后端进行校验。

  • 2.禁止跨站请求: 可以在后端通过添加HTTP Header来禁止跨站请求。如使用Spring Security,可以通过配置HttpSecurity来禁用CSRF保护:http.csrf().disable()。

  • 3.合理设置cookie属性: 设置HttpOnly和Secure属性,HttpOnly属性可以防止cookie被javascript读取,Secure属性可以防止cookie在https之外被传递。

  • 4.验证Referer信息: 在后端验证请求的Referer是否合法,这种方式需要前端将Referer信息放入请求头中,后端进行校验。

  • 综上,为了防止CSRF攻击,应该采取多种手段结合使用,以提高安全性。

15.springMvc常用注解

  • @RequestMapping,指定请求路径

  • @RequestParam,设置默认值;定义映射规则

  • @RequestHeader,获取请求头信息

  • @CookieValue,获取Cookie

  • @ResponseBody,响应体,返回jackson对象,需要导入依赖 jackson-databind

  • @RequestBody,请求体,接收前端传过来的json对象

  • @ModelAttribute,

  • @ModelAttribute,取出请求中占位符对应的参数

  • @SessionAttributes,加在类上,指定哪些属性名,或者哪些属性值会被加入到session中

三、SpringBoot相关面试题

1.什么是 Spring Boot?它的作用是什么?

  • Spring Boot是一个基于Spring框架的快速开发应用程序的工具,它提供了一个开箱即用的配置和约定优于配置的方式来简化Spring应用程序的开发和部署。Spring Boot致力于使开发人员能够快速创建独立的、生产级别的应用程序,而无需手动配置和集成各种组件。

  • Spring Boot有以下特点:

  • 1.自动配置: Spring Boot根据应用程序的依赖关系自动配置各种功能,从而大大简化了开发人员的工作。

  • 2.起步依赖: Spring Boot提供了一组预定义的依赖项集合,可以轻松地将常用的框架和库集成到应用程序中。

  • 3.命令行界面: Spring Boot提供了一个命令行工具,可以用于快速创建、测试和运行应用程序。

  • 4.统一的配置模型: Spring Boot使用一种统一的配置模型,使得开发人员可以在不同的环境中轻松地配置应用程序。

  • Spring Boot的作用是简化Spring应用程序的开发和部署过程,使开发人员能够更快地创建生产级别的应用程序,并且不需要手动配置和集成各种组件。Spring Boot还提供了许多有用的功能,如自动配置、起步依赖和命令行界面等,使得开发人员可以更加专注于业务逻辑的实现,而不是繁琐的配置和集成工作。

2.Spring Boot 的特点是什么?它是如何简化开发的?

  • Spring Boot有以下特点:

  • 1.简化配置: Spring Boot使用约定优于配置的方式来简化配置,使得开发人员可以更快速地搭建应用程序。

  • 2.自动配置: Spring Boot可以根据应用程序的依赖关系自动配置各种功能,从而大大减少了开发人员的配置工作。

  • 3.起步依赖: Spring Boot提供了一系列预定义的依赖项集合,可以轻松地将常用的框架和库集成到应用程序中。

  • 4.统一的配置模型: Spring Boot使用一种统一的配置模型,使得开发人员可以在不同的环境中轻松地配置应用程序。

  • 5.内嵌式容器: Spring Boot集成了一些常用的内嵌式容器,使得应用程序的部署变得更加简单。

  • 6.命令行界面: Spring Boot提供了一个命令行工具,可以用于快速创建、测试和运行应用程序。

  • Spring Boot通过上述特点,简化了开发人员的工作。首先,约定优于配置的方式使得开发人员不需要过多地关注配置文件,大大减少了编写配置文件的工作量。其次,自动配置使得开发人员不需要手动进行各种配置,减少了错误和不必要的工作。再者,起步依赖和内嵌式容器使得开发人员能够更加便捷地将第三方库和框架集成到应用程序中,从而减少了集成的复杂性。最后,命令行界面使得开发人员可以更加方便地测试和运行应用程序,提高了开发效率。

3.Spring Boot 中的自动配置是什么?它是如何实现的?

  • Spring Boot的自动配置是指根据应用程序的依赖关系和类路径自动为应用程序配置所需的各种功能的过程。这些自动配置功能包括数据源、Web MVC、安全性、缓存、日志、消息队列等等。

  • Spring Boot的自动配置是通过使用条件化配置来实现的。条件化配置是指只有在满足特定条件的情况下才会应用某种配置。例如,只有在类路径中存在特定的依赖项时才会启用某个功能。这些条件通常由Spring Boot的自动配置类中的各种条件注解来定义。

  • Spring Boot的自动配置流程通常包括以下几个步骤:

  • 1. Spring Boot扫描应用程序中的所有依赖项,并检查它们所包含的Spring组件。

  • 2. Spring Boot自动配置启动,并根据检测到的组件自动创建所需的Bean和其他配置。

  • 3. 如果需要,Spring Boot会检查应用程序的配置文件,并将其合并到自动配置中。

  • 4. 如果有必要,开发人员可以通过添加自己的配置来覆盖或扩展自动配置。

  • 总之,Spring Boot的自动配置大大简化了应用程序的配置工作,使开发人员能够更加专注于业务逻辑的实现,而不必过多关注配置问题。同时,Spring Boot的自动配置机制也提供了足够的灵活性,使得开发人员可以根据需要进行扩展和定制。

  • MySQL数据库连接案例

  • 1.引入MySQL依赖(在pom.xml文件中添加如下依赖

  • 2.配置MySQL连接属性(在application.properties文件中添加属性

  • 3.启用自动配置

Spring Boot的自动配置可以根据上述配置自动创建一个DataSource对象,用于连接MySQL数据库。要启用自动配置,只需在Spring Boot应用程序的入口类上添加@SpringBootApplication注解即可

4.Spring Boot 中的 Starter 是什么?它的作用是什么?

  • Spring Boot中的Starter是一种特殊的依赖项,用于为应用程序添加特定的功能模块。Starter通常是一个包含一组相关依赖项的POM文件,用于简化应用程序的配置和启动。

  • Spring Boot提供了大量的Starter,覆盖了诸如Web开发、数据访问、安全性、消息传递、测试等方面的功能。例如,Spring Boot的Web Starter包含了一组相关的依赖项,用于启用Web开发所需的Spring MVC、Tomcat、Jackson、Spring Boot Actuator等模块。通过引入Web Starter,开发人员无需手动配置这些依赖项,即可轻松地构建一个基于Spring MVC的Web应用程序。

  • Starter的作用是简化应用程序的配置和启动,同时提高了应用程序的可重用性。通过引入Starter,开发人员可以更快速地创建一个基于Spring Boot的应用程序,而无需了解和配置每个单独的依赖项。此外,Starter还可以提高应用程序的可重用性,使得开发人员可以更容易地将自己的应用程序打包成一个可复用的组件,供其他应用程序使用。

  • 总之,Spring Boot的Starter是一种便捷的机制,可以帮助开发人员快速启用和配置应用程序所需的功能模块,提高了应用程序的可重用性和开发效率。

  • 比如说:

    • spring-boot-starter-web: 用于Web应用程序开发的Starter,包括Spring MVC、Tomcat和Jackson等模块。

    • spring-boot-starter-data-jpa: 用于访问关系型数据库的Starter,包括Spring Data JPA和Hibernate等模块。

    • spring-boot-starter-data-redis: 用于访问Redis数据库的Starter,包括Spring Data Redis和Jedis等模块。

    • spring-boot-starter-security: 用于添加安全性功能的Starter,包括Spring Security和OAuth2等模块。

    • spring-boot-starter-test: 用于测试应用程序的Starter,包括JUnit、Mockito和Hamcrest等模块。

    • spring-boot-starter-actuator: 用于添加应用程序管理和监控功能的Starter,包括Spring Boot Actuator等模块。

5.Spring Boot 中如何配置日志?它有哪些常用的日志框架?

  • 在Spring Boot中,可以通过配置日志框架来管理和输出应用程序的日志信息。Spring Boot支持多种常用的日志框架,包括Logback、Log4j2和Java Util Logging等。下面是Spring Boot中配置Logback日志框架的示例:
  • 1.引入Logback依赖,在pom.xml文件中添加依赖
  • 2.配置日志输出格式,在application.properties文件中添加属性
  • 3.配置日志输出级别

通过上述配置,我们可以将应用程序的日志级别设置为不同的级别,并将日志输出到控制台。通过修改上述配置,我们还可以将日志输出到文件、邮件等不同的位置和方式。

总之,在Spring Boot中,我们可以通过配置不同的日志框架来管理和输出应用程序的日志信息,以及通过配置不同的属性来控制日志的输出格式和级别。

6.Spring Boot 中如何配置数据库?它有哪些常用的数据库框架?

  • 在Spring Boot中,可以使用配置文件和依赖库来配置和连接数据库。Spring Boot支持多种常用的数据库框架,包括JPA、Hibernate、MyBatis、Spring Data JDBC等。下面以JPA为例来演示如何在Spring Boot中配置和连接数据库。
  • 1.引入JPA依赖2.配置数据源,3.配置JPA属性
  • 通过上述配置,我们可以使用JPA框架来访问和操作数据库。通过修改上述配置,我们还可以使用其他数据库框架来连接和操作不同类型的数据库。

  • 除了JPA框架,还有Hibernate、MyBatis、Spring Data JDBC等常用的数据库框架。这些框架各有优缺点,可以根据具体的业务需求和开发经验来选择合适的数据库框架。

7.Spring Boot 中如何实现数据校验和格式化?

  • 在Spring Boot中,可以使用Hibernate Validator来实现数据校验和格式化。Hibernate Validator是一种基于JSR-380规范的数据校验框架,可以用来验证Java Bean中的属性值是否符合要求,并提供多种内置的校验注解和校验器。

8.Spring Boot 中如何实现缓存?它有哪些常用的缓存框架?

  • 在Spring Boot中,可以通过集成缓存框架来实现缓存功能,常用的缓存框架包括Ehcache、Redis、Caffeine等。

9.Spring Boot 中如何实现任务调度?它有哪些常用的任务调度框架?

  • 在Spring Boot中,可以通过集成任务调度框架来实现任务调度功能,常用的任务调度框架包括Quartz和Spring自带的任务调度框架。

10.Spring Boot 中如何实现消息队列?它有哪些常用的消息队列框架?

  • 在Spring Boot中实现消息队列需要用到Spring Boot提供的集成框架Spring Boot AMQP。Spring Boot AMQP提供了一个基于AMQP协议的消息系统,可以方便地将消息发送到RabbitMQ等消息队列中间件。

  • 以下是在Spring Boot中使用RabbitMQ的步骤:

  • 1.添加RabbitMQ依赖,在pom.xml中添加RabbitMQ依赖:


    org.springframework.boot
    spring-boot-starter-amqp

  • 2.配置RabbitMQ连接信息
spring.rabbitmq.host=your-rabbitmq-host
spring.rabbitmq.port=your-rabbitmq-port
spring.rabbitmq.username=your-rabbitmq-username
spring.rabbitmq.password=your-rabbitmq-password
  • 3.创建消息发送者
   @Component
    public class MessageSender {
        private final RabbitTemplate rabbitTemplate;

        @Autowired
        public MessageSender(RabbitTemplate rabbitTemplate) {
            this.rabbitTemplate = rabbitTemplate;
        }

        public void sendMessage(String message) {
            rabbitTemplate.convertAndSend("your-exchange-name", "your-routing-key",message);
        }
    }

在上述代码中,通过RabbitTemplate来发送消息,其中your-exchange-name表示交换机名称,your-routing-key表示路由键,message表示发送的消息内容。

  • 4.创建消息接收者

    @Component
    @RabbitListener(queues = "your-queue-name")
    public class MessageReceiver {
        @RabbitHandler
        public void handleMessage(String message) {
            // 处理接收到的消息
        }
    }
  • 在上述代码中,通过@RabbitListener注解来监听消息队列中的消息,其中your-queue-name表示队列名称,@RabbitHandler注解表示处理接收到的消息的方法。

  • 常用的消息队列框架还包括Kafka、ActiveMQ、RocketMQ等。Spring Boot也支持这些框架的集成,只需要添加相应的依赖和配置即可。

11.Spring Boot 的启动流程是什么?

  • 1.加载 Spring Boot 程序入口类: Spring Boot 的启动流程始于加载 Spring Boot 程序入口类。在程序入口类上使用 @SpringBootApplication 注解,它包含了多个注解的组合,其中包括 @Configuration、@EnableAutoConfiguration 和 @ComponentScan。

  • 2.扫描并加载 Spring Bean: Spring Boot 通过 @ComponentScan 注解扫描程序入口类所在的包及其子包下的所有类,加载其中所有被 @Component、@Service、@Controller、@Repository 等注解标识的 Bean。

  • 3.执行自动配置: Spring Boot 通过 @EnableAutoConfiguration 注解实现自动配置,自动配置可以根据应用程序的依赖和配置自动配置 Spring 和其他框架的功能。自动配置的实现是通过加载位于 classpath 下的 META-INF/spring.factories 文件中的配置类来实现的。

  • 4.启动嵌入式的 Web 服务器: Spring Boot 默认使用 Tomcat 作为嵌入式 Web 服务器,也支持 Jetty 和 Undertow。Spring Boot 在启动过程中会自动配置嵌入式 Web 服务器并启动它。

  • 5.运行应用程序: 当嵌入式 Web 服务器启动后,Spring Boot 会运行应用程序。根据配置,应用程序可以在 Web 服务器上运行一个或多个 Web 应用程序或非 Web 应用程序。

  • 需要注意的是,Spring Boot 的启动流程是高度自动化和可配置的,因此开发人员可以通过配置文件和自定义代码来修改其行为和实现。

你可能感兴趣的:(Spring面试,Spring,SpringBoot,spring,java,面试)