博客文章编辑功能需要同时处理前端交互、后端逻辑和数据存储三个层面的需求,在Java技术栈中通常会结合Spring Boot框架和主流富文本编辑器来实现。整个功能的核心目标是让用户能够便捷地撰写、修改、保存文章,同时保证内容的完整性和格式的正确性。

功能需求梳理
一个基础的博客编辑功能需要包含以下几个核心能力:
- 支持富文本格式编辑,包括加粗、斜体、标题、列表、图片插入等
- 文章的创建、保存草稿、发布、修改操作
- 文章封面图、分类、标签等元数据的编辑
- 编辑内容的实时自动保存,避免意外丢失
- 图片上传并插入到编辑内容中
数据库表设计
首先需要设计文章表来存储编辑后的内容,基础的表结构如下:
CREATE TABLE `blog_article` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '文章ID', `title` varchar(200) NOT NULL COMMENT '文章标题', `content` longtext NOT NULL COMMENT '文章内容(富文本HTML)', `cover_image` varchar(500) DEFAULT NULL COMMENT '封面图地址', `category_id` bigint(20) DEFAULT NULL COMMENT '分类ID', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态 0草稿 1已发布', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='博客文章表';
后端接口实现
实体类定义
首先定义对应的JPA实体类:
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
@Table(name = "blog_article")
public class BlogArticle {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 200)
private String title;
@Lob
@Column(nullable = false)
private String content;
@Column(name = "cover_image", length = 500)
private String coverImage;
@Column(name = "category_id")
private Long categoryId;
private Integer status = 0; // 0草稿 1已发布
@Column(name = "create_time", updatable = false)
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
@PrePersist
protected void onCreate() {
createTime = LocalDateTime.now();
updateTime = LocalDateTime.now();
}
@PreUpdate
protected void onUpdate() {
updateTime = LocalDateTime.now();
}
// 省略getter和setter方法
}
文章保存与更新接口
编写Controller层接口处理文章的保存和更新请求:
import org.springframework.web.bind.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
@RestController
@RequestMapping("/api/article")
public class ArticleController {
@Autowired
private ArticleService articleService;
/**
* 保存或更新文章
*/
@PostMapping("/save")
public Result saveArticle(@RequestBody ArticleSaveDTO saveDTO) {
Long articleId = articleService.saveOrUpdateArticle(saveDTO);
return Result.success(articleId);
}
/**
* 获取文章详情用于编辑
*/
@GetMapping("/detail/{id}")
public Result getArticleDetail(@PathVariable Long id) {
ArticleDetailVO detailVO = articleService.getArticleDetail(id);
return Result.success(detailVO);
}
}
Service层核心逻辑
import org.springframework.stereotype.Service;
import org.springframework.beans.BeanUtils;
@Service
public class ArticleService {
@Autowired
private ArticleRepository articleRepository;
public Long saveOrUpdateArticle(ArticleSaveDTO saveDTO) {
BlogArticle article;
if (saveDTO.getId() != null) {
// 更新操作
article = articleRepository.findById(saveDTO.getId())
.orElseThrow(() -> new RuntimeException("文章不存在"));
BeanUtils.copyProperties(saveDTO, article, "id", "createTime", "updateTime");
} else {
// 新增操作
article = new BlogArticle();
BeanUtils.copyProperties(saveDTO, article);
article.setStatus(saveDTO.getStatus() != null ? saveDTO.getStatus() : 0);
}
// 保存文章内容
BlogArticle savedArticle = articleRepository.save(article);
return savedArticle.getId();
}
public ArticleDetailVO getArticleDetail(Long id) {
BlogArticle article = articleRepository.findById(id)
.orElseThrow(() -> new RuntimeException("文章不存在"));
ArticleDetailVO vo = new ArticleDetailVO();
BeanUtils.copyProperties(article, vo);
return vo;
}
}
前端编辑页面集成
前端可以使用wangEditor这类轻量富文本编辑器,结合Vue框架实现编辑页面:
<template>
<div class="article-edit-container">
<div class="form-item">
<label>文章标题</label>
<input v-model="articleForm.title" placeholder="请输入文章标题" />
</div>
<div class="form-item">
<label>文章内容</label>
<div id="editor"></div>
</div>
<div class="form-item">
<button @click="saveArticle(0)">保存草稿</button>
<button @click="saveArticle(1)">发布文章</button>
</div>
</div>
</template>
<script>
import WangEditor from 'wangeditor';
import axios from 'axios';
export default {
data() {
return {
articleForm: {
id: null,
title: '',
content: '',
status: 0
},
editor: null
};
},
mounted() {
// 初始化富文本编辑器
this.editor = new WangEditor('#editor');
// 配置图片上传接口
this.editor.config.uploadImgServer = '/api/upload/image';
this.editor.config.uploadFileName = 'file';
this.editor.config.onchange = (html) => {
this.articleForm.content = html;
};
this.editor.create();
// 如果是编辑模式,加载已有文章数据
const articleId = this.$route.query.id;
if (articleId) {
this.loadArticleDetail(articleId);
}
},
methods: {
loadArticleDetail(id) {
axios.get(`/api/article/detail/${id}`).then(res => {
if (res.data.code === 200) {
this.articleForm = res.data.data;
this.editor.txt.html(this.articleForm.content);
}
});
},
saveArticle(status) {
this.articleForm.status = status;
axios.post('/api/article/save', this.articleForm).then(res => {
if (res.data.code === 200) {
alert(status === 0 ? '草稿保存成功' : '文章发布成功');
this.articleForm.id = res.data.data;
}
});
}
}
};
</script>
图片上传处理
富文本中的图片需要单独处理上传接口,避免文章内容过大:
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.UUID;
@RestController
@RequestMapping("/api/upload")
public class UploadController {
// 上传文件存储路径,实际项目中可配置到配置文件中
private static final String UPLOAD_PATH = "/data/blog/upload/";
@PostMapping("/image")
public Result uploadImage(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return Result.error("上传文件不能为空");
}
try {
// 生成唯一文件名
String originalFilename = file.getOriginalFilename();
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
String fileName = UUID.randomUUID().toString() + suffix;
// 保存文件
File destFile = new File(UPLOAD_PATH + fileName);
if (!destFile.getParentFile().exists()) {
destFile.getParentFile().mkdirs();
}
file.transferTo(destFile);
// 返回可访问的图片地址,实际项目中需要配置静态资源映射
String imageUrl = "https://ipipp.com/upload/" + fileName;
return Result.success(imageUrl);
} catch (Exception e) {
return Result.error("图片上传失败:" + e.getMessage());
}
}
}
注意事项
- 富文本内容存储到数据库时需要注意长度限制,建议使用
longtext类型 - 保存内容前可以对HTML内容进行基础过滤,避免XSS攻击
- 自动保存功能可以通过前端定时调用保存接口实现,减少用户内容丢失风险
- 发布文章时可以添加校验逻辑,确保标题和内容不为空
Java博客编辑Spring_Boot富文本编辑后端接口修改时间:2026-06-19 02:27:34