- 后端 (Java):负责处理文件上传、提供配置、管理会话等。
- 前端 (HTML/JavaScript):负责实例化和渲染 CKEditor 编辑器。
下面我将为你提供一个详细、分步的指南,涵盖从基础配置到高级功能(如文件上传)的完整流程。

第一步:添加 CKEditor 依赖
你需要将 CKEditor 5 添加到你的项目中,CKEditor 5 有两种主要形式:经典版(ClassicEditor)和InlineEditor(内联编辑),这里我们以最常用的 ClassicEditor 为例。
通过 CDN 引入 (最简单的方式)
这种方式适用于快速原型开发或简单的 Web 项目,你只需要在 HTML 页面中引入 CKEditor 的 JavaScript 和 CSS 文件即可。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">CKEditor 示例</title>
<!-- 引入 CKEditor 5 样式 -->
<link rel="stylesheet" href="https://cdn.ckeditor.com/ckeditor5/39.0.1/ckeditor5.css">
</head>
<body>
<h1>CKEditor 5 演示</h1>
<div id="editor">
<p>在这里输入一些初始内容...</p>
</div>
<!-- 引入 CKEditor 5 核心 JavaScript -->
<script src="https://cdn.ckeditor.com/ckeditor5/39.0.1/ckeditor5.js"></script>
<script>
// 使用 ClassicEditor 创建编辑器实例
ClassicEditor
.create(document.querySelector('#editor'), {
// 在这里配置你的编辑器
language: 'zh-cn' // 设置语言为中文
})
.then(editor => {
console.log('编辑器已初始化', editor);
})
.catch(error => {
console.error('初始化编辑器时发生错误', error);
});
</script>
</body>
</html>
通过 npm/yarn 安装 (适用于现代前端项目)
如果你的项目是使用 Maven/Gradle 构建的,并且前端部分是分离的(使用 Vue, React, 或 Webpack),推荐使用 npm/yarn 安装。
# 安装 CKEditor 5 经典编辑器 npm install @ckeditor/ckeditor5-build-classic
然后在你的 JavaScript 模块中引入:

import ClassicEditor from '@ckeditor/ckeditor5-build-classic'; // ... 然后使用上面的 create 方法
第二步:基础配置
CKEditor 的配置是通过一个 config 对象传递给 create() 方法的,以下是一些最常用的配置项。
ClassicEditor
.create(document.querySelector('#editor'), {
// --- 基础配置 ---
language: 'zh-cn', // 设置语言
toolbar: {
items: [
'heading', '|',
'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|',
'outdent', 'indent', '|',
'blockQuote', 'insertTable', 'undo', 'redo'
]
},
// --- 高级配置 ---
// 移除不需要的插件
removePlugins: [
'EasyImage', // 如果你不需要自动图片上传
'MediaEmbed' // 如果你不需要嵌入媒体
],
// 自定义标题格式
heading: {
options: [
{ model: 'paragraph', title: '段落', class: 'ck-heading_paragraph' },
{ model: 'heading1', view: 'h1', title: '标题 1', class: 'ck-heading_heading1' },
{ model: 'heading2', view: 'h2', title: '标题 2', class: 'ck-heading_heading2' },
{ model: 'heading3', view: 'h3', title: '标题 3', class: 'ck-heading_heading3' }
]
}
})
.then(editor => {
// 你可以在这里保存编辑器实例,以便后续使用
window.myEditor = editor;
})
.catch(error => {
console.error(error);
});
配置说明:
language: 设置编辑器语言,CKEditor 5 内置了多种语言,包括zh-cn。toolbar: 自定义工具栏,你可以通过增减items数组中的元素来控制显示哪些按钮,完整的工具栏项列表可以查阅 CKEditor 5 官方文档。removePlugins: 从构建中移除插件,可以减小最终文件的大小。heading: 自定义标题样式,可以定义哪些级别的标题可用。
第三步:Java 后端集成 (核心部分)
当用户点击“保存”按钮时,你需要从编辑器获取内容,并将其发送到 Java 后端进行处理。
从编辑器获取内容
在保存按钮的点击事件中,调用编辑器实例的 getData() 方法。

<button id="saveButton">保存内容</button>
<script>
ClassicEditor.create(document.querySelector('#editor'))
.then(editor => {
const saveButton = document.getElementById('saveButton');
saveButton.addEventListener('click', () => {
// 获取编辑器中的 HTML 内容
const data = editor.getData();
console.log('编辑器内容:', data);
// 发送到后端
saveContentToServer(data);
});
});
function saveContentToServer(content) {
fetch('/api/save-content', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ htmlContent: content })
})
.then(response => response.json())
.then(data => {
alert('保存成功!');
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
alert('保存失败!');
});
}
</script>
Java 后端接收和处理
这里我们使用 Spring Boot 作为后端框架示例,因为它非常流行且易于使用。
控制器类 (ContentController.java)
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
@RestController
@RequestMapping("/api")
public class ContentController {
// 模拟一个服务层来处理数据持久化
private final ContentService contentService;
public ContentController(ContentService contentService) {
this.contentService = contentService;
}
@PostMapping("/save-content")
public ResponseEntity<String> saveContent(@RequestBody ContentRequest request) {
// 1. 从请求体中获取 HTML 内容
String htmlContent = request.getHtmlContent();
// 2. 对 HTML 内容进行安全处理 (非常重要!)
// 防止 XSS (跨站脚本攻击) 攻击
String sanitizedContent = sanitizeHtml(htmlContent);
// 3. 保存到数据库或文件
// 这里我们调用服务层来处理
contentService.save(sanitizedContent);
// 4. 返回成功响应
return ResponseEntity.ok("内容保存成功!");
}
/**
* 使用 OWASP Java HTML Sanitizer 清理 HTML 内容
* 这是一个关键的安全步骤,防止用户输入恶意脚本。
*/
private String sanitizeHtml(String html) {
// 你需要添加 OWASP 依赖: org.owasp.html:html-sanitizer
// 实际项目中应该使用成熟的库,这里仅为示意
return html; // 在实际应用中,这里应该进行清理
}
}
// 请求体 DTO
class ContentRequest {
private String htmlContent;
// Getters and Setters
public String getHtmlContent() {
return htmlContent;
}
public void setHtmlContent(String htmlContent) {
this.htmlContent = htmlContent;
}
}
// 服务层接口
interface ContentService {
void save(String content);
}
// 服务层实现
class ContentServiceImpl implements ContentService {
@Override
public void save(String content) {
// 这里实现将 content 保存到数据库的逻辑
System.out.println("正在保存内容到数据库: " + content.substring(0, 50) + "...");
// e.g., contentRepository.save(new ContentEntity(content));
}
}
安全警告:永远不要直接将用户提交的 HTML 内容存储或显示在页面上而不进行任何处理,这会导致严重的 XSS 安全漏洞,请使用专门的安全库来清理 HTML,OWASP Java HTML Sanitizer。
第四步:配置文件上传
CKEditor 5 的文件上传功能通常通过插件实现,最常用的是 EasyImage 或 FileRepository,这里我们展示如何配置一个自定义的上传接口。
修改 CKEditor 配置
在 create() 方法的配置对象中,添加 fileRepository 的上传配置。
ClassicEditor
.create(document.querySelector('#editor'), {
// ... 其他配置
// 配置文件上传
simpleUpload: {
// 上传的 URL,指向你的 Java 后端接口
uploadUrl: '/api/upload-image',
// 请求头,如果需要认证
headers: {
'X-CSRF-Token': 'CSRF_TOKEN_VALUE' // 如果你的应用使用 CSRF 保护
},
// 可选:自定义上传响应的解析方式
// 默认情况下,CKEditor 期望一个包含 { url: "..." } 的 JSON 响应
responseUrl: (response) => {
// 假设你的后端返回格式是 { "code": 0, "msg": "success", "data": { "url": "/path/to/image.jpg" } }
return response.data.url;
}
}
})
.then(editor => { /* ... */ });
Java 后端实现上传接口
创建一个新的控制器方法来处理文件上传。
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.http.ResponseEntity;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
@RestController
@RequestMapping("/api")
public class FileUploadController {
// 定义上传文件的目录
private static final String UPLOADED_FOLDER = "/var/www/uploads/"; // 在实际应用中,使用配置文件管理
@PostMapping("/upload-image")
public ResponseEntity<?> uploadImage(@RequestParam("upload") MultipartFile file) {
try {
if (file.isEmpty()) {
return ResponseEntity.badRequest().body("请选择一个文件上传。");
}
// 生成唯一的文件名,防止文件名冲突
String originalFilename = file.getOriginalFilename();
String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
String newFilename = UUID.randomUUID().toString() + fileExtension;
// 构建目标文件路径
Path destinationFile = Paths.get(UPLOADED_FOLDER).resolve(newFilename);
// 确保目录存在
Files.createDirectories(destinationFile.getParent());
// 保存文件
Files.copy(file.getInputStream(), destinationFile);
// 返回 CKEditor 5 期望的 JSON 格式
// { "url": "http://your-domain.com/uploads/newFilename.jpg" }
String fileUrl = "http://your-domain.com/uploads/" + newFilename; // 替换为你的实际域名
return ResponseEntity.ok().body("{\"url\": \"" + fileUrl + "\"}");
} catch (IOException e) {
e.printStackTrace();
return ResponseEntity.status(500).body("文件上传失败: " + e.getMessage());
}
}
}
注意:
- 你需要在 Spring Boot 项目中添加对
commons-fileupload或spring-boot-starter-web中内置的文件上传支持的支持。spring-boot-starter-web默认已经包含了。 - 确保你的应用有权限在
UPLOADED_FOLDER目录下创建和写入文件。 - 在生产环境中,你需要考虑文件大小限制、文件类型白名单、病毒扫描等安全措施。
总结与最佳实践
- 分离前后端:前端负责 UI 和交互,后端负责业务逻辑和数据持久化,通过 RESTful API 进行通信。
- 安全第一:
- XSS 防护:后端在保存和显示富文本内容时,必须使用 HTML Sanitizer 对其进行清理。
- CSRF 防护:如果你的应用使用 Session,确保对表单提交(包括文件上传)进行 CSRF 保护。
- 文件上传安全:限制文件类型、大小,使用随机文件名,并对上传的文件进行病毒扫描。
- 模块化配置:不要在 HTML 中硬编码所有配置,可以将配置放在一个单独的
.js文件中,或者从后端动态获取配置。 - 利用官方文档:CKEditor 5 官方文档 是最权威的参考资料,包含了所有配置项和插件的详细说明。
通过以上步骤,你就可以在 Java 项目中成功集成并配置 CKEditor 5 了,从简单的文本编辑到复杂的富文本内容和文件管理,CKEditor 5 都提供了强大的支持。
