教程

在 Spring Boot 中将 YAML 转换成对象列表

1、概览 本文将带你了解如何在 YAML 中定义列表,以及如何在 Spring Boot 中把 YAML 列表映射为 Java List 对象。 2、回顾一下 YAML 中的列表 简而言之,YAML 是一种人类可读的数据序列化标准,为编写配置文件提供了一种简洁明了的方法。YAML 的优点在于它支持多种数据类型,如 List、Map 和标量(Scalar)类型。 YAML 列表中的元素使用 - 字符定义,它们的缩进级别相同: yamlconfig: list: - item1 - item2 - item3 - item4 相比之下,在 properties 中定义列表则使用的是索引值: yamlconfig.list[0]=item1 yamlconfig.list[1]=item2 yamlconfig.list[2]=item3 yamlconfig.list[3]=item4 与 properties 文件相比,YAML 的分层性质大大提高了可读性。YAML 的另一个功能是可以为不同的 Spring Profile 定义不同的属性。从 Boot 2.4.0 版开始,properties 文件也可以这样做。 Spring Boot 为 YAML 配置提供了开箱即用的支持。根据设计,Spring Boot 会在启动时从 application.yml 中加载配置属性,无需任何额外工作。 3、将 YAML 列表绑定至简单的 List Spring Boot 提供了 @ConfigurationProperties 注解,以简化将外部配置数据映射到对象模型的逻辑。

在 Spring Boot 中使用 WebSocket 构建在线日志系统

本文将带你了解如何在 Spring Boot 应用中使用 WebSocket 构建一个在线的日志系统。通过该系统,不需要登录服务器,即可在 HTML 页面上通过 WebSocket 长连接预览到服务器的即时日志。 创建 Spring Boot 应用 添加 spring-boot-starter-websocket 依赖。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> WebSocket 配置 创建 WebSocketConfiguration 配置类,配置 ServerEndpointExporter Bean,用于扫描系统中的 WebSocket 端点实现。 package cn.springdoc.demo.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration public class WebSocketConfiguration { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } 创建日志端点 创建 LoggingChannel WebSocket 端点实现类,接受客户端连接,并且推送日志消息。 package cn.springdoc.demo.web.channel; import java.

Spring Security 和 Apache Shiro

1、概览 在应用开发中,尤其是在企业级 Web 和移动应用领域,安全是一个首要问题。 本文将带你了解、比较两种流行的 Java 安全框架 - Apache Shiro 和 Spring Security。 2、背景 Apache Shiro 诞生于 2004 年,原名 JSecurity,2008 年被 Apache 基金会接受。迄今为止,它已发布了多个版本,最新版本为 1.13.0。 Spring Security 起源于 2003 年的 Acegi,在 2008 年首次公开发布时被纳入 Spring 框架。自诞生以来,它经历了多次迭代,目前的 GA 版本是 6.2.0。 这两种技术都提供身份认证和授权支持,以及加密和 Session 管理解决方案。此外,Spring Security 还提供了一流的保护,防范诸如 CSRF 和会话固定等攻击。 接下来,我们将通过使用 FreeMarker 的 Spring Boot 应用来演示如何使用这两种技术进行身份认证和授权。 3、配置 Apache Shiro 首先,来看看这两种框架的配置有何不同。 3.1、Maven 依赖 添加 shiro-spring-boot-web-starter 和 shiro-core 依赖: <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.5.3</version> </dependency> 依赖的最新版本可在 Maven Central 上找到。

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

使用 Spring Boot 创建 Docker 镜像

1、概览 随着越来越多的企业转向使用容器,Docker 在软件开发中的地位也越来越重要。为此,Spring Boot 2.3 的一大新功能就是为 Spring Boot 应用轻松创建 Docker 镜像提供了支持。 本文将带你了解如何为 Spring Boot 应用创建 Docker 镜像。 2、传统的 Docker 构建 使用 Spring Boot 构建 Docker 镜像的传统方法是使用 Dockerfile。 下面是一个简单的 Dockerfile 示例: FROM openjdk:8-jdk-alpine EXPOSE 8080 ARG JAR_FILE=target/demo-app-1.0.0.jar ADD ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar"] 然后,使用 docker build 命令创建 Docker 镜像。这对大多数应用都很有效,但也有一些缺点。 首先,我们使用的是 Spring Boot 创建的 Fat jar。这会影响启动时间,尤其是在容器化环境中。我们可以通过添加 Jar 文件的解压内容来节省启动时间。 其次,Docker 镜像是分层构建的。Spring Boot Fat Jar 的性质导致所有应用代码和第三方库都被放在一个层中。这意味着,即使只有一行代码发生变化,也必须重建整个层。 通过在构建之前解压 Jar 文件,应用代码和第三方库分别有自己的层。这使我们能够利用 Docker 的缓存机制,当更改一行代码时,只需要重新构建相应的层。 有了这个理念,让我们看看 Spring Boot 如何改进创建 Docker 镜像的过程。

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 表达式提供的功能远不止这些。

在 Spring Boot 中通过 XML 定义 Bean

1、概览 在 Spring 3.0 之前,XML 是定义和配置 Bean 的唯一方法。Spring 3.0 引入了 JavaConfig,允许我们使用 Java 类配置 Bean。不过,如今有些项目仍然在使用 XML 配置文件。 本文将带你了解如何在 Spring Boot 应用中整合 XML 配置。 2、@ImportResource 注解 @ImportResource 注解可以导入一个或多个包含 Bean 定义的资源。 比方说,我们有一个包含 Bean 定义的 beans.xml 文件: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean class="com.baeldung.springbootxml.Pojo"> <property name="field" value="sample-value"></property> </bean> </beans> 要在 Spring Boot 应用中使用它,可以使用 @ImportResource 注解,告诉它在哪里可以找到配置文件: @Configuration @ImportResource("classpath:beans.xml") public class SpringBootXmlApplication implements CommandLineRunner { @Autowired private Pojo pojo; public static void main(String[] args) { SpringApplication.

在 Spring Boot 中恢复 Flyway 失败的迁移

1、概览 Flyway 迁移并不总是一帆风顺行,本文将带你了解迁移失败后的恢复方案。 2、设置 从基本的 Spring Boot 配置 Flyway 开始。它依赖 flyway-core、spring-boot-starter-jdbc 和 flyway-maven-plugin。 对于如何在 Spring Boot 中使用 Flyway 进行数据库迁移,你可以参阅 这篇文章。 2.1、配置 首先,添加两个不同的 Profile(配置文件)。这能够轻松地针对不同的数据库引擎运行迁移: <profile> <id>h2</id> <activation> <activeByDefault>true</activeByDefault> </activation> <dependencies> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> </dependencies> </profile> <profile> <id>postgre</id> <dependencies> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> </dependencies> </profile> 还要为每个 Profile 添加 Flyway 数据库配置文件。 首先,创建 application-h2.properties: flyway.url=jdbc:h2:file:./testdb;DB_CLOSE_ON_EXIT=FALSE;AUTO_RECONNECT=TRUE;MODE=MySQL;DATABASE_TO_UPPER=false; flyway.user=testuser flyway.password=password 然后,创建 PostgreSQL application-postgre.properties: flyway.url=jdbc:postgresql://127.0.0.1:5431/testdb flyway.user=testuser flyway.password=password 注:你可以调整 PostgreSQL 配置,使其与你的数据库相匹配,也可以使用 代码示例中的 docker-compose 文件。 2.2、迁移 添加第一个迁移(migration)文件 V1_0__add_table.sql: create table table_one ( id numeric primary key ); 添加第二个包含错误的迁移文件 V1_1__add_table.

如果 @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")。