SpringBoot(看这一篇就够了)

news2024/11/15 18:36:06

目录:

  • SpringBoot
    • Spring的缺点
    • 什么是SpringBoot?
    • Springboot3 版本要求
    • Springboot的三种构建方式
      • 官网搭建
      • 通过IDEA脚手架搭建
      • 通过Maven搭建项目
    • SpringBoot的项目结构
    • 编写一个测试代码
    • YAML文件
      • 自定义配置文件
      • @Value读取配置文件
      • @ConfigurationProperties读取配置文件
    • SpringBoot整合Web开发
      • 注册方式一
      • 注册方式二
    • SpringBoot整合Web开发_Filter
      • 注册方式一
      • 注册方式二
    • SpringBoot整合Web开发_Listener
      • 注册方式一
      • 注册方式二
    • SpringBoot整合Web开发_静态资源
    • SpringBoot整合Web开发_静态资源其他存放位置
    • SpringBoot整合Web开发_JSP
    • SpringBoot整合MyBatis
    • SpringBoot单元测试
    • SpringBoot热部署
    • SpringBoot定时任务
    • SpringBoot内容协商机制
    • SpringBoot内容协商机制_基于请求参数
    • SpringBoot国际化
    • SpringBoot国际化_在Thymeleaf中进行国际化
    • SpringBoot参数校验
      • 简单数据类型
      • 异常处理
      • 参数校验_校验相关注解
      • 参数校验_对象类型
    • SpringBoot指标监控
      • 添加Actuator功能
      • Spring Boot Admin
    • SpringBoot日志管理
      • Logback
      • 打印自定义日志
    • SpringBoot项目部署
      • 项目打包
      • 多环境配置
      • Dockerfile制作镜像
      • Maven插件制作镜像
    • SpringBoot3新特性
      • 与之前版本的改动
      • ProblemDetails
      • 原生镜像
      • Native Image 和 GraalVM
      • 生成原生镜像
      • 生成Linux原生镜像

在这里插入图片描述

SpringBoot

Spring的缺点

Spring是一个非常优秀的轻量级框架,以IOC(控制反转)和AOP(面向切面)为思想内核,极大简化了JAVA企业级项目的开发。

虽然Spring的组件代码是轻量级的,但它的配置却是重量级的。使用Spring进行项目开发需要在配置文件中写很多代码,所有这些配置都代表了开发时的损耗。

除此之外,Spring项目的依赖管理也是一件耗时耗力的事情。在环境搭建时,需要分析要导入哪些库的坐标,而且还需要分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发进度。比如Spring5.0以上只能使用Junit4.12以上的版本。

总结起来,Spring的缺点就是:

  • 配置过于繁琐。
  • 引入的依赖过多,版本控制复杂。

什么是SpringBoot?

SpringBoot对Spring的缺点进行改善和优化,基于约定大于配置的思想,简化了Spring的开发,所谓简化是指简化了Spring中大量的配置文件和繁琐的依赖引入。所以SpringBoot是一个服务于框架的框架,它不是对Spring功能的增强,而是提供了一种快速使用Spring框架的方式

SpringBoot的优点:

  • 配置简单
  • 依赖引入简单
  • 提供了一些大型项目的非功能特性,如嵌入式服务器,安全指标,健康监测等。

自动配置

SpringBoot项目自动提供最优配置,同时可以修改默认值满足特定的要求。

起步依赖

SpringBoot的依赖是基于功能的,而不是普通项目的依赖是基于JAR包的。SpringBoot将完成一个功能所需要的所有坐标打包到一起,并完成了版本适配,我们在使用某功能时只需要引入一个依赖即可。

Springboot3 版本要求

然使用SpringBoot是需要一定版本要求的:

工具版本要求
IDEA2021.2.1+
Java17+
Maven3.5+
Tomcat10.0+
Servlet5.0+
GraalVM(原生镜像功能) Community 22.3+
Native Build Tools(原生镜像功能)0.9.19+

Springboot的三种构建方式

官网搭建

接下来我们搭建一个SpringBoot项目,并引入SpringMVC的功能,首先我们可以通过官网搭建项目:

1.访问start.spring.io

2.生成SpringBoot项目

在这里插入图片描述

SpringBoot版本说明:

  • SNAPSHOT:快照版,表示开发版本,随时可能修改;
  • M1(Mn):M1是milestone的缩写,也就是里程碑版本;
  • RC1(RCn):RC1是release candidates的缩写,也就是发布预览版;
  • Release:正式版,也可能没有任何后缀也表示正式版

SpringBoot打包类型说明:

  • 使用SpringMVC开发的是一个web项目,但由于在SpringBoot中直接嵌入了Tomcat等Web容器,所以在使用SpringBoot做Web开发时不需要部署War文件,只需要打成Jar包即可。

3.解压生成的SpringBoot项目

4.在Idea中打开解压的SpringBoot项目即可

通过IDEA脚手架搭建

我们也可以在IDEA中利用脚手架工具搭建项目:

1.在IDEA中新建项目,项目类型为Spring Initializr,写项目名、存放位置、语言类型、项目类型、JDK版本等。点击下一步。

注意:这里一定要将项目类型改为Maven

在这里插入图片描述
2. 选择SpringBoot版本和需要的起步依赖,创建。
在这里插入图片描述
3.完成项目搭建

通过Maven搭建项目

不管是通过官网,还是通过脚手架搭建项目,都需要连接SpringBoot官网,但国内与SpringBoot官网连接并不稳定,此时我们也可以使用Maven手动搭建SpringBoot项目:

1.创建新项目

在这里插入图片描述
2.在pom中添加项目的父工程、起步依赖、插件、依赖和插件的下载地址

<!-- 父工程 -->
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>3.1.2</version>
</parent>
<!-- 起步依赖 -->
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>


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


<!-- 插件 -->
<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>

3.编写启动类

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

4.编写配置文件application.properties

#日志格式
logging.pattern.console=%d{MM/dd HH:mm:ss.SSS} %clr(%-5level) ---  [%-15thread] %cyan(%-50logger{50}):%msg%n
#端口号
server.port=8889

5.运行启动类主方法,启动项目

SpringBoot的项目结构

在这里插入图片描述
src.main.java
这个目录下存放的是Java代码,在我们写好的包名下,SprinBoot生成了一个启动类,启动类的作用是启动SpringBoot项目,运行启动类的main方法即可启动SpringBoot项目。

src.main.resources
这个目录下存放的是配置文件和页面相关的代码,SpringBoot默认在static目录中存放静态资源,如css、js、图片等等。而templates中存放模板引擎,如jsp、thymeleaf等。

由于SpringBoot极大简化了Spring配置,所以只有一个application.properties配置文件,Spring的自动配置功能使得大部分的配置都有默认配置,该文件的功能是覆盖默认配置信息,该文件不写任何信息都可以启动项目。

启动后默认端口号为8080,我们可以覆盖该配置:

server.port=8888

src.test.java
这个目录下编写的是测试代码

pom文件

1.SpringBoot项目必须继承spring-boot-starter-parent,即所有的SpringBoot项目都是spring-boot-starter-parent的子项目。spring-boot-starter-parent中定义了常用配置、依赖、插件等信息,供SpringBoot项目继承使用。

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>3.1.2</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>

2.SpringBoot项目中可以定义起步依赖,起步依赖不是以jar包为单位,而是以功能为单位

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

3.spring-boot-maven-plugin插件是将项目打包成jar包的插件。该插件打包后的SpringBoot项目无需依赖web容器,可以直接使用JDK运行

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>

编写一个测试代码

之前搭建的SpringBoot项目已经都整合了SpringMVC,我们编写一个控制器进行测试:

@Controller
public class MyController {
  @RequestMapping("/hello")
  @ResponseBody
  public String hello(){
    System.out.println("hello springboot!");
    return "hello springboot!";
   }
}

启动类在启动时会做注解扫描(@Controller、@Service、@Repository…),扫描位置为同包或者同级包下的注解,所以我们要在启动类同级或同级包下编写代码。
在这里插入图片描述
启动项目,访问http://localhost:8889/hello

YAML文件

SpringBoot项目中,大部分配置都有默认值,但如果想替换默认配置的话,可以使用application.properties文件进行配置。properties文件是键值对类型的文件,之前一直在使用,所以我们不再对properties文件进行阐述。

https://docs.spring.io/spring-boot/docs/3.1.2/reference/htmlsingle/#appendix.application-properties
可以查找配置文件如何覆盖SpringBoot项目的默认配置。

除了properties文件外,SpringBoot还支持YAML文件进行配置。YAML文件的扩展名为.yml.yaml。SpringBoot默认会从resources目录下加载application.propertiesapplication.yml文件。

YAML文件的基本要求如下:

  • 大小写敏感
  • 使用缩进代表层级关系
  • 同级配置必须对齐,上下级配置必须缩进,但缩进的空格数不限。
  • 相同的部分只出现一次
  • 冒号和值之间必须要有空格

比如使用properties文件配置tomcat端口以及项目路径:

server.port=8888
server.servlet.context-path=/jjy 

而使用YAML文件配置tomcat端口:

server:
  servlet:
   context-path: /jjy
  port: 8888

自定义配置文件

配置简单数据
语法:

数据名: 值

示例代码:

email: jjy@qq.com

配置对象数据

语法:

对象:
    属性名1: 属性值
    属性名2: 属性值
# 或者
对象: {属性名1: 属性值,属性名2: 属性值}

示例代码:

# 邮箱1
my1:
  email: jjy@qq.com
  password: jjy

# 邮箱2
my2: {email: jjyss@qq.com,password: jjyss}

配置集合数据
语法

集合:
    - 值1
    - 值2
    
# 或者
集合: [值1,值2]

示例代码

# 城市
city1:
  - beijing
  - shanghai
  - tianjin
  - chongqing


city2: [beijing,tianjin,shanghai,chongqing]


# 集合中的元素是对象
sxt:
  - address: beijing
   mobile: 13888888888
   email: jjy@qq.com
  - address: shanghai
   mobile: 13777777777
   email: jjyss@qq.com
  - address: guangzhou
   mobile: 13666666666
   email: jjyaa@qq.com

@Value读取配置文件

读取自定义配置时,我们可以通过@Value注解将配置文件中的值映射到一个Spring管理的Bean的字段上,用法如下:

配置文件

email: jjy@qq.com


my1:
  email: jjy@qq.com
  password: ijjy


city1:
  - beijing
  - shanghai
  - tianjin
  - chongqing


sxt:
  - address: beijing
   mobile: 13888888888
   email: jjy@qq.com
  - address: shanghai
   mobile: 13777777777
   email: jjysss@qq.com
  - address: guangzhou
   mobile: 13666666666
   email: jjyaaa@qq.com

读取配置文件数据

@Controller
public class YmlController1 {
  @Value("${email}")
  private String email;


  @Value("${my1.password}")
  private String password;


  @Value("${city1[0]}")
  private String city1;


  @Value("${sxt[1].mobile}")
  private String mobile;


  @RequestMapping("/yml1")
  @ResponseBody
  public String yml1(){
    return email+":"+password+":"+city1+":"+mobile;
   }
}

@Value只能映射简单数据类型,不能将yaml文件中的对象、集合映射到属性中。

@ConfigurationProperties读取配置文件

通过@ConfigurationProperties(prefifix="对象")可以将配置文件中的配置自动与实体进行映射,这样可以将yml文件中配置的对象属性直接映射到Bean当中。
配置文件

user:
  id: 10001
  username: shangxuetang
  address:
   - beijing
   - tianjin
   - shanghai
   - chongqing
  grades:
   - subject: math
    score: 100
   - subject: english
    score: 90

实体类

public class Grade {
  private String subject;
  private double score;
  // 省略getter/setter/tostring
}

读取配置文件

@Controller
@ConfigurationProperties(prefix = "user")
public class YmlController2 {
  private int id;
  private String username;
  private List<String> address;
  private List<Grade> grades;


  @RequestMapping("/yml2")
  @ResponseBody
  public String yml2(){
    System.out.println(id);
    System.out.println(username);
    System.out.println(address);
    System.out.println(grades);
    return "hello springboot!";
   }


  public int getId() {
    return id;
   }


  public void setId(int id) {
    this.id = id;
   }


  public String getUsername() {
    return username;
   }


  public void setUsername(String username) {
    this.username = username;
   }


  public List<String> getAddress() {
    return address;
   }


  public void setAddress(List<String> address) {
    this.address = address;
   }


  public List<Grade> getGrades() {
    return grades;
   }


  public void setGrades(List<Grade> grades) {
    this.grades = grades;
   }
}

SpringBoot整合Web开发

由于SpringBoot项目没有web.xml文件,所以无法在web.xml中注册web组件,SpringBoot有自己的方式注册web组件。

注册方式一

1.编写servlet

@WebServlet("/first")
public class FirstServlet extends HttpServlet {
  public void doGet(HttpServletRequest request, HttpServletResponse response){
    System.out.println("First Servlet........");
   }
}

2.启动类扫描web组件

@SpringBootApplication
//SpringBoot启动时扫描注册注解标注的Web组件
@ServletComponentScan
public class Springbootdemo2Application {
  public static void main(String[] args) {
    SpringApplication.run(Springbootdemo2Application.class, args);
   }
}

注册方式二

编写servlet

public class SecondServlet extends HttpServlet {
  public void doGet(HttpServletRequest request, HttpServletResponse response){
    System.out.println("Second Servlet........");
   }
}

使用配置类注册servlet

@Configuration
public class ServletConfig {
  //ServletRegistrationBean可以注册Servlet组件,将其放入Spring容器中即可注册Servlet
  @Bean
  public ServletRegistrationBean getServletRegistrationBean(){
    // 注册Servlet组件
    ServletRegistrationBean bean = new ServletRegistrationBean(new SecondServlet());
    // 添加Servlet组件访问路径
    bean.addUrlMappings("/second");
    return bean;
   }
}

SpringBoot整合Web开发_Filter

注册方式一

编写filter

@WebFilter(urlPatterns = "/first")
public class FirstFilter implements Filter {
  @Override
  public void init(FilterConfig filterConfig) throws ServletException { }
  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    System.out.println("进入First Filter");
    filterChain.doFilter(servletRequest,servletResponse);
    System.out.println("离开First Filter");
   }
  @Override
  public void destroy() { }
}

启动类扫描web组件

@SpringBootApplication
//SpringBoot启动时扫描注册注解标注的Web组件
@ServletComponentScan
public class Springbootdemo2Application {
  public static void main(String[] args) {
    SpringApplication.run(Springbootdemo2Application.class, args);
   }
}

注册方式二

编写filter

public class SecondFilter implements Filter {
  @Override
  public void init(FilterConfig filterConfig) throws ServletException { }
  
  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    System.out.println("进入Second Filter");
    filterChain.doFilter(servletRequest,servletResponse);
    System.out.println("离开Second Filter");
   }


  @Override
  public void destroy() { }
}

使用配置类注册filter

@Configuration
public class FilterConfig {
  @Bean
  public FilterRegistrationBean getFilterRegistrationBean(){
    // 注册filter组件
    FilterRegistrationBean bean = new FilterRegistrationBean(new SecondFilter());
    // 添加过滤路径
    bean.addUrlPatterns("/second");
    return bean;
   }
}

SpringBoot整合Web开发_Listener

注册方式一

编写Listener

@WebListener
public class FirstListener implements ServletContextListener {
  @Override
  public void contextInitialized(ServletContextEvent sce) {
    System.out.println("First Listener Init......");
   }


  @Override
  public void contextDestroyed(ServletContextEvent sce) {


   }
}

启动类扫描web组件

@SpringBootApplication
//SpringBoot启动时扫描注册注解标注的Web组件
@ServletComponentScan
public class Springbootdemo2Application {
  public static void main(String[] args) {             
    SpringApplication.run(Springbootdemo2Application.class, args);
   }
}

注册方式二

编写Listener

public class SecondListener implements ServletContextListener {
  @Override
  public void contextInitialized(ServletContextEvent sce) {
    System.out.println("Second Listener Init......");
   }

  @Override
  public void contextDestroyed(ServletContextEvent sce) {

   }
}

使用配置类注册Listener

@Configuration
public class ListenerConfig {
  @Bean
  public ServletListenerRegistrationBean getServletListenerRegistrationBean(){
    ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean(new SecondListener());
    return bean;
   }
}

SpringBoot整合Web开发_静态资源

SpringBoot项目中没有WebApp目录,只有src目录。在src/main/resources下面有static和templates两个文件夹。SpringBoot默认在static目录中存放静态资源,而在templates中放动态页面。

SpringBoot不推荐JSP作为动态页面,推荐使用Thymeleaf技术编写动态页面。templates目录是存放Thymeleaf页面的目录,稍后我们讲解Thymeleaf技术。

接下来我们在resources/static中编写html静态页面:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>测试HTML</title>
  <script src="/js/page1.js"></script>
  <link rel="stylesheet" href="/css/page1.css" />
</head>
<body>
<p>我的HTML</p>
<img src="/img/img.png">
</body>
</html>

目录结构
在这里插入图片描述

SpringBoot整合Web开发_静态资源其他存放位置

除了/resources/static目录,SpringBoot还会扫描以下位置的静态资源:

  • /resources/META‐INF/resources/
  • /resources/resources/
  • /resources/public/
    在这里插入图片描述
    我们还可以在配置文件自定义静态资源位置

在这里插入图片描述
在SpringBoot配置文件进行自定义静态资源位置配置

spring:
  web:
   resources:
    static-locations: classpath:/suibian/,classpath:/static/

注意
该配置会覆盖默认静态资源位置,如果还想使用之前的静态资源位置,还需要配置在后面。
SpringBoot2.5之前的配置方式为:spring.resources.static-locations

SpringBoot整合Web开发_JSP

在SpringBoot中不推荐使用JSP作为动态页面,如果我们要想使用JSP编写动态页面,需要手动添加webapp目录。

  • 由于SpringBoot自带tomcat无法解析JSP,需要在pom文件添加JSP引擎
<!--添加jsp引擎,SpringBoot内置的Tomcat不能解析JSP-->
<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
  • 将webapp标记为web目录
    在这里插入图片描述
  • 创建webapp目录,编写JSP文件
    在这里插入图片描述
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
  <title>MYJSP</title>
</head>
<body>
MYJSP
</body>
</html>
  • 启动项目,访问http://localhost:8080/myJsp.jsp

SpringBoot整合MyBatis

Spring整合MyBatis时需要进行大量配置,而SpringBoot整合MyBatis则可以简化很多配置:
1.准备数据库

CREATE DATABASE `student`;
USE `student`;
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(255) DEFAULT NULL,
 `sex` varchar(10) DEFAULT NULL,
 `address` varchar(255) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;


insert into `student`(`id`,`name`,`sex`,`address`) values (1,'百战程序员','男','北京'),(2,'北京尚学堂','女','北京');

2.在pom中添加MyBatis起步依赖和Mysql驱动依赖

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <!-- mybatis起步依赖 -->
  <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.2</version>
  </dependency>
  <!-- mysql依赖 -->
  <dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
  <!-- mybatis测试起步依赖 -->
  <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter-test</artifactId>
    <version>3.0.2</version>
    <scope>test</scope>
  </dependency>
</dependencies>

3.编写实体类

public class Student {
  private int id;
  private String name;
  private String sex;
  private String address;
  
  // 省略构造方法/getter/setter/tostring
}

4.编写Mapper

@Mapper
public interface StudentMapper {
  List<Student> findAll();
  
  @Select("select * from student where id = #{id}")
  Student findById(int id);
}

5.编写Mapper映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jjy.springbootmybatis.mapper.StudentMapper">
  <select id="findAll" resultType="student">
     select * from student
  </select>
</mapper>

6.编写配置文件

# 配置数据源
spring:
  datasource:
   driver-class-name: com.mysql.cj.jdbc.Driver
   url: jdbc:mysql:///student?serverTimezone=UTC
   username: root
   password: root

#mybatis配置
mybatis:
 # 映射文件位置
  mapper-locations: com/jjy/springbootdemo7/mapper/*Mapper.xml
 # 别名
  type-aliases-package: com.jjy.springbootdemo7.pojo

logging:
  pattern:
   console: '%d{HH:mm:ss.SSS} %clr(%-5level) ---  [%-15thread] %cyan(%-50logger{50}):%msg%n'

SpringBoot单元测试

写了MyBatis相关代码后,我们要测试MyBatis代码是否正确。需要进行单元测试。SpringBoot单元测试要比Spring更简单。

1.SpringBoot项目在构建时,默认引入单元测试的起步依赖

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

2.在src.test.java下创建测试类,也可以让idea自动创建测试类,打开要测试的类:

ctrl+shift+t --> create new test
在这里插入图片描述
3.编写测试类

// 测试类注解,可以在运行测试代码时加载容器
@SpringBootTest
class StudentMapperTest {
  @Autowired
  private StudentMapper studentMapper;


  @Test
  void findAll() {
    List<Student> all = studentMapper.findAll();
    all.forEach(System.out::println);
   }


  @Test
  void findById() {
    Student student = studentMapper.findById(1);
    System.out.println(student);
   }
}

SpringBoot热部署

热部署,就是在应用正在运行的时候升级软件,却不需要重新启动应用。即修改完代码后不需要重启项目即可生效。在SpringBoot中,可以使用DevTools工具实现热部署

1.添加DevTools依赖

<!-- 热部署工具 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <optional>true</optional>
</dependency>
  1. 在idea中设置自动编译

点击File–>Settings–>Compiler
在这里插入图片描述
3.开启允许在运行中修改文件

点击File–>Settings–>Advanced Settings,勾选Allow auto-make to start even if developed application is currently running
在这里插入图片描述
此时热部署即可生效

SpringBoot定时任务

定时任务即系统在特定时间执行一段代码。Spring Boot默认已经整合了Spring Task定时任务,只需要添加相应的注解即可完成。

1.在启动类中加入@EnableScheduling注解即可开启定时任务

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

2.编写定时任务

@Component
public class MyTask {
  // 定时任务方法,每秒执行一次
  @Scheduled(cron="* * * * * *")
  public void task1() {
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
    System.out.println(sdf.format(new Date()));
   }
}

@Scheduled 是 Spring Framework 中的一个注解,它用于标记一个方法,使其成为一个定时任务,按照一定的时间间隔或特定的时间点执行。cron 参数是一个字符串,用于定义任务执行的计划。Cron 表达式由六或七个字段组成,每个字段代表不同的时间单位:
秒 (0 - 59)
分钟 (0 - 59)
小时 (0 - 23,24小时制)
日期 (1 - 31)
月份 (1 - 12 或 JAN-DEC)
星期几 (0 - 7,7 或 0 表示星期天,或者使用 SUN-SAT)
年份(可选字段)
cron="* * * * * " 表示:
秒:
表示每秒钟都会触发一次。
分钟:* 表示每分钟的每秒钟都会触发。
小时:* 表示每小时的每分钟都会触发。
日期:* 表示每月的每天都会触发。
月份:* 表示每年的每个月都会触发。
星期几:* 表示每周的每一天都会触发。
这意味着任务将每秒钟执行一次,这通常是不必要的,除非有特定的需求需要如此高频率的执行。通常,我们会根据实际需要来调整这个表达式,以避免过度执行任务。

3.启动项目,定时任务方法按照配置定时执行。

SpringBoot内容协商机制

在这里插入图片描述
如果我们的Java服务为浏览器和安卓手机同时提供服务,浏览器期望接受的请求是JSON格式,安卓客户端期望接收的请求是XML格式,这个时候是否需要写两个方法?

不需要!SpringBoot的内容协商机制可以解决这个问题。

内容协商机制:根据客户端接收能力不同,SpringBoot 返回不同媒体类型的数据。

Spring默认支持内容协商机制,但SpringBoot默认只支持返回Json数据,所以需要导入jackson-dataformat-xml让SpringBoot支持返回xml数据

1.引入依赖

<!-- 引入支持返回 xml 数据格式 -->
<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

2.编写控制器

@Controller
public class ConsultController {
  @Autowired
  private StudentMapper studentMapper;

  @RequestMapping("/student/findById")
  @ResponseBody
  public Student findById(Integer id){
    Student student = studentMapper.findById(id);
    return student;
   }
}

3.进行测试,SpringBoot的内容协商机制是根据请求头不同,返回不同格式的数据,所以需要我们能够修改请求头,我们使用postman进行测试:
在这里插入图片描述
在这里插入图片描述

SpringBoot内容协商机制_基于请求参数

SpringBoot默认根据请求头不同,返回不同的数据格式。我们还可以配置基于请求参数的内容协商,也就是请求参数值不同,返回不同的数据:

1.配置SpringBoot基于请求参数的内容协商

#开启请求参数内容协商模式
spring.mvc.contentnegotiation.favor-parameter=true
#请求参数内容协商模式的参数名
spring.mvc.contentnegotiation.parameter-name=format

2.在postman进行测试:
在这里插入图片描述
在这里插入图片描述

SpringBoot国际化

国际化:(Internationalization 简称 I18n,其中“I”和“n”分别为首末字符,18 则为中间的字符数)。是指软件能同时应对不同国家和地区的用户访问,并根据用户地区和语言习惯,提供相应的、符合用具阅读习惯的页面和数据,例如,为中国用户提供汉语界面显示,为美国用户提供英语界面显示。接下来我们来说一下在SpringBoot项目中,如何进行国际化配置:

1、编写国际化资源文件
SpringBoot国际化资源文件的文件名规范为:基本名_语言代码_国家或地区代码。例如:

  • 美国英语:messages_en_US.properties:

  • 中国汉语:messages_zh_CN.properties。
    我们在 src/main/resources中,按照国际化资源文件命名格式分别创建以下三个文件:

  • messages.properties:无语言设置时生效

  • messages_en_US.properties:美国英语时生效

  • messages_zh_CN.properties:中文时生效

在这里插入图片描述

编写三个文件:

# messages.properties
welcome=欢迎使用{0}(默认)


# messages_en_US.properties 
welcome=welcome to {0}


# messages_zh_CN.properties
welcome=欢迎使用{0}(中文)

注意,这里要将项目配置文件的编码方式改成UTF-8,否则会出现乱码

在这里插入图片描述

2、在配置文件指定国际资源文件的基本名

spring:
  messages:
   basename: messages

3、编写控制器

@Controller
public class I18nController {
  @Autowired
  private MessageSource messageSource;

  @RequestMapping("/welcome")
  @ResponseBody
  public String welcome(HttpServletRequest request) {
    // 获取请求来源的地区
    Locale locale = request.getLocale();
    /**
     * 使用国际化
     * 第一个参数是国际化文件的key,
     * 第二个参数value中的占位符数据
     * 第三个是区域
     */
    String welcome = messageSource.getMessage("welcome", new Object[]{"springboot"}, locale);
    return welcome;
   }
}

4、在浏览器测试国际化
先在默认情况下访问/welcome,之后切换浏览器环境,再次访问/welcome
在这里插入图片描述

SpringBoot国际化_在Thymeleaf中进行国际化

在Thymeleaf页面中获取国际化资源数据的方式如下:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8"/>
  <title>Title</title>
</head>
<body>
<h1 th:text="#{welcome('springboot')}">欢迎</h1>
<h1>[[#{welcome('springboot')}]]</h1>
</body>
</html>

SpringBoot参数校验

简单数据类型

SpringBoot自带了validation工具可以从后端对前端传来的参数进行校验,用法如下:

1.引入validation起步依赖

<!-- 参数校验 -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2.编写Controller

// 该控制器开启参数校验
@Validated
@Controller
public class TestController {
  @RequestMapping("/t1")
  @ResponseBody
  // 在参数前加校验注解,该注解的意思是字符串参数不能为null
  public String t1(@NotBlank String username){
    System.out.println(username);
    return "请求成功!";
   }
}

3.访问http://localhost:8080/t1,发现当没有传来参数时,会抛出ConstraintViolationException异常。

4.在校验参数的注解中添加message属性,可以替换异常信息。

// 该控制器开启参数校验
@Validated
@Controller
public class TestController {
  @RequestMapping("/t1")
  @ResponseBody
  // 在参数前加校验注解,该注解的意思是字符串参数不能为null
  public String t1(@NotBlank(message = "用户名不能为空") String username){
    System.out.println(username);
    return "请求成功!";
   }
}

异常处理

当抛出ConstraintViolationException异常后,我们可以使用SpringMVC的异常处理器,也可以使用SpringBoot自带的异常处理机制。

当程序出现了异常,SpringBoot会使用自带的BasicErrorController对象处理异常。该处理器会默认跳转到/resources/templates/error.html页面。

编写异常页面:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>错误页面</title>
</head>
<body>
<h1>服务器开小差了!</h1>
</body>
</html>

参数校验_校验相关注解

注解作用
@NotNull判断包装类是否为null
@NotBlank判断字符串是否为null或者是空串(去掉首尾空格)
@NotEmpty判断集合是否为空
@Length判断字符的长度(最大或者最小)
@Min判断数值最小值
@Max判断数值最大值
@Email判断邮箱是否合法
@RequestMapping("/t2")
@ResponseBody
public String t2(
    @NotBlank @Length(min = 1, max = 5) String username,
    @NotNull @Min(0) @Max(150) Integer age,
    @NotEmpty @RequestParam List<String> address,
    @NotBlank @Email String email) {
  System.out.println(username);
  System.out.println(age);
  System.out.println(address);
  System.out.println(email);
  return "请求成功!";
}

参数校验_对象类型

SpringBoot也可以校验对象参数中的每个属性,用法如下:

1.添加实体类

public class Student {
  @NotNull(message = "id不能为空")
  private Integer id;
  @NotBlank(message = "姓名不能为空")
  private String name;
  // 省略getter/setter/tostring
}

2.编写控制器

@Controller
public class TestController2 {
  @RequestMapping("/t3")
  @ResponseBody
  // 校验的对象参数前添加@Validated,并将异常信息封装到BindingResult对象中
  public String t3(@Validated Student student,BindingResult result) {
    // 判断是否有参数异常
    if (result.hasErrors()) {
      // 所有参数异常
      List<ObjectError> list = result.getAllErrors();
      // 遍历参数异常,输出异常信息
      for (ObjectError err : list) {
        FieldError fieldError = (FieldError) err;
        System.out.println(fieldError.getDefaultMessage());
       }
      return "参数异常";
     }
    System.out.println(student);
    return "请求成功!";
   }
}

SpringBoot指标监控

添加Actuator功能

Spring Boot Actuator可以帮助程序员监控和管理SpringBoot应用,比如健康检查、内存使用情况统计、线程使用情况统计等。我们在SpringBoot项目中添加Actuator功能,即可使用Actuator监控项目,用法如下:

1.在被监控的项目中添加Actuator起步依赖

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

2.编写配置文件

#开启所有监控端点
management:
  endpoints:
   web:
    exposure:
     include: '*'
     

3.访问项目:http://localhost:8080/actuator

通过URL可以调用actuator的功能:

URL查看的数据
/env环境属性
/health健康检查
/mappings显示所有的@RequestMapping路径
/loggers日志
/info定制信息
/metrics查看内存、CPU核心等系统参数
/trace用户请求信息

例如查询健康数据,访问http://localhost:8080/actuator/health

Spring Boot Admin

在这里插入图片描述
Actuator使用JSON格式展示了大量指标数据,不利于我们查看,我们可以使用可视化工具Spring Boot Admin查看actuator生成指标数据。Spring Boot Admin是一个独立的项目,我们需要创建并运行该项目。

创建Spring Boot Admin服务端项目

1.创建SpringBoot项目,添加SpringMVC和Spring Boot Admin服务端起步依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>de.codecentric</groupId>
  <artifactId>spring-boot-admin-starter-server</artifactId>
  <version>3.1.3</version>
</dependency>

2.修改配置文件

# 端口号
server.port=9090
# 日志格式
logging.pattern.console=%d{HH:mm:ss.SSS} %clr(%-5level) ---  [%-15thread] %cyan(%-50logger{50}):%msg%n

3.修改启动类

@SpringBootApplication
@EnableAdminServer //开启Spring Boot Admin服务端
public class MyadminApplication {
  public static void main(String[] args) {
    SpringApplication.run(MyadminApplication.class, args);
   }
}

连接Spring Boot Admin项目
在被监控的项目中连接Spring Boot Admin项目,才能使用Spring Boot Admin查看指标数据。

被监控项目添加Spring Boot Admin客户端起步依赖

<dependency>
  <groupId>de.codecentric</groupId>
  <artifactId>spring-boot-admin-starter-client</artifactId>
  <version>3.1.3</version>
</dependency>

修改配置文件

#Spring boot admin访问地址
spring.boot.admin.client.url=http://localhost:9090

此时Spring Boot Admin即可连接被监控的项目

SpringBoot日志管理

Logback

SpringBoot默认使用Logback组件作为日志管理。Logback是log4j创始人设计的一个开源日志组件。在SpringBoot中已经整合了Logback的依赖,所以我们不需要额外的添加其他依赖:

Logback配置用法如下:

1.在/resources下添加Logback配置文件logback.xml

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
  <!--定义日志文件的存储地址-->
  <property name="LOG_HOME" value="${catalina.base}/logs/"/>
  
  <!-- 控制台输出 -->
  <appender name="Stdout" class="ch.qos.logback.core.ConsoleAppender">
    <!-- 日志输出编码 -->
    <layout class="ch.qos.logback.classic.PatternLayout">
      <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
      <pattern>%d{MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
      </pattern>
    </layout>
  </appender>
  
  <!-- 按照每天生成日志文件 -->
  <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!--日志文件输出的文件名-->
      <FileNamePattern>${LOG_HOME}/server.%d{yy99-MM-dd}.log</FileNamePattern>
      <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <layout class="ch.qos.logback.classic.PatternLayout">
      <!--格式化输出:%d表示时间,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
      </pattern>
    </layout>
    <!--日志文件最大的大小-->
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <MaxFileSize>10MB</MaxFileSize>
    </triggeringPolicy>
  </appender>


  <!-- 日志输出级别 -->
  <root level="info">
    <appender-ref ref="Stdout"/>
    <appender-ref ref="RollingFile"/>
  </root>
</configuration>

注:Logback配置文件名为logback-test.xml或logback.xml,如果classpath下没有这两个文件,LogBack会自动进行最小化配置。

打印自定义日志

如果想在运行时打印自定义日志,只需要引入Logger对象即可:

@Controller
public class LogbackController {
  private final static Logger logger = LoggerFactory.getLogger(LogbackController.class);

  @RequestMapping("/printLog")
  @ResponseBody
  public String showInfo(){
    logger.info("记录日志");
    return "Hello Logback";
   }
}

如果日志过多,可以屏蔽一些包的日志,在配置文件中配置

#屏蔽org包中的日志输出
logging.level.org=off

SpringBoot项目部署

项目打包

SpringBoot项目是依赖于Maven构建的,但打包时如果只依赖Maven打包工具则会打包不完整,我们还需要在SpringBoot项目中引入SpringBoot打包插件 :

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>

此时再使用Maven插件打包:
在这里插入图片描述
运行jar包:

1.进入jar包所在目录,使用cmd打开命令行窗口

2.输入命令:

java -jar jar包名

多环境配置

在真实开发中,在不同环境下运行项目往往会进行不同的配置,比如开发环境使用的是开发数据库,测试环境使用的是测试数据库,生产环境使用的是生产数据库。SpringBoot支持不同环境下使用不同的配置文件,用法如下:

配置文件名:

application-环境名.properties/yml

如:

application-dev.properties/yml 开发环境配置文件

# 开发环境端口号为8080
server:
  port: 8080

application-test.properties/yml 测试环境配置文件

# 测试环境端口号为8081
server:
  port: 8081 

application-prod.properties/yml 生产环境配置文件

# 生产环境端口号为80
server:
  port: 80

运行jar包时选择环境:

java -jar jar包名 --spring.profiles.active=环境名

Dockerfile制作镜像

为了节约资源,在生产环境中我们更多的是使用Docker容器部署SpringBoot应用,首先我们准备Docker环境:

1.准备一台centos7系统的虚拟机,连接虚拟机。

2.关闭虚拟机防火墙

# 关闭运行的防火墙
systemctl stop firewalld.service

# 禁止防火墙自启动
systemctl disable firewalld.service

3.安装Docker

# 安装Docker
yum -y install docker

# 启动docker
systemctl start docker

4.由于SpringBoot中嵌入了Web容器,所以在制作SpringBoot项目的镜像时无需依赖Web容器,基于JDK制作镜像即可,接下来我们使用Dockerfile制作镜像:

5.进入opt目录

cd /opt

6.使用rz命令将项目Jar包上传至虚拟机

7.编写DockerFile

cat <<EOF > Dockerfile
# 基于JDK17
FROM openjdk:17
# 作者
MAINTAINER itbaizhan
# 拷贝到容器opt目录
ADD springbootdemo9-0.0.1-SNAPSHOT.jar /opt
#保留端口
EXPOSE 8080
# 启动容器后执行的命令
CMD java -jar /opt/springbootdemo9-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
EOF

8.构建镜像

docker build -t springbootdocker .

9.查看所有的镜像,出现springbootdocker代表镜像构建成功

docker images

10.使用镜像启动容器

docker run -d -p 8080:8080 springbootdocker

11.访问项目

Maven插件制作镜像

除了DockerFile,我们还可以使用Maven插件制作镜像。使用方法如下:

1.开启远程docker服务

# 修改docker配置文件
vim /lib/systemd/system/docker.service


# 在ExecStart=后添加配置,远程访问docker的端口为2375
ExecStart=/usr/bin/dockerd-current -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock \
     --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current \
     --default-runtime=docker-runc \
     --exec-opt native.cgroupdriver=systemd \
     --userland-proxy-path=/usr/libexec/docker/docker-proxy-current \
     --init-path=/usr/libexec/docker/docker-init-current \
     --seccomp-profile=/etc/docker/seccomp.json \
     $OPTIONS \
     $DOCKER_STORAGE_OPTIONS \
     $DOCKER_NETWORK_OPTIONS \
     $ADD_REGISTRY \
     $BLOCK_REGISTRY \
     $INSECURE_REGISTRY \
     $REGISTRIES




# 重启docker
systemctl daemon-reload
systemctl restart docker

2.在项目的pom文件中添加docker-maven-plugin插件

<!-- docker-maven-plugin-->
<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>docker-maven-plugin</artifactId>
  <version>1.2.2</version>
  <configuration>
    <!-- Docker路径 -->
    <dockerHost>http://192.168.1.25:2375</dockerHost>
    <!-- Dockerfile定义 -->
    <baseImage>openjdk:17</baseImage>
    <!-- 作者 -->
    <maintainer>itbaizhan</maintainer>
    <resources>
      <resource>
        <!-- 复制jar包到docker容器指定目录 -->
        <targetPath>/</targetPath>
        <!-- 从哪个包拷贝文件,target包 -->
        <directory>${project.build.directory}</directory>
        <!-- 拷贝哪个文件 -->
        <include>${project.build.finalName}.jar</include>
      </resource>
    </resources>
    <workdir>/</workdir>
    <entryPoint>["java", "-jar", "${project.build.finalName}.jar","--spring.profiles.active=dev"]</entryPoint>
    <forceTags>true</forceTags>
    <!-- 镜像名 -->
    <imageName>${project.artifactId}</imageName>
    <!-- 镜像版本 -->
    <imageTags>
      <imageTag>${project.version}</imageTag>
    </imageTags>
  </configuration>
</plugin>

3.使用maven的package命令给项目打包
在这里插入图片描述

4.用maven的docker插件制作镜像

在这里插入图片描述

5.查看镜像是否构建成功

docker images

6.使用镜像启动容器

docker run -d -p 8081:8080 demo1:0.0.1-SNAPSHOT

7.访问项目

SpringBoot3新特性

与之前版本的改动

我们在使用SpringBoot3的时候,一定要注意以下几个方面的改动:

  • JDK要求最低版本Java17

  • SpringBoot3底层默认的Spring版本是Spring6

  • 新增了一些起步依赖,有一些起步依赖进行了调整,但改动不大。

  • 自动配置包位置发生了变化

SpringBoot2.x
在这里插入图片描述
SpringBoot3.x
在这里插入图片描述

  • jakarta api迁移

由于JavaEE已经变更为Jakarta EE,包名以 javax开头的需要相应地变更为jakarta

SpringBoot2.x
在这里插入图片描述

SpringBoot3.x

在这里插入图片描述

ProblemDetails

RFC 7807
之前的项目如果出现异常,默认跳转到error页面。或者是抛出500异常。

在这里插入图片描述
在这里插入图片描述

但是对于前后端分离的项目,Java程序员不负责页面跳转,只需要把错误信息交给前端程序员处理即可。而RFC 7807规范就是将异常信息转为JSON格式的数据。这个JSON数据包含五个部分

  • type: 问题描述文档地址,如果不存在,则"about:blank"

  • title: 简短的描述问题

  • status: http 状态码,比如400、401、500等

  • detail: 详细说明发生问题的原因

  • instance: 问题发生的URL地址

{
  "type": "https://pack.com/probs/out-of-credit",
  "title": "你没有足够的信用。",
  "status": 601,
  "detail": "你现在的余额是30,但是要花50。",
  "instance": "/account/12345/msgs/abc"
}

前端程序员拿到这串JSON数据进行处理就可以了。

ProblemDetails
SpringBoot中提供了一个类ProblemDetailsExceptionHandler,他会把错误信息转为RFC 7807规范并返回。

可以看到ProblemDetailsExceptionHandler是一个异常处理器
在这里插入图片描述
它会处理以下异常
在这里插入图片描述
接下来我们就使用ProblemDetails处理异常,请求方式异常也属于ProblemDetails处理的异常,我们就模拟改异常的发生。

ProblemDetails默认是不开启的,要想开启需要进行如下配置:

spring.mvc.problemdetails.enabled=true

编写一个控制器方法

@Controller
public class ProblemDetailsController {
  @GetMapping("/testProblem")
  @ResponseBody
  public String testProblem(){
    return "hello";
   }
}

用POST方式访问该方法:

在这里插入图片描述

原生镜像

JAVA语言的执行原理

  • 计算机语言:
    计算机能够直接执行的指令。这种指令和系统及硬件有关。

  • 计算机高级语言:
    在遵循语法的前提下,写一个文本文件,之后利用某种方式,把文本转换为计算机指令执行。

我们编写的都是计算机高级语言,而将计算机高级语言转为计算机语言运行,有两种方式:

  • 动态解释(JIT):解释执行,运行时翻译为机器码。(比如Python,也称为解释型语言)
    在这里插入图片描述

  • 静态编译(AOT):程序在执行前全部被翻译为机器码,可以直接运行二进制文件。(比如C++,也称为解释型语言)
    在这里插入图片描述
    这两种方式各有优缺点,动态解释代码运行效率较低,但可以跨平台运行。

静态编译代码运行效率较高,但不能跨平台运行,而且编译代码比较浪费时间,调试成本高。

JAVA语言:先编译,后解释执行
在这里插入图片描述

注意,JVM并不是单纯依靠解释器解释虚拟指令,JVM中既有解释器,还有即时编译器。

  • 解释器可以将字节码文件解释为机器指令,立即执行。

  • 即时编译器可以将字节码文件编译为机器指令,存在内存中,编译完成后直接执行本地机器指令即可。
    当Java虚拟器启动后,解释器首先发挥作用,不必等待即时编译器全部编译完成后再执行。随着时间的推移,编译器把越来越多的代码编译成本地代码,此时运行本地机器指令,获得更高的执行效率。

虽然这种启动方式很优秀,但他的启动还是比AOT方式慢。在当前微服务云原生盛行的时代,JAVA 程序显得越来越臃肿,虽然使用AOT也有诸多缺点,比如打包时间长、舍弃平台无关性、反射、动态代理的分析能力有限。但是JAVA必定会向AOT发展,否则在云原生时代,可以能被其他后起之秀慢慢蚕食市场。

Native Image 和 GraalVM

Native Image
Native Image(原生镜像)是一种将Java代码提前编译为二进制文件的技术,即本机可执行文件。在Windows中就是.exe文件,它脱离了Java程序员运行时对JVM的依赖,运行时效率极高。

Spring推荐使用SpringBoot3+GraalVM官方构建工具实现原生镜像构建。

GraalVM
GraalVM是一个高性能跨语言虚拟机,其目的是提升Java和其他使用JVM语言编写程序的执行速度,同时也为JavaScript、Python和许多其他流行语言提供运行时环境。起始于2011年Oracle实验室的一个研究项目。
在这里插入图片描述

GraalVM可以直接当做JVM使用,也可以对Java等多种语言实现静态编译,生成Java项目的原生镜像。

生成原生镜像

接下来我们就生成SpringBoot3项目的原生镜像:

1.安装GraalVM

  • 解压windows版的GraalVM
  • 配置环境变量JAVA_HOME和Path

2.创建SpringBoot项目

创建时的JDK一定要选择GraalVM

添加依赖时一定要选择GraalVM
在这里插入图片描述

编写控制器

@Controller
public class HelloController {
  @ResponseBody
  @RequestMapping("/hello")
  public String hello(){
    return "Hello Native Image";
   }
}

3.通过安装VisualStudio安装C++开发环境,虽然GraalVM可以生成原生镜像,但底层是调用C++的方式生成的.exe可执行文件。
在这里插入图片描述
在这里插入图片描述
4.使用maven将SpringBoot项目打包成可执行文件
在这里插入图片描述

生成Linux原生镜像

1.准备Linux虚拟机,连接虚拟机

2.安装C++开发环境

yum install -y gcc glibc-devel zlib-devel

3.安装GraalVM

# 创建空文件夹
mkdir -p /usr/local/java

# 进入文件夹
cd /usr/local/java

# 上传GraalVM到Linux虚拟机

# 解压GraalVM
tar -zxvf graalvm-jdk-17_linux-x64_bin.tar.gz

4.配置GraalVM环境变量

# 打开环境变量配置文件
vim  /etc/profile

# 添加如下内容
export JAVA_HOME=/usr/local/java/graalvm-jdk-17.0.8+9.1
export PATH=$PATH:$JAVA_HOME/bin

# 使环境变量生效
source /etc/profile

# 查看Java版本
java -version

如果Java版本没有改动,卸载掉Linux系统自带的JDK即可:

# 查看系统自带的Java
rpm -qa|grep java

# 卸载JAVA
rpm -e --nodeps java版本

5.安装Maven

# 创建空文件夹
mkdir -p /usr/local/maven

# 进入文件夹
cd /usr/local/maven

# 上传Maven到Linux虚拟机

# 解压Maven
tar -xvf apache-maven-3.8.8-bin.tar.gz

6.配置Maven环境变量

# 打开环境变量配置文件
vim  /etc/profile

# 添加如下内容
export M2_HOME=/usr/local/maven/apache-maven-3.8.8
export PATH=$PATH:$M2_HOME/bin

# 使环境变量生效
source /etc/profile

# 查看Maven版本
mvn -version

7.修改SpringBoot项目pom文件

<!-- 添加如下内容,使maven给项目打包时生成原生镜像 -->
<profiles>
  <profile>
    <id>native</id>
    <properties>
      <repackage.classifier>exec</repackage.classifier>
      <native-buildtools.version>0.9.13</native-buildtools.version>
    </properties>
    <build>
      <plugins>
        <plugin>
          <groupId>org.graalvm.buildtools</groupId>
          <artifactId>native-maven-plugin</artifactId>
          <extensions>true</extensions>
          <executions>
            <execution>
              <id>build-native</id>
              <phase>package</phase>
              <goals>
                <goal>build</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
  </profile>
</profiles>

8.把项目压缩成zip文件

9.把项目的压缩文件上传到虚拟机上

10解压项目

# 安装unzip
yum install unzip
# 解压项目
upzip springbootdemo10.zip 

10.进入项目,执行mvn clean package -DskipTests -Pnative,生成原生镜像

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力
在这里插入图片描述

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

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

相关文章

阿里P8大佬推荐的前端书籍资料,限时免费领取!

&#x1f381; 限时福利大放送&#xff01; &#x1f389; 亲爱的前端小伙伴们&#xff0c;今天给大家分享几个前端必备资料 有P8大佬的算法解题笔记, 最新大厂高频100题, 前端经典八股文&#xff0c;也有一些前端经典书籍&#xff0c;如nodejs&#xff0c;http&#xff0c;jav…

ros笔记04--从零体验ros2行为通信方式

ros笔记04--从零体验ros2行为通信方式 介绍创建步骤体验官方案例基于python开发行为案例创建action接口创建action sever和client 注意事项说明 介绍 行为是ros2中的一种通信方式&#xff0c;其多被用于一些长时间运行的任务&#xff0c;它包含了目标、反馈、结果三部分。 行为…

科普文:从源码解读5种Redis基本数据类型

键值对字符串 char* 与 SDS char* 的不足&#xff1a; 操作效率低&#xff1a;获取长度需遍历&#xff0c;O(N)复杂度 二进制不安全&#xff1a;无法存储包含 \0 的数据 SDS 的优势&#xff1a; 操作效率高&#xff1a;获取长度无需遍历&#xff0c;O(1)复杂度&#xff08…

HIS系统搭建|HIS系统功能|HIS系统开发

在当今医疗信息化的浪潮中&#xff0c;医院信息系统&#xff08;HIS&#xff09;的搭建成为了提升医疗服务效率和质量的关键。HIS系统不仅仅是一个简单的数据记录工具&#xff0c;它是一个集成了预约挂号、病历管理、药品管理、财务结算等多个功能模块的综合性平台。通过这一系…

使用idea集成的springboot实现注册接口

跟黑马程序员学pringboot3vue3,代码都是黑马程序员视频里的代码 实战篇-03_注册接口_哔哩哔哩_bilibili 本文仅仅用于学习记录 开发用户接口 注册接口 开发流程&#xff1a;明确需求>>阅读接口文档>>思路分析>>开发>>测试 分析&#xff1a; 这个…

使用SDL库以及C++实现的简单的贪吃蛇:AI Fitten生成

简单使用AI代码生成器做了一个贪吃蛇游戏 设计的基本逻辑都是正确的&#xff0c;能流畅运行 免费准确率高&#xff0c;非常不错&#xff01;支持Visual Studio系列 Fitten&#xff1a;https://codewebchat.fittenlab.cn/ SDL 入门指南&#xff1a;安装配置https://blog.csdn.n…

高效数据抓取:Scrapy框架详解

一、Scrapy框架简介 Scrapy是一个为了爬取网站数据、提取结构性数据而编写的爬虫框架。它支持异步处理&#xff0c;能够快速抓取大量网页&#xff0c;并且易于扩展。Scrapy使用Twisted这个事件驱动的网络引擎&#xff0c;可以处理大量的并发请求&#xff0c;从而提高数据抓取的…

C语言分支结构作业

作业 输入你的身高和体重&#xff0c;测试你的健康状况。 计算bmi的值&#xff0c; bmi &#xff08;体重/身高的平方) 如果bmi 小于18.5&#xff0c;则显示“偏瘦&#xff0c;注意加强营养” 如果bmi 在18.5和23.9之间&#xff0c;则显示“体重指数良好&#xff0c;注意保持…

【全栈实战】大模型自学:从入门到实战打怪升级,20W字总结(二)

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本栏讲解【全栈实战】大模型自学&#xff1a;从入门到实战打怪升级。 &#x1f514;专栏持续更新&#xff0c;适合人群&#xff1a;本科生、研究生、大模型爱好者&#xff0c;期…

基于单片机的电梯控制系统的设计

摘 要: 本文提出了一种基于单片机的电梯控制系统设计 。 设计以单片机为核心&#xff0c;通过使用和设计新型先进的硬件和控制程序来模拟和控制整个电梯的运行&#xff0c;在使用过程中具有成本低廉、 维护方便、 运行稳定 、 易于操作 、 安全系数高等优点 。 主要设计思路是…

聚焦全局应用可用性的提升策略,详解GLSB是什么

伴随互联网的快速发展和全球化趋势的深入&#xff0c;企业对网络应用的需求日渐增长。为满足全球范围内用户大量的访问需求&#xff0c;同时解决容灾、用户就近访问以及全球应用交付等问题&#xff0c;GLSB&#xff08;全局负载均衡&#xff09;也因此应运而生。那么GLSB是什么…

Axure RP:打造动态交互的大屏可视化设计利器

Axure大屏可视化是指使用Axure RP这款原型设计工具来创建具有视觉冲击力和数据展示功能的大屏幕界面。Axure以其强大的交互设计和丰富的组件库&#xff0c;成为了实现大屏可视化的重要工具之一。以下是对Axure大屏可视化的详细阐述&#xff1a; 一、Axure在大屏可视化中的优势 …

​易能医药董事长易跃能博士荣获“湖湘药学领航奖”

近日&#xff0c;湖南省药学会主办的“湖南省药学会70周年庆典暨第六届湖南药学大会”在湖南长沙隆重召开。易能医药董事长易跃能博士荣获由湖南省药学会颁发的“湖湘药学领航奖”。此次“湖湘药学领航奖”由湖南药学大会学术委员会组织评选&#xff0c;湖南省全省仅有八个名额…

六、3 PWM 舵机代码

目录 1、通道选择 2、参数计算 3、代码部分 1、通道选择 PA1对应通道2 注意&#xff1a;同一个定时器不同通道输出PWM的特点 同一个定时器的不同通道输出的PWM&#xff0c;频率相同&#xff08;因为它们共用一个计数器&#xff09;&#xff0c;占空比可以各自设定&#xff…

Kubernetes 学习记录

https://note.youdao.com/ynoteshare/index.html?idbc7bee305611b52d6900ba209a92bd4d&typenote&_time1694072007342 概览 K8S官网文档&#xff1a;https://kubernetes.io/zh/docs/home/ K8S 是Kubernetes的全称&#xff0c;源于希腊语&#xff0c;意为“舵手”或“…

ITSS:IT服务工程师

证书亮点&#xff1a;适中的费用、较低的难度、广泛的应用范围以及专业的运维认证。 总体评价&#xff1a;性价比良好&#xff01; 证书名称&#xff1a;ITSS服务工程师 证书有效期&#xff1a;持续3年 培训要求&#xff1a;必须参加培训&#xff0c;否则将无法参与考试 发…

Aboboo一些操作

常用快捷键⌨ 快捷键/操作方式 功能 鼠标中键/Esc 进入/退出全屏 空格/Tab 暂停/恢复播放 左/右箭头 快退/快进 Ctrl-左/右箭头 30秒快退/快进 Alt-左/右箭头 60秒快退/快进 Ctrl-Alt-左/右箭头 播放速率调节 PageUp/PageDown 上一句/下一句 上下箭头/滚轮 …

WSL配置镜像网络使用本地端口调试Linux程序

一、安装WSL 二、配置WSL为镜像 在C:\Users\XXUser目录下添加.wslconfig文件 [wsl2] networkingModemirrored # 开启镜像网络 dnsTunnelingtrue # 开启 DNS Tunneling firewalltrue # 开启 Windows 防火墙 autoProxytrue # 开启自动同步代理重启WSL wsl --shutdown wsl三、…

计算机毕业设计选题推荐-音乐播放系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

计算机网络04

文章目录 IP 基本认识**IP 地址的基础知识****IP 地址的分类**无分类地址 CIDR公有 IP 地址与私有 IP 地址IP 地址与路由控制IP 分片与重组IPv6 基本认识IPv4 首部与 IPv6 首部 IP 协议相关技术DNS 域名解析ARP 与 RARP 协议DHCP 动态获取 IP 地址NAT 网络地址转换ICMP 互联网控…