建议从第三篇博文开始看起:https://blog.youkuaiyun.com/DaiYuMeng/article/details/104677362
有任何问题欢迎下方留言=w=
一、界面图
二、难点分析
难点一:“上传封面图”按钮点击时,选择了本地图片后,下方要出现你选择的图片
(1)在该按钮下方放入img标签,display属性设置为none
(2)调用layui的upload方法
(3)upload接口
①点击“上传封面图”按钮,在本地选择一张图片,该图片通过upload接口会上传到服务器上
②然后再返回一个路径returnPath给前台,即该图片的路径(部分路径),例子如图:
③然后再在前面加在服务器前缀地址形成http://localhost:8080/MyBlog/upload/returnPath
(即完整的该图片在服务器上的地址)
④如果你想查找其在本地路径上的地址,你可以通过getServletContext()方法,我将先在WebContent目录下新建了一个upload文件夹,所以我具体获得路径是使用如图方法:
难点二:选择父分类时,子分类联动出现选项
(1)注意这是动态获取后台的数据,不是前台固定写好的
(2)然后获取一级分类,调用相关接口
(3)然后获取二级分类,使用form.on()的方法,myFirstSelect为布局中lay-filter的属性值
难点三:显示富文本编辑器,并保证提交后相关格式也会存储在数据库中
(1)从百度编辑器umedit的官网下载好jsp的压缩包并解压,放置到项目中,在文件下引入相关js文件
还有ueditor.all.js和controller.jsp中会涉及参数的修改,这个比较简单,具体的可以百度一下,或下载我的项目查看一下
(2)进行布局设置,注意id值为editor,id值可以随意设置
(3)初始化富文本编辑器
(4)使用UE.getEditor('editor').getContent方法获取内容(含h5格式)
难点四:保证提交后,标签选择一项后台存储一项,选择两项后台存储两项,三项同理
(由于博文和标签是多对多的关系,故除了博文表和标签表外还多了一张表,是博文和标签之间的关联表)
(1)布局,第二个标签和第三个标签都有一个option,默认为不选择
(2)调用相关方法,显示数据
(3)保证选择多项时,不会选择到重复项
(4)进入提交表单时的addArticle接口,先将其它项插入博文的表中,待成功后再进行判断,插入博文与标签的关联表中
三、代码
由于这个涉及的代码太多了,如果有需要可以下载查看,我就放上一些我觉得容易出错的
Upload.java(处理图片下载文件的接口)
package servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
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 javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import pojo.Data;
import util.JsonUtil;
/**
* Servlet implementation class Upload
*/
@WebServlet("/upload")
public class Upload extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public Upload() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* 后台最后进行一个判断
* 1.判断文件大小
* 2.判断文件宽和高的比值
* 3.上传失败进行提示
* 4.通过map.put("msg","xxxxx")将值传过来
* 5.进行文件扩展名判断
* **/
PrintWriter writer = null;
//1.得到上传文件的保存目录
String savePath = this.getServletContext().getRealPath("/upload");
//ps.这个就是上传文件夹在本地的服务器路径
System.out.println("savePath:"+savePath);
String returnPath;
File file = new File(savePath);
//2.判断上传文件的保存目录是否存在
// 如果目录不存在或者目录是文件
if(!file.exists()&&!file.isDirectory()) {
System.out.println(savePath+"目录不存在,需要创建");
//3.创建目录
file.mkdir();
}
try {
//4.使用apache文件上传组件处理文件步骤
//4.1 创建一个DiskFileItemFactory
DiskFileItemFactory factory = new DiskFileItemFactory();
//4.2 创建一个文件上传解码器
ServletFileUpload upload = new ServletFileUpload(factory);
//4.3解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
//4.4 判断提交上来的数据是否是上传表单的数据
if(!ServletFileUpload.isMultipartContent(request)) {
return;
}
//5.使用ServletFileUpload解析器上传数据
List<FileItem> list = upload.parseRequest(request);
//6.遍历 处理文件
for(FileItem item:list) {
String filename = item.getName();
if(filename==null||filename.trim().equals("")) {
continue;
}
System.out.println(filename);
//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
filename = filename.substring(filename.lastIndexOf("\\") + 1);
//获取item中的上传文件的输入流
InputStream in = item.getInputStream();
//创建一个文件输出流
returnPath = filename;
FileOutputStream out = new FileOutputStream(savePath+"\\"+filename);
//创建一个缓冲区
byte buffer[] = new byte[1024];
//判断输入流中的数据是否已经读完的标识
int len = 0;
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while ((len = in.read(buffer)) > 0) {
//System.out.println("是否写入进了服务器!!!");
out.write(buffer, 0, len);
}
//关闭输入流
in.close();
//关闭输出流
out.close();
//删除处理文件上传时生成的临时文件
item.delete();
Map<String, Object> map = new HashMap<String, Object>();
map.put("code", 0);
map.put("msg", "我从upload的servlet中返回了");
Data data = new Data();
data.setReturnPath(returnPath);
map.put("data", data);
String jsonStr = JsonUtil.beanToString(map);
writer= response.getWriter();
writer.write(jsonStr);
}
}catch(Exception e) {
e.printStackTrace();
}finally {
writer.flush();
writer.close();
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
addArticle.jsp(增加博文页面)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@include file="../base.jsp"%>
<!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>增加博文</title>
<style type="text/css">
#box {
width: 1000px;
margin-left: auto;
margin-right: auto;
background-image: url(../css/image/18.gif);
padding: 20px;
opacity: 0.8;
}
.layui-form-select dl {
z-index: 1999;
}
</style>
</head>
<body>
<div id="box">
<form class="layui-form" action="" enctype="multipart/form-data"
id="myform">
<!-- <h3 style="text-align:center;margin-bottom:20px;text-shadow:1px 1px 2px red;">增加博文</h3> -->
<div class="layui-form-item">
<label class="layui-form-label">文章标题</label>
<div class="layui-input-block" style="width: 420px;">
<input type="text" name="title" required lay-verify="required"
placeholder="请输入标题" autocomplete="off" class="layui-input"
id="article_title">
</div>
</div>
<div class="layui-form-item" style="z-index: 1999px;">
<label class="layui-form-label">文章分类</label>
<div class="layui-input-inline" style="width: 180px;">
<select name="first_category" lay-verify="required"
id="first_category" lay-filter="myFirstSelect">
<option value=""></option>
</select>
</div>
<div class="layui-input-inline" style="width: 180px;">
<select name="second_category" lay-verify="required"
id="second_category" lay-filter="mySecondSelect">
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">置顶</label>
<div class="layui-input-block">
<input type="radio" name="isTop" value="是" title="是"> <input
type="radio" name="isTop" value="否" title="否" checked>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<!-- 在这里放一个img标签 默认不显示 -->
<button type="button" class="layui-btn" id="test1">
<i class="layui-icon"></i>上传封面图
</button>
<!-- style="display:none;" -->
<div style="height: 20px; width: 100%;"></div>
<img src="" id="article_image" class="article_image"
style="display: none; margin-top: 20px;"></img>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">文章内容</label>
<div class="layui-input-block">
<div id="editor" name="article_content"
style="width: 900px; height: 400px;"></div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">标签</label>
<div class="layui-input-inline" style="width: 150px;">
<select name="tag1" id="tag1" lay-verify="" lay-search>
</select>
</div>
<div class="layui-input-inline" style="width: 150px;">
<select name="tag2" id="tag2" lay-verify="" lay-search>
<option id="0">可不选</option>
</select>
</div>
<div class="layui-input-inline" style="width: 150px;">
<select name="tag3" id="tag3" lay-verify="" lay-search>
<option id="0">可不选</option>
</select>
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">博文简介</label>
<div class="layui-input-block">
<textarea placeholder="请输入内容" class="layui-textarea"
id="article_desc"></textarea>
</div>
</div>
<div class="layui-form-item" style="margin-top: 50px;">
<div class="layui-input-block">
<button class="layui-btn" type="button" lay-submit
lay-filter="formDemo">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary"
style="margin-left: 12%;">重置</button>
</div>
</div>
</form>
</div>
</body>
<script>
function getFirstCategory() {
//alert("1-进入了getFirstCategory的方法");
$.post("${ctx}/getFirstCategory", {}, function(result) {
with (result) {
for (var i = 0; i < data.length; i++) {
var option = "<option id="+data[i].category_id+">"
+ data[i].category_name + "</option>";
$("#first_category").append(option);
layui.form.render('select');
}
}
}, "json");
$.ajaxSetup({
cache : false
});
}
function getFirstTag() {
$.post("${ctx}/getFirstTag", {}, function(result) {
with (result) {
for (var i = 0; i < data.length; i++) {
var option = "<option id="+data[i].tag_id+">"
+ data[i].tag_name + "</option>";
$("#tag1").append(option);
$("#tag2").append(option);
$("#tag3").append(option);
layui.form.render('select');
}
}
}, "json");
$.ajaxSetup({
cache : false
});
}
layui.use('form', function() {
//1.初始化form表单
var form = layui.form;
//2.初始化富文本编辑器
var ue = window.UE.getEditor('editor');
//3.获得一级分类
getFirstCategory();
//补充之获得标签(最少选择一个,最多选择三个)
getFirstTag();
//4.获得二级分类
form.on('select(myFirstSelect)', function(data2) {
var category_id = $("#first_category :selected").attr("id");
$.post("${ctx}/getSecondCatgegory", {
parent_id : category_id
}, function(result) {
with (result) {
$("#second_category").html("");
for (var i = 0; i < data.length; i++) {
//alert("2-测试进入了吗")
var option = "<option id="+data[i].category_id+">"
+ data[i].category_name + "</option>";
$("#second_category").append(option);
layui.form.render('select');
}
}
}, "json");
$.ajaxSetup({
cache : false
});
layui.form.render('select');
});
//监听提交
form.on('submit(formDemo)', function(data) {
var tag_id1 = $("#tag1 :selected").attr("id");
var tag_id2 = $("#tag2 :selected").attr("id");
var tag_id3 = $("#tag3 :selected").attr("id");
var category_id = $("#second_category :selected").attr("id");
var article_title = $("#article_title").val();
var article_desc = $("#article_desc").val();
var article_content = UE.getEditor('editor').getContent();
var article_image = $("#article_image").attr("src");
var article_isTop_name = $('input[name="isTop"]:checked').val();
if (article_isTop_name == '是') {
var article_isTop = 1;
} else {
var article_isTop = 0;
}
if(tag_id2==tag_id3&&tag_id2!=0){
layer.msg("不能多次选择同一个标签哦!", {
icon : 2
});
return;
}
if (tag_id1 === tag_id2 || tag_id1 === tag_id3) {
layer.msg("不能多次选择同一个标签哦!", {
icon : 2
});
return;
}
if (article_image == "") {
layer.msg("一定要上传封面图哦!", {
icon : 2
});
return;
}
if(article_desc==""){
layer.msg("博文简介不能为空哦!", {
icon : 2
});
return;
}
// 1.检查是否提交了必填项
$.post("${ctx}/addArticle",//后台地址
{
article_title : article_title,
article_desc : article_desc,
article_content : article_content,
article_image : article_image,
article_isTop : article_isTop,
tag_id1 : tag_id1,
tag_id2 : tag_id2,
tag_id3 : tag_id3,
category_id : category_id
},//需要提交到后台的数据
function(result) {
if (result) {
//添加成功
alert("添加成功");
layer.msg("添加成功", {
icon : 1
});
document.getElementById("myform").reset();
} else {
layer.msg("添加失败", {
icon : 2
});
}
},//回调函数
"json");
});
});
let UPLOAD_FILES;
layui.use('upload', function() {
var upload = layui.upload;
//提示用户上传图片不可以太大了
//执行实例
var uploadInst = upload.render({
elem : '#test1' //绑定元素
,
url : '${ctx}/upload' //上传接口
,
exts : 'jpg|png|jpeg' //可传输文件的后缀
,
accept : 'file' //video audio images
,
done : function(res) {
//上传完毕回调
if (res.code == 0) {
var returnPath = res.data.returnPath;
console.log(returnPath);
$("#article_image")
.attr(
"src",
"http://localhost:8080/MyBlog/upload/"
+ returnPath);
$("#article_image").attr("style",
"display:block;width:135px;height:180px;");
}
},
error : function() {
//请求异常回调
//比如生成一个“重新上传”的按钮
}
});
});
</script>
<script type="text/javascript" src="${ctx}/js/umedit/ueditor.config.js"></script>
<script type="text/javascript" src="${ctx}/js/umedit/ueditor.all.min.js"></script>
<script type="text/javascript"
src="${ctx}/js/umedit/lang/zh-cn/zh-cn.js"></script>
</html>