SpringBoot快速上手

news2024/11/26 22:22:38

SpringBoot

概述

  • Spring Boot 可以轻松创建独立的、生产级的基于 Spring 的应用程序,您可以“直接运行”。

特征

  • 创建独立的 Spring 应用程序
  • 直接嵌入Tomcat,Jetty或Undertow(无需部署WAR文件)

  • 提供固执己见的“入门”依赖项以简化构建配置

  • 尽可能自动配置 Spring 和第三方库

  • 提供生产就绪功能,如指标、运行状况检查和外部化配置

  • 绝对无需生成代码,也无需 XML 配置

什么是微服务?

  • 微服务是一种架构风格,它要求我们在开发一个应用的时候,这个应用必须构建成一系列小服务的组合;可以通过http的方式进行互通。

SpringBoot原理

自动配置:
pox .xml

  • spring-boot-dependencies:核心依赖在父工程中
  • 当引入一些SpringBoot以来的时候,不需要指定版本,因为有版本仓库

启动器

<dependency>
	  <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-staeter</artifactId>
</dependency>
  • 启动类:说白了就是SpringBoot的启动场景
  • 比如spring-boot-starter-web ,它会帮我们自动导入web环境的所有依赖。
  • springboot会将所有的功能场景都变成一个个启动器

主程序


//@SpringBootApplication:标注这个类是一个springboot的应用
@SpringBootApplication
public class AliyunApplication {

    public static void main(String[] args) {
    		//将springboot应用启动
        SpringApplication.run(AliyunApplication.class, args);
    }

}

注解

@SpringBootConfiguration :springboot的配置
	@Configuration :spring配置类
		@Component:说明这是一个spring的组件
@EnableAutoConfiguration 自动配置
	@AutoConfigurationPackage:自动配置包
	@Import({AutoConfigurationImportSelector.class}):导入选择 
	

结论: springboot所有自动加载都是在启动的时候扫描并加载spring.factories所有的自动配置类都在这里面,但不一定生效,要判断条件是否成立,只需要导入对应的start,就有对应的启动器了,有了启动其自动配置就会成效,然后配置成功。

  1. springboot在启动的时候,从类路径下/META-INF/spring.factories获取指定的值;
  2. 将这些自动配置的类导入容器,自动配置就会生效,帮我们进行自动配置!
  3. 以前我们需要自动配置的东西,现在springboot就帮我们做了。
  4. 整个javaEE解决方案与自动配置的东西都在spring-boot-autoconfigure-2.6.11.jar这个包下
  5. 它会把所有需要导入的组件,以类名的形式返回,这些组件就会北添加到容器;
  6. 容器中也会存在非常多的xxxAutoConfiguration的文件(@Bean),就是这邪恶类给容器中导入了所有的组件;并自动配置,@Configuration,JavaConfig
  7. 有了这些自动配置类,免去了我们手动编写配置文件的工作!

yaml

简介:YAML(/ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达数据序列化的格式。YAML参考了其他多种语言,包括:C语言、Python、Perl,并从XML、电子邮件的数据格式(RFC 2822)中获得灵感。Clark Evans在2001年首次发表了这种语言,另外Ingy döt Net与Oren Ben-Kiki也是这语言的共同设计者。当前已经有数种编程语言或脚本语言支持(或者说解析)这种语言。

基本语法

server:
  port: 8080

#普通的的key-value
name: springboot

#对象
student:
  name: zhangsan
  age: 20

#行内写法
teacher: { name: lisi,age: 22 }

#数组
pets:
  - cat
  - dog
  - pig

Animals: [cat,dog,pig]

yaml可以直接给实体类赋值。
Dog类

package com.example.aliyun.pojo;

import org.springframework.stereotype.Component;

@Component
public class Dog {
    private String name;
    private Integer age;

    public Dog() {
    }

    public Dog(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Person类:

package com.example.aliyun.pojo;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private Integer age;
    private Boolean happy;
    private Date birthday;
    private Map<String, Object> maps;
    private List<Object> list;
    private Dog dog;

    public Person() {
    }

    public Person(String name, Integer age, Boolean happy, Date birthday, Map<String, Object> maps, List<Object> list, Dog dog) {
        this.name = name;
        this.age = age;
        this.happy = happy;
        this.birthday = birthday;
        this.maps = maps;
        this.list = list;
        this.dog = dog;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Boolean getHappy() {
        return happy;
    }

    public void setHappy(Boolean happy) {
        this.happy = happy;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public List<Object> getList() {
        return list;
    }

    public void setList(List<Object> list) {
        this.list = list;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", happy=" + happy +
                ", birthday=" + birthday +
                ", maps=" + maps +
                ", list=" + list +
                ", dog=" + dog +
                '}';
    }
}

application.yaml

person:
  name: lisi
  age: 18
  happy: false
  birthday: 2023/1/1
  maps: {hight: 188,weight: 72}
  list:
    - code
    - music
    - film
  dog:
   name: 小黑
   age: 2



Test测试类

package com.example.aliyun;

import com.example.aliyun.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class AliyunApplicationTests {
   @Autowired
    private Person person;
    @Test
    void contextLoads() {
        System.out.println(person);
    }

}

运行结果
在这里插入图片描述

值得注意的是yaml可以使用${}
Dog类

package com.example.aliyun.pojo;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "dog")
public class Dog {
    private String name;
    private Integer age;

    public Dog() {
    }

    public Dog(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

applicat.yaml

dog:
  name: 小黑${random.uuid}
  age: ${random.int}

测试类

package com.example.aliyun;

import com.example.aliyun.pojo.Dog;
import com.example.aliyun.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class AliyunApplicationTests {
   @Autowired
    private Dog dog;
    @Test
    void contextLoads() {
        System.out.println(dog);
    }

}

运行结果
在这里插入图片描述
松散绑定
比如我们在yaml中写的是last-name在类中的属性为驼峰命名法的lastName,这两个之间还是可以绑定起来
Dog类

package com.example.aliyun.pojo;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "dog")
public class Dog {
    private String lastName;
    private Integer age;
    public Dog() {

    }
    public Dog(String lastName, Integer age) {
        this.lastName = lastName;
        this.age = age;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "lastName='" + lastName + '\'' +
                ", age=" + age +
                '}';
    }
}

application.yaml

dog:
  last-name: 小黑${random.uuid}
  age: ${random.int}

运行结果
在这里插入图片描述
JSR303校验:就是在字段上增加一层过滤器验证,可以保证数据的合法性
在这里插入图片描述

在这里插入图片描述
图片来自与狂神说

测试一下
Person类

package com.example.aliyun.pojo;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.validation.constraints.Email;

@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {

   @Email(message = "你的邮箱格式错了")
    private String name;
    private Integer age;
    private Boolean happy;
    private Date birthday;
    private Map<String, Object> maps;
    private List<Object> list;
    private Dog dog;

    public Person() {
    }

    public Person(String name, Integer age, Boolean happy, Date birthday, Map<String, Object> maps, List<Object> list, Dog dog) {
        this.name = name;
        this.age = age;
        this.happy = happy;
        this.birthday = birthday;
        this.maps = maps;
        this.list = list;
        this.dog = dog;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Boolean getHappy() {
        return happy;
    }

    public void setHappy(Boolean happy) {
        this.happy = happy;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public List<Object> getList() {
        return list;
    }

    public void setList(List<Object> list) {
        this.list = list;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", happy=" + happy +
                ", birthday=" + birthday +
                ", maps=" + maps +
                ", list=" + list +
                ", dog=" + dog +
                '}';
    }
}

application.yaml

person:
  name: lisi
  age: 18
  happy: false
  birthday: 2023/1/1
  maps: {hight: 188,weight: 72}
  list:
    - code
    - music
    - film
  dog:
   last-name: 小黑
   age: 2

测试类

package com.example.aliyun;

import com.example.aliyun.pojo.Dog;
import com.example.aliyun.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class AliyunApplicationTests {
   @Autowired
   private Person person;;
    @Test
    void contextLoads() {
        System.out.println(person);
    
    }

}

运行结果
在这里插入图片描述
在这里插入图片描述

多环境配置以及配置文件位置

配置文件位置

  1. file:./config/
  2. file:./
  3. classpath:./config/
  4. classpath:./

优先级顺序
在这里插入图片描述
多环境配置

方式一(application.properties)
现在有三个端口【默认:8081】【开发环境:8081】【测试环境:8082】
在这里插入图片描述
application.properties

server.port=8080

application-dev.properties

server.port=8081

application-test.properties

server.port=8082

springboot的多环境配置:可以选择激活哪一个文件配置

application.properties

spring.profiles.active=dev

运行结果
在这里插入图片描述
application.properties

spring.profiles.active=test

运行结果

在这里插入图片描述
方式二(application.yaml)[推荐使用]
注意:---为分割线,分割其他环境
spring: profiles:的作用相当于起名称
application.yaml

server:
  port: 8080

---
server:
  port: 8081
spring:
  profiles: dev
---
server:
  port: 8082
spring:
  profiles: test

这就相当于方式一的三个文件了
springfiles: active:选择要激活的版本
比如现在需要激活dev环境
applicat.yaml

server:
  port: 8080
spring:
  profiles:
    active: dev
---
server:
  port: 8081
spring:
  profiles: dev
---
server:
  port: 8082
spring:
  profiles: test

运行结果
在这里插入图片描述
如果现在需要激活test环境

server:
  port: 8080
spring:
  profiles:
    active: test
---
server:
  port: 8081
spring:
  profiles: dev
---
server:
  port: 8082
spring:
  profiles: test

运行结果
在这里插入图片描述
由此可以发现yaml格式要方便的多

自动装配原理的精髓重点

  1. SpringBoot启动会加载大量的自动配置类
  2. 我们看我们需要的功能有没有在SpringBoot默任写好的自动配置类当中;
  3. 我们再来看这个自动装配类中到底配置了哪些组件;(只要我们要用的组件存在其中,我们就不再需要手动配置了)
  4. 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可。
    xxxAutoConfiguration:自动配置类;给容器中添加组件;
    xxxPeoperties:封装配置文件中的相关属性;
    通过springboot配置 ...yaml去修改属性

可以通过debug: ture查看哪些自动配置类生效,哪些自动配置类没有生效
运行结果
在这里插入图片描述


springWeb开发

首先要解决的问题

  • 导入静态资源…
  • 固定首页
  • jsp,模板引擎Thymeleaf
  • 装配扩展SpringMVC
  • 增删改查
  • 拦截器
  • 国际化
静态资源
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
	if (!this.resourceProperties.isAddMappings()) {
	    logger.debug("Default resource handling disabled");
			return;
	}
	addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
	addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
	registration.addResourceLocations(this.resourceProperties.getStaticLocations());
	if (this.servletContext != null) {
		ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION);
	   registration.addResourceLocations(resource);
		}
	});
}

什么是webjars
Webjars本质就是以jar包的方式引入我们的静态资源 , 我们以前要导入一个静态资源文件,直接导入即可。
例如以maven的方式引入jQuery

<dependency>
    <groupId>org.webjars</groupId>
     <artifactId>jquery</artifactId>
    <version>3.4.1</version>
</dependency>

在这里插入图片描述

第一种方式
在这里插入图片描述
在这里插入图片描述
当这三种方式同时存在时比较优先级
在这里插入图片描述
结论:当三种方式同时存在时:resources包下面的优先级最高

删除resources包下的1.js,比较剩下两种的优先级
在这里插入图片描述

再删除static包下的1.js,
在这里插入图片描述

结论 优先级从高到低:resources->static->public

resouses、static、public优先级比较
1. 在springboot中我们可以使用以下方式处理静态资源

  • webjars 访问方式:localhost:8080/webjars/
  • resources、static、public ,/** 访问方式:localhost:8080/

2. 优先级:resource>static>public
3.当我们自定义了一个访问静态资源的路径,那么默认的路径都会失效
例如:

spring:
  mvc:
    static-path-pattern: "/hello/**"

结果如下:
在这里插入图片描述

需要用我们自定义的路径去访问
在这里插入图片描述

首页和图标的定制

…未完待续

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

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

相关文章

初始C语言 - 函数(2)

目录 1.函数的嵌套调用和链式访问 1&#xff09;函数嵌套调用 2&#xff09;函数的链式访问 - 函数的返回值作为另一个函数的参数 2. 函数的声明和定义 1&#xff09;变量的声明和定义 2&#xff09;函数的声明和定义 //函数必须先声明后使用//函数的声明写在头文件里 3.…

集成学习、Bagging集成原理、随机森林构造过程、随机森林api与案例、boosting集成原理、梯度提升决策树(GBDT)、XGBoost与泰勒展开式

一、集成学习 集成学习&#xff1a;通过建立几个模型来解决单一预测问题&#xff0c;工作原理是生成多个分类器/模型&#xff0c;各自独立地学习和作出预测。这些预测最后结合成组合预测&#xff0c;因此优于任何一个单分类的做出预测 机器学习的两个核心任务 集成学习中boost…

【UE4 第一人称射击游戏】51-制作手榴弹

上一篇&#xff1a;【UE4 第一人称射击游戏】50-用另一种方法实现僵尸随机漫游 僵尸攻击玩家时造成伤害本篇效果&#xff1a;按G键投掷出手榴弹&#xff0c;产生爆炸效果步骤&#xff1a;新建一个蓝图类&#xff08;父类为Actor&#xff09;&#xff0c;命名为“GrenadeActor”…

水声功率放大器模块在圆柱壳结构声源辐射研究中的应用

客户需求&#xff1a;实验需要在消声水池中对圆柱壳声源振动和远场声压进行实验测量&#xff0c;圆柱壳内部尺寸为&#xff1a;高0.5m(不含盖板)&#xff0c;壳外径0.5&#xff0c;内径0.497m&#xff0c;上下盖板高0.014m&#xff0c;所以对圆柱壳内功率放大模块的尺寸以及供电…

Qt图表操作(QCustomPlot 与 QtCharts的介绍与使用)

一、QCustomPlot简介 QCustomPlot是QT下一个方便易用的绘图工具&#xff0c;该绘图库专注于制作美观&#xff0c;出版品质的2D图表&#xff0c;图表和图表&#xff0c;以及为实时可视化应用程序提供高性能。它可以导出为各种格式&#xff0c;如矢量化的PDF文件和光栅化图像&…

Task12 数据缘何而来数据格式

目录1 常见的格式1.1 Excel文件的格式1.2 Excel数据的格式1.3 基本知识2 Excel数据格式2.1 数据类型转换3 练习1 常见的格式 1.1 Excel文件的格式 Excel文件的常见格式&#xff1a;.xls和.xlsx 1.2 Excel数据的格式 Excel数据的存储不同格式&#xff1a;xlsx、csv、txt cs…

mysql快速生成100W条测试数据(8)全球各城市人口及经济增长速度并存入mysql数据库

这是之前的文章里面包含一些以前的一些操作流程可以进行参考学习 更加详细操作步骤在第一篇文章里面 mysql快速生成100W条测试数据&#xff08;1&#xff09;&#xff1a;游戏人物数据 mysql快速生成100W条测试数据&#xff08;2&#xff09;公司员工信息 mysql快速生成100W条测…

本地挂载网盘_Alist_RaiDrive_windows

目录 一、下载安装Alist 二、启动登录Alist 三、挂载网盘 四、挂载到本地 五、开机自启动 一、下载安装Alist 安装地址&#xff1a;https://github.com/alist-org/alist 二、启动登录Alist 1.打开alist.exe所在目录&#xff0c;输入cmd 2.利用cmd&#xff0c;输入alist …

[oeasy]python0051_ 转义_escape_字符_character_单引号_双引号_反引号_ 退格键

转义字符 回忆上次内容 上次研究的是进制转化10进制可以转化为其他形式 binocthex 其他进制也可以转化为10进制 int可以设置base来决定转为多少进制 回忆一下 我们为什么会有八进制&#xff1f;因为需要用八进制输出转义字符 \ooo 把(ooo)8进制对应的ascii字符输出 就如同 \…

QMAKE_POST_LINK QMAKE_PRE_LINK解释

命令解释 QMAKE_POST_LINK是在可执行程序链接后执行它的命令 QMAKE_PRE_LINK是在可执行程序链接前执行它的命令 注意C/C程序是先编译后链接 如果你需要一个编译前执行的命令可以使用 copy_files.files $$filelist copy_files.path $$OUT_PWD COPIES copy_files即使是编…

存储与数据库 | 字节青训营笔记

目录 一、存储系统 1、什么是存储系统 2、存储系统的特点 3、RAID技术 RAID出现的背景 RAID 0 RAID 1 RAID 01 二、数据库 1、难道数据库和存储系统不一样吗 2、数据库vs经典存储 三、主流产品剖析 1、单机存储 本地文件系统 key-value存储 2、分布式存储系统 …

【程序员陪你过大年】html+css+js 实现春节动态烟花特效及服务器部署

前言 不知不觉又到了年底&#xff0c;这一年是值得庆贺的一年&#xff0c;疫情过去&#xff0c;经济好转。我们急需在春节这个特殊的日志释放下自己的情绪。但是大部分地区都不让放炮&#xff0c;于是乎我为大家带来一套十分炫酷应景的春节烟花动画代码实现。效果如下图所示 :…

第10章 FreeRTOS

ESP32 FREERTOS 打印ESP32任务 menuconfig中&#xff0c;打开FreeRTOS的trace打印功能 menuconfig中&#xff0c;增加app_main主任务的栈大小 测试代码 ESP32最小工程 #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h&q…

php sql注入

文章目录一、什么是sql注入二、sql注入处理1、使用内置函数2、使用pdo预处理语句三、安全注意事项一、什么是sql注入 在应用程序中&#xff0c;为了和用户交互&#xff0c;允许用户提交输入数据&#xff0c;假如应用程序并没有对用户输入数据进行处理&#xff0c;攻击者可以输…

linux开发工具

文章目录linux开发工具1.软件包管理器yum2.编辑器vim3.gcc4.make与makefile5.git6.gdb7.小程序进度条linux开发工具 1.软件包管理器yum yum等同于手机上的应用商店.yum自动解决软件之间的耦合问题 yum list 显示软件清单 yum install 下载 yum remove 删除 2.编辑器vim 其…

opencv开发之numpy使用

打开Spyder, 在IPython控制台中输入 import numpy as np 引入numpy库并使用numpy构造一个ndarray对象: np.zeros((2,4),np.uint8),该对象为一个二维数组 ,构造一个2行4列的二维数组(矩阵) ,并初始化所有元素为0,及指定数据类型为uint8 创建并初始化:数据可视化:取矩阵类型: typ…

基于YOLOv4的车辆检测 MATLAB实现

目录 摘要 研究背景 算法设计及实现过程 车辆目标数据集的构建 基于YOLOv4的目标检测 对YOLOv4模型进行改进 实验结果及分析 结论与展望 代码实现 摘要 针对车辆检测&#xff0c;本文提出了一种基于YOLOv4车辆检测算法。制作了一个多天侯、多时段、多场景的车辆目标数…

怎么拆分PDF文件,教你用最简单的方法

PDF文档拆分是一种很常见的需求。因为有时候文档页数过多&#xff0c;打开和阅读都不太方便&#xff0c;我们可以通过拆分把想要的部分提取出来。拆分PDF的时候可以借助一些工具更快更有效地达成目的&#xff0c;这里就给大家介绍几款比较受欢迎的处理工具&#xff0c;它们在辅…

Linux——系统管理篇

1、、Linux 中的进程和服务 计算机中、一个正在执行的程序或命令&#xff0c;叫进程&#xff08;process&#xff09;。 启动之后一直存在、常驻内存的进程&#xff0c;一般称为“服务”&#xff08;Service&#xff09; // 我更喜欢叫它守护进程 Daemon 比如windows的那一堆…

软件测试面试,如何自我介绍?

01 如何自我介绍 面试过程中一定要放慢语速&#xff0c;做到条理清晰。特别是做自我介绍时&#xff0c;可以适当多介绍自己会什么&#xff0c;有哪些重要经验。 例如&#xff1a; 面试官&#xff0c;上午/下午好。 我是XXX&#xff0c;今天来面试贵公司的软件测试工程师岗位&a…