1. Обзор
В этой статье мы рассмотрим, как использовать CKEditor с Spring Boot . В этом руководстве мы будем импортировать XML-документ с многочисленными данными, запрограммировать возможность загрузки набора данных в экземпляр CKEditor с помощью запроса GET и выполнить запрос POST для сохранения данных CKEditor.
Технологии, которые мы будем использовать, включают MongoDB, Thymeleaf и Spring Batch.
Полный исходный код этого руководства доступен на Github .
2. Что такое CKEditor?
CKEditor — это редактор содержимого «WYSIWYG», основанный на браузере (WYSIWYG) . Целью CKEditor является привнесение в веб-интерфейс общих функций текстового процессора, которые можно найти в приложениях для редактирования на компьютере, таких как Microsoft Word и OpenOffice.
CKEditor имеет множество функций для конечных пользователей в отношении пользовательского интерфейса, вставки контента, создания контента и многого другого.
Существуют разные версии CKEditor, но для этого урока мы используем CKEditor 4. Чтобы увидеть демонстрацию, посетите: https://ckeditor.com/ckeditor-4/
3. Документ XML
Как уже упоминалось, мы загружаем XML-документ в этом приложении. Данные XML будут вставлены в базу данных и использованы для остальной части учебника.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
<?xml version="1.0"?><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. 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-кода мы можем смоделировать песню следующим образом:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
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 с отдельной моделью и репозиторием.
Давайте теперь определим, что такое обновленная песня:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
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 Processing
- Преобразование XML в JSON + Raw для использования в MongoDB + Spring Batch
6. Установка данных для CKEditor — GET Request
Наша цель — извлечь данные для отдельной песни и отобразить эти данные в CKEditor. Необходимо решить две проблемы: получить данные для отдельной песни и отобразить их в CKEditor.
6.1 Клиентский код
В view.html мы используем таблицу в Thymeleaf для перебора каждой песни в репозитории Song. Чтобы получить данные с сервера для конкретной песни, мы передаем идентификатор песни в функцию.
Вот фрагмент кода, который отвечает за вызов функции, которая получает данные с сервера и впоследствии устанавливает данные для экземпляра CKEditor :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
<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> |
Как мы видим, идентификатор Song необходим для того, чтобы мы могли получить данные.
В функции getSong мы используем отложенное обещание, чтобы гарантировать, что данные установлены после запроса GET:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
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 , который обозначает идентификатор песни. sid также является переменной пути в @GetMapping . Мы рассматриваем sid как String, потому что это идентификатор песни из MongoDB.
Мы проверяем, была ли песня изменена, и если это так, мы получаем соответствующую сущность ОбновленоSong . Если нет, мы относимся к Песне по-другому. В конечном итоге мы возвращаем простой POJO со строкой для данных с именем ResponseModel , однако:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
@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, как уже упоминалось:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
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 является текстовой областью внутри формы, мы можем вызвать функцию при отправке формы:
|
01
02
03
04
05
06
07
08
09
10
|
$(document).ready(function() { // SUBMIT FORM$("#form").submit(function(event) {// Prevent the form from submitting via the browser.event.preventDefault();ajaxPost();}); |
ajaxPost () извлекает текущие данные в CKEditor и устанавливает их в переменную formData :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
function ajaxPost() { // PREPARE FORM DATAvar 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 — это «текст»
Наличие неправильного contentType или dataType может привести к ошибкам или искаженным данным.
7.2 Серверный код
Мы указали в нашем contentType для запроса POST, что медиатип является «text / html» . Нам нужно указать в нашем отображении, что это будет использовано. Поэтому мы добавляем потребляемый = MediaType.TEXT_HTML_VALUE с нашим @PostMapping .
Области для нас, чтобы отметить, включают в себя:
- @RequestBody String body отвечает за установку тела переменной для содержимого нашего запроса
- Мы снова возвращаем ResponseModel , простой POJO, описанный ранее, который содержит наши данные
- Мы рассматриваем ранее измененную SongModel отличную от той, которая не была изменена ранее
Также, как и запрос GET, sid позволяет нам иметь дело с правильной песней:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
@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. Вывод
В этом руководстве мы рассмотрели, как загружать данные с помощью GET-запроса с идентификатором объекта, устанавливать для данных экземпляр CKEditor и сохранять данные CKEditor обратно в базу данных с помощью запроса POST. Есть дополнительный код, такой как использование двух разных сущностей для данных (исходная и измененная версия), который не нужен, но, надеюсь, поучителен.
Полный код можно найти на Github .
| Опубликовано на Java Code Geeks с разрешения Майкла Гуда, партнера нашей программы JCG . Смотреть оригинальную статью здесь: AJAX с CKEditor в Spring Boot
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |



