杰瑞科技汇

java ckeditor 配置

  1. 后端 (Java):负责处理文件上传、提供配置、管理会话等。
  2. 前端 (HTML/JavaScript):负责实例化和渲染 CKEditor 编辑器。

下面我将为你提供一个详细、分步的指南,涵盖从基础配置到高级功能(如文件上传)的完整流程。

java ckeditor 配置-图1
(图片来源网络,侵删)

第一步:添加 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 模块中引入:

java ckeditor 配置-图2
(图片来源网络,侵删)
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() 方法。

java ckeditor 配置-图3
(图片来源网络,侵删)
<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 的文件上传功能通常通过插件实现,最常用的是 EasyImageFileRepository,这里我们展示如何配置一个自定义的上传接口。

修改 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-fileuploadspring-boot-starter-web 中内置的文件上传支持的支持。spring-boot-starter-web 默认已经包含了。
  • 确保你的应用有权限在 UPLOADED_FOLDER 目录下创建和写入文件。
  • 在生产环境中,你需要考虑文件大小限制、文件类型白名单、病毒扫描等安全措施。

总结与最佳实践

  1. 分离前后端:前端负责 UI 和交互,后端负责业务逻辑和数据持久化,通过 RESTful API 进行通信。
  2. 安全第一
    • XSS 防护:后端在保存和显示富文本内容时,必须使用 HTML Sanitizer 对其进行清理。
    • CSRF 防护:如果你的应用使用 Session,确保对表单提交(包括文件上传)进行 CSRF 保护。
    • 文件上传安全:限制文件类型、大小,使用随机文件名,并对上传的文件进行病毒扫描。
  3. 模块化配置:不要在 HTML 中硬编码所有配置,可以将配置放在一个单独的 .js 文件中,或者从后端动态获取配置。
  4. 利用官方文档CKEditor 5 官方文档 是最权威的参考资料,包含了所有配置项和插件的详细说明。

通过以上步骤,你就可以在 Java 项目中成功集成并配置 CKEditor 5 了,从简单的文本编辑到复杂的富文本内容和文件管理,CKEditor 5 都提供了强大的支持。

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