Spring

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 和业务逻辑的职责。

Linux 与 Spring 中 Cron 的区别

1、概览 通过 Cron 表达式,我们可以安排任务在特定日期和时间定期运行。Cron 表达式在 Unix 中推出后,其他基于 Unix 的操作系统和软件库(包括 Spring)都采用了它的任务调度方法。 本文将带你了解基于 Unix 操作系统的 Cron 表达式与 Spring Cron 之间的区别。 2、Unix Cron 在大多数基于 Unix 的系统中,Cron 有五个字段:分钟(0-59)、小时(0-23)、月日(1-31)、月份(1-12 或名称)和星期(0-7 或名称)。 可以在每个字段中添加一些特殊值,如星号(*): 5 0 * * * 任务将在每天午夜后 5 分钟执行。也可以使用数值范围: 5 0-5 * * * 如上,调度器将在午夜 12 点后 5 分钟执行任务,并在每天 1 点、2 点、3 点、4 点和 5 点后 5 分钟执行任务。 或者,可以使用一个值列表: 5 0,3 * * * 现在,调度器会在每天午夜 12 点后 5 分钟和下午 3 点后 5 分钟执行作业。原始 Cron 表达式提供的功能远不止这些。

如果 @PathVariable 包含点(.),会被截断

1、概览 使用 Spring 的 @PathVariable 和 @RequestMapping 来映射包含点的请求时,最后一个 URI 路径变量的值被会截断。 2、原因 具体来说,Spring 认为最后一个点后面的任何内容都是文件扩展名,如 .json 或 .xml,因此,它会截断值以检索路径变量。 来看一个使用路径变量的例子: @RestController public class CustomController { @GetMapping("/example/{firstValue}/{secondValue}") public void example(@PathVariable("firstValue") String firstValue, @PathVariable("secondValue") String secondValue) { // ... } } 如上,考虑以下请求 URL 以及 firstValue 和 secondValue 变量的值: example/gallery/link:firstValue = "gallery",secondValue = "link"。 example/gallery.df/link.ar URL:firstValue = "gallery.df ",secondValue = "link" example/gallery.df/link.com.ar:firstValue = "gallery.df",secondValue = "link.com" 可以看到,第一个变量不受影响,但第二个带点(.)的变量总是被截断。 3、解决办法 解决这种不便的方法之一是修改 @PathVariable 定义,添加一个 regex(正则)映射。这样,任何点(包括最后一个点)都将被视为参数的一部分: @GetMapping("/example/{firstValue}/{secondValue:.+}") public void example( @PathVariable("firstValue") String firstValue, @PathVariable("secondValue") String secondValue) { //.

Spring 中的 @PathVariable 注解

1、概览 本文将带你了解 Spring 中 @PathVariable 注解的作用和用法。 简单地说,@PathVariable 注解可用于处理请求 URI 映射中的模板变量,并将其绑定到 Controller 方法参数。 2、示例映射 @PathVariable 注解的一个简单用例是用于标识具有 ID 的实体的端点: @GetMapping("/api/employees/{id}") @ResponseBody public String getEmployeesById(@PathVariable String id) { return "ID: " + id; } 在本例中,使用 @PathVariable 注解来提取 URI 的模板部分,该部分由变量 {id} 表示。 调用示例如下: http://localhost:8080/api/employees/111 ---- ID: 111 3、指定 PATH (路径)变量名 在上一个示例中,由于方法参数和路径变量的名称相同,可以不用主动设置模板路径变量的名称。 如果路径变量名不同,可以在 @PathVariable 注解的参数中指定: @GetMapping("/api/employeeswithvariable/{id}") @ResponseBody public String getEmployeesByIdWithVariableName(@PathVariable("id") String employeeId) { return "ID: " + employeeId; } 测试如下: http://localhost:8080/api/employeeswithvariable/1 ---- ID: 1 为了清晰起见,还可以将路径变量名定义为 @PathVariable(value="id"),而不是 PathVariable("id")。

Spring MVC Async 和 WebFlux

1、概览 本文将带你了解 Spring Async 和 Spring WebFlux 之间的区别。 2、场景 本文分别用 Spring Async 和 Spring WebFlux 来实现一个简单的 Web 应用。 Web 请求会通过一个延迟时间为 200 毫秒的 Filter,然后 Controller 需要 500 毫秒来计算并返回结果。 最后使用 Apache ab 分别进行负载测试,并使用 JConsole 监控应用的行为。 3、Spring MVC Async Spring 3.0 引入了 @Async 注解。@Async 的目标是允许应用在单独的线程上运行重负载的任务。此外,调用方可以等待结果(如果感兴趣)。因此,返回类型不能是void,而可以是 Future、CompletableFuture 或 ListenableFuture 之一。 Spring 3.2 引入了 org.springframework.web.context.request.async 包,它与 Servlet 3.0 一起为 Web 层带来了异步的支持。因此,自 Spring 3.2 起,@Async 可以在 @Controller 或 @RestController 类中使用。 当客户端发起请求时,请求会经过过滤器链(filter chain)中所有匹配的过滤器(filter),直到到达 DispatcherServlet 实例。 然后,Servlet 会对请求进行异步调度。它通过调用 AsyncWebRequest#startAsync 将请求标记为已启动,将请求处理转移到 WebSyncManager 的实例,然后在不提交响应的情况下完成其工作。过滤器链也按相反的方向遍历执行到根节点。