第六章 :Spring Boot web开发常用注解(一)

第六章 :Spring Boot web开发常用注解(一)

前言

本章节知识重点:作者结合自身开发经验,以及觉察到的一个现象:Springboot注解全面理解和掌握的并不多,对注解进行了全面总结,共分两个章节,可以作为web开发工程师注解参考手册。本章节内容包含:启动类注解,组件注解,实例与生命周期相关注解,SpringMVC相关注解。

web应用开发常用注解概览

作者整理了一张SpringBoot常用注解的思维导图,共分两个章节讲解这些注解的用法。

启动类注解
(1)@SpringBootApplication

作用:这是一个组合注解,包括了@Configuration、@EnableAutoConfiguration和@ComponentScan三个注解。

java 复制代码
@SpringBootApplication
public class MyApplication {

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

@Configuration 注解用于定义配置类,可以替换 XML 配置文件。被注解的类内部包含有一个或多个被 @Bean 注解的方法,这些方法会被 AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext 类进行扫描,并用于构建 bean 定义,初始化 Spring 容器。

java 复制代码
@Configuration  
public class AppConfig {  
  
    @Bean  
    public DataSource dataSource() {  
        DriverManagerDataSource dataSource = new DriverManagerDataSource();  
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");  
        dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");  
        dataSource.setUsername("username");  
        dataSource.setPassword("password");  
        return dataSource;  
    }  
}
(3)@ConfigurationProperties

@ConfigurationProperties 注解用于将配置文件中的属性值注入到一个 Java Bean 中,通常用于将应用程序的配置属性注入到 Java 对象中。它可以将属性对象注册到 Spring 容器中,并与其他 Spring 注解(如 @Autowired)一起使用,实现更加灵活和可配置化的功能。

java 复制代码
@Configuration  
@ConfigurationProperties(prefix = "myapp")  
public class MyAppConfig {  
    private String username;  
    private String password;  
    private int timeout;  
    // getter and setter methods  
}

@ConfigurationProperties 注解的 prefix 属性指定了配置文件中的属性前缀为 myapp,因此 usernamepasswordtimeout 这三个属性值会从配置文件中读取 myapp.usernamemyapp.passwordmyapp.timeout 属性的值。

注意

使用 @ConfigurationProperties 注解时需要在 Spring Boot 主类或配置类上添加 @EnableConfigurationProperties 注解,以激活该注解的功能。

(4)@EnableAutoConfiguration

@EnableAutoConfiguration 注解用于开启自动配置功能,可以自动配置符合条件的 @Configuration 配置,并将它们加载到 Spring Boot 创建并使用的 IoC 容器中。

java 复制代码
@SpringBootApplication  
@EnableAutoConfiguration  
public class MyApp {  
    public static void main(String[] args) {  
        SpringApplication.run(MyApp.class, args);  
    }  
}

@EnableAutoConfiguration 注解被添加到 MyApp 类中,该类还包含了 @SpringBootApplication 注解。这个注解组合实现了自动配置和应用程序启动的功能。

注意

@EnableAutoConfiguration 注解会根据类路径和其他条件自动判断并加载符合条件的配置类,因此开发者不需要手动添加或配置这些配置类。此外,还可以通过 spring.factories 文件来自定义自动配置的类和条件,以满足更加灵活和个性化的需求。

(5)@ComponentScan

@ComponentScan 注解用于自动扫描和注册容器中的组件。使用 @ComponentScan 注解可以告诉 Spring 在指定的包或类路径下进行组件扫描,然后自动将被扫描到的组件注册到 Spring 容器中。

java 复制代码
@Configuration  
@ComponentScan(basePackages = {"com.example.package"})  
public class AppConfig {  
    // 其他配置  
}

Spring Boot 会扫描 com.example.package 包以及其子包中的组件,并将它们注册到 Spring 容器中。

注意

@ComponentScan 可以和 Spring Boot 的自动配置功能一起使用,以实现更加灵活和可配置化的功能。

(6)@PropertySources 与@PropertySource

@PropertySources 和 @PropertySource 注解在 Spring 框架中用于加载外部的属性文件,并将文件中的属性值注入到 Spring 容器中的对象。

@PropertySources 注解可以包含多个 @PropertySource 注解,每个 @PropertySource 指定一个属性文件,用于存储配置信息。

java 复制代码
@Configuration  
@PropertySources({  
    @PropertySource("classpath:config1.properties"),  
    @PropertySource("classpath:config2.properties")  
})  
public class AppConfig {  
    // 其他配置  
}
组件注解
(7)@Component

作用:

  1. 自动扫描和实例化bean:通过@Component注解,Spring Boot会自动扫描带有该注解的类,并将其实例化为Spring容器中的bean。这使得这些类可以在Spring应用程序中使用,并可以通过依赖注入等方式进行配置和使用。
  2. 提供自定义命名:通过在@Component注解中指定value属性,可以为组件指定一个自定义的名称。这有助于在注入时使用指定的名称来引用该组件,而不是使用其默认的类名。
java 复制代码
@Component  
public class MyComponent {  
    // 类的定义和逻辑  
}

注意

@Component注解可以用于任何普通的Java类,包括服务、仓库、控制器等。它是其他特定用途注解(如@Service、@Repository、@Controller等)的基础注解。

(8)@Service

作用:注解用于标记一个类为服务层组件,通常用于实现业务逻辑和封装数据访问等操作。被@Service注解标记的类将被Spring框架自动注册为Spring容器中的Bean,并且可以通过依赖注入的方式在其他组件中使用。

java 复制代码
@Service  
public class MyService {  
    @Autowired  
    private MyRepository myRepository;  
      
    public MyEntity getEntityById(Long id) {  
        return myRepository.findById(id).orElse(null);  
    }  
      
    // 其他业务逻辑方法...  
}
(9)@Repository

作用:注解用于标记一个类为数据访问对象(DAO),通常用于访问数据库。被@Repository注解标记的类将作为DAO层组件,主要作用是封装对数据库的访问操作。

以下是一个使用@Repository注解的示例:

java 复制代码
@Repository  
public interface UserRepository extends JpaRepository<User, Long> {  
    User findByUsername(String username);  
}

注意

@Repository注解还可以用于标记实现类为DAO层组件,例如:

java 复制代码
@Repository  
public class UserRepositoryImpl implements UserRepository {  
    // 实现UserRepository接口中的方法...  
}
(10)@Controller

作用:注解用于标记一个类为控制器层组件,通常用于处理HTTP请求并返回HTTP响应。被@Controller注解标记的类将作为控制器层组件,主要作用是接收客户端发送的请求,并根据请求参数和业务逻辑生成相应的响应。

以下是一个使用@Controller注解的示例:

java 复制代码
@Controller  
@RequestMapping("/users")  
public class UserController {  
    @Autowired  
    private UserService userService;  
      
    @GetMapping("/{id}")  
    public ResponseEntity<User> getUserById(@PathVariable Long id) {  
        User user = userService.getUserById(id);  
        return ResponseEntity.ok(user);  
    }  
      
    // 其他处理请求的方法...  
}
(11)@RestController

作用:注解用于标记一个类或方法,表示该类或方法用于处理HTTP请求,并将响应的结果直接返回给客户端,不需要进行视图渲染

以下是一个使用@RestController注解的示例:

java 复制代码
@RestController  
@RequestMapping("/hello")  
public class HelloController {  
    @GetMapping public String sayHello() {  
        return "Hello World!";  
    }  
}

注意

使用@RestController注解时,方法返回值默认会被转换成JSON格式,并通过HTTP响应返回给客户端。如果需要返回其他格式的数据,可以使用其他注解,比如@ResponseBody注解或者使用特定的视图解析器来渲染视图。

简化代码注解
(12)@Data

作用: 注解是Lombok库提供的一个注解,Lombok会自动生成这些方法,无需手动编写。这可以减少模板代码的编写量,提高代码的可读性和可维护性。它用于简化代码,提高开发效率。@Data注解的主要作用是自动生成一些常用的方法,如getters、setters、equals、hashCode和toString等。

以下是一个使用@Data注解的示例:

java 复制代码
import lombok.Data;  
@Data  
public class User {  
    private String name;  
    private int age;  
}
依赖注入注解
(13)@Autowired

作用:注解是一个核心功能,它用于实现Spring的依赖注入功能。依赖注入是指将一个对象的依赖项(也称为Bean)注入到另一个对象中,从而消除了显式的依赖关系创建。通过使用@Autowired注解,Spring容器会在启动时自动查找并装配标记了该注解的Bean对象。

@Autowired注解可以用于类成员变量、方法及构造函数,它默认是按照类去匹配Bean,也可以配合@Qualifier注解按照名称去装配Bean。

以下是一个使用@Autowired注解的示例:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.stereotype.Component;  
  
@Component  
public class MyComponent {  
    private MyService myService;  
  
    @Autowired  
    public MyComponent(MyService myService) {  
        this.myService = myService;  
    }  
  
    // 其他方法...  
}
(14)@Resource

作用:注解用于依赖注入,和@Autowired注解类似,用于自动装配Spring容器中的Bean之间的依赖关系。

@Resource注解可以用于类中的字段或setter方法,使Spring容器自动装配相应的依赖项。它提供了更多的配置选项,可以通过name属性指定要注入的bean名称,也可以通过type属性指定需要注入的bean类型。

@Resource注解是由Java EE规范定义的,因此使用它可以增加代码的可移植性,使代码可以在其他Java EE应用服务器中重用。

以下是一个使用@Resource注解的示例:

java 复制代码
import javax.annotation.Resource;  
import org.springframework.stereotype.Component;  
  
@Component  
public class MyComponent {  
    @Resource(name="myBean")  
    private MyService myService;  
  
    // 其他方法...  
}
(15)@Qualifier

Spring Boot中的@Qualifier注解是Spring框架中用于注入Bean的注解。它通常与@Autowired或@Inject注解一起使用,用于指定需要注入的Bean的名称。当容器中有多个类型相同的Bean时,可以使用@Qualifier注解来指定需要注入的Bean。

@Qualifier注解可以用于字段、方法参数、构造函数参数等位置。

以下是一个使用@Qualifier注解的示例:

java 复制代码
@Service  
public class UserService {  
    @Autowired  
    @Qualifier("userRepositoryImpl")  
    private UserRepository userRepository;  
      
    public User getUserById(Long id) {  
        return userRepository.findById(id).orElse(null);  
    }  
    // Other business methods...  
}
(16)@Value

作用:注解用于将属性值注入到Spring管理的对象中。通过在字段、方法参数或构造函数参数上使用@Value注解,可以将配置文件中的属性值或其他动态计算的值注入到应用程序中。这样可以将配置信息与代码分离,提高了代码的可维护性和灵活性。

以下是一个使用@Value注解的示例:

java 复制代码
@Value("${test.array1}") private String[] testArray1;  
@Value("${test.array2}") private int[] testArray2;  
@Value("${test.array3}") private double[] testArray3;
(17)@Bean

作用:注解用于定义一个JavaBean,并将其注册到Spring容器中。使用@Bean注解可以方便地将普通的Java类转换为Spring容器中的Bean,并由Spring容器负责实例化、配置和管理。

@Bean注解可以用于类或方法上,通常用于在类中定义一个方法,该方法的返回值是一个JavaBean对象,并由Spring容器负责实例化、配置和管理。

以下是一个使用@Bean注解的示例:

java 复制代码
@Configuration  
public class AppConfig {  
    @Bean  
    public UserService userService() {  
        return new UserServiceImpl();  
    }  
}

注意

使用@Bean注解定义的方法不应该有任何参数,否则会报错。同时,如果该方法有返回值,则返回值应该是一个JavaBean对象,否则也会报错。

实例与生命周期相关注解
(17)@PostConstruct

作用:注解用于在依赖注入完成后自动调用一个初始化方法。该注解可以用于类中的非静态方法上,且该方法会在服务器加载Servlet时执行一次。

注意

使用@PostConstruct注解时,该注解的方法在整个Bean初始化中的执行顺序为:Constructor -> @Autowired -> @PostConstruct。

以下是一个使用@PostConstruct注解的示例:

java 复制代码
@Component  
public class MyBean {  
    @PostConstruct  
    public void init() {  
        // 在依赖注入完成后执行的初始化操作  
    }  
}
(17)@PreDestroy

作用:注解用于在Bean销毁之前执行一个方法。当Bean被销毁时,容器会自动调用被@PreDestroy注解标注的方法。

@PreDestroy注解只能用于方法上,且该方法不能有参数。它可以用于任何Bean中,包括单例Bean和原型Bean。

以下是一个使用@PreDestroy注解的示例:

java 复制代码
@Component  
public class MyBean {  
    @PreDestroy  
    public void destroy() {  
        // 在Bean销毁之前执行的代码  
    }  
}
(17)@Scope

作用:注解用于配置Spring Bean的作用域。它主要定义了Bean的作用范围是单实例还是多实例,可以控制Bean的生命周期。

@Scope注解可以作用于类和方法,通过属性来控制作用域。其作用范围包括singleton、prototype、request、session、globalSession,以及其他的自定义范围。

以下是一个使用@Scope注解的示例:

java 复制代码
@Component  
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)  
public class Service {  
    // ...  
}
SpringMVC相关注解
(18)@RequestMapping

作用:用于将HTTP请求映射到特定的处理方法上。

@RequestMapping注解可以用在类或方法上,用于定义URL和HTTP请求方法与处理方法的映射关系。

以下是一个使用@RequestMapping注解的示例:

java 复制代码
@RestController  
@RequestMapping("/api")  
public class MyController {  
  
    @GetMapping("/hello")  
    public String hello() {  
        return "Hello World!";  
    }  
}
(19)@RequestParam

作用:将请求参数绑定到方法的参数上。在Spring MVC框架中,当浏览器向服务器发起请求时,请求中可能会包含一些参数,例如查询字符串或表单数据。使用@RequestParam注解可以将这些请求参数的值映射到控制器方法的参数上,从而方便地获取和使用这些参数。

@RequestParam注解有以下属性:

  • value:请求参数的名称。如果请求参数的名称与方法参数的名称相同,则该属性可以省略。
  • required:指定请求参数是否是必需的,默认为true。如果设置为false,则表示该参数是可选的。
  • defaultValue:指定当请求参数未提供时使用的默认值。

以下是一个使用@RequestParam注解的示例:

java 复制代码
@RequestMapping("/hello")  
public String hello(@RequestParam("name") String name, @RequestParam(value="age", required=false, defaultValue="0") int age){  
    System.out.println("Hello "+name+", you are "+age+" years old.");  
    return "hello";  
}
(20)@ResponseBody

作用:将Controller的方法返回的对象,通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据。

@ResponseBody注解可以将控制器方法的返回值直接写入到HTTP响应的body中,而不需要经过视图解析器的处理。

以下是一个使用@ResponseBody注解的示例:

java 复制代码
@RestController  
@RequestMapping("/api")  
public class MyController {  
  
    @GetMapping("/data")  
    public @ResponseBody DataResponse getData() {  
        DataResponse response = new DataResponse();  
        response.setId(1);  
        response.setName("John");  
        return response;  
    }  
}
(21)@PathVariable

作用:是将URL路径中的占位符参数绑定到控制器方法的参数上。通过使用@PathVariable注解,控制器方法可以接收URL路径中的参数作为输入,以便根据不同的参数值执行相应的操作。

以下是一个使用@PathVariable注解的示例:

java 复制代码
@RestController  
@RequestMapping("/users/{id}")  
public class UserController {  
  
    @GetMapping("/info")  
    public String getUserInfo(@PathVariable Long id) {  
        // 获取用户信息并返回  
        return "User info for user with ID " + id;  
    }  
}
(22)@GetMapping

作用:处理HTTP GET请求映射到特定的处理方法(Controller方法)。当你希望从服务器获取某些资源或数据时,通常会使用GET请求,适用于获取数据、查看页面等不会产生副作用的操作。

以下是一个使用@GetMapping注解的示例:

java 复制代码
@RestController  
@RequestMapping("/users")  
public class UserController {  
  
    @GetMapping("/{id}")  
    public String getUserInfo(@PathVariable Long id) {  
        // 根据用户ID获取用户信息并返回  
        return "User info for user with ID " + id;  
    }  
}
(23)@PostMapping

@PostMapping注解是Spring Boot中用来声明POST请求处理方法的注解。它的作用是将HTTP POST请求映射到特定的处理方法(Controller方法),并自动将请求体中的数据转换为Java对象。

以下是一个使用@PostMapping注解的示例:

java 复制代码
@RestController  
@RequestMapping("/users")  
public class UserController {  
  
    @PostMapping("/add")  
    public String addUser(@RequestBody User user) {  
        // 处理添加用户的逻辑,并返回结果  
        return "User added successfully!";  
    }  
}

在这个示例中,我们使用@PostMapping注解将POST请求映射到/users/add路径上,并指定处理方法为addUser()。在addUser()方法中,我们使用@RequestBody注解将请求体中的数据自动转换为User对象。这样,当请求体中包含User对象的数据时,该对象将被自动解析并传递给addUser()方法进行处理。在这个例子中,我们将获取到的User对象作为输入,用于添加用户的逻辑,并返回一个字符串作为响应。

测试相关注解

(24)@SpringBootTest

作用:测试Spring Boot应用程序的注解,它会启动整个应用程序上下文以便于执行测试。该注解可以让你在测试时使用完整的Spring应用程序上下文,包括所有的bean、配置和中间件。

以下是一个使用@SpringBootTest注解的示例:

java 复制代码
@RunWith(SpringRunner.class)  
@SpringBootTest(classes = Application.class)  
public class MyApplicationTest {  
  
    @Autowired  
    private MyService myService;  
  
    @Test  
    public void testMyService() {  
        // 执行测试方法,使用myService进行测试  
    }  
}
(25)@MockBean

作用:是在测试中模拟指定的bean。使用该注解可以在测试中创建一个模拟的bean,以便于替换应用程序上下文中原有的bean。通过模拟bean,可以在测试过程中模拟外部依赖或服务,以便于独立地测试应用程序的特定方面。

以下是一个使用@MockBean注解的示例:

java 复制代码
import org.junit.jupiter.api.Test;  
import org.mockito.MockBean;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.boot.test.context.SpringBootTest;  
import org.springframework.boot.test.mock.mockito.MockBeanBuilder;  
import org.springframework.test.context.junit4.rules.SpringClassRule;  
import org.springframework.test.context.junit4.rules.SpringMethodRule;  
  
import static org.junit.jupiter.api.Assertions.*;  
import static org.mockito.Mockito.*;  
  
@SpringBootTest  
public class MyApplicationTest {  
  
    @Autowired  
    private MyService myService;  
  
    @MockBean  
    private MyDependency myDependency;  
  
    @Test  
    public void testMyService() {  
        // 使用MockBean模拟MyDependency对象,并注入到myService中  
        // 在测试方法中,可以通过模拟MyDependency对象来测试myService的行为  
        // 例如,可以调用myDependency的某个方法,验证myService是否正确地使用了该方法  
    }  
}
(26)@Test

注意

SpringBoot和Spring都有各自的测试框架,用于对应用程序进行单元测试和集成测试。

以下是SpringBoot中的@Test注解的作用和示例:

作用: SpringBoot @Test注解的作用是告诉Spring Boot在测试时启动整个应用程序上下文,以便进行集成测试。

以下是一个使用SpringBoot @Test org.junit.jupiter.api.Test 注解的示例:

java 复制代码
import org.junit.jupiter.api.Test;  
import org.springframework.boot.test.context.SpringBootTest;  
import org.springframework.test.context.junit4.SpringRunner;  
  
@RunWith(SpringRunner.class)  
@SpringBootTest  
public class MyApplicationTest {  
  
    @Test  
    public void testMyApplication() {  
        // 在这里编写集成测试代码,使用整个应用程序上下文进行测试  
    }  
}

以下是Spring中的@Test注解的作用和示例:

@Test注解用于标记测试方法或测试类,用于执行单元测试。在测试类中,被标记为测试方法的方法将会被JUnit编译器自动识别并执行。

以下是一个使用@Test org.junit.Test 注解的示例:

java 复制代码
import org.junit.Test;  
import static org.junit.Assert.*;  
  
public class MyOtherTest {  
    @Test  
    public void testSubtraction() {  
        int result = 4 - 2;  
        assertEquals(2, result);  
    }  
}

在上面的示例中,@Test注解用于标记testSubtraction()方法为测试方法,JUnit编译器会自动执行该方法并验证其结果是否符合预期。

(27)@BeforeEach

注意:@AfterEach注解是JUnit5中的注解

作用:用于表示在每个测试方法之前应该执行该注解的方法。这个注解可以用来进行测试前的准备工作,比如初始化测试环境、准备测试数据等。

以下是一个使用@BeforeEach注解的示例:

java 复制代码
import org.junit.jupiter.api.BeforeEach;  
import org.junit.jupiter.api.Test;  
  
public class MyTest {  
    @BeforeEach  
    public void setUp() {  
        // 在每个测试方法之前执行的代码,可以用来进行准备工作  
    }  
  
    @Test  
    public void testMethod1() {  
        // 测试方法1  
    }  
  
    @Test  
    public void testMethod2() {  
        // 测试方法2  
    }  
}
(28)@AfterEach

注意:@AfterEach注解是JUnit5中的注解

作用:这个注解可以用来进行测试后的清理工作,比如回滚数据库修改、关闭文件流等。

以下是一个使用@AfterEach注解的示例:

java 复制代码
import org.junit.jupiter.api.AfterEach;  
import org.junit.jupiter.api.Test;  
  
public class MyTest {  
    @Test  
    public void testMethod1() {  
        // 测试方法1  
    }  
  
    @Test  
    public void testMethod2() {  
        // 测试方法2  
    }  
  
    @AfterEach  
    public void tearDown() {  
        // 在每个测试方法之后执行的代码,可以用来进行清理工作  
    }  
}
(29)@BeforeAll

注意:@AfterEach注解是JUnit5中的注解

作用:用于表示在所有测试方法之前只执行一次该注解的方法。这个注解可以用来进行测试前的准备工作,比如初始化测试环境、读取测试数据等。

以下是一个使用@BeforeAll注解的示例:

java 复制代码
import org.junit.jupiter.api.BeforeAll;  
import org.junit.jupiter.api.Test;  
  
public class MyTest {  
    @BeforeAll  
    public static void setupAll() {  
        // 在所有测试方法之前只执行一次的代码,可以用来进行准备工作  
    }  
  
    @Test  
    public void testMethod1() {  
        // 测试方法1  
    }  
  
    @Test  
    public void testMethod2() {  
        // 测试方法2  
    }  
}
(30)@AfterAll

作用:@AfterAll注解是JUnit5中的注解,用于表示在所有测试方法之后只执行一次该注解的方法。这个注解可以用来进行测试后的清理工作,比如关闭测试数据库连接、清理测试文件等。

以下是一个使用@AfterAll注解的示例:

java 复制代码
import org.junit.jupiter.api.AfterAll;  
import org.junit.jupiter.api.Test;  
  
public class MyTest {  
    @Test  
    public void testMethod1() {  
        // 测试方法1  
    }  
  
    @Test  
    public void testMethod2() {  
        // 测试方法2  
    }  
  
    @AfterAll  
    public static void tearDownAll() {  
        // 在所有测试方法之后只执行一次的代码,可以用来进行清理工作  
    }  
}
相关推荐
seventeennnnn2 小时前
谢飞机的Java高级开发面试:从Spring Boot到分布式架构的蜕变之旅
spring boot·微服务架构·java面试·分布式系统·电商支付
超级小忍4 小时前
服务端向客户端主动推送数据的几种方法(Spring Boot 环境)
java·spring boot·后端
时间会给答案scidag4 小时前
报错 400 和405解决方案
vue.js·spring boot
Wyc724095 小时前
SpringBoot
java·spring boot·spring
ladymorgana6 小时前
【Spring Boot】HikariCP 连接池 YAML 配置详解
spring boot·后端·mysql·连接池·hikaricp
GJCTYU8 小时前
spring中@Transactional注解和事务的实战理解附代码
数据库·spring boot·后端·spring·oracle·mybatis
风象南9 小时前
SpringBoot敏感配置项加密与解密实战
java·spring boot·后端
写不出来就跑路10 小时前
暑期实习感悟与经验分享:从校园到职场的成长之路
java·开发语言·经验分享·spring boot
程序员张314 小时前
Maven编译和打包插件
java·spring boot·maven
灵犀学长16 小时前
EasyExcel之SheetWriteHandler:解锁Excel写入的高阶玩法
spring boot·excel