JSP后台管理系统
开发工具是IntelliJ IDEA+tomcat+mysql5.6.19+mysql-connector-java-5.1.48.jar+easyui+kindeditor
之前也有记录一些Servlet基础(java,idea)
这篇我只把一些重要的记录一下
easyui很简单,而且中文文档介绍得很详细,对照文档做就好了
kindeditor问题比较多,这里记录一下
准备工作
mysql数据库test中建立t_hp_new表
thumb是缩略图,为blob类型,这里先不考虑这个。建立New类been数据的时候,把thumb定义为String类型
kindeditor的使用
·初始化
在需要使用kindeditor的地方添加
<link type="text/css" href="kindeditor-4.1.11-zh-CN/kindeditor/themes/default/default.css" rel="stylesheet"> <script type="text/javascript" src="kindeditor-4.1.11-zh-CN/kindeditor/kindeditor-all.js"></script> <script type="text/javascript" src="kindeditor-4.1.11-zh-CN/kindeditor/kindeditor-all-min.js"></script> <script type="text/javascript" src="kindeditor-4.1.11-zh-CN/kindeditor/lang/zh-CN.js"></script>
内容编辑区域是一个富文本框
<th> <textarea id="editor" name="editor" style="height:480px;width:900px"></textarea> </th>
初始化
<script type="text/javascript"> let editor KindEditor.ready(function (K) { editor=K.create(‘textarea[id="editor"]‘,{ items:[‘source‘, ‘undo‘, ‘|‘, ‘redo‘, ‘|‘, ‘cut‘, ‘copy‘, ‘paste‘, ‘|‘, ‘plainpaste‘, ‘|‘, ‘fontname‘, ‘fontsize‘, ‘forecolor‘, ‘hilitecolor‘, ‘bold‘, ‘italic‘, ‘underline‘, ‘strikethrough‘, ‘|‘, ‘justifyleft‘, ‘justifyright‘, ‘justifycenter‘, ‘|‘, ‘image‘, ‘insertfile‘, ‘link‘, ‘code‘], }) }) </script>
items:可选
添加插入图片功能
添加uploadJson:"kindeditor-4.1.11-zh-CN/kindeditor/jsp/upload_json.jsp"
把jsp/lib下的jar包粘贴到web工程的lib目录下
此时提示上传目录不存在
然后修改upload_json.jsp的savepath
String savePath=request.getSession().getServletContext().getRealPath("/");
在这里顺便把saveUrl也改了,因为后面会用到saveUrl
(这个问题不一定是这样,也可以试着在web目录下新建一个attached目录)
把上图图片插入到编辑框里
默认上传图片后,点显示html源码它是这样的,浏览器错误提示Not allowed to load local resource
<img>标签不允许引用本地磁盘的图片
一种解决办法是把src后的url的图片转换成base64编码
定义编码函数
看情况导入包,如果提示错误The import java.util.Base64.Encoder collides with another import statement就去掉
<%@ page import="java.util.Base64.Encoder" %> <%@ page import="java.util.Base64.Decoder" %>
//图片编码 <%! public String getBaseImg(String imgPath){ InputStream in=null; byte[] data=null; try{ in=new FileInputStream(imgPath); data=new byte[in.available()]; in.read(data); in.close(); }catch (Exception e) { e.printStackTrace(); } Base64.Encoder encoder=Base64.getEncoder(); String encode=encoder.encodeToString(data); return encode; } %>
在传递saveUrl之前,对saveUrl进行编码处理
JSONObject obj = new JSONObject();
//
String saveUrlEncode="data:image/jpeg;base64,"+getBaseImg(saveUrl + newFileName);
obj.put("error", 0);
obj.put("url", saveUrlEncode);
out.println(obj.toJSONString());
记得要加"data:image/jpeg;base64,"这个加在base64编码前,<img>标签才能正常显示
kindeditor编辑框内容上传
在表单提交之前首先要把kindeditor的内容同步到textarea中,使用
editor.sync()
那这样提交一下就厉害了,发送这么一长串请求会遇到问题:
比如java.lang.IllegalArgumentException: Request header is too large 请求头太大
具体可以参考Servlet基础(java,idea)之前提到改成post会乱码,是因为没有添加req.setCharacterEncoding("utf-8");(那这里就可以把get请求改成post了,不用之后的对内容进行url编码)
还有一个easyui也不能正常读取新闻列表了
这是因为之前读取数据库的数据,把数据转换成Json数据(使用json-lib),而json数据里不能存在html的一些标签,特殊符号的。具体的错误提示at net.sf.json.util.JSONTokener.syntaxError
那在New的java been类中,添加一个自定义的tostring1()函数,把content转化为url编码
public String toString1() { Long date=0L; if(pubdate!=null){ date=pubdate.getTime(); } SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); String dateString=sdf.format(date); String contentUrlEncode= URLEncoder.encode(content); return "{" + "id=" + id + ", title=‘" + title + ‘\‘‘ + ", author=‘" + author + ‘\‘‘ + ", pubDate=" + dateString + ", origin=‘" + origin + ‘\‘‘ + ", href=‘" + href + ‘\‘‘ + ", content=‘" + contentUrlEncode + ‘\‘‘ + ", thumb=‘" + thumb + ‘\‘‘ + ‘}‘; }
在执行select * from t_hp_new查询的时候,会输出很长的字段值,那这个暂时没办法了
关于缩略图上传(也可以是通用图片上传)
先是form表单要改一下,添加enctype="multipart/form-data"
<form id="fm" method="post" enctype="multipart/form-data">
点击提交,发现浏览器上传这样一段数据(request payload)
------WebKitFormBoundary8BC9g9ZlOORkXrkN Content-Disposition: form-data; name="title" a ------WebKitFormBoundary8BC9g9ZlOORkXrkN Content-Disposition: form-data; name="thumb"; filename="1.png" Content-Type: image/png ------WebKitFormBoundary8BC9g9ZlOORkXrkN Content-Disposition: form-data; name="editor" b ------WebKitFormBoundary8BC9g9ZlOORkXrkN Content-Disposition: form-data; name="author" c ------WebKitFormBoundary8BC9g9ZlOORkXrkN Content-Disposition: form-data; name="origin" d ------WebKitFormBoundary8BC9g9ZlOORkXrkN Content-Disposition: form-data; name="href" e ------WebKitFormBoundary8BC9g9ZlOORkXrkN--
(改成get请求,好像是正常title=%E5%93%88%E5%93%88&thumb=1.jpg&editor=00&author=ee&origin=dd&href=ex;这里还是改回post)
上面那段字符串,分为两种域,一种是图片文件的域
------WebKitFormBoundary8BC9g9ZlOORkXrkN Content-Disposition: form-data; name="thumb"; filename="1.png" Content-Type: image/png
一种是普通from的域
d ------WebKitFormBoundary8BC9g9ZlOORkXrkN Content-Disposition: form-data; name="href"
接下来就有点傻了,我们要在字符串里,截取文件filename,Content-Type和name以及下面的值。那就先随便试一下
这个看起来很复杂,但是思路是挺简单的。这里没必要看别人的代码,自己动手实践一下就好
public class main { public static void main(String[] args) { String str = "------WebKitFormBoundaryoAZzkCVEWZ0J434f\n" + "Content-Disposition: form-data; name=\"title\"\n" + "WO\n" + "------WebKitFormBoundaryoAZzkCVEWZ0J434f\n" + "Content-Disposition: form-data; name=\"thumb\"; filename=\"1.jpg\"\n" + "Content-Type: image/png\n" + "------WebKitFormBoundaryoAZzkCVEWZ0J434f\n" + "Content-Disposition: form-data; name=\"editor\"\n" + "HAHA\n" + "------WebKitFormBoundaryoAZzkCVEWZ0J434f\n" + "Content-Disposition: form-data; name=\"author\"\n" + "DD\n" + "------WebKitFormBoundaryoAZzkCVEWZ0J434f\n" + "Content-Disposition: form-data; name=\"origin\"\n" + "EE\n" + "------WebKitFormBoundaryoAZzkCVEWZ0J434f\n" + "Content-Disposition: form-data; name=\"href\"\n" + "SS\n" + "------WebKitFormBoundaryoAZzkCVEWZ0J434f--\n"; String contentType = "multipart/form-data; boundary=----WebKitFormBoundaryoAZzkCVEWZ0J434f"; int position = contentType.indexOf("boundary="); position += ("boundary=").length(); String boundary = "--" + contentType.substring(position); String lastboundary = boundary + "--"; System.out.println(lastboundary); BufferedReader reader = new BufferedReader(new StringReader(str)); String s = null; while (true) { try { //读取每一行,当读取到最末一行或者返回null的时候结束 s = reader.readLine(); if (s == lastboundary || s == null) break; if (s.startsWith(boundary)) { s = reader.readLine();//读取下一行 if (s != null) { if(s.indexOf("filename=")!=-1){ //上传图片域 //截取文件名 int pos=s.indexOf("filename="); pos+="filename=".length(); String filename=s.substring(pos); filename=filename.replace("\"",""); //继续获取图片文件类型 s=reader.readLine(); pos=s.indexOf("Content-Type:"); pos+="Content-Type:".length(); String type=s.substring(pos).replace(" ",""); System.out.println(type); //判断图片类型应该是image/jpeg,image/png,image/gif if(type.equals("image/jpeg")||type.equals("image/png")||type.equals("image/gif")){ System.out.println("上传图片格式正确"); }else { System.out.println("只支持上传jpg,png,gif文件"); } }else { //普通from域 int pos=s.indexOf("name="); pos+="name=".length(); String name=s.substring(pos); name=name.replace("\"",""); //获得name //再读取下一行获取到值 s=reader.readLine(); String value=s; // System.out.println("{name:"+name+",value:"+value+"}"); } } } } catch (Exception e) { e.printStackTrace(); } } } }
那之后的重点是获得图片流数据。当执行
ServletInputStream in = req.getInputStream(); int len = req.getContentLength(); //获得请求数据字节长度 byte[] orginData = new byte[len];//len字节数组 orginData=in.readAllBytes(); in.close(); String orginStr=new String(orginData); System.out.println(orginStr);
会输出一段乱码,那么乱码的位置就是图片流数据的位置。先找到字符串orginStr乱码的开始,结束位置,过程大概是这样
这个过程的代码如下
public class AddNewsServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // req.setCharacterEncoding("utf-8"); // String title=req.getParameter("title"); // String author=req.getParameter("author"); // String content=req.getParameter("editor"); // String origin=req.getParameter("origin"); // String href=req.getParameter("href"); //获得请求流数据,并转换成字符串 ServletInputStream in = req.getInputStream(); int len = req.getContentLength(); //获得请求数据字节长度 byte[] orginData = new byte[len];//len字节数组 orginData=in.readAllBytes(); in.close(); String orginStr=new String(orginData); String contentType=req.getContentType();// int position = contentType.indexOf("boundary="); position += ("boundary=").length(); String boundary = "--" + contentType.substring(position); String lastboundary = boundary + "--"; BufferedReader reader = new BufferedReader(new StringReader(orginStr)); String savePath=req.getSession().getServletContext().getRealPath("/")+"thumb/"; String s = null; JSONObject params=new JSONObject(); while (true) { try { //读取每一行,当读取到最末一行或者返回null的时候结束 s = reader.readLine(); if (s == lastboundary || s == null) break; if (s.startsWith(boundary)) { s = reader.readLine();//读取下一行 if (s != null) { if(s.indexOf("filename=")!=-1){ //上传图片域 //截取文件名 int pos=s.indexOf("filename="); pos+="filename=".length(); String filename=s.substring(pos); filename=filename.replace("\"",""); //继续获取图片文件类型 s=reader.readLine(); pos=s.indexOf("Content-Type:"); pos+="Content-Type:".length(); String type=s.substring(pos).replace(" ",""); System.out.println(type); //判断图片类型应该是image/jpeg,image/png,image/gif if(type.equals("image/jpeg")||type.equals("image/png")||type.equals("image/gif")){ System.out.println("上传图片格式正确"); //重命名图片名称 filename=filename.substring(filename.lastIndexOf(".")); SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmss"); String ymd=sdf.format(new Date()); String newFilename=ymd+filename; //获得图片流开始位置 int typeStart=orginStr.indexOf("Content-Type"); //定位到Content-Type开始位置 int fileStart=orginStr.indexOf("\n",typeStart)+1;//定位到Content-Type下一行 fileStart=orginStr.indexOf("\n",fileStart)+1;//再下一行 //获得图片流结束的位置 int fileEnd=orginStr.indexOf(boundary,fileStart);//从文件开始处开始查找,直到第一个boundary出现 String saveFile=orginStr.substring(fileStart,fileEnd); // System.out.println(saveFile); // System.out.println(orginStr); int contentStart=orginStr.substring(0,fileStart).getBytes().length; int contentEnd=orginStr.substring(0,fileEnd).getBytes().length; FileOutputStream out=new FileOutputStream(savePath+newFilename); out.write(orginData,contentStart,contentEnd); out.close(); }else { System.out.println("只支持上传jpg,png,gif文件"); } }else { //普通from域 int pos=s.indexOf("name="); pos+="name=".length(); String name=s.substring(pos); name=name.replace("\"",""); //获得name //再读取下一行获取到值,可能是空行,那就继续读下一行 while ((s=reader.readLine()).equals("")){ } String value=s; //添加进json params.put(name,value); } } } } catch (Exception e) { e.printStackTrace(); } } System.out.println(params); //获得系统的时间 // Timestamp pubdate=new Timestamp(System.currentTimeMillis()); // int count=new T_NewImpl().addNewsForHp(title,author,content,origin,href,pubdate); // resp.setContentType("text/html;charset=utf-8"); // JSONObject result=new JSONObject(); // result.put("count",count); // // resp.getWriter().println(result); // resp.getWriter().flush(); // resp.getWriter().close(); } }
那如果是这样,看来数据库的thumb字段还是让它是varchar类型好了,就保存一个图片的地址;或者要保存到数据库的话,就把图片流数据写到数据库里吧,之前尝试过,在这里面常用sql语句(mysql测试)
简直不要太累
源码
链接:https://pan.baidu.com/s/1Crxq7HpciMDkTNQ5zannrA
提取码:ebms