============= 后端_发布文章 ============= 1 实体类 1.1 文章标签关联实体类 /ysdblog-api/src/main/java/com/weihome/ysdblog/dao/pojo/ArticleTag.java: @Data public class ArticleTag { private Long id; private Long articleId; private Long tagId; } 2 数据访问接口 2.1 文章标签关联数据访问接口 /ysdblog-api/src/main/java/com/weihome/ysdblog/dao/mapper/ArticleTagMapper.java: public interface ArticleTagMapper extends BaseMapper { } 3 视图对象 3.1 内容参数视图对象 /ysdblog-api/src/main/java/com/weihome/ysdblog/vo/param/ContentParam.java: @Data public class ContentParam { private String content; private String contentHtml; } 3.2 文章参数视图对象 /ysdblog-api/src/main/java/com/weihome/ysdblog/vo/param/ArticleParam.java: @Data public class ArticleParam { private Long id; private String title; private ContentParam contentParam; private String summary; private CategoryVo category; private List tags; } 4 内容服务 4.1 内容服务接口 /ysdblog-api/src/main/java/com/weihome/ysdblog/service/ContentService.java: public interface ContentService { ... /** * 添加内容 */ public Long add(ContentParam contentParam, Long articleId); ... } 4.2 内容服务实现 /ysdblog-api/src/main/java/com/weihome/ysdblog/service/impl/ContentServiceImpl.java: ... public class ContentServiceImpl implements ContentService { ... @Override public Long add(ContentParam contentParam, Long articleId) { Content content = new Content(); BeanUtils.copyProperties(contentParam, content); content.setArticleId(articleId); contentMapper.insert(content); return content.getId(); } ... } 5 文章标签关联服务 5.1 文章标签关联服务接口 /ysdblog-api/src/main/java/com/weihome/ysdblog/service/ArticleTagService.java: public interface ArticleTagService { /** * 添加文章标签关联 */ public void add(Long articleId, Long tagId); } 5.2 文章标签关联服务实现 /ysdblog-api/src/main/java/com/weihome/ysdblog/service/impl/ArticleTagServiceImpl.java: @Service public class ArticleTagServiceImpl implements ArticleTagService { @Autowired private ArticleTagMapper articleTagMapper; @Override public void add(Long articleId, Long tagId) { ArticleTag articleTag = new ArticleTag(); articleTag.setArticleId(articleId); articleTag.setTagId(tagId); articleTagMapper.insert(articleTag); } } 6 文章服务 6.1 文章服务接口 /ysdblog-api/src/main/java/com/weihome/ysdblog/service/ArticleService.java: public interface ArticleService { ... /** * 发布文章 */ public Result publish(ArticleParam articleParam); ... } 6.2 文章服务实现 /ysdblog-api/src/main/java/com/weihome/ysdblog/service/impl/ArticleServiceImpl.java: ... public class ArticleServiceImpl implements ArticleService { ... @Autowired private ArticleTagService articleTagService; ... @Override @Transactional public Result publish(ArticleParam articleParam) { // 在文章表中插入文件记录并获得文章ID Article article = new Article(); article.setCommentCount(0); article.setCreateDate(System.currentTimeMillis()); article.setSummary(articleParam.getSummary()); article.setTitle(articleParam.getTitle()); article.setViewCount(0); article.setWeight(0); article.setAuthorId(UserThreadLocal.get().getId()); article.setCategoryId(articleParam.getCategory().getId()); articleMapper.insert(article); Long articleId = article.getId(); // 在内容表中插入内容记录并获得内容ID // 将内容ID更新到刚刚插入的文章记录中 Long contentId = contentService.add( articleParam.getContentParam(), articleId); article.setContentId(contentId); articleMapper.updateById(article); // 如有标签,则将其插入文章标签关联表 List tags = articleParam.getTags(); if (tags != null) for (TagVo tag: tags) articleTagService.add(articleId, tag.getId()); // 返回文章ID(采用字符串避免损失精度) Map data = new HashMap<>(); data.put("id", articleId.toString()); return Result.success(data); } ... } 通过Transactional注解启用事务,避免因发生错误导致多个表中的数据不一致。 7 文章控制器 /ysdblog-api/src/main/java/com/weihome/ysdblog/controller/ArticleController.java: ... public class ArticleController { ... /** * 发布文章 */ @PostMapping("publish") public Result publish(@RequestBody ArticleParam articleParam) { return articleService.publish(articleParam); } ... } 8 添加登录拦截 /ysdblog-api/src/main/java/com/weihome/ysdblog/config/WebMvcConfig.java: ... public class WebMvcConfig implements WebMvcConfigurer { ... @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor) ... .addPathPatterns("/article/publish") ... } ... } 9 运行测试 Postman POST localhost:8888/article/publish Headers Authorization: eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDk2ODEyNzYsInVzZXJJZCI6MSwiaWF0IjoxNjQ4NzkyMjQzfQ.Ba9co3QLNvRJ3k2aYAN9zVvDliLl0KBTtTBfz1UkOgU Body { "id": "", "title": "title_a", "contentParam": { "content": "content_a", "contentHtml": "content_html_a" }, "summary": "summary_a", "category": { "id": "1", "avatar": "category_a.png", "categoryName": "category_a" }, "tags": [ { "id": "1", "tagName": "tag_a" }, { "id": "2", "tagName": "tag_b" } ] } --------------------------------------- { "success": true, "code": 200, "msg": "success", "data": { "id": "1510091381639589889" } } 检查数据库中t_article、t_content和t_article_tag表中的新增记录。