教程

Spring Boot 注解

1、概览 Spring Boot 的自动配置功能让配置 Spring 变得更容易。 本文将带你了解 org.springframework.boot.autoconfigure 和 org.springframework.boot.autoconfigure.condition 包中的核心注解。 2、@SpringBootApplication 使用此注解来标记 Spring Boot 应用的 main 类: @SpringBootApplication class VehicleFactoryApplication { public static void main(String[] args) { SpringApplication.run(VehicleFactoryApplication.class, args); } } @SpringBootApplication 封装了 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 注解,均为默认属性。 3、@EnableAutoConfiguration @EnableAutoConfiguration 顾名思义就是启用自动配置。这意味着 Spring Boot 会在其 classpath 上查找自动配置 Bean,并自动应用它们。 注意,必须将此注解与 @Configuration 一起使用: @Configuration @EnableAutoConfiguration class VehicleFactoryConfig {} 4、自动配置的条件注解 通常,在编写自定义自动配置时,我们希望 Spring 有条件地使用它们。这可以通过本节中的注解来实现这一目标。 可以将本节中的注解放在 @Configuration 类或 @Bean 方法上。 4.1、@ConditionalOnClass 和 @ConditionalOnMissingClass 只有注解参数中的类存在/不存在时,Spring 才会使用标记的自动配置 Bean:

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 时,会抛出异常,反之则不会。

REST 查询语言 - 实现 OR 操作

1、概览 本文将扩展 上一篇文章 中实现的高级搜索操作,在 REST API 查询语言中加入基于 OR 的搜索条件。 2、实现方法 以前,search 查询参数中的所有条件都是由 AND 运算符组成的条件。 现在,使用标志来指示必须使用 OR 运算符组合条件。 http://localhost:8080/users?search=firstName:john,'lastName:doe 注意,这里用单引号标记了条件 lastName,以示区别。我们会在条件值对象 SpecSearchCriteria 中捕获 OR 运算符的 Predicate: public SpecSearchCriteria( String orPredicate, String key, SearchOperation operation, Object value) { super(); this.orPredicate = orPredicate != null && orPredicate.equals(SearchOperation.OR_PREDICATE_FLAG); this.key = key; this.operation = operation; this.value = value; } 3、改进 UserSpecificationBuilder 修改 UserSpecificationBuilder,以在构建 Specification<User> 时考虑 OR 条件: public Specification<User> build() { if (params.size() == 0) { return null; } Specification<User> result = new UserSpecification(params.

REST 查询语言 - 高级搜索操作

1、概览 前面几篇文章介绍了三种 REST 查询语言的实现方式,分别是:JPA Criteria、Spring Data JPA Specification 和 QueryDSL。 本文将扩展前面几篇文章中开发的 REST 查询语言,使其包含更多搜索操作,如:等于、不等于、大于、小于、前缀、后缀、包含和类似(Like)。 本文选择使用 Specification,因为它是一种清晰而灵活的表示操作的方式。 2、SearchOperation 枚举 首先,通过枚举来更好地定义各种支持的搜索操作: public enum SearchOperation { EQUALITY, NEGATION, GREATER_THAN, LESS_THAN, LIKE, STARTS_WITH, ENDS_WITH, CONTAINS; public static final String[] SIMPLE_OPERATION_SET = { ":", "!", ">", "<", "~" }; public static SearchOperation getSimpleOperation(char input) { switch (input) { case ':': return EQUALITY; case '!': return NEGATION; case '>': return GREATER_THAN; case '<': return LESS_THAN; case '~': return LIKE; default: return null; } } } 有两组操作:

使用 Spring Data JPA 和 Querydsl 构建 REST 查询语言

1、概览 在前两篇文章中,我们使用 JPA Criteria 和 Spring Data JPA Specification 构建了相同的搜索/过滤功能。 本文将带你了解如何使用 Spring Data JPA 和 Querydsl 构建 REST API 查询语言。 2、Querydsl 配置 首先,在 pom.xml 中添加以下依赖: <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <version>4.2.2</version> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> <version>4.2.2</version> </dependency> 还需要配置 APT(注解处理工具)插件: <plugin> <groupId>com.mysema.maven</groupId> <artifactId>apt-maven-plugin</artifactId> <version>1.1.3</version> <executions> <execution> <goals> <goal>process</goal> </goals> <configuration> <outputDirectory>target/generated-sources/java</outputDirectory> <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor> </configuration> </execution> </executions> </plugin> 该插件会根据实体类生成 Q 开头的查询类。 关于如何在 Spring Boot 中使用 QueryDSL,你可以参阅 这篇文章。 3、MyUser 实体 定义 MyUser 实体,用于在 API 中进行搜索: @Entity public class MyUser { @Id @GeneratedValue(strategy = GenerationType.

使用 Spring Data Specification 构建 REST 查询语言

1、概览 上一篇文章 介绍了一个基于 JPA Criteria 的查询语言解决方案。 本文将带你了解如何使用 Spring Data JPA 和 Specification 构建一个搜索/过滤 REST API。 2、 User 实体 创建一个 User 实体类,用于检索 API: @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String firstName; private String lastName; private String email; private int age; // get、set 方法 } 3、使用 Specification 进行过滤 来看看如何使用自定义 Spring Data JPA Specification 进行查询。 创建一个实现 Specification 接口的 UserSpecification,并传入自己的约束条件来构建实际查询: public class UserSpecification implements Specification<User> { private SearchCriteria criteria; @Override public Predicate toPredicate (Root<User> root, CriteriaQuery<?

使用 Spring 和 JPA Criteria 构建 REST 查询语言

1、概览 在接下来的一系列文章中,我将带你了解一种用于 REST API 的简单查询语言。 为什么要使用查询语言(Query Language)?因为对于任何足够复杂的 API 来说,仅仅通过简单的字段来搜索/过滤资源是远远不够的。查询语言更加灵活,可以准确过滤选出所需的资源。 2、User 实体 首先,创建一个 User 实体,用于在过滤/搜索 API 中使用: @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String firstName; private String lastName; private String email; private int age; } 3、使用 CriteriaBuilder 过滤 构建查询抽象是一个平衡问题。一方面,需要足够的灵活性,另一方面,需要保持可控的复杂性。高级查询的功能很简单 - 输入一些约束条件,然后得到一些结果。 来看看如何使用: @Repository public class UserDAO implements IUserDAO { @PersistenceContext private EntityManager entityManager; @Override public List<User> searchUser(List<SearchCriteria> params) { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<User> query = builder.

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 Security OAuth2 实现 SSO 单点登录

1、概览 本文将带你了解如何使用 Spring Security OAuth 和 Spring Boot 以及 Keycloak 作为授权服务器来实现单点登录(SSO)。 我们会使用 4 个不同的应用: 授权服务器 - 中央认证机制 资源服务器 - Foo 资源的提供者 两个客户端应用 - 使用 SSO 的应用 简单地说,当用户试图通过一个客户端应用访问资源时,他们会被重定到授权服务器进行身份认证。Keycloak 会对用户进行登录,在登录第一个应用后,如果使用同一浏览器访问第二个客户端应用,用户无需再次输入凭据。 使用 OAuth2 的授权码(Authorization Code)模式。 Spring Security 将此功能称为 OAuth 2.0 登录,而 Spring Security OAuth 将其称为 SSO。 2、授权服务器 以前,通过 Spring Security OAuth 可以将授权服务器设置为 Spring 应用。 不过,Spring Security OAuth 已被 Spring 弃用,现在可以使用 Keycloak 作为授权服务器。 因此,这次我们在 Spring Boot 应用中把授权服务器设置为嵌入式 Keycloak 服务器。 在 预配置 中,我们将定义两个客户端,即 ssoClient-1 和 ssoClient-2,分别对应每个客户端应用。