在 Spring Boot 中使用 CKEditor 的 AJAX

位置:首页>文章>详情   分类: Java教程 > 编程技术   阅读(63)   2024-04-19 06:21:36

一、概述

在本文中,我们将介绍如何将 CKEditor 与 Spring Boot 结合使用。在本教程中,我们将导入一个包含大量数据的 XML 文档,编写使用 GET 请求将一组数据加载到 CKEditor 实例的能力,并执行 POST 请求以保存 CKEditor 的数据。

我们将使用的技术包括 MongoDB、Thymeleaf 和 Spring Batch。

Github 上提供了本教程的完整源代码。

2.什么是CKEditor?

CKEditor 是一个基于浏览器的所见即所得 (WYSIWYG) 内容编辑器。 CKEditor 旨在将桌面编辑应用程序(如 Microsoft Word 和 OpenOffice)中常见的文字处理器功能引入 Web 界面。

CKEditor 在用户界面、插入内容、创作内容等方面为最终用户提供了许多功能。

CKEditor 有不同的版本,但对于本教程,我们使用的是 CKEditor 4。要查看演示,请访问:https://ckeditor.com/ckeditor-4/

3. XML文档

如前所述,我们将在此应用程序中上传 XML 文档。 XML 数据将被插入数据库并用于本教程的其余部分。

<?xml version="1.0"?>
<Music xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="MUS-1" style="1.1">
<status date="2017-11-07">draft</status>
 <title xmlns:xhtml="http://www.w3.org/1999/xhtml" >Guide to Music I Like - No Specific Genre</title>
  <description xmlns:xhtml="http://www.w3.org/1999/xhtml" >This guide presents a catalog of music that can be found on Spotify. 
    <html:br xmlns:html="http://www.w3.org/1999/xhtml"/>
    <html:br xmlns:html="http://www.w3.org/1999/xhtml"/>
    This is a very small sample of music found on Spotify and is no way to be considered comprehensive.
    </description>
    <songs>
    <song>
    <artist>
    Run the Jewels
    </artist>
    <song-title>Legend Has It</song-title>
    </song>
    <song>
    <artist>
    Kendrick Lamar
    </artist>
    <song-title>ELEMENT.</song-title>
    </song>
    <song>
    <artist>
    Weird Al Yankovic
    </artist>
    <song-title>NOW That's What I Call Polka!</song-title>
    </song>
    <song>
    <artist>
    Eiffel 65
    </artist>
    <song-title>Blue (Da Ba Dee) - DJ Ponte Ice Pop Radio</song-title>
    </song>
    <song>
    <artist>
    YTCracker
    </artist>
    <song-title>Hacker Music</song-title>
    </song>
    <song>
    <artist>
    MAN WITH A MISSION
    </artist>
    <song-title>
    Raise Your Flag
    </song-title>
    </song>
    <song>
    <artist>
    GZA, Method Man
    </artist>
    <song-title>
    Shadowboxin'
    </song-title>
    </song>
    </songs>
</Music>

4.型号

对于上面的 XML 代码,我们可以像这样建模一首歌曲:

public class SongModel {
    @Id
    private String id;
    @Indexed
    private String artist;
    @Indexed
    private String songTitle;
    @Indexed
    private Boolean updated;
     
    public Boolean getUpdated() {
        return updated;
    }
    public void setUpdated(Boolean updated) {
        this.updated = updated;
    }
    public String getArtist() {
        return artist;
    }
    public void setArtist(String artist) {
        this.artist = artist;
    }
    public String getSongTitle() {
        return songTitle;
    }
    public void setSongTitle(String songTitle) {
        this.songTitle = songTitle;
    }
     
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
     
    @JsonCreator
    public SongModel(
        @JsonProperty("artist") String artist,
        @JsonProperty("song-title") String songTitle){
        this.artist = artist;
        this.songTitle = songTitle;
    }
  
    @Override
    public String toString() {
      return "Person [id=" + id + ", artist=" + artist + ", song-title=" + songTitle + "]";
    }
 
}

对于我们的应用程序,我们将区分未修改的歌曲和已在 CKEditor 中使用单独的模型和存储库修改的歌曲。

现在让我们定义什么是更新的歌曲:

public class UpdatedSong {
     
    @Id
    private String id;
    @Indexed
    private String artist;
    @Indexed
    private String songTitle;
    @Indexed
    private String html;
    @Indexed
    private String sid;
     
    public String getSid() {
        return sid;
    }
    public void setSid(String sid) {
        this.sid = sid;
    }
     
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getArtist() {
        return artist;
    }
    public void setArtist(String artist) {
        this.artist = artist;
    }
    public String getSongTitle() {
        return songTitle;
    }
    public void setSongTitle(String songTitle) {
        this.songTitle = songTitle;
    }
    public String getHtml() {
        return html;
    }
    public void setHtml(String html) {
        this.html = html;
    }
 
}

5. 文件上传及处理

由于本文的重点是 CKEditor 和 AJAX,我们不会详细介绍使用 Spring Batch 进行文件上传和处理。我们已经在这些之前的帖子中深入回顾了这个过程,但是:

  • Spring Batch CSV 处理
  • 将 XML 转换为 JSON + 在 MongoDB + Spring Batch 中原始使用

6.设置数据到CKEditor-GET请求

我们的目标是检索单个歌曲的数据并在 CKEditor 中显示该数据。有两个问题需要解决:检索单个歌曲的数据并将其显示在 CKEditor 中。

6.1 客户端代码

view.html 中,我们使用 Thymeleaf 中的一个表来迭代歌曲存储库中的每首歌曲。为了能够从服务器检索特定歌曲的数据,我们将歌曲的 id 传递给一个函数。

以下是负责调用从服务器检索数据并随后将数据设置到 CKEditor 实例的函数的代码片段:

<table class="table datatable">
<thead>
<tr>
<th>Artist</th>
<th>Song Title</th>
<th>Load</th>
</tr>
</thead>
<tbody>
<tr th:each="songList : ${songList}">
<td th:text="${songList.artist}">Text ...</td>
<td th:text="${songList.songTitle}">Text ...</td>
<td><button th:onclick="|getSong('${songList.id}')|" id="button" class="btn btn-primary btn-condensed">
<i class="glyphicon glyphicon-folder-open"></i>
</button></td>
</tr>
</tbody>
</table>

如我们所见,Songid 对于我们能够检索数据至关重要。

getSong 函数中,我们使用延迟承诺来确保 data 在 GET 请求之后设置:

function getSong(song) {
    $.ajax({
        url : "/api/show/?sid=" + song,
        type : 'GET',
        dataType : 'text'
    }).then(function(data) {
        var length = data.length-2;
        var datacut = data.slice(9,length);
        CKEDITOR.instances.content.setData(datacut);
 
    });
 
    $("#form").attr("action", "/api/save/?sid=" + song);
 
};

6.2 服务器端代码

getSong 接受一个名为sid 的参数,它代表歌曲id。 sid 也是@GetMapping 中的一个路径变量。我们将 sid 视为字符串,因为这是来自 MongoDB 的歌曲的 id

我们检查 Song 是否已被修改,如果是,我们检索关联的 UpdatedSong 实体。如果不是,我们将以不同的方式对待这首歌。最终,我们返回一个带有字符串的简单 POJO,用于名为 ResponseModel 的数据,但是:

@GetMapping(value={"/show/","/show/{sid}"})
public ResponseEntity<?> getSong(@RequestParam String sid, Model model){
    ResponseModel response = new ResponseModel();
    System.out.println("SID :::::" + sid);
    ArrayList<String> musicText = new ArrayList<String>();
    if(sid!=null){
        String sidString = sid;
        SongModel songModel = songDAO.findOne(sidString);
        System.out.println("get status of boolean during get ::::::" + songModel.getUpdated());
        if(songModel.getUpdated()==false ){
             
            musicText.add(songModel.getArtist());
            musicText.add(songModel.getSongTitle());
            String filterText = format.changeJsonToHTML(musicText);
            response.setData(filterText);
             
        } else if(songModel.getUpdated()==true){
            UpdatedSong updated = updatedDAO.findBysid(sidString);
            String text = updated.getHtml();
            System.out.println("getting the updated text ::::::::" + text);
            response.setData(text);
        }
         
    }
 
    model.addAttribute("response", response);
     
    return ResponseEntity.ok(response);
}

如前所述,ResponseModel 是一个非常简单的 POJO:

public class ResponseModel {
    private String data;
     
    public ResponseModel(){
             
    }
     
    public ResponseModel(String data){
            this.data = data;
    }
 
    public String getData() {
            return data;
    }
 
    public void setData(String data) {
            this.data = data;
    }
}

7. 保存CKEditor数据——POST请求

发布数据不是什么大问题;但是,可以确保数据得到适当处理。

7.1 客户端代码

由于 CKEditor 实例是表单中的文本区域,我们可以在表单提交时触发一个函数:

$(document)
.ready(
function() {
 
// SUBMIT FORM
$("#form").submit(function(event) {
// Prevent the form from submitting via the browser.
event.preventDefault();
ajaxPost();
});

ajaxPost() 检索 CKEditor 中的当前数据并将其设置为变量 formData

function ajaxPost() {
 
// PREPARE FORM DATA
var formData = CKEDITOR.instances.content
.getData();
 
// DO POST
$
.ajax({
type : "POST",
contentType : "text/html",
url : $("#form").attr("action"),
data : formData,
dataType : 'text',
success : function(result) {
 
$("#postResultDiv")
.html(
"
 
"
+ "Post Successfully! "
+ "
 
");
 
console.log(result);
},
error : function(e) {
alert("Error!")
console.log("ERROR: ", e);
}
});
 
}
 
})

重要的是要注意:

  • contentType “text/html”
  • dataType“text”

具有不正确的 contentType 或 dataType 会导致错误或格式错误的数据。

7.2 服务器端代码

我们在 POST 请求的 contentType 中声明媒体类型是 “text/html”。我们需要在我们的映射中指定这将被消耗。因此,我们使用 @PostMapping 添加 consumes = MediaType.TEXT_HTML_VALUE

我们需要注意的领域包括:

  • @RequestBody String body 负责设置变量body 为我们请求的内容
  • 我们再次返回 ResponseModel,这是前面描述的包含我们数据的简单 POJO
  • 我们对待之前修改过的SongModel与之前未修改过的不同

此外,与 GET 请求一样,sid 允许我们处理正确的歌曲:

@PostMapping(value={"/save/","/save/[sid]"}, consumes = MediaType.TEXT_HTML_VALUE)
   public @ResponseBody ResponseModel saveSong( @RequestBody String body, @RequestParam String sid){
       ResponseModel response = new ResponseModel();
       response.setData(body);
       SongModel oldSong = songDAO.findOne(sid);
       String songTitle = oldSong.getSongTitle();
       String artistName = oldSong.getArtist();
       if(oldSong.getUpdated() == false){
           UpdatedSong updatedSong = new UpdatedSong();
           updatedSong.setArtist(artistName);
           updatedSong.setSongTitle(songTitle);
           updatedSong.setHtml(body);
           updatedSong.setSid(sid);
           oldSong.setUpdated(true);
           songDAO.save(oldSong);
           updatedDAO.insert(updatedSong);
           System.out.println("get status of boolean during post :::::" + oldSong.getUpdated());
       }else{
           UpdatedSong currentSong = updatedDAO.findBysid(sid);
           currentSong.setHtml(body);
           updatedDAO.save(currentSong);
       }        
        
       return response;
   }

8.演示

我们访问 localhost:8080

我们上传提供的 music-example.xml 文件:

我们点击“加载”一首歌曲:

我们添加内容,点击“保存”:

如果您返回保存的内容,您可能会看到换行符“\n”。目前,讨论这超出了本教程的范围。

9.总结

在本教程中,我们介绍了如何使用带有对象 ID 的 GET 请求加载数据,将数据设置到 CKEditor 实例,并使用 POST 请求将 CKEditor 的数据保存回数据库。还有额外的代码,例如对数据使用两个不同的实体(原始版本和修改后的版本),这不是必需的,但希望具有指导意义。

完整代码可以在 Github 上找到。

标签2: Java教程
地址:https://www.cundage.com/article/jcg-ajax-ckeditor-spring-boot.html

相关阅读

Java HashSet 教程展示了如何使用 Java HashSet 集合。 Java哈希集 HashSet 是一个不包含重复元素的集合。此类为基本操作(添加、删除、包含和大小)提供恒定时间性...
SpringApplicationBuilder 教程展示了如何使用 SpringApplicationBuilder 创建一个简单的 Spring Boot 应用程序。 春天 是用于创建企业应...
通道是继 buffers 之后 java.nio 的第二个主要新增内容,我们在之前的教程中已经详细了解了这一点。通道提供与 I/O 服务的直接连接。 通道是一种在字节缓冲区和通道另一端的实体(通...
课程大纲 Elasticsearch 是一个基于 Lucene 的搜索引擎。它提供了一个分布式的、支持多租户的全文搜索引擎,带有 HTTP Web 界面和无模式的 JSON 文档。 Elasti...
解析器是强大的工具,使用 ANTLR 可以编写可用于多种不同语言的各种解析器。 在这个完整的教程中,我们将: 解释基础:什么是解析器,它可以用来做什么 查看如何设置 ANTLR 以便在 Java...
Java 是用于开发各种桌面应用程序、Web 应用程序和移动应用程序的最流行的编程语言之一。以下文章将帮助您快速熟悉 Java 语言,并迈向 API 和云开发等更复杂的概念。 1. Java语言...
Java中的继承是指子类继承或获取父类的所有非私有属性和行为的能力。继承是面向对象编程的四大支柱之一,用于提高层次结构中类之间的代码可重用性。 在本教程中,我们将了解 Java 支持的继承类型,...
Java Message Service 是一种支持正式通信的 API,称为 网络上计算机之间的消息传递。 JMS 为支持 Java 程序的标准消息协议和消息服务提供了一个通用接口。 JMS 提...
Java 项目中的一项常见任务是将日期格式化或解析为字符串,反之亦然。解析日期意味着你有一个代表日期的字符串,例如“2017-08-3”,你想把它转换成一个代表 Java 中日期的对象,例如Ja...
之前,我介绍了spring 3 + hibernate 集成 示例和struts 2 hello world 示例。在本教程中,我将讨论在将 spring 框架与 struts 与 hibern...