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

news2024/12/27 13:29:13

相关技术

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/1709627.html

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

相关文章

基于51单片机的汽车智能灯光控制系统

一.硬件方案 本设计硬件部分&#xff0c;中央处理器采用了STC89C52RC单片机&#xff0c;另外使用两个灯珠代表远近光灯&#xff0c;感光部分采用了光敏电阻&#xff0c;因为光敏电阻输出的是电压模拟信号&#xff0c;单片机不能直接处理模拟信号&#xff0c;所以经过ADC0832进…

为什么配置了安全组还是有攻击进来?

面对DDoS攻击&#xff0c;即使配置了安全组规则来限制入站流量&#xff0c;攻击者仍可能找到绕过这些基本防护措施的方法&#xff0c;尤其是当攻击流量巨大时。这是因为安全组主要工作在网络层和传输层&#xff0c;它们依据IP地址、协议和端口号来过滤流量&#xff0c;对于应用…

【模拟面试问答】深入解析力扣164题:最大间距(桶排序与排序方法详解)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

c 系统宏有多少

在C语言中&#xff0c;系统宏&#xff08;也称为预定义宏或内置宏&#xff09;的数量并不是固定的&#xff0c;因为它们取决于C标准、编译器以及可能的其他因素。然而&#xff0c;有一些常见的预定义宏是几乎所有C编译器都支持的。 以下是一些常见的C预定义宏&#xff1a; __…

Nature 正刊!瑞典于默奥大学研究团队在研究全球河流和溪流的甲烷排放中取得新进展

甲烷(CH4)是一种强有力的温室气体&#xff0c;自工业革命以来&#xff0c;其在大气中的浓度增加了两倍。有证据表明&#xff0c;全球变暖增加了淡水生态系统的 CH4 排放&#xff0c;为全球气候提供了积极的反馈。然而&#xff0c;对于河流和溪流来说&#xff0c;甲烷排放的控制…

鸿蒙OS开发:典型页面场景【一次开发,多端部署】(信息应用)案例

信息应用 简介 内容介绍 Mms应用是OpenHarmony中预置的系统应用&#xff0c;主要的功能包含信息查看、发送短信、接收短信、短信送达报告、删除短信等功能。 架构图 目录 /Mms/ ├── doc # 资料 ├── entry │ └── src │…

阳光电源临摹品引发的EMC正向设计思考

画画可以临摹。画电路板临摹的人更多。 抄板&#xff0c;抄的是过去的板子&#xff0c;容易出问题。现在市场竞争激烈&#xff0c;欧美客户对出口产品的标准要求推陈出新&#xff0c;防不胜防。由于市场的竞争&#xff0c;欧洲客户已经意识到EMC电磁兼容的重要性&#xff0c;不…

洁净环境测试标准、监测计划要点及风险评估注意事项

洁净区日常环境监测 洁净区环境监测作为污染控制策略&#xff08;CCS&#xff09;的重要组成部分&#xff0c;用于监测旨在将粒子和微生物污染风险降至最低的控制措施。下面内容&#xff0c;中邦兴业小编将与大家做个详细的分享。 环境监测计划 评估和定义粒子、微生物监测所…

Python 机器学习 基础 之 模型评估与改进 【评估指标与评分】的简单说明

Python 机器学习 基础 之 模型评估与改进 【评估指标与评分】的简单说明 目录 Python 机器学习 基础 之 模型评估与改进 【评估指标与评分】的简单说明 一、简单介绍 二、评估指标与评分 1、牢记最终目标 2、二分类指标 1&#xff09;错误类型 2&#xff09;不平衡数据集…

什么是erp仓储管理系统?ERP系统的价值体现在哪些方面?

ERP仓储管理系统是一个帮助企业管理仓库的工具。想象一下&#xff0c;如果你是一个仓库管理员&#xff0c;里面堆满了各种各样的产品和货物&#xff0c;如何确保这些产品数量准确、摆放有序&#xff0c;以及快速找到自己需要的产品呢&#xff1f; 这时&#xff0c;如果企业引用…

Web会话管理

一、会话管理的概念&#xff1a; 在人机交互时&#xff0c;会话管理是保持用户的整个会话活动的互动与计算机系统跟踪过程会话管理分类: 桌面会话管理、浏览器会话管理、Web服务器的会话管理。 二、为什么需要会话管理&#xff1f; HTTP是一种无状态协议&#xff0c;一次请…

【SpringCloud】Spring Cloud基本介绍

目录 回顾架构分类单体架构分布式架构微服务架构什么是微服务优点缺点微服务的架构特征&#xff1a;微服务架构面临的挑战技术挑战微服架构的设计原则微服务概念提供者(Provider)消费者(Consumer)RPC和Restful集群分布式 总结 服务拆分和远程调用服务拆分原则服务拆分示例 思考…

保障餐饮场所安全:可燃气体报警器专业检测的必要性

在餐饮行业&#xff0c;火灾隐患一直是备受关注的问题。为了有效预防和及时发现可燃气体泄漏&#xff0c;可燃气体报警器的专业检测周期显得尤为重要。 今天&#xff0c;佰德和大家一起来深入了解一下可燃气体报警器的专业检测周期&#xff0c;若您对此有不同的观点或其他的问…

比较(一)利用python绘制条形图

比较&#xff08;一&#xff09;利用python绘制条形图 条形图&#xff08;Barplot&#xff09;简介 条形图主要用来比较不同类别间的数据差异&#xff0c;一条轴表示类别&#xff0c;另一条则表示对应的数值度量。 快速绘制 基于seaborn import seaborn as sns import matplo…

新型高性能数据记录仪ETHOS 2

| 具有强大CPU性能的数据记录仪 IPETRONIK推出了一款新型高性能数据记录仪——ETHOS 2&#xff0c;作为ETHOS的第二代&#xff0c;它借助新型英特尔i7-9850HE处理器&#xff0c;实现了11,572的性能指数&#xff0c;从而能够快速有效应对CAN FD、LIN和以太网总线测量方面的日益…

linux线程,线程控制与线程相关概念

线程概念 线程这个词或多或少大家都听过&#xff0c;今天我们正式的来谈一下线程&#xff1b; 在我一开始的概念中线程就是进程的一部分&#xff0c;一个进程中有很多个线程&#xff0c;这个想法基本是正确的&#xff0c;但细节部分呢我们需要细细讲解一下&#xff1b; 什么…

OKR 实践:来自一位信息技术部主管的成功秘诀

OKR 实践&#xff1a;来自一位信息技术部主管的成功秘诀 为什么选择OKR 公司信息技术部为38个各地分公司、12,000名员工的IT需求提供服务。庞大而多样的客户群常常使我们的团队分散&#xff0c;许多团队都在各自为政&#xff0c;以个案为基础解决问题&#xff0c;而不是采用企业…

CSS文本粒子动画特效之爱心粒子文字特效-Canvas

1. 效果图 2.完整代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><style>body,html {margin: 0;paddin…

Sqoop的安装与测试

这里写目录标题 什么是Sqoop?Sqoop的安装与配置安装测试 什么是Sqoop? Sqoop就是hadoop和mysql的一个中间介质 , 作用就是可以将hadoop中的数据传到mysql中 , 或将mysql中的数据导入到hadoop中 Sqoop的安装与配置 安装 详细代码 //解压安装 [roothadoop soft]# tar -zxv…

国产数据库替代加速 助力数字中国建设

5月24日&#xff0c;随着第七届数字中国建设峰会在福州的成功举办&#xff0c;释放数据要素价值、发展新质生产力成为当下热议的话题。 数据作为新型生产要素&#xff0c;是数字化、网络化、智能化的重要基础。北京人大金仓信息技术股份有限公司&#xff08;以下简称人大金仓&a…