Spring

使用 Spring ResponseEntity 处理 HTTP 响应

1、概览 本文将带你了解如何使用 ResponseEntity 设置 HTTP 响应的 Body、Status 和 Header。 2、ResponseEntity ResponseEntity 表示整个 HTTP 响应:状态码、Header 和 Body。因此,可以用它来完全配置 HTTP 响应。只需从端点返回它,Spring 就会处理接下来的所有事情。 ResponseEntity 是一个泛型类。因此,可以使用任何类型作为响应体: @GetMapping("/hello") ResponseEntity<String> hello() { return new ResponseEntity<>("Hello World!", HttpStatus.OK); } 通过编程式,可以针对不同情况返回不同的 HTTP 状态码: @GetMapping("/age") ResponseEntity<String> age( @RequestParam("yearOfBirth") int yearOfBirth) { if (isInFuture(yearOfBirth)) { return new ResponseEntity<>( "Year of birth cannot be in the future", HttpStatus.BAD_REQUEST); // 400 } return new ResponseEntity<>( "Your age is " + calculateAge(yearOfBirth), HttpStatus.OK); // 200s } 还可以设置 HTTP 响应头:

Spring 中的 @RequestParam 注解

1、概览 本文将带你了解 Spring 中 @RequestParam 注解的用法。 简单地说,可以使用 @RequestParam 从请求中提取查询参数、表单参数甚至是多个参数。 2、示例端点 假设我们有一个端点 /api/foos,它接受一个名为 id 的查询参数: @GetMapping("/api/foos") @ResponseBody public String getFoos(@RequestParam String id) { return "ID: " + id; } 在本例中,使用 @RequestParam 来提取 id 查询参数。 通过 GET 请求来调用 getFoos: http://localhost:8080/spring-mvc-basics/api/foos?id=abc ---- ID: abc 接下来,看看注解的属性:name、value、required 和 defaultValue。 3、指定请求参数名称 在上一个示例中,变量名和参数名都是相同的。 如果变量名称和参数名称不同,可以使用 name 属性配置 @RequestParam 名称: @PostMapping("/api/foos") @ResponseBody public String addFoo(@RequestParam(name = "id") String fooId, @RequestParam String name) { return "ID: " + fooId + " Name: " + name; } 也可以使用 @RequestParam(value = "id") 或直接使用 @RequestParam("id")。

Spring 重新加载 Properties 属性

1、概览 本文将带你了解如何在 Spring 中重新加载 Properties 配置属性。 2、Spring 读取 Properties Spring 有几种不同的方式来访问 Properties: Environment - 可以注入 Environment,然后使用 Environment#getProperty 来读取给定的属性。Environment 包含不同的属性源,如系统属性(System Properties)、-D 参数和 application.properties(或者 .yml) 等。还可以使用 @PropertySource 将额外的属性源添加到 Environment 中。 Properties - 可以将 properties 文件加载到 Properties 实例中,然后在 Bean 中通过调用 properties.get("property") 使用它。 @Value - 可以使用 @Value(${'property'}) 注解在 Bean 中注入特定属性。 @ConfigurationProperties - 可以使用 @ConfigurationProperties 在 Bean 中加载层次化的属性。。 3、重新加载外部属性文件 要在运行时更改文件中的属性(Properties),应该将该文件放在 Jar 之外的某个地方。然后使用命令行参数 -spring.config.location=file://{文件路径} 告诉 Spring 文件的位置。或者,也可以将其放在 application.properties 中。 对于基于磁盘文件的 Properties,可以开发一个端点或定时任务来读取文件并更新 Properties。 Apache 的 commons-configuration 是一个用于重新加载属性文件的库。可以使用 PropertiesConfiguration 和不同的 ReloadingStrategy 。

Spring Bean 注解

1、概览 本文将带你了解最常见的 Spring Bean 注解,用于定义不同类型的 Bean。 在 Spring 容器中配置 Bean 有几种方法。可以使用 XML 配置声明,也可以在配置类中使用 @Bean 注解声明 Bean。 最后,还可以使用 org.springframework.stereotype 包中的注解来标记类,然后由组件扫描来处理。 2、组件扫描 如果启用了组件扫描,Spring 就可以自动扫描包中的 Bean。 通过 @ComponentScan 注解配置要扫描的包,以查找带有注解配置的类。可以使用 basePackages 或 value 参数(value 是 basePackages 的别名)指定 base package: @Configuration @ComponentScan(basePackages = "com.baeldung.annotations") class VehicleFactoryConfig {} 还可以使用 basePackageClasses 参数指定 base package 中的类: @Configuration @ComponentScan(basePackageClasses = VehicleFactoryConfig.class) class VehicleFactoryConfig {} 这两个参数都是数组,因此可以为每个参数指定多个 package。 如果没有指定参数,将从 @ComponentScan 注解类所在的同一个包中开始扫描。 @ComponentScan 利用了 Java 8 的重复注解功能,这意味着可以多次使用它来标记一个类: @Configuration @ComponentScan(basePackages = "com.baeldung.annotations") @ComponentScan(basePackageClasses = VehicleFactoryConfig.

Spring Data 注解

1、简介 Spring Data 提供了对数据存储技术的抽象。因此,我们的业务逻辑代码可以更加独立于底层持久化实现。而且,Spring 还简化了处理与数据存储相关的实现细节的过程。 本文将带你了解 Spring Data、Spring Data JPA 和 Spring Data MongoDB 项目中最常见的注解。 2、常见的 Spring Data 注解 2.1、@Transactional @Transactional 用于定义事务方法: @Transactional void pay() {} 如果在类上应用此注解,那么它就会对类中的所有方法起作用。也可以在方法上定义此注解来进行覆盖。 2.2、@NoRepositoryBean 有时我们会通过一个基本的 Repository 接口,定义一些通用的方法。然后,所有的 Repository 来继承这个基本的 Repository 接口。 基本的 Repository 接口不应该被实例化为 Bean,所以可以使用 @NoRepositoryBean 注解进行标注。 例如,如果想在所有 Repository 中使用 Optional<T> findById(ID id) 方法,那么可以创建一个基础 Repository 接口: @NoRepositoryBean interface MyUtilityRepository<T, ID extends Serializable> extends CrudRepository<T, ID> { Optional<T> findById(ID id); } 此注解不会影响子接口,因此 Spring 将会把下面 Repository 接口创建为 Bean:

Spring 定时任务注解

1、概览 本文将带你了解 org.springframework.scheduling.annotation 包中和调度相关的注解。 2、@EnableAsync 注解用于在 Spring 中启用异步功能。 必须与 @Configuration 一起使用: @Configuration @EnableAsync class VehicleFactoryConfig {} 启用了异步调用后,可以使用 @Async 来定义支持异步调用的方法。 3、@EnableScheduling @EnableScheduling 用于启用定时任务调度。同样,必须与 @Configuration 结合使用: @Configuration @EnableScheduling class VehicleFactoryConfig {} 启用了定时调度后,就可以可以使用 @Scheduled 注解来定期运行方法。 4、@Async @Async 用于注解需要异步执行的方法。 @Async void repairCar() { // ... } 如果将此注解应用于一个类,那么所有方法都将被异步调用。 注意,需要通过 @EnableAsync 或 XML 配置来启用异步调用,此注解才会生效。 5、@Scheduled 如果需要定期执行一个方法,可以使用此注解: @Scheduled(fixedRate = 10000) void checkVehicle() { // ... } 可以使用它来按固定间隔执行方法,或者可以使用类似 cron 的表达式进行微调。 @Scheduled 利用了 Java 8 的重复注解功能,这意味着可以多次使用它来标记一个方法: @Scheduled(fixedRate = 10000) @Scheduled(cron = "0 * * * * MON-FRI") void checkVehicle() { // .

Spring Web 注解

1、概览 本文将带你了解 org.springframework.web.bind.annotation 包中的 Spring Web 注解。 2、@RequestMapping 简单地说,@RequestMapping 注解用于标记 @Controller 类中的请求处理方法(Handler),可配置的属性如下: path 或其别名 name 和 value:方法映射到的 URL method:支持的 HTTP 方法 params:内容协商,根据 HTTP 参数的有无或值匹配请求 headers:内容协商,根据 HTTP Header 的存在、缺失或值匹配请求 consumes:支持的请求媒体类型(Content-Type) produces:响应的媒体类型 示例如下: @Controller class VehicleController { @RequestMapping(value = "/vehicles/home", method = RequestMethod.GET) String home() { return "home"; } } 在 @Controller 类的类级应用此注解,就能为类中的所有 Handler 方法提供默认设置。唯一的例外是 URL,Spring 不会在方法级设置覆盖 URL,而是将两个 path 部分拼接在一起。 例如,以下配置与上述配置效果相同: @Controller @RequestMapping(value = "/vehicles", method = RequestMethod.GET) class VehicleController { @RequestMapping("/home") String home() { return "home"; } } 此外,@GetMapping、@PostMapping、@PutMapping、@DeleteMapping 和 @PatchMapping 是 @RequestMapping 的不同变体,其 HTTP 方法已分别设置为 GET、POST、PUT、DELETE 和 PATCH。

Spring 核心注解

1、概览 我们可以通过 org.springframework.beans.factory.annotation 和 org.springframework.context.annotation 包中的注解来使用 Spring DI 引擎的功能。 通常把这些注解称为 “Spring 核心注解”。 2、和 DI 相关的注解 2.1、@Autowired 可以在构造函数、Setter 方法或字段注入中使用 @Autowired 注解,Spring 会解析并注入依赖。 构造函数注入: class Car { Engine engine; @Autowired Car(Engine engine) { this.engine = engine; } } Setter 注入: class Car { Engine engine; @Autowired void setEngine(Engine engine) { this.engine = engine; } } 字段注入: class Car { @Autowired Engine engine; } @Autowired 有一个名为 required 的 boolean 参数,默认值为 true。当 Spring 找不到合适的 Bean 进行注入时,它会控制 Spring 的行为。当值为 true 时,会抛出异常,反之则不会。

Spring Kafka 的 “Trusted Packages” 特性

1、概览 本文将带你了解 Spring Kafka 中的 “Trusted Packages” 功能,了解其背后的动机以及用法。 2、先决条件 一般来说,Spring Kafka 模块允许我们指定一些关于发送的 POJO 的元数据。它通常采用 Kafka Message Header 的形式。 例如,可以这样配置 ProducerFactory: @Bean public ProducerFactory<Object, SomeData> producerFactory() { JsonSerializer<SomeData> jsonSerializer = new JsonSerializer<>(); jsonSerializer.setAddTypeInfo(true); return new DefaultKafkaProducerFactory<>( producerFactoryConfig(), new StringOrBytesSerializer(), jsonSerializer ); } @Data @AllArgsConstructor static class SomeData { private String id; private String type; private String status; private Instant timestamp; } 然后,使用上面用 producerFactory 配置的 KafkaTemplate 在一个 Topic 中生产一条新消息: public void sendDataIntoKafka() { SomeData someData = new SomeData("1", "active", "sent", Instant.

Spring 中的 ApplicationContext

1、概览 本文将带你详细了解 Spring 中的 ApplicationContext 接口。 2、ApplicationContext 接口 Spring 框架的主要功能之一是 IoC(控制反转)容器。Spring IoC 容器负责管理应用的对象。它使用依赖注入来实现控制反转。 BeanFactory 和 ApplicationContext 接口,代表 Spring IoC 容器。其中,BeanFactory 是访问 Spring 容器的根接口。它提供了管理 Bean 的基本功能。 而 ApplicationContext 是 BeanFactory 的子接口。因此,它具备 BeanFactory 的所有功能。 此外,它还提供了更多面向企业的特定功能。ApplicationContext 的重要功能包括解析消息、支持国际化、发布事件以及应用层特定的上下文。这就是为什么我们将其作为默认的 Spring 容器使用的原因。 3、Spring Bean 是什么? 在深入了解 ApplicationContext 容器之前,有必要了解一下 Spring Bean。在 Spring 中,Bean 是 Spring 容器实例化、组装和管理的对象。 那么,是否应该将应用的所有对象都配置为 Spring Bean 呢?作为最佳实践,不应该这样做。 一般来说,根据 Spring 文档 所述,应该为服务层对象、数据访问对象 (DAO)、表现对象、基础架构对象(如 Hibernate SessionFactory、JMS Queue 等)定义 Bean。 此外,通常情况下,不应该在容器中配置细粒度的 Domain 对象。创建和加载 Domain 对象通常是 DAO 和业务逻辑的职责。