杰瑞科技汇

Java CKEditor如何配置?

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

Java CKEditor如何配置?-图1
(图片来源网络,侵删)
  1. 前端配置:在 JSP/HTML 页面中引入 CKEditor 并进行初始化和个性化设置。
  2. 后端交互:Java 后端如何处理 CKEditor 的数据(读取、保存、上传文件等)。

下面我将分步详细讲解如何进行配置,并提供一个完整的示例。


第一步:准备 CKEditor 文件

你需要下载 CKEditor 的文件,推荐使用官方 CDN 或通过 npm/yarn 安装,但对于简单的 Java Web 项目,直接下载文件最方便。

  1. 访问 CKEditor 官网https://ckeditor.com/ckeditor-5/
  2. 选择版本和构建
    • 选择 CKEditor 5(当前主流版本)。
    • 选择 "Classic editor"(经典编辑器,类似 Word)。
    • 选择 "Download" 下载打包好的文件。
  3. 解压并放置文件: 将下载的 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 文件,并初始化编辑器。

Java CKEditor如何配置?-图2
(图片来源网络,侵删)

创建一个简单的 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-content URL。
  • request.setCharacterEncoding("UTF-8"): 非常重要! 这行代码确保了从请求中读取的参数(包含中文的 HTML 内容)不会被乱码。
  • request.getParameter("editorContent"): 通过 name 属性获取编辑器中的 HTML 字符串。
  • 业务逻辑: System.out.println 只是演示,真实项目中你需要调用 Service 层,将 editorContent 保存到数据库。

第四步:高级配置(文件上传)

富文本编辑器通常需要支持图片上传,CKEditor 5 的文件上传功能需要后端提供一个 API 接口。

Java CKEditor如何配置?-图3
(图片来源网络,侵删)

修改 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)而不是本地服务器磁盘。

总结与最佳实践

  1. 前后端分离:现代 Java Web 项目(特别是 Spring Boot)更倾向于前后端分离,前端是一个独立的项目(如 Vue, React),通过 API 与后端 Java 服务交互,CKEditor 配置在前端项目中,后端只提供 RESTful API(如 /api/content, /api/upload)。
  2. 安全性
    • XSS 攻击:从 CKEditor 获取的 HTML 是用户输入,直接存入数据库或显示在页面上有风险,后端在保存和显示时,应该使用经过验证的库(如 OWASP Java HTML Sanitizer)来清理和净化 HTML。
    • 文件上传:严格限制上传的文件类型(只允许图片),检查文件内容(MIME type),并对文件名进行随机化处理,防止路径遍历攻击。
  3. 配置管理:将 CKEditor 的配置(如工具栏、插件列表)放在一个单独的 JS 文件中,而不是内联在 JSP 里,便于维护。
  4. 使用官方文档:CKEditor 5 的配置非常灵活,官方文档是最好的参考资料,请查阅:CKEditor 5 Documentation

通过以上步骤,你就可以在 Java 项目中成功配置并使用 CKEditor 5 了,从基本集成到文件上传,涵盖了最常见的使用场景。

分享:
扫描分享到社交APP
上一篇
下一篇