You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
13 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.aurora.controller;
import com.aurora.annotation.OptLog;
import com.aurora.model.dto.*;
import com.aurora.enums.FilePathEnum;
import com.aurora.service.ArticleService;
import com.aurora.strategy.context.ArticleImportStrategyContext;
import com.aurora.strategy.context.UploadStrategyContext;
import com.aurora.model.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.Valid;
import java.util.List;
import static com.aurora.constant.OptTypeConstant.*;
//APIApplication Programming Interface应用程序编程接口就像是一个软件服务员
// 它定义了一套明确的规则,让不同的软件应用能够安全、高效地相互“对话”和协作,而无需了解对方内部的复杂细节
//使用Swagger注解标记本类为API的"文章模块"分组,方便生成交互式文档
@Api(tags = "文章模块") //类定义,@Api注解来自Swagger用于分组API文档,给API接口添加标签
@RestController //一个REST控制器返回数据而非视图,返回数据通常为JSON格式,结合了@Controller和@ResponseBody用于REST API
public class ArticleController { //每个API方法使用@GetMapping、@PostMapping等对应HTTP方法
//使用依赖注入自动装配ArticleService避免手动实例化推荐构造函数注入但字段注入常见于简单场景
@Autowired //字段注入:@Autowired 用于依赖注入
private ArticleService articleService;
@Autowired
private UploadStrategyContext uploadStrategyContext; // 注入文件上传策略上下文,用于处理文件存储(如文章图片)
@Autowired
private ArticleImportStrategyContext articleImportStrategyContext; // 注入文章导入策略上下文支持多种格式的文章导入如Markdown、Word
// 获取置顶和推荐文章HTTP GET请求路径为/articles/topAndFeatured
@ApiOperation("获取置顶和推荐文章")
@GetMapping("/articles/topAndFeatured")
public ResultVO<TopAndFeaturedArticlesDTO> listTopAndFeaturedArticles() {
return ResultVO.ok(articleService.listTopAndFeaturedArticles());// 调用Service层方法返回统一封装的结果对象ResultVO
}
// 获取所有文章列表(分页卡片形式)
@ApiOperation("获取所有文章")
@GetMapping("/articles/all")
//返回值是ResultVO<PageResultDTO<ArticleCardDTO>>其中ResultVO是统一的返回结果包装类
//PageResultDTO是分页结果的封装类ArticleCardDTO是文章卡片形式的数据传输对象只包含文章列表展示需要的信息比如标题、简介
public ResultVO<PageResultDTO<ArticleCardDTO>> listArticles() {
return ResultVO.ok(articleService.listArticles());
}
// 根据分类ID查询文章使用@RequestParam接收URL查询参数如?categoryId=1
@ApiOperation("根据分类id获取文章")
@GetMapping("/articles/categoryId")
public ResultVO<PageResultDTO<ArticleCardDTO>> getArticlesByCategoryId(@RequestParam Integer categoryId) {
//@RequestParam用来接收URL查询参数就是URL中后面的参数如果@RequestParam后没写参数名默认会匹配和方法名参数一致的查询参数
return ResultVO.ok(articleService.listArticlesByCategoryId(categoryId));
//PageResultDTO<ArticleCardDTO>为分页文章卡片数据
}
// 根据文章ID获取详情使用@PathVariable从URL路径中提取参数如/articles/1
@ApiOperation("根据id获取文章") //是Swagger相关的注解用来给接口添加说明方便生成接口文档让开发、测试人员查看
@GetMapping("/articles/{articleId}")
//@GetMapping表示这是一个处理GET请求的接口接口路径为/articles/{articleId}
//其中{articleId}是一个路径参数占位符比如请求/articles/1时1就会作为articleId的值
public ResultVO<ArticleDTO> getArticleById(@PathVariable("articleId") Integer articleId) {
//@PathVariable("articleId"):用于从URL路径中提取和占位符所对应的参数把它赋值给方法参数Integer articleId
return ResultVO.ok(articleService.getArticleById(articleId));
//调用articleService业务对象的getArticleById方法传入获取到的articleId来查询文章详情
//最后用ResultVO.ok()把查询到的ArticleDTO文章数据传输对象包装成统一的返回结果并返回
}
// 校验文章访问密码:@RequestBody接收JSON格式的密码对象
@ApiOperation("校验文章访问密码")
@PostMapping("/articles/access")//处理post请求的接口。请求路径为/articles/accesspost请求更适合传递密码这类私密数据
public ResultVO<?> accessArticle(@Valid @RequestBody ArticlePasswordVO articlePasswordVO) {
// @Valid触发参数校验确保ArticlePasswordVO对象中的参数符合约束如非空密码格式必填
//@RequestBody表示把请求体RequestBody中的JSON数据转换为ArticlePasswordVO类型的对象articlePasswordVO
//调用业务对象articleService的accessArticle方法传入密码参数对象进行校验校验完成后通过ResultVO.ok()返回成功的统一结果
articleService.accessArticle(articlePasswordVO);
return ResultVO.ok();// 返回空结果表示成功
}
@ApiOperation("根据标签id获取文章")
@GetMapping("/articles/tagId")
public ResultVO<PageResultDTO<ArticleCardDTO>> listArticlesByTagId(@RequestParam Integer tagId) {
return ResultVO.ok(articleService.listArticlesByTagId(tagId));
}
@ApiOperation("获取所有文章归档") //获取文章归档列表(按时间分组)
@GetMapping("/archives/all") //无参数
public ResultVO<PageResultDTO<ArchiveDTO>> listArchives() {
//<ArchiveDTO>是文章归档的数据传输对象(包含年月,对应的文章数量等信息)
return ResultVO.ok(articleService.listArchives());
}
@ApiOperation("获取后台文章")
@GetMapping("/admin/articles") //路径带/admin说明是后台接口通常需要权限
public ResultVO<PageResultDTO<ArticleAdminDTO>> listArticlesAdmin(ConditionVO conditionVO) {
//ConditionVO conditionVO是用来传递查询条件比如文章标题、状态等筛选条件是一个条件封装的VOValue Object,值对象)类
//ArticleAdminDTO是后台文章的数据传输对象会包含更多的管理相关的信息
return ResultVO.ok(articleService.listArticlesAdmin(conditionVO));
}
// 保存或更新文章:@RequestBody接收文章数据@Valid触发校验
@OptLog(optType = SAVE_OR_UPDATE) //项目里自定义注解,记录操作日志(如保存/更新),作用是自动记录该接口的操作日志
@ApiOperation("保存和修改文章")
@PostMapping("/admin/articles")
public ResultVO<?> saveOrUpdateArticle(@Valid @RequestBody ArticleVO articleVO) {
//@Valid触发对ArticleVO对象的参数校验比如文章标题不为空内容长度是否符合要求等需要在ArticleVO的属性上配置@NotBlank、@Length等校验注解
//@RequestBody将前端传递到请求体JSON形式的文章数据转换成ArticleVO类型的对象articleVO
articleService.saveOrUpdateArticle(articleVO);
return ResultVO.ok();
}
@OptLog(optType = UPDATE)
@ApiOperation("修改文章是否置顶和推荐")
@PutMapping("/admin/articles/topAndFeatured") //处理PUT请求的后台接口PUT常用于更新数据
public ResultVO<?> updateArticleTopAndFeatured(@Valid @RequestBody ArticleTopFeaturedVO articleTopFeaturedVO) {
//@RequestBody将请求体中JSON格式的“文章ID+置顶状态+推荐状态”数据转换成ArticleTopFeaturedVO类型的对象articleTopFeaturedVO
articleService.updateArticleTopAndFeatured(articleTopFeaturedVO);
return ResultVO.ok();
}
// 逻辑删除或恢复文章(通过更新状态字段而非物理删除),不是从数据库删除,而是通过修改文章的“状态字段”
@ApiOperation("删除或者恢复文章")
@PutMapping("/admin/articles")
public ResultVO<?> updateArticleDelete(@Valid @RequestBody DeleteVO deleteVO) {
articleService.updateArticleDelete(deleteVO);
return ResultVO.ok();
}
//直接从数据库删除文章,无法恢复
@OptLog(optType = DELETE)
@ApiOperation(value = "物理删除文章")
@DeleteMapping("/admin/articles/delete") //处理DELETE请求的后台接口DELETE请求专门用于删除类操作
public ResultVO<?> deleteArticles(@RequestBody List<Integer> articleIds) {
//@RequestBody:将请求体中JSON形式的文章ID列表List<Integer> articleIds转换成相应的集合对象比如前端传递[1,2,3]就会对应删除ID为12,3的文章
articleService.deleteArticles(articleIds);
return ResultVO.ok();
}
// 上传文章图片MultipartFile接收文件返回图片访问路径
@OptLog(optType = UPLOAD) //表示“上传”类型的操作,用来自动记录“上传文章图片”的操作日志
@ApiOperation("上传文章图片")
@ApiImplicitParam(name = "file", value = "文章图片", required = true, dataType = "MultipartFile")
// 给Swagger文档补充参数说明参数名file含义是“文章图片”为必填项数据类型为MultipartFileSpring中专门用来接收上传文件的类型
@PostMapping("/admin/articles/images")
public ResultVO<String> saveArticleImages(MultipartFile file) {
// 通过策略上下文上传文件FilePathEnum指定存储路径
//参数MultipartFile接受前端上传的图片文件
//返回值ResultVO<String>:返回图片的访问路径(字符串形式,比如/upload/artic;e/202505/123.jpg)
return ResultVO.ok(uploadStrategyContext.executeUploadStrategy(file, FilePathEnum.ARTICLE.getPath()));
}
// 后台根据文章ID获取详情可能包含敏感字段
@ApiOperation("根据id查看后台文章")
@ApiImplicitParam(name = "articleId", value = "文章id", required = true, dataType = "Integer")
@GetMapping("/admin/articles/{articleId}")//{articleId}为路径参数比如查询ID为。。的文章
public ResultVO<ArticleAdminViewDTO> getArticleBackById(@PathVariable("articleId") Integer articleId) {
//参数@PathVariable将URL路径中{articleId}对应的数值转换成Integer类型的参数articleId
//ArticleAdminViewDTO是后台文章详情的数据传输对象包含文章的完整信息含敏感字段
return ResultVO.ok(articleService.getArticleByIdAdmin(articleId));
}
// 导入文章:文件+类型参数,支持多种格式
@OptLog(optType = UPLOAD)
@ApiOperation(value = "导入文章")
@PostMapping("/admin/articles/import")
public ResultVO<?> importArticles(MultipartFile file, @RequestParam(required = false) String type) {
//参数MultipartFile接受前端上传的文章导入文件各种格式
//@RequestParam(required = false) String type接受文件类型参数required=false表示类型参数可选不传则默认形式
articleImportStrategyContext.importArticles(file, type);
return ResultVO.ok();
}
// 导出文章返回导出文件的路径或ID列表
@OptLog(optType = EXPORT) //表示这是“导出”类型的操作,用来记录“到处文章”的操作日志
@ApiOperation(value = "导出文章")
@ApiImplicitParam(name = "articleIdList", value = "文章id", required = true, dataType = "List<Integer>")
//value为必填项数据类型List<Integer>文章ID的集合
@PostMapping("/admin/articles/export")//导出操作需传递文章ID列表用POST请求更适合传递集合类参数
public ResultVO<List<String>> exportArticles(@RequestBody List<Integer> articleIds) {
//@RequestBody将请求体中JSON形式的文章ID列表转换成List<Integer>类型的参数articleIds
return ResultVO.ok(articleService.exportArticles(articleIds));
//调用业务层articleService.exportArticles(articleIds)执行文章导出操作,导出完成后返回文件路径/ID列表的统一结果
}
// 搜索文章接口通过ConditionVO封装搜索条件如关键词、分类、发布时间范围等
@ApiOperation(value = "搜索文章")
@GetMapping("/articles/search")
public ResultVO<List<ArticleSearchDTO>> listArticlesBySearch(ConditionVO condition) {
//ConditionVO condition接收前端传递的搜索条件
//如果是GET请求条件会以查询参数的形式传递比如/articles/search?keyword=春天&pageNum=1Spring会自动把查询参数匹配到ConditionVO的属性上
//ArticleSearchDTO是搜索结果的展示类只包含标题、简介、发布时间等搜索结果需要的信息
return ResultVO.ok(articleService.listArticlesBySearch(condition));
}
}