在上一篇 【Spring实战】20 Spring Data REST+JPA构建RESTful API 文章中,我们已经知道了如何去使用 Spring Data REST 集成 JPA 去帮我们构建基础的 RESTful API(常用的增删改查)。它的作用远不止于此,本文将继续研究一下 Spring Data REST 还有哪一些常用的功能,并提供详细的代码示例。
Spring Data REST 会自动将 Spring Data 存储库中的实体类型暴露为 RESTful 资源。我们无需显式编写控制器或服务层代码,就可以让实体成为可通过 HTTP 请求访问的资源。
package com.cheney.demo.modle;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "t_user")
public class User {
@Id
private Integer id;
private String name;
private Integer age;
}
这个就和我们上一篇写的基础功能一致了,让我们访问一下,这个自定义查询的 URL 吧
localhost:8080/users
通过方法命名规则,我们可以轻松地创建查询方法。以下是一个通过产品名称查询的例子:
package com.cheney.demo.repository;
import com.cheney.demo.modle.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Integer> {
// 自定义一个通过名字查询用户信息的方法
User findByName(String name);
}
让我们访问一下,这个自定义查询的 URL 吧
localhost:8080/users/search/findByName?name=cheney
Spring Data REST 支持对资源进行分页和排序,以便处理大量数据。在查询参数中指定 page
、size
和 sort
,即可实现分页和排序。
package com.cheney.demo.repository;
import com.cheney.demo.modle.User;
import lombok.NonNull;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Integer> {
// 自定义一个通过名字查询用户信息的方法
User findByName(String name);
// 分页和排序
Page<User> findAll(@NonNull Pageable pageable);
}
这个 findAll
方法的目的是获取所有用户的数据,并支持分页和排序。参数 @NonNull Pageable pageable
表示通过传递 Pageable
对象来进行分页和排序。
让我们访问一下这个 URL 吧,来获取第一页的3条数据,并且指定了 id 升序
localhost:8080 /users?page=0&size=3&sort=id,asc
让我们访问一下这个 URL 吧,来获取第二页的3条数据,并且指定了 id 升序
localhost:8080 /users?page=1&size=3&sort=id,asc
Spring Data REST 会自动检测实体之间的关联关系,并创建关联资源。例如,一个用户和多个角色之间的关联:
@Entity
public class User {
@Id
private Long id;
@OneToMany
private List<Role> roles;
}
通过监听事件,我们可以在资源的创建、更新、删除等操作时执行自定义逻辑。以下是一个简单的例子:
package com.cheney.demo.handler;
import com.cheney.demo.modle.User;
import org.springframework.data.rest.core.annotation.HandleBeforeCreate;
import org.springframework.data.rest.core.annotation.RepositoryEventHandler;
import org.springframework.stereotype.Component;
@Component
@RepositoryEventHandler(User.class)
public class UserEventHandler {
@HandleBeforeCreate
public void handleBeforeCreate(User user) {
System.out.println("handleBeforeCreate user");
}
}
通过 @RepositoryEventHandler(User.class)
注解,指定了这个事件处理器将处理与 User
类相关的事件。在事件处理器中,通过 @HandleBeforeCreate
注解标注的 handleBeforeCreate
方法表示,在创建(插入)用户之前执行的逻辑。在这个例子中,当有新的用户即将被创建时,会输出一条日志信息。
让我们访问一下这个 URL 吧,来获取第一页的3条数据,并且指定了 id 升序
localhost:8080 /users
查看一下日志,发现调用了我们定义的 handle 方法
集成 Spring Security 可以实现对资源的安全控制。配置安全规则,限制对某些资源的访问权限。
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
@EnableGlobalMethodSecurity(prePostEnabled = true)
:
这个注解用于启用全局方法安全性,其中 prePostEnabled = true
表示启用 Spring Security 的 @PreAuthorize
和 @PostAuthorize
注解,允许在方法级别进行访问控制。
GlobalMethodSecurityConfiguration
:
它是用于配置全局方法安全性。通过继承这个类,可以进行一些自定义的配置。
createExpressionHandler()
方法:
在 GlobalMethodSecurityConfiguration
类中,通过重写 createExpressionHandler()
方法,可以配置 Spring Security 表达式处理器(Expression Handler)。这个方法返回一个 MethodSecurityExpressionHandler
对象,用于解析和处理方法级别的安全性表达式。
OAuth2MethodSecurityExpressionHandler
:
在这个具体的配置中,createExpressionHandler()
方法返回了一个 OAuth2MethodSecurityExpressionHandler
对象。这表示使用 OAuth 2.0 的方法安全性表达式处理器,该处理器与 OAuth 2.0 令牌一起工作,用于处理涉及 OAuth 2.0 认证和授权的方法级别安全性。
通过本文的介绍,我们深入了解了 Spring Data REST 的一些常用功能。这些功能大大简化了构建 RESTful API 的过程,提高了开发效率。希望这些示例能够帮助你更好地使用 Spring Data REST 构建强大的 RESTful 服务。