在本系列的文章中,我将介绍如何在Spring Boot Application中使用CKEditor编辑器。介绍的内容包括基本环境的搭建,文件上传,SpringData JPA数据持久化,CKEditor5的安装,CKEditor图片上传,CKEditor插入视频,获取/设置CKEditor内容等。
本系列文章的项目源码同步更新至 码云 和 Github ,你可以任选其一下载源码到本地。项目地址如下:
你也可以通过Git命令行工具下载项目源码,命令如下(二者任选其一):
git clone https://gitee.com/ramostear/CKEditor5-SpringBoot.git
git clone https://github.com/ramostear/CKEditor5-SpringBoot.git
接上篇内容,本篇的主要内容是引入MySQL数据库驱动依赖和SpringData JPA依赖,然后创建内容实体,并完成数据持久层(DAO)和业务逻辑层(Service)相关代码的设计和实现。
前面的内容中我们分析过,需要将CKEditor5编辑的内容存储到数据库中(图片数据存储到磁盘)。本项目使用MySQL数据库来存储数据。数据的持久化过程选用SpringData JPA进行实现,除此之外,我们借用Alibaba Druid来管理数据库连接池。
在项目根目录下找到并打开pom.xml文件,然后向文件中添加如下的依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> <scope>runtime</scope> </dependency>
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.14</version> </dependency>
依赖包加载完成,我们需要对项目中的JPA和数据源进行配置。配置的内容包括数据库的类型,数据库方言,数据源类型,数据库驱动以及连接数据库所需要的用户名,密码和连接地址。详细配置如下图:
在“src/main/resources”目录下找到_application.properties_ 文件,并将该文件更名为_application.yml_ 并添加下列配置信息:
spring: jpa: database: mysql show-sql: true hibernate: ddl-auto: update database-platform: org.hibernate.dialect.MySQL5Dialect properties: hibernate.format_sql: true datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver username: root password: root url: jdbc:mysql://localhost:3306/db_ckeditor_springboot?useUnicode=true&useSSL=false&characterEncoding=utf8
如上图所示:
①:指定数据库类型为MySQL数据库
②:在启动项目时,如果数据库表和对应的实体之间的映射不一致,则更新数据库表,并保留原有数据
③:配置数据库方言为org.hibernate.dialect.MySQL5Dialect
④:配置数据源类型为Alibaba Druid Datasource
⑤:配置数据库驱动
⑥:数据账户名
⑦:账户密码
⑧:数据库的连接地址
在上一步中,我们配置的数据库连接地址为:jdbc : mysql://localhost:3306/db_ckeditor_springboot?useUnicode=true&useSSL=false&characterEncoding=utf8 。因此,我们需要创建一个名为 db_ckeditor_springboot 的数据库。你可以使用Navicat或SQLyog这一类的可视化软件来创建数据库,也可以使用MySQL命令行窗口来创建。这里我们使用命令行的方式来创建 db_ckeditor_springboot 数据库,命令如下:
CREATE DATABASE `db_ckeditor_springboot` `CHARACTER SET utf5 COLLATE utf8_bin`;
USE `db_ckeditor_springboot`;
在配置环节,我们配置了spring.jpa.hibernate.ddl-auto=update。因此,我们不需要再手动创建数据库表,当项目中存在对应的实体类时,SpringData JPA为自动生成表。
spring.jpa.hibernate.ddl-auto有四个可选配置项:
在 com.ramostear.ckeditor 包下创建model包用来存放实体类,为了减少编码工作量,这里我们需要引入Lombok依赖包。在pom.xml文件中添加如下依赖:
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
接下来,我们创建一个用于存储CKEditor编辑器内容的实体类Content,为了简化操作,该类只设计三个属性,具体如下:
属性名
类型
数据库类型
id
Integer
int 自增,不允许为空
text
String
text, 默认值为””
createTime
Date
Date,默认值为CURRENT_TIMESTAMP
Content.java类详细信息如下:
①: @Table 为实体类指定数据库表。
②: @GeneratedValue 注解存在的意义主要就是为一个实体生成一个唯一标识的主键、 @GeneratedValue 提供了主键的生成策略。
③: @Lob 指定持久属性或字段应作为大对象持久保存到数据库支持的大对象类型。
④: @PrePersist 在持久化之前自动填充实体属性。
以下是Content.java的源代码:
package com.ramostear.ckeditor.model; import lombok.Data; import org.hibernate.annotations.Type; import javax.persistence.*; import java.util.Date; @Data @Entity @Table(name = "content") public class Content { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Lob @Type(type = "text") @Column(name = "text") private String text; @Temporal(TemporalType.TIMESTAMP) @Column(name = "create_time",columnDefinition = "timestamp default CURRENT_TIMESTAMP") private Date createTime; @PrePersist public void prePersist(){ this.id = null; this.createTime = new Date(); if(text == null || text.trim().equals("")){ text = ""; } } }
@Data 是 @Getter , @Setter , @RequiredArgsConstructor , @ToString 和 @EqualsAndHashCode 的组合注解(快捷方式),用于生成getter(),setter(),toString()等方法。
SpringData JPA是spring在ORM框架和JPA规范的基础上封装的一套JPA应用框架,可以使开发者使用极简的代码实现对数据库的访问和操作。它提供了包括增删改查等在内的基本功能,且易于扩展。因此,创建持久化类最快的方式是继承SpringData JPA提供的基础类。我们将继承SpringData JPA的JpaRepository类来实现内容数据的增删改查功能。下面是ContentRepository.java类的代码明细:
package com.ramostear.ckeditor.repository; import com.ramostear.ckeditor.model.Content; import org.springframework.data.jpa.repository.JpaRepository; public interface ContentRepository extends JpaRepository<Content,Integer> { }
该类放置在“com.ramostear.ckeditor.repository”包下,在一开始的时候,我们只需要继承JpaRepository接口即可。
首先,我们仅提供一个包含增、删、改、查四个功能的业务逻辑接口(ContentService.java),并在其实现类(ContentServiceImpl.java)中实现接口中定义的方法。
package com.ramostear.ckeditor.service; import com.ramostear.ckeditor.model.Content; import java.util.List; public interface ContentService { /** * 保存内容 * @param content * @return */ Content save(Content content); /** * 修改内容 * @param content * @return */ boolean update(Content content); /** * 根据ID删除内容 * @param id * @return */ boolean delete(Integer id); /** * 根据ID查询内容 * @param id * @return */ Content findById(Integer id); /** * 获取所有的内容 * @return */ List<Content> findAll(); }
package com.ramostear.ckeditor.service.impl; import com.ramostear.ckeditor.model.Content; import com.ramostear.ckeditor.repository.ContentRepository; import com.ramostear.ckeditor.service.ContentService; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; @Service(value = "contentService") @Transactional(readOnly = true) public class ContentServiceImpl implements ContentService { private final ContentRepository contentRepository; @Autowired ContentServiceImpl(ContentRepository contentRepository){ this.contentRepository = contentRepository; } @Override @Transactional public Content save(Content content) { return contentRepository.save(content); } @Override @Transactional public boolean update(Content content) { Content target = this.findById(content.getId()); if(target != null){ BeanUtils.copyProperties(content,target,"id","createTime"); contentRepository.saveAndFlush(target); return true; } return false; } @Override @Transactional public boolean delete(Integer id) { Optional<Content> check = contentRepository.findById(id); if(check.isPresent()){ contentRepository.deleteById(id); return true; } return false; } @Override public Content findById(Integer id) { return contentRepository.findById(id).orElse(null); } @Override public List<Content> findAll() { return contentRepository.findAll(Sort.by(Sort.Direction.DESC,"createTime")); } }
所有的业务接口都放置在“com.ramostear.ckeditor.service”包下,所有的业务接口实现类都放置在“com.ramostear.ckeditor.service.impl”包下。
其中, @Service 注解表面当前类是一个被Spring容器所管理的Bean,Bean的名称为“contentService”; @Transactional 是声明式事务管理编程中使用的注解,该注解放置在接口实现类或方法上;另外,在ContentServiceImpl.java类中,使用基于构造方法的方式将ContentRepository.java的实例化对象注入其中。特别地,当类中只有一个构造方法时, @Autowired 注解可以省略不写。
完成以上编码工作后,我们将启动应用程序,检查应用程序是否与MySQL数据库连接成功并创建名为“content”的数据表。启动应用后,当IDEA控制台输出如下的信息,则表明我们的应用已经和MySQL建立连接,并成功在db_ckeditor_springboot数据库创建了content表。
为了进一步验证是否创建了content表,我们可以打开MySQL命令行工具,并输入如下命令进行检查:
>mysql use db_ckeditor_springboot; >mysql show tables; >mysql show columns from content;
若查询结果如下,则证明content表已经创建:
另外,我们还可以通过Druid来查看应用的数据库连接信息,要实现该功能,只需向application.yml配置文件中添加如下的配置项即可:
spring: datasource: druid: stat-view-servlet: enabled: true
然后重启应用,应用启动成功后,在浏览器中输入: http://localhost:8080/druid/index.html 便可查看应用的数据库连接情况,如下图:
本章详细介绍了依赖包的引入,项目的配置,实体类,持久化类和业务类的实现过程,并通过SpringData JPA实现了自动创建数据表,最后介绍了通过命令行工具和Druid Monitor两种方式查看数据库信息。你可以访问下面的地址,下载该项目的所有源代码:
在下一章节中,我将着重介绍如何在SpringBoot中实现文件上传功能,以及如何映射上传文件路径等技术要点。
未经作者允许,请勿擅自转载