Spring Boot面试题

什么是 Spring Boot?

Spring Boot 是一个简化 Spring 应用程序开发的框架,通过自动配置、起步依赖和简化的配置方式,使开发人员能够更快速、方便地创建和配置 Spring 应用程序,提高开发效率和开发体验。

Spring Boot 的设计目标是使开发人员能够更加快速、方便地创建和配置 Spring 应用程序,同时尽可能地减少样板代码和繁琐的配置。它通过自动配置、约定大于配置和起步依赖等特性,使得开发人员能够更专注于业务逻辑的实现,而不需要过多关注底层的配置细节。

Spring Boot 提供了许多功能和特性包括:

  1. 自动配置:Spring Boot 根据应用程序的依赖和配置,自动配置 Spring 应用程序的各种组件,如数据源、Web 容器等,减少了手动配置的工作量。
  2. 起步依赖:Spring Boot 提供了一系列预配置的依赖项,称为起步依赖(Starter Dependencies),可以快速集成常用的技术栈,如数据库、消息队列、Web 开发等。
  3. 嵌入式容器:Spring Boot 内置了多种嵌入式容器,如 Tomcat、Jetty 等,可以将应用程序打包成可执行的 JAR 文件,并直接运行,无需部署到外部容器。
  4. Actuator:Spring Boot Actuator 提供了对应用程序的监控和管理功能,包括健康检查、指标收集、配置信息等,方便运维和监控应用程序。
  5. 简化的配置:Spring Boot 使用了约定大于配置的原则,提供了简化的配置方式,如 application.properties 或 application.yml 文件,可以集中管理应用程序的配置信息。

Spring Boot 有哪些优点/Spring boot 相对 Spring有什么优势 ?

1.可快速构建独立的Spring应用

Spring Boot主要是通过注解和自动化配置的方式推出的全新框架,旨在快速、敏捷的开发新一代基于Spring框架的应用程序。在构建Spring Boot项目时,只要根据需求选择对应的场景依赖,Spring Boot会自动添加该场景所需要的全部依赖并提供自动化配置,在无需额外手动添加配置的情况下可以快速构建出一个独立的Spring应用程序。

2.直接嵌入Tomcat、Jetty和Undertow服务器(无需部署WAR文件)

Spring Boot项目不需要像传统的Spring应用一样打成WAR包的形式部署到Tomcat、Jetty或Undertow服务器中,运行一个Spring Boot项目,可以直接将项目打成JAR包的形式,并通过命令“java -jar xx.jar”运行。这是因为,Spring Boot项目内嵌了Tomcat、Jetty和Undertow服务器,因此在部署过程中减少了对第三方插件的依赖和管理。

3.提供依赖启动器简化构建配置

在Spring Boot项目构建过程中,无需准备各种独立的JAR文件,只需在构建项目时根据开发场景需求选择对应的依赖启动器“starter”即可,在引入的依赖启动器“starter”内部已经包含了对应开发场景所需的依赖,并会自动下载和拉取相关JAR包。例如,在Web开发时,只需在构建项目时选择对应的Web场景依赖启动器spring-boot-starter-web,Spring Boot项目便会自动导入spring-webmvc、spring-web、spring-boot-starter-tomcat等子依赖,并自动下载和拉取Web开发需要的相关JAR包。

4.极大程度的自动化配置Spring和第三方库

Spring Boot充分考虑到了与传统Spring框架以及其他第三方库融合的场景,在提供了各种场景依赖启动器的基础上,内部还默认提供了大量的各种自动化配置类(例如RedisAutoConfiguration)。使用Spring Boot开发项目时,一旦引入了某个场景的依赖启动器,Spring Boot内部提供的默认自动化配置类就会生效,开发者无需再手动进行配置文件的配置(除非开发者修改了相关默认配置,例如Redis地址、密码等),从而极大减少了开发人员的工作量,提高了程序的开发效率。

5.提供监控应用

Spring Boot提供了一些用于生产环境运行时的特性,例如指标、健康检查和外部化配置。其中,指标和监控检查可以很方便的帮助运维人员在运维期间监控项目运行情况;外部化配置可以很方便的让运维人员快速、方便的外部化配置和部署工作。

6.极少的代码生成和XML配置

Spring Boot框架内部已经实现了与Spring以及其他常用第三方库的整合连接,并提供了默认最优化的整合配置,使用时基本上不需要额外生成配置代码和XML配置文件。在需要自定义配置的情况下,Spring Boot更加提倡使用Java config(Java配置类)替换传统的XML配置方式,这样更加方便查看和管理。

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

启动类上面的注解是@SpringBootApplication,它是 Spring Boot 的核心注解

主要组合包含了以下 3 个注解:

@SpringBootConfiguration

@SpringBootConfiguration里面就只有一个@Configuration主要注解,也就是把该类变成一个配置类所以@SpringBootConfiguration就相当于@Configuration。实现配置文件的功能

@EnableAutoConfiguration

@EnableAutoConfiguration是由 @AutoConfigurationPackage和@Import(EnableAutoConfigurationImportSelector.class)这两个组成的

打开自动配置的功能,帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot,并创建对应配置类的Bean,并把该Bean实体交给IoC容器进行管理。

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })

如上所示可以关闭某个自动配置的选项,如关闭数据源自动配置功能

@ComponentScan

@ComponentScan注解是Spring组件扫描注解,默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中

什么是 JavaConfig?JavaConfig 的优点?

JavaConfig 是一种用于配置 Java 应用程序的方式,它是 Spring 框架中的一种替代方案,用于替代传统的 XML 配置文件方式。

JavaConfig 允许开发人员使用 Java 代码来定义和配置应用程序中的各种组件,包括 Bean 的定义、依赖关系、切面等。通过 JavaConfig,可以将应用程序的配置集中在一个或多个 Java 类中,使得配置更加可读、可维护,并且可以利用 Java 语言的特性进行编程。

JavaConfig 的优点包括:

1. 类型安全:JavaConfig 使用 Java 代码进行配置,可以在编译时进行类型检查,避免了在 XML 配置文件中可能出现的拼写错误或类型错误。
2. 易于重构:由于 JavaConfig 使用 Java 代码进行配置,可以利用 IDE 的重构功能,轻松地进行重命名、提取方法等操作,提高了代码的可维护性。
3. 面向对象:JavaConfig 可以利用 Java 语言的面向对象特性,如继承、多态等,更加灵活地进行配置和组件定义。
4. 可读性和可维护性:JavaConfig 使用 Java 代码进行配置,配置信息直观可见,易于理解和维护。相比于 XML 配置文件,JavaConfig 更加直观和易读。
5. 编程能力:JavaConfig 允许开发人员使用 Java 语言的编程能力,如条件判断、循环等,可以根据需要进行动态的配置。

Spring Boot 自动配置原理是什么?

我们知道SpringBoot可以帮我们减少很多的配置,也肯定听过“约定大于配置”这么一句话,那SpringBoot是怎么做的呢?其实靠的就是@EnableAutoConfiguration注解。

简单来说,这个注解可以帮助我们自动载入应用程序所需要的所有默认配置。

发现有两个比较重要的注解

  • @AutoConfigurationPackage:自动配置包扫描
  • @Import:给IOC容器导入组件

@AutoConfigurationPackage

@AutoConfigurationPackage是 Spring Boot 提供的注解,用于自动配置包扫描。通过在主配置类上添加该注解,可以告诉 Spring Boot 自动配置机制,将主配置类所在的包及其子包作为组件扫描的基础包,简化了组件扫描的配置过程。

我们可以发现,依靠的还是@Import注解

@AutoConfigurationPackage注解就是在默认的情况下就是将主配置类(@SpringBootApplication这个注解所在包及其子包里边的组件)扫描到Spring容器中

看起来跟@ComponentScan注解一样的作用,但是扫描的对象不一样,比如说,你用了Spring Data JPA,可能会在实体类上写@Entity注解。这个@Entity注解由 @AutoConfigurationPackage扫描并加载,而我们平时开发用的@Controller/@Service/@Component/@Repository这些注解是由@ComponentScan来扫描并加载的。

简单理解:这二者扫描的对象是不一样的。

@Import(AutoConfigurationImportSelector.class)

AutoConfigurationImportSelector这个类中有个selectImports方法,其中getCandidateConfigurations方法可以获取很多的配置信息

那这些配置信息哪里来的呢?

这里包装了一层,我们看到的只是通过SpringFactoriesLoader来加载获取到的配置信息,还没看到关键信息,继续进去:

解析

  • FACTORIES_RESOURCE_LOCATION(工厂资源加载路径)的值是META-INF/spring.factories
  • Spring启动的时候会扫描所有jar路径下的META-INF/spring.factories,将其文件包装成Properties对象
  • 从Properties对象获取到key值为EnableAutoConfiguration的数据,然后添加到容器里边。

最后我们会默认加载113个默认的配置类:

Spring Boot 自动配置原理是什么?

@EnableAutoConfiguration 是 Spring Boot 提供的注解,用于启用自动配置。在 Spring Boot 启动过程中,Spring 会扫描所有的 jar 路径下的 META-INF/spring.factories 文件(通过 @Import(AutoConfigurationImportSelector.class) 导入了 AutoConfigurationImportSelector 类来实现的),将其包装成 Properties 对象。然后从这个 Properties 对象中获取 key 值为 EnableAutoConfiguration 的数据,这些数据都是 Spring Boot 默认配置好的配置文件数据。并根据配置数据自动加载和应用相应的自动配置类,以实现自动配置的功能。

@Import(AutoConfigurationImportSelector.class)@EnableAutoConfiguration 注解的核心部分。它的作用是将 AutoConfigurationImportSelector 类导入到 IOC 容器中,并根据 EnableAutoConfiguration 的配置数据,自动加载相应的自动配置类。

自动配置类是 Spring Boot 提供的一系列配置类,用于根据应用程序的依赖和配置,自动配置相应的组件。这些自动配置类会根据配置文件中的属性值,自动创建并注册相应的 Bean,以实现自动配置的功能。

通过使用 @EnableAutoConfiguration 注解,Spring Boot 可以根据项目的依赖和配置,自动加载并应用这些自动配置类,从而简化了配置的过程。

骚戴理解:其中@EnableAutoConfiguration是关键(启用自动配置),这个注解里的

@Import(AutoConfigurationImportSelector.class)注解起核心作用,Spring启动的时候会扫描所有jar路径下的META-INF/spring.factories,将其文件包装成Properties对象,从Properties对象获取到key值为EnableAutoConfiguration的数据(这些数据都是SpringBoot默认配置好了的配置文件数据,例如Redis常用配置的数据,这样就不需要我们配置了,我们只要简单配置几个核心的数据就可以用Redis了,从而简化了配置),加载到IOC容器中,实现自动配置功能!

SpringBoot 常用的配置形式,按照配置生效的优先级从高到低排列?

 Spring Boot 常用的配置形式,按照配置生效的优先级从高到低排列:

1. 命令行参数:通过在启动应用程序时传递命令行参数,可以覆盖配置文件中的相应配置项。例如,使用 `--server.port=8080` 可以指定应用程序的端口号为 8080。

2. 操作系统环境变量:可以通过设置操作系统的环境变量来配置应用程序。Spring Boot 会自动将环境变量映射到相应的配置项上。例如,设置名为 `SPRING_APPLICATION_JSON` 的环境变量,可以传递 JSON 格式的配置信息给应用程序。

3. 配置文件:Spring Boot 支持多种配置文件格式,包括 YAML 文件(以 yml或yaml后缀)和 Properties 文件(以properties后缀)。配置文件通常位于应用程序的 classpath下,可以包含多个配置项。如果存在多个配置文件

优先级从高到低为:application.yml > application.properties> application-{profile}.yml> application-{profile}.properties,其中 {profile} 是当前激活的配置文件。

4. @Configuration注解类上的 @PropertySource指定的配置文件:可以在 @Configuration注解的类上使用 @PropertySource注解指定一个或多个配置文件。这些配置文件的优先级低于上述的全局配置文件,但高于默认的配置值。通过这种方式,可以将特定的配置文件与特定的配置类关联起来。

需要注意的是,上述配置形式的优先级是从高到低,即高优先级的配置会覆盖低优先级的配置。

骚戴理解:命令行参数>操作系统环境变量>配置文件>@Configuration注解类上的 @PropertySource指定的配置文件

什么是 YAML?

YAML(YAML Ain't Markup Language)是一种易读的数据序列化语言。它的设计目标是提供一种简洁、可读性强的数据格式,适用于配置文件和数据交换。

与其他数据序列化格式相比,如 JSON 或 XML,YAML 的语法更加简洁和易读。它使用缩进和空格来表示层级关系,使用冒号来表示键值对,使用短横线来表示列表,使得配置文件的结构更加清晰和可读性强。

YAML 在许多应用场景中被广泛使用,特别是在 Spring Boot 和其他许多开发框架中作为配置文件的首选格式。它不仅可以用于简单的键值对配置,还支持复杂的数据结构,如嵌套的映射、列表和引用等。

YAML 配置的优缺点?

YAML 配置具有以下优点:

1. 可读性强:YAML 使用缩进和空格来表示层级关系,使用冒号来表示键值对,使得配置文件的结构更加清晰和易读。相比于其他格式,如 JSON 或 XML,YAML 更加直观和易于理解。

2. 简洁性:YAML 的语法相对简洁,可以用较少的字符表示相同的数据结构。相比于 XML,YAML 的配置文件通常更加简洁和精简。

3. 支持复杂数据结构:YAML 支持嵌套的映射、列表和引用等复杂数据结构,可以灵活地表示各种配置需求。

4. 可扩展性:YAML 支持自定义标签和类型,可以根据需要扩展和定制配置文件的语义。

YAML 配置也存在一些缺点:

1. 学习曲线:相比于其他格式,如 JSON 或 Properties 文件,YAML 的语法可能对于一些开发者来说需要一定的学习成本。尤其是对于没有接触过 YAML 的开发者来说,可能需要一些时间来熟悉和理解其语法规则。

2. 语法敏感性:YAML 的语法对于缩进和空格的使用非常敏感,不正确的缩进或空格可能导致配置文件解析错误。这可能会增加调试和排查问题的难度。

3. 不适合大型配置:对于大型配置文件,YAML 的层级结构可能会变得复杂,不易于维护和管理。在这种情况下,可能需要考虑其他更适合的配置格式。

YAML 配置的用法

以下是一些常见的 YAML 配置用法案例:

1. 简单的键值对配置:

server:
  port: 8080
  host: localhost

在上述示例中,配置了一个简单的键值对,指定了服务器的端口号和主机名。

2. 嵌套的映射和列表配置:

database:
  driver: com.mysql.jdbc.Driver
  url: jdbc:mysql://localhost:3306/mydb
  username: root
  password: password
  pool:
    max-size: 10
    min-size: 5
  tables:
    - users
    - products

上述示例中,配置了数据库连接相关的信息,包括驱动类、URL、用户名和密码。还配置了连接池的最大大小和最小大小,以及需要操作的数据表列表。

3. 环境配置和多个配置文件:

spring:
  profiles:
    active: dev

---

spring:
  profiles: dev
  datasource:
    url: jdbc:mysql://localhost:3306/devdb
    username: devuser
    password: devpassword

---

spring:
  profiles: prod
  datasource:
    url: jdbc:mysql://localhost:3306/proddb
    username: produser
    password: prodpassword

在上述示例中,通过 `spring.profiles.active` 配置了激活的环境为 `dev`。然后,使用 `---` 分隔符定义了不同环境下的配置。在 `dev` 环境下,配置了开发数据库的连接信息;在 `prod` 环境下,配置了生产数据库的连接信息。

4. 自定义类型和引用:

person: &person
  name: John Doe
  age: 30

employee:
  <<: *person
  position: Manager

在上述示例中,首先定义了一个名为 `person` 的自定义类型,包含姓名和年龄。然后,使用 `<<: *person` 引用了 `person` 类型,并在 `employee` 类型中添加了职位信息。这样可以避免重复定义相同的属性。

5. 简单的数组:

fruits:
  - apple
  - banana
  - orange

在上述示例中,`fruits` 是一个简单的数组对象,包含了苹果、香蕉和橙子三个元素。

6. 数组中包含映射对象:

users:
  - name: John
    age: 25
  - name: Alice
    age: 30

上述示例中,`users` 是一个包含了两个映射对象的数组。每个映射对象都有 `name` 和 `age` 两个属性。

7. 数组中嵌套数组:

matrix:
  - [1, 2, 3]
  - [4, 5, 6]
  - [7, 8, 9]

在上述示例中,`matrix` 是一个包含了三个嵌套数组的数组对象。每个嵌套数组都包含了三个元素。

8. 使用 `-` 表示数组元素:

- apple
- banana
- orange

上述示例中,直接使用 `-` 表示数组元素,不需要显式指定键名。这种写法适用于简单的数组。

9. 数组中包含复杂对象:

products:
  - name: Apple
    price: 1.99
    details:
      - color: red
        weight: 100g
      - color: green
        weight: 150g
  - name: Banana
    price: 0.99
    details:
      - color: yellow
        weight: 120g

上述示例中,`products` 是一个包含了两个复杂对象的数组。每个对象都有 `name`、`price` 和 `details` 三个属性。`details` 属性是一个嵌套的数组,包含了颜色和重量两个属性。

Spring Boot 是否可以使用 XML 配置 ?

Spring Boot 推荐使用 Java 配置而非 XML 配置,但是 Spring Boot 中也可以使用 XML 配置,通过@ImportResource 注解可以引入一个 XML 配置。

spring boot 核心配置文件是什么?bootstrap.properties 和application.properties 有何区别 ?

spring boot 核心配置文件是什么?

在 Spring Boot 中,核心的两个配置文件是 bootstrap.yml(或 bootstrap.properties)和 application.yml(或 application.properties

bootstrap.properties 和application.properties 有何区别 ?

bootstrap.propertiesapplication.properties 是两个常用的配置文件,用于配置 Spring Boot 应用程序的属性。它们之间的区别如下:

  1. 加载顺序:Spring Boot 在启动过程中会按照一定的加载顺序读取配置文件。其中,bootstrap.properties 是在 Spring Boot 启动时最早加载的配置文件,用于配置应用程序的基础设施,如连接远程配置服务器等。而 application.properties 是在 bootstrap.properties 加载后,应用程序开始启动之前加载的配置文件,用于配置应用程序的具体业务逻辑。

  2. 作用范围:bootstrap.properties 主要用于配置 Spring Cloud 相关的属性,如配置中心、服务注册和发现等。它的作用范围通常是整个应用程序的基础设施。而 application.properties 则用于配置应用程序的具体业务逻辑,如数据库连接、日志配置、缓存配置等。

  3. 配置继承:application.properties 可以继承 bootstrap.properties 中的配置。这意味着,如果在 bootstrap.properties 中配置了某些属性,而在 application.properties 中没有重新定义,那么应用程序会使用 bootstrap.properties 中的配置。

什么是 Spring Profiles?

Spring Profiles 是 Spring Framework 提供的一种机制,用于根据不同的环境或配置文件选择性地加载和应用不同的配置。通过使用 Spring Profiles,可以在同一个应用程序中定义多个不同的配置集合,以适应不同的部署环境或应用需求。

使用 Spring Profiles 可以实现以下功能

1. 配置分离:将应用程序的配置信息根据不同的环境或需求进行分离,避免在单个配置文件中包含大量的条件判断和配置项。

2. 灵活切换配置:通过激活不同的 Profile,可以在不同的环境中切换配置,如开发环境、测试环境和生产环境。

3. 条件化加载:可以根据特定的条件选择性地加载和应用某些配置,从而实现更灵活的配置管理。

使用 Spring Profiles 的步骤

1. 在配置文件中定义不同的 Profile,可以使用 `application-{profile}.yml`(或 `application-{profile}.properties`)的命名方式。

2. 在配置文件中根据 Profile 进行配置,可以覆盖或扩展默认的配置。

3. 在应用程序中通过激活 Profile 的方式来加载对应的配置,可以使用 `spring.profiles.active` 属性来指定激活的 Profile。

Spring Profiles 提供了一种灵活和可扩展的配置管理机制,可以根据不同的环境和需求来管理和加载配置,使应用程序更具可配置性和可移植性。

骚戴理解:例如,在 `application.yml` 中定义了 `dev` 和 `prod` 两个 Profile,可以分别配置开发环境和生产环境的数据库连接信息。然后,通过设置 `spring.profiles.active` 属性来激活对应的 Profile,从而加载相应的配置。

实际开发中会同时存在dev、uat、prod等多套环境,这些环境共用一套代码逻辑,但却需要不同的配置。例如dev环境要连接测试数据库,而prod则需要连接生产数据库等等。profile最主要的目的就是可以区分不同的环境,进而对不同环境进行配置

当profile为default时,只使用application.yaml,SpringBoot默认Server端口为8080。将当前profile激活为dev时, SpringBoot就会额外加载application-dev.yaml 后合并到application.yaml中,若其中有相同的配置则覆盖掉。

案例分析

spring:
  profiles:
    active: dev

---

spring:
  profiles: dev
  datasource:
    url: jdbc:mysql://localhost:3306/devdb
    username: devuser
    password: devpassword

---

spring:
  profiles: prod
  datasource:
    url: jdbc:mysql://localhost:3306/proddb
    username: produser
    password: prodpassword

在上述示例中,通过 `spring.profiles.active` 配置了激活的环境为 `dev`。然后,使用 `---` 分隔符定义了不同环境下的配置。在 `dev` 环境下,配置了开发数据库的连接信息;在 `prod` 环境下,配置了生产数据库的连接信息。

如何在自定义端口上运行 Spring Boot 应用程序?

为了在自定义端口上运行 Spring Boot 应用程序,您可以在application.properties 中指定端口。server.port = 8090

如何实现 Spring Boot 应用程序的安全性?

为了实现 Spring Boot 的安全性,我们使用SpringSecurity框架来实现,首先导入这个框架的

spring-boot-starter-security 依赖项,并且必须添加安全配置。它只需要很少的代码。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

由于springboot对starter依赖进行了自动化的配置,即约定大于配置,也就是带有starter的依赖在整合springboot时,在我们不做任何配置时,默认使用starter约定的配置,只有当我们进行自定义配置时,springboot才会使用我们的配置

创建一个配置类来定义认证和授权规则,配置类必须扩展WebSecurityConfigurerAdapter 并覆盖其configure方法。并使用 @EnableWebSecurity 注解启用 Spring Security

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/user/**").hasAnyRole("ADMIN", "USER")
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .logout()
            .logoutUrl("/logout")
            .logoutSuccessUrl("/login")
            .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("admin").password("{noop}admin123").roles("ADMIN")
            .and()
            .withUser("user").password("{noop}user123").roles("USER");
    }
}

上述代码定义了以下规则:

  • /admin/** 路径需要具有 ADMIN 角色的用户才能访问。
  • /user/** 路径需要具有 ADMIN 或 USER 角色的用户才能访问。
  • 其他所有路径需要进行身份验证。
  • 使用基于表单的登录进行认证。
  • 定义了两个用户:admin(具有 ADMIN 角色)和 user(具有 USER 角色)。

请注意,上述示例中的密码使用了 {noop} 前缀,这表示密码不会进行加密处理(仅用于示例,请勿在实际生产环境中使用明文密码)。

最后,可以在 application.properties 文件中配置一些基本的安全属性,如下所示:

spring.security.user.name=admin

spring.security.user.password=admin123

这是一个简单的示例,用于演示如何使用 Spring Security 实现基本的认证和授权。

Spring Boot 中如何解决跨域问题 ?

跨域问题现象

been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource

上面的意思就是 你访问一个什么地址被CORS 协议阻止, 没有 在Hearder 里面发现 Access-Control-Allow-Origin 的参数的资源

跨域问题的原因

跨域问题的原因是浏览器的同源策略(Same-Origin Policy),该策略限制了不同源之间的交互。

什么是同源策略?

同源策略(Same-Origin Policy)是一种安全策略,用于保护Web浏览器中的文档对象模型(DOM)免受恶意网站的攻击。它是一种浏览器的安全机制,用于限制一个源(包括协议、域名和端口)的文档或脚本如何与其他源的资源进行交互。

同源策略的原则是:只有当两个页面具有相同的协议(HTTP或HTTPS)、主机名和端口号时,它们才被认为是同源的。如果两个页面不满足同源策略,那么它们之间的交互将受到限制。

同源策略的目的是防止恶意网站通过跨域请求或访问其他网站的敏感数据,从而保护用户的隐私和安全。例如,如果一个网站加载了一个恶意脚本,它将无法通过XMLHttpRequest或Fetch API发送跨域请求到其他网站,因为浏览器会阻止这种行为。

然而,同源策略也可能会限制一些合法的跨域请求,为了解决这个问题,可以使用CORS(跨域资源共享)机制来实现跨域访问的控制。

总结起来,同源策略是一种浏览器安全机制,用于限制不同源之间的交互,以保护用户的隐私和安全。它是Web安全的重要组成部分。

什么是源和跨域

源(origin)就是协议、域名和端口号。

URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口全部相同,则表示他们同源。否则,只要协议、域名、端口有任何一个不同就是跨域。

对https://www.baidu.com/index.html进行跨域比较:

Spring Boot跨域问题解决方案

1. 使用`@CrossOrigin`注解:可以在Controller类或具体的请求处理方法上添加`@CrossOrigin`注解来指定允许跨域访问的域名。

在Spring Boot应用程序的配置类或者Web配置类中添加一个CorsFilter bean

@Configuration
public class WebConfig {

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*"); // 允许所有域名进行跨域访问,可以根据需求进行配置
        config.addAllowedMethod("*"); // 允许所有HTTP方法进行跨域访问
        config.addAllowedHeader("*"); // 允许所有请求头进行跨域访问
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

在Controller类或者具体的请求处理方法上添加@CrossOrigin注解,以允许特定的跨域请求

@RestController
public class MyController {

    @CrossOrigin(origins = "http://example.com") // 允许http://example.com进行跨域访问
    @GetMapping("/api/data")
    public String getData() {
        // 处理请求并返回数据
        return "Data";
    }
}

在上述代码中,使用@CrossOrigin注解来指定允许跨域访问的域名。可以根据需要配置多个域名,或者使用通配符"*"来允许所有域名进行跨域访问。

2. 使用全局配置类:可以创建一个全局配置类,继承`WebMvcConfigurerAdapter`并重写`addCorsMappings`方法,配置全局的跨域访问规则。

@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://example.com") // 允许http://example.com进行跨域访问
                .allowedMethods("*") // 允许所有HTTP方法进行跨域访问
                .allowedHeaders("*"); // 允许所有请求头进行跨域访问
    }
}

3. 使用过滤器:可以创建一个自定义的过滤器来处理跨域请求,设置相应的响应头信息。

@Component
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "http://example.com"); // 允许http://example.com进行跨域访问
        httpServletResponse.setHeader("Access-Control-Allow-Methods", "*"); // 允许所有HTTP方法进行跨域访问
        httpServletResponse.setHeader("Access-Control-Allow-Headers", "*"); // 允许所有请求头进行跨域访问
        chain.doFilter(request, response);
    }
}

4. 使用Spring Security配置:如果你的应用程序使用了Spring Security,可以在配置类中添加相应的跨域配置。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors(); // 开启跨域支持
        // 其他的安全配置
    }
}

什么是 CSRF 攻击?

CSRF(Cross-site request forgery)也被称为 one-click attack或者 session riding,中文全称是叫跨站请求伪造。一般来说,攻击者通过伪造用户的浏览器的请求,向访问一个用户自己曾经认证访问过的网站发送出去,使目标网站接收并误以为是用户的真实操作而去执行命令。常用于盗取账号、转账、发送虚假消息等。攻击者利用网站对请求的验证漏洞而实现这样的攻击行为,网站能够确认请求来源于用户的浏览器,却不能验证请求是否源于用户的真实意愿下的操作行为。

CSRF(Cross-Site Request Forgery)攻击是一种利用受信任用户的身份执行非预期操作的攻击方式。攻击者通过诱使用户在已登录的受信任网站上执行恶意操作,从而利用用户的身份发送未经授权的请求。

具体来说,CSRF攻击的过程如下:

1. 用户登录受信任网站A,并获取了一个有效的会话凭证(例如通过Cookie)。
2. 用户在不知情的情况下访问了恶意网站B。
3. 恶意网站B中的恶意代码会自动向受信任网站A发送一个请求,该请求会利用用户的会话凭证执行某个操作(例如修改用户信息、发起资金转账等)。
4. 受信任网站A接收到请求后,由于请求中包含了有效的会话凭证,会误认为是用户本人发出的请求,从而执行了恶意操作。

CSRF攻击的危害在于它可以利用用户的身份执行一些非法或未授权的操作,例如篡改用户信息、发起资金转账、删除重要数据等。攻击者通常会利用社交工程、钓鱼网站、恶意广告等方式来引诱用户点击恶意链接或访问恶意网站,从而触发CSRF攻击。

为了防止CSRF攻击,可以采取以下几种防御措施:

1. 使用CSRF令牌:在每个表单或请求中添加一个CSRF令牌,该令牌由服务器生成并与用户会话相关联。在处理请求时,服务器会验证令牌的有效性,只有在令牌有效的情况下才执行操作。
2. 检查Referer头:服务器可以检查请求中的Referer头,确保请求来源于合法的域名。然而,这种方法并不完全可靠,因为有些浏览器可能会禁用或修改Referer头。
3. 使用SameSite Cookie属性:将Cookie的SameSite属性设置为Strict或Lax,限制Cookie只能在同源请求中发送,从而防止跨域请求中的CSRF攻击。
4. 避免使用GET请求进行敏感操作:将敏感操作改为使用POST、PUT、DELETE等非GET请求,因为GET请求可以通过URL链接进行CSRF攻击。

综上所述,采取适当的防御措施可以有效防止CSRF攻击,保护用户的安全和隐私。

Spring Boot 中的监视器是什么?

监视器就是一个类似现实生活中的监控,但是它监控的是程序内部运行情况。Spring Boot自带监控组件—Actuator,它就负责监控程序的健康状况、Bean加载情况、环境变量、日志信息、线程信息等,Actuator的核心是端点(Endpoint),它用来监视、提供应用程序的信息,Spring Boot提供的spring-boot-actuator组件中已经内置了非常多的Endpoint(health、info、beans、metrics、httptrace、shutdown等),每个端点都可以启用和禁用。

在Spring Boot中,监视器(Actuator)是一个用于监控和管理应用程序的模块。它提供了一组RESTful接口,可以用于获取应用程序的各种健康指标、性能指标和运行时信息。通过监视器,你可以实时监控应用程序的运行状态、调整配置参数、查看日志等。

Spring Boot的监视器模块提供了以下一些常用的功能:

1. 健康检查(Health Check):通过`/actuator/health`端点可以获取应用程序的健康状态,包括是否存活、是否就绪等。你可以使用该端点来监控应用程序是否正常运行。

2. 信息端点(Info Endpoint):通过`/actuator/info`端点可以获取应用程序的自定义信息,例如版本号、构建信息等。

3. 环境端点(Environment Endpoint):通过`/actuator/env`端点可以获取应用程序的环境变量和配置属性信息。

4. 日志配置端点(Log Configuration Endpoint):通过`/actuator/loggers`端点可以获取和修改应用程序的日志配置信息,例如设置日志级别、添加日志输出器等。

5. 线程转储端点(Thread Dump Endpoint):通过`/actuator/threaddump`端点可以获取应用程序的线程转储信息,用于分析应用程序的线程状态和性能问题。

6. 执行器端点(Custom Endpoints):除了上述内置的端点外,你还可以自定义其他的端点,用于获取应用程序的特定信息或执行特定的操作。

通过在Spring Boot应用程序中添加`spring-boot-starter-actuator`依赖,监视器模块将被自动启用,并提供上述功能。你可以通过配置文件或代码来配置监视器的端点路径、安全性等。

总之,Spring Boot的监视器模块提供了一系列有用的端点,可以帮助你监控和管理应用程序的运行状态,从而更好地了解和调试应用程序。

如何在 Spring Boot 中禁用 Actuator 端点的安全性?

在Spring Boot中,可以通过配置来禁用Actuator端点的安全性。默认情况下,Actuator端点是受保护的,需要进行身份验证才能访问。以下是禁用Actuator端点安全性的几种方法:

1. application.properties配置文件:在`application.properties`文件中添加以下配置来禁用Actuator端点的安全性:

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

2. application.yml配置文件:在`application.yml`文件中添加以下配置来禁用Actuator端点的安全性:

management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always

3. 使用Java配置:创建一个配置类,继承`WebSecurityConfigurerAdapter`,重写`configure(HttpSecurity http)`方法,并禁用Actuator端点的安全性。

@Configuration
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .requestMatchers(EndpointRequest.toAnyEndpoint())
            .permitAll()
            .and()
            .csrf().disable();
    }
}

请注意,禁用Actuator端点的安全性会使所有的Actuator端点对外开放,任何人都可以访问。因此,需要谨慎使用,并确保只在安全的环境中使用。另外,禁用Actuator端点的安全性可能会导致安全风险,请确保在生产环境中仔细评估和测试。

我们如何监视所有 Spring Boot 微服务?

Spring Boot 提供监视器端点来监控。这些端点对于获取有关应用程序的信息(如它们是否已启动)以及它们的组件(如数据库等)是否正常运行很有帮助。但是,使用监视器的一个主要缺点或困难是,我们必须单独打开应用程序的端点来了解其状态或健康状况。想象一下涉及 50 个应用程序的微服务,管理员将不得不击中所有 50 个应用程序的执行终端。为了帮助我们处理这种情况,我们将使用位于 GitHub - codecentric/spring-boot-admin: Admin UI for administration of spring boot applications 的开源项目。 它建立在 Spring Boot Actuator 之上,它提供了一个 Web UI,使我们能够可视化多个应用程序的度量。

如何集成 Spring Boot 和 ActiveMQ?

Spring Boot针对ActiveMQ专门提供了spring-boot-starter-activemq,用来支持ActiveMQ在Spring Boot的自动集成配置。在此基础上我们可以很轻易的进行集成和使用。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>

要集成Spring Boot和ActiveMQ,你可以使用Spring Boot提供的JMS(Java Message Service)支持,在`application.properties`文件中配置ActiveMQ的连接信息:

spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin

接下来,创建一个消息发送者和一个消息接收者。

1. 消息发送者:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

@Component
public class MessageSender {

    @Autowired
    private JmsTemplate jmsTemplate;

    public void sendMessage(String message) {
        jmsTemplate.convertAndSend("myQueue", message);
    }
}

2. 消息接收者:

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class MessageReceiver {

    @JmsListener(destination = "myQueue")
    public void receiveMessage(String message) {
        System.out.println("Received message: " + message);
    }
}

在上述示例中,消息发送者通过`JmsTemplate`将消息发送到名为`myQueue`的队列中,而消息接收者使用`@JmsListener`注解监听`myQueue`队列,并在收到消息时进行处理。

最后,你可以在任何需要发送消息的地方注入`MessageSender`,调用`sendMessage`方法发送消息。

需要注意的是,如果你使用的是默认的ActiveMQ配置,你需要确保ActiveMQ服务器已经启动,并且连接信息与`application.properties`中的配置相匹配。

这只是一个简单的示例,你可以根据自己的需求进行扩展和定制。通过集成Spring Boot和ActiveMQ,你可以方便地在应用程序中使用JMS来进行消息的发送和接收。

前后端分离如何维护接口文档 ?

在 Spring Boot 中,这个问题常见的解决方案是 Swagger ,使用 Swagger 我们可以快速生成一个在线接口文档,控制器的内容一旦发生变化,文档就会自动更新,所有开发工程师访问这一个在线网站就可以获取到最新的接口文档,非常方便。

什么是 Swagger?你用 Spring Boot 实现了它吗?

Swagger 是一个可视化 RESTful 风格的 Web 服务框架,支持 API 自动生成同步的在线文档:使用 Swagger 后可以直接通过代码生成文档,不再需要自己手动编写接口文档了,Swagger 生成的文档还支持在线测试。参数和格式都定好了,直接在界面上输入参数对应的值即可在线测试接口。

@Api:用在请求的类上,表示对类的说明
    tags="说明该类的作用,可以在UI界面上看到的注解"
    value="该参数没什么意义,在UI界面上也看到,所以不需要配置"
 
 
@ApiOperation:用在请求的方法上,说明方法的用途、作用
    value="说明方法的用途、作用"
    notes="方法的备注说明"
 
 
@ApiImplicitParams:用在请求的方法上,表示一组参数说明
    @ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
        name:参数名
        value:参数的汉字说明、解释
        required:参数是否必须传
        paramType:参数放在哪个地方
            · header --> 请求参数的获取:@RequestHeader
            · query --> 请求参数的获取:@RequestParam
            · path(用于restful接口)--> 请求参数的获取:@PathVariable
            · body(不常用)
            · form(不常用)    
        dataType:参数类型,默认String,其它值dataType="Integer"       
        defaultValue:参数的默认值
 
 
@ApiResponses:用在请求的方法上,表示一组响应
    @ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
        code:数字,例如400
        message:信息,例如"请求参数没填好"
        response:抛出异常的类
 
 
@ApiModel:用于响应类上,表示一个返回响应数据的信息
            (这种一般用在post创建的时候,使用@RequestBody这样的场景,
            请求参数无法使用@ApiImplicitParam注解进行描述的时候)
    @ApiModelProperty:用在属性上,描述响应类的属性

Swagger使用案例

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 1. swagger配置类
 */
@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                //是否开启 (true 开启  false隐藏。生产环境建议隐藏)
                //.enable(false)
                .select()
                //扫描的路径包,设置basePackage会将包下的所有被@Api标记类的所有方法作为api
                .apis(RequestHandlerSelectors.basePackage("com.mcy.springbootswagger.controller"))
                //指定路径处理PathSelectors.any()代表所有的路径
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                //设置文档标题(API名称)
                .title("SpringBoot中使用Swagger2接口规范")
                //文档描述
                .description("接口说明")
                //服务条款URL
                .termsOfServiceUrl("http://localhost:8080/")
                //版本号
                .version("1.0.0")
                .build();
    }
}

@EnableSwagger2的作用是启用Swagger2相关功能。

import com.mcy.springbootswagger.User.User;
import com.mcy.springbootswagger.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
//说明接口文件
@Api(value = "测试接口", tags = "用户管理相关的接口", description = "用户测试接口")
public class UserController {
    @Autowired
    private UserService userService;

    /**
     * 保存数据
     * @param user
     * @return
     */
    @PostMapping(value = "/save")
    //方法参数说明,name参数名;value参数说明,备注;dataType参数类型;required 是否必传;defaultValue 默认值
    @ApiImplicitParam(name = "user", value = "新增用户数据")
    //说明是什么方法(可以理解为方法注释)
    @ApiOperation(value = "添加用户", notes = "添加用户")
    public String saveUser(User user){
        userService.save(user);
        return "保存成功";
    }

    /**
     * 根据id查询用户
     * @param id
     * @return
     */
    @GetMapping(value = "findById")
    @ApiOperation(value = "根据id获取用户信息", notes = "根据id查询用户信息")
    public User getUser(Integer id){
        return userService.findById(id);
    }

    @DeleteMapping(value = "deleteById")
    @ApiOperation(value = "根据id删除数据", notes = "删除用户")
    public String delete(Integer id){
        userService.deleteById(id);
        return "删除成功";
    }
}

运行项目,输入http://localhost:8080/swagger-ui.html访问Swagger页面,页面如下:

如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?(热部署)

这可以使用 DEV 工具来实现。通过这种依赖关系,您可以节省任何更改,嵌入式tomcat 将重新启动。Spring Boot 有一个开发工具(DevTools)模块,它有助于提高开发人员的生产力。Java 开发人员面临的一个主要挑战是将文件更改自动部署到服务器并自动重启服务器。开发人员可以重新加载 Spring Boot 上的更改,而无需重新启动服务器。这将消除每次手动部署更改的需要。Spring Boot 在发布它的第一个版本时没有这个功能。这是开发人员最需要的功能。DevTools 模块完全满足开发人员的需求。该模块将在生产环境中被禁用。它还提供 H2 数据库控制台以更好地测试应用程序。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
</dependency>  

骚戴理解:Spring也是支持热部署的!

你使用了哪些 starter maven 依赖项?

常用的Spring Boot Starter Maven依赖项,这些依赖项可以帮助你快速集成各种功能和技术:

  1. spring-boot-starter-web:用于构建Web应用程序,包括Spring MVC、Tomcat等。
  2. spring-boot-starter-data-jpa:用于使用JPA(Java Persistence API)访问和操作数据库。
  3. spring-boot-starter-data-mongodb:用于使用MongoDB数据库。
  4. spring-boot-starter-data-redis:用于使用Redis数据库。
  5. spring-boot-starter-security:用于集成Spring Security,实现身份验证和授权功能。
  6. spring-boot-starter-test:用于编写单元测试和集成测试。
  7. spring-boot-starter-actuator:用于监控和管理应用程序的运行时行为。
  8. spring-boot-starter-amqp:用于使用AMQP(Advanced Message Queuing Protocol)进行消息传递。
  9. spring-boot-starter-cache:用于启用应用程序级缓存功能。
  10. spring-boot-starter-mail:用于发送电子邮件。
  11. spring-boot-starter-oauth2-client:用于集成OAuth2客户端功能。
  12. spring-boot-starter-websocket:用于启用WebSocket功能。
  13. mybatis-spring-boot-starter:用于mybatis

Spring Boot 中的 starter 到底是什么 ?

在Spring Boot中,starter是一种特殊的Maven依赖项,它用于简化项目的配置和依赖管理。Starter依赖项是预定义的、可重用的依赖项集合,它们封装了一组相关的依赖项,用于快速集成和启动特定的功能或技术。当你添加一个特定的starter依赖项时,它会自动引入所需的相关依赖项,并进行默认的配置。这样,你可以快速启动并集成各种功能和技术,而无需手动处理复杂的依赖项和配置。

Spring Boot的starter依赖项遵循一种命名约定,通常以`spring-boot-starter-`开头,后面跟着特定功能或技术的名称。例如,`spring-boot-starter-web`是用于构建Web应用程序的starter依赖项,`spring-boot-starter-data-jpa`是用于集成JPA的starter依赖项。

使用starter依赖项的好处是,它们自动处理了依赖项的版本管理和配置,简化了项目的构建和配置过程。另外,Spring Boot还提供了一些其他类型的starter依赖项,例如`spring-boot-starter-test`用于编写测试,`spring-boot-starter-actuator`用于监控和管理应用程序的运行时行为。这些starter依赖项使得在Spring Boot项目中集成常用的功能和技术变得更加简单和便捷。

骚戴理解:Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成Spring及其他技术,而不需要到处找依赖包。Starters包含了许多项目中需要用到的依赖,它们能快速持续的运行,都是一系列得到支持的管理传递性依赖。

和自动配置一样,Spring Boot Starter的目的也是简化配置,而Spring Boot Starter解决的是依赖管理配置复杂的问题,有了它,当我需要构建一个Web应用程序时,不必再遍历所有的依赖包,一个一个地添加到项目的依赖管理中,而是只需要一个配置spring-boot-starter-web, 同理,如果想引入持久化功能,可以配置spring-boot-starter-data-jpa:

spring-boot-starter-parent 有什么用 ?

  1. 统一的版本管理:spring-boot-starter-parent中定义了Spring Boot及其相关依赖项的版本号。这样,你在项目中引入其他的Spring Boot Starter依赖项时,无需手动指定版本号,而是继承自spring-boot-starter-parent

  2. 默认的插件配置:spring-boot-starter-parent中配置了一些常用的Maven插件,并定义了一些默认的插件配置。这些插件和配置可以帮助你简化项目的构建过程,例如自动执行测试、打包可执行的JAR文件等。

  3. 通用的属性定义:spring-boot-starter-parent中定义了一些通用的属性,例如编译器版本、编码规范、资源过滤等。这些属性可以在项目中直接使用,提供了一致的配置和约定。

Spring Boot 打成的 jar 和普通的 jar 有什么区别 ?

1、Spring Boot 中默认打包成的 jar 叫做 可执行 jar,这种 jar 不可以被其他项目依赖,即使强制依赖,也无法获取里边的类。但是普通的 jar 主要是被其他应用依赖,但是可执行 jar 并不是 Spring Boot 独有的,Java 工程本身就可以打包成可执行 jar

2、普通的 jar 不可以通过 java -jar xxx.jar 命令执行,Spring Boot 打成的 jar 可以通过 java -jar xxx.jar 命令执行执行

3、主要是两者的结构不同。普通的 jar 包,解压后直接就是包名,包里就是我们的代码,而 Spring Boot 打包成的可执行 jar 解压后,在 \BOOT-INF\classes 目录下才是我们的代码,因此无法被直接引用。如果非要引用,可以在 pom.xml 文件中增加配置,将 Spring Boot 项目打包成两个 jar ,一个可执行, 一个可引用。

运行 Spring Boot 有哪几种方式?

运行Spring Boot应用程序有以下几种方式:

1. 使用IDE运行:在大多数集成开发环境(IDE)中,你可以直接运行Spring Boot应用程序。通常,你需要在IDE中配置一个运行配置,指定主类(包含`@SpringBootApplication`注解的类),然后点击运行按钮即可启动应用程序。

2. 使用Maven命令运行:通过命令行使用Maven命令也可以运行Spring Boot应用程序。在项目根目录下,使用以下命令:

  mvn spring-boot:run

这将使用Maven插件启动Spring Boot应用程序。

3. 打包成可执行的JAR文件并运行:使用Maven或Gradle构建项目时,可以将Spring Boot应用程序打包成可执行的JAR文件。在项目根目录下,使用以下命令进行构建:

mvn clean package

构建完成后,在`target`目录下会生成一个JAR文件。然后,你可以使用以下命令运行应用程序:

 java -jar your-application.jar

4. 使用Spring Boot DevTools进行热部署:Spring Boot DevTools是一个开发工具,它提供了热部署的功能,可以在应用程序运行时自动检测代码更改并重新加载。你可以将Spring Boot应用程序作为普通的Java应用程序运行,然后在开发过程中进行代码更改,DevTools会自动重新启动应用程序以应用更改。

Spring Boot 需要独立的容器运行吗?

不需要,内置了 Tomcat/ Jetty 等容器。

开启 Spring Boot 特性有哪几种方式?

1、继承spring-boot-starter-parent项目

<parent>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.6.RELEASE</version>
</parent>

这个时候再导入我们需要的springboot starter时,就可以忽略版本号:

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
	    <artifactId>spring-boot-starter</artifactId>
	</dependency>
</dependencies>

2、导入spring-boot-dependencies项目依赖

<dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>1.5.4.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
</dependencyManagement>

这个时候再导入我们需要的springboot starter时,就可以忽略版本号:

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
	    <artifactId>spring-boot-starter</artifactId>
	</dependency>
</dependencies>

如何使用 Spring Boot 实现异常处理?

1、使用 @ExceptionHandler 注解处理局部异常(只能处理当前controller中的ArithmeticException和NullPointerException异常,缺点就是只能处理单个controller的异常)

@Controller
public class ExceptionHandlerController {
    
    @RequestMapping("/excep")
    public String exceptionMethod(Model model) throws Exception {
        String a=null;
        System.out.println(a.charAt(1));
        int num = 1/0;
        model.addAttribute("message", "没有抛出异常");
        return "index";
    }
    
    @ExceptionHandler(value = {ArithmeticException.class,NullPointerException.class})
    public String arithmeticExceptionHandle(Model model, Exception e) {
        model.addAttribute("message", "@ExceptionHandler" + e.getMessage());
        return "index";
    }
}

2、使用 @ControllerAdvice + @ExceptionHandler 注解处理全局异常(value后面可以填写数组),Spring 提供了一种使用 ControllerAdvice 处理异常的非常有用的方法。 我们通过实现一个 ControlerAdvice 类,来处理控制器类抛出的所有异常。

@ControllerAdvice
public class ControllerAdviceException {
	
	@ExceptionHandler(value = {NullPointerException.class})
	public String NullPointerExceptionHandler(Model model, Exception e) {
		model.addAttribute("message", "@ControllerAdvice + @ExceptionHandler :" + e.getMessage());
		return "index";
	}
}

3、配置 SimpleMappingExceptionResolver 类处理异常(配置类)

@Configuration
public class SimpleMappingException {
	@Bean
	public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){

		SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
		Properties mappings = new Properties();
		//第一个参数为异常全限定名,第二个为跳转视图名称
		mappings.put("java.lang.NullPointerException", "index");
		mappings.put("java.lang.ArithmeticException", "index");
		//设置异常与视图映射信息的
		resolver.setExceptionMappings(mappings);
		return resolver;
	}
}

4、实现 HandlerExceptionResolver 接口处理异常,重写resolveException方法

@Configuration
public class HandlerException implements HandlerExceptionResolver {
	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

		ModelAndView modelAndView = new ModelAndView();
		modelAndView.addObject("message", "实现HandlerExceptionResolver接口");

		//判断不同异常类型,做不同视图跳转
		if(ex instanceof NullPointerException){
			modelAndView.setViewName("index");
		}
		if(ex instanceof ArithmeticException){
			modelAndView.setViewName("index");
		}
		return modelAndView;
	}
}

如何使用 Spring Boot 实现分页和排序?

在Spring Boot中,你可以使用Spring Data JPA来实现分页和排序功能。Spring Data JPA提供了`Pageable`接口和`Sort`类,用于定义分页和排序的参数。

下面是一个使用Spring Boot实现分页和排序的示例:

首先,定义一个Repository接口,继承自`JpaRepository`,并添加一个方法,使用`Pageable`参数来实现分页和排序:

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
    Page<User> findAll(Pageable pageable);
}

然后,在你的Service或Controller中注入该Repository,并使用`PageRequest`来创建一个`Pageable`对象,指定分页和排序的参数:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public Page<User> getUsers(int pageNo, int pageSize, String sortBy) {
        Pageable pageable = PageRequest.of(pageNo, pageSize, Sort.by(sortBy));
        return userRepository.findAll(pageable);
    }
}

  Pageable pageable = PageRequest.of(pageNo, pageSize, Sort.by(sortBy));

最后,在你的Controller中调用Service方法,传入分页和排序的参数,获取分页结果:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/users")
    public Page<User> getUsers(
            @RequestParam(defaultValue = "0") int pageNo,
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(defaultValue = "id") String sortBy) {
        return userService.getUsers(pageNo, pageSize, sortBy);
    }
}

在上述示例中,`getUsers`方法接收三个参数:`pageNo`表示页码,`pageSize`表示每页大小,`sortBy`表示按照哪个字段排序。通过调用`userRepository.findAll(pageable)`方法,可以获取到按照指定分页和排序参数查询的结果。

通过访问`/users`接口,传入相应的参数,即可获取到分页和排序的结果。

Spring Boot 中如何实现定时任务 ?

定时任务也是一个常见的需求,Spring Boot 中对于定时任务的支持主要还是来自 Spring 框架。

在 Spring Boot 中使用定时任务主要有两种不同的方式

  • 使用 Spring 中的 @Scheduled 注解
  • 使用第三方框架 Quartz。

@Scheduled 注解

在Spring Boot中,你可以使用`@Scheduled`注解来实现定时任务。通过在方法上添加`@Scheduled`注解,并指定任务的执行时间表达式,即可实现定时任务的调度。

下面是一个使用Spring Boot实现定时任务的示例:

为了使用定时任务功能,需要在`pom.xml`文件中添加`spring-boot-starter-task`依赖项 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-task</artifactId>
</dependency>

在你的Spring Boot应用程序的配置类或任意一个Bean上添加`@EnableScheduling`注解,启用定时任务功能:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

然后,在你的定时任务类中定义一个方法,并使用`@Scheduled`注解来指定任务的执行时间表达式:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class MyTask {
    @Scheduled(cron = "0 0 0 * * ?") // 每天凌晨执行
    public void myTaskMethod() {
        // 定时任务的具体逻辑
        System.out.println("定时任务执行了!");
    }
}

在上述示例中,`myTaskMethod`方法使用`@Scheduled`注解,并指定了一个cron表达式`0 0 0 * * ?`,表示每天凌晨执行一次。你可以根据自己的需求,设置不同的时间表达式来调度定时任务。

最后,运行你的Spring Boot应用程序,定时任务将会按照指定的时间表达式进行调度执行。

请注意,上述示例中的定时任务方法需要在一个被Spring容器管理的Bean中定义,因此添加了`@Component`注解。如果你的定时任务方法不在一个Bean中,可以使用`@Configuration`或者`@Bean`注解来创建一个Bean,并在其中定义定时任务方法。

这样,你就可以在Spring Boot中轻松实现定时任务了。

Quartz框架

Quartz是一个功能强大的Java调度框架,可以用于实现各种复杂的定时任务和调度需求。

下面是一个使用Quartz框架的简单示例:

首先,需要添加Quartz的依赖项。在你的Maven项目中,可以在`pom.xml`文件中添加以下依赖项:

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
</dependency>

然后,在你的Spring Boot应用程序中创建一个Quartz配置类,用于配置Quartz的调度器和任务:

import org.quartz.JobDetail;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetailFactoryBean jobDetail() {
        JobDetailFactoryBean factory = new JobDetailFactoryBean();
        factory.setJobClass(MyJob.class); // 指定任务类
        factory.setDurability(true); // 设置任务持久化
        return factory;
    }

    @Bean
    public Trigger trigger(JobDetail jobDetail) {
        TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
        triggerBuilder.forJob(jobDetail);
        triggerBuilder.withSchedule(SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10) // 每隔10秒执行一次
                .repeatForever()); // 无限重复执行
        return triggerBuilder.build();
    }

    @Bean
    public SchedulerFactoryBean scheduler(Trigger trigger) {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setTriggers(trigger);
        return factory;
    }
}

在上述示例中,我们创建了一个`JobDetail`对象,用于定义任务的具体执行逻辑和属性。然后,创建了一个`Trigger`对象,用于定义任务的触发条件和执行频率。最后,创建了一个`SchedulerFactoryBean`对象,用于配置Quartz的调度器,并将`Trigger`对象设置为触发器。接下来,创建一个继承自`org.quartz.Job`接口的任务类,实现具体的任务逻辑:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        // 任务逻辑
        System.out.println("Quartz定时任务执行了!");
    }
}

最后,在你的Spring Boot应用程序的启动类中添加`@EnableScheduling`注解,启用定时任务功能:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

现在,当你运行Spring Boot应用程序时,Quartz将会按照配置的调度规则执行定时任务。

请注意,上述示例中的定时任务是基于Quartz框架的,与Spring Boot的定时任务(`@Scheduled`)是不同的。Quartz提供了更灵活和强大的定时任务功能,适用于复杂的调度需求。如果你只有简单的定时任务需求,可以直接使用Spring Boot的定时任务功能。

Starters的命名和分类

Starters命名

Spring Boot官方的启动器都是以spring-boot-starter-命名的,代表了一个特定的应用类型。第三方的启动器不能以spring-boot开头命名,它们都被Spring Boot官方保留。一般一个第三方的应该这样命名,像mybatis的mybatis-spring-boot-starter。

常见的Starters的分类和命名示例:

在Spring Boot中,Starters是一组依赖项的集合,用于简化应用程序的构建和配置。Starters的命名和分类遵循一定的规则,以便开发人员能够快速找到所需的功能。

Starters的命名通常遵循以下模式:`spring-boot-starter-{name}`,其中`{name}`表示所提供功能的名称或领域。下面是一些常见的Starters的分类和命名示例:

1. 核心Starters:
   - `spring-boot-starter-web`:用于构建基于Web的应用程序,包含Spring MVC、Tomcat等。
   - `spring-boot-starter-data-jpa`:用于与关系型数据库进行交互,包含Spring Data JPA、Hibernate等。
   - `spring-boot-starter-data-mongodb`:用于与MongoDB进行交互,包含Spring Data MongoDB等。
   - `spring-boot-starter-security`:用于实现应用程序的安全性,包含Spring Security等。

2. 数据库Starters:
   - `spring-boot-starter-jdbc`:用于使用JDBC进行数据库操作。
   - `spring-boot-starter-data-redis`:用于与Redis进行交互,包含Spring Data Redis等。
   - `spring-boot-starter-amqp`:用于与消息队列进行交互,包含Spring AMQP等。

3. 测试Starters:
   - `spring-boot-starter-test`:用于编写单元测试和集成测试,包含JUnit、Mockito等。

4. 云平台Starters:
   - `spring-boot-starter-cloud-connectors`:用于在云平台上连接各种服务,如数据库、消息队列等。
   - `spring-boot-starter-aws`:用于与亚马逊Web服务(AWS)进行交互,包含AWS SDK等。

除了上述示例之外,还有许多其他的Starters可用,覆盖了各种不同的功能和领域,如批处理、安全认证、缓存等。你可以在Spring Boot官方文档中查找完整的Starters列表,并根据你的需求选择适合的Starters来简化你的应用程序开发和配置。

如何在Spring Boot启动的时候运行一些特定的代码?

在Spring Boot中,你可以使用`CommandLineRunner`或`ApplicationRunner`接口来在应用程序启动时运行一些特定的代码。这两个接口都提供了一个`run`方法,在应用程序启动完成后会被自动调用。

下面是使用`CommandLineRunner`的示例:

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class MyCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        // 在应用程序启动后执行的代码
        System.out.println("应用程序启动成功!");
    }
}

在上述示例中,我们创建了一个实现了`CommandLineRunner`接口的类`MyCommandLineRunner`,并重写了`run`方法。在`run`方法中,你可以编写任何你希望在应用程序启动后执行的代码。

另外,你还可以使用`@Order`注解来指定多个`CommandLineRunner`或`ApplicationRunner`的执行顺序。较小的值具有更高的优先级。

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(1)
public class MyApplicationRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 在应用程序启动后执行的代码
        System.out.println("应用程序启动成功!");
    }
}

在上述示例中,我们创建了一个实现了`ApplicationRunner`接口的类`MyApplicationRunner`,并使用`@Order(1)`注解指定了执行顺序为1。

以下是一个使用`ApplicationRunner`的简单示例:

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationRunner implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("应用程序启动成功!");
        
        // 在应用程序启动后执行其他操作
        // 例如初始化一些数据、调用外部API等
    }
}

在上述示例中,我们创建了一个名为`MyApplicationRunner`的类,并实现了`ApplicationRunner`接口。在`run`方法中,你可以编写任何你希望在应用程序启动后执行的代码。

你可以根据自己的需求在`run`方法中执行各种操作,例如初始化一些数据、调用外部API等。这些操作将在应用程序启动后自动执行。

请注意,`MyApplicationRunner`类上需要添加`@Component`注解,以确保它被Spring Boot自动扫描并注册为一个bean。

当你启动Spring Boot应用程序时,`run`方法中的代码将在应用程序启动后立即执行。你可以根据需要在`run`方法中编写多个操作,它们将按照`@Order`注解指定的顺序执行。

ApplicatonRunner和CommandLineRunner的区别

ApplicationRunnerCommandLineRunner接口在功能上没有太大的区别,它们都提供了在Spring Boot应用程序启动后执行特定代码的机制。它们的主要区别在于传递参数的方式和使用场景的不同。

1、参数传递方式:

  • ApplicationRunner接口的run方法接收一个ApplicationArguments对象作为参数,该对象提供了应用程序启动时传递的命令行参数和选项的访问方法。
  • CommandLineRunner接口的run方法接收一个字符串数组作为参数,这些字符串是应用程序启动时从命令行传递的参数。

2、使用场景:

  • ApplicationRunner接口更适合处理复杂的命令行参数,例如键值对、选项等。它提供了更灵活的方式来处理命令行参数,并且可以轻松地解析和操作这些参数。
  • CommandLineRunner接口更适合处理简单的命令行参数,例如单个值或简单的标志。它提供了更简单的方式来处理命令行参数,不需要进行复杂的解析操作。

在实际使用中,你可以根据需要选择使用ApplicationRunnerCommandLineRunner接口。如果你需要处理复杂的命令行参数,或者需要更灵活地操作命令行参数,那么ApplicationRunner是一个更好的选择。如果你只需要处理简单的命令行参数,那么CommandLineRunner就足够了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/32438.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何做一份干净的git提交记录

背景 毕业工作有一些年头了&#xff0c;之前在写工作代码或者给开源项目贡献的时候&#xff0c;提交代码都不是很规范&#xff0c;甚至可以说十分的随意&#xff0c;想到什么就提交什么&#xff0c;根本没有管理提交记录的概念或者想法&#xff08;当你身边的人都不怎么在意的…

基于 Wav2Lip-GFPGAN 深度学习模型的数字人Demo

写在前面 工作中遇到简单整理博文为 Wav2Lip-GFPGAN 环境搭建运行的 Demo理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停息。所有其它的路都是不完整的&#xff0c;是…

kubernetes operator解析

您是否想过站点可靠性工程 (SRE) 团队如何有效地成功管理复杂的应用程序&#xff1f; 在 Kubernetes 生态中&#xff0c;只有一个答案&#xff1a;Kubernetes Operators&#xff01; 在本文中&#xff0c;我们将研究它们是什么以及它们是如何工作的。 Kubernetes Operator 概念…

RabbitMQ 能保证消息可靠性吗

系列文章目录 消息队列选型——为什么选择RabbitMQ RabbitMQ 五种消息模型 RabbitMQ 能保证消息可靠性吗 系列文章目录前言一、消息可靠性的定义二、几种不可靠的场景三、防意外丢失1. 消息持久化2. 队列持久化3. 发布确认3.1 简单发布确认3.2 批量发布确认3.3 异步发布确认 4…

miniconda 安装 windows+linux

虽然常用anaconda&#xff0c;但是有时候只需要管理环境的时候&#xff0c;用miniconda更方便 如果想安装anaconda&#xff0c;可以参考这篇&#xff1a;anaconda安装 一、linux下 1.下载 链接&#xff1a;miniconda文档 cd /usr/localwget https://repo.anaconda.com/mini…

简要介绍 | CUDA底层原理:加速高性能计算的关键技术

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对CUDA的底层原理进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 CUDA底层原理&#xff1a;加速高性能计算的关键技术 CUDA Refresher: The GPU Computing Ecosystem | NVIDIA Technical Blog 1…

python自动化办公——定制化读取Excel数据并写入到word表格

Python自动化办公——Excel写word表格 文章目录 Python自动化办公——Excel写word表格一、引言二、数据准备三、python代码1、方法一2、方法二3、方法三 一、引言 最近到了毕业设计答辩的时候&#xff0c;老师让我帮毕业生写一段毕业设计的功能就是提供一个学士学位授予申请表…

基于CST软件的对数周期天线设计

摘要&#xff1a; 对数周期天线存在多种形式&#xff0c;主要包括齿片形、齿线型和偶极型等。其中&#xff0c;1960年提出的对数周期偶极子天线&#xff08;LPDA&#xff09;是结构最简单、应用最广泛且性能优良的一类对数周期天线&#xff0c;广泛应用于 UHF、VHF、HF 频段的…

python中os库用法详解(总结)

os库主要是对文件和文件夹进行操作&#xff0c;在Python中对⽂件和⽂件夹的操作要借助os模块⾥⾯的相关功能。 具体步骤如下&#xff1a; 1. 导⼊os模块 import os 2. 使⽤ os 模块相关功能 os.函数名() 1、⽂件重命名 os.rename(⽬标⽂件名, 新⽂件名) 示例代码&#…

MySQL:七种 SQL JOINS 的实现(图文详解)

MySQL&#xff1a;7种SQL JOINS的实现 前言一、图示表示二、代码举例1、INNER JOIN&#xff08;内连接&#xff09;2、LEFT JOIN&#xff08;左连接&#xff09;3、RIGHT JOIN&#xff08;右连接&#xff09;4、OUTER JOIN&#xff08;全连接&#xff09;5、LEFT EXCLUDING JOI…

nbcio-vue中formdesigner的组件显示不正常的处理

今天看演示系统的formdesigner组件显示不正常&#xff0c;也不知道是什么时候开始的事情&#xff0c; 如下&#xff1a; 对组件的操作倒是正常&#xff0c;但看本地是正常的&#xff0c;如下&#xff1a; 开始也不知道是什么原因&#xff0c;看代码也是一样的&#xff0c;应该…

JavaScript 中内存泄漏的几种情况?

一、是什么 内存泄漏&#xff08;Memory leak&#xff09;是在计算机科学中&#xff0c;由于疏忽或错误造成程序未能释放已经不再使用的内存 并非指内存在物理上的消失&#xff0c;而是应用程序分配某段内存后&#xff0c;由于设计错误&#xff0c;导致在释放该段内存之前就失…

Hidl编程实战(一)——定义HAL服务

1. 概述 hidl基本知识可以参考官网 安卓官网-hidl 也讲解了C和Java实现hidl 本文讲解CHal服务的创建 2. 文件的创建 aosp整编过的代码&#xff0c;可以直接choosecombo后使用hidl-gen工具。如果没有整编过&#xff0c;可以单编hidl-gen工具。 hidl-gen工具可以用来协助创建h…

Windows和Linux动态注入

摘要&#xff1a;最近对动态注入有一些兴趣因此搜索了些资料&#xff0c;简单整理了下相关的技术实现。本文只能够带你理解何如注入以及大概如何实现&#xff0c;对注入的方法描述的并不详细。   关键字&#xff1a;dll注入&#xff0c;hook&#xff0c;提权   读者须知&am…

基于Springboot+Vue的校园招聘系统(进阶版)

本项目是一年前写的一个项目的升级版&#xff0c;因为某些原因将它作了一个升级改进&#xff0c; 好多兄弟来问有没有演示&#xff0c;现在先来写个说明&#xff01;&#xff01;&#xff01; 目录 一. &#x1f981; 前言二. &#x1f981; 开源代码与组件使用情况说明三. &am…

Qt之事件过滤器讲解并且实现快捷键切换鼠标焦点

目录 1、需求背景2、使用Qt键盘事件3、安装事件过滤器4、事件处理级别 1、需求背景 现在有一个类似于下方图的ui&#xff0c;用户需要在输入前一行内容后&#xff0c;需要摁下指定案件能够跳转到下一行继续进行输入。 2、使用Qt键盘事件 一种更为直接的解决方案是子类化QLi…

如何在 Linux 中安装、设置和使用 SNMP?

概要 SNMP&#xff08;Simple Network Management Protocol&#xff09;是一种用于管理和监控网络设备的协议。它允许网络管理员通过远程方式收集设备的运行状态、性能数据和错误信息&#xff0c;以便进行故障排除和网络优化。在Linux系统中&#xff0c;我们可以安装、设置和使…

IDEA配置本地Maven详细教程

IDEA配置本地Maven详细教程 一、下载二、安装三、配置环境变量四、IDEA配置Maven 一、下载 官网下载&#xff1a;点击下载 网盘下载&#xff1a;点击下载 二、安装 将下载后的zip文件&#xff08;免安装版&#xff09;解压到自己想要放的位置&#xff0c;&#xff0c;我这里…

对MVVM和MVC开发模式的理解

对MVVM和MVC开发模式的理解 1、MVVM2、MVC3、MVVM与MVC的区别 1、MVVM MVVM最早由微软提出来&#xff0c;它借鉴了桌面应用程序的MVC思想&#xff0c;在前端页面中&#xff0c;把Model用纯JavaScript对象表示&#xff0c;View负责显示&#xff0c;两者做到了最大限度的分离&am…

UE4/5 通过Control rig的FullBody【蜘蛛模型,不用basic ik】

目录 根设置 FullBody IK 额外骨设置 ​编辑 晃动效果 根设置 第一步你需要准备一个蜘蛛模型&#xff0c;不论是官方示例或者是epic上购买的模型 然后我用的是epic上面购买的一个眼球蜘蛛&#xff1a; 第一步&#xff0c;我们从根创建一个空项【这个记得脱离父子级到root之…