教程

Spring Cache 入门教程

1、缓存抽象 本文将带你了解如何使用 Spring Cache 来提高系统性能。 2、开始使用 Spring 提供的核心缓存抽象位于 spring-context 模块中。 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.3</version> </dependency> 另外,还有一个名为 spring-context-support 的模块,它位于 spring-context 模块之上,并提供了更多由 EhCache 或 Caffeine 支持的 CacheManager。如果想使用这些模块作为缓存存储,则需要使用 spring-context-support 模块: <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>5.3.3</version> </dependency> 由于 spring-context-support 模块临时依赖于 spring-context 模块,因此 spring-context 不需要单独的依赖声明。 2.1、Spring Boot 如果是 Spring Boot 项目,可以利用 spring-boot-starter-cache Starter 来轻松添加缓存依赖项: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> <version>2.4.0</version> </dependency> 该 Starter 包含了 spring-context-support 模块。 3、启用缓存 只需在任何配置类中添加 @EnableCaching 注解,即可启用缓存功能: @Configuration @EnableCaching public class CachingConfig { @Bean public CacheManager cacheManager() { return new ConcurrentMapCacheManager("addresses"); } } 当然,也可以通过 XML 配置来启用缓存:

Spring 中的 @Autowired 注解

1、概览 从 Spring 2.5 开始,框架引入了注解驱动的依赖注入功能。该功能的主要注解是 @Autowired 。它允许 Spring 解析并注入所依赖的 Bean 到 Bean 中。 本文将带你了解如何启用自动装配以及自动装配 Bean 的各种方法,以及如何使用 @Qualifier 注解来解决 Bean 冲突以及潜在的异常情况。 2、启用 @Autowired 注解 Spring 框架支持自动依赖注入。换句话说,通过在 Spring 配置文件中声明所有 Bean 的依赖关系,Spring 容器可以自动装配依赖 Bean 之间的关系。这就是所谓的 Spring Bean 自动装配。 首先启用注解驱动注入来加载 Spring 配置(基于 Java 的配置): @Configuration @ComponentScan("com.baeldung.autowire.sample") public class AppConfig {} <context:annotation-config> 主要用于激活 Spring XML 文件中的依赖注入注解。 Spring Boot 还引入了 @SpringBootApplication 注解。这个注解相当于使用 @Configuration、@EnableAutoConfiguration 和 @ComponentScan。 在应用的 main 类中使用这个注解: @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.

Spring Cloud Config 快速入门

1、概览 Spring Cloud Config 是 Spring 用于在分布式环境下提供集中式配置的解决方案。 本文将带你了解如何设置一个基于 Git 的配置服务器(包括加密的属性值),以及如何在 REST 应用中使用它。 2、依赖 首先是配置服务器应用,包含了 spring-cloud-config-server、spring-boot-starter-security 和 spring-boot-starter-web Starter: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 然后是客户端应用,只需要 spring-cloud-starter-config 和 spring-boot-starter-web 模块: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 3、实现配置服务器 通过在 @SpringBootApplication 类上注解 @EnableConfigServer 来启用配置服务器。该注解会自动配置所有必要的组件: @SpringBootApplication @EnableConfigServer public class ConfigServer { public static void main(String[] arguments) { SpringApplication.run(ConfigServer.class, arguments); } } 还需要配置服务器的监听端口和 Git URL(提供版本控制的配置内容)。后者可以使用诸如 http、ssh 或本地文件系统上的简单文件等协议。

在 Security Filter Chain 中自定义 Filter

1、概览 本文将带你了解如何在 Spring Security Filter Chain(过滤器链)中定义一个自定义过 Filter(过滤器)。 2、创建 Filter Spring Security 默认提供了许多 Filter,这些 Filter 在大多数情况下已经足够。 当然,有时也需要在链中创建一个新的 Filter 来实现新功能。 首先,可以实现 org.springframework.web.filter.GenericFilterBean。 GenericFilterBean 是一个简单的 javax.servlet.Filter 实现,它还实现了一系列的 Aware 接口,可以感知到 Spring 容器中的一些组件。 只需实现一个方法: public class CustomFilter extends GenericFilterBean { @Override public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); } } 3、在 Security Config 中配置 Filter 可以通过 XML 或 Java 配置把 Filter 配置到 Spring Security Filter Chain 中。

Spring 中的 @Value 注解

1、概览 本文将带你了解 Spring 中的 @Value 注解。它用于向 Spring 管理的 Bean 中的字段注入值,可在字段或构造函数/方法上注解。 2、应用设置 创建一个简单的 Spring 应用来介绍该注解的不同用法。 首先,在 Properties 文件中定义想用 @Value 注解注入的值。 Properties 文件如下: value.from.file=Value got from the file priority=high listOfValues=A,B,C 然后,在配置类中定义一个 @PropertySource,指定 Properties 文件的名称以导入该 Properties 文件。 3、示例 通过注解注入 String(这种行为完全是多此一举,这里只是为了演示): @Value("string value") private String stringValue; 使用 @PropertySource 注解导入了 Properties 文件后,就可以使用 @Value 注解处理 Properties 文件中的值。 如下,注入 value.from.file 属性值: @Value("${value.from.file}") private String valueFromFile; 也可以使用相同的语法从系统属性中设置值。 假设定义了一个名为 systemValue 的系统属性,如下: @Value("${systemValue}") private String systemValue; 可以给未定义的属性提供默认值,如下: @Value("${unknown.param:some default}") private String someDefault; 如果同一个属性在系统属性和 Properties 文件中都被定义了,那么系统属性将会生效。

Spring Boot 中的 @ConfigurationProperties 注解

1、简介 Spring Boot 有许多有用的功能,包括外部化配置和轻松访问 Properties 文件中定义的属性。上一篇文章 介绍了实现这一点的各种方法。 本文将带你了解 Spring Boot 中的 @ConfigurationProperties 注解。 2、项目设置 按照惯例,在 pom.xml 中将 spring-boot-starter-parent 添加为 <parent>: <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.0</version> <relativePath/> </parent> 为了验证文件中定义的属性,还需要一个 JSR-380 实现,hibernate-validator 就是其中之一,它由 spring-boot-starter-validation 依赖提供。 把它也添加到 pom.xml 中: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> 更多详细信息可参阅 Hibernate Validator 入门。 3、示例属性 官方文档建议将配置属性隔离到单独的 POJO 中。 如下: @Configuration @ConfigurationProperties(prefix = "mail") public class ConfigProperties { private String hostName; private int port; private String from; //Get、Set 方法 } 通过 @Configuration 注解,Spring 会在 Application Context 中创建一个 Spring Bean。

Spring 和 Spring Boot 中的属性配置

1、概览 本文将带你了解如何通过 Java 配置和 @PropertySource 在 Spring 中设置和使用 Properties,以及 Properties 在 Spring Boot 中的工作原理。 2、通过注解注册 Properties 文件 Spring 3.1 引入了新的 @PropertySource 注解,作为一种方便的机制,用于将属性源添加到环境中。 可以将此注解与 @Configuration 注解结合使用: @Configuration @PropertySource("classpath:foo.properties") public class PropertiesWithJavaConfig { //... } 另一种非常有用的注册新 Properties 文件的方法是使用占位符,它允许在运行时动态选择不同的文件: @PropertySource({ "classpath:persistence-${envTarget:mysql}.properties" }) ... 2.1、定义多个属性位置 @PropertySource 注解是可重复的(Java 8 的可重复注解特性)。因此,如果使用的是 Java 8 或更高版本,就可以使用此注解来定义多个属性位置: @PropertySource("classpath:foo.properties") @PropertySource("classpath:bar.properties") public class PropertiesWithJavaConfig { //... } 当然,也可以使用 @PropertySources 注解并指定一个 @PropertySource 数组。这不仅适用于 Java 8 或更高版本,也适用于任何受支持的 Java 版本: @PropertySources({ @PropertySource("classpath:foo.properties"), @PropertySource("classpath:bar.properties") }) public class PropertiesWithJavaConfig { //.

Spring Boot 中的测试

1、概览 本文将带你了解如何使用 Spring Boot 中的框架支持来编写测试,包括可以独立运行的单元测试,以及在执行测试之前加载 Spring Application Context 的集成测试。 2、项目设置 本文中的示例项目是一个 “雇员管理 API”,提供了对 Employee 资源的一些操作。是一个典型的MVC三层架构,从 Controller 到 Service 最后到持久层。 3、Maven 依赖 首先,添加测试依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <version>2.5.0</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>test</scope> </dependency> spring-boot-starter-test 是主要的依赖,它包含了测试所需的大部分依赖。 H2 DB 是内存数据库,非常方便用于测试。 3.1、JUnit 4 从 Spring Boot 2.4 开始,JUnit 5 的 Vintage 引擎已从 spring-boot-starter-test 中移除。如果仍想使用 JUnit 4 编写测试,则需要添加以下 Maven 依赖: <dependency> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> </exclusion> </exclusions> </dependency> 4、使用 @SpringBootTest 进行集成测试 顾名思义,集成测试的重点是集成应用的不同层。这也意味着不涉及模拟(Mock)。

手动写入响应后对 @ResponseBody 注解的影响

问题回溯 2023 年 Q2 某日运营反馈一个问题,商品系统商家中心某批量工具模板无法下载,导致功能无法使用(因为模板是动态变化的) 商家中心报错如下(JSON串): {"code":-1,"msg":"失败"} 负责的同事看到失败后立即与我展开讨论(因为不是关键业务,所以不需要回滚,修复即可),我们发现新功能模板下载的代码与之前的代码有所不同,恰好之前的功能又可以正常运行,所以同事对现有代码进行改造然后预发布测试完成后再次上线。 其他业务代码: /** * 模板下载 */ @RequestMapping("/doBatchWareSetAd") public void doBatchWareSetAd(@RequestParam MultipartFile file, HttpServletResponse response) { wareBatchBusiness.doBatchWareSetAd(file, response, getLongOrgCode(), getCurrentUserPin(), getCurrentUserId()); } 上线的结果是:仍然无法使用。 其实也正常:因为两种代码在预发布都可以正常运行,在线上出错只可能是因为其他原因,只不过我们不了解底层原理,害怕它 “可能” 有问题罢了,最终查询得到的结论是权限系统管理员在线上环境没有给我们配置相应的文件,导致请求为空,导致请求失败。 探索 @ResponseBody 与主动写入响应流的关系 我们都知道 @ResponseBody 注解可以帮助我们把返回对象转化为 JSON,方便展示和交互。 那它到底是如何工作的呢,请看下面的讲解: 代码案例 1 @RequestMapping("/test1") @ResponseBody public Map<String, String> test1(HttpServletResponse response) { Map<String, String> map = new HashMap<>(); map.put("1", "1"); return map; } // 响应 JSON报文 Debug 代码,发现其核心处理类为:RequestResponseBodyMethodProcessor。 方法:org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor#handleReturnValue 会处理其相关返回值。 真正的核心处理方法:org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor#writeWithMessageConverters。 关键 DEBUG 记录如下图所示:

Spring Security 方法安全(Method Security)简介

1、概览 简而言之,Spring Security 支持方法级别的授权语义。可以通过限制哪些角色可以执行特定方法等方式来确保 Service 层的安全。 2、启用 Method Security 要使用 Spring Method Security,需要添加 spring-security-config 依赖: <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> </dependency> 可以在 Maven Central 上找到它的最新版本。 如果使用的是 Spring Boot,可以添加 spring-boot-starter-security 依赖,其中包括 spring-security-config: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> 同样,它的最新版本也可以在 Maven Central 中找到。 接下来,需要启用全局 Method Security: @Configuration @EnableGlobalMethodSecurity( prePostEnabled = true, securedEnabled = true, jsr250Enabled = true) public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { } prePostEnabled 属性可启用 Spring Security Pre/Post 注解。 securedEnabled 属性决定是否启用 @Secured 注解。 jsr250Enabled 属性允许使用 @RoleAllowed 注解。 3、应用 Method Security 3.