JavaWeb_(视频网站)_四、博客模块1
添加博客
添加博客流程图

创建博客实体
blog实体中包含了三个复杂字段catagory、subCatagory、tag
blog与catagory属于多对一关系
blog与subCatagory属于多对一关系
subCatagory与tag属于多对多关系
catagory与subCatagory属于一对多关系
blog与tag属于多对多关系
package com.Gary.betobe.domain; import java.util.HashSet; import java.util.Set; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.Lob; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; //博客 @Entity public class Blog { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String coverImage; private String title; @Lob private String content; private String keyword; private Long viewNum; private String createTime; //该博客属于哪一个分类 @ManyToOne(targetEntity = Catagory.class) @JoinColumn(name="catagory_id") private Catagory catagory; //该博客属于哪一个小分类 @ManyToOne(targetEntity = SubCatagory.class) @JoinColumn(name="sub_catagory_id") private SubCatagory subCatagory; //博客标签,多对多 @ManyToMany @JoinTable( name = "blog_tag", joinColumns = @JoinColumn(name="blog_id"), inverseJoinColumns = @JoinColumn(name = "tag_id") ) private Set<Tag> blogTags = new HashSet<Tag>(); //该博客是哪一个人发的 @ManyToOne(targetEntity = User.class) @JoinColumn(name="user_id") private User user; protected Blog() { } public Blog(Long id, String coverImage, String title, String content, String keyword, Long viewNum, String createTime, Catagory catagory, SubCatagory subCatagory, Set<Tag> blogTags) { super(); this.id = id; this.coverImage = coverImage; this.title = title; this.content = content; this.keyword = keyword; this.viewNum = viewNum; this.createTime = createTime; this.catagory = catagory; this.subCatagory = subCatagory; this.blogTags = blogTags; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getCoverImage() { return coverImage; } public void setCoverImage(String coverImage) { this.coverImage = coverImage; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getKeyword() { return keyword; } public void setKeyword(String keyword) { this.keyword = keyword; } public Long getViewNum() { return viewNum; } public void setViewNum(Long viewNum) { this.viewNum = viewNum; } public String getCreateTime() { return createTime; } public void setCreateTime(String createTime) { this.createTime = createTime; } public Catagory getCatagory() { return catagory; } public void setCatagory(Catagory catagory) { this.catagory = catagory; } public SubCatagory getSubCatagory() { return subCatagory; } public void setSubCatagory(SubCatagory subCatagory) { this.subCatagory = subCatagory; } public Set<Tag> getBlogTags() { return blogTags; } public void setBlogTags(Set<Tag> blogTags) { this.blogTags = blogTags; } }
package com.Gary.betobe.domain; import java.util.HashSet; import java.util.Set; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; //大分类 @Entity public class Catagory { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String catagory; //大分类下的所有博客 @OneToMany(targetEntity = Blog.class) @JoinColumn(name="catagory_id") private Set<Blog> blogs = new HashSet<Blog>(); //该大分类下的所有小分类 @OneToMany(targetEntity = SubCatagory.class) @JoinColumn(name="catagory_id") private Set<SubCatagory> subCatagorys = new HashSet<SubCatagory>(); protected Catagory() { } public Catagory(Long id, String catagory, Set<Blog> blogs, Set<SubCatagory> subCatagorys) { super(); this.id = id; this.catagory = catagory; this.blogs = blogs; this.subCatagorys = subCatagorys; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getCatagory() { return catagory; } public void setCatagory(String catagory) { this.catagory = catagory; } public Set<Blog> getBlogs() { return blogs; } public void setBlogs(Set<Blog> blogs) { this.blogs = blogs; } public Set<SubCatagory> getSubCatagorys() { return subCatagorys; } public void setSubCatagorys(Set<SubCatagory> subCatagorys) { this.subCatagorys = subCatagorys; } }
package com.Gary.betobe.domain; import java.util.HashSet; import java.util.Set; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; //小分类 @Entity public class SubCatagory { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String subCatagory; //该小分类下的所有博客 @OneToMany(targetEntity = Blog.class) @JoinColumn(name="sub_catagory_id") private Set<Blog> blogs = new HashSet<Blog>(); //这个小分类属于哪一个大分类 @ManyToOne(targetEntity = Catagory.class) @JoinColumn(name="catagory_id") private Catagory catagory; //小分类与标签,多对多 @ManyToMany @JoinTable( name="sub_catagory_tag", joinColumns = @JoinColumn(name = "sub_catagory_id"), inverseJoinColumns = @JoinColumn(name="tag_id") ) private Set<Tag> tags = new HashSet<Tag>(); protected SubCatagory() { } public SubCatagory(Long id, String subCatagory, Set<Blog> blogs, Catagory catagory, Set<Tag> tags) { super(); this.id = id; this.subCatagory = subCatagory; this.blogs = blogs; this.catagory = catagory; this.tags = tags; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getSubCatagory() { return subCatagory; } public void setSubCatagory(String subCatagory) { this.subCatagory = subCatagory; } public Set<Blog> getBlogs() { return blogs; } public void setBlogs(Set<Blog> blogs) { this.blogs = blogs; } public Catagory getCatagory() { return catagory; } public void setCatagory(Catagory catagory) { this.catagory = catagory; } public Set<Tag> getTags() { return tags; } public void setTags(Set<Tag> tags) { this.tags = tags; } }
package com.Gary.betobe.domain; import java.util.HashSet; import java.util.Set; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToMany; //标签 @Entity public class Tag { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String tag; //该标签下的所有博客 @ManyToMany(mappedBy = "blogTags") private Set<Blog> tagBlogs = new HashSet<Blog>(); //该标签下的所有小分类 @ManyToMany(mappedBy = "tags") private Set<SubCatagory> subCatagoryTage = new HashSet<SubCatagory>(); protected Tag() { } public Tag(Long id, String tag, Set<Blog> tagBlogs, Set<SubCatagory> subCatagoryTage) { super(); this.id = id; this.tag = tag; this.tagBlogs = tagBlogs; this.subCatagoryTage = subCatagoryTage; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTag() { return tag; } public void setTag(String tag) { this.tag = tag; } public Set<Blog> getTagBlogs() { return tagBlogs; } public void setTagBlogs(Set<Blog> tagBlogs) { this.tagBlogs = tagBlogs; } public Set<SubCatagory> getSubCatagoryTage() { return subCatagoryTage; } public void setSubCatagoryTage(Set<SubCatagory> subCatagoryTage) { this.subCatagoryTage = subCatagoryTage; } }
数据库多生成了六张表(六个关系)

给catagory大分类添加一些假数据

给sub_catagory大分类下增加小分类

动态将catagory大分类标签显示在subit-post-blog.html上
<div class="post-category submit-post"> <label>Choose Blog Category: <select> <option th:each="catagory:${catagoryList}" th:text="${catagory.catagory}" th:value="${catagory.catagory}">one</option> </select> </label> </div>
上传Bolg标签的Controller层
@RequestMapping("/submitPostBlog")
public String submitPostBlog(Model model)
{
User user = (User) session.getAttribute("user");
baseDataUtils.getData(model,user.getId().toString());
List<Catagory> catagoryList = catagoryService.findAllCatagory();
System.out.println(catagoryList);
model.addAttribute("catagoryList",catagoryList);
return "submit-post-blog.html";
}
package com.Gary.betobe.repository; import org.springframework.data.repository.CrudRepository; import com.Gary.betobe.domain.Catagory; public interface CatagoryRepository extends CrudRepository<Catagory,Long>{ }
package com.Gary.betobe.service; import java.util.List; import org.springframework.stereotype.Service; import com.Gary.betobe.domain.Catagory; @Service public interface CatagoryService { List<Catagory> findAllCatagory(); }

接下来制作当改变了Choose Blog Category大标题后,下边的Choose Blog SubCategory下标题也会跟着改变
给大标题和小标题添加一个隐藏button
<!-- 大标题 --> <div class="post-category submit-post"> <label>Choose Blog Category: <select> <option th:each="catagory:${catagoryList}" th:onclick="catagoryClick([[${#setUtils.getSubCatagorys(catagory.subCatagorys)}]],[[${catagory.id}]])" th:value="${catagory.catagory}" th:text="${catagory.catagory}">one</option> </select> </label> <input required="required" id="catagoryIdInput" type="text" style="display:none;"> </div> <!-- 小标题 --> <div class="post-category submit-post"> <label>Choose Blog SubCategory: <select id="subCatagoryId"> <option value="">one</option> <option value="">two</option> <option value="">three</option> </select> </label> <input required="required" id="subcatagoryInInput" type="text" style="display:none"> </div>
<script type="text/javascript">
function catagoryClick(str,id)
{
//清空select
//获得父元素
var subCatagoryId = document.getElementById("subCatagoryId");
//获得父元素下的所有子元素
var childs = subCatagoryId.childNodes;
//遍历删除
for(var i = childs.length - 1;i>=0;i--)
{
subCatagoryId.removeChild(childs[i]);
}
//切割str
var subCatagory = new Array();
subCatagory = str.split("|");
//1,MAD
//2,MMD
for(var i=0;i<subCatagory.length;i++)
{
//alert(subCatagory[i]);
//2,MMD
var idList = new Array();
idList = subCatagory[i].split(",");
//alert(idList[1]);
//添加option
var option = document.createElement("option");
option.innerHTML = idList[1];
//二级下拉点击事件
option.setAttribute("onclick","subCatagoryClick("+idList[0]+")")
subCatagoryId.appendChild(option);
}
//
$("#catagoryIdInput").val(id);
//alert(str);
}
function subCatagoryClick(id)
{
//给subcatagoryinput赋值
$("#subcatagoryInInput").val(id);
}
</script>

通过Cropper插件更换图片
图片的替换流程图

通过表单提交图片
<form id="uploadBlogCoverImageForm" method="post" enctype="multipart/form-data"> <input type="file" name="file" id="videoUpload" onchange="uploadBlogCover(this)" class="show-for-sr"> </form>
当点击Upload File上传图片按钮后,文件将保存到classpath:static\upload\blog\temp下

上传文件的javascript代码
//上传封面 function uploadBlogCover(e) { //alert(e.files[0].name); var forData = new FormData($("#uploadBlogCoverImageForm")[0]); $.ajax({ type:"POST", cache:false, url:"/uploadImageAJAX", data:forData, processData:false, contentType:false, dataType:"json", success:function(result) { alert("success") }, error:function() { alert("dis success") } }) }
后端处理图片上传请求
@RequestMapping("/uploadImageAJAX")
@ResponseBody
public String uploadImageAJAX(@RequestParam("file")MultipartFile file) throws Exception
{
//保存图片
//创建文件
String path = ResourceUtils.getURL("classpath:").getPath()+"static/upload/blog/temp";
String name = file.getOriginalFilename();
File dest = new File(path + "/" +name);
//如果路径不存在,创建路径
if(!dest.getParentFile().exists())
{
dest.getParentFile().mkdir();
}
//保存文件
file.transferTo(dest);
String json = "{\"success\":"+true+"}";
return json;
}

当图片成功上传到classpath:static\upload\blog\temp后,在ajax中使用cropperMy.replace()将读取图片上传到本地文件夹的位置
cropperMy.replace("http://www.pinzhi365.com/upload/blog/temp/"+fileName,false);
//上传封面 function uploadBlogCover(e) { //alert(e.files[0].name); var fileName = e.files[0].name; var forData = new FormData($("#uploadBlogCoverImageForm")[0]); $.ajax({ type:"POST", cache:false, url:"/uploadImageAJAX", data:forData, processData:false, contentType:false, dataType:"json", success:function(result) { cropperMy.replace("http://www.pinzhi365.com/upload/blog/temp/"+fileName,false); }, error:function() { alert("dis success") } }) }

如何将前端切割好的图片保存分析

Ajax上传Base64格式文件前端书写
<a href="javascript;void(0);" onclick="saveImage()" style="background: #656fc3;border-bottom: 3px solid #424da9" class="button"> <i class="fa fa-plus"></i> Save COVER </a>
//保存切割之后的图片 function saveImage() { //alert("Gary555"); //拿到Base64格式的文本 var base64URL = cropperMy.getCroppedCanvas({width:770,height:370}).toDataURL("image/jpeg"); //ajax保存图片 $.post( [[@{~/uploadCoverAJAX}]], {"base64":base64URL}, function(data) { if(data.success) { $("#coverImageInput").val("blog/cover/"+data.fileName); layer.msg("上传成功!!") } //alert(); //文件路径 }, "json" ) }
后端处理上传的Base64文件图片
@RequestMapping("/uploadCoverAJAX")
@ResponseBody
public String uploadCoverAJAX(String base64) throws Exception
{
//获得classpath在本地的地址
String path = ResourceUtils.getURL("classpath:").getPath() + "static/upload/blog/cover";
//保存图片
File file = new File(path);
if(!file.exists())
{
file.mkdir();
}
//替换数据
if(base64.indexOf("jpeg")!=-1)
{
base64 = base64.replaceFirst("jpeg", "jpg");
}
//获取文件名
String upName = UUID.randomUUID().toString()+System.currentTimeMillis()+"."+base64.substring(11,14);
//将base64中有用的数据保存下来
String iconBase64 = base64.substring(22);
//将base64换位字节数据
byte[] buffer = Base64Coder.decode(iconBase64);
//用FileOutputStream写文件
FileOutputStream out = new FileOutputStream(path + "/" + upName);
out.write(buffer);
out.close();
//返回Json
String json = "{\"success\":"+true+",\"fileName\":\""+upName+"\"}";
return json;
}
前端封装富文本字段
<div class="large-12 columns submit-post"> <button class="button expanded" type="button" onclick="mySubmit()">publish now</button> </div>
富文本表单字段的提交
//自己的表单提交 function mySubmit() { var markup = $(".summernote").summernote('code'); //富文本的内容赋值到textarea中 $("#contentTextarea").text(markup); //表单提交 $("#submitButton").click(); }
<form th:action="@{~/saveBlog}" method="post" data-abide novalidate> <div data-abide-error class="alert callout submit-post" style="display: none;"> <p><i class="fa fa-exclamation-triangle"></i> There are some errors in your form.</p> </div> <div class="row"> <div class="large-12 columns submit-post"> <div class="upload-video"> <label for="videoUpload" class="button">Upload File</label> <span>No file chosen</span> </div> <p class="extraMargin">Please upload the appropriate blog cover recommendation 770 * 370.</p> <!-- 图片切割 --> <div style="width:400px;heigh:280px;"> <img id="image" src="../upload/user/head/1.jpg"> </div> <div> </div> <h6>Perview Cover</h6> <div class="blogCover" style="overflow:hidden;height:770px;width:370px;position:relative;"></div> <div> </div> <a href="javascript:void(0);" onclick="saveImage()" style="background: #656fc3;border-bottom: 3px solid #424da9" class="button"> <i class="fa fa-plus"></i> Save COVER </a> </div> <div class="large-12 columns"> <div class="post-meta submit-post"> <label>Meta Title: <textarea name="title" required="required" placeholder="enter meta title"></textarea> </label> <p>IF you want to put your custom meta Title then put here otherwise your post title will be the default meta Title</p> </div> <div class="post-meta"> <label>Meta Description: </label> <!-- 富文本 --> <div class="summernote"></div> <textarea id="contentTextarea" name="content" style="display:none;"></textarea> <div class="submit-post"> <p>IF you want to put your custom meta description then put here otherwise your post description will be the default meta description</p> </div> </div> <div class="post-meta submit-post"> <label>Meta keywords: <textarea name="keyword" required="required" placeholder="enter meta keywords"></textarea> </label> <p>IF you want to put your custom meta Keywords then put here otherwise your post Keywords will be the default meta Keywords</p> </div> <!-- 大标题 --> <div class="post-category submit-post"> <label>Choose Blog Category: <select> <option th:each="catagory:${catagoryList}" th:onclick="catagoryClick([[${#setUtils.getSubCatagorys(catagory.subCatagorys)}]],[[${catagory.id}]])" th:value="${catagory.catagory}" th:text="${catagory.catagory}">one</option> </select> </label> <input required="required" name="catagoryId" id="catagoryIdInput" type="text" style="display:none;"> </div> <!-- 小标题 --> <div class="post-category submit-post"> <label>Choose Blog SubCategory: <select id="subCatagoryId"> <option value="">one</option> <option value="">two</option> <option value="">three</option> </select> </label> <input required="required" name="subCatagoryId" id="subcatagoryInInput" type="text" style="display:none"> </div> </div> <div class="large-12 columns submit-post"> <label>Tags: <!-- 英文逗号隔开 --> <input name="tagsinput" id="tagsinputval" class="tagsinput" data-role="tagsinput" value="faltui,这是一个标签" placeholder="输入后回车"/> </label> </div> <input id="coverImageInput" name="coverImage" type="text" style="display:none;"> <div class="large-12 columns submit-post"> <button id="submitButton" type="submit" style="display:none;"></button> <button class="button expanded" type="button" onclick="mySubmit()">publish now</button> </div> </div> </form>
小分类与标签绑定关系

更新更新SubCatagory小标签

展示上传图片(期间出了一个bug,栈溢出问题 解决:传送门)

BlogController.java下的saveBlog请求
@RequestMapping("/saveBlog")
public String saveBlog(Blog blog,String tagsinput,String catagoryId,String subCatagoryId)
{
System.err.println("blog = "+blog);
//ViewNum
//createTime
//catagory
System.err.println("catagoryId = "+catagoryId);
//subCatagory
System.err.println("subCatagoryId = "+subCatagoryId);
//user session
//blogTags
System.err.println("tagsinput = "+tagsinput);
//封装分类
Catagory catagory = catagoryService.findCatagoryById(catagoryId);
blog.setCatagory(catagory);
//封装小分类
SubCatagory subCatagory = subCatagoryService.findSubCatagoryById(subCatagoryId);
//blog.setSubCatagory(subCatagory);
//封装创建时间
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm");
String createTime = format.format(date);
blog.setCreateTime(createTime);
//封装标签
//tagsinput = tagsinput.toUpperCase();
String[] tags = tagsinput.split(",");
Set<Tag> blogTags = new HashSet<>();
for(int i=0;i<tags.length;i++)
{
Tag tag = null;
//如果标签不存在,数据库里没有重复的标签
if(tagService.findTagByTag(tags[i]) ==null )
{
//如果没有重复的,可以添加
tag = new Tag(null,tags[i],new HashSet<>(),new HashSet<>());
tag = tagService.saveTag(tag);
}
//如果标签存在
else
{
//不可添加
tag = tagService.findTagByTag(tags[i]);
}
blogTags.add(tag);
//维护subCatagory与tag之间多对多关系
subCatagory.getTags().add(tag);
System.out.println("111");
tag.getSubCatagoryTage().add(subCatagory);
}
//维护blog与tag关系
blog.setBlogTags(blogTags);
blog.setSubCatagory(subCatagory);
//封装发布博客的用户
User user = (User) session.getAttribute("user");
blog.setUser(user);
//封装浏览数目
blog.setViewNum(0L);
//保存
blogService.saveBlog(blog);
return "redirect:/index";
}

浙公网安备 33010602011771号