基于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 {@Autowiredprivate UserMapper userMapper;@Testvoid selectById() {System.out.println(userMapper.selectById(2));}@Testvoid 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 {@Autowiredprivate BlogMapper blogMapper;@Testvoid selectAllBlogs() {System.out.println(blogMapper.selectAllBlogs());}@Testvoid insertBlog() {Blog blog = new Blog();blog.setTitle("测试接⼝");blog.setContent("单元测试测试接⼝测试接⼝");blog.setUserId(1);blogMapper.insertBlog(blog);}@Testvoid selectById() {System.out.println(blogMapper.selectById(3));}@Testvoid 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 {@Autowiredprivate BlogService blogService;@RequestMapping("/getList")public List<Blog> getList(){return blogService.getBlogList();}
}

服务层代码 :

@Service
public class BlogService {@Autowiredprivate 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) {//循环拼接数据到documentvar 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:谢谢观看!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/423945.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

现代 Web 开发工具箱:Element-UI 表单组件全攻略(二)

现代 Web 开发工具箱&#xff1a;Element-UI 表单组件全攻略&#xff08;二&#xff09; 一 . Switch 开关控件1.1 Switch 组件的创建① 注册路由② 创建 Switch 组件 1.2 Switch 组件的属性① 开关的宽度② 开关 打开/关闭 的文字提示③ 开关打开或者关闭时候的值④ 开关打开或…

Qt控制开发板的LED

Qt控制开发板的LED 使用开发板的IO接口进行控制是嵌入式中非常重要的一点&#xff0c;就像冯诺依曼原理说的一样&#xff0c;一个计算机最起码要有输入输出吧&#xff0c;我们有了信息的接收和处理&#xff0c;那我们就要有输出。 我们在开发板上一般都是使用开发板的GPIO接口…

测试通用面试题大全

24年软件测试的发展如何&#xff1f; 1、IT行业还会继续升温&#xff0c;高质量人才需求相对还是短缺。 2、要求变高之后&#xff0c;很难再下降了&#xff0c;学历和经验。 3、功能测试之外的东西&#xff0c;接口、性能和自动化要掌握一点。 4、长远来看&#xff0c;软件…

数据集 wider_face 人脸数据集 人脸检测 >> DataBall

数据集 wider 人脸检测数据集 WIDER FACE: A Face Detection Benchmark inproceedings{yang2016wider, Author {Yang, Shuo and Luo, Ping and Loy, Chen Change and Tang, Xiaoou}, Booktitle {IEEE Conference on Computer Vision and Pattern Recognition (CVPR)}, Title…

Radware Alteon 负载均衡-基于URL Filetype的七层负载均衡

作者&#xff1a;Xiaolei Ren Radware Alteon作为一款高性能的负载均衡器&#xff0c;其基于URL Filetype的七层负载均衡功能为众多企业提供了灵活、高效的解决方案。 该案例实现如下需求&#xff1a;当客户端访问服务器时&#xff0c;默认访问10.200.1.100&#xff0c;在ht…

【Ubuntu】Ubuntu双网卡配置 实现内外网互不影响同时可用

【Ubuntu】Ubuntu双网卡配置 实现内外网互不影响同时可用 建议前提配置用到的命令参考文献&#xff1a; 建议 本文仅作个人记录&#xff0c;请勿完全照搬&#xff0c;建议直接看此视频&#xff0c;按作者的步骤进行配置 linux配置内外网&#xff08;ubuntu举例&#xff09;&am…

决策树算法上篇

决策树概述 决策树是属于有监督机器学习的一种&#xff0c;起源非常早&#xff0c;符合直觉并且非常直观&#xff0c;模仿人类做决策的过程&#xff0c;早期人工智能模型中有很多应用&#xff0c;现在更多的是使用基于决策树的一些集成学习的算法。 示例一&#xff1a; 上表根据…

Sparse4D v1

Sparse4D: Multi-view 3D Object Detection with Sparse Spatial-Temporal Fusion Abstract 基于鸟瞰图 (BEV) 的方法最近在多视图 3D 检测任务方面取得了重大进展。与基于 BEV 的方法相比&#xff0c;基于稀疏的方法在性能上落后&#xff0c;但仍然有很多不可忽略的优点。为了…

四数之和--力扣18

四数之和 题目思路代码 题目 思路 类似于三数之和&#xff0c;先排序&#xff0c;利用双指针解题。 如果排序后的第一个元素大于目标值&#xff0c;直接返回&#xff0c;为什么nums[i]需要大于等于0&#xff0c;因为目标值可能为负数。比如&#xff1a;数组是[-4, -3, -2, -1…

大数据安全需求分析与安全保护工程

大数据安全威胁与需求分析 特征&#xff1a;海量是数据规模、快速的数据流转、多样的数据类型和价值密度低 种类和来源&#xff1a;结构化、半结构化和非结构化数据 数据种类&#xff1a; 结构化数据&#xff1a;关系模型数据&#xff0c;以关系数据库表形式管理的数据 非…

Docker:对已有的容器,对当前容器映射的端口实时 (增删改查)

首先我的docker已经起了一个容器&#xff0c;我突然想把他的80->80映射的端口改成80->8080 但是我不想去新启动容器&#xff0c;想在现有容器基础上去修改&#xff0c;或者我想删除某个端口映射&#xff08;只是大概思路&#xff09; 如何寻找容器配置文件位置 首先我这…

Linux系统使用Docker安装DockerUI并实现远程管理本地容器无需公网IP

文章目录 前言1. 安装部署DockerUI2. 安装cpolar内网穿透3. 配置DockerUI公网访问地址4. 公网远程访问DockerUI5. 固定DockerUI公网地址 前言 DockerUI是一个docker容器镜像的可视化图形化管理工具。DockerUI可以用来轻松构建、管理和维护docker环境。它是完全开源且免费的。基…

立足本土,面向全球 | 全视通闪耀亮相Medical Fair Asia新加坡医疗展

Medical Fair Asia是亚洲地区最大的医疗设备、医疗器械和医疗技术展览会之一&#xff0c;自1997年创办以来&#xff0c;每两年在新加坡举办一次。该展会不仅是新加坡医疗行业交流的龙头平台&#xff0c;也是亚洲乃至全球医疗企业和专业人士共聚一堂、展示最新产品和技术的重要舞…

红黑树的删除

文章目录 前言一.删除的节点左子树右子树都有二.删除的节点只有左/右子树删除调整操作 三.删除的节点没有孩子1.删除的节点为红色2.删除的节点为黑色1).兄弟节点为黑色(1).兄弟节点至少有一个红色的孩子节点LL型RR型RL型LR型 (2).兄弟节点没有孩子或所有孩子为黑色 2).兄弟节点…

vue3使用leaflet+trackplayer实现非地图动画轨迹(市场平面图动态轨迹)

vue3使用leaflettrackplayer实现非地图动画轨迹(市场平面图动态轨迹) 先下载 leaflet 和 leaflet-trackplayer两个主要库 leaflet官方文档 npm install leaflet npm install leaflet-trackplayer然后在页面中引用 html <template><button click"playMap&quo…

【时时三省】(C语言基础)指针进阶 例题7

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 二维数组 第一个a 因为它有12个元素 每个元素占4个字节 所以就打印48 第二个a&#xff3b;0&#xff3d;&#xff3b;0&#xff3d; 表示是第一行第一个元素 所…

滑动窗口算法—最小覆盖子串

题目 ”最小覆盖子串“问题&#xff0c;难度为Hard&#xff0c;题目如下&#xff1a; 给你两个字符串 S 和 T&#xff0c;请你在 S 中找到包含 T 中全部字母的最短子串。如果 S 中没有这样一个子串&#xff0c;则算法返回空串&#xff0c;如果存在这样一个子串&#xff0c;则可…

Codeforces practice C++ 2024/9/11 - 2024/9/13

D. Mathematical Problem Codeforces Round 954 (Div. 3) 原题链接&#xff1a;https://codeforces.com/contest/1986/problem/D 题目标签分类&#xff1a;brute force&#xff0c;dp&#xff0c;greedy&#xff0c;implementation&#xff0c;math&#xff0c;two pointers…

[数据集][目标检测]乱堆物料检测数据集VOC+YOLO格式1143张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1143 标注数量(xml文件个数)&#xff1a;1143 标注数量(txt文件个数)&#xff1a;1143 标注…

Java高级Day41-反射入门

115.反射 反射机制 1.根据配置文件re.properties指定信息&#xff0c;创建Cat对象并调用hi方法 SuppressWarnings({"all"}) public class ReflectionQuestion {public static void main(String[] args) throws IOException {//根据配置文件 re.properties 指定信息…