重构Article模块 新增Message模块 优化安全配置
This commit is contained in:
16
pom.xml
16
pom.xml
@@ -23,7 +23,23 @@
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>2.2.2</version>
|
||||
</dependency>
|
||||
<!-- Spring Security 核心依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Security 配置 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- AOP支持(用于方法级安全控制) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
|
||||
@@ -5,37 +5,63 @@ import com.qf.myafterprojecy.pojo.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
||||
import com.qf.myafterprojecy.service.IArticleService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/article")
|
||||
@RequestMapping("/api/articles")
|
||||
@Validated
|
||||
public class ArticleController {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Autowired
|
||||
IArticleService ArticleService;
|
||||
private IArticleService articleService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseMessage<Article> getArticle(@PathVariable Integer id) {
|
||||
return articleService.getArticleById(id);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseMessage<Iterable<Article>> getArticleAllByID(@Validated @RequestBody ArticleDto articleDto){
|
||||
return ArticleService.getArticleAllByID(articleDto);
|
||||
public ResponseMessage<List<Article>> getAllArticles() {
|
||||
return articleService.getAllArticles();
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
public ResponseMessage<Article> UpdateArticle(@RequestBody ArticleDto articleDto){
|
||||
return ArticleService.SaveArticle(articleDto);
|
||||
};
|
||||
|
||||
@PostMapping
|
||||
public ResponseMessage<Article> AddArticle(@RequestBody ArticleDto articleDto){
|
||||
return ArticleService.SaveArticle(articleDto);
|
||||
@PreAuthorize("hasRole('AUTHOR')")
|
||||
public ResponseMessage<Article> createArticle(@Valid @RequestBody ArticleDto articleDto) {
|
||||
return articleService.saveArticle(articleDto);
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
public ResponseMessage<Article> DeleteArticle(@RequestBody ArticleDto articleDto){
|
||||
return ArticleService.deleteArticle(articleDto.getArticleid());
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("hasRole('AUTHOR') or hasRole('ADMIN')")
|
||||
public ResponseMessage<Article> updateArticle(
|
||||
@PathVariable Integer id,
|
||||
@Valid @RequestBody ArticleDto articleDto) {
|
||||
return articleService.updateArticle(id, articleDto);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("hasRole('AUTHOR') or hasRole('ADMIN')")
|
||||
public ResponseMessage<Article> deleteArticle(@PathVariable Integer id) {
|
||||
return articleService.deleteArticle(id);
|
||||
}
|
||||
|
||||
@GetMapping("/author/{authorId}")
|
||||
public ResponseMessage<List<Article>> getArticlesByAuthor(@PathVariable Integer authorId) {
|
||||
return articleService.getArticlesByAuthor(authorId);
|
||||
}
|
||||
|
||||
@GetMapping("/category/{categoryId}")
|
||||
public ResponseMessage<List<Article>> getArticlesByCategory(@PathVariable Integer categoryId) {
|
||||
return articleService.getArticlesByCategory(categoryId);
|
||||
}
|
||||
|
||||
@GetMapping("/popular")
|
||||
public ResponseMessage<List<Article>> getMostViewedArticles() {
|
||||
return articleService.getMostViewedArticles();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.qf.myafterprojecy.controller;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Message;
|
||||
import com.qf.myafterprojecy.pojo.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
||||
import com.qf.myafterprojecy.service.IMessageService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/messages")
|
||||
public class MessageController {
|
||||
@Autowired
|
||||
private IMessageService messageService;
|
||||
|
||||
@GetMapping
|
||||
public ResponseMessage<Iterable<Message>> getAllMessages() {
|
||||
return messageService.getAllMessages();
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseMessage<Message> getMessage(@PathVariable Integer id) {
|
||||
return messageService.getMessageById(id);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseMessage<Message> createMessage(@RequestBody MessageDto message) {
|
||||
return messageService.saveMessage(message);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseMessage<Message> deleteMessage(@PathVariable Integer id) {
|
||||
return messageService.deleteMessage(id);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.qf.myafterprojecy.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "article")
|
||||
@@ -11,18 +12,35 @@ public class Article {
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "articleid")
|
||||
private Integer articleid;
|
||||
|
||||
@NotBlank(message = "标题不能为空")
|
||||
@Column(name = "title")
|
||||
private String title;
|
||||
@Column(name = "content")
|
||||
|
||||
@NotBlank(message = "内容不能为空")
|
||||
@Column(name = "content", columnDefinition = "TEXT")
|
||||
private String content;
|
||||
|
||||
@NotNull(message = "类别id不能为空")
|
||||
@Column(name = "typeid")
|
||||
private Integer typeid;
|
||||
|
||||
@Column(name = "img")
|
||||
private String img;
|
||||
@Column(name = "typeid")
|
||||
private int typeid;
|
||||
@Column(name = "published_at")
|
||||
private String publisher_at;
|
||||
|
||||
@Column(name = "created_at")
|
||||
private String created_at;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Column(name = "updated_at")
|
||||
private LocalDateTime updatedAt;
|
||||
@Column(name = "view_count")
|
||||
private Integer viewCount;
|
||||
|
||||
@Column(name = "status")
|
||||
private Integer status; // 0-草稿,1-已发布,2-已删除
|
||||
|
||||
// Getters and Setters
|
||||
|
||||
|
||||
public Integer getArticleid() {
|
||||
return articleid;
|
||||
@@ -48,6 +66,38 @@ public class Article {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public Integer getTypeid() {
|
||||
return typeid;
|
||||
}
|
||||
|
||||
public void setTypeid(Integer typeid) {
|
||||
this.typeid = typeid;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getImg() {
|
||||
return img;
|
||||
}
|
||||
@@ -56,40 +106,11 @@ public class Article {
|
||||
this.img = img;
|
||||
}
|
||||
|
||||
public int getTypeid() {
|
||||
return typeid;
|
||||
public Integer getViewCount() {
|
||||
return viewCount;
|
||||
}
|
||||
|
||||
public void setTypeid(int typeid) {
|
||||
this.typeid = typeid;
|
||||
}
|
||||
|
||||
public String getPublisher_at() {
|
||||
return publisher_at;
|
||||
}
|
||||
|
||||
public void setPublisher_at(String publisher_at) {
|
||||
this.publisher_at = publisher_at;
|
||||
}
|
||||
|
||||
public String getCreated_at() {
|
||||
return created_at;
|
||||
}
|
||||
|
||||
public void setCreated_at(String created_at) {
|
||||
this.created_at = created_at;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Article{" +
|
||||
"articleid=" + articleid +
|
||||
", title='" + title + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
", img='" + img + '\'' +
|
||||
", typeid=" + typeid +
|
||||
", publisher_at='" + publisher_at + '\'' +
|
||||
", created_at='" + created_at + '\'' +
|
||||
'}';
|
||||
public void setViewCount(Integer viewCount) {
|
||||
this.viewCount = viewCount;
|
||||
}
|
||||
}
|
||||
|
||||
83
src/main/java/com/qf/myafterprojecy/pojo/Message.java
Normal file
83
src/main/java/com/qf/myafterprojecy/pojo/Message.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package com.qf.myafterprojecy.pojo;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Date;
|
||||
|
||||
@Entity
|
||||
@Table(name = "message")
|
||||
public class Message {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Integer messageid;
|
||||
|
||||
private String nickname;
|
||||
|
||||
private String email;
|
||||
|
||||
@Column(columnDefinition = "text")
|
||||
private String content;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date createdAt;
|
||||
|
||||
private Integer parentid;
|
||||
|
||||
private Integer articleid;
|
||||
|
||||
|
||||
public Integer getMessageid() {
|
||||
return messageid;
|
||||
}
|
||||
|
||||
public void setMessageid(Integer messageid) {
|
||||
this.messageid = messageid;
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public Date getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(Date createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Integer getParentid() {
|
||||
return parentid;
|
||||
}
|
||||
|
||||
public void setParentid(Integer parentid) {
|
||||
this.parentid = parentid;
|
||||
}
|
||||
|
||||
public Integer getArticleid() {
|
||||
return articleid;
|
||||
}
|
||||
|
||||
public void setArticleid(Integer articleid) {
|
||||
this.articleid = articleid;
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,11 @@ package com.qf.myafterprojecy.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
@Data
|
||||
public class ResponseMessage<T> {
|
||||
private Integer code;
|
||||
private String message;
|
||||
private boolean success;
|
||||
private T data;
|
||||
public ResponseMessage(Integer code, String message, T data) {
|
||||
this.code = code;
|
||||
@@ -13,6 +14,14 @@ public class ResponseMessage<T> {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public void setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
@@ -36,18 +45,54 @@ public class ResponseMessage<T> {
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
public ResponseMessage(Integer code, String message, T data, boolean success) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
// 接口请求成功
|
||||
public static <T> ResponseMessage<T> success(T data ,String message ,boolean success) {
|
||||
return new ResponseMessage(HttpStatus.OK.value(), message, data ,success);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个表示操作失败的响应消息
|
||||
* @param message 失败原因的描述信息
|
||||
* @return 返回一个包含错误状态码和错误信息的ResponseMessage对象
|
||||
*/
|
||||
public static <T> ResponseMessage<T> failure(String message) {
|
||||
return new ResponseMessage<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), message, null, false);
|
||||
}
|
||||
|
||||
|
||||
public static <T> ResponseMessage<T> success(T data) {
|
||||
return new ResponseMessage(HttpStatus.OK.value(), "success", data);
|
||||
return new ResponseMessage<>(HttpStatus.OK.value(), "操作成功", data, true);
|
||||
}
|
||||
|
||||
public static <T> ResponseMessage<T> Delete(Boolean delete) {
|
||||
return new ResponseMessage(HttpStatus.OK.value(), "delete", delete);
|
||||
public static <T> ResponseMessage<T> success(T data, String message) {
|
||||
return new ResponseMessage<>(HttpStatus.OK.value(), message, data, true);
|
||||
}
|
||||
|
||||
public static <T> ResponseMessage<T> Save(Boolean save) {
|
||||
return new ResponseMessage(HttpStatus.OK.value(), "save", save);
|
||||
public static <T> ResponseMessage<T> error(String message) {
|
||||
return new ResponseMessage<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), message, null, false);
|
||||
}
|
||||
|
||||
public static <T> ResponseMessage<T> error(Integer code, String message) {
|
||||
return new ResponseMessage<>(code, message, null, false);
|
||||
}
|
||||
|
||||
public static <T> ResponseMessage<T> Save(boolean success) {
|
||||
return success ?
|
||||
new ResponseMessage<>(HttpStatus.OK.value(), "保存成功", null, true) :
|
||||
new ResponseMessage<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), "保存失败", null, false);
|
||||
}
|
||||
|
||||
public static <T> ResponseMessage<T> Delete(boolean success) {
|
||||
return success ?
|
||||
new ResponseMessage<>(HttpStatus.OK.value(), "删除成功", null, true) :
|
||||
new ResponseMessage<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), "删除失败", null, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,21 +1,32 @@
|
||||
package com.qf.myafterprojecy.pojo.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Getter
|
||||
public class ArticleDto {
|
||||
private Integer articleid;
|
||||
private String title;
|
||||
private String content;
|
||||
private String img;
|
||||
private Integer typeid;
|
||||
private String publisher_at;
|
||||
private String created_at;
|
||||
private Integer id;
|
||||
|
||||
public Integer getArticleid() {
|
||||
return articleid;
|
||||
@NotBlank(message = "标题不能为空")
|
||||
private String title;
|
||||
|
||||
@NotBlank(message = "内容不能为空")
|
||||
private String content;
|
||||
|
||||
private String img;
|
||||
|
||||
private Integer status;
|
||||
|
||||
// Getters and Setters
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setArticleid(Integer articleid) {
|
||||
this.articleid = articleid;
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
@@ -34,6 +45,14 @@ public class ArticleDto {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getImg() {
|
||||
return img;
|
||||
}
|
||||
@@ -41,41 +60,4 @@ public class ArticleDto {
|
||||
public void setImg(String img) {
|
||||
this.img = img;
|
||||
}
|
||||
|
||||
public Integer getTypeid() {
|
||||
return typeid;
|
||||
}
|
||||
|
||||
public void setTypeid(Integer typeid) {
|
||||
this.typeid = typeid;
|
||||
}
|
||||
|
||||
public String getPublisher_at() {
|
||||
return publisher_at;
|
||||
}
|
||||
|
||||
public void setPublisher_at(String publisher_at) {
|
||||
this.publisher_at = publisher_at;
|
||||
}
|
||||
|
||||
public String getCreated_at() {
|
||||
return created_at;
|
||||
}
|
||||
|
||||
public void setCreated_at(String created_at) {
|
||||
this.created_at = created_at;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ArticleDto{" +
|
||||
"articleid=" + articleid +
|
||||
", title='" + title + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
", img='" + img + '\'' +
|
||||
", typeid=" + typeid +
|
||||
", publisher_at='" + publisher_at + '\'' +
|
||||
", created_at='" + created_at + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
77
src/main/java/com/qf/myafterprojecy/pojo/dto/MessageDto.java
Normal file
77
src/main/java/com/qf/myafterprojecy/pojo/dto/MessageDto.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package com.qf.myafterprojecy.pojo.dto;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Date;
|
||||
|
||||
public class MessageDto {
|
||||
private Integer messageid;
|
||||
|
||||
private String nickname;
|
||||
|
||||
private String email;
|
||||
|
||||
private String content;
|
||||
|
||||
private Date createdAt;
|
||||
|
||||
private Integer parentid;
|
||||
|
||||
private Integer articleid;
|
||||
|
||||
|
||||
public Integer getMessageid() {
|
||||
return messageid;
|
||||
}
|
||||
|
||||
public void setMessageid(Integer messageid) {
|
||||
this.messageid = messageid;
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public Date getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(Date createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Integer getParentid() {
|
||||
return parentid;
|
||||
}
|
||||
|
||||
public void setParentid(Integer parentid) {
|
||||
this.parentid = parentid;
|
||||
}
|
||||
|
||||
public Integer getArticleid() {
|
||||
return articleid;
|
||||
}
|
||||
|
||||
public void setArticleid(Integer articleid) {
|
||||
this.articleid = articleid;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,30 @@
|
||||
package com.qf.myafterprojecy.repository;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Article;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface ArticleRepository extends CrudRepository<Article,Integer> {
|
||||
//public interface ArticleRepository extends CrudRepository<Article,Integer> {
|
||||
//}
|
||||
public interface ArticleRepository extends JpaRepository<Article, Integer> {
|
||||
|
||||
@Query("SELECT a FROM Article a WHERE a.status = 1 AND a.articleid = :articleid")
|
||||
List<Article> findPublishedByAuthor(@Param("authorId") Integer authorId);
|
||||
|
||||
@Query("SELECT a FROM Article a WHERE a.status = 1 AND a.typeid = :typeid")
|
||||
List<Article> findPublishedByCategory(@Param("categoryId") Integer categoryId);
|
||||
|
||||
@Modifying
|
||||
@Query("UPDATE Article a SET a.viewCount = a.viewCount + 1 WHERE a.id = :id")
|
||||
void incrementViewCount(@Param("id") Integer id);
|
||||
|
||||
@Query("SELECT a FROM Article a WHERE a.status = 1 ORDER BY a.viewCount DESC")
|
||||
List<Article> findMostViewed();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.qf.myafterprojecy.repository;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Message;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface MessageRepository extends CrudRepository<Message, Integer> {
|
||||
// 可根据需要添加自定义查询方法
|
||||
}
|
||||
@@ -4,39 +4,140 @@ import com.qf.myafterprojecy.pojo.Article;
|
||||
import com.qf.myafterprojecy.pojo.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
||||
import com.qf.myafterprojecy.repository.ArticleRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ArticleService implements IArticleService{
|
||||
public class ArticleService implements IArticleService {
|
||||
|
||||
@Autowired
|
||||
ArticleRepository articleRepository;
|
||||
private ArticleRepository articleRepository;
|
||||
|
||||
@Override
|
||||
public ResponseMessage<Iterable<Article>> getArticleAllByID(ArticleDto articleDto){
|
||||
Iterable<Article> Articles = null;
|
||||
if (articleDto.getArticleid()!=null && articleDto.getArticleid()!=0){
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<Article> getArticleById(Integer id) {
|
||||
try {
|
||||
Article article = articleRepository.findById(id)
|
||||
.orElseThrow(() -> new RuntimeException("文章不存在"));
|
||||
|
||||
Articles = Collections.singleton(articleRepository.findById(articleDto.getArticleid()).orElseThrow(()-> new RuntimeException("没有该文章")));
|
||||
}else {
|
||||
Articles = articleRepository.findAll();
|
||||
// 增加浏览次数
|
||||
articleRepository.incrementViewCount(id);
|
||||
|
||||
return ResponseMessage.success(article);
|
||||
} catch (Exception e) {
|
||||
log.error("获取文章失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("获取文章失败");
|
||||
}
|
||||
return ResponseMessage.success(Articles) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseMessage<Article> SaveArticle(ArticleDto article) {
|
||||
Article articlenew = new Article();
|
||||
BeanUtils.copyProperties(article,articlenew);
|
||||
return ResponseMessage.Save(articleRepository.save(articlenew)!= null);
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<List<Article>> getAllArticles() {
|
||||
try {
|
||||
List<Article> articles = articleRepository.findAll();
|
||||
return ResponseMessage.success(articles);
|
||||
} catch (DataAccessException e) {
|
||||
log.error("获取文章列表失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("获取文章列表失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseMessage<Article> saveArticle(ArticleDto articleDto) {
|
||||
try {
|
||||
Article article = new Article();
|
||||
BeanUtils.copyProperties(articleDto, article);
|
||||
article.setCreatedAt(LocalDateTime.now());
|
||||
article.setUpdatedAt(LocalDateTime.now());
|
||||
article.setImg(articleDto.getImg() != null ? articleDto.getImg() : "");
|
||||
article.setStatus(articleDto.getStatus() != null ? articleDto.getStatus() : 0);
|
||||
|
||||
Article savedArticle = articleRepository.save(article);
|
||||
return ResponseMessage.success(savedArticle);
|
||||
} catch (DataAccessException e) {
|
||||
log.error("保存文章失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("保存文章失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseMessage<Article> deleteArticle(Integer articleid) {
|
||||
return ResponseMessage.Delete(articleRepository.existsById(articleid)) ;
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseMessage<Article> updateArticle(Integer id, ArticleDto articleDto) {
|
||||
try {
|
||||
Article article = articleRepository.findById(id)
|
||||
.orElseThrow(() -> new RuntimeException("文章不存在"));
|
||||
|
||||
BeanUtils.copyProperties(articleDto, article);
|
||||
article.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
Article updatedArticle = articleRepository.save(article);
|
||||
return ResponseMessage.success(updatedArticle);
|
||||
} catch (Exception e) {
|
||||
log.error("更新文章失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("更新文章失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseMessage<Article> deleteArticle(Integer id) {
|
||||
try {
|
||||
Article article = articleRepository.findById(id)
|
||||
.orElseThrow(() -> new RuntimeException("文章不存在"));
|
||||
|
||||
article.setStatus(2); // 标记为已删除
|
||||
article.setUpdatedAt(LocalDateTime.now());
|
||||
articleRepository.save(article);
|
||||
|
||||
return ResponseMessage.success(null);
|
||||
} catch (Exception e) {
|
||||
log.error("删除文章失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("删除文章失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<List<Article>> getArticlesByAuthor(Integer authorId) {
|
||||
try {
|
||||
List<Article> articles = articleRepository.findPublishedByAuthor(authorId);
|
||||
return ResponseMessage.success(articles);
|
||||
} catch (DataAccessException e) {
|
||||
log.error("获取作者文章失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("获取作者文章失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<List<Article>> getArticlesByCategory(Integer categoryId) {
|
||||
try {
|
||||
List<Article> articles = articleRepository.findPublishedByCategory(categoryId);
|
||||
return ResponseMessage.success(articles);
|
||||
} catch (DataAccessException e) {
|
||||
log.error("获取分类文章失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("获取分类文章失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<List<Article>> getMostViewedArticles() {
|
||||
try {
|
||||
List<Article> articles = articleRepository.findMostViewed();
|
||||
return ResponseMessage.success(articles);
|
||||
} catch (DataAccessException e) {
|
||||
log.error("获取热门文章失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("获取热门文章失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,30 +4,15 @@ import com.qf.myafterprojecy.pojo.Article;
|
||||
import com.qf.myafterprojecy.pojo.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IArticleService {
|
||||
|
||||
/**
|
||||
* 根据id查询 如果id为空查询所有
|
||||
*
|
||||
* @param articleDto
|
||||
* @return ResponseMessage<Article>
|
||||
*/
|
||||
ResponseMessage<Iterable<Article>> getArticleAllByID(ArticleDto articleDto);
|
||||
|
||||
|
||||
/**
|
||||
* 新增(id=0)
|
||||
* 修改 (id=修改数据的id)
|
||||
* @param article
|
||||
* @return ResponseMessage<Article>
|
||||
*/
|
||||
ResponseMessage<Article> SaveArticle(ArticleDto article);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param articleid
|
||||
* @return ResponseMessage<Article>
|
||||
*/
|
||||
ResponseMessage<Article> deleteArticle(Integer articleid);
|
||||
|
||||
ResponseMessage<Article> getArticleById(Integer id);
|
||||
ResponseMessage<List<Article>> getAllArticles();
|
||||
ResponseMessage<Article> saveArticle(ArticleDto articleDto);
|
||||
ResponseMessage<Article> updateArticle(Integer id, ArticleDto articleDto);
|
||||
ResponseMessage<Article> deleteArticle(Integer id);
|
||||
ResponseMessage<List<Article>> getArticlesByAuthor(Integer authorId);
|
||||
ResponseMessage<List<Article>> getArticlesByCategory(Integer categoryId);
|
||||
ResponseMessage<List<Article>> getMostViewedArticles();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.qf.myafterprojecy.service;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Message;
|
||||
import com.qf.myafterprojecy.pojo.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
||||
|
||||
public interface IMessageService {
|
||||
/**
|
||||
* 获取所有消息的方法
|
||||
* @return 返回一个ResponseMessage对象,其中包含一个可迭代的Message集合
|
||||
* ResponseMessage是响应消息的包装类,Iterable<Message>表示可迭代的消息集合
|
||||
*/
|
||||
ResponseMessage<Iterable<Message>> getAllMessages();
|
||||
/**
|
||||
* 根据消息ID获取消息的方法
|
||||
* @param id 消息的唯一标识符
|
||||
* @return ResponseMessage<Message> 包含消息的响应对象,其中Message为消息的具体内容
|
||||
*/
|
||||
ResponseMessage<Message> getMessageById(Integer id);
|
||||
/**
|
||||
* 保存消息的方法
|
||||
* @param message 消息数据传输对象,包含需要保存的消息信息
|
||||
* @return ResponseMessage<Message> 返回一个响应消息对象,包含操作结果和保存后的消息信息
|
||||
*/
|
||||
ResponseMessage<Message> saveMessage(MessageDto message);
|
||||
/**
|
||||
* 根据消息ID删除消息的方法
|
||||
* @param id 要删除的消息ID
|
||||
* @return ResponseMessage<Message> 包含操作结果的响应消息,其中泛型Message表示被删除的消息内容
|
||||
*/
|
||||
ResponseMessage<Message> deleteMessage(Integer id);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.qf.myafterprojecy.service;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Message;
|
||||
import com.qf.myafterprojecy.pojo.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
||||
import com.qf.myafterprojecy.repository.MessageRepository;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.Config.log;
|
||||
|
||||
@Service
|
||||
public class MessageService implements IMessageService {
|
||||
@Autowired
|
||||
private MessageRepository messageRepository;
|
||||
|
||||
@Override
|
||||
public ResponseMessage<Iterable<Message>> getAllMessages() {
|
||||
return ResponseMessage.success(messageRepository.findAll(), "查询成功", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseMessage<Message> getMessageById(Integer id) {
|
||||
return ResponseMessage.success(messageRepository.findById(id).orElse(null), "查询成功", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseMessage<Message> saveMessage(MessageDto messageDto) {
|
||||
// 参数校验
|
||||
if (messageDto == null) {
|
||||
throw new IllegalArgumentException("MessageDto cannot be null");
|
||||
}
|
||||
// 业务逻辑校验
|
||||
if (StringUtils.isEmpty(messageDto.getContent())) {
|
||||
throw new IllegalArgumentException("Message content cannot be empty");
|
||||
}
|
||||
// 调用Repository保存数据
|
||||
try {
|
||||
Message message = new Message();
|
||||
BeanUtils.copyProperties(messageDto,message);
|
||||
Message savedMessage = messageRepository.save(message);
|
||||
return ResponseMessage.success(savedMessage, "保存成功", true);
|
||||
} catch (DataAccessException e) {
|
||||
return ResponseMessage.failure("Failed to save message");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseMessage<Message> deleteMessage(Integer id) {
|
||||
if (messageRepository.existsById(id)) {
|
||||
messageRepository.deleteById(id);
|
||||
return ResponseMessage.success(null, "删除成功", true);
|
||||
} else {
|
||||
return ResponseMessage.failure("Message not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,56 @@ spring.datasource.username=root
|
||||
spring.datasource.password=123456
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
|
||||
spring.jpa.show-sql=true
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
#下面这些内容是为了让MyBatis映射
|
||||
#指定Mybatis的Mapper文件
|
||||
mybatis.mapper-locations=classpath:mappers/*xml
|
||||
#指定Mybatis的实体目录
|
||||
mybatis.type-aliases-package=com.qf.myafterprojecy.mybatis.entity
|
||||
# 数据库连接池配置
|
||||
spring.datasource.hikari.maximum-pool-size=10
|
||||
spring.datasource.hikari.minimum-idle=5
|
||||
spring.datasource.hikari.idle-timeout=300000
|
||||
spring.datasource.hikari.connection-timeout=20000
|
||||
spring.datasource.hikari.max-lifetime=1200000
|
||||
# JPA配置
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.show-sql=true
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
|
||||
spring.jpa.open-in-view=false
|
||||
# 缓存配置
|
||||
spring.cache.type=redis
|
||||
spring.cache.redis.time-to-live=1800000
|
||||
spring.cache.redis.key-prefix=CACHE_
|
||||
spring.cache.redis.use-key-prefix=true
|
||||
spring.cache.redis.cache-null-values=false
|
||||
# Redis配置
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
spring.redis.password=
|
||||
spring.redis.database=0
|
||||
spring.redis.timeout=10000ms
|
||||
spring.redis.lettuce.pool.max-active=8
|
||||
spring.redis.lettuce.pool.max-wait=-1ms
|
||||
spring.redis.lettuce.pool.max-idle=8
|
||||
spring.redis.lettuce.pool.min-idle=0
|
||||
# 日志配置
|
||||
logging.level.root=INFO
|
||||
logging.level.com.qf.myafterprojecy=DEBUG
|
||||
logging.file.name=logs/web_project.log
|
||||
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
||||
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
||||
# Actuator配置
|
||||
management.endpoints.web.exposure.include=*
|
||||
management.endpoint.health.show-details=always
|
||||
management.metrics.export.prometheus.enabled=true
|
||||
# 安全配置
|
||||
# JWT配置
|
||||
jwt.secret=mySecretKey
|
||||
jwt.expiration=86400000
|
||||
|
||||
# CORS配置
|
||||
cors.allowed-origins=http://localhost:3000
|
||||
cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS
|
||||
cors.allowed-headers=*
|
||||
cors.allow-credentials=true
|
||||
|
||||
Reference in New Issue
Block a user