我应该如何在rest api请求中正确实现动态搜索?我的rest api分为Controller->服务->存储库。我创建了从数据库获取所有驱动程序的GET请求:
@GetMapping
public ResponseEntity<Set<DriverDTO>> getAll(@PageableDefault(value = 15) Pageable pageable) {
Page<DriverEntity> driverEntities = driverService.getAll(pageable);
Set<DriverDTO> driverDTOSet = modelMapperService.mapPageToSetOfEnteredClass(driverEntities, DriverDTO.class);
return new ResponseEntity<>(driverDTOSet, HttpStatus.OK);
}
现在我想添加一些搜索参数,例如name、ageUpToX。。。所以我添加了@RequestParams:
@GetMapping
public ResponseEntity<Set<DriverDTO>> getAll(@PageableDefault(value = 15) Pageable pageable,
@RequestParam String name,
@RequestParam int ageUpTo,
@RequestParam int ageOver) {
Page<DriverEntity> driverEntities = driverService.getAll(pageable);
Set<DriverDTO> driverDTOSet = modelMapperService.mapPageToSetOfEnteredClass(driverEntities, DriverDTO.class);
return new ResponseEntity<>(driverDTOSet, HttpStatus.OK);
}
来自服务的方法getAll((看起来像:
public Page<DriverEntity> getAll(Pageable pageable) {
return driverEntityRepository.findAll(pageable);
}
那么接下来是什么呢?我是否应该将每个requestParam添加到getAll方法中,如:getAll(String name,int ageUpTo,int ageOver(,如果字段为空,则检查几个if循环/!=无效的或者通过某种开关?
如果您想验证查询参数,您不必使用If语句,这可以使用注释以更优雅的方式完成。
首先,您需要在pom.xml
文件中包含以下依赖项
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
spring-boot-starter-validation
依赖项将包括验证请求参数所需的所有jar。
因此,如果要验证查询参数ageUpTo
的最小值为5,最大值为7,则可以将@Validated
注释与@Min
和@Max
注释一起使用。@Validated
注释用于指定要验证的休息控制器。spring-boot应用程序在调用之前验证所有方法。以下是示例:
@Validated
public RestController {
@GetMapping
public ResponseEntity<Set<DriverDTO>> getAll(@PageableDefault(value = 15) Pageable pageable,
@RequestParam String name,
@RequestParam @Min(5) @Max(7) int ageUpTo,
@RequestParam int ageOver) {
Page<DriverEntity> driverEntities = driverService.getAll(pageable);
Set<DriverDTO> driverDTOSet = modelMapperService.mapPageToSetOfEnteredClass(driverEntities, DriverDTO.class);
return new ResponseEntity<>(driverDTOSet, HttpStatus.OK);
}
}
如果要验证请求参数name
是否为空,可以使用@NotBlank
注释。
此外,您还可以自定义验证失败时将显示给用户的消息。
你可以在这里或这里阅读更多关于
如果要根据给定的查询参数搜索数据库,则必须在存储库界面中声明一个新方法,该方法将根据给定的参数执行搜索。这意味着您还必须在将调用该方法的服务中声明一个新方法,类似于您之前所做的操作。
我认为你需要将这些参数添加到你的服务方法中,否则你可以向服务发送一个Map,而不是一个接一个地发送,其中键将是你需要筛选的列,然后你可以迭代映射,如果键/值不为空,你可以将其添加到查询规范中,例如:
Specification<MyDomain> querySpec = Specifications.where((root, query, cb) -> {
Predicate p = null;
//iterate over the map
mapParam.forEach(k,v -> {
if(k != null && v!= null) {
p = cb.and(p, cb.equal(root.get(k), k));
}
})
return p;
});
// then use the specification
Page<MyDomain> pageResult = myRepo.findAll(querySpec, pageRequest);
注意,您需要执行一些验证,因为CCD_ 10可能为空,另一件重要的事情是,您的存储库必须从JpaSpecificationExecutor
扩展
我认为您可以在spring存储库中使用规范,你需要扩展JpaSpecificationExecutor,比如这个
@Repository
public interface PostRepository extends PagingAndSortingRepository<Post, Integer>, JpaSpecificationExecutor<Post>{}
你必须制作一个规范文件,在那里你会有你的搜索规范,比如下面的
public class PostSpecification implements Specification<Post> {
//.....other codes
//.....other codes
public static Specification<Post> bySearch(String search) {
return (root, query, criteriaBuilder) -> {
if (search == null) {
return criteriaBuilder.conjunction();
}
query.distinct(true);
Predicate titlePredicate = criteriaBuilder.like(root.<String>get("title"), "%" + search + "%");
Predicate contentPredicate = criteriaBuilder.like(root.<String>get("content"), "%" + search + "%");
Predicate authorPredicate = criteriaBuilder.like(root.<String>get("author"), "%" + search + "%");
Join<Post, Tag> postTagsTable = root.join("tags", JoinType.INNER);
Predicate tagPredicate = criteriaBuilder.like(postTagsTable.get("name"), "%" + search + "%");
return criteriaBuilder.or(titlePredicate, contentPredicate,
authorPredicate, tagPredicate);
};
}
}
现在你必须从你的控制器调用findAll,如下
PostSpecification postSpecification = new PostSpecification();
Specification<Post> filteredSpecification =
postSpecification.findByFilters(search, authorNames, tagNames);
posts = postRepository.findAll(filteredSpecification, pageable).getContent();