从0开始实现一个博客系统 (SSM 实现)

news2024/11/16 23:49:27

相关技术

Spring + Spring Boot + Spring MVC + MyBatis
Html + Css + JS

pom 文件我就不放出来了, 之前用的 jdk8 做的, MySQL 用的 5.7, 都有点老了, 你们自己看着配版本就好

实现功能

  1. 用户注册 - 密码加盐加密 (md5 加密)
  2. 前后端用户信息存储 - 令牌技术
  3. 用户登录 - (使用 拦截器 做登录校验)
  4. 博客的增删改查
  5. 后端数据返回前端, 采用 SpringBoot 做统一功能处理和统一异常处理

数据库设计

  1. 用户表
  2. 博客表

在这里插入图片描述

前端页面

博客登录页 (blog_login.html)

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <me_ta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>博客登陆页</title>

    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/login.css">

</head>

<body>
    <div class="nav">
        <img src="pic/logo2.jpg" alt="">
        <span class="blog-title">我的博客系统</span>
        <div class="space"></div>
        <a class="nav-span" href="blog_list.html">主页</a>
        <a class="nav-span" href="blog_edit.html">写博客</a>
    </div>

    <div class="container-login">
        <div class="login-dialog">
            <h3>登陆</h3>
            <div class="row">
                <span>用户名</span>
                <input type="text" name="username" id="username">
            </div>
            <div class="row">
                <span>密码</span>
                <input type="password" name="password" id="password">
            </div>
            <div class="row">
                <button id="submit" onclick="login()">提交</button>
            </div>
        </div>
    </div>
    <script src="js/jquery.min.js"></script>
    <script>
        function login() {
            // 发送 ajax 请求, 获取 token
            $.ajax({
                type: "post",
                url: "/user/login",
                data: {
                    "userName": $("#username").val(),
                    "password": $("#password").val()
                },
                success: function(result) {
                    if(result.code == 200 && result.data != null) {
                        // 存储 token 到本地
                        localStorage.setItem("user_token", result.data);
                        location.href = "blog_list.html";
                    }else{
                        alert("用户名或密码错误");
                    }
                }
            });
        }
    </script>
</body>

</html>

用户登录成功之后, 会将用户信息, 生成令牌, 存储到 request 中, 前后端都能从中获取当前登录用户的信息

博客列表页 (blog_list.html)

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>博客列表页</title>

    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/list.css">

</head>
<body>
    <div class="nav">
        <img src="pic/logo2.jpg" alt="">
        <span class="blog-title">我的博客系统</span>
        <div class="space"></div>
        <a class="nav-span" href="blog_list.html">主页</a>
        <a class="nav-span" href="blog_edit.html">写博客</a>
        <a class="nav-span" href="#" onclick="logout()">注销</a>
    </div>

    <div class="container">
        <div class="left">
            <div class="card">
                <img src="pic/doge.jpg" alt="">
                <h3></h3>
                <a href="#"></a>
                <div class="row">
                    <span>文章</span>
                    <span>分类</span>
                </div>
                <div class="row">
                    <span>2</span>
                    <span>1</span>
                </div>
            </div>
        </div>
        <div class="right">
        </div>
    </div>
    <script src="js/jquery.min.js"></script>
    <script src="js/common.js"></script>
    <script>
        //显示用户信息
        var userUrl = "/user/getUserInfo";
        getUserInfo(userUrl);

        // 获取所有的博客信息
        $.ajax({
            type: "get",
            url: "/blog/getList",
            success: function(result) {
                console.log("result:" + result);
                if(result.code == 200 && result.data != null) {
                    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("error:" + error);
                location.href = "blog_login.html";
                if(error != null && error.state == 401) {
                    location.href = "blog_login.html";
                }
            }
        });
    </script>
</body>
</html>

当前页面会自动调用一个 ajax 请求, 用以获取数据库中 所有未删除博客 的信息进行展示 (博客正文会裁取前100字进行显示)

博客详情页 (blog_detail.html)

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>博客详情页</title>

    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/detail.css">

</head>

<body>
    <div class="nav">
        <img src="pic/logo2.jpg" alt="">
        <span class="blog-title">我的博客系统</span>
        <div class="space"></div>
        <a class="nav-span" href="blog_list.html">主页</a>
        <a class="nav-span" href="blog_edit.html">写博客</a>
        <a class="nav-span" href="#" onclick="logout()">注销</a>
    </div>

    <div class="container">
        <div class="left">
            <div class="card">
                <img src="pic/doge.jpg" alt="">
                <h3></h3>
                <a href="#"></a>
                <div class="row">
                    <span>文章</span>
                    <span>分类</span>
                </div>
                <div class="row">
                    <span>2</span>
                    <span>1</span>
                </div>
            </div>
        </div>
        <div class="right">
            <div class="content">
                <div class="title"></div>
                <div class="date"></div>
                <div class="detail" id="detail" style="background-color: transparent;">
                </div>
                <!-- <div class="operating">
                    <button onclick="window.location.href='blog_update.html'">编辑</button>
                    <button onclick="deleteBlog()">删除</button>
                </div> -->
            </div>

        </div>
    </div>

    <!-- 引入 editor.md 的依赖 -->
    <link rel="stylesheet" href="blog-editormd/css/editormd.css" />
    <script src="js/jquery.min.js"></script>
    <script src="blog-editormd/lib/marked.min.js"></script>
    <script src="blog-editormd/lib/prettify.min.js"></script>
    <script src="blog-editormd/editormd.js"></script>
    <script src="js/common.js"></script>
    <script>
        // 获取博客详情
        $.ajax({
            type: "get",
            url: "/blog/getBlogDetail"+location.search,
            success: function(result) {
                console.log(result);
                if(result.code == 200 && result.data != null) {
                    console.log("abc" + result);
                    var blog = result.data;
                    $(".right .content .title").text(blog.title);
                    $(".right .content .date").text(blog.createTime);
                    // $(".right .content .detail").text(blog.content);
                    editormd.markdownToHTML("detail", {
                        markdown: blog.content,
                    });
                    // 是否显示 编辑/删除 按钮
                    if(blog.isLoginUser == true) {
                        var html = "";
                        html += '<div class="operating">';
                        html += '<button onclick="window.location.href=\'blog_update.html'+location.search+'\'">编辑</button>';
                        html += '<button onclick="deleteBlog()">删除</button>';
                        html += '</div>';

                        $(".content").append(html);
                    }
                }
            },
            error: function(error) {
                if(error != null && error.status == 401) {
                    location.href = "blog_list.html";
                }
            }
        });
        
        //显示博客作者信息
        var userUrl = "/user/getAuthorInfo" + location.search;
        getUserInfo(userUrl);

        function deleteBlog() {
            $.ajax({
                type: "post",
                url: "/blog/delete" + location.search,
                success: function(result) {
                    if(result.code == 200 && result.data != null && result.data == true) {
                        location.href = "blog_list.html";
                    }
                }
            });
        }
    </script>
</body>

</html>

对于每篇博客, 会显示博客信息 (标题, 最后一次的修改时间, 博客正文), 和博客作者的信息 (用户名) (TODO: 作者头像, 作者的总文章数量, 博客的分类所属)
页面会自动校验登录用户是否为当前博客的作者, 如果是, 那么可以对当前博客进行编辑和删除, 如果不是, 这两个按钮不会显示

博客编辑页 (blog_edit.html)

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>博客编辑页</title>

    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/edit.css">
    <link rel="stylesheet" href="blog-editormd/css/editormd.css" />

</head>

<body>
    <div class="nav">
        <img src="pic/logo2.jpg" alt="">
        <span class="blog-title">我的博客系统</span>
        <div class="space"></div>
        <a class="nav-span" href="blog_list.html">主页</a>
        <a class="nav-span" href="blog_edit.html">写博客</a>
        <a class="nav-span" href="#" onclick="logout()">注销</a>
    </div>
    <div class="content-edit">
        <div class="push">
            <input type="text" name="" id="title">
            <input type="button" value="发布文章" id="submit" onclick="submit()">
        </div>
        <!-- markdown 插件 html代码 -->
        <div id="editor">
            <textarea style="display:none;" id="content" name="content">##在这里写下一篇博客</textarea>
        </div>
    </div>

    <script src="js/jquery.min.js"></script>
    <script src="blog-editormd/editormd.min.js"></script>
    <script src="js/common.js"></script>
    <script type="text/javascript">

        $(function () {
            var editor = editormd("editor", {
                width: "100%",
                height: "550px",
                path: "blog-editormd/lib/"
            });
        });

        function submit() {
            $.ajax({
                type: "post",
                url: "/blog/add",
                data: {
                    title: $("#title").val(),
                    content: $("#content").val()
                },
                success: function(result) {
                    if(result.code == 200 && result.data != null && result.data == true) {
                        location.href = "blog_list.html";
                    }else {
                        alert("博客发布失败!");
                    }
                }
            });
        }
    </script>
</body>

</html>

博客编辑页使用了 gittee 上的一个开源 markdown 组件
对于未有博客的 “写博客” , 调用的是 “插入操作”
对于已有博客的 “编辑博客” , 调用的是 “更新操作”
“删除博客” 操作是逻辑删除, 即修改数据库的某一字段, 所以调用的也是 “更新操作”

前端页面共同的 js (common.js)

$(document).ajaxSend(function(e, xhr, opt) {
    // 获取本地存储中的 token
    var user_token = localStorage.getItem("user_token");
    // 将 token 设置到每个 ajax 请求的 header 中
    xhr.setRequestHeader("user_token_header", user_token);
});

// 获取用户信息
function getUserInfo(url) {
    $.ajax({
        type: "post",
        url: url,
        success: function(result) {
            if(result.code == 200 && result.data != null) {
                $(".left .card h3").text(result.data.userName);
                $(".left .card a").attr("href", result.data.githubUrl);
            }
        }
    });
}

// 用户退出
function logout() {
    localStorage.removeItem("user_token");
    location.href = "blog_login.html";
}

主要就是获取当前登录用户的信息, 以及退出登录的逻辑

后端代码

项目的基本框架

在这里插入图片描述

实体类

BlogInfo
@Data
public class BlogInfo {
    private Integer id;
    private String title;
    private String content;
    private Integer userId;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
    private Boolean isLoginUser = false;

    // 返回 String 类型的数据 (BlogInfo 里面存储的是 Date 类型数据)
    public String getCreateTime() {
        return DateUtils.formateDate(createTime);
    }

    public String getUpdateTime() {
        return DateUtils.formateDate(updateTime);
    }
}

对应数据的 blog 表

UserInfo
@Data
public class UserInfo {
    private Integer id;
    private String userName;
    private String password;
    private String githubUrl;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

对应数据的 user 表

Result
@Data
public class Result {
    private int code;  //200成功  -1失败  -2未登录
    private String errMsg;
    private Object data;

    public static Result success(Object data) {
        Result result = new Result();
        result.setCode(Constant.SUCCESS_CODE);
        result.setErrMsg("");
        result.setData(data);
        return result;
    }


    public static Result fail(String errMsg) {
        Result result = new Result();
        result.setCode(Constant.FAIL_CODE);
        result.setErrMsg(errMsg);
        result.setData(null);
        return result;
    }


    public static Result fail(String errMsg, Object data) {
        Result result = new Result();
        result.setCode(Constant.FAIL_CODE);
        result.setErrMsg(errMsg);
        result.setData(data);
        return result;
    }

    public static Result unlogin() {
        Result result = new Result();
        result.setCode(Constant.FAIL_CODE);
        result.setErrMsg("用户未登录");
        result.setData(null);
        return result;
    }

    public static Result unlogin(String errMsg) {
        Result result = new Result();
        result.setCode(Constant.UNLOGIN_CODE);
        result.setErrMsg("用户未登录");
        result.setData(null);
        return result;
    }
}

用于统一数据格式返回 (不知道可以看一下我的另一篇博客 Spring Boot统一功能处理(拦截器, 统一数据返回格式, 统一异常处理) )

Constant 类 (常量值存储)

public class Constant {
    public final static Integer SUCCESS_CODE = 200;

    public final static Integer FAIL_CODE = -1;

    public final static Integer UNLOGIN_CODE = -2;

    public final static String USER_TOKEN_HEADER = "user_token_header";

    public final static String USER_CLAIM_ID = "id";

    public final static String USER_CLAIM_NAME = "name";
}

Mapper 类

通过 MyBatis 操作数据库

BlogMapper
@Mapper
public interface BlogMapper {
    // 查询博客列表
    @Select("select * from blog where delete_flag = 0 order by create_time desc")
    List<BlogInfo> selectAllBlog();

    // 根据博客 ID, 查询博客信息
    @Select("select * from blog where delete_flag = 0 and id = #{blogId}")
    BlogInfo selectById(@Param("blogId") Integer blogId);

    // 根据博客 ID, 修改/删除 博客信息
    Integer updateBlog(BlogInfo blogInfo);

    // 插入博客
    @Insert("insert into blog(title, content, user_id) values(#{blogInfo.title}, #{blogInfo.content}, #{blogInfo.userId})")
    Integer insertBlog(@Param("blogInfo") BlogInfo blogInfo);
}

数据库操作 blog 表

UserMapper
@Mapper
public interface UserMapper {
    // 根据用户名, 查询用户信息
    @Select("select * from user where user_name = #{userName} and delete_flag = 0")
    UserInfo selectByName(@Param("userName") String userName);

    // 根据用户 ID, 查询用户信息
    @Select("select * from user where id = #{userId} and delete_flag = 0")
    UserInfo selectById(@Param("userId") Integer userId);

}

数据库操作 user 表

用户登录页

登录功能

登录页面点击登录按钮后, 触发 controller 层的 login 接口

	@Autowired
    private UserService userService;
    
    // 登录接口
    @RequestMapping("/login")
    public Result login(String userName, String password) {
        // 1.对参数进行校验
        // 2.对密码进行校验
        // 3.如果校验成功, 生成 token
        if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
//            throw new UnsupportedOperationException("用户名或密码不能为空");
            return Result.fail("用户名或密码不能为空");
        }

        // 获取用户信息
        UserInfo userInfo = userService.queryUserByName(userName);
        if(userInfo == null || userInfo.getId() <= 0) {
            return Result.fail("用户不存在");
        }
        
        // 密码校验
        if(!SecurityUtils.verify(password, userInfo.getPassword())) {
            return Result.fail("密码错误");
        }


        // 用户信息正确, 生成 token
        Map<String, Object> claim = new HashMap<>();
        claim.put(Constant.USER_CLAIM_ID, userInfo.getId());
        claim.put(Constant.USER_CLAIM_NAME, userInfo.getUserName());

        return Result.success(JWTUtils.getToken(claim));
    }

login 接口先对前端数据进行判空校验, 然后根据用户名 查询数据库中是否有对应的信息, 将获取信息与输入信息进行比对, 返回登录判定信息 (登录成功生成 token 令牌)

获取用户信息:
在这里插入图片描述
密码校验:

在这里插入图片描述
生成 token 令牌:
在这里插入图片描述

用户注销

用户注销是个前端功能
在 common.js 里面

function logout() {
    localStorage.removeItem("user_token");
    location.href = "blog_login.html";
}

博客列表页

博客列表页获取所有未删除博客的信息进行展示

调用接口 getList

@Autowired
private BlogService blogService;

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

在这里插入图片描述

博客列表页左侧登录用户信息栏, 获取当前登录用户的信息进行展示

调用接口 getUserInfo

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    // 获取当前登录用户的信息
    @RequestMapping("/getUserInfo")
    public UserInfo getUserInfo(HttpServletRequest request) {
        // 1. 获取 token, 从 token 中获取 ID
        String user_token = request.getHeader(Constant.USER_TOKEN_HEADER);
        Integer userId = JWTUtils.getUserIdFromToken(user_token);

        // 2. 根据 ID, 获取用户信息
        if(userId == null || userId <= 0) {
            return null;
        }
        UserInfo userInfo =userService.queryUserByID(userId);
        userInfo.setPassword("");
        return userInfo;
    }
}

在这里插入图片描述

博客详情页

博客详情页右侧获取博客详情信息

调用接口 getBlogDetail

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

    // 根据博客id获取博客信息
    @RequestMapping("/getBlogDetail")
    public BlogInfo getBlogDetail(Integer blogId, HttpServletRequest request) {
        BlogInfo blogInfo = blogService.getBlogDetail(blogId);
        // 获取登录用户信息
        String user_token = request.getHeader(Constant.USER_TOKEN_HEADER);
        Integer userId = JWTUtils.getUserIdFromToken(user_token);
        // 判断登录用户是否为作者
        if(userId != null && userId == blogInfo.getUserId()) {
            blogInfo.setIsLoginUser(true);
        }else {
            blogInfo.setIsLoginUser(false);
        }

        return blogInfo;
    }
}

在这里插入图片描述

博客详情页左侧获取博客作者信息

调用接口 getAuthorInfo

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    // 根据博客 ID, 获取作者信息
    @RequestMapping("/getAuthorInfo")
    public UserInfo getAuthorInfo(Integer blogId) {
        // 校验博客 ID 是否正确
        if(blogId == null || blogId <= 0) {
            return null;
        }

        UserInfo userInfo = userService.queryAuthorInfoByBlogId(blogId);
        userInfo.setPassword("");
        return userInfo;
    }
}

在这里插入图片描述

博客详情页中, 编辑和删除功能

调用接口 update & delete

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

    // 编辑博客
    @RequestMapping("/update")
    public Boolean update(Integer blogId, String title, String content) {
        log.error("blogId:{}, title:{}, content:{}", blogId, title, content);
        if(blogId == null || !StringUtils.hasLength(title) || !StringUtils.hasLength(content)) {
            log.error("update, 参数非法");
            return false;
        }
        BlogInfo blogInfo = new BlogInfo();
        blogInfo.setId(blogId);
        blogInfo.setTitle(title);
        blogInfo.setContent(content);

        log.error("blogInfo:{}", blogInfo);

        Integer result = blogService.updateBlog(blogInfo);
        if(result < 1) return false;
        return true;
    }


    // 删除博客(逻辑删除)
    @RequestMapping("/delete")
    public Boolean delete(Integer blogId) {
        BlogInfo blogInfo = new BlogInfo();
        blogInfo.setId(blogId);
        blogInfo.setDeleteFlag(1);

        log.error("blogInfo:{}", blogInfo);

        Integer result = blogService.updateBlog(blogInfo);
        if(result < 1) return false;
        return true;
    }
}

在这里插入图片描述

博客编辑页

博客撰写后存入数据库

调用接口 add

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

    // 添加博客
    @RequestMapping("/add")
    public Boolean publishBlog(String title, String content, HttpServletRequest request) {

        // 1.参数校验
        if(!StringUtils.hasLength(title) || !StringUtils.hasLength(content)) {
            return false;
        }

        // 2.获取当前用户
        String user_token = request.getHeader(Constant.USER_TOKEN_HEADER);
        Integer userId = JWTUtils.getUserIdFromToken(user_token);
        if(userId == null || userId <= 0) {
            return false;
        }

        // 3.博客发布
        BlogInfo blogInfo = new BlogInfo();
        blogInfo.setUserId( userId);
        blogInfo.setContent(content);
        blogInfo.setTitle(title);

        Integer result = blogService.publishBlog(blogInfo);
        return result<=0 ? false:true;
    }
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++(三)

C&#xff08;三&#xff09; staticc语言的staticc中的staticstatic修饰的成员变量static 修饰成员函数 constc语言cconst修饰成员变量const修饰的成员函数const修饰的类对象 mutable友元普通函数作为友元类的成员函数作为友元友元类 static c语言的static C语言中static的作…

【test】Windows11下通过sshfs挂载远程服务器目录

下载安装下面三个软件&#xff1a; sshfs-win&#xff1a;https://github.com/billziss-gh/sshfs-win/releases winfsp&#xff1a;https://github.com/billziss-gh/winfsp/releases SSHFS-Win Manager&#xff1a;https://github.com/evsar3/sshfs-win-manager/releases 安装…

增强ev代码签名证书2300

代码签名证书是软件开发者们确保软件完整性和安全性的重要工具之一。在各种类型的代码签名证书中&#xff0c;增强EV代码签名证书拥有许多独特的功能而受到企业开发者的欢迎&#xff0c;今天就随SSL盾小编了解增强EV代码签名证书的申请条件以及申请流程。 1.增强型EV代码签名证…

Linux——Dockerfile

在这里我们来整理一下docker容器、dockerfile、docker镜像的关系&#xff1a; dockerfile是面向开发的&#xff0c;发布项目做镜像的时候就要编写dockerfile文件。 dockerfile&#xff1a;构建文件&#xff0c;定义了一切的步骤&#xff0c;源代码。 dockerImanges&#xff1a…

【AI绘画Stable Diffusion】单人LoRA模型训练,打造你的专属模型,新手入门宝典请收藏!

大家好&#xff0c;我是灵魂画师向阳 本期我将教大家如何进行LoRA模型训练&#xff0c;打造你的专属模型&#xff0c;内容比较干&#xff0c;还请耐心看完&#xff01; 随着AIGC的发展&#xff0c;许多传统工作岗位正逐渐被AI取代。同时&#xff0c;AI变革也在创造前所未有的…

STM32 学习——1. STM32最小系统

这是一个最小系统的测试&#xff0c;LED灯会进行闪烁。选用PC13口&#xff0c;因为STM32F103C8T6 硬件开发板中&#xff0c;这个端口是一个LED 1. proteus8.15 原理图 2. cubemx 新建工程 3. keil 代码 while (1){HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);HAL_Delay(100);…

《计算机网络微课堂》1-3 三种交换方式

本节课我们介绍三种交换方式&#xff0c;分别是电路交换&#xff08;Circuit Switching&#xff09;&#xff0c;分组交换&#xff08;Packet Switching&#xff09;以及报文&#xff08;Message Switching&#xff09;交换。 我们首先来看电路交换&#xff0c;在电话问世后不…

探索未来,与移动云共舞

探索未来&#xff0c;与移动云共舞 在数字化飞速发展的今天&#xff0c;云计算已经成为企业、政府乃至个人用户不可或缺的一部分。而在众多云服务提供商中&#xff0c;移动云凭借其独特的优势&#xff0c;为用户带来前所未有的体验。接下来&#xff0c;让我们一起走进移动云的世…

Python--List列表

list列表⭐⭐ 1高级数据类型 Python中的数据类型可以分为&#xff1a;数字型&#xff08;基本数据类型&#xff09;和非数字型&#xff08;高级数据类型&#xff09; ●数字型包含&#xff1a;整型int、浮点型float、布尔型bool、复数型complex ●非数字型包含&#xff1a;字符…

Python实现数据可视化效果图总结

一、JSON格式 JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据。 JSON本质上是一个带有特定格式的字符串 Json格式 JSON数据格式在Python中可以是字典、又可以是列表中嵌套着字典的格式。 Pyhton数据和Json数据相互转化 二、pyecharts模块 如果想…

SpringMVC接收请求参数的方式:

接收简单变量的请求参数 直接使用简单变量作为形参进行接收&#xff08;这里简单变量名称需要与接收的参数名称保持一致&#xff0c;否则需要加上RequestParam注解&#xff09;&#xff1a; 细节&#xff1a; 1&#xff1a;SpringMVC会针对常见类型&#xff08;八种基本类型及…

翻译《The Old New Thing》- The importance of the FORMAT_MESSAGE_IGNORE_INSERTS flag

The importance of the FORMAT_MESSAGE_IGNORE_INSERTS flag - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20071128-00/?p24353 Raymond Chen 2007年11月28日 FORMAT_MESSAGE_IGNORE_INSERTS 标志的重要性 简要 文章讨论了使用FormatMes…

数据结构----堆的实现(附代码)

当大家看了鄙人的上一篇博客栈后&#xff0c;稍微猜一下应该知道鄙人下一篇想写的博客就是堆了吧。毕竟堆栈在C语言中常常是一起出现的。那么堆是什么&#xff0c;是如何实现的嘞。接下来我就带大家去尝试实现一下堆。 堆的含义 首先我们要写出一个堆&#xff0c;那么我们就需…

nodejs 与 npm 版本对应关系

官方地址&#xff1a;https://nodejs.org/en/about/previous-releases

手机边听边充音频转接器双盲插系列:便捷充电,畅享音乐6500

在快节奏的生活中&#xff0c;手机已经成为我们不可或缺的日常用品。无论是工作、学习还是娱乐&#xff0c;手机都扮演着重要角色。然而&#xff0c;当我们沉浸在音乐的海洋中时&#xff0c;手机电量不足的困扰却时常打断我们的美好体验。为了解决这一难题&#xff0c;手机边听…

你真正了解 Java 中的 Date 类吗?以及如何正确使用它

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

设计模式8——原型模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 原型模式&#xff08;Prototyp…

css卡片横线100%宽度

所需样式: 横线不用border, 用单独一个div, 这样就不会影响父组件的padding <div class"pumpDetailView"><div class"pump_title_name"><span>{{ pumpInfo.pointname }}</span><divclass"point_state":style"…

vr商品全景展示场景编辑软件的优点

3D模型展示网站搭建编辑器以强大的3D编辑引擎和逼真的渲染效果&#xff0c;让您轻松实现模型展示的优化。让用户通过简单的操作&#xff0c;就能满足个人/设计师/商户多样化展示的需求&#xff0c;让您的模型成为独一无二的杰作。 3D模型展示网站搭建编辑器采用国内领先的实时互…

玩转盲盒潮流:从0到1搭建小程序平台

在当前的消费市场中&#xff0c;盲盒已成为一种炙手可热的消费模式&#xff0c;凭借其神秘性和随机性&#xff0c;迅速俘获了年轻消费者的心。作为一位有志于创新并紧跟市场趋势的创业者&#xff0c;你可能会想&#xff1a;如何从0到1搭建一个属于自己的盲盒小程序平台&#xf…