- 2018-12-06 进行整理本篇文章,主要是解决如何引入富文本编辑器的使用
- 2019-06-18 进行了二次完善,解决了富文本编辑器的图片上传和附件上传问题
本篇文章进行二次更新操作,完善了上传图片功能 ,各位只需要将我下方创建的两个servlet的拷贝到你们的servlet里去。另外在修改一下js代码,如图:

今日课堂无聊,简单写了些前台,顺便给大家说说富文本编辑器的使用教程

对于分类描述,我采用了富文本编辑器~KingEditer的插件。
什么是富文本编辑器?

1.搭建富文本编辑器
去KingEditor官网去下载KingEditor文件 kingeditor
下载解压后,如下图:

 我是在WebContent或者WebRoot下新建了一个文件夹Folder,命名为:kindEditer,将lang,plugins,themes,kindediteror-all.js,kindediteror-all-min.js拷贝到kindEditer文件夹下了。如图:

 在WebContent里新建了一个页面,命名为header.jsp,在其中引入了部分官方提供模板代码,(大家也可以选择拷贝我的代码:)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/main.css" />
<!--想使用富文本编辑器,需要引入下面三条-->
<link rel="stylesheet" href="${pageContext.request.contextPath}/kindEditor/themes/default/default.css" />
<script charset="utf-8" src="${pageContext.request.contextPath}/kindEditor/kindeditor-all-min.js"></script>
<script charset="utf-8" src="${pageContext.request.contextPath}/kindEditor/lang/zh_CN.js"></script>
<!-- <script>
//简单模式初始化
//简单模式 注意:下方中的content属性值要与textarea的name属性值相同才可以
var editor;
KindEditor.ready(function(K) {
editor = K.create('textarea[name="content"]', {
resizeType : 1,
allowPreviewEmoticons : false,
allowImageUpload : false,
items : [
'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold', 'italic', 'underline',
'removeformat', '|', 'justifyleft', 'justifycenter', 'justifyright', 'insertorderedlist',
'insertunorderedlist', '|', 'emoticons', 'image', 'link']
});
});
</script> -->
<script>
//默认模式 注意:下方中的content属性值要与textarea的name属性值相同才可以
var editor;
KindEditor.ready(function(K) {
editor = K.create('textarea[name="content"]', {
allowFileManager : true,
uploadJson:'${pageContext.request.contextPath}/kindeditorUploadServlet',
fileManagerJson:'${pageContext.request.contextPath}/kindeditorFileManagerServlet'
});
K('input[name=getHtml]').click(function(e) {
alert(editor.html());
});
K('input[name=isEmpty]').click(function(e) {
alert(editor.isEmpty());
});
K('input[name=getText]').click(function(e) {
alert(editor.text());
});
K('input[name=selectedHtml]').click(function(e) {
alert(editor.selectedHtml());
});
K('input[name=setHtml]').click(function(e) {
editor.html('<h3>Hello KindEditor</h3>');
});
K('input[name=setText]').click(function(e) {
editor.text('<h3>Hello KindEditor</h3>');
});
K('input[name=insertHtml]').click(function(e) {
editor.insertHtml('<strong>插入HTML</strong>');
});
K('input[name=appendHtml]').click(function(e) {
editor.appendHtml('<strong>添加HTML</strong>');
});
K('input[name=clear]').click(function(e) {
editor.html('');
});
});
</script>
</head>
代码中,我涉及到了两种模式:(二选一)
第一种简约模式,效果如图:

第二种默认的富文本编辑模式,效果如图:

这里,我选择的是第二种模式。【即,把简约模式进行了注释】
以下是我的代码示例:
步骤一:新建一个jsp页面,起名为addCategory.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="/header.jsp" %>
<br/>
<center>
<form action="${pageContext.request.contextPath}/CategoryServlet?op=addCategory" method="post" >
<table>
<tr>
<td>分类名称:</td>
<td>
<input type="text" name="name" >
</td>
</tr>
<tr>
<td>分类描述:</td>
<td><textarea id="mul_input" name="description" style="width:700px;height:200px;visibility:hidden;display: block;"></textarea>
</tr>
<tr class="input_control">
<td colspan="2">
<input type="submit" value="添加图书" id="btn1" >
</td>
</tr>
</table>
</form>
</center>
首先我是在addCategory.jsp的开头就引进了一个header页面,header页面代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/kingEditer/themes/default/default.css" />
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/main.css" />
<script charset="utf-8" src="${pageContext.request.contextPath}/kingEditer/kindeditor-all-min.js"></script>
<script charset="utf-8" src="${pageContext.request.contextPath}/kingEditer/lang/zh_CN.js"></script>
<!-- <script>
//简单模式初始化
var editor;
KindEditor.ready(function(K) {
editor = K.create('textarea[name="description"]', {
resizeType : 1,
allowPreviewEmoticons : false,
allowImageUpload : false,
items : [
'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold', 'italic', 'underline',
'removeformat', '|', 'justifyleft', 'justifycenter', 'justifyright', 'insertorderedlist',
'insertunorderedlist', '|', 'emoticons', 'image', 'link']
});
});
</script> -->
<script>
//默认模式
var editor;
KindEditor.ready(function(K) {
editor = K.create('textarea[name="description"]', {
allowFileManager : true
});
K('input[name=getHtml]').click(function(e) {
alert(editor.html());
});
K('input[name=isEmpty]').click(function(e) {
alert(editor.isEmpty());
});
K('input[name=getText]').click(function(e) {
alert(editor.text());
});
K('input[name=selectedHtml]').click(function(e) {
alert(editor.selectedHtml());
});
K('input[name=setHtml]').click(function(e) {
editor.html('<h3>Hello KindEditor</h3>');
});
K('input[name=setText]').click(function(e) {
editor.text('<h3>Hello KindEditor</h3>');
});
K('input[name=insertHtml]').click(function(e) {
editor.insertHtml('<strong>插入HTML</strong>');
});
K('input[name=appendHtml]').click(function(e) {
editor.appendHtml('<strong>添加HTML</strong>');
});
K('input[name=clear]').click(function(e) {
editor.html('');
});
});
</script>
</head>
<body>
<h1>欢迎来到趣读书屋</h1>
<br/>
<br/>
<ul>
<li>
<a href="">添加分类</a>
</li>
<li>
<a href="">添加图书</a>
</li>
<li>
<a href="">用户注册</a>
</li>
<li>
<a href="">用户登录</a>
</li>
<li>
<a href="">购物车</a>
</li>
<li>
<a href="">我的订单</a>
</li>
</ul>
<br/>
<br/>
<hr/>
【2019.06】完善上传功能实现
1. 上传Jar包
commons-collections-3.2.1.jar
commons-fileupload-1.3.1.jar
commons-io-2.4.jar
json_simple-1.1.jar
2. 创建两个Servlet
2.1 第一个Servlet命名为 KindeditorFileManagerServlet
package cn.javabs.school.servlet;
import org.json.simple.JSONObject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Comparator;
import java.text.SimpleDateFormat;
import java.util.*;
@WebServlet("/kindeditorFileManagerServlet")
public class KindeditorFileManagerServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
/**
* KindEditor JSP
*
* 本JSP程序是演示程序,建议不要直接在实际项目中使用。 如果您确定直接使用本程序,使用之前请仔细确认相关安全设置。
*
*/
// 根目录路径,可以指定绝对路径,比如 /var/www/attached/
String rootPath = getServletContext().getRealPath("/") + "attached/";
// 根目录URL,可以指定绝对路径,比如 http://www.yoursite.com/attached/
String rootUrl = request.getContextPath() + "/attached/";
// 图片扩展名
String[] fileTypes = new String[] { "gif", "jpg", "jpeg", "png", "bmp" };
String dirName = request.getParameter("dir");
if (dirName != null) {
if (!Arrays.<String> asList(
new String[] { "image", "flash", "media", "file" })
.contains(dirName)) {
out.println("Invalid Directory name.");
return;
}
rootPath += dirName + "/";
rootUrl += dirName + "/";
File saveDirFile = new File(rootPath);
if (!saveDirFile.exists()) {
saveDirFile.mkdirs();
}
}
// 根据path参数,设置各路径和URL
String path = request.getParameter("path") != null ? request
.getParameter("path") : "";
String currentPath = rootPath + path;
String currentUrl = rootUrl + path;
String currentDirPath = path;
String moveupDirPath = "";
if (!"".equals(path)) {
String str = currentDirPath.substring(0,
currentDirPath.length() - 1);
moveupDirPath = str.lastIndexOf("/") >= 0 ? str.substring(0, str
.lastIndexOf("/") + 1) : "";
}
// 排序形式,name or size or type
String order = request.getParameter("order") != null ? request
.getParameter("order").toLowerCase() : "name";
// 不允许使用..移动到上一级目录
if (path.indexOf("..") >= 0) {
out.println("Access is not allowed.");
return;
}
// 最后一个字符不是/
if (!"".equals(path) && !path.endsWith("/")) {
out.println("Parameter is not valid.");
return;
}
// 目录不存在或不是目录
File currentPathFile = new File(currentPath);
if (!currentPathFile.isDirectory()) {
out.println("Directory does not exist.");
return;
}
// 遍历目录取的文件信息
List<Hashtable> fileList = new ArrayList<Hashtable>();
if (currentPathFile.listFiles() != null) {
for (File file : currentPathFile.listFiles()) {
Hashtable<String, Object> hash = new Hashtable<String, Object>();
String fileName = file.getName();
if (file.isDirectory()) {
hash.put("is_dir", true);
hash.put("has_file", (file.listFiles() != null));
hash.put("filesize", 0L);
hash.put("is_photo", false);
hash.put("filetype", "");
} else if (file.isFile()) {
String fileExt = fileName.substring(
fileName.lastIndexOf(".") + 1).toLowerCase();
hash.put("is_dir", false);
hash.put("has_file", false);
hash.put("filesize", file.length());
hash.put("is_photo", Arrays.<String> asList(fileTypes)
.contains(fileExt));
hash.put("filetype", fileExt);
}
hash.put("filename", fileName);
hash.put("datetime",
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(file
.lastModified()));
fileList.add(hash);
}
}
if ("size".equals(order)) {
Collections.sort(fileList, new SizeComparator());
} else if ("type".equals(order)) {
Collections.sort(fileList, new TypeComparator());
} else {
Collections.sort(fileList, new NameComparator());
}
JSONObject result = new JSONObject();
result.put("moveup_dir_path", moveupDirPath);
result.put("current_dir_path", currentDirPath);
result.put("current_url", currentUrl);
result.put("total_count", fileList.size());
result.put("file_list", fileList);
response.setContentType("application/json; charset=UTF-8");
out.println(result.toJSONString());
out.close();
}
public class NameComparator implements Comparator {
public int compare(Object a, Object b) {
Hashtable hashA = (Hashtable) a;
Hashtable hashB = (Hashtable) b;
if (((Boolean) hashA.get("is_dir"))
&& !((Boolean) hashB.get("is_dir"))) {
return -1;
} else if (!((Boolean) hashA.get("is_dir"))
&& ((Boolean) hashB.get("is_dir"))) {
return 1;
} else {
return ((String) hashA.get("filename"))
.compareTo((String) hashB.get("filename"));
}
}
}
public class SizeComparator implements Comparator {
public int compare(Object a, Object b) {
Hashtable hashA = (Hashtable) a;
Hashtable hashB = (Hashtable) b;
if (((Boolean) hashA.get("is_dir"))
&& !((Boolean) hashB.get("is_dir"))) {
return -1;
} else if (!((Boolean) hashA.get("is_dir"))
&& ((Boolean) hashB.get("is_dir"))) {
return 1;
} else {
if (((Long) hashA.get("filesize")) > ((Long) hashB
.get("filesize"))) {
return 1;
} else if (((Long) hashA.get("filesize")) < ((Long) hashB
.get("filesize"))) {
return -1;
} else {
return 0;
}
}
}
}
public class TypeComparator implements Comparator {
public int compare(Object a, Object b) {
Hashtable hashA = (Hashtable) a;
Hashtable hashB = (Hashtable) b;
if (((Boolean) hashA.get("is_dir"))
&& !((Boolean) hashB.get("is_dir"))) {
return -1;
} else if (!((Boolean) hashA.get("is_dir"))
&& ((Boolean) hashB.get("is_dir"))) {
return 1;
} else {
return ((String) hashA.get("filetype"))
.compareTo((String) hashB.get("filetype"));
}
}
}
}
2.2 第二个Servlet命名为 KindeditorUploadServlet
package cn.javabs.school.servlet;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.json.simple.JSONObject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.*;
@WebServlet("/kindeditorUploadServlet")
public class KindeditorUploadServlet extends HttpServlet {
public KindeditorUploadServlet() {
super();
}
private String getError(String message) {
JSONObject obj = new JSONObject();
obj.put("error", 1);
obj.put("message", message);
return obj.toJSONString();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* KindEditor JSP
*
* 本JSP程序是演示程序,建议不要直接在实际项目中使用。 如果您确定直接使用本程序,使用之前请仔细确认相关安全设置。
*
*/
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
// 文件保存目录路径
String savePath = getServletContext().getRealPath("/") + "attached/";
System.out.println("savePath:" + savePath);
// 文件保存目录URL
String saveUrl = request.getContextPath() + "/attached/";
// 定义允许上传的文件扩展名
HashMap<String, String> extMap = new HashMap<String, String>();
extMap.put("image", "gif,jpg,jpeg,png,bmp");
extMap.put("flash", "swf,flv");
extMap.put("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb");
extMap.put("file", "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2");
// 最大文件大小
long maxSize = 1000000;
response.setContentType("application/json; charset=UTF-8");
if (!ServletFileUpload.isMultipartContent(request)) {
out.println(getError("请选择文件。"));
return;
}
// 检查目录
File uploadDir = new File(savePath);
if (!uploadDir.isDirectory()) {
uploadDir.mkdirs();
// out.println(getError("上传目录不存在。"));
return;
}
// 检查目录写权限
if (!uploadDir.canWrite()) {
out.println(getError("上传目录没有写权限。"));
return;
}
String dirName = request.getParameter("dir");
if (dirName == null) {
dirName = "image";
}
if (!extMap.containsKey(dirName)) {
out.println(getError("目录名不正确。"));
return;
}
// 创建文件夹
savePath += dirName + "/";
saveUrl += dirName + "/";
File saveDirFile = new File(savePath);
if (!saveDirFile.exists()) {
saveDirFile.mkdirs();
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String ymd = sdf.format(new Date());
savePath += ymd + "/";
saveUrl += ymd + "/";
File dirFile = new File(savePath);
if (!dirFile.exists()) {
dirFile.mkdirs();
}
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");
try {
List items = upload.parseRequest(request);
Iterator itr = items.iterator();
while (itr.hasNext()) {
FileItem item = (FileItem) itr.next();
String fileName = item.getName();
long fileSize = item.getSize();
if (!item.isFormField()) {
// 检查文件大小
if (item.getSize() > maxSize) {
out.println(getError("上传文件大小超过限制。"));
return;
}
// 检查扩展名
String fileExt = fileName.substring(
fileName.lastIndexOf(".") + 1).toLowerCase();
if (!Arrays.<String> asList(extMap.get(dirName).split(","))
.contains(fileExt)) {
out.println(getError("上传文件扩展名是不允许的扩展名。\n只允许"
+ extMap.get(dirName) + "格式。"));
return;
}
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
String newFileName = df.format(new Date()) + "_"
+ new Random().nextInt(1000) + "." + fileExt;
try {
File uploadedFile = new File(savePath, newFileName);
item.write(uploadedFile);
} catch (Exception e) {
out.println(getError("上传文件失败。"));
return;
}
JSONObject obj = new JSONObject();
obj.put("error", 0);
obj.put("url", saveUrl + newFileName);
out.println(obj.toJSONString());
}
}
} catch (FileUploadException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
3. 在jsp中引入以下代码
<!-- 以下是kindEditor 需要用的静态资源 -->
<link rel="stylesheet" href="${pageContext.request.contextPath}/admin/resource/kindEditor/themes/default/default.css" />
<script charset="utf-8" src="${pageContext.request.contextPath}/admin/resource/kindEditor/kindeditor-all-min.js"></script>
<script charset="utf-8" src="${pageContext.request.contextPath}/admin/resource/kindEditor/lang/zh-CN.js"></script>
<script type="text/javascript">
$(function () {
$("#saveUpdateForm").validate({debug:false});
});
</script>
<script>
//默认模式 注意:下方中的content属性值要与textarea的name属性值相同才可以
var editor;
KindEditor.ready(function(K) {
editor = K.create('textarea[name="content"]', {
allowFileManager : true,
uploadJson:'${pageContext.request.contextPath}/kindeditorUploadServlet',
fileManagerJson:'${pageContext.request.contextPath}/kindeditorFileManagerServlet'
});
K('input[name=getHtml]').click(function(e) {
alert(editor.html());
});
K('input[name=isEmpty]').click(function(e) {
alert(editor.isEmpty());
});
K('input[name=getText]').click(function(e) {
alert(editor.text());
});
K('input[name=selectedHtml]').click(function(e) {
alert(editor.selectedHtml());
});
K('input[name=setHtml]').click(function(e) {
editor.html('<h3>Hello KindEditor</h3>');
});
K('input[name=setText]').click(function(e) {
editor.text('<h3>Hello KindEditor</h3>');
});
K('input[name=insertHtml]').click(function(e) {
editor.insertHtml('<strong>插入HTML</strong>');
});
K('input[name=appendHtml]').click(function(e) {
editor.appendHtml('<strong>添加HTML</strong>');
});
K('input[name=clear]').click(function(e) {
editor.html('');
});
});
</script>
<body>
<label>文章正文</label>
<textarea id="entityContent" name="content" style="width:800px;height:400px;visibility:hidden;" data-rule-required="true">
</textarea>
</body>
注意:
因为我在设计分类实体的属性时,采用了描述的单词[description],所以我在表单中的属性值也是description,所以在header中的content需要改成description,才会有效!!!
此时的富文本编辑器就实现了。
但是我还加入一些css样式,在WebContent下创建一个文件夹,命名为css,并且在css文件夹中船舰了一个文件,命名为main.css
代码如下:
@CHARSET "UTF-8";
body {
margin: 20 auto; font-size : 12px;
text-align: center;
font-size: 12px;
}
/* 导航栏 */
ul {
list-style: none;
margin-left: 280px;
}
/*无序列表*/
li {
float: left; /* 向左悬浮起来 */
height: 30px;/* 告诉为30像素 */
width: 100px;/* 宽度为100像素 */
color: white;/* 向左悬浮起来 */
background-color: red;/* 背景颜色为红色 */
margin-left: 3px;/* 每个li向左空开3个像素 */
border-radius: 15px 15px 0 0;/* 属于css3的样式: 加入圆角边框的形式;上边出现圆角弧度,下边没有弧度。若想都设置为带有弧度,可以全部填写15px */
}
/* 未点击时的超链接 */
li a:LINK {
font-size: 14px;/* 字体大小 */
line-height: 32px; /* 字体行高 */
text-decoration: none; /* 去除下划线 */
color: #efefef; /* 字体颜色 */
}
/* 鼠标悬浮时的超链接 */
li a:hover {
background-color: #e151ff;
color: #efefef;
}
/* 添加分类 */
table {
margin: 20 auto;
font-size: 14px;
text-align: center;
}
/*添加分类的按钮*/
#btn1 {
width: 160px;
margin: 20px auto;
box-sizing: border-box;
text-align: center;
border-radius: 4px;
border: 1px solid #c8cccf;
color: #6a6f77;
-web-kit-appearance: none;
-moz-appearance: none;
display: block;
outline: 0;
padding: 0 1em;
text-decoration: none;
height: 2.7em;
width: 30%;
}
.form-input {
-web-kit-appearance: none;
-moz-appearance: none;
font-size: 1.4em;
height: 2.7em;
border-radius: 4px;
border: 1px solid #c8cccf;
color: #6a6f77;
}
input[type="text"], #btn2 {
box-sizing: border-box;
text-align: center;
height: 2.7em;
font-size: 1.4em;
border-radius: 4px;
border: 1px solid #c8cccf;
color: #6a6f77;
-web-kit-appearance: none;
-moz-appearance: none;
display: block;
outline: 0;
padding: 0 1em;
text-decoration: none;
width: 100%;
}
input[type="text"]:focus {
border: 1px solid #ff7496;
}
下载代码
https:///yangsir1688/kindeditor-fileUploadDemo
作者: 杨校
 
 
                     
            
        













 
                    

 
                 
                    