基于spring的博客系统(二)

 4. 业务代码

 4.1 持久层

        根据需求, 先⼤致计算有哪些DB相关操作, 完成持久层初步代码, 后续再根据业务需求进⾏完善

        1. ⽤⼾登录⻚

                a. 根据⽤⼾名查询⽤⼾信息

        2. 博客列表⻚

                a. 根据id查询user信息

                b. 获取所有博客列表

        3. 博客详情⻚

                a. 根据博客ID查询博客信息

                b. 根据博客ID删除博客(修改delete_flag=1)

        4. 博客修改⻚

                a. 根据博客ID修改博客信息

        5. 发表博客

                a. 插⼊新的博客数据

        根据以上分析, 来实现持久层的代码:

package com.example.spring_blog_24_9_8.mapper;

import com.example.spring_blog_24_9_8.model.Blog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;
@Mapper
public interface BlogMapper {

    @Select("Select id,title,content,user_id,delete_flag,create_time,update_time" +
            "from blog where delete_flag = 0 order by create_time desc")
    List<Blog> selectAllBlogs();


    @Insert("insert into blog (title,content,user_id) values (#{title},#{content},#{userId})")
    int insertBlog(Blog record);

    @Select("select * from blog where id = #{id}")
    Blog selectById(Integer id);

    int updateBlog(Blog blog);

}
package com.example.spring_blog_24_9_8.mapper;

import com.example.spring_blog_24_9_8.model.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserMapper {

    @Select("select id, user_name, password, github_url, delete_flag, create_time " +
            "from user where id = #{id}")
    User selectById(Integer id);

    @Select("select id, user_name, password, github_url, delete_flag, create_time " +
                "from user where user_name = #{userName}")
    User selectByName(String name);

}
<?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="com.example.spring_blog_24_9_8.mapper.BlogMapper">
    <update id="updateBlog">
        update blog
        <set>
            <if test="title!=null">
                title = #{title},
            </if>
            <if test="content!=null">
                content = #{content},
            </if>
            <if test="deleteFlag!=null">
                delete_flag = #{deleteFlag},
            </if>
        </set>
        where id = #{id}
    </update>
</mapper>

书写测试⽤例, 简单进⾏单元测试 

package com.example.spring_blog_24_9_8.mapper;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    void selectById() {
        System.out.println(userMapper.selectById(2));
    }

    @Test
    void selectByName() {
        System.out.println(userMapper.selectByName("shenmengyao"));

    }
}

selectbyid结果如下:

selestbyname结果如下:

package com.example.spring_blog_24_9_8.mapper;

import com.example.spring_blog_24_9_8.model.Blog;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class BlogMapperTest {

    @Autowired
    private BlogMapper blogMapper;


    @Test
    void selectAllBlogs() {
        System.out.println(blogMapper.selectAllBlogs());
    }

    @Test
    void insertBlog() {
        Blog blog = new Blog();
        blog.setTitle("测试接⼝");
        blog.setContent("单元测试测试接⼝测试接⼝");
        blog.setUserId(1);
        blogMapper.insertBlog(blog);
    }

    @Test
    void selectById() {
        System.out.println(blogMapper.selectById(3));
    }

    @Test
    void updateBlog() {
        Blog blog = new Blog();
        blog.setId(3);
        blog.setDeleteFlag(1);
        blog.setTitle("测试修改接⼝");
        blog.setContent("测试修改接⼝测试修改接⼝测试修改接⼝");
        blogMapper.updateBlog(blog);
    }
}

selectallblogs结果如下:

insertblog结果如下:

 selectbyid结果如下:

updateblog结果如下:

4.2 实现博客列表

4.2.1 约定前后端交互接⼝ 

[请求]
/blog/getlist
[响应]
{
 "code": 200,
 "msg": "",
 "data": [{
 "id": 1,
 "title": "第⼀篇博客",
 "content": "111我是博客正⽂我是博客正⽂我是博客正⽂",
 "userId": 1,
 "deleteFlag": 0,
 "createTime": "2023-10-21 16:56:57",
 "updateTime": "2023-10-21T08:56:57.000+00:00"
 },
 .....
 ]
}

        客⼾端给服务器发送⼀个 /blog/getlist 这样的 HTTP 请求, 服务器给客户端返回了⼀个 JSON 格 式的数据.

4.2.2 实现服务器代码

控制层代码:

@RestController
@RequestMapping("/blog")
public class BlogController {
    @Autowired
    private BlogService blogService;

    @RequestMapping("/getList")
    public List<Blog> getList(){
        return blogService.getBlogList();
    }
}

服务层代码 :

@Service
public class BlogService {
    @Autowired
    private BlogMapper blogMapper;

    public List<Blog> getBlogList(){
        return blogMapper.selectAllBlogs();
    }
}

运行程序,浏览器访问http://127.0.0.1:8087/blog/getList,结果如下:

 4.2.3 实现客⼾端代码

        修改 blog_list.html, 删除之前写死的博客内容, 并新增 js 代码处理 ajax 请求;

        使⽤ ajax 给服务器发送 HTTP 请求.;

        服务器返回的响应是⼀个 JSON 格式的数据, 根据这个响应数据使⽤ DOM API 构造⻚⾯内容.         

        响应中的 postTime 字段为 ms 级时间戳, 需要转成格式化⽇期.

        跳转到博客详情⻚的 url 形如 blog_detail.html?blogId=1 这样就可以让博客详情⻚知道 当前是要访问哪篇博客.

 前端代码修改如下:

   function getBlogList() {
            $.ajax({
                type: "get",
                url: "/blog/getList",
                success: function (result) {
                    //逻辑不全
                    //可以再完善, 比如code==200, 但是data为空的, 页面可以提示: 当前还没有任何博客, 快去写博客吧...
                    if (result.code == 200 && result.data != null && result.data.length > 0) {
                        //循环拼接数据到document
                        var finalHtml = "";
                        //页面展示
                        for (var blog of result.data) {
                            finalHtml += '<div class="blog">';
                            finalHtml += '<div class="title">' + blog.title + '</div>';
                            finalHtml += '<div class="date">' + blog.createTime + '</div>';
                            finalHtml += '<div class="desc">' + blog.content + '</div>';
                            finalHtml += '<a class="detail" href="blog_detail.html?blogId=' + blog.id + '">查看全文&gt;&gt;</a>';
                            finalHtml += '</div>';
                        }
                        $(".right").html(finalHtml);
                    }
                },
                error: function (error) {
                    console.log("后端返回失败");
                }
            });
        }

        如上图所示,我们当前博客列表页显示的时间为时间戳,我们从后端也⽇期进⾏处理;SimpleDateFormat,格式参考官⽅⽂档:

/**
 * 日期工具类
 */
public class DateUtils {

    public static String format(Date date){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return simpleDateFormat.format(date);
    }
}

         重写获取博客创建时间:

@Data
public class Blog {
    private Integer id;
    private String title;
    private String content;
    private Integer userId;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;

    public String getCreateTime(){
        return DateUtils.format(createTime);
    }
}

        重新访问博客列表页,查看页面结果:

4.3 实现博客详情

        ⽬前点击博客列表⻚的 "查看全⽂" , 能进⼊博客详情⻚, 但是这个博客详情⻚是写死的内容. 我们期望 能够根据当前的 博客 id 从服务器动态获取博客内容

4.3.1 约定前后端交互接⼝

[请求]
/blog/getBlogDetail?blogId=1
[响应]
{
 "code": 200,
 "msg": "",
 "data": {
 "id": 1,
 "title": "第⼀篇博客",
 "content": "我是神喵我是神喵我是神喵",
 "userId": 1,
"deleteFlag": 0,
 "createTime": "2023-10-21 16:56:57",
 "updateTime": "2023-10-21T08:56:57.000+00:00"
 }
}

4.3.2 实现服务器代码

        在BlogController中添加getBlogDeatail ⽅法

@RequestMapping("/getBlogDetail")
    public Blog getBlogDetail(Integer blogId){
        return blogService.getBlogDetail(blogId);
    }

在BlogService 中添加getBlogDeatil⽅法

 public Blog getBlogDetail(Integer blogId){
        return blogMapper.selectById(blogId);
    }

        访问http://127.0.0.1:8087/blog/getBlogDetail?blogId=1,结果如下:

4.3.3 实现客户端代码

        修改 blog_content.html :

        根据当前⻚⾯ URL 中的 blogId 参数(使⽤ location.search 即可得到形如 ?blogId=1 的数据), 给服务器发送 GET /blog 请求.

         根据获取到的响应数据, 显⽰在⻚⾯上

1. 修改html⻚⾯, 去掉原来写死的博客标题, ⽇期和正⽂部分 ,代码如下:

 <div class="content">
                <div class="title"></div>
                <div class="date"></div>
                <div class="detail"></div>
                <div class="operating">
                    <button onclick="window.location.href='blog_update.html'">编辑</button>
                    <button>删除</button>
                </div>
            </div>

2. 完善 js 代码, 从服务器获取博客详情数据.

 $.ajax({
            type: "get",
            url: "/blog/getBlogDetail" + location.search,
            success: function (result){
                console.log(result);
                if(result.code == 200 && result.data != null){
                    $(".title").text(result.data.title);
                    $(".date").text(result.data.createTime);
                    $(".detail").text(result.data.detail);

                }   
            }
        })

前进入到博客列表页,点击其中的查看全文进入到文章全文页面:

        点击编辑进入到文章更新页面:

ps:谢谢观看!!!

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于Spring Boot的个人博客系统源码是一个基于Java语言开发的Web应用程序,可以实现个人分享、发布文章、管理评论等功能。该源码会基于Spring Boot框架来构建整个系统,使用Spring MVC来实现页面的展示和交互,利用Spring Data JPA来管理数据库操作,同时整合Thymeleaf模板引擎来实现页面的动态渲染。此外,该源码还会使用Spring Security来实现用户认证和权限控制,保障用户数据的安全性。 博客系统的源码会包括用户管理模块、文章管理模块、评论管理模块等功能。用户管理模块将包括用户注册、登录、个人信息修改等功能;文章管理模块将包括文章的发布、编辑、删除等功能;评论管理模块将包括评论的查看、回复、删除等功能。整个系统的源码会注重用户体验和系统性能,设计到前端页面的响应式布局和后端数据的高效管理。 另外,该源码还会考虑系统的扩展性和可维护性,会遵循MVC的设计模式,将页面、逻辑处理和数据管理做到清晰分离,还会注重代码的规范和注释,方便其他开发人员进行次开发和维护。同时,会充分利用Spring Boot提供的快速开发特性,加速系统的建设过程。 综上所述,基于Spring Boot的个人博客系统源码将会是一个强大的、高可用性的系统,可以满足用户的基本需求,而且具有良好的扩展性和可维护性,是一个值得学习和使用的优秀开源项目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值