From ff968e449f0416433dcacea44bdda748e4369045 Mon Sep 17 00:00:00 2001 From: AkagiYui Date: Sat, 26 Aug 2023 21:27:55 +0800 Subject: [PATCH] feat: support announcement create, get --- README.md | 2 + .../controller/AnnouncementController.java | 58 ++++++++++++++ .../akagiyui/drive/entity/Announcement.java | 49 ++++++++++++ .../model/request/AddAnnouncementRequest.java | 38 +++++++++ .../response/AnnouncementDisplayResponse.java | 65 ++++++++++++++++ .../model/response/AnnouncementResponse.java | 77 +++++++++++++++++++ .../repository/AnnouncementRepository.java | 25 ++++++ .../drive/service/AnnouncementService.java | 31 ++++++++ .../service/impl/AnnouncementServiceImpl.java | 40 ++++++++++ src/main/resources/i18n/messages.properties | 2 + .../resources/i18n/messages_zh_CN.properties | 2 + 11 files changed, 389 insertions(+) create mode 100644 src/main/java/com/akagiyui/drive/controller/AnnouncementController.java create mode 100644 src/main/java/com/akagiyui/drive/entity/Announcement.java create mode 100644 src/main/java/com/akagiyui/drive/model/request/AddAnnouncementRequest.java create mode 100644 src/main/java/com/akagiyui/drive/model/response/AnnouncementDisplayResponse.java create mode 100644 src/main/java/com/akagiyui/drive/model/response/AnnouncementResponse.java create mode 100644 src/main/java/com/akagiyui/drive/repository/AnnouncementRepository.java create mode 100644 src/main/java/com/akagiyui/drive/service/AnnouncementService.java create mode 100644 src/main/java/com/akagiyui/drive/service/impl/AnnouncementServiceImpl.java diff --git a/README.md b/README.md index d65ca88..e53a351 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ API 文档:https://apifox.com/apidoc/project-2811497 - [x] [Spring Cache 缓存](src/main/java/com/akagiyui/drive/config/CacheConfig.java) - [x] [Caffeine 本地缓存](src/main/java/com/akagiyui/drive/config/CacheConfig.java) - [x] [Redis 缓存](src/main/java/com/akagiyui/drive/component/RedisCache.java) +- [ ] [多级缓存](https://github.com/pig-mesh/multilevel-cache-spring-boot-starter) - [x] [JWT 鉴权](src/main/java/com/akagiyui/drive/component/JwtUtils.java) - [x] [Docker 容器化部署](docker-compose.yaml) - [x] [Drone CI/CD 自动化部署](.drone.yml) @@ -115,4 +116,5 @@ API 文档:https://apifox.com/apidoc/project-2811497 - [CSDN: spring常见错误【数据库】idleTimeout is close to or more than maxLifetime, disabling it.](https://blog.csdn.net/qq_26462567/article/details/123982879) - [CSDN: spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during v](https://blog.csdn.net/jj89929665/article/details/111387865) - [CSDN: 大文件上传下载实现思路,分片、断点续传代码实现,以及webUpload组件](https://blog.csdn.net/weixin_52210557/article/details/124097574) +- [简书: Spring Boot - 数据校验](https://www.jianshu.com/p/e69a1f187482) - [简书: java 修改HttpServletRequest的参数或请求头](https://www.jianshu.com/p/a8c9d45775ea) diff --git a/src/main/java/com/akagiyui/drive/controller/AnnouncementController.java b/src/main/java/com/akagiyui/drive/controller/AnnouncementController.java new file mode 100644 index 0000000..9f7cf56 --- /dev/null +++ b/src/main/java/com/akagiyui/drive/controller/AnnouncementController.java @@ -0,0 +1,58 @@ +package com.akagiyui.drive.controller; + +import com.akagiyui.drive.entity.Announcement; +import com.akagiyui.drive.model.request.AddAnnouncementRequest; +import com.akagiyui.drive.model.response.AnnouncementDisplayResponse; +import com.akagiyui.drive.model.response.AnnouncementResponse; +import com.akagiyui.drive.service.AnnouncementService; +import com.akagiyui.drive.service.UserService; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 公告控制器 + * + * @author AkagiYui + */ +@RestController +@RequestMapping("/announcement") +public class AnnouncementController { + + @Resource + private AnnouncementService announcementService; + + @Resource + private UserService userService; + + /** + * 新增公告 + */ + @PostMapping({"", "/"}) + public Boolean addAnnouncement(@RequestBody @Validated AddAnnouncementRequest request) { + // todo 权限校验 + Announcement announcement = request.toAnnouncement(); + announcement.setAuthor(userService.getUser()); + return announcementService.addAnnouncement(announcement); + } + + /** + * 获取公告列表 + */ + @GetMapping({"", "/"}) + public List getAnnouncementList(@RequestParam(defaultValue = "false") Boolean all) { + // todo 权限校验 + return AnnouncementResponse.fromAnnouncementList(announcementService.getAnnouncementList(all)); + } + + /** + * 获取用于首页展示的公告列表 + */ + @GetMapping("/index") + public List getIndexAnnouncementList() { + return AnnouncementDisplayResponse.fromAnnouncementList(announcementService.getAnnouncementDisplayList()); + } + +} diff --git a/src/main/java/com/akagiyui/drive/entity/Announcement.java b/src/main/java/com/akagiyui/drive/entity/Announcement.java new file mode 100644 index 0000000..ea2b250 --- /dev/null +++ b/src/main/java/com/akagiyui/drive/entity/Announcement.java @@ -0,0 +1,49 @@ +package com.akagiyui.drive.entity; + +import com.akagiyui.common.entity.BaseEntity; +import jakarta.persistence.*; +import lombok.Data; +import lombok.ToString; +import lombok.experimental.Accessors; +import org.hibernate.annotations.ColumnDefault; +import org.hibernate.annotations.DynamicInsert; + + +/** + * 公告实体 + * + * @author AkagiYui + */ +@Data +@ToString(exclude = "author") +@Accessors(chain = true) +@Entity +@Table +@DynamicInsert +public class Announcement extends BaseEntity { + /** + * 标题 + */ + @Column(nullable = false) + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 已启用 + */ + @Column(nullable = false) + @ColumnDefault("true") + private Boolean enabled; + + /** + * 发布者 + */ + @ManyToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "user_id") + private User author; + +} diff --git a/src/main/java/com/akagiyui/drive/model/request/AddAnnouncementRequest.java b/src/main/java/com/akagiyui/drive/model/request/AddAnnouncementRequest.java new file mode 100644 index 0000000..aaecb4f --- /dev/null +++ b/src/main/java/com/akagiyui/drive/model/request/AddAnnouncementRequest.java @@ -0,0 +1,38 @@ +package com.akagiyui.drive.model.request; + +import com.akagiyui.drive.entity.Announcement; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 新增公告 请求 + * + * @author AkagiYui + */ +@Data +public class AddAnnouncementRequest { + + /** + * 标题 + */ + @NotBlank(message = "{title cannot be empty}") + @NotNull(message = "{title is missing}") + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 转换为公告实体 + */ + public Announcement toAnnouncement() { + return new Announcement() + .setTitle(title) + .setContent(content) + .setEnabled(true); + } + +} diff --git a/src/main/java/com/akagiyui/drive/model/response/AnnouncementDisplayResponse.java b/src/main/java/com/akagiyui/drive/model/response/AnnouncementDisplayResponse.java new file mode 100644 index 0000000..632f6b2 --- /dev/null +++ b/src/main/java/com/akagiyui/drive/model/response/AnnouncementDisplayResponse.java @@ -0,0 +1,65 @@ +package com.akagiyui.drive.model.response; + +import com.akagiyui.drive.entity.Announcement; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 公告信息 响应 + * + * @author AkagiYui + */ +@Data +@Accessors(chain = true) +public class AnnouncementDisplayResponse { + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 发布者昵称 + */ + private String userNickname; + + /** + * 发布时间 + */ + private Date createTime; + + /** + * 修改时间 + */ + private Date updateTime; + + /** + * 从公告实体转换 + */ + public static AnnouncementDisplayResponse fromAnnouncement(Announcement announcement) { + return new AnnouncementDisplayResponse() + .setTitle(announcement.getTitle()) + .setContent(announcement.getContent()) + .setUserNickname(announcement.getAuthor().getNickname()) + .setCreateTime(announcement.getCreateTime()) + .setUpdateTime(announcement.getUpdateTime()); + } + + /** + * 从公告实体列表转换 + */ + public static List fromAnnouncementList(List announcementList) { + return announcementList.stream() + .map(AnnouncementDisplayResponse::fromAnnouncement) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/akagiyui/drive/model/response/AnnouncementResponse.java b/src/main/java/com/akagiyui/drive/model/response/AnnouncementResponse.java new file mode 100644 index 0000000..35b713e --- /dev/null +++ b/src/main/java/com/akagiyui/drive/model/response/AnnouncementResponse.java @@ -0,0 +1,77 @@ +package com.akagiyui.drive.model.response; + +import com.akagiyui.drive.entity.Announcement; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 公告信息 响应 + * + * @author AkagiYui + */ +@Data +@Accessors(chain = true) +public class AnnouncementResponse { + + /** + * 公告id + */ + private String id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 用户ID + */ + private String userId; + + /** + * 已启用 + */ + private Boolean enabled; + + /** + * 发布时间 + */ + private Date createTime; + + /** + * 修改时间 + */ + private Date updateTime; + + /** + * 从公告实体转换 + */ + public static AnnouncementResponse fromAnnouncement(Announcement announcement) { + return new AnnouncementResponse() + .setId(announcement.getId()) + .setTitle(announcement.getTitle()) + .setContent(announcement.getContent()) + .setUserId(announcement.getAuthor().getId()) + .setEnabled(announcement.getEnabled()) + .setCreateTime(announcement.getCreateTime()) + .setUpdateTime(announcement.getUpdateTime()); + } + + /** + * 从公告实体列表转换 + */ + public static List fromAnnouncementList(List announcementList) { + return announcementList.stream() + .map(AnnouncementResponse::fromAnnouncement) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/com/akagiyui/drive/repository/AnnouncementRepository.java b/src/main/java/com/akagiyui/drive/repository/AnnouncementRepository.java new file mode 100644 index 0000000..b536fad --- /dev/null +++ b/src/main/java/com/akagiyui/drive/repository/AnnouncementRepository.java @@ -0,0 +1,25 @@ +package com.akagiyui.drive.repository; + +import com.akagiyui.drive.entity.Announcement; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +/** + * 公告 操作接口 + * + * @author AkagiYui + */ +public interface AnnouncementRepository extends JpaRepository { + + /** + * 查询所有启用的公告 + */ + List findAnnouncementsByEnabledIsTrue(); + + /** + * 查询所有启用的公告并按更新时间倒序排序 + */ + List findAnnouncementsByEnabledIsTrueOrderByUpdateTimeDesc(); + +} diff --git a/src/main/java/com/akagiyui/drive/service/AnnouncementService.java b/src/main/java/com/akagiyui/drive/service/AnnouncementService.java new file mode 100644 index 0000000..c704291 --- /dev/null +++ b/src/main/java/com/akagiyui/drive/service/AnnouncementService.java @@ -0,0 +1,31 @@ +package com.akagiyui.drive.service; + +import com.akagiyui.drive.entity.Announcement; + +import java.util.List; + +/** + * 公告服务接口 + * + * @author AkagiYui + */ +public interface AnnouncementService { + + /** + * 新增公告 + */ + boolean addAnnouncement(Announcement announcement); + + /** + * 获取公告列表 + * + * @param all 是否获取所有公告 + */ + List getAnnouncementList(Boolean all); + + /** + * 获取用于首页展示的公告列表 + */ + List getAnnouncementDisplayList(); + +} diff --git a/src/main/java/com/akagiyui/drive/service/impl/AnnouncementServiceImpl.java b/src/main/java/com/akagiyui/drive/service/impl/AnnouncementServiceImpl.java new file mode 100644 index 0000000..d170d0c --- /dev/null +++ b/src/main/java/com/akagiyui/drive/service/impl/AnnouncementServiceImpl.java @@ -0,0 +1,40 @@ +package com.akagiyui.drive.service.impl; + +import com.akagiyui.drive.entity.Announcement; +import com.akagiyui.drive.repository.AnnouncementRepository; +import com.akagiyui.drive.service.AnnouncementService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 公告服务实现类 + * @author AkagiYui + */ +@Service +public class AnnouncementServiceImpl implements AnnouncementService { + + @Resource + private AnnouncementRepository announcementRepository; + + @Override + public boolean addAnnouncement(Announcement announcement) { + announcementRepository.save(announcement); + return true; + } + + @Override + public List getAnnouncementList(Boolean all) { + if (all) { + return announcementRepository.findAll(); + } else { + return announcementRepository.findAnnouncementsByEnabledIsTrue(); + } + } + + @Override + public List getAnnouncementDisplayList() { + return announcementRepository.findAnnouncementsByEnabledIsTrueOrderByUpdateTimeDesc(); + } +} diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index b655069..1d9b3cf 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -6,6 +6,8 @@ password\ cannot\ be\ empty=password cannot be empty password\ is\ missing=password is missing password\ length\ must\ be\ more\ than\ 8=password length must be more than 8 TEST=测试 +title\ cannot\ be\ empty=title cannot be empty +title\ is\ missing=title is missing username\ can\ only\ contain\ letters,\ numbers\ and\ underscores=username can only contain letters, numbers and underscores username\ cannot\ be\ empty=username cannot be empty username\ is\ missing=username is missing diff --git a/src/main/resources/i18n/messages_zh_CN.properties b/src/main/resources/i18n/messages_zh_CN.properties index aa3254e..7577433 100644 --- a/src/main/resources/i18n/messages_zh_CN.properties +++ b/src/main/resources/i18n/messages_zh_CN.properties @@ -6,6 +6,8 @@ password\ cannot\ be\ empty=password不能为空 password\ is\ missing=password不能为空 password\ length\ must\ be\ more\ than\ 8=密码长度必须不少于8 TEST=测试 +title\ cannot\ be\ empty=标题不可为空 +title\ is\ missing=title 不可为空 username\ can\ only\ contain\ letters,\ numbers\ and\ underscores=用户名仅能包含字母、数字与下划线 username\ cannot\ be\ empty=username不能为空 username\ is\ missing=username不能为空