Vaadin开源富文本编辑器解决方案:基于wangEditor的深度集成实践

1. 背景与优势

1.1 现有方案痛点

  • Vaadin官方Editor组件需商业授权
  • 现有开源方案功能不完善
  • 企业应用需要深度定制能力

1.2 本方案特点

特性说明
开源免费APACHE 2.0许可协议
功能完整基于wangEditor 5.x核心
企业级集成深度适配Vaadin框架
生产就绪发布至Maven中央仓库

2. 技术栈要求

  • 基础环境

    • JDK 17+
    • Spring Boot 3.5.0+
    • Vaadin 24.7.4+
  • 开发工具

    • IntelliJ IDEA 2022+(社区版即可)
    • Maven 3.8+

3. 快速集成指南

3.1 项目初始化

使用Spring Initializr创建项目,参考:
Spring Boot Initializr Vaadin集成指南

3.2 添加依赖

<dependency>
    <groupId>io.gitee.muyun2800</groupId>
    <artifactId>vaadin-wangeditor</artifactId>
    <version>1.0.0</version>
</dependency>

3.3 基础使用示例

@Route("demo/basic-editor")
public class BasicEditorView extends Div {
    public BasicEditorView() {
        WangEditor editor = new WangEditor();
        editor.setHtml("<p>初始内容</p>");
        add(editor);
    }
}

3.4 必要配置

application.properties

# Vaadin组件扫描配置
vaadin.allowed-packages=com.vaadin,org.vaadin,io.gitee.muyun2800

# URL映射配置
vaadin.url-mapping=/ui/*

配置说明

  • vaadin.allowed-packages:用于将组件加入到vaadin框架的扫描路径下,第三方包都需要将其命名空间配置在此,否则组件在加载时会异常。
  • vaadin.url-mapping: 配置vaadin框架的url路径,它的默认值为/, 表示匹配所有的路径。如果采用默认的值的话,springmvc的路径会无法使用,原因是所有的url路径都被vaadin框架所匹配。这里将它修改为/ui/,表示仅匹配/ui/下的路径,springmvc的路径只要错开这个路径前缀就都可以使用。

4. 更多功能

4.1 图片上传集成

界面代码

@Route("demo/wang-editor7")
public class WangEditorView7 extends Div {

    public WangEditorView7() {
        WangEditor editor = new WangEditor();
        add(editor);
        // 上传图片配置
        EditorConfig.UploadImageConfig uploadImageConfig = new EditorConfig.UploadImageConfig();
        uploadImageConfig.setServer("/api/upload");
        uploadImageConfig.setFieldName("file");
        //
        EditorConfig editorConfig = new EditorConfig();
        editorConfig.setPlaceholder("请上传图片.....");
        editorConfig.getMenuConfMap().put("uploadImage", uploadImageConfig);
        editor.setEditorConfig(editorConfig);
    }
}

处理图片上传和下载的代码

@RestController
@Slf4j
public class UploadController {
    File uploadDir = new File("d:\\workspace\\upload");
    
    @PostMapping("/api/upload")
    public UploadOutput handleFileUpload(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return new UploadOutput(1, "请选择文件上传!");
        }
        try {
            if (!uploadDir.exists()) {
                uploadDir.mkdirs();
            }
            File uploadedFile = new File(uploadDir, file.getOriginalFilename());
            System.out.println("uploadedFile = " + uploadedFile);
            file.transferTo(uploadedFile);
            log.info("uploadedFile = {}", uploadedFile);
            String url = "/api/download?fileName=" + file.getOriginalFilename();
            UploadOutput uploadOutput = new UploadOutput(0);
            uploadOutput.setData(new UploadOutput.UploadOutputData(url));
            return uploadOutput;
        } catch (IOException e) {
            e.printStackTrace();
            return new UploadOutput(1, "文件上传失败!");
        }
    }

    @GetMapping("/api/download")
    public void download(@RequestParam("fileName") String fileName, HttpServletResponse response) throws IOException {
        File file = new File(uploadDir, fileName);
        if (!file.exists()) {
            throw new IOException("文件找不到!文件为:" + file.toString());
        }
        OutputStream outputStream = response.getOutputStream();
        // 普通文件为 application/octet-stream
        response.setContentType("image/jpg");
        try {
            //
            byte[] bytes = Files.toByteArray(file);
            outputStream.write(bytes);
            outputStream.flush();
        } catch (Exception ex) {
            throw new IOException("写入下载输出流失败!");
        }
    }
}
@Data
public class UploadOutput {
    int errno;
    /**
     * 错误消息, 可选
     */
    String message;

    UploadOutputData data;

    public UploadOutput(int errno) {
        this.errno = errno;
    }

    public UploadOutput(int errno, String message) {
        this.errno = errno;
        this.message = message;
    }
    public UploadOutput() {
    }

    @Data
    public static class UploadOutputData {
        /**
         * 图片地址,必须
         */
        String url;

        /**
         * 图片不可见时的文本,可选
         */
        String alt;

        /**
         * 图片链接,可选
         */
        String href;

        public UploadOutputData(String url) {
            this.url = url;
        }

        public UploadOutputData() {
        }
    }
}

4.2 更多的示例

更多的示例参见: vaadin-wangeditor。下载代码之后,打开子模块:vaadin-wangeditor-demo,里面有一些示例代码,包括事件、菜单配置、模式等,见下图:

0000

5. 参考资源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值