编辑
2024-11-14
学习记录
00

介绍

Optional 是 Java 8 引入的一个容器类,代表一个值存在或不存在。原来用 null 表示一个值不存在,现在 Optional 可以更好地表达这个概念。并且可以避免空指针异常(NullPointerException)。

主要用途

作为方法的返回类型:当你想要明确表示一个方法可能会返回值也可能不返回值时,可以使用 Optional 作为返回类型。

避免空指针异常:通过使用 Optional,你可以显式地检查值是否存在,从而避免直接访问可能导致的 NullPointerException。

提供默认操作:如果值不存在,可以通过 Optional 提供的方法来指定默认行为。

常用方法

  • of(T value):创建一个 Optional 实例,如果传递的参数是 null,则抛出 NullPointerException。
  • ofNullable(T value):创建一个 Optional 实例,如果传递的参数是 null,则返回一个空的 Optional。
  • isPresent():判断 Optional 是否包含非 null 值。
  • get():如果 Optional 包含值,则返回该值,否则抛出 NoSuchElementException。
  • orElse(T other):如果 Optional 包含值,则返回该值,否则返回 other。
  • orElseGet(Supplier<? extends T> supplier):如果 Optional 包含值,则返回该值,否则返回由 Supplier 生成的值。
  • orElseThrow(Supplier<? extends X> exceptionSupplier):如果 Optional 包含值,则返回该值,否则抛出由 exceptionSupplier 生成的异常。
  • ifPresent(Consumer<? super T> consumer):如果 Optional 包含值,则执行 consumer 指定的操作。
  • filter(Predicate<? super T> predicate):如果 Optional 包含值并且该值满足给定的谓词,则返回包含该值的 Optional,否则返回空的 Optional。
  • map(Function<? super T, ? extends U> mapper):如果 Optional 包含值,则对值应用 mapper 函数,并返回包含结果的 Optional;如果 Optional 不包含值,则返回空的 Optional。
编辑
2024-11-14
实用工具
00

随着项目规模的扩大,单一数据源已无法满足复杂业务需求,多数据源(动态数据源)应运而生。本文将介绍两种 MyBatis-Plus 的多数据源扩展插件:开源生态的 dynamic-datasource 和 企业级生态的 mybatis-mate。

dynamic-datasource

dynamic-datasource 是一个开源的 Spring Boot 多数据源启动器,提供了丰富的功能,包括数据源分组、敏感信息加密、独立初始化表结构等。

特性

数据源分组:适用于多种场景,如读写分离、一主多从等。 敏感信息加密:使用 ENC() 加密数据库配置信息。 独立初始化:支持每个数据库独立初始化表结构和数据库。 自定义注解:支持自定义注解,需继承 DS。 简化集成:提供对 Druid、HikariCP 等连接池的快速集成。 组件集成:支持 Mybatis-Plus、Quartz 等组件的集成方案。 动态数据源:支持项目启动后动态增加或移除数据源。 分布式事务:提供基于 Seata 的分布式事务方案。

约定

本框架专注于数据源切换,不限制具体操作。 配置文件中以下划线 _ 分割的数据源首部为组名。 切换数据源可以是组名或具体数据源名。 默认数据源名为 master,可通过 spring.datasource.dynamic.primary 修改。 方法上的注解优先于类上的注解。

编辑
2024-11-14
实用工具
00

MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。

在 MyBatis-Plus 中,Wrapper 类是构建查询和更新条件的核心工具。以下是主要的 Wrapper 类及其功能:

  • AbstractWrapper:这是一个抽象基类,提供了所有 Wrapper 类共有的方法和属性。它定义了条件构造的基本逻辑,包括字段(column)、值(value)、操作符(condition)等。所有的 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper 都继承自 AbstractWrapper。

  • QueryWrapper:专门用于构造查询条件,支持基本的等于、不等于、大于、小于等各种常见操作。它允许你以链式调用的方式添加多个查询条件,并且可以组合使用 and 和 or 逻辑。

  • UpdateWrapper:用于构造更新条件,可以在更新数据时指定条件。与 QueryWrapper 类似,它也支持链式调用和逻辑组合。使用 UpdateWrapper 可以在不创建实体对象的情况下,直接设置更新字段和条件。

  • LambdaQueryWrapper:这是一个基于 Lambda 表达式的查询条件构造器,它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名。这种方式提高了代码的可读性和可维护性,尤其是在字段名可能发生变化的情况下。

  • LambdaUpdateWrapper:类似于 LambdaQueryWrapper,LambdaUpdateWrapper 是基于 Lambda 表达式的更新条件构造器。它允许你使用 Lambda 表达式来指定更新字段和条件,同样避免了硬编码字段名的问题。

编辑
2024-11-14
学习记录
00

前提

如果被调用服务方法有HttpServletResponse,会导致调用失败,因为Feign不能处理HttpServletResponse

使用返回值ResponseEntity<org.springframework.core.io.Resource>进行处理

方法

调用方

java
@GetMapping("/download") public void download(@RequestParam(value = "fileUrl") String fileUrl, HttpServletResponse response){ try { ResponseEntity<org.springframework.core.io.Resource> responseEntity = remoteFileService.downloadByRes(fileUrl);; if (responseEntity.getStatusCode().is2xxSuccessful()) { org.springframework.core.io.Resource resource = responseEntity.getBody(); if (resource != null) { response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment;filename=" + resource.getFilename()); try (OutputStream outputStream = response.getOutputStream()) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = resource.getInputStream().read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } outputStream.flush(); } } } else { response.setStatus(responseEntity.getStatusCodeValue()); } } catch (IOException e) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } }
编辑
2024-11-14
实用工具
00

说明

Seata 是阿里巴巴开源的分布式事务中间件,以高效并且对业务 0 侵入的方式,解决微服务场景下面临的分布式事务问题。 Seata 将为用户提供了 AT、TCC、SAGA 和XA 事务模式,为用户打造一站式的分布式解决方案。AT模式是阿里首推的模式,阿里云上有商用版本的GTS(Global Transaction Service 全局事务服务)。

github地址

AT模式

在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作。

Server 端存储模式(store.mode)支持三种方式:

file:单机模式(默认为此模式),全局事务会话信息存储在内存中,读写并持久化至本地文件 root.data (bin\sessionStore\root.data) 中,性能较高。 db:高可用模式(Mysql 5.7+),全局事务会话信息通过db共享,相应性能差些。 redis:Seata-Server 1.3及以上版本支持,性能较高,但存在事务信息丢失风险,请提前配置适合当前场景的redis持久化配置。

创建 undo_log 表

Seata AT 模式 需要使用到 undo_log 表。

sql
-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log CREATE TABLE `undo_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `branch_id` bigint(20) NOT NULL, `xid` varchar(100) NOT NULL, `context` varchar(128) NOT NULL, `rollback_info` longblob NOT NULL, `log_status` int(11) NOT NULL, `log_created` datetime NOT NULL, `log_modified` datetime NOT NULL, `ext` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;