文档章节

【ssm个人博客项目实战07】博客的后台实现

YuKongA
 YuKongA
发布于 2017/05/16 09:17
字数 2274
阅读 115
收藏 1

在前面我们已经完成了博客类别的添加修改删除分页查询操作了,现在我们就来完成了博客的添加修改

首先创建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方法带参数呢,因为我需要实现模糊分页查询的功能的,所以你对应查询记录的总数也要带上参数。其中的<if> <set>是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":{"$ref":"$.1"}}
    第一个对象正常序列化,第二个对象则用引用表示
  • 第二个列子序列化后输出结果为:{"1":{"1":{"$ref":".."}}}

    关闭循环引用/重复引用

    fastjson默认对json序列化的时候进行循环引用的检测,从而避免了出现StackOverFlow异常。当序列化后的JSON传输到浏览器或者其他语言中,这些json解析器不支持循环引用,从而导致数据丢失。你可以关闭fastjson的循环引用检测。
    全局配置关闭
    javaJSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();

非全局关闭

JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);

当我们的博客属于同一个类型的时候 也就是说blogType属性相同的时候就会出现循环引用的情况 这样我们就需要关闭循环引用了。
这样控制层写完了
接下来我们可以使用postman测试了

下一节我们将实现博客的前台实现

© 著作权归作者所有

YuKongA
粉丝 6
博文 10
码字总数 15504
作品 0
私信 提问
ZHENFENGSHISAN/perfect-ssm

Quick Start 项目简介 ssm系列 ssm-demo:Spring+SpringMVC+Mybatis+easyUI整合 perfect-ssm:RESTful API+redis缓存 ssm-cluster:前后端分离+集群部署 ssm-dubbo:dubbo服务化 ssm-micro-se......

ZHENFENGSHISAN
2017/09/18
0
0
Java实现个人博客网站

说明:该项目是实验楼用户“LOU3165780622”发布在实验楼上的项目教程:【Java实现个人博客】,未经允许,禁止转载; 该项目利用 SSM 框架和 Mysql 以及一些简单的前端知识搭建一个自己的个人...

实验楼
2017/12/12
0
0
SSM(十一) 基于dubbo的分布式架构

前言 现在越来越多的互联网公司还是将自己公司的项目进行服务化,这确实是今后项目开发的一个趋势,就这个点再凭借之前的项目来让第一次接触的同学能快速上手。 浅谈分布式架构 单看这个名字...

crossoverJie
2017/04/08
5.3K
11
基于SpringBoot构建个人博客

最近心血来潮,想与大家分享一下SpringBoot应用实战,以一个简单的博客项目来带领大家使用SpringBoot,让大家体会SpringBoot的简单。 本系列视频总共分为8节,会手把手教大家写一个博客系统,...

水门_
2017/12/18
0
0
手写spring+springmvc+mybatis框架篇

我们平日开发时所用的SSM框架,可是你真的了解它吗?技术革新,换代应接不暇,只有理解了源码才能保证在技术快速更迭的时代中真正站稳脚跟。 本系列文章抽丝剥茧,源码分析百度有很多,在这里...

技术小能手
2018/07/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

堆”和“栈

C++作为一款C语言的升级版本,具有非常强大的功能。它不但能够支持各种程序设计风格,而且还具有C语言的所有功能。我们在这里为大家介绍的是其中一个比较重要的内容,C++内存区域的基本介绍。...

SibylY
20分钟前
2
0
总结:Https

一、介绍 简单理解,https即在http协议的基础上,增加了SSL协议,保障数据传输的安全性。 它由以前的http—–>tcp,改为http——>SSL—–>tcp;https采用了共享密钥加密+公开密钥加密的方式 ...

浮躁的码农
23分钟前
2
0
数据库表与表之间的一对一、一对多、多对多关系

表1 foreign key 表2 多对一:表 1 的多条记录对应表 2 的一条记录 利用foreign key的原理我们可以制作两张表的多对多,一对一关系 多对多: 表1的多条记录可以对应表2的一条记录 表2的多条记...

Garphy
54分钟前
6
0
MySQL 表崩溃修复

MySQL日志报错 2019-10-19 13:41:51 19916 [ERROR] /usr/local/mysql/bin/mysqld: Table './initread_hss/user_info' is marked as crashed and should be repaired2019-10-19 13:41:51 1......

雁南飞丶
今天
6
0
Error和Exception

1.Error类和Exception类都是继承Throwable类 2.Error(错误)是系统中的错误,程序员是不能改变的和处理的,是在程序编译时出现的错误,只能通过修改程序才能修正。一般是指与虚拟机相关的问...

大瑞清_liurq
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部