配置 CKEditor 主要涉及两个部分:

- 前端配置:在 JSP/HTML 页面中引入 CKEditor 并进行初始化和个性化设置。
- 后端交互:Java 后端如何处理 CKEditor 的数据(读取、保存、上传文件等)。
下面我将分步详细讲解如何进行配置,并提供一个完整的示例。
第一步:准备 CKEditor 文件
你需要下载 CKEditor 的文件,推荐使用官方 CDN 或通过 npm/yarn 安装,但对于简单的 Java Web 项目,直接下载文件最方便。
- 访问 CKEditor 官网:https://ckeditor.com/ckeditor-5/
- 选择版本和构建:
- 选择 CKEditor 5(当前主流版本)。
- 选择 "Classic editor"(经典编辑器,类似 Word)。
- 选择 "Download" 下载打包好的文件。
- 解压并放置文件:
将下载的
ckeditor文件夹解压,并放置在你的 Java Web 项目的webapp目录下,放在webapp/ckeditor/目录里。
你的项目结构大概会是这样:
your-webapp/
├── src/
│ └── main/
│ ├── java/
│ ├── resources/
│ └── webapp/
│ ├── WEB-INF/
│ ├── index.jsp
│ └── ckeditor/ <-- CKEditor 文件夹
│ ├── adapters/
│ ├── build/
│ ├── lang/
│ ├── samples/
│ └── ...
└── pom.xml
第二步:前端配置(在 JSP 页面中集成)
我们需要在 JSP 页面中引入 CKEditor 的 CSS 和 JS 文件,并初始化编辑器。

创建一个简单的 JSP 页面 (index.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">CKEditor Java 配置示例</title>
<!-- 1. 引入 CKEditor 的样式文件 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/ckeditor/ckeditor5.css">
</head>
<body>
<h1>CKEditor 5 配置示例</h1>
<form action="save-content" method="post">
<!-- 2. 创建一个 textarea 作为编辑器的容器 -->
<!-- id 属性非常重要,用于初始化编辑器 -->
<textarea name="editorContent" id="editor">
<p>这里是 CKEditor 的初始内容。</p>
<p>你可以在 Java 后端通过 request.getParameter("editorContent") 来获取这里的 HTML 内容。</p>
</textarea>
<button type="submit">保存内容</button>
</form>
<!-- 3. 引入 CKEditor 核心脚本文件 -->
<!-- 注意:使用绝对路径或 contextPath -->
<script src="${pageContext.request.contextPath}/ckeditor/ckeditor.js"></script>
<!-- 4. 初始化编辑器 -->
<script>
// ClassicEditor.create() 返回一个 Promise
ClassicEditor
.create(document.querySelector('#editor'), {
// 在这里进行你的个性化配置
toolbar: {
items: [
'heading', '|',
'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|',
'outdent', 'indent', '|',
'blockQuote', 'insertTable', 'undo', 'redo'
]
},
language: 'zh-cn' // 设置语言为中文
})
.then(editor => {
console.log('编辑器已初始化', editor);
// 你可以在这里保存 editor 实例,以便后续操作
window.myEditor = editor;
})
.catch(error => {
console.error('初始化编辑器时发生错误', error);
});
</script>
</body>
</html>
关键点解释:
<textarea>: CKEditor 5 会将这个textarea替换成一个功能完整的编辑器。name属性用于表单提交,id属性用于 JS 初始化。ckeditor.js: 这是 CKEditor 5 的核心脚本文件。ClassicEditor.create(): 这是初始化经典编辑器的核心方法。- 配置对象 : 第二个参数是一个配置对象,你可以在这里自定义编辑器的行为,比如工具栏、插件、语言等。
第三步:后端配置(Java Servlet 处理)
当用户在编辑器中输入内容并点击“保存”按钮后,表单数据会被发送到 action="save-content" 指定的地址,我们需要一个 Java Servlet 来接收和处理这些数据。
创建一个 Servlet (ContentSaveServlet.java)
package com.example.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/save-content")
public class ContentSaveServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 设置请求和响应的字符编码,防止中文乱码
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8");
// 2. 从请求中获取 CKEditor 提交的内容
// 这个 "editorContent" 必须与 JSP 中 textarea 的 name 属性一致
String editorContent = request.getParameter("editorContent");
// 3. 在实际应用中,你会将这个内容保存到数据库
// contentService.saveContentToDatabase(editorContent);
System.out.println("从 CKEditor 获取到的内容是:");
System.out.println(editorContent);
// 4. 向客户端返回一个简单的成功消息
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>保存成功</title></head>");
out.println("<body>");
out.println("<h1>内容已成功保存!</h1>");
out.println("<p>返回的 HTML 内容长度: " + editorContent.length() + " 字符。</p>");
out.println("<a href='index.jsp'>返回编辑器</a>");
out.println("</body>");
out.println("</html>");
}
}
关键点解释:
@WebServlet("/save-content"): 这是 Servlet 3.0+ 的注解,用于将这个类映射到/save-contentURL。request.setCharacterEncoding("UTF-8"): 非常重要! 这行代码确保了从请求中读取的参数(包含中文的 HTML 内容)不会被乱码。request.getParameter("editorContent"): 通过name属性获取编辑器中的 HTML 字符串。- 业务逻辑:
System.out.println只是演示,真实项目中你需要调用 Service 层,将editorContent保存到数据库。
第四步:高级配置(文件上传)
富文本编辑器通常需要支持图片上传,CKEditor 5 的文件上传功能需要后端提供一个 API 接口。

修改 JSP 配置,添加上传适配器
在 index.jsp 的初始化脚本中,你需要配置一个文件上传处理器。
// 在 index.jsp 的 <script> 标签内修改初始化代码
ClassicEditor
.create(document.querySelector('#editor'), {
// ... 其他配置 ...
// 添加文件上传功能
ckfinder: {
// 上传文件的 URL,指向你的后端上传 Servlet
uploadUrl: '${pageContext.request.contextPath}/upload-image'
}
})
.then(editor => {
console.log('编辑器已初始化', editor);
})
.catch(error => {
console.error('初始化编辑器时发生错误', error);
});
创建文件上传 Servlet (ImageUploadServlet.java)
这个 Servlet 需要接收上传的图片文件,将其保存到服务器,并返回一个 CKEditor 5 能识别的 JSON 响应。
package com.example.servlet;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
@WebServlet("/upload-image")
@MultipartConfig // 必须使用此注解来处理文件上传
public class ImageUploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 定义上传文件在服务器上存放的目录
private static final String UPLOAD_DIR = "uploads";
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1. 确保上传目录存在
String applicationPath = getServletContext().getRealPath("");
String uploadFilePath = applicationPath + File.separator + UPLOAD_DIR;
File uploadDir = new File(uploadFilePath);
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
// 2. 获取上传的文件部分
Part filePart = request.getPart("upload"); // CKEditor 默认使用 'upload' 作为文件字段的 name
String fileName = getFileName(filePart);
// 3. 生成唯一文件名,防止覆盖
String uniqueFileName = UUID.randomUUID().toString() + "-" + fileName;
String fullPath = uploadFilePath + File.separator + uniqueFileName;
// 4. 将文件写入服务器
filePart.write(fullPath);
// 5. 构造并返回 CKEditor 5 所需的 JSON 响应
// CKEditor 5 需要特定的格式
String fileUrl = request.getContextPath() + "/" + UPLOAD_DIR + "/" + uniqueFileName;
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.println("{");
out.println(" \"uploaded\": 1,");
out.println(" \"fileName\": \"" + fileName + "\",");
out.println(" \"url\": \"" + fileUrl + "\"");
out.println("}");
System.out.println("图片已上传: " + fullPath);
System.out.println("可访问的 URL: " + fileUrl);
}
// 辅助方法:从 Part 对象中获取文件名
private String getFileName(final Part part) {
final String partHeader = part.getHeader("content-disposition");
for (String content : partHeader.split(";")) {
if (content.trim().startsWith("filename")) {
return content.substring(content.indexOf('=') + 1).trim().replace("\"", "");
}
}
return null;
}
}
关键点解释:
@MultipartConfig: 必须添加,否则request.getPart()会抛出异常。request.getPart("upload"): CKEditor 5 在上传文件时,默认使用upload作为表单字段的name。- JSON 响应格式: CKEditor 5 期望一个非常严格的 JSON 格式来确认上传成功并获取图片的 URL,格式错误会导致上传失败。
- 文件路径: 使用
getServletContext().getRealPath("")获取 Web 应用的根路径,然后拼接出上传目录的完整路径。注意:在真实项目中,你需要考虑文件存储策略,比如使用云存储(如阿里云 OSS、AWS S3)而不是本地服务器磁盘。
总结与最佳实践
- 前后端分离:现代 Java Web 项目(特别是 Spring Boot)更倾向于前后端分离,前端是一个独立的项目(如 Vue, React),通过 API 与后端 Java 服务交互,CKEditor 配置在前端项目中,后端只提供 RESTful API(如
/api/content,/api/upload)。 - 安全性:
- XSS 攻击:从 CKEditor 获取的 HTML 是用户输入,直接存入数据库或显示在页面上有风险,后端在保存和显示时,应该使用经过验证的库(如 OWASP Java HTML Sanitizer)来清理和净化 HTML。
- 文件上传:严格限制上传的文件类型(只允许图片),检查文件内容(MIME type),并对文件名进行随机化处理,防止路径遍历攻击。
- 配置管理:将 CKEditor 的配置(如工具栏、插件列表)放在一个单独的 JS 文件中,而不是内联在 JSP 里,便于维护。
- 使用官方文档:CKEditor 5 的配置非常灵活,官方文档是最好的参考资料,请查阅:CKEditor 5 Documentation。
通过以上步骤,你就可以在 Java 项目中成功配置并使用 CKEditor 5 了,从基本集成到文件上传,涵盖了最常见的使用场景。
