目录
-
- Controller
-
- @Controller
- @RestController
- @ResponseBody
- [@GetMapping 与 @PostMapping](#@GetMapping 与 @PostMapping)
- @RequestMapping
- @RequestParam
- @PathVariable
- @RequestBody
- @Valid
- Service
- Entity
-
- @Data
- @JsonFormat
- @ToString
- @TableName("xxx")
- @TableField
- @ApiModel("xxx对象")
- [@Accessors(chain = true)](#@Accessors(chain = true))
- DAO
- 配置
- 其他
Controller
@Controller
标识一个Spring MVC控制器,用于处理HTTP请求。
@RestController
@RestController 注解是 @Controller 和 @ResponseBody 两个注解的组合。@Controller 注解表明这个类是一个 Spring MVC 控制器,而 @ResponseBody 注解则表明控制器的方法返回值应该绑定到 web 响应体上。
@RestController
是 Spring Boot 中的一个非常核心的注解,它用于标注在类上,表明这个类是一个控制器(Controller),并且所有的方法返回值都会直接作为 HTTP 响应体返回给客户端,这通常用于构建 RESTful Web 服务。
@ResponseBody
@ResponseBody
是 Spring MVC 和 Spring Boot 中用于标注在控制器(Controller)的方法上的注解。它表明该方法的返回值应该直接作为 HTTP 响应体返回给客户端,而不是被解析为跳转路径或模板名称。
java
@Controller
public class MyController {
@GetMapping("/hello")
@ResponseBody
public String hello() {
return "Hello, Spring MVC!";
}
}
@GetMapping 与 @PostMapping
@GetMapping
和 @PostMapping
是用于处理 HTTP GET 和 POST 请求的注解。它们分别对应于 HTTP 协议中的 GET 和 POST 方法,常用于构建 RESTful Web 服务。
java
@RestController
public class MyController {
@GetMapping("/hello")
public String hello() {
return "Hello, GET request!";
}
@PostMapping("/submit")
public String submit(@RequestParam String data) {
// 处理提交的数据
return "Received data: " + data;
}
}
@RequestMapping
@RequestMapping
用于处理 HTTP 请求的注解。它可以标注在类 或方法上,用于将 HTTP 请求映射到特定的处理方法上。
java
@Controller
@RequestMapping("/users")
public class UserController {
@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
public String getUser(@PathVariable("userId") String userId, Model model) {
// 处理 GET 请求,路径如 /users/{userId}
return "user";
}
@RequestMapping(value = "/new", method = RequestMethod.GET)
public String newUserForm(Model model) {
// 处理 GET 请求,路径如 /users/new
return "userForm";
}
}
@RequestParam
@RequestParam
将HTTP请求中的查询参数或表单参数绑定到控制器方法的参数上。
如果你有一个请求URL为/user?name=John,那么使用@RequestParam("name") String userName可以将查询参数name的值John绑定到方法参数userName上。
@PathVariable
@PathVariable
将URL模板变量值绑定到控制器方法的参数上。这通常用于RESTful风格的URL,其中URL的一部分表示资源的标识符。
如果你有一个请求URL为/users/123,并且控制器方法定义为@GetMapping("/users/{userId}"),那么使用@PathVariable("userId") String userId可以将URL模板变量userId的值123绑定到方法参数userId上。
@RequestBody
@RequestBody
将HTTP请求体的内容绑定到控制器方法的参数上。这通常用于处理客户端发送的JSON或XML数据。
如果你有一个请求体为{"name":"John", "age":30}的POST请求,并且控制器方法定义为@PostMapping("/user"),那么使用@RequestBody User user可以将请求体中的JSON数据绑定到方法参数user上,其中User是一个具有name和age属性的Java类。
java
@RestController
@RequestMapping("/api")
public class MyController {
// 使用@RequestParam绑定查询参数
@GetMapping("/greeting")
public ResponseEntity<String> greeting(@RequestParam(name = "name", defaultValue = "World") String name) {
return ResponseEntity.ok("Hello, " + name + "!");
}
// 使用@PathVariable绑定URL模板变量
@GetMapping("/users/{userId}")
public ResponseEntity<String> getUser(@PathVariable("userId") String userId) {
return ResponseEntity.ok("User ID: " + userId);
}
// 使用@RequestBody绑定请求体内容
@PostMapping("/user")
public ResponseEntity<String> createUser(@RequestBody User user) {
// 假设User是一个具有name和age属性的Java类
return ResponseEntity.ok("User created: " + user.getName() + ", " + user.getAge());
}
}
@Valid
@Valid
注解在 Spring 框架中用于开启对方法参数或返回值的自动验证,通常与 @NotNull
、@Size
等一起使用以验证 Java Bean 的属性。
java
@RestController
@RequestMapping("/api")
public class ValidationController {
@PostMapping("/create")
public ResponseEntity<String> createItem(@Valid @RequestBody Item item) {
// 如果验证通过,则处理数据
return ResponseEntity.ok("Item created: " + item.getName());
}
public static class Item {
@NotBlank(message = "Name is required and cannot be blank")
private String name;
@Min(1)
private int quantity;
// 省略构造函数、getter和setter方法
}
}
Service
@Service
@Service
注解主要用于标记业务逻辑层的服务组件。这个注解是 @Component
的一个特化版本,用于指示一个类应该被视为Spring应用上下文中的一个Bean。当Spring进行组件扫描时,它会自动检测并实例化所有带有 @Service
注解的类,并将它们注入到依赖于这些服务的其他Bean中。
@Autowired
@Autowired
用于实现依赖注入,可以用在变量、构造方法、setter 方法上。Spring 在进行依赖注入时,会先尝试按类型(byType)进行匹配,如果找到多个相同类型的 Bean,则会按名称(byName)进行匹配。
java
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 使用 userRepository 的方法...
}
@Resource
@Resource
用于实现依赖注入。
虽然@Autowired和@Resource都用于依赖注入,但它们在细节上存在一些差异:
- 来源:@Autowired是Spring框架提供的注解,而@Resource是Java EE 5引入的标准注解,Spring框架也支持它。
- 默认行为:@Autowired默认按类型进行注入,可以通过@Qualifier注解指定名称;@Resource默认按名称进行注入,如果未指定名称,则按字段名或setter方法名进行查找,如果还是找不到,则按类型查找。
- 灵活性:@Resource注解在灵活性方面略胜一筹,因为它同时支持按名称和按类型进行注入。
@Scheduled
@Scheduled
注解用于在应用程序中定义定时任务。它允许你以声明式的方式定义需要周期性执行的方法。@Scheduled
注解可以接受多个参数来自定义调度策略,其中initialDelay和fixedRate就是两个常用的参数。
- initialDelay: 设定第一次执行任务前的延迟时间,单位是毫秒。例如,initialDelay = 360000L意味着第一次执行这个定时任务将在360秒(即360000毫秒)之后开始。
- fixedRate: 一个固定的时间间隔(毫秒),从上一次任务的完成到下一次任务的开始。例如,fixedRate = 300000L意味着每次任务执行完成后,下一次执行将在5分钟后(即300000毫秒)开始。
- cron: 一个 cron 表达式,用于定义任务的执行频率。cron 表达式是一个字符串,由六个或七个空格分隔的字段组成,分别代表秒、分、小时、日、月、周和年(可选)。例如 "0 0 12 * * ?" 表示每天中午12点执行。
- fixedDelay: 类似于 fixedRate,但是计算间隔是从上一次任务的开始到下一次任务的开始。
注意事项:1.如果一个方法同时使用了 cron 和 fixedRate 或 fixedDelay,那么 cron 将会优先级更高。2.使用 fixedRate 或 fixedDelay 时,如果方法的执行时间超过设定的间隔,那么下一次执行将被推迟,直到当前执行完成。3.任务的执行是在后台线程中进行的,因此不会阻塞应用程序的主线程。
java
@Service
public class ScheduledTasks {
@Scheduled(cron = "0 0 * * * ?")
public void scheduledMethod() {
// 你的任务代码
}
}
在Spring Boot中启用@Scheduled
注解需要在配置类上添加@EnableScheduling
注解。一旦你添加了@EnableScheduling
,你就可以在任何bean类中使用@Scheduled
注解来定义定时任务。
java
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
@Configuration
@EnableScheduling
public class AppConfig {
// 其他配置代码...
}
@Async
@Async
是 Spring 框架中的一个注解,用于在 Spring 应用程序中轻松地实现异步方法调用。通过使用 @Async
,你可以将方法标记为异步执行,从而提高应用程序的响应性和性能。
用途:
- 异步方法调用:将长时间运行的任务放在后台线程中执行,以避免阻塞主线程。
- 提高应用性能:通过将耗时的任务异步执行,可以显著提高应用程序的响应速度和吞吐量。
- 解耦任务执行:将任务提交给异步执行器,而不关心具体的执行细节。
java
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
@Service
@EnableAsync
public class AsyncService {
@Async
public void doSomethingAsync() {
try {
Thread.sleep(5000); // 模拟耗时操作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Finished executing asynchronously");
}
}
为了启用异步支持, 需要使用 @EnableAsync
启用异步支持
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(4);
executor.setQueueCapacity(50);
executor.setThreadNamePrefix("Async-Executor-");
executor.initialize();
return executor;
}
}
指定异步执行器:
- 定义执行器
java
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean(name = "deleteCosExecutor")
public Executor deleteCosExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.initialize();
return executor;
}
}
- 异步注解使用自定义执行器
java
@Service
public class SomeService {
@Async("deleteCosExecutor")
public void deleteSomethingAsync() {
// 这里是异步执行的代码
System.out.println("Deleting something asynchronously...");
// 模拟耗时操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
Entity
@Data
@Data
是 Lombok 库提供的一个非常实用的注解,它能够极大地减少在 Java 类中编写 getter、setter、toString、equals 和 hashCode 方法的样板代码。当你在一个类上使用 @Data
注解时,Lombok 会基于类中的字段自动生成这些方法。
@Data
注解是以下多个 Lombok 注解的组合:
@Getter
:为所有非静态字段生成 getter 方法。@Setter
:为所有非静态字段生成 setter 方法。@RequiredArgsConstructor
:为所有被 @NonNull 标记的构造器参数生成构造器。@ToString
:生成toString 方法。@EqualsAndHashCode
:生成 equals 和 hashCode 方法。
java
@Data
public class Person {
private String name;
private int age;
private boolean active;
}
@JsonFormat
@JsonFormat
是一个属于 Jackson 库的注解,是一个流行的 Java JSON 处理库。Jackson 用于将 Java 对象序列化成 JSON 字符串(也称为"写入"或"序列化"),以及将 JSON 字符串反序列化成 Java 对象(也称为"读取"或"反序列化")。
@JsonFormat
注解允许你自定义 Java 对象中的属性如何被序列化和反序列化成 JSON。这包括日期时间格式、空值处理、模式匹配等。
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="Asia/Shanghai")
java
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
public class Event {
private String name;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date eventTime;
// getters and setters
}
@ToString
@ToString
是 Lombok 库中的一个注解,用于自动生成类的 toString() 方法。
@TableName("xxx")
@TableName
是 MyBatis Plus 中的一个注解,用于指定映射到数据库表的实体类所对应的表名。这个注解通常用在实体类上,以明确指出该实体类与哪个数据库表相对应。
@TableField
@TableField
是 MyBatis Plus 中的一个注解,用于指定实体类中的字段与数据库表中的字段之间的映射关系。
除了指定字段映射之外,@TableField 注解还支持其他配置选项。以下是一些常见的配置:
- exist:指定字段是否存在于数据库表中。默认为 true。
- fill:指定字段的填充策略,例如 INSERT(插入时填充)、UPDATE(更新时填充)等。
- el:表达式语言,用于动态生成字段值。
- select:查询时的 SQL 片段。
- update:更新时的 SQL 片段。
java
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@TableName("user") // 指定实体类对应的数据库表名
public class User {
@TableId(type = IdType.AUTO) // 指定主键,并设置主键生成策略为自增
private Long id;
@TableField("name") // 指定Java对象属性对应数据库表的字段名,如果Java属性名和数据库字段名一致,则可以省略该注解
private String name;
@TableField("age")
private Integer age;
// 如果Java属性名和数据库字段名不一致,则需要使用@TableField注解明确指定
@TableField("email_address")
private String email;
// 省略getter和setter方法
// ...
}
@ApiModel("xxx对象")
@ApiModel
是一个用于生成 API 文档的注解,它属于 Swagger(现在称为 OpenAPI)规范的一部分。Swagger 是一个用于生成、描述、调用和可视化 RESTful 服务的框架。@ApiModel
注解用来描述一个模型(通常是一个 POJO 类),它提供了关于模型的元数据,例如模型的描述和属性。
java
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel(value = "xxx对象", description = "这是一个xxx对象的描述,包含了xxx的相关信息")
public class XxxObject {
@ApiModelProperty(value = "ID", example = "123")
private Long id;
@ApiModelProperty(value = "名称", example = "示例名称")
private String name;
// 省略getter和setter方法
}
@Accessors(chain = true)
@Accessors(chain = true)
是 Lombok 库中的一个注解,用于简化 Java 类中 getter 和 setter 方法的编写。当你在类上应用此注解时,Lombok 会在编译时自动生成 getter 和 setter 方法,并且这些方法可以链式调用。
java
import lombok.Accessors;
import lombok.Data;
@Data
@Accessors(chain = true)
public class Person {
private String name;
private int age;
private String address;
}
链式调用:
java
public class Main {
public static void main(String[] args) {
Person person = new Person()
.setName("Alice")
.setAge(30)
.setAddress("123 Main St.");
System.out.println(person);
}
}
DAO
@Repository
主要用于标记数据访问层(DAO层)的组件。
@Mapper
用于指示接口应该被 MyBatis 作为映射器(Mapper)处理的注解。
- 识别 Mapper 接口:
当你在一个接口上使用@Mapper
注解,MyBatis 和 Spring 就知道这个接口是一个 Mapper,它会被自动扫描并注册到 Spring 容器中作为一个 Bean。 - 自动创建 Mapper 实现:
MyBatis 会为带有@Mapper
注解的接口自动生成一个实现类。这个实现类通过动态代理机制创建,并且实现了接口中定义的所有方法。 - 避免 XML 映射文件:
从 MyBatis 3.4.0 版本开始,你可以完全不使用 XML 映射文件,而是在接口的方法上使用注解来定义 SQL 查询和其他数据库操作。 - 动态 SQL 支持:
你可以在接口方法上使用如@Selec
t,@Insert
,@Update
,@Delete
等注解来定义 SQL 语句。对于更复杂的动态 SQL,还可以使用@SelectProvider
或@UpdateProvider
等注解配合提供者类和方法来生成 SQL。
java
import org.apache.ibatis.annotations.*;
// 使用@Mapper注解表明这是一个MyBatis的Mapper接口
@Mapper
public interface UserMapper {
// 定义一个查询所有用户的SQL语句
@Select("SELECT * FROM user")
List<User> findAllUsers();
// 定义一个根据ID查询用户的SQL语句
@Select("SELECT * FROM user WHERE id = #{id}")
User findUserById(@Param("id") int id);
// 定义一个插入新用户的SQL语句
@Insert("INSERT INTO user (name, email) VALUES (#{name}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insertUser(User user);
// 定义一个更新用户信息的SQL语句
@Update("UPDATE user SET name = #{name}, email = #{email} WHERE id = #{id}")
void updateUser(User user);
// 定义一个删除用户的SQL语句
@Delete("DELETE FROM user WHERE id = #{id}")
void deleteUser(@Param("id") int id);
}
// 假设User类如下
public class User {
private int id;
private String name;
private String email;
// 构造函数,getters和setters省略...
}
配置
@Configuration
@Configuration
是 Spring 框架中的一个注解,用于定义 Spring 配置类。它用于替代 XML 配置文件,使你可以通过 Java 代码来定义 Spring 应用程序的配置。
主要用途:
- 定义 Bean:通过
@Bean
方法定义 Spring 容器中的 Bean。 - 导入其他配置类:使用
@Import
注解导入其他的配置类。 - 启用自动扫描:使用
@ComponentScan
注解来指定 Spring 自动扫描的包,从而发现和注册带有相应注解的类(如@Service
,@Repository
,@Controller
等)作为 Spring Bean。
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
// 其他 @Bean 方法...
}
@ComponentScan
@ComponentScan
是 Spring 框架中的一个注解,用于指定 Spring IoC 容器自动扫描的包,从而发现和注册带有特定注解的类作为 Spring Bean。这使得你可以以声明式的方式管理组件,而不是手动定义每一个 Bean。
用途:
- 自动发现组件:Spring 会自动查找并注册标注了
@Component
,@Service
,@Repository
,@Controller
,@RestController
等注解的类作为 Spring Bean。 - 减少显式配置:通过使用
@ComponentScan
,你可以减少在配置文件中显式定义 Bean 的需求,从而简化配置。 - 灵活的扫描选项:可以指定扫描的包、排除的包、扫描的模式等。
java
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"com.example.service"})
public class AppConfig {
// 其他配置...
}
@Component
@Component
注解用于标记一个类可以被Spring的IoC(控制反转)容器管理为一个"bean"。这意味着Spring可以自动创建这个类的实例并管理其生命周期。
@Bean
@Bean
是 Spring 框架中的一个注解,用于在配置类中定义和注册 bean。当在方法上使用 @Bean
注解时,该方法会被 Spring 容器识别,并将其返回的对象注册为一个 bean。这个 bean 将被管理并可以注入到其他 bean 中。
java
@Configuration // @Bean 注解通常与 @Configuration 注解一起使用。
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
在下面的例子中,myService() 方法依赖于 Dependency 类型的 bean。Spring 会首先调用 dependency() 方法来创建并注册 Dependency 类型的 bean,然后将它注入到 myService() 方法中,以便你可以将它传递给 MyServiceImpl 实例。
java
@Configuration
public class AppConfig {
// myService bean依赖于dependency bean,而Spring会自动处理这些依赖关系,确保在创建MyServiceImpl实例时,Dependency 已经准备好并可以使用。
@Bean
public MyService myService(Dependency dependency) {
MyServiceImpl myService = new MyServiceImpl();
myService.setDependency(dependency);
return myService;
}
@Bean
public Dependency dependency() {
return new Dependency();
}
}
@PostConstruct
用于标记在依赖注入完成后执行的方法。
java
/*
使用了 Spring 的 @Component 注解来将 MySpringComponent 注册为 Spring Bean。Spring 容器会自动检测到 @PostConstruct 注解,并在依赖注入完成后调用 initializeConnection 方法。
*/
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class MySpringComponent {
private Connection connection;
public MySpringComponent(Connection connection) {
this.connection = connection;
}
// @PostConstruct 方法应该是 void 类型的,不接受任何参数。
@PostConstruct
public void initializeConnection() {
// 初始化连接
connection.initialize();
System.out.println("Connection initialized.");
}
// 其他方法...
}
@Conditional
@Conditional
是 Spring 框架中的一个注解,用于根据一定的条件决定是否注册一个 Bean。这使得你可以根据应用程序的环境或配置动态地决定哪些 Bean 应该被创建和注册到 Spring 容器中。
用途:
- 条件化 Bean 注册:根据不同的条件(如系统属性、环境变量、类是否存在等)来决定是否注册一个 Bean。
- 依赖检查:检查特定的类或 Bean 是否存在,从而决定是否注册另一个 Bean。
- 配置选择:根据不同的环境配置(如开发、测试、生产环境)来选择不同的 Bean 实现。
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConditionalConfig {
@Bean
@Conditional(OnWindowsCondition.class)
public Service windowsService() {
return new WindowsServiceImpl();
}
@Bean
@Conditional(OnLinuxCondition.class)
public Service linuxService() {
return new LinuxServiceImpl();
}
}
// 条件类
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
// Condition 接口需要实现 matches 方法,该方法接收两个参数:
// - ConditionContext:提供了访问 Spring 应用上下文的方法,可以获取环境变量、类路径资源等。
// - AnnotatedTypeMetadata:提供了访问元数据的方法,可以获取注解信息等。
public class OnWindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").toLowerCase().contains("windows");
}
}
public class OnLinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getEnvironment().getProperty("os.name").toLowerCase().contains("linux");
}
}
@ConfigurationProperties
@ConfigurationProperties
是 Spring Boot 提供的一个非常有用的注解,它用于将配置文件中的属性绑定到 Java Bean 上。通过使用 @ConfigurationProperties
,开发者可以很方便地将 application.properties 或 application.yml 文件中的配置项映射到 Java 类的字段上,进而在 Spring 应用程序中使用这些配置项。
application.properties 文件:
myapp.name=MyApplication
myapp.description=This is my application's description
在类中绑定属性:
java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "myapp")
public class MyAppConfig {
private String name;
private String description;
// getters and setters 省略
}
其他
@Slf4j
@Slf4j
是 Lombok 库中的一个注解,它用于简化在 Java 类中创建 Logger 对象的过程。
在没有 Lombok 的情况下:
java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ExampleClass {
private static final Logger logger = LoggerFactory.getLogger(ExampleClass.class);
public void someMethod() {
logger.info("This is an info message.");
}
}
然而,使用 Lombok 的 @Slf4j
注解,可以自动为类生成 logger 成员变量,而不需要手动写这段代码。只需要在你的类定义上添加@Slf4j
注解,Lombok 就会在编译时为你生成相应的 Logger 实例。因此,上面的代码可以简化为:
java
@Slf4j
public class ExampleClass {
public void someMethod() {
// 注意这里的logger已经由Lombok自动生成了
logger.info("This is an info message.");
}
}
ps:本文每个注解的主要内容由文心一言、通义千问、kimi生成,然后节选部分内容后归类整理,主要用于复习知识与快速查阅,如果觉得本文有用欢迎点赞收藏哦🌹