Spring

RestTemplate 上传文件

在调用第三方Api服务的时候,如果涉及到文件上传,就需要自己通过 Http 客户端发起 Multipart 请求来上传文件。 在 Spring 应用中比较流行的 Http 客户端就是 RestTemplate。本文将会指导你如何用 RestTemplate 发起 Multipart 请求来上传文件。 服务端 在服务端创建一个用于测试的 FileUploadController, 它接受来自客户端的 Multipart 文件请求,并且响应文件的相关信息。 package cn.springdoc.demo.controller; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import jakarta.servlet.http.HttpServletResponse; @RestController @RequestMapping("/upload") public class FileUploadController { private static final Logger log = LoggerFactory.getLogger(FileUploadController.class); /** * 文件上传 * @param file * @param response * @return * @throws IOException */ @PostMapping(consumes = MediaType.

Spring 中的 “自注入”

1、概览 自注入是指 Spring Bean 将自身作为依赖注入。它使用 Spring 容器获取自身的引用,然后使用该引用执行某些操作。 在这个简短的教程中,我们将了解如何在 Spring 中使用自注入。 2、自注入的场景 自注入最常见的用例是在需要将切面应用于自引用的方法或类时,绕过 Spring AOP 的限制 假设我们有一个执行某些业务逻辑的 service 类,需要调用自身的一个方法作为该逻辑的一部分: @Service public class MyService { public void doSomething() { // ... doSomethingElse(); } @Transactional public void doSomethingElse() { // ... } } 不过,当我们运行应用程序时,可能会发现 @Transactional 并未生效。这是因为 doSomething() 方法直接调用了 doSomethingElse(),从而绕过了 Spring 代理。 为了解决这个问题,我们可以使用自注入获取 Spring 代理的引用,然后通过该代理调用方法。 3、使用 @Autowired 自注入 在 Spring 中,我们可以通过在 Bean 的字段、构造器参数或 setter 方法上使用 @Autowired 注解来进行自注入。 下面是一个在字段上使用 @Autowired 的示例: @Component public class MyBean { @Autowired private MyBean self; public void doSomething() { // 在这里使用 self 引用 } } 通过构造器参数自注入。

为什么在 Spring 中不推荐使用字段注入

1、概览 当我们在 IDE 中运行代码分析工具时,它可能会对带有 @Autowired 注解的字段发出 “Field injection is not recommended” 的警告。 在本教程中,我们将探讨为什么不推荐字段注入,以及我们可以使用哪些替代方法。 2、依赖注入(DI) 依赖注入是一种设计模式,用于管理对象之间的依赖关系。它通过外部容器提供对象的依赖,使得对象之间的关系更加灵活、可配置和可测试。依赖注入提高了代码的可维护性、可测试性和可扩展性。它是 Spring 框架的核心功能之一。 我们可以通过三种方式注入依赖对象,即: 构造函数注入。 Setter 方法注入。 字段注入。 第三种方法是使用 @Autowired 注解将依赖直接注入类中。虽然这可能是最简单的方法,但它可能会导致一些潜在的问题。 更重要的是,即使是在 Spring 的官方文档 中,也不再介绍字段注入。 3、Null 安全 让我们定义 EmailService 类并使用字段注入 EmailValidator 依赖: @Service public class EmailService { @Autowired private EmailValidator emailValidator; } 现在,让我们添加 process() 方法: public void process(String email) { if(!emailValidator.isValid(email)){ throw new IllegalArgumentException(INVALID_EMAIL); } // ... } 我们可以使用默认构造函数直接创建 EmailService 实例。但只有在提供了 EmailValidator 依赖的情况下,EmailService 才能正常工作。 EmailService emailService = new EmailService(); emailService.

如何解决 Spring Boot POST 请求中的 403 错误

1、概览 在 web 开发过程中,经常会遇到 HTTP 403 forbidden error。 在本教程中,我们将学习如何解决 Spring Boot POST 请求中的 403 错误。我们将首先了解 403 错误的含义,然后探讨在 Spring Boot 应用程序中解决该错误的步骤。 2、403 Error 是什么? HTTP 403 错误(通常称为 “Forbidden” 错误)是一种状态代码,表示服务器理解了请求,但选择不授权。这通常意味着客户端没有权限访问请求的资源。 需要注意的是,该错误不同于 401 错误,后者表示服务器需要对客户端进行身份认证,但尚未收到有效凭证。 “401” 表示需要认证,“403” 表示认证过了(不需要认证),但是没有权限。 3、导致 403 Error 的原因 在 Spring Boot 应用程序中,有几个因素会触发 403 错误。其中之一就是客户端未能提供身份认证凭据。在这种情况下,服务器因无法认证客户端的权限而拒绝请求,从而导致 403 错误。 另一个可能的原因在于服务器配置(server configuration)。例如,出于安全原因,服务器可能被配置为拒绝来自某些 IP 地址或用户代理(user agent)的请求。如果请求来自这些被阻止的资源,服务器会响应 403 错误。 此外,Spring Security 默认启用跨站请求伪造(CSRF)保护。CSRF 是一种通过欺骗受害者提交恶意请求并利用受害者的凭证代表其执行非预期功能的攻击。如果用于防范此类攻击的 CSRF token 丢失或不正确,服务器也可能会响应 403 错误。 4、项目设置 要了解如何解决 403 错误,让我们创建一个带有 spring-boot-starter-web 和 spring-boot-starter-security 依赖的 Spring Boot 项目:

Spring 中的事务管理器(TransactionManager)

事务管理 ,一个被说烂的也被看烂的话题,还是面试中常问到的问题之一。 本文会从设计角度,一步步的剖析 Spring 事务管理的设计思路(都会设计事务管理器了,还能玩不转?)。 一、为什么需要事务管理? 先看看如果没有事务管理器的话,如果想让多个操作(方法/类)处在一个事务里应该怎么做: // MethodA: public void methodA(){ Connection connection = acquireConnection(); try{ int updated = connection.prepareStatement().executeUpdate(); methodB(connection); connection.commit(); }catch (Exception e){ rollback(connection); }finally { releaseConnection(connection); } } // MethodB: public void methodB(Connection connection){ int updated = connection.prepareStatement().executeUpdate(); } 或者用 ThreadLocal 存储 Connection? static ThreadLocal<Connection> connHolder = new ThreadLocal<>(); // MethodA: public void methodA(){ Connection connection = acquireConnection(); connHolder.set(connection); try{ int updated = connection.prepareStatement().executeUpdate(); methodB(); connection.commit(); }catch (Exception e){ rollback(connection); }finally { releaseConnection(connection); connHolder.

Spring 和 CORS 跨域

如果你从事 web 应用开发,在前端使用异步请求(fetch/XMLHttpRequest)时,那你或多或少都应该在浏览器控制台见识过如下异常信息。 Access to fetch at 'http://localhost:8080/hello' from origin 'http://localhost:1313' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. 是的,这就是在异步请求时跨域失败的异常信息。接下来本文将会先简单地介绍跨域的基础知识,再详细地介绍如何在 spring 应用中处理跨域。 简单了解跨域 跨域,全称为“跨域资源共享”(Cross-origin resource sharing),是浏览器的一种安全机制。只会在浏览器中,使用 AJAX (fetch/XMLHttpRequest)时发生。当你在一个 web 页面中,使用 ajax 对目标 URL 发起了请求,只要目标 URL 的 协议,主机,端口 和当前 web 页面的 协议,主机,端口 任意不一致,就会产生跨域。 例如,我在页面 http://localhost:1313 中,对如下 URL 发起 AJAX 请求,都会导致跨域:

Spring Bean Scope 指南

在本教程中,将带你学习 Spring Framework 的重要组成部分 Spring Bean Scope(作用域)。你将了解它们是什么、如何工作以及何时使用。最后,你将对 Spring Bean Scope 有一个清晰的了解,从而帮助你构建更好的 Spring 应用程序。 Spring Bean 介绍 在 Spring Framework 的世界里,“Spring Bean” 是一个非常重要的术语。从本质上讲,Spring Bean 是由 Spring IoC(反转控制)容器实例化、组装和管理的对象。这些 Bean 是根据你提供给容器的配置元数据创建的,例如,以 XML 定义或源代码注解的形式。 Bean 可以看作是任何 Spring 应用程序的基本构件。它们是构成应用程序主干的对象,由 Spring IoC 容器管理。这些 Bean 是根据项目中提供的定义创建的,用于履行应用程序中的各种角色,如 service 类、数据访问对象 (DAO)、Spring MVC Controller 等对象,甚至是简单对象。 Spring Bean Scope 是什么 Spring Bean Scope(或换句话说,Bean 的作用域)决定了这些 Bean 在应用程序各种上下文中的生命周期和可见性。 Spring Bean 的 scope 定义了 Bean 存在的边界、与之绑定的上下文以及存活时间。简而言之,它定义了何时创建 Bean 的新实例,以及何时删除该特定实例。 Spring 提供多种 scope,例如: Singleton Prototype Request Session Application Websocket 每个 scope 都意味着不同的生命周期和它们定义的 Bean 的可见性。正确理解和使用这些 scope 对于构建稳健高效的 Spring 应用程序至关重要。

Spring 6.1的新特性:RestClient

Spring Framework 6.1 M2 引入了 RestClient,一个新的同步HTTP客户端。顾名思义,RestClient 提供了 WebClient 的 fluent API和 RestTemplate 的基础架构。 14年前,当 RestTemplate 在 Spring Framework 3.0 中被引入时,我们很快发现在一个类似模板的类中暴露 HTTP 的所有功能会导致过多的重载方法。因此,在 Spring Framework 5 中,我们为响应式的 WebClient 使用了 fluent API。通过 RestClient,我们引入了一个 HTTP 客户端,它提供了类似于 WebClient 的API,并使用了 message converter、request factory、拦截器以及 RestTemplate 的其他底层组件。 创建 RestClient 你可以使用静态的create方法创建一个RestClient。你也可以使用RestClient::builder来获得一个具有更多选项的 builder,比如指定要使用的HTTP客户端,设置默认的URL、path 变量和 header,或者注册拦截器和初始化器(initializer)。 使用 RestClient::create(RestTemplate),你可以使用现有 RestTemplate 的配置初始化 RestClient。 Retrieve 让我们创建一个 RestClient,用它来设置一个基本的 GET 请求,并使用 retrieve 以字符串形式获取网站的内容: RestClient restClient = RestClient.create(); String result = restClient.get() .uri("https://example.com") .retrieve() .body(String.class); System.out.println(result); 如果你对响应状态码和 header 感兴趣,而不仅仅是对响应内容感兴趣,你可以使用 toEntity 获取 ResponseEntity:

Spring 快速入门指南

本入门指南将会引导你如何从零开始建立一个 Spring 应用,并提供经典的“Hello World!”端点,可供任何浏览器都访问。 环境预备 你需要在本地安装好 Java™ 开发工具包(JDK),以及一个 IDE,如 IntelliJ IDEA、Spring Tools、Visual Studio Code 或 Eclipse。 第 1 步:创建新的 Spring Boot 项目 通过 start.springboot.io 来创建一个“web”项目。在“Dependencies”对话框中搜索并添加 “web”依赖项,如截图所示。点击“Generate”按钮,下载压缩包,并将其解压到电脑上的一个文件夹。 start.springboot.io 创建的项目包含 Spring Boot,这个框架使你不需要太多的代码或配置就可以让 Spring 在你的应用中工作。Spring Boot 是启动 Spring 项目的最快速和最流行的方式。 第 2 步:添加代码 在你的 IDE 中打开项目,找到 src/main/java/com/example/demo 文件夹中的 DemoApplication.java 文件。现在改变该文件的内容,添加下面代码中所示的额外方法和注解。你可以复制并粘贴该代码,或者手动输入该代码。 package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController public class DemoApplication { public static void main(String[] args) { SpringApplication.