From 3d8579cb139e54f4024e468aca5c6665365620af Mon Sep 17 00:00:00 2001 From: johnniang Date: Wed, 10 Apr 2019 16:52:40 +0800 Subject: [PATCH] Complete post query api --- .../run/halo/app/model/params/PostQuery.java | 30 ++++++++++ .../run/halo/app/service/PostService.java | 43 ++++++++++---- .../app/service/impl/PostServiceImpl.java | 57 +++++++++++++++++++ .../controller/admin/api/PostController.java | 9 +++ 4 files changed, 127 insertions(+), 12 deletions(-) create mode 100644 src/main/java/run/halo/app/model/params/PostQuery.java diff --git a/src/main/java/run/halo/app/model/params/PostQuery.java b/src/main/java/run/halo/app/model/params/PostQuery.java new file mode 100644 index 000000000..488061c8b --- /dev/null +++ b/src/main/java/run/halo/app/model/params/PostQuery.java @@ -0,0 +1,30 @@ +package run.halo.app.model.params; + +import lombok.Data; +import run.halo.app.model.enums.PostStatus; + +/** + * Post query. + * + * @author johnniang + * @date 4/10/19 + */ +@Data +public class PostQuery { + + /** + * Keyword. + */ + private String keyword; + + /** + * Post status. + */ + private PostStatus status; + + /** + * Category id. + */ + private Integer categoryId; + +} diff --git a/src/main/java/run/halo/app/service/PostService.java b/src/main/java/run/halo/app/service/PostService.java index 33dbc3a07..245c38b14 100755 --- a/src/main/java/run/halo/app/service/PostService.java +++ b/src/main/java/run/halo/app/service/PostService.java @@ -1,18 +1,18 @@ package run.halo.app.service; -import run.halo.app.model.dto.post.PostMinimalOutputDTO; -import run.halo.app.model.dto.post.PostSimpleOutputDTO; -import run.halo.app.model.entity.Post; -import run.halo.app.model.enums.PostStatus; -import run.halo.app.model.vo.ArchiveMonthVO; -import run.halo.app.model.vo.ArchiveYearVO; -import run.halo.app.model.vo.PostDetailVO; -import run.halo.app.model.vo.PostListVO; -import run.halo.app.service.base.CrudService; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.lang.NonNull; import org.springframework.transaction.annotation.Transactional; +import run.halo.app.model.dto.post.PostMinimalOutputDTO; +import run.halo.app.model.dto.post.PostSimpleOutputDTO; +import run.halo.app.model.entity.Post; +import run.halo.app.model.enums.PostStatus; +import run.halo.app.model.params.PostQuery; +import run.halo.app.model.vo.ArchiveMonthVO; +import run.halo.app.model.vo.ArchiveYearVO; +import run.halo.app.model.vo.PostDetailVO; +import run.halo.app.model.vo.PostListVO; import run.halo.app.service.base.CrudService; import java.util.List; @@ -56,18 +56,28 @@ public interface PostService extends CrudService { Page pageLatest(int top); /** - * List by status and type + * Lists by status and type * * @param status post status must not be null * @param pageable page info must not be null - * @return Page + * @return a page of post */ @NonNull Page pageBy(@NonNull PostStatus status, @NonNull Pageable pageable); + /** + * Pages posts. + * + * @param postQuery post query must not be null + * @param pageable page info must not be null + * @return a page of post + */ + @NonNull + Page pageBy(@NonNull PostQuery postQuery, @NonNull Pageable pageable); + /** - * List simple output dto by status and type + * Lists simple output dto by status and type * * @param status post status must not be null * @param pageable page info must not be null @@ -165,4 +175,13 @@ public interface PostService extends CrudService { */ @NonNull List listMonthArchives(); + + /** + * Converts to a page of post simple output dto. + * + * @param postPage post page must not be null + * @return a page of post simple output dto + */ + @NonNull + Page convertTo(@NonNull Page postPage); } diff --git a/src/main/java/run/halo/app/service/impl/PostServiceImpl.java b/src/main/java/run/halo/app/service/impl/PostServiceImpl.java index fa2640093..c2cedb1fa 100644 --- a/src/main/java/run/halo/app/service/impl/PostServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/PostServiceImpl.java @@ -1,10 +1,12 @@ package run.halo.app.service.impl; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.Specification; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.stereotype.Service; @@ -19,6 +21,7 @@ import run.halo.app.model.dto.post.PostMinimalOutputDTO; import run.halo.app.model.dto.post.PostSimpleOutputDTO; import run.halo.app.model.entity.*; import run.halo.app.model.enums.PostStatus; +import run.halo.app.model.params.PostQuery; import run.halo.app.model.vo.ArchiveMonthVO; import run.halo.app.model.vo.ArchiveYearVO; import run.halo.app.model.vo.PostDetailVO; @@ -30,6 +33,9 @@ import run.halo.app.utils.DateUtils; import run.halo.app.utils.MarkdownUtils; import run.halo.app.utils.ServiceUtils; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.Subquery; import java.util.*; import java.util.function.Function; import java.util.function.Supplier; @@ -101,6 +107,50 @@ public class PostServiceImpl extends AbstractCrudService implemen return postRepository.findAllByStatus(status, pageable); } + @Override + public Page pageBy(PostQuery postQuery, Pageable pageable) { + Assert.notNull(postQuery, "Post query must not be null"); + Assert.notNull(pageable, "Page info must not be null"); + + // Build specification and find all + return postRepository.findAll(buildSpecByQuery(postQuery), pageable); + } + + private Specification buildSpecByQuery(@NonNull PostQuery postQuery) { + Assert.notNull(postQuery, "Post query must not be null"); + + return (Specification) (root, query, criteriaBuilder) -> { + List predicates = new LinkedList<>(); + + if (postQuery.getStatus() != null) { + predicates.add(criteriaBuilder.equal(root.get("status"), postQuery.getStatus())); + } + + if (postQuery.getCategoryId() != null) { + Subquery postSubquery = query.subquery(Post.class); + Root postCategoryRoot = postSubquery.from(PostCategory.class); + postSubquery.select(postCategoryRoot.get("postId")); + postSubquery.where( + criteriaBuilder.equal(root.get("id"), postCategoryRoot.get("postId")), + criteriaBuilder.equal(postCategoryRoot.get("categoryId"), postQuery.getCategoryId())); + predicates.add(criteriaBuilder.exists(postSubquery)); + } + + if (postQuery.getKeyword() != null) { + // Format like condition + String likeCondition = String.format("%%%s%%", StringUtils.strip(postQuery.getKeyword())); + + // Build like predicate + Predicate titleLike = criteriaBuilder.like(root.get("title"), likeCondition); + Predicate originalContentLike = criteriaBuilder.like(root.get("originalContent"), likeCondition); + + predicates.add(criteriaBuilder.or(titleLike, originalContentLike)); + } + + return query.where(predicates.toArray(new Predicate[0])).getRestriction(); + }; + } + /** * List by status and type * @@ -361,6 +411,13 @@ public class PostServiceImpl extends AbstractCrudService implemen .collect(Collectors.toList()); } + @Override + public Page convertTo(@NonNull Page postPage) { + Assert.notNull(postPage, "Post page must not be null"); + + return postPage.map(post -> new PostSimpleOutputDTO().convertFrom(post)); + } + /** * Converts to post detail vo. * diff --git a/src/main/java/run/halo/app/web/controller/admin/api/PostController.java b/src/main/java/run/halo/app/web/controller/admin/api/PostController.java index e17080d47..0a891c5c6 100644 --- a/src/main/java/run/halo/app/web/controller/admin/api/PostController.java +++ b/src/main/java/run/halo/app/web/controller/admin/api/PostController.java @@ -10,6 +10,7 @@ import run.halo.app.model.dto.post.PostSimpleOutputDTO; import run.halo.app.model.entity.Post; import run.halo.app.model.enums.PostStatus; import run.halo.app.model.params.PostParam; +import run.halo.app.model.params.PostQuery; import run.halo.app.model.vo.PostDetailVO; import run.halo.app.service.*; @@ -50,6 +51,14 @@ public class PostController { this.optionService = optionService; } + @GetMapping + @ApiOperation("Lists posts") + public Page pageBy(@PageableDefault(sort = "updateTime", direction = DESC) Pageable pageable, + PostQuery postQuery) { + Page postPage = postService.pageBy(postQuery, pageable); + return postService.convertTo(postPage); + } + @GetMapping("latest") @ApiOperation("Pages latest post") public List pageLatest(@RequestParam(name = "top", defaultValue = "10") int top) {