在前面我們已經完成了博客類別的添加修改刪除分頁查詢操作了,現在我們就來完成了博客的添加修改
首先創建t_blog表
CREATE TABLE `t_blog` (
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '博客類型',
`title` VARCHAR(200) NOT NULL COMMENT '博客題目',
`summary` VARCHAR(400) DEFAULT NULL COMMENT '博客摘要',
`releaseDate` DATETIME DEFAULT NULL COMMENT '發佈日期',
`clickHit` INT(11) DEFAULT NULL COMMENT '評論次數',
`replyHit` INT(11) DEFAULT NULL COMMENT '回覆次數',
`content` TEXT COMMENT '博客內容',
`keyWord` VARCHAR(200) DEFAULT NULL COMMENT '關鍵字',
`type_id` INT(11) DEFAULT NULL COMMENT '外鍵關聯博客類別',
PRIMARY KEY (`id`),
KEY `type_id` (`type_id`),
CONSTRAINT `t_blog_ibfk_1` FOREIGN KEY (`type_id`) REFERENCES `t_blogtype` (`id`)
) ENGINE=INNODB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8;
id 博客主鍵
type_id爲關聯外鍵列 代表所屬博客類別
然後創建對應的實體類
package ssm.blog.entity;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
/**
* @Description 博客實體
* @author xp
*
*/
public class Blog {
private Integer id;
private String title;
private String summary;
private Date releaseDate;
private Integer clickHit;
private Integer replyHit;
private String content;
private String keyWord; //關鍵字,用空格隔開
private BlogType blogType; //博客類型
private Integer blogCount; //博客數量,非博客實際屬性,用於根據發佈日期歸檔查詢
private String releaseDateStr; //發佈日期的字符串,只取年月
private List<String> imageList = new LinkedList<String>();//博客裏存的圖片,主要用於展示縮略圖
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public Date getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(Date releaseDate) {
this.releaseDate = releaseDate;
}
public Integer getClickHit() {
return clickHit;
}
public void setClickHit(Integer clickHit) {
this.clickHit = clickHit;
}
public Integer getReplyHit() {
return replyHit;
}
public void setReplyHit(Integer replyHit) {
this.replyHit = replyHit;
}
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 BlogType getBlogType() {
return blogType;
}
public void setBlogType(BlogType blogType) {
this.blogType = blogType;
}
public List<String> getImageList() {
return imageList;
}
public void setImageList(List<String> imageList) {
this.imageList = imageList;
}
}
其中
blogType 是該博客所屬的博客類型 屬於多對一的關係
blogCount 博客數量,非博客實際屬性,用於根據發佈日期歸檔查詢
releaseDateStr 發佈日期的字符串,只取年月
接下來就是dao
package ssm.blog.dao;
import java.util.List;
import java.util.Map;
import ssm.blog.entity.Blog;
/**
* @Description 博客Dao接口
* @author xp
*
*/
public interface BlogDao {
// 分頁查詢博客
public List<Blog> listBlog(Map<String, Object> map);
// 獲取總記錄數
public Long getTotal(Map<String ,Object> map);
// 根據博客類型的id查詢該類型下的博客數量
public Integer getBlogByTypeId(Integer typeId);
//添加博客
public Integer saveBlog(Blog blog);
//更新博客
public Integer updateBlog(Blog blog);
//刪除博客
public Integer deleteBlog(Integer id);
//通過id獲取博客
public Blog getById(Integer id);
接下來就dao對應mapper文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ssm.blog.dao.BlogDao">
<resultMap type="Blog" id="BlogResult">
<id property="id" column="id"/>
<result property="title" column="title"/>
<result property="summary" column="summary"/>
<result property="releaseDate" column="releaseDate"/>
<result property="clickHit" column="clickHit"/>
<result property="replyHit" column="replyHit"/>
<result property="content" column="content"/>
<result property="keyWord" column="keyWord"/>
<association property="blogType" column="type_id" select="ssm.blog.dao.BlogTypeDao.getById">
</association>
</resultMap>
<select id="listBlog" parameterType="Map" resultMap="BlogResult">
SELECT * FROM t_blog
<where>
<if test="title!=null and title!=''">
and title like "%"#{title}"%"
</if>
<if test="typeId!=null and typeId!=''">
and type_id=#{typeId}
</if>
<if test="releaseDateStr!=null and releaseDateStr!=''">
and DATE_FORMAT(releaseDate,'%Y年%m月')=#{releaseDateStr}
</if>
</where>
ORDER BY releaseDate DESC
<if test="start!=null and end!=null">
limit #{start},#{end}
</if>
</select>
<select id="getTotal" parameterType="Map" resultType="Long">
SELECT COUNT(*) FROM t_blog
<where>
<if test="title!=null and title!=''">
and title like "%"#{title}"%"
</if>
<if test="typeId!=null and typeId!=''">
and type_id=#{typeId}
</if>
<if test="releaseDateStr!=null and releaseDateStr!=''">
and DATE_FORMAT(releaseDate,'%Y年%m月')=#{releaseDateStr}
</if>
</where>
</select>
<select id="getBlogByTypeId" parameterType="Integer" resultType="Integer">
select count(*) from t_blog where type_id=#{typeId}
</select>
<insert id="saveBlog" parameterType="Blog" keyProperty="id" useGeneratedKeys="true">
insert into t_blog VALUES (NULL ,#{title},#{summary},now(),0,0,#{content},#{keyWord},#{blogType.id})
</insert>
<update id="updateBlog" parameterType="Blog">
update t_blog
<set>
<if test="title!=null and title!=''">
title=#{title},
</if>
<if test="summary!=null and summary!=''">
summary=#{summary},
</if>
<if test="content!=null and content!=''">
content=#{content},
</if>
<if test="blogType.id!=null">
type_id=#{blogType.id},
</if>
<if test="clickHit!=null">
clickHit=#{clickHit},
</if>
<if test="replyHit!=null">
replyHit=#{replyHit},
</if>
<if test="keyWord!=null and keyWord!=''">
keyWord=#{keyWord},
</if>
</set>
where id=#{id}
</update>
<delete id="deleteBlog" parameterType="java.lang.Integer">
DELETE FROM t_blog
where id=#{id}
</delete>
<select id="getById" parameterType="java.lang.Integer" resultMap="BlogResult">
SELECT * from t_blog where id=#{id}
</select>
</mapper>
爲什麼getTotal方法帶參數呢,因爲我需要實現模糊分頁查詢的功能的,所以你對應查詢記錄的總數也要帶上參數。其中的 是mybatis提供給我們實現動態sql的工具
association : 一個複雜的類型關聯;許多結果將包成這種類型
其中property實體類屬性 column關聯外鍵類 select給實體類屬性初始化的方法 因爲我們的實體類是BlogType對象 所以我們可以根據type_id的值從BlogTypeDao的getById方法把這條記錄查詢出來並且賦值給blogType屬性
接下來就是service實現
package ssm.blog.service;
import java.util.List;
import java.util.Map;
import ssm.blog.entity.Blog;
import ssm.blog.entity.PageBean;
/**
* @author xp
* @Description 博客Service接口
*/
public interface BlogService {
// 分頁查詢博客
public List<Blog> listBlog(Map<String,Object> map);
// 分頁查詢博客
public PageBean<Blog> listBlog(String title,PageBean<Blog> pageBean);
// 根據博客類型的id查詢該類型下的博客數量
public Integer getBlogByTypeId(Integer typeId);
//添加博客
public Integer saveBlog(Blog blog);
//更新博客
public Integer updateBlog(Blog blog);
//通過id刪除博客
public Integer deleteBlog(Integer id);
//通過id獲取博客
public Blog getById(Integer id);
long getTotal(Map<String, Object> map);
package ssm.blog.service.impl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import ssm.blog.dao.BlogDao;
import ssm.blog.entity.Blog;
import ssm.blog.entity.PageBean;
import ssm.blog.service.BlogService;
/**
* @Description 博客Service實現類
* @author xp
*
*/
@Service("blogService")
public class BlogServiceImpl implements BlogService {
@Resource
private BlogDao blogDao;
public PageBean<Blog> listBlog(String title, PageBean<Blog> pageBean) {
Map<String,Object> map = new HashMap<String,Object>();
//設置查詢條件
map.put("title",title);
//總記錄放入pageBean
pageBean.setTotal(blogDao.getTotal(map));
map.put("start",pageBean.getStart());
map.put("end",pageBean.getEnd());
//把分頁結果放入pageBean
pageBean.setResult(blogDao.listBlog(map));
return pageBean;
}
public List<Blog> listBlog(Map<String,Object> map) {
return blogDao.listBlog(map);
}
public Integer getBlogByTypeId(Integer typeId) {
return blogDao.getBlogByTypeId(typeId);
}
public Integer saveBlog(Blog blog) {
return blogDao.saveBlog(blog);
}
public Integer updateBlog(Blog blog) {
return blogDao.updateBlog(blog);
}
public Integer deleteBlog(Integer id) {
return blogDao.deleteBlog(id);
}
public Blog getById(Integer id) {
return blogDao.getById(id);
}
public long getTotal(Map<String, Object> map) {
return blogDao.getTotal(map);
}
}
直接下來就是controller的實現
package ssm.blog.controller.admin;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ssm.blog.entity.Blog;
import ssm.blog.entity.PageBean;
import ssm.blog.lucene.BlogIndex;
import ssm.blog.service.BlogService;
import ssm.blog.service.CommentService;
import ssm.blog.util.ResponseUtil;
/**
* @author xp
* @Description 管理員博客Controller層
*/
@Controller
@RequestMapping("/admin/blog")
public class BlogAdminController {
@Resource
private BlogService blogService;
//後臺分頁查詢博客信息
@RequestMapping("/listBlog")
public String listBlog(
@RequestParam(value = "page", required = false) String page,
@RequestParam(value = "rows", required = false) String rows,
Blog s_blog,
HttpServletResponse response) throws Exception {
PageBean<Blog> pageBean = new PageBean<Blog>(Integer.parseInt(page), Integer.parseInt(rows));
pageBean = blogService.listBlog(s_blog.getTitle(), pageBean);
//創建json對象
JSONObject result = new JSONObject();
//設置json序列化日期格式
JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";
//禁止對象循環引用
//使用默認日期格式化
String jsonStr = JSONObject.toJSONString(pageBean.getResult(),
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteDateUseDateFormat);
//得到json數組
JSONArray array = JSON.parseArray(jsonStr);
//把結果放入json
result.put("rows", array);
result.put("total", pageBean.getTotal());
//返回
ResponseUtil.write(response, result);
return null;
}
//更新或者新增博客
@RequestMapping(value = "/save")
public String saveBlog(Blog blog,HttpServletResponse response) throws Exception {
int resultTotal = 0;
if(blog.getId()!=null){
//更新操作
resultTotal = blogService.updateBlog(blog);
//更新索引
blogIndex.updateIndex(blog);
}else{
//新增操作
resultTotal = blogService.saveBlog(blog);
//添加索引
blogIndex.addIndex(blog);
}
JSONObject result = new JSONObject();
if(resultTotal > 0) {
result.put("success", true);
} else {
result.put("success", false);
}
ResponseUtil.write(response, result);
return null;
}
//刪除博客
@RequestMapping(value = "delete")
public String deleteBlog(@RequestParam("ids")String ids,HttpServletResponse response) throws Exception {
String[] idsStr = ids.split(",");
for(int i = 0; i < idsStr.length; i++) {
int id = Integer.parseInt(idsStr[i]);
//先刪除博客所關聯的評論 現在沒有完成評論的功能 先註釋
//commentService.deleteCommentByBlogId(id);
blogService.deleteBlog(id);
}
JSONObject result = new JSONObject();
result.put("success", true);
ResponseUtil.write(response, result);
return null;
}
//通過id獲取博客
@RequestMapping(value = "get")
public String getById(@RequestParam("id") String id,HttpServletResponse response) throws Exception {
Blog blog = blogService.getById(Integer.parseInt(id));
String jsonStr = JSONObject.toJSONString(blog);
JSONObject result = JSONObject.parseObject(jsonStr);
ResponseUtil.write(response, result);
return null;
}
}
這裏主要注意一下json序列化的時候
//設置json序列化日期格式
JSON.DEFFAULT_DATE_FORMAT = “yyyy-MM-dd”;
設置序列化時date序列化的格式
如果不設置 時間戳的格式,
設置完格式化日期格式後 就使用該格式序列化日期
還有一個問題就是對象循環引用的問題
什麼是循環引用和重複引用
重複引用:一個對象中的多個屬性同時引用同一個對象
例如
Object obj=new Object();
Map<String,Object> map=new HashMap<>();
map.put("1", obj);
map.put("2", obj);//引用了同一個對象
System.out.println(JSON.toJSONString(map));
循環引用:對象的屬性之間存在相互引用導致循環,會引起StackOverFlow異常
例如:
Map<String,Object> map1=new HashMap<>();
Map<String,Object> map2=new HashMap<>();
map1.put("1",map2);//map1引用了map2
map2.put("1",map1);//map2又引用了map1,導致循環引用
System.out.println(JSON.toJSONString(map1));
fastjson支持循環引用/重複引用,並且是缺省打開的。
* 第一個例子序列化後輸出結果爲:{“1”:{},”2”:{“
第一個對象正常序列化,第二個對象則用引用表示
* 第二個列子序列化後輸出結果爲:{“1”:{“1”:{“$ref”:”..”}}}
關閉循環引用/重複引用
fastjson默認對json序列化的時候進行循環引用的檢測,從而避免了出現StackOverFlow異常。當序列化後的JSON傳輸到瀏覽器或者其他語言中,這些json解析器不支持循環引用,從而導致數據丟失。你可以關閉fastjson的循環引用檢測。
全局配置關閉
```
非全局關閉
```java
JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
當我們的博客屬於同一個類型的時候 也就是說blogType屬性相同的時候就會出現循環引用的情況 這樣我們就需要關閉循環引用了。
這樣控制層寫完了
接下來我們可以使用postman測試了
下一節我們將實現博客的前臺實現