SpringBoot 面试题总结 (JavaGuide)

news2024/12/19 14:06:46

SpringBoot 面试题总结 (JavaGuide)

用 JavaGuide 复习 SpringBoot 时,找到一些面试题,没有答案,自己花了一天时间在网上找资料总结了一些,有些答案的来源比较杂忘了没有标注,望见谅。

1. 简单介绍一下 Spring?有啥缺点?

(一)重量级框架

我们看到 Spring 架构图时会发现 Spring 里面包含有很多其他组件,比如数据访问、MVC、事务管理、面向切点、WebSocket 功能等,因此这么复杂的组件集中到一起就会提高初学者的学习成本。还有一方面随着你的服务越多,那么 Spring 的启动就会变得越慢。

(二)集成复杂

比如我们想要使用 MyBatis 或者 MongoDB的时候,我们要做很多工作不管使用配置方式也好还是使用注解方式。

(三)配置复杂

在使用 Spring 的时候,我们更多可能是选择 XML 进行配置,但目前这种配置方式已不在流行。

(四)构建和部署复杂

启动 Spring 的 IOC 容器,是完全要依赖于第三方的 web 服务器。自身不能启动的。

2.为什么要有 SpringBoot?

​ 分开来看Spring Boot 是由 Spring 和 Boot 构成,Spring 即 Spring 框架,换句话而言,Spring Boot 是基于 Spring框架进行构建,Boot 就是 BootStrap(牵引),就是以 Spring作为基础的牵引程序。

​ Spring Boot 就是一个快速创建单个的、生产级别的基于Spring 的应用。而且是尽量使用少的依赖和少的配置完成。

​ 从本质上来说,Spring Boot就是Spring,它做了哪些没有它你也会去做的Spring Bean的配置。

3. 说出使用 Spring Boot 的主要优点

①良好的基因

因为SpringBoot是伴随着Spring 4.0而生的,boot是引导的意思,也就是它的作用其实就是在于帮助开发者快速的搭建Spring框架,因此SpringBoot继承了Spring优秀的基因,在Spring中开发更为方便快捷。

②简化依赖

比如我们要创建一个 web 项目,使用 Spring 的朋友都知道,在使用 Spring 的时候,需要在 pom 文件中添加多个依赖,而 Spring Boot 则会帮助开发着快速启动一个 web 容器,在 Spring Boot 中,我们只需要在 pom 文件中添加如下一个 starter-web 依赖即可。

③简化配置

Spring 虽然使Java EE轻量级框架,但由于其繁琐的配置,一度被人认为是“配置地狱”。各种XML、Annotation配置会让人眼花缭乱,而且配置多的话,如果出错了也很难找出原因。Spring Boot更多的是采用 Java Config 的方式,对 Spring 进行配置。

部署配置方面,原来 Spring 有多个 xml 和 properties配置,在 Spring Boot 中只需要个 application.yml即可。

④简化部署

在使用 Spring 时,项目部署时需要我们在服务器上部署 tomcat,然后把项目打成 war 包扔到 tomcat里,在使用 Spring Boot 后,我们不需要在服务器上去部署 tomcat,因为 Spring Boot 内嵌了 tomcat,我们只需要将项目打成 jar 包,使用 java -jar xxx.jar一键式启动项目。

另外,也降低对运行环境的基本要求,环境变量中有JDK即可

⑤简化监控

我们可以引入 spring-boot-start-actuator 依赖,直接使用 REST 方式来获取进程的运行期性能参数,从而达到监控的目的,比较方便。但是 Spring Boot 只是个微框架,没有提供相应的服务发现与注册的配套功能,没有外围监控集成方案,没有外围安全管理方案,所以在微服务架构中,还需要 Spring Cloud 来配合一起使用。

4. 什么是 Spring Boot Starters?

​ starter是SpringBoot中的一个新发明,它有效的降低了项目开发过程的复杂程度,对于简化开发操作有着非常好的效果。 starter是一种对依赖的synthesize(合成)

  • starter的理念:starter会把所有用到的依赖都给包含进来,避免了开发者自己去引入依赖所带来的麻烦。需要注意的是不同的starter是为了解决不同的依赖,所以它们内部的实现可能会有很大的差异,

  • starter的实现:虽然不同的starter实现起来各有差异,但是他们基本上都会使用到两个相同的内容:ConfigurationProperties和AutoConfiguration。因为Spring Boot坚信“约定大于配置”这一理念,所以我们使用ConfigurationProperties来保存我们的配置,并且这些配置都可以有一个默认值,即在我们没有主动覆写原始配置的情况下,默认值就会生效,这在很多情况下是非常有用的。除此之外,starter的ConfigurationProperties还使得所有的配置属性被聚集到一个文件中(一般在resources目录下的application.properties),这样我们就告别了Spring项目中XML地狱。

starter的整体逻辑:

img

总结: Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,可以一站式集成Spring及其他技术,而不需要到处找示例代码和依赖包。 starter其实是把这一些繁琐的配置操作交给了自己,而把简单交给了用户。除了帮助用户去除了繁琐的构建操作,在“约定大于配置”的理念下,ConfigurationProperties还帮助用户减少了无谓的配置操作。并且因为 application.properties 文件的存在,即使需要自定义配置,所有的配置也只需要在一个文件中进行,使用起来非常方便。

5. Spring Boot 支持哪些内嵌 Servlet 容器?

三种嵌入式servlet容器:tomcat(默认), jetty, undertow

使用starter即可方便嵌入,默认情况下,嵌入服务器的访问端口为8080。

Servlets、Filters & Listeners

这些组件可以同组件扫描注册,即把他们定义为Spring Bean。

默认情况下,如果只有一个servlet,则把它映射到 / ;如果有多个servlet,则加上bean name作为前缀然后映射到 /*

容器初始化

如果你需要执行容器初始化,可以通过实现注册一个org.springframework.web.WebApplicationInitializer Bean。这个接口只有一个方法onStartup,这个方法可以访问ServletContext。

当使用嵌入式容器时,可以通过@ServeltComponentScan启用@WebServlet,@WebFilter和@WebListener注解。

6. 如何在 Spring Boot 应用程序中使用 Jetty 而不是 Tomcat?

spring-boot-starter-web模块默认是使用 tomcat 作为内嵌容器,如果我们想要切换为jetty,只需要添加 jetty 的依赖即可,如:

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

7. 介绍⼀下@SpringBootApplication 注解

放置在Springboot启动类上,表明该类是开启Springboot容器的入口,它是一个复合注解。里面包含了包扫描,自动注入,配置注入的功能

【1】@SpringBootConfiguration

它表示的是该类会作为Springboot的一个配置类,进入该注解,发现里面包含@Configuration注解,@Configuration注解是Spring里面的注解,在Spring里,它表示该类也是一个配置类。进入@Configuration注解,我们发现他是被@Component所修饰的,所以该配置类也是一个组件。

【2】@EnableAutoConfiguration**

它表示开启自动配置功能。进入@EnableAutoConfiguration中,发现它仍然是一个组合注解.

1、@AutoConfigurationPackage表示自动注入包:主要作用就是将@SpringBootApplication修饰的类的同包,子孙包下的所有组件都扫描到Spring容器中。

2、@Import({AutoConfigurationImportSelector.class})

表示根据上述所说@Import的作用是导入组件,导入自动配置选择器的组件。 将指定的值导入到Spring容器中,帮我们进行自动配置的功能。

【3】@ComponentScan

用来将指定包(如果未指定就是将当前类所在包及其子孙包)加入SpringIOC的包扫描,本质上等于配置

8. Spring Boot 的自动配置是如何实现的?

同上一题

​ 自动装配就是自动去把第三方组件的 Bean 装载到 IOC 容器里面,不需要开发人员再去写Bean相关的一个配置,在SpringBoot应用里面只需要在启动类上加上@SpringBootApplication注解就可以去实现自动装配。

img SpringBoot自动配置流程.png

9. 开发 RESTful Web 服务常用的注解有哪些?

restful风格,就是一种面向资源服务的API设计方式,它不是规范,不是标准,它一种设计模式。核心在于,当你设计一个系统的时候,资源是第一位的考虑,你首先从资源的角度进行系统的拆分、设计,而不是像以往一样以操作为角度来进行设计 。

Restful风格最大的特点为:资源、统一接口、URI和无状态。
这种风格设计的软件,可以更简洁,更有层次,更易于实现缓存等机制

1、@GetMapping
@RequestMapping(method = RequestMethod.GET)的简写
作用:对应查询,表明是一个查询URL映射

2、@PostMapping
@RequestMapping(method = RequestMethod.POST)的简写
作用:对应增加,表明是一个增加URL映射

3、@PutMapping
@RequestMapping(method = RequestMethod.PUT)的简写
作用:对应更新,表明是一个更新URL映射

4、@DeleteMapping
@RequestMapping(method = RequestMethod.DELETE)的简写
作用:对应删除,表明是一个删除URL映射

5、@PatchMapping
Patch方式是对put方式的一种补充;
put方式是可以更新.但是更新的是整体.patch是对局部更新;

仅仅使用一个url,用请求方式去区分增删改查,降低了url的复杂度,并且更加的统一和规范。

@PathVariable 用于修饰方法传入参数,表示该参数值从请求路径中获取
@RequestMapping(“h2/{a}/{b}) /{a}/{b}:表示要传入的参数值,在请求url中用斜线/分隔多个参数。
    
//RESTful:http://localhost:8080/h2/1/11
@RequestMapping("h2/{a}/{b}")
public String test2(@PathVariable int a, @PathVariable int b)

10. Spirng Boot 常用的两种配置文件

​ SpringBoot支持 propertiesyml 两种配置方式,两种格式的功能类似,都可以完成项目的配置信息。但是properties的优先级要于yml,而yml文件采用树状结构,直观上更加一目了然

11. 什么是 YAML?YAML 配置的优势在哪里?

​ YAML是一种便于人类理解的序列化结构语言,通常同于属性的配置,在配置过程中有着良好的结构规则,与properties相比不易混淆,并且可以配置一些较为复杂的属性。

优点:

YAML有自己的结构,在具体配置过程中需遵守规则,便于程序员理解;
YAML中有配置的顺序性,在某些场合下,配置的顺序很重要;
YAML中支持数组,可以配置基本数据对象,也可以配置对象;
相较于properties,YAML的配置更加简洁

12. Spring Boot 常用的读取配置文件的方法有哪些?

1、@Value方式获取

@Value("${value.request.url}")
private String url;

2、@ConfigurationProperties方式获取(强烈推荐)

为了更契合java的面向对象,我们采用自动配置的方式映射配置文件属性,配置完成后直接当做java对象即可使用。

@Data
@Component
@ConfigurationProperties(value = "app")
public class AppProperties {}
  • @ConfigurationProperties(value = “app”)表示的配置文件里属性的前缀都是app开头
  • 配置类上记得加@Data@Component注解(或者在启动类上加上@EnableConfigurationProperties(value = AppProperties.class))
  • 如果有内部类对象,记得加上@Data,不然无法映射数据
  • .properties 类型文件映射规则,短横线(-)后面的首个字母会变成大写,同时注意有内部类时的写法

使用方法也很简单,直接使用spring的注解@Autowired引入即可

@Autowired
private AppProperties appProperties;

3、Environment对象获取

使用很简单,直接使用spring的注解@Autowired引入即可

@Autowired
private Environment environment;

注意:

Environment 是org.springframework.core.env.Environment

使用Environment对象获取配置文件的值,最好使用带默认值的方法:getProperty(“配置项key”,“默认值”),避免null值

使用Environment对象还可以获取到一些系统的启动信息,当然如果配置项过多也会有维护管理方面的问题

4、@PropertySource方式获取

有时候我们会有一些特殊意义的配置,会单独用一个配置文件存储,比如数据库配置连接参数

@Data
@Component
@ConfigurationProperties(prefix = "csdn")
@PropertySource(value = "classpath:alian.properties", encoding = "UTF-8", ignoreResourceNotFound = true) 
public class ALianProperties {}

注意:

  • @ConfigurationProperties(value = “csdn”)表示配置文件里属性的前缀都是csdn开头
  • @PropertySource中value属性表示指定配置文件的路径,encoding属性表示指定的是读取配置文件时的编码,记得和文件alian.properties的编码保持一致,ignoreResourceNotFound属性值为true时没找到指定配置文件的时候不报错
  • 配置类上记得加上@Component注解
  • .yml 格式不支持@PlaceSource注解导入配置

使用方法也很简单,直接使用spring的注解@Autowired引入即可

@Autowired
private ALianProperties ALianProperties;

5、原生方式获取:加载配置文件,getProperty( )

Properties props = new Properties();
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(Objects.requireNonNull(this.getClass().getClassLoader().getResourceAsStream("load.properties")), StandardCharsets.UTF_8);
            props.load(inputStreamReader);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        System.out.println("LoadProperties测试获取的功能名称:" + props.getProperty("function.name"));
        System.out.println("LoadProperties测试获取的功能描述:" + props.getProperty("function.desp"));

原文链接:Spring Boot读取配置文件常用方式

13. Spring Boot 加载配置文件的优先级了解么?

1. 项目内部配置文件

spring boot 启动会扫描以下位置的 application.properties 或者 application.yml 文件作为Spring boot的默认配置文件

–file:./config/
  –file:./
  –classpath:/config/
  –classpath:/

  1. 项目根目录下的/config目录下的配置文件。
  2. 项目根目录下的配置文件。
  3. 项目类路径(resources)下的/config目录下的配置文件。
  4. 项目类路径(resources)下的配置文件。

img

以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容。 同一目录下,.properties文件优先于.yml文件加载

SpringBoot会从这四个位置全部加载主配置文件,如果高优先级中配置文件属性与低优先级配置文件不冲突的属性,则会共同存在—互补配置。

2. 外部配置加载顺序

SpringBoot也可以从以下位置加载配置:优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置。

1.命令行参数

  • 所有的配置都可以在命令行上进行指定;
  • 多个配置用空格分开; –配置项=值

java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc

2.来自java:comp/env的JNDI属性

3.Java系统属性(System.getProperties())

4.操作系统环境变量

5.RandomValuePropertySource配置的random.*属性值

6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件

7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件

8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件

9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件

10.@Configuration注解类上的@PropertySource

11.通过SpringApplication.setDefaultProperties指定的默认属性

14. 常用的 Bean 映射工具有哪些?

1. Dozer

Dozer 是一个映射框架,它使用递归将数据从一个对象复制到另一个对象。框架不仅能够在 bean 之间复制属性,还能够在不同类型之间自动转换。

2. Orika

Orika 是一个 bean 到 bean 的映射框架,它递归地将数据从一个对象复制到另一个对象。

Orika 的工作原理与 Dozer 相似。两者之间的主要区别是 Orika 使用字节码生成。这允许以最小的开销生成更快的映射器。

3. MapStruct

MapStruct 是一个自动生成 bean mapper 类的代码生成器。MapStruct 还能够在不同的数据类型之间进行转换。

4. ModelMapper

ModelMapper 是一个旨在简化对象映射的框架,它根据约定确定对象之间的映射方式。它提供了类型安全的和重构安全的 API。

5. JMapper

JMapper 是一个映射框架,旨在提供易于使用的、高性能的 Java bean 之间的映射。该框架旨在使用注释和关系映射应用 DRY 原则。该框架允许不同的配置方式:基于注释、XML 或基于 api。

参考链接: 5种常见Bean映射工具的性能比对

15. Spring Boot 如何监控系统实际运行状况?

Actuator( HTTP 端点 )

  • Spring Boot的Actuator提供了运行状态的监控的功能,Actuator的监控数据可以通过REST、远程shell(1.5之后的版本弃用)和JMX方式获得。 Actuator模块提供了众多HTTP接口端点(Endpoint),来提供应用程序运行时的内部状态信息。

  • 只需要在pom.xml文件中加入依赖

  • Spring Boot Actuator提供了非常丰富的监控接口,可以通过这些接口了解应用程序运行时的内部状况。Actuator也支持用户自定义添加端点,可以根据实际应用,定义一些比较关心的指标,在运行期进行监控。

JMX

  • JMX 全称为 Java Management Extensions,即 Java 管理扩展。它提供了对 Java 应用程序JVM 的监控管理

  • 通过 JMX 我们可以监控服务器中各种资源的使用情况以及线程,内存和 CPU 等使用情况。

    打开 jdk 下提供的工具 jConsole

16. Spring Boot 如何做请求参数校验?

​ 接口开发中,为了防止非法参数对业务造成影响,经常需要对接口的参数做校验,例如登录的时候需要校验用户名密码是否为空,创建用户的时候需要校验邮件、手机号码格式是否准确 。

Validator 专门用来进行接口参数校验,例如常见的必填校验email格式校验用户名必须位于6到12之间 等等…

第一步,引入依赖

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

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

第二步,定义要参数校验的实体类

@Data
public class ValidVO {
    private String id;

    @Length(min = 6,max = 12,message = "appId长度必须位于6到12之间")
    private String appId;

    @NotBlank(message = "名字为必填项")
    private String name;

    @Email(message = "请填写正确的邮箱地址")
    private String email;

    private String sex;

    @NotEmpty(message = "级别不能为空")
    private String level;
}

我们在需要验证的参数上加上了@Valid注解,如果验证失败,它将抛出异常。
一定一定不要忘记在类上加上 @Validated 注解了,这个参数可以告诉 Spring 去校验方法参数。

@RestController
@RequestMapping("/api")
@Validated
public class ValidVOController {

    @GetMapping("/validvo/{id}")
    public ResponseEntity<Integer> getValidVO (@Valid @PathVariable("appid") @Max(value = 5,message = "超过 id 的范围了") Integer appid) {
        return ResponseEntity.ok().body(appid);
    }
}

常见的约束注解如下:

注解功能
@AssertFalse可以为null,如果不为null的话必须为false
@AssertTrue可以为null,如果不为null的话必须为true
@DecimalMax设置不能超过最大值
@DecimalMin设置不能超过最小值
@Digits设置必须是数字且数字整数的位数和小数的位数必须在指定范围内
@Future日期必须在当前日期的未来
@Past日期必须在当前日期的过去
@Max最大不得超过此最大值
@Min最大不得小于此最小值
@NotNull不能为null,可以是空
@Null必须为null
@Pattern必须满足指定的正则表达式
@Size集合、数组、map等的size()值必须在指定范围内
@Email必须是email格式
@Length长度必须在指定范围内
@NotBlank字符串不能为null,字符串trim()后也不能等于“”
@NotEmpty不能为null,集合、数组、map等size()不能为0;字符串trim()后可以等于“”
@Range值必须在指定范围内
@URL必须是一个URL

还可以自定义参数校验

虽然 Spring Validation 提供的注解基本上够用,但是面对复杂的定义,我们还是需要自己定义相关注解来实现自动校验。

参考链接: SpringBoot 如何进行参数校验,老鸟们都这么玩的!-阿里云开发者社区 (aliyun.com)

17. 如何使用Spring Boot 实现全局异常处理?

​ 默认下,SpringBoot提供了一个 /error 映射,当我们系统发生异常,直接转到 /error 。原始错误页面很简陋,用户体验很不友好。如果想要显示给定状态码的自定义HTML错误页,可以将文件添加到error文件夹。错误页面可以是静态HTML(即添加到任何静态资源文件夹下),也可以使用模板构建

@ControllerAdvice 注解和 @ExceptionHandler 注解

  • @ControllerAdvice:这是一个增强的 Controller, 用于定义全局异常处理类作用在所有的@Controller类型的接口上。

    使用这个 Controller ,可以实现三个方面的功能:

    全局异常处理
    全局数据绑定
    全局数据预处理

    灵活使用这三个功能,可以帮助我们简化很多工作,需要注意的是,这是SpringMVC提供的功能,在SpringBoot中可以直接使用。

  • @ExceptionHandler: 用于声明处理异常的方法,统一处理某一类异常,从而能够减少代码重复率和复杂度。

@ControllerAdvice
public class GlobalExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 全局异常处理
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ReturnMsg handleException(HttpServletRequest request, Exception e) {
        // 请求状态
        HttpStatus status = getStatus(request);

        // 返回错误信息:失败代码、失败信息、具体代码、具体信息
        return new ReturnMsg(MsgUtil.MSG_ERROR, "发生异常", String.valueOf(status.value()), status.getReasonPhrase());
    }

    /**
     * 自定义异常处理
     */
    @ExceptionHandler(value = MyException.class)
    @ResponseBody
    public ReturnMsg myErrorHandler(MyException myException) {
        // 返回错误信息:失败代码、失败信息、具体代码、具体信息
        return new ReturnMsg(MsgUtil.MSG_ERROR, "发生异常", String.valueOf(myException.getStatus()), myException.getReason());
    }
}

参考链接: 实现全局异常处理

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

定时任务实现的几种方式:

Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。

ScheduledExecutorService:也jdk自带的一个类;是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。

Spring Task:Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。

Quartz:这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂。

以上参考链接: Spring Boot 实现定时任务的 4 种方式

​ 在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Quartz ,Spring Boot 源自 Spring+SpringMVC ,因此天然具备这两个 Spring 中的定时任务实现策略,当然也支持 Quartz。

@Scheduled

使用 @Scheduled 非常容易,直接创建一个 Spring Boot 项目,并且添加 web 依赖 spring-boot-starter-web,项目创建成功后,添加 @EnableScheduling 注解,开启定时任务:

@SpringBootApplication
@EnableScheduling
public class ScheduledApplication {

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

接下来配置定时任务:

    @Scheduled(fixedRate = 2000)
    public void fixedRate() {
        System.out.println("fixedRate>>>"+new Date());    
    }
    @Scheduled(fixedDelay = 2000)
    public void fixedDelay() {
        System.out.println("fixedDelay>>>"+new Date());
    }
    @Scheduled(initialDelay = 2000,fixedDelay = 2000)
    public void initialDelay() {
        System.out.println("initialDelay>>>"+new Date());
    }
  1. 首先使用 @Scheduled 注解开启一个定时任务。
  2. fixedRate 表示任务执行之间的时间间隔,具体是指两次任务的开始时间间隔,即第二次任务开始时,第一次任务可能还没结束。
  3. fixedDelay 表示任务执行之间的时间间隔,具体是指本次任务结束到下次任务开始之间的时间间隔。
  4. initialDelay 表示首次任务启动的延迟时间。
  5. 所有时间的单位都是毫秒。

上面这是一个基本用法,除了这几个基本属性之外,@Scheduled 注解也支持 cron 表达式,使用 cron 表达式,可以非常丰富的描述定时任务的时间。cron 表达式格式如下(最下面有详细链接):

[秒] [分] [小时] [日] [月] [周] [年]

例如,在 @Scheduled 注解中来一个简单的 cron 表达式,每隔5秒触发一次,如下:

@Scheduled(cron = "0/5 * * * * *")
public void cron() {
    System.out.println(new Date());
}

Quartz

一般在项目中,除非定时任务涉及到的业务实在是太简单使用 @Scheduled 注解来解决定时任务,否则大部分情况可能都是使用 Quartz 来做定时任务。

在 Spring Boot 中使用 Quartz ,只需要在创建项目时,添加 Quartz 依赖即可。

项目创建完成后,也需要添加开启定时任务的注解

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

Quartz 在使用过程中,有两个关键概念,一个是JobDetail(要做的事情),另一个是触发器(什么时候做),

  • 要定义 JobDetail,需要先定义 Job

第一种方式,直接定义一个Bean:

关于这种定义方式说两点:

  1. 首先将这个 Job 注册到 Spring 容器中。
  2. 这种定义方式有一个缺陷,就是无法传参。

第二种定义方式,则是继承 QuartzJobBean 并实现默认的方法

  • Job 有了之后,接下来创建类,配置 JobDetail 和 Trigger 触发器,

参考链接: Spring Boot 中实现定时任务的两种方式

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Visual Studio 2022开发Arduino详述

目录&#xff1a; 一、概述 二、软件的下载与安装 1、前言 2、Visual Studio 2022的下载与安装 3、Visual Micro扩展插件的导入 4、Visual Micro的使用 1&#xff09;安装修改插件 2&#xff09;搜索 : Visual.Micro.Processing.Sketch.dll 3&#xff09;打开Visual.…

【Linux学习】基础IO

目录前言一、C语言文件IO1. C语言文件接口以及打开方式2. 对当前路径的理解3. 默认打开的三个流二、 系统文件IO1. 系统接口openwritereadclose系统接口和库函数2. 文件描述符及其分配规则文件描述符文件描述符分配原则3. 重定向及dup2系统调用重定向标准输出和标准错误的区别d…

Linux XWindow的安装和配置

1.开始安装XWindow必须需要的组件 输入指令&#xff1a;yum groupinstall "X Window System" yum groupinstall "X Window System" 选择y继续安装。 当看到complete表示已经安装成功了。 输入startx测试一下 看到如上界面就证明你的XWindow安装成功了。 2…

Python数据分析(3):pandas

文章目录二. pandas入门2.1 数据结构2.1.1 Series对象2.1.2 DataFrame对象2.2 读取数据2.2.1 读取Excel&#xff1a;read_excel()1. 读取特定工作簿&#xff1a;sheet_name2. 指定列标签&#xff1a;header3. 指定行标签&#xff1a;index_col4. 读取指定列&#xff1a;usecols…

TypeScript接口——interface

目录 一、接口概述&#xff1a; 二、接口类型介绍&#xff1a; 1、属性接口&#xff1a; 2、 函数接口&#xff1a; 3、可索引接口&#xff1a; &#xff08;1&#xff09;可索引接口约束数组示例&#xff1a; &#xff08;2&#xff09; 可索引接口约束对象示例&#xf…

【Python】numpy矩阵运算大全

文章目录前言0 遇事不决&#xff0c;先查官网&#xff0c;查着查着就查熟了1 矩阵运算及其必要性2 矩阵的创建2.1 普通矩阵2.2 特殊矩阵3 矩阵的索引3.1 str, list, tupple的索引3.2 numpy索引4 矩阵的运算4.1 通用函数与广播机制4.3 矩阵乘法4.4 矩阵求逆4.5 矩阵转置4.6 向量…

SpringBoot整合mybatis-plus 实现增删改查和分页查询

SpringBoot整合mybatis-plus 实现增删改查和分页查询整体的运行图片&#xff1a;一、环境搭建&#xff1a;1、依赖2、application.yml文件3、数据库二、实体类&#xff1a;三、数据层开发——基础CRUD四、业务层开发——分页功能制作4.1分页配置类 configuration4.2service接口…

【Node.js】模块化学习

Node.js教学 专栏 从头开始学习 目录 模块化的基本概念 什么是模块化 现实中的模块化 编程领域中的模块化 模块化规范 Node.js中的模块化 Node.js中模块的分类 加载模块 Node.js中的模块作用域 什么是模块作用域 模块作用域好处 向外共享模块作用域中的成员 module对象 modu…

第二站:分支与循环(终幕)一些经典的题目

目录 一、计算n的阶乘 1.一般解法 2.优化不能表示出较大数的阶乘 二、 计算 1!2!3!……10! 1.循环嵌套解法 2.一次循环解法(优化计算时间) 三、在一个有序数组中查找具体的某个数字n 1.遍历查找 2.二分查找算法&#xff08;优化了查找时间&#xff09; 四、编写代码&am…

IDEA Out of memory 问题

文章目录1. 前提2. 问题记录与解决方案1. 前提 阅读本文之前&#xff0c;读者要首先把 Out of memory 这个问题的解决方案多搜几个帖子&#xff0c;先按照其他帖子的解决方案&#xff08;修改配置文件Xmx属性等&#xff09;尝试一遍&#xff0c;不能解决再参考本文。 本文所描…

前端小游戏——植物大战僵尸

给大家分享一个植物大战僵尸网页游戏源代码&#xff0c;感兴趣的小伙伴可收藏学习 &#x1f449;完整源码 文章目录⌛️效果展示⌛️游戏介绍⌛️游戏内容&#xff08;1&#xff09;冒险模式&#xff08;2&#xff09;小游戏⌛️图片资源⌛️代码展示&#xff08;1&#xff09;…

【黑猩猩算法】基于加权反对技术和贪婪搜索进化黑猩猩优化算法求解多模态工程问题附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

终于拿到了阿里P8架构师分享的JCF和JUC源码分析与实现笔记java岗

时代的一粒尘&#xff0c;落在每个人身上&#xff0c;就是一座山”。 时代更迭变换&#xff0c;我们好像都知道今天与昨天不同&#xff0c;又好像肉眼看不出哪里不同。 但其实它就正在以各种各样的方式体现在每一个普通人身上。 疫情爆发三个月的时间&#xff0c;截止2020年…

~外中断~

目录 一、接口芯片和端口 二、外中断信息 三、PC机键盘的处理过程 一、接口芯片和端口 外设的输出不直接送入内存和CPU&#xff0c;而是送入相关的接口芯片的端口中&#xff1b;CPU向外设的输出也不是直接送入外设&#xff0c;而是先送入端口&#xff0c;再由相关的芯片送到…

C语言程序设计--火车订票系统

任务要求: 创建一个火车票管理系统&#xff0c;功能包括&#xff1a; &#xff08;1&#xff09;录入班次信息(信息用文件保存),可不定时地增加班次数据 &#xff08;2&#xff09;浏览班次信息,可显示出所有班次当前状总(如果当前系统时间超过了某班 次的发车时间,则…

js中map()的使用详解

引入&#xff1a; 有网友有如下困惑&#xff1a; map是数组的方法&#xff0c;有一个参数&#xff0c;参数是一个函数&#xff0c;函数中有3个参数 参数1&#xff1a;item必须。当前元素的值 参数2&#xff1a;index&#xff0c;可选。当前元素在数组中的索引值 参数3&#xff…

CentOS 7迁移Anolis OS 7 ——筑梦之路

迁移注意事项 Anolis OS 7生态上和依赖管理上保持跟CentOS7.x兼容&#xff0c;一键式迁移脚本centos2anolis.py&#xff0c;实现CentOS7.x到Anolis OS 7的平滑迁移。 使用迁移脚本前需要注意如下事项&#xff1a; 迁移涉及到软件包的重新安装&#xff0c;是不可逆过程&#…

BBR/CUBIC 共存时的 buffer 挤兑

BBR 与 CUBIC 共存时的收敛图&#xff0c;理论情况&#xff1a; 理论上 BBR 不会挤占 buffer&#xff0c;inflight 保持为恒定的 BDP。 但 BBR 的 inflight 做不到恒定&#xff0c;多流共存时&#xff0c;依然会 “主动占用 buffer” 而相互挤兑带宽&#xff0c;而该行为是必须…

java - 序列化

钱应该怎么花 前几天看到一个新闻&#xff0c;一女子打拼了5年攒了30万买房钱&#xff0c;最后因为意外被一场突如其来的大火烧了&#xff0c;经过多家银行&#xff0c;长达4小时的鉴定&#xff0c;挽回了15万损失。 还看到一个新闻&#xff0c;老人攒5000元钱遭虫蛀烂&#…

「Linux」400行纯C语言代码带你「手撕线程池」

线程池的基本概念 不管线程池是什么东西&#xff01;但是我们必须知道线程池被搞出来的目的就是&#xff1a;提高程序执行效率而设计出来的&#xff1b; 了解了线程池的目的后&#xff1a;我们就可以开始理解线程池&#xff1a; 首先回答一个问题&#xff1a;为什么会有线程…