feat: 添加随机内容模块并优化安全配置

新增Nonsense相关实体、DTO、Repository、Service和Controller,实现随机内容的CRUD功能
优化CORS和安全配置,增加更精细的权限控制和错误处理
移除Article和Message中不必要的验证注解,调整部分API的权限要求
This commit is contained in:
qingfeng1121
2025-11-05 16:11:38 +08:00
parent 25eeab4940
commit 5136a3a78b
24 changed files with 9960 additions and 17168 deletions

View File

@@ -20,23 +20,33 @@ public class CorsConfig {
// 创建CORS配置对象
CorsConfiguration config = new CorsConfiguration();
// 允许的来源,这里允许所有来源,实际生产环境应该限制特定域名
// 允许的来源,使用通配符模式
config.addAllowedOriginPattern("*");
// 允许携带凭证如Cookie
config.setAllowCredentials(true);
// 允许的请求方法
config.addAllowedMethod("*");
// 明确列出允许的HTTP方法比使用通配符更安全
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("PATCH");
// 允许的请求头
config.addAllowedHeader("*");
// 暴露的响应头,这些头信息可以被前端JavaScript访问
config.addExposedHeader("*");
// 明确暴露的响应头,对于JWT认证很重要
config.addExposedHeader("Authorization");
config.addExposedHeader("Content-Type");
config.addExposedHeader("X-Requested-With");
config.addExposedHeader("Accept");
config.addExposedHeader("Access-Control-Allow-Origin");
config.addExposedHeader("Access-Control-Allow-Credentials");
// 设置预检请求的有效期(秒)
config.setMaxAge(3600L);
config.setMaxAge(86400L); // 增加到24小时减少预检请求次数
// 创建基于URL的CORS配置源
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

View File

@@ -48,7 +48,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
if (token != null && validateToken(token)) {
// 从token中获取用户名
String username = jwtUtils.getUsernameFromToken(token);
System.out.println("username: " + username);
// 加载用户信息
UserDetails userDetails = userDetailsService.loadUserByUsername(username);

View File

@@ -1,6 +1,6 @@
package com.qf.myafterprojecy.config;
import javax.ws.rs.HttpMethod;
import org.springframework.http.HttpMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@@ -15,6 +15,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.http.HttpServletResponse;
/**
* Spring Security配置类
@@ -53,19 +54,24 @@ public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// 启用CORS支持确保与CorsConfig中配置的过滤器配合工作
.cors().and()
// 禁用CSRF保护对于API服务通常不需要
.csrf().disable()
// 配置URL访问权限
.authorizeRequests()
// 允许公开访问的路径
// 登录和认证相关端点应该全部公开
.antMatchers("/api/auth/**").permitAll()
// 公开get请求
.antMatchers(HttpMethod.GET,"/api/auth/**").permitAll()
.antMatchers(HttpMethod.GET,"/api/help/**").permitAll()
.antMatchers(HttpMethod.GET,"/api/category-attributes/**").permitAll()
.antMatchers(HttpMethod.GET,"/api/markdowns/**").permitAll()
.antMatchers(HttpMethod.GET,"/api/articles/**").permitAll()
.antMatchers(HttpMethod.GET,"/api/messages/**").permitAll()
.antMatchers(HttpMethod.GET,"/api/categories/**").permitAll()
.antMatchers(HttpMethod.GET,"/api/category-attributes/**").permitAll()
.antMatchers(HttpMethod.GET,"/api/nonsense/**").permitAll()
// 公开post请求
.antMatchers(HttpMethod.POST,"/api/messages/**").permitAll()
.antMatchers(HttpMethod.POST,"/api/users/**").permitAll()
@@ -76,7 +82,29 @@ public class SecurityConfig {
.and()
// 配置会话管理,使用无状态会话
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// 确保OPTIONS请求能够通过处理预检请求
.exceptionHandling()
.authenticationEntryPoint((request, response, authException) -> {
// 设置CORS头信息
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Max-Age", "86400");
// 如果是预检请求直接返回200
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
return;
}
// 未认证处理
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"message\": \"未授权访问,请先登录\"}");
});
// 添加JWT认证过滤器
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
@@ -86,10 +114,23 @@ public class SecurityConfig {
http.addFilterBefore((request, response, chain) -> {
// 确保响应使用UTF-8编码
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.setContentType("application/json;charset=UTF-8");
chain.doFilter(request, response);
}, JwtAuthenticationFilter.class);
// 配置访问拒绝处理器
http.exceptionHandling()
.accessDeniedHandler((request, response, accessDeniedException) -> {
// 设置CORS头信息
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
// 无权限处理
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"message\": \"权限不足,无法访问\"}");
});
return http.build();
}
}

View File

@@ -70,7 +70,6 @@ public class ArticleController {
return articleService.getArticlesByAttribute(attributeId);
}
/**
/**
* 根据属性ID获取最新文章按创建时间降序
* @param attributeId 属性ID
@@ -88,7 +87,7 @@ public class ArticleController {
* @return 返回包含新创建文章信息的ResponseMessage对象
*/
@PostMapping
@PreAuthorize("hasRole('AUTHOR')")
@PreAuthorize("hasRole('ADMIN')")
public ResponseMessage<Article> createArticle(@Valid @RequestBody ArticleDto articleDto) {
return articleService.saveArticle(articleDto);
}
@@ -109,7 +108,7 @@ public class ArticleController {
* @return 返回包含更新后文章信息的ResponseMessage对象
*/
@PutMapping("/{id}")
@PreAuthorize("hasRole('AUTHOR')")
@PreAuthorize("hasRole('ADMIN')")
public ResponseMessage<Article> updateArticle(
@PathVariable Integer id,
@Valid @RequestBody ArticleDto articleDto) {
@@ -123,7 +122,7 @@ public class ArticleController {
* @return 返回包含被删除文章信息的ResponseMessage对象
*/
@DeleteMapping("/{id}")
@PreAuthorize("hasRole('AUTHOR') or hasRole('ADMIN')")
@PreAuthorize("hasRole('ADMIN')")
public ResponseMessage<Article> deleteArticle(@PathVariable Integer id) {
return articleService.deleteArticle(id);
}

View File

@@ -35,7 +35,11 @@ public class CategoryAttributeController {
log.info("接收根据ID获取分类属性的请求: ID={}", id);
return categoryAttributeService.getCategoryAttributeById(id);
}
@GetMapping
public ResponseMessage<List<Category_attribute>> getAttributeCount() {
log.info("接收获取分类属性数量的请求");
return categoryAttributeService.getAllCategoryAttributes();
}
/**
* 根据分类ID获取属性列表

View File

@@ -53,8 +53,8 @@ public class HelpController {
// 读取文件内容
String markdownContent = new String(FileCopyUtils.copyToByteArray(new FileInputStream(readmeFile)), StandardCharsets.UTF_8);
// 将Markdown转换为HTML
// String htmlContent = convertMarkdownToHtml(markdownContent);
return ResponseMessage.success(markdownContent, "获取API文档成功");
String htmlContent = convertMarkdownToHtml(markdownContent);
return ResponseMessage.success(htmlContent, "获取API文档成功");
} catch (IOException e) {
return ResponseMessage.error("读取README_API.md文件失败: " + e.getMessage());
}

View File

@@ -108,12 +108,11 @@ public class MessageController {
logger.info("接收删除消息的请求: {}", id);
return messageService.deleteMessage(id);
}
//删除所有评论
//删除所有评论 - 仅管理员可操作
@DeleteMapping("/all")
@PreAuthorize("hasRole('ADMIN')")
public ResponseMessage<Void> deleteAllMessages() {
logger.info("接收删除所有消息的请求");
return messageService.deleteAllMessages();
}
// 新增API端点
}

View File

@@ -0,0 +1,87 @@
package com.qf.myafterprojecy.controller;
import com.qf.myafterprojecy.config.ResponseMessage;
import com.qf.myafterprojecy.pojo.Nonsense;
import com.qf.myafterprojecy.pojo.dto.NonsenseDto;
import com.qf.myafterprojecy.service.imp.INonsenseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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("/api/nonsense")
@Validated
public class NonsenseController {
private static final Logger logger = LoggerFactory.getLogger(NonsenseController.class);
@Autowired
private INonsenseService nonsenseService;
/**
* 获取所有随机内容
* @return 随机内容列表
*/
@GetMapping("")
public ResponseMessage<List<Nonsense>> getAllNonsense() {
logger.info("请求获取所有随机内容");
return nonsenseService.getAllNonsense();
}
/**
* 根据ID获取随机内容
* @param id 随机内容ID
* @return 随机内容
*/
@GetMapping("/{id}")
public ResponseMessage<Nonsense> getNonsenseById(@PathVariable("id") Integer id) {
logger.info("请求获取ID为{}的随机内容", id);
return nonsenseService.getNonsenseById(id);
}
/**
* 创建随机内容
* 需要管理员权限
* @param nonsenseDto 随机内容数据
* @return 创建结果
*/
@PostMapping("")
@PreAuthorize("hasRole('ADMIN')")
public ResponseMessage<Nonsense> saveNonsense(@Valid @RequestBody NonsenseDto nonsenseDto) {
logger.info("请求保存随机内容");
return nonsenseService.saveNonsense(nonsenseDto);
}
/**
* 更新随机内容
* 需要管理员权限
* @param id 随机内容ID
* @param nonsenseDto 随机内容数据
* @return 更新结果
*/
@PutMapping("/{id}")
@PreAuthorize("hasRole('ADMIN')")
public ResponseMessage<Nonsense> updateNonsense(@PathVariable("id") Integer id, @Valid @RequestBody NonsenseDto nonsenseDto) {
logger.info("请求更新ID为{}的随机内容", id);
return nonsenseService.updateNonsense(id, nonsenseDto);
}
/**
* 删除随机内容
* 需要管理员权限
* @param id 随机内容ID
* @return 删除结果
*/
@DeleteMapping("/{id}")
@PreAuthorize("hasRole('ADMIN')")
public ResponseMessage<Boolean> deleteNonsense(@PathVariable("id") Integer id) {
logger.info("请求删除ID为{}的随机内容", id);
return nonsenseService.deleteNonsense(id);
}
}

View File

@@ -17,7 +17,6 @@ public class Article {
@Column(name = "title")
private String title;
@NotBlank(message = "内容不能为空")
@Column(name = "content", columnDefinition = "TEXT")
private String content;
@@ -44,7 +43,6 @@ public class Article {
private Integer status; // 0-草稿1-已发布2-已删除
@Column(name = "markdownscontent")
@NotBlank(message = "Markdown内容不能为空")
private String markdownscontent;
// Getters and Setters

View File

@@ -8,7 +8,6 @@ import java.util.Date;
public class Message {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "messageid")
private Integer messageid;
@@ -21,6 +20,9 @@ public class Message {
@Column(name = "content", columnDefinition = "text")
private String content;
@Column(name = "messageimg")
private String messageimg;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at")
private Date createdAt;
@@ -37,6 +39,7 @@ public class Message {
@Column(name = "likes")
private Integer likes; // 点赞数
public Integer getLikes() {
return likes;
}
@@ -108,4 +111,12 @@ public class Message {
public void setArticleid(Integer articleid) {
this.articleid = articleid;
}
public String getMessageimg() {
return messageimg;
}
public void setMessageimg(String messageimg) {
this.messageimg = messageimg;
}
}

View File

@@ -0,0 +1,38 @@
package com.qf.myafterprojecy.pojo;
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name = "nonsense")
public class Nonsense {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, unique = true)
private Integer id;
@Column(name = "content",nullable = false)
private String content;
@Column(name = "time")
private Date time;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
}

View File

@@ -20,6 +20,8 @@ public class MessageDto {
private Integer articleid;
private Integer likes;
private String messageimg;
public Integer getReplyid() {
return replyid;
@@ -92,4 +94,12 @@ public class MessageDto {
public void setLikes(Integer likes) {
this.likes = likes;
}
public String getMessageimg() {
return messageimg;
}
public void setMessageimg(String messageimg) {
this.messageimg = messageimg;
}
}

View File

@@ -0,0 +1,36 @@
package com.qf.myafterprojecy.pojo.dto;
import java.util.Date;
public class NonsenseDto {
private Integer id;
private String content;
private Date time;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
}

View File

@@ -79,6 +79,7 @@ public interface ArticleRepository extends JpaRepository<Article, Integer> {
*/
@Query("SELECT a FROM Article a WHERE a.status = 1 ORDER BY a.viewCount DESC")
List<Article> findMostViewed();
/**
* 根据状态查询文章列表
* @param status 文章状态0-草稿1-已发布2-已删除

View File

@@ -0,0 +1,9 @@
package com.qf.myafterprojecy.repository;
import com.qf.myafterprojecy.pojo.Nonsense;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface NonsenseRepository extends JpaRepository<Nonsense, Integer> {
}

View File

@@ -24,6 +24,27 @@ public class CategoryAttributeService implements ICategoryAttributeService {
@Autowired
private CategoryAttributeRepository categoryAttributeRepository;
/**
* 获取全部分类属性
* @return 所有分类属性列表
*/
@Override
@Transactional(readOnly = true)
public ResponseMessage<List<Category_attribute>> getAllCategoryAttributes() {
try {
List<Category_attribute> attributes = categoryAttributeRepository.findAll();
return ResponseMessage.success(attributes, "获取所有分类属性成功");
} catch (DataAccessException e) {
log.error("获取所有分类属性失败: {}", e.getMessage());
return ResponseMessage.error("获取所有分类属性失败");
}
}
/**
* 根据ID获取分类属性
* @param id 属性ID
* @return 分类属性信息
*/
@Override
@Transactional(readOnly = true)
public ResponseMessage<Category_attribute> getCategoryAttributeById(Integer id) {
@@ -48,6 +69,11 @@ public class CategoryAttributeService implements ICategoryAttributeService {
}
}
/**
* 根据分类ID获取属性列表
* @param categoryId 分类ID
* @return 属性列表
*/
@Override
@Transactional(readOnly = true)
public ResponseMessage<List<Category_attribute>> getAttributesByCategoryId(Integer categoryId) {
@@ -64,6 +90,11 @@ public class CategoryAttributeService implements ICategoryAttributeService {
}
}
/**
* 保存分类属性
* @param dto 分类属性DTO
* @return 保存结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ResponseMessage<Category_attribute> saveCategoryAttribute(CategoryAttributeDto dto) {
@@ -88,6 +119,12 @@ public class CategoryAttributeService implements ICategoryAttributeService {
}
}
/**
* 更新分类属性
* @param id 属性ID
* @param dto 分类属性DTO
* @return 更新结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ResponseMessage<Category_attribute> updateCategoryAttribute(Integer id, CategoryAttributeDto dto) {
@@ -126,6 +163,11 @@ public class CategoryAttributeService implements ICategoryAttributeService {
}
}
/**
* 删除分类属性
* @param id 属性ID
* @return 删除结果
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ResponseMessage<Boolean> deleteCategoryAttribute(Integer id) {
@@ -147,7 +189,12 @@ public class CategoryAttributeService implements ICategoryAttributeService {
return ResponseMessage.error("删除分类属性失败");
}
}
/**
* 检查分类属性是否存在
* @param categoryId 分类ID
* @param attributeName 属性名称
* @return 是否存在
*/
@Override
@Transactional(readOnly = true)
public ResponseMessage<Boolean> existsByCategoryAndName(Integer categoryId, String attributeName) {

View File

@@ -0,0 +1,132 @@
package com.qf.myafterprojecy.service;
import com.qf.myafterprojecy.config.ResponseMessage;
import com.qf.myafterprojecy.pojo.Nonsense;
import com.qf.myafterprojecy.pojo.dto.NonsenseDto;
import com.qf.myafterprojecy.repository.NonsenseRepository;
import com.qf.myafterprojecy.service.imp.INonsenseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.Date;
import java.util.List;
import java.util.Optional;
@Service
public class NonsenseService implements INonsenseService {
private static final Logger logger = LoggerFactory.getLogger(NonsenseService.class);
@Autowired
private NonsenseRepository nonsenseRepository;
@Override
public ResponseMessage<List<Nonsense>> getAllNonsense() {
try {
List<Nonsense> nonsenseList = nonsenseRepository.findAll();
logger.info("获取所有随机内容成功,共{}条数据", nonsenseList.size());
return new ResponseMessage<>(200, "获取成功", nonsenseList, true);
} catch (DataAccessException e) {
logger.error("获取所有随机内容失败", e);
return new ResponseMessage<>(500, "数据库查询异常", null, false);
} catch (Exception e) {
logger.error("获取所有随机内容失败", e);
return new ResponseMessage<>(500, "服务器内部错误", null, false);
}
}
@Override
public ResponseMessage<Nonsense> getNonsenseById(Integer id) {
try {
Optional<Nonsense> nonsenseOptional = nonsenseRepository.findById(id);
if (nonsenseOptional.isPresent()) {
logger.info("获取ID为{}的随机内容成功", id);
return new ResponseMessage<>(200, "获取成功", nonsenseOptional.get(), true);
} else {
logger.warn("未找到ID为{}的随机内容", id);
return new ResponseMessage<>(404, "未找到指定随机内容", null, false);
}
} catch (DataAccessException e) {
logger.error("根据ID查询随机内容失败ID: {}", id, e);
return new ResponseMessage<>(500, "数据库查询异常", null, false);
} catch (Exception e) {
logger.error("根据ID查询随机内容失败ID: {}", id, e);
return new ResponseMessage<>(500, "服务器内部错误", null, false);
}
}
@Override
@Transactional
public ResponseMessage<Nonsense> saveNonsense(NonsenseDto nonsenseDto) {
try {
Nonsense nonsense = new Nonsense();
BeanUtils.copyProperties(nonsenseDto, nonsense);
// 设置创建时间
if (nonsense.getTime() == null) {
nonsense.setTime(new Date());
}
Nonsense savedNonsense = nonsenseRepository.save(nonsense);
logger.info("保存随机内容成功ID: {}", savedNonsense.getId());
return new ResponseMessage<>(200, "保存成功", savedNonsense, true);
} catch (DataAccessException e) {
logger.error("保存随机内容失败", e);
return new ResponseMessage<>(500, "数据库操作异常", null, false);
} catch (Exception e) {
logger.error("保存随机内容失败", e);
return new ResponseMessage<>(500, "服务器内部错误", null, false);
}
}
@Override
@Transactional
public ResponseMessage<Nonsense> updateNonsense(Integer id, NonsenseDto nonsenseDto) {
try {
Optional<Nonsense> nonsenseOptional = nonsenseRepository.findById(id);
if (nonsenseOptional.isPresent()) {
Nonsense nonsense = nonsenseOptional.get();
BeanUtils.copyProperties(nonsenseDto, nonsense, "id");
Nonsense updatedNonsense = nonsenseRepository.save(nonsense);
logger.info("更新随机内容成功ID: {}", id);
return new ResponseMessage<>(200, "更新成功", updatedNonsense, true);
} else {
logger.warn("更新失败未找到ID为{}的随机内容", id);
return new ResponseMessage<>(404, "未找到指定随机内容", null, false);
}
} catch (DataAccessException e) {
logger.error("更新随机内容失败ID: {}", id, e);
return new ResponseMessage<>(500, "数据库操作异常", null, false);
} catch (Exception e) {
logger.error("更新随机内容失败ID: {}", id, e);
return new ResponseMessage<>(500, "服务器内部错误", null, false);
}
}
@Override
@Transactional
public ResponseMessage<Boolean> deleteNonsense(Integer id) {
try {
if (nonsenseRepository.existsById(id)) {
nonsenseRepository.deleteById(id);
logger.info("删除随机内容成功ID: {}", id);
return new ResponseMessage<>(200, "删除成功", true, true);
} else {
logger.warn("删除失败未找到ID为{}的随机内容", id);
return new ResponseMessage<>(404, "未找到指定随机内容", false, false);
}
} catch (DataAccessException e) {
logger.error("删除随机内容失败ID: {}", id, e);
return new ResponseMessage<>(500, "数据库操作异常", false, false);
} catch (Exception e) {
logger.error("删除随机内容失败ID: {}", id, e);
return new ResponseMessage<>(500, "服务器内部错误", false, false);
}
}
}

View File

@@ -7,6 +7,11 @@ import com.qf.myafterprojecy.pojo.dto.CategoryAttributeDto;
import java.util.List;
public interface ICategoryAttributeService {
/**
* 获取全部分类属性
* @return 所有分类属性列表
*/
ResponseMessage<List<Category_attribute>> getAllCategoryAttributes();
/**
* 根据ID获取分类属性

View File

@@ -0,0 +1,44 @@
package com.qf.myafterprojecy.service.imp;
import com.qf.myafterprojecy.config.ResponseMessage;
import com.qf.myafterprojecy.pojo.Nonsense;
import com.qf.myafterprojecy.pojo.dto.NonsenseDto;
import java.util.List;
public interface INonsenseService {
/**
* 获取所有随机内容
* @return 随机内容列表
*/
ResponseMessage<List<Nonsense>> getAllNonsense();
/**
* 根据ID获取随机内容
* @param id 随机内容ID
* @return 随机内容
*/
ResponseMessage<Nonsense> getNonsenseById(Integer id);
/**
* 保存随机内容
* @param nonsenseDto 随机内容数据传输对象
* @return 保存结果
*/
ResponseMessage<Nonsense> saveNonsense(NonsenseDto nonsenseDto);
/**
* 更新随机内容
* @param id 随机内容ID
* @param nonsenseDto 随机内容数据传输对象
* @return 更新结果
*/
ResponseMessage<Nonsense> updateNonsense(Integer id, NonsenseDto nonsenseDto);
/**
* 删除随机内容
* @param id 随机内容ID
* @return 删除结果
*/
ResponseMessage<Boolean> deleteNonsense(Integer id);
}