4、SpringMVC 实战小项目【加法计算器、用户登录、留言板、图书管理系统】

SpringMVC 实战小项目

    • 3.1 加法计算器
      • 3.1.1 准备⼯作
        • 前端
      • 3.1.2 约定前后端交互接⼝
        • 需求分析
        • 接⼝定义
        • 请求参数:
        • 响应数据:
      • 3.1.3 服务器代码
    • 3.2 ⽤⼾登录
      • 3.2.1 准备⼯作
      • 3.2.2 约定前后端交互接⼝
      • 3.2.3 实现服务器端代码
    • 3.3 留⾔板
      • 实现服务器端代码
    • 3.4 图书管理系统
      • 准备
      • 后端

3.1 加法计算器

需求: 输⼊两个整数, 点击"点击相加"按钮, 显⽰计算结果

在这里插入图片描述

3.1.1 准备⼯作

创建SpringBoot项⽬: 引⼊Spring Web依赖, 把前端⻚⾯放在项⽬中(课件中提供)

前端
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
     <form action="calc/sum" method="post">
        <h1>计算器</h1>
        数字1:<input name="num1" type="text"><br>
        数字2:<input name="num2" type="text"><br>
        <input type="submit" value=" 点击相加 ">
    </form>
</body>

</html>

3.1.2 约定前后端交互接⼝

需求分析

加法计算器功能, 对两个整数进⾏相加, 需要客⼾端提供参与计算的两个数, 服务端返回这两个整数计算的结果

接⼝定义

在这里插入图片描述

请求路径:calc/sum
请求⽅式:GET/POST
接⼝描述:计算两个整数相加
请求参数:

在这里插入图片描述

⽰例: num1=5&num2=3

响应数据:
Content-Type: text/html
响应内容: 计算机计算结果: 8

3.1.3 服务器代码

@RestController
@RequestMapping("/calc")
public class CalcController {
	@RequestMapping("/sum")
	public String sum(Integer num1,Integer num2){
		Integer sum = num1+num2;
		return "<h1>计算机计算结果: "+sum+"</h1>";
	}
}

3.2 ⽤⼾登录

需求: ⽤⼾输⼊账号和密码, 后端进⾏校验密码是否正确

  1. 如果不正确, 前端进⾏⽤⼾告知
  2. 如果正确, 跳转到⾸⻚. ⾸⻚显⽰当前登录⽤⼾
  3. 后续再访问⾸⻚, 可以获取到登录⽤⼾信息

在这里插入图片描述

3.2.1 准备⼯作

把前端⻚⾯放在项⽬中(课件中提供)
码云地址: 前端代码/⽤⼾登录

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

<head>
  <meta charset="UTF-8">
  <title>登录页面</title>
</head>

<body>
  <h1>用户登录</h1>
  用户名:<input name="userName" type="text" id="userName"><br>
  密码:<input name="password" type="password" id="password"><br>
  <input type="button" value="登录" onclick="login()">
  
  <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
  <script>
    function login() {
      $.ajax({
        type: "post",
        url: "/login/check",
        data:{
          userName: $("#userName").val(),
          password: $("#password").val()
        },
        success: function(result){
          if(result==true){
            //用户名和密码正确
            location.href = "index.html";
            // location.assign("index.html");
            // location.replace("index.html")
          }else{
            alert("用户名或密码错误!");
          }
        }
      });
    }

  </script>
</body>

</html>

3.2.2 约定前后端交互接⼝

需求分析
对于后端开发⼈员⽽⾔, 不涉及前端⻚⾯的展⽰, 只需要提供两个功能

  1. 登录⻚⾯: 通过账号和密码, 校验输⼊的账号密码是否正确, 并告知前端
  2. ⾸⻚: 告知前端当前登录⽤⼾. 如果当前已有⽤⼾登录, 返回登录的账号, 如果没有, 返回空

接⼝定义

  1. 校验接⼝
请求路径:/user/login
请求⽅式:POST
接⼝描述:校验账号密码是否正确

在这里插入图片描述

3.2.3 实现服务器端代码

@RequestMapping("/login")
@RestController
public class LoginController {
    @RequestMapping("/check")
    public boolean check(String userName, String password, HttpSession session){
        System.out.println("接收到参数 userName:"+userName + ",password:"+password);
        //校验账号和密码是否为空
//        if (userName==null || "".equals(userName) || password==null || "".equals(password)){
//            return false;
//        }
        if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){
            return false;
        }
        //校验账号和密码是否正确
        //数据模拟
        if ("zhangsan".equals(userName) && "123456".equals(password)){
            session.setAttribute("userName",userName);
            return true;
        }
        return false;
    }

    @RequestMapping("/index")
    public String index(HttpSession session){
        String userName = (String)session.getAttribute("userName");
        return userName;
    }
}

3.3 留⾔板

需求:
界⾯如下图所⽰

  1. 输⼊留⾔信息, 点击提交. 后端把数据存储起来.
  2. ⻚⾯展⽰输⼊的表⽩墙的信息

在这里插入图片描述

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>留言板</title>
    <style>
        .container {
            width: 350px;
            height: 300px;
            margin: 0 auto;
            /* border: 1px black solid; */
            text-align: center;
        }

        .grey {
            color: grey;
        }

        .container .row {
            width: 350px;
            height: 40px;

            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .container .row input {
            width: 260px;
            height: 30px;
        }

        #submit {
            width: 350px;
            height: 40px;
            background-color: orange;
            color: white;
            border: none;
            margin: 10px;
            border-radius: 5px;
            font-size: 20px;
        }
    </style>
</head>

<body>
    <div class="container">
        <h1>留言板</h1>
        <p class="grey">输入后点击提交, 会将信息显示下方空白处</p>
        <div class="row">
            <span>谁:</span> <input type="text" name="" id="from">
        </div>
        <div class="row">
            <span>对谁:</span> <input type="text" name="" id="to">
        </div>
        <div class="row">
            <span>说什么:</span> <input type="text" name="" id="say">
        </div>
        <input type="button" value="提交" id="submit" onclick="submit()">
        <!-- <div>A 对 B 说: hello</div> -->
    </div>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script>
        //页面加载时, 显示留言信息
        //从后端获取到留言信息, 并显示在页面上
        $.ajax({
            type: "get",
            url: "/message/getList",
            success: function(messages){
                for(var message of messages){
                    var html = "<div>"+message.from+" 对 "+message.to+" 说: "+message.message+"</div>";
                    $(".container").append(html);
                }
            }
        });


        function submit() {
            //1. 获取留言的内容
            var from = $('#from').val();
            var to = $('#to').val();
            var say = $('#say').val();
            if (from == '' || to == '' || say == '') {
                return;
            }
            $.ajax({
                type: "post",
                url: "/message/publish",
                data: {
                    from: from,
                    to: to,
                    message: say
                },
                success: function (result) {
                    if (result == true) {
                        //添加成功
                        //2. 构造节点
                        var divE = "<div>" + from + "对" + to + "说:" + say + "</div>";
                        //3. 把节点添加到页面上
                        $(".container").append(divE);
                        //4. 清空输入框的值
                        $('#from').val("");
                        $('#to').val("");
                        $('#say').val("");
                    }else{
                        alert("发表失败");
                    }
                }
            });
        }

    </script>
</body>

</html>

实现服务器端代码

@Data
public class MessageInfo {
    private Integer id;
    private String from;
    private String to;
    private String message;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;

}

@RequestMapping("/message")
@RestController
public class MessageController {
    @Autowired
    private MessageService messageService;

    private List<MessageInfo> messageInfos = new ArrayList<>();

    @RequestMapping("/publish")
    public boolean publishMessage(MessageInfo messageInfo){
        if (!StringUtils.hasLength(messageInfo.getFrom())
                || !StringUtils.hasLength(messageInfo.getTo())
                || !StringUtils.hasLength(messageInfo.getMessage())){
            return false;
        }
        //暂时存放在内存中
//        messageInfos.add(messageInfo);
        //把数据放在mysql当中
        messageService.insertMessage(messageInfo);
        return true;
    }

    @RequestMapping("/getList")
    public List<MessageInfo> getList(){
        return messageService.queryList();
    }
}

3.4 图书管理系统

需求:

  1. 登录: ⽤⼾输⼊账号,密码完成登录功能
  2. 列表展⽰: 展⽰图书

在这里插入图片描述

准备

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/login.css">
    <script type="text/javascript" src="js/jquery.min.js"></script>
</head>

<body>
    <div class="container-login">
        <div class="container-pic">
            <img src="pic/computer.png" width="350px">
        </div>
        <div class="login-dialog">
            <h3>登陆</h3>
            <div class="row">
                <span>用户名</span>
                <input type="text" name="userName" id="userName" class="form-control">
            </div>
            <div class="row">
                <span>密码</span>
                <input type="password" name="password" id="password" class="form-control">
            </div>
            <div class="row">
                <button type="button" class="btn btn-info btn-lg" onclick="login()">登录</button>
            </div>
        </div>
    </div>
    <script src="js/jquery.min.js"></script>
    <script>
        function login() {
            $.ajax({
                type:"post",
                url: "/user/login",
                data:{
                    userName: $("#userName").val(),
                    password: $("#password").val()
                },
                success:function(result){
                    console.log(result);
                    if(result.code==200 && result.data==true){
                        //验证成功
                        location.href = "book_list.html";
                    }else{
                        alert("用户名或密码失败");
                    }
                }
            });
           
        }
    </script>
</body>

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图书列表展示</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">

    <link rel="stylesheet" href="css/list.css">
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" src="js/bootstrap.min.js"></script>
    <script src="js/jq-paginator.js"></script>

</head>

<body>
    <div class="bookContainer">
        <h2>图书列表展示</h2>
        <div class="navbar-justify-between">
            <div>
                <button class="btn btn-outline-info" type="button" onclick="location.href='book_add.html'">添加图书</button>
                <button class="btn btn-outline-info" type="button" onclick="batchDelete()">批量删除</button>
            </div>
        </div>

        <table>
            <thead>
                <tr>
                    <td>选择</td>
                    <td class="width100">图书ID</td>
                    <td>书名</td>
                    <td>作者</td>
                    <td>数量</td>
                    <td>定价</td>
                    <td>出版社</td>
                    <td>状态</td>
                    <td class="width200">操作</td>
                </tr>
            </thead>
            <tbody>

            </tbody>
        </table>

        <div class="demo">
            <ul id="pageContainer" class="pagination justify-content-center"></ul>
        </div>
        <script>

            getBookList();


            function getBookList() {
                $.ajax({
                    type: "get",
                    url: "/book/getListByPage" + location.search,
                    success: function (result) {
                        console.log("后端返回成功");
                        if (result.code == -1) {
                            alert("发生内部错误, 请联系管理员");
                            return;
                        }
                        var data = result.data;
                        var books = data.records;
                        console.log(books);
                        var finalHtml = "";
                        for (var book of books) {
                            //拼接html
                            finalHtml += '<tr>';
                            finalHtml += '<td><input type="checkbox" name="selectBook" value="' + book.id + '" id="selectBook" class="book-select"></td>';
                            finalHtml += '<td>' + book.id + '</td>';
                            finalHtml += '<td>' + book.bookName + '</td>';
                            finalHtml += '<td>' + book.author + '</td>';
                            finalHtml += '<td>' + book.count + '</td>';
                            finalHtml += '<td>' + book.price + '</td>';
                            finalHtml += '<td>' + book.publish + '</td>';
                            finalHtml += '<td>' + book.stateCN + '</td>';
                            finalHtml += '<td>';
                            finalHtml += '<div class="op">';
                            finalHtml += '<a href="book_update.html?bookId=' + book.id + '">修改</a>';
                            finalHtml += '<a href="javascript:void(0)" οnclick="deleteBook(' + book.id + ')">删除</a>';
                            finalHtml += '</div>';
                            finalHtml += '</td>';
                            finalHtml += '</tr>';
                        }

                        $("tbody").html(finalHtml);

                        //处理翻页信息
                        //翻页信息
                        $("#pageContainer").jqPaginator({
                            totalCounts: data.count, //总记录数
                            pageSize: 10,    //每页的个数
                            visiblePages: 5, //可视页数
                            currentPage: data.pageRequest.currentPage,  //当前页码
                            first: '<li class="page-item"><a class="page-link">首页</a></li>',
                            prev: '<li class="page-item"><a class="page-link" href="javascript:void(0);">上一页<\/a><\/li>',
                            next: '<li class="page-item"><a class="page-link" href="javascript:void(0);">下一页<\/a><\/li>',
                            last: '<li class="page-item"><a class="page-link" href="javascript:void(0);">最后一页<\/a><\/li>',
                            page: '<li class="page-item"><a class="page-link" href="javascript:void(0);">{{page}}<\/a><\/li>',
                            //页面初始化和页码点击时都会执行
                            onPageChange: function (page, type) {
                                console.log("第" + page + "页, 类型:" + type);
                                if (type == "change") {
                                    // console.log("book_list.html"+location.search);
                                    location.href = "book_list.html?currentPage=" + page;
                                }

                            }
                        });
                    },
                    error: function (error) {
                        console.log(error);
                        if (error != null && error.status == 401) {
                            location.href = "login.html";
                        }
                    }



                });
            }


            function deleteBook(id) {
                var isDelete = confirm("确认删除?");//弹出确认框
                if (isDelete) {
                    console.log(id);
                    //删除图书
                    $.ajax({
                        type: "post",
                        url: "/book/updateBook",
                        data: {
                            id: id,
                            status: 0
                        },
                        success: function (result) {
                            if (result.code == 200 && result.data == true) {
                                alert("删除成功");
                                location.href = "book_list.html";
                            }
                        }
                    });
                }
            }
            function batchDelete() {
                var isDelete = confirm("确认批量删除?");
                if (isDelete) {
                    //获取复选框的id
                    var ids = [];
                    $("input:checkbox[name='selectBook']:checked").each(function () {
                        ids.push($(this).val());
                    });
                    console.log(ids);
                    $.ajax({
                        type: "post",
                        url: "/book/batchDelete?ids=" + ids,
                        success: function (result) {
                            if (result.code==200 && result.data == true) {
                                //删除成功
                                location.href = "book_list.html";
                            } else {
                                alter("删除失败, 请联系管理员");
                            }
                        }
                    });
                }
            }

        </script>
    </div>
</body>

</html>

根据需求可以得知, 后端需要提供两个接⼝

  1. 账号密码校验接⼝: 根据输⼊⽤⼾名和密码校验登录是否通过
  2. 图书列表: 提供图书列表信息

在这里插入图片描述

后端

@RequestMapping("/user")
@RestController
public class UserController {
	@RequestMapping("/login")
	public boolean login(String name, String password, HttpSession session){
		//账号或密码为空
		if (!StringUtils.hasLength(name) || !StringUtils.hasLength(password)){
			return false;
		}
		//模拟验证数据, 账号密码正确
		if("admin".equals(name) && "admin".equals(password)){
			session.setAttribute("userName",name);
			return true;
		}
		//账号密码错误
		return false;
	}
}
@RequestMapping("/book")
@RestController
public class BookController {
	@RequestMapping("/getList")
	public List<BookInfo> getList(){
		//获取数据
		List<BookInfo> books = mockData();
		//处理⻚⾯展⽰
		for (BookInfo book:books){
			if (book.getStatus()==1){
				book.setStatusCN("可借阅");
			}else {
				book.setStatusCN("不可借阅");
			}
		}
		return books;
	}
	/**
	* 数据Mock 获取图书信息
	*
	* @return
	*/
	public List<BookInfo> mockData() {
		List<BookInfo> books = new ArrayList<>();
		for (int i = 0; i < 5; i++) {
			BookInfo book = new BookInfo();
			book.setId(i);
			book.setBookName("书籍" + i);
			book.setAuthor("作者" + i);
			book.setCount(i * 5 + 3);
			book.setPrice(new BigDecimal(new Random().nextInt(100)));
			book.setPublish("出版社" + i);
			book.setStatus(1);
			books.add(book);
		}
		return books;
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【内存管理】页面分配机制

前言 Linux内核中是如何分配出页面的&#xff0c;如果我们站在CPU的角度去看这个问题&#xff0c;CPU能分配出来的页面是以物理页面为单位的。也就是我们计算机中常讲的分页机制。本文就看下Linux内核是如何管理&#xff0c;释放和分配这些物理页面的。 伙伴算法 伙伴系统的…

Visual Studio开发环境搭建

原文&#xff1a;https://blog.c12th.cn/archives/25.html Visual Studio开发环境搭建 测试&#xff1a;笔记本原装操作系统&#xff1a;Windows 10 家庭中文版 资源分享链接&#xff1a;提取码&#xff1a;qbt2 注意事项&#xff1a;注意查看本地硬盘是否够用&#xff0c;建议…

在阿里云使用Docker部署MySQL服务,并且通过IDEA进行连接

阿里云使用Docker部署MySQL服务&#xff0c;并且通过IDEA进行连接 这里演示如何使用阿里云来进行MySQL的部署&#xff0c;系统使用的是Linux系统 (Ubuntu)。 为什么使用Docker? 首先是因为它的可移植性可以在任何有Docker环境的系统上运行应用&#xff0c;避免了在不通操作系…

SpringBoot+ENC实现密钥加密及使用原理

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; SpringBootENC实现密钥加密及使用原理 ⏱️ 创作时间&#xff1a; 202…

AtCoder Beginner Contest 359 A~C(D~F更新中...)

A.Count Takahashi 题意 给出 N N N个字符串&#xff0c;每个字符串为以下两种字符串之一&#xff1a; "Takahashi" "Aoki" 请你统计"Takahashi"出现了多少次。 分析 输入并统计即可。 代码 #include <bits/stdc.h>using namespa…

web集群-nginx(nginx三种文件模块,nginx用户请求流程,域名访问网站,虚拟主机,搭建大型直播购物平台)

nginx文件模块 lineinfile未来修改配置文件使用&#xff0c;类似于sed -i ‘sg’ 和sed ‘cai’ 掌握file模块&#xff1a;创建文件&#xff0c;目录&#xff0c;创建软链接&#xff0c;修改权限和所有者&#xff0c;删除文件目录 服务管理systemd systemctl相当于linux sys…

[stm32]温湿度采集与OLED显示

一、I2C总线协议 I2C&#xff08;Inter-integrated circuit &#xff09;是一种允许从不同的芯片或电路与不同的主芯片通信的协议。它仅用于短距离通信&#xff0c;是一种用于两个或多个设备之间进行数据传输的串行总线技术&#xff0c;它可以让你在微处理器、传感器、存储器、…

UE5开发游戏Tutorial

文章目录 PlayerStart 初始化设置默认 LevelBP_Character 初始化BP_Character 添加动画BP_Character 攻击BP_Enemy 初始化 以及 AI 运动Camera Collision 相机碰撞BP_Character 生命以及伤害Wave Spawner 波生成UI 初始化以及 Damage Screen指定位置随机生成添加声音环境 Envir…

使用SpringCache实现Redis缓存

目录 一 什么是Spring Cache 二 Spring Cache 各注解作用 ①EnableCaching ②Cacheable ③CachePut ④CacheEvict 三实现步骤 ①导入spring cache依赖和Redis依赖 ②配置Redis连接信息 ③在启动类上加上开启spring cache的注解 ④ 在对应的方法上加上需要的注解 一 什么…

PINN解偏微分方程实例4

PINN解偏微分方程实例4 一、正问题1. Diffusion equation2. Burgers’ equation3. Allen–Cahn equation4. Wave equation 二、反问题1. Burgers’ equation3. 部分代码示例 本文使用 PINN解偏微分方程实例1中展示的代码求解了以四个具体的偏微分方程&#xff0c;包括Diffusio…

长亭谛听教程部署和详细教程

PPT 图片先挂着 挺概念的 谛听的能力 hw的时候可能会问你用过的安全产品能力能加分挺重要 溯源反制 反制很重要感觉很厉害 取证分析 诱捕牵制 其实就是蜜罐 有模板直接爬取某些网页模板进行伪装 部署要求 挺低的 对linux内核版本有要求 需要root 还有系统配置也要修改 …

论文阅读--Efficient Hybrid Zoom using Camera Fusion on Mobile Phones

这是谷歌影像团队 2023 年发表在 Siggraph Asia 上的一篇文章&#xff0c;主要介绍的是利用多摄融合的思路进行变焦。 单反相机因为卓越的硬件性能&#xff0c;可以非常方便的实现光学变焦。不过目前的智能手机&#xff0c;受制于物理空间的限制&#xff0c;还不能做到像单反一…

long long ago

一、long 众所周知&#xff0c;英文单词 long&#xff0c;表示长,长的。 但是&#xff0c;还有很多你不知道到的东西&#xff0c;根据英文单词首字母象形原则&#xff0c;我们可以做一下单词long结构分析&#xff1a; long l长 ong长 什么意思&#xff1f;就是说首字线 l…

Maven的依赖传递、依赖管理、依赖作用域

在Maven项目中通常会引入大量依赖&#xff0c;但依赖管理不当&#xff0c;会造成版本混乱冲突或者目标包臃肿。因此&#xff0c;我们以SpringBoot为例&#xff0c;从三方面探索依赖的使用规则。 1、 依赖传递 依赖是会传递的&#xff0c;依赖的依赖也会连带引入。例如在项目中…

AI大模型企业应用实战(14)-langchain的Embedding

1 安装依赖 ! pip install --upgrade langchain ! pip install --upgrade openai0.27.8 ! pip install -U langchain-openai ! pip show openai ! pip show langchain ! pip show langchain-openai 2 Embed_documents # 1. 导入所需的库 from langchain_openai import Open…

poi生成的excel,输入数字后变成1.11111111111111E+23

poi版本4.1.2 生成excel后&#xff0c;单元格输入数字&#xff0c;过长的话变成这样 解决&#xff1a;生成的时候设置单元格格式为文本格式 import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.FileOutputStream; imp…

解析PDF文件中的图片为文本

解析PDF文件中的图片为文本 1 介绍 解析PDF文件中的图片&#xff0c;由两种思路&#xff0c;一种是自己读取PDF文件中的图片&#xff0c;然后用OCR解析&#xff0c;例如&#xff1a;使用PyMuPDF读取pdf文件&#xff0c;再用PaddleOCR或者Tesseract-OCR识别文字。另一种使用第…

使用matlab的大坑,复数向量转置!!!!!变量区“转置变量“功能(共轭转置)、矩阵转置(默认也是共轭转置)、点转置

近期用verilog去做FFT相关的项目&#xff0c;需要用到matlab进行仿真然后和verilog出来的结果来做对比&#xff0c;然后计算误差。近期使用matlab犯了一个错误&#xff0c;极大的拖慢了项目进展&#xff0c;给我人都整emo了&#xff0c;因为怎么做仿真结果都不对&#xff0c;还…

clean code-代码整洁之道 阅读笔记(第十一章)

第十一章 系统 “复杂要人命,它消磨开发者的生命&#xff0c;让产品难以规划、构建和测试。” --RayOzzie&#xff0c;微软公司首席技术官 11.1 如何建造一个城市 每个城市都有一组组人管理不同的部分&#xff0c;有些人负责全局&#xff0c;其他人负责细节。 城市能运转&#…

【git】gitee仓库本地克隆失败可能的一种解决办法

出错点&#xff1a; 在 gitee 克隆远程仓库到 本地时&#xff0c;可能会出现以下报错情况&#xff0c;无法成功克隆 正常流程&#xff1a;&#xff08;熟悉正常克隆流程的可以直接跳到下面的【解决办法】&#xff09; 我们一般复制仓库地址是在下面红线框框的位置&#xff0c…