Spring Web入门练习

news2024/11/22 16:55:54

加法计算器

约定前后端交互接⼝

约定 "前后端交互接⼝" 是进⾏ Web 开发中的关键环节.

接⼝⼜叫 API(Application Programming Interface), 我们⼀般讲到接⼝或者 API,指的都是同⼀个东西.

是指应⽤程序对外提供的服务的描述, ⽤于交换信息和执⾏任务(与JavaSE阶段学习的[类和接⼝]中的接⼝是两回事).

简单来说, 就是允许客⼾端给服务器发送哪些 HTTP 请求, 并且每种请求预期获取什么样的 HTTP 响应.

现在"前后端分离"模式开发, 前端和后端代码通常由不同的团队负责开发. 双⽅团队在开发之前, 会提前

约定好交互的⽅式. 客⼾端发起请求, 服务器提供对应的服务. 服务器提供的服务种类有很多, 客⼾端按照双⽅约定指定选择哪⼀个服务.

接⼝, 其实也就是我们前⾯⽹络模块讲的的"应⽤层协议". 把约定的内容写在⽂档上, 就是"接⼝⽂档" ,接⼝⽂档也可以理解为是 应⽤程序的"操作说明书".

需求分析

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

基于以上分析, 我们来定义接⼝

接⼝定义

请求路径:calc/sum

请求⽅式:GET/POST

接⼝描述:计算两个整数相加

响应数据:

Content-Type: text/html

响应内容: 计算机计算结果: 8

服务器代码


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

调整前端⻚⾯代码

<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>

⽤⼾登录

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

1. 如果不正确, 前端进⾏⽤⼾告知

2. 如果正确, 跳转到⾸⻚. ⾸⻚显⽰当前登录⽤⼾

3. 后续再访问⾸⻚, 可以获取到登录⽤⼾信息

约定前后端交互接⼝

需求分析

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

1. 登录⻚⾯: 通过账号和密码, 校验输⼊的账号密码是否正确, 并告知前端

2. ⾸⻚: 告知前端当前登录⽤⼾. 如果当前已有⽤⼾登录, 返回登录的账号, 如果没有, 返回空

接⼝定义

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

响应数据:
Content-Type: text/html
响应内容:
true //账号密码验证成功
false//账号密码验证失败

查询登录⽤⼾接⼝

请求路径:/user/getLoginUser
请求⽅式:GET
接⼝描述:查询当前登录的⽤⼾
请求参数:
响应数据:
Content-Type: text/html
响应内容: 
zhangsan
返回当前登录的⽤⼾

实现服务器端代码

package com.example.demo;

import ch.qos.logback.core.util.StringUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/user")
@RestController
public class UserController {
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Boolean login(String userName, String password, HttpServletRequest request) {
//        if(userName == null || "".equals(userName)) {
//            return false;
//        }
        if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
            return false;
        }
        if("admin".equals(userName) && "admin".equals(password)) {
            //set session
            HttpSession session = request.getSession(true);
            session.setAttribute("userName", userName);
            return true;
        }
        return false;
    }

    @RequestMapping(value = "getLoginUser", method= RequestMethod.GET)
    public String getLoginUser(HttpSession session) {
        if(session.getAttribute("userName") == null) {
            return "";
        }
        return (String)session.getAttribute("userName");
    }
}

调整前端⻚⾯代码

<!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="jquery-3.7.1.min.js"></script>
  <script>
    function login() {
      $.ajax({
        type:"post",
        url: "/user/login",
        data: {
          "userName":$("#userName").val(),
          "password":$("#password").val()
        },
        success: function(body) {
          if(body == true){
            //skip to index page
            location.href = "index.html"
          }else {
            //current page
            alert("wrong userName or password")
          }
        }
      });
    }

  </script>
</body>

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>用户登录首页</title>
</head>

<body>
    登录人: <span id="loginUser"></span>

    <script src="jquery-3.7.1.min.js"></script>
    <script>
        $.ajax({
            type : "get",
            url : "/user/getLoginUser",
            success: function(userName) {
                $("#loginUser").text(userName);
            }
        });
    </script>
</body>

</html>

留⾔板

需求:

界⾯如下图所⽰

1. 输⼊留⾔信息, 点击提交. 后端把数据存储起来.

2. ⻚⾯展⽰输⼊的表⽩墙的信息

约定前后端交互接⼝

需求分析

后端需要提供两个服务

1. 提交留⾔: ⽤⼾输⼊留⾔信息之后, 后端需要把留⾔信息保存起来

2. 展⽰留⾔: ⻚⾯展⽰时, 需要从后端获取到所有的留⾔信息

接⼝定义

1. 获取全部留⾔

全部留⾔信息, 我们⽤List来表⽰, 可以⽤JSON来描述这个List数据.

请求:

GET /message/getList
响应: JSON 格式
[
    {
     "from": "⿊猫",
     "to": "⽩猫",    
     "message": "喵"    
    },{
     "from": "⿊狗",
     "to": "⽩狗",
     "message": "汪"
     },
 //...
]
浏览器给服务器发送⼀个 GET /message/getList 这样的请求, 就能返回当前⼀共有哪些留⾔
记录. 结果以 json 的格式返回过来
2. 发表新留⾔

请求: body 也为 JSON 格式

POST /message/publish
{
 "from": "⿊猫",
 "to": "⽩猫",
 "message": "喵"
}
响应: JSON 格式.
{
 ok: 1
}

实现服务器端代码

lombok介绍

在这个环节, 我们介绍⼀个新的⼯具包 lombok

Lombok是⼀个Java⼯具库,通过添加注解的⽅式,简化Java的开发.

简单来学习下它的使⽤

1. 引⼊依赖

<dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <optional>true</optional>
</dependency>
2. 使⽤

lombok通过⼀些注解的⽅式, 可以帮助我们消除⼀些冗⻓代码, 使代码看起来简洁⼀些

@Data
public class Person {
 private int id;
 private String name;
 private String password;
}
如果觉得@Data⽐较粗暴(⽣成⽅法太多), lombok也提供了⼀些更精细粒度的注解

服务器代码实现

package com.example.demo;

import lombok.Data;

@Data
public class MessageInfo {
    private String from;
    private String to;
    private String message;
}


package com.example.demo;

import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/message")
public class MessageController {

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

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

    @RequestMapping(value = "/publish", produces = "application/json")
    public String publish(@RequestBody MessageInfo messageInfo) {
        if((StringUtils.hasLength(messageInfo.getFrom())) &&
                (StringUtils.hasLength(messageInfo.getTo())) &&
                (StringUtils.hasLength(messageInfo.getMessage()))
        ) {
            messageInfos.add(messageInfo);
            return "{\"ok\":1}";
        }
        return "{\"ok\":0}";
    }

}

调整前端⻚⾯代码

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

<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="jquery-3.7.1.min.js"></script>
    <script>
        getList();
        function getList() {
            $.ajax({
                type: "get",
                url: "/message/getList",
                success: function (message) {
                    for (var msg of message) {
                        //2. 构造节点
                        var divE = "<div>" + msg.from + "对" + msg.to + "说:" + msg.message + "</div>";
                        //3. 把节点添加到页面上    
                        $(".container").append(divE);
                    }
                }
            });
        }


        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",
                contentType: "application/json",
                data: JSON.stringify({
                    from: from,
                    to: to,
                    message: say
                }),
                success: function (result) {
                    if (result.ok == 1) {
                        alert("add success!")
                        //2. 构造节点
                        var divE = "<div>" + from + "对" + to + "说:" + say + "</div>";
                        //3. 把节点添加到页面上    
                        $(".container").append(divE);
                        //4. 清空输入框的值
                        $('#from').val("");
                        $('#to').val("");
                        $('#say').val("");
                    } else {
                        alert("add fail!");
                    }
                }
            });





        }

    </script>
</body>

</html>

图书管理系统

需求:

1. 登录: ⽤⼾输⼊账号,密码完成登录功能

2. 列表展⽰: 展⽰图书

约定前后端交互接⼝

需求分析

图书管理系统是⼀个相对较⼤⼀点的案例, 咱们先实现其中的⼀部分功能.

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

1. 账号密码校验接⼝: 根据输⼊⽤⼾名和密码校验登录是否通过

2. 图书列表: 提供图书列表信息

接⼝定义

1. 登录接⼝


[URL]
POST /user/login
[请求参数]
name=admin&password=admin
[响应]
true //账号密码验证成功
false//账号密码验证失败

2. 图书列表展⽰

[URL]
POST /book/getList
[请求参数]
⽆
[响应]
返回图书列表
[
 {
 "id": 1,
 "bookName": "活着",
 "author": "余华",
 "count": 270,
 "price": 20,
 "publish": "北京⽂艺出版社",
 "status": 1,
 "statusCN": "可借阅"
 },
 ...
]

字段说明:

服务器代码

package com.pixiao.book;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

@RestController
@RequestMapping("/book")
public class BookController {
    @RequestMapping(value = "/getList", method = RequestMethod.GET)
    public List<BookInfo> getList() {
        List<BookInfo> bookInfos = mockData();
        for(BookInfo bookInfo: bookInfos) {
            if(bookInfo.getStatus() == 1) {
                bookInfo.setStatusCN("可借阅");
            } else {
                bookInfo.setStatusCN("不可借阅");
            }
        }
        return bookInfos;
    }

    private List<BookInfo> mockData() {
        List<BookInfo> bookInfos = new ArrayList<>();
        for (int i = 1; i <= 15; i++) {
            BookInfo bookInfo = new BookInfo();
            bookInfo.setId((long) i);
            bookInfo.setBookName("book" + i);
            bookInfo.setAuthor("author" + i);
            bookInfo.setPublishName("press" + i);
            bookInfo.setNum("" + new Random().nextInt(100));
            bookInfo.setPrice(new BigDecimal(new Random().nextInt(70) + 10));
            bookInfo.setStatus(i % 5 == 0 ? 0: 1);
            bookInfos.add(bookInfo);
        }
        return bookInfos;
    }
}


package com.pixiao.book;

import lombok.Data;

import java.math.BigDecimal;

@Data
public class BookInfo {
    private Long id;
    private String bookName;
    private String author;
    private String num;
    private BigDecimal price;
    private String publishName;
    private Integer status;
    private String statusCN;
}


package com.pixiao.book;

import jakarta.servlet.http.HttpSession;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping(value = "/login" , method = RequestMethod.POST)
    public Boolean login(String name, String password, HttpSession session) {
        //1.校验参数
        if(!StringUtils.hasLength(name) || !StringUtils.hasLength(password)) {
            return false;
        }
        //2.校验账号密码
        if("admin".equals(name) && "admin".equals(password)) {
            //3.如果正确,存储session,返回true
            session.setAttribute("userName", name);
            return true;
        }
        return false;
    }

}

调整前端⻚⾯代码

<!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 : {
                    name: $("#userName").val(),
                    password: $("#password").val()
                },
                success: function(result) {
                    if(result) {
                        location.href = "book_list.html";
                    } else {
                        alert("error");
                    }
                }
            }); 
        }
    </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 id="bookList">
           
            </tbody>
        </table>

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

            getBookList();
            function getBookList() {
                $.ajax({
                    type: "get",
                    url: "book/getList",
                    success: function(books) {
                        var finalHtml = "";
                        for(var book of books) {
                            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.num+"</td>";
                            finalHtml += "<td>"+book.price+"</td>";
                            finalHtml += "<td>"+book.publishName+"</td>";
                            finalHtml += "<td>"+book.statusCN+"</td>";
                            finalHtml += "<td>";
                            finalHtml += '<div class="op">';
                            finalHtml += '<a href="book_update.html?bookId='+book.id+'">修改</a>';
                            finalHtml += '<a href="javascript:void(0)" onclick="deleteBook('+book.id+')">删除</a>';
                            finalHtml += "</div>";
                            finalHtml += "</td>";
                            finalHtml += "</tr>";
                        }
                        $("#bookList").html(finalHtml);
                    }
                });
            }
    
            //翻页信息
            $("#pageContainer").jqPaginator({
                totalCounts: 100, //总记录数
                pageSize: 10,    //每页的个数
                visiblePages: 5, //可视页数
                currentPage: 1,  //当前页码
                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);
                }
            });
            function deleteBook(id) {
                var isDelete = confirm("确认删除?");
                if (isDelete) {
                    //删除图书
                    alert("删除成功");
                }
            }
            function batchDelete() {
                var isDelete = confirm("确认批量删除?");
                if (isDelete) {
                    //获取复选框的id
                    var ids = [];
                    $("input:checkbox[name='selectBook']:checked").each(function () {
                        ids.push($(this).val());
                    });
                    console.log(ids);
                    alert("批量删除成功");
                }
            }

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

</html>

应⽤分层

⽬前现在更主流的开发⽅式是 "前后端分离" 的⽅式, 后端开发⼯程师不再需要关注前端的实现, 所以对于Java后端开发者, ⼜有了⼀种新的分层架构: 把整体架构分为表现层、业务逻辑层和数据层. 这种分层⽅式也称之为"三层架构".

1. 表现层: 就是展⽰数据结果和接受⽤⼾指令的,是最靠近⽤⼾的⼀层;

2. 业务逻辑层: 负责处理业务逻辑, ⾥⾯有复杂业务的具体实现;

3. 数据层: 负责存储和管理与应⽤程序相关的数据

按照上⾯的层次划分, Spring MVC 站在后端开发⼈员的⻆度上, 也进⾏了⽀持, 把上⾯的代码划分为三个部分:

请求处理、响应数据:负责,接收⻚⾯的请求,给⻚⾯响应数据.

逻辑处理:负责业务逻辑处理的代码.

数据访问:负责业务数据的维护操作,包括增、删、改、查等操作.

这三个部分, 在Spring的实现中, 均有体现:

Controller:控制层。接收前端发送的请求,对请求进⾏处理,并响应数据。
Service:业务逻辑层。处理具体的业务逻辑。
Dao:数据访问层,也称为持久层。负责数据访问操作,包括数据的增、删、改、查

MVC 和三层架构的区别和联系

从概念上来讲, ⼆者都是软件⼯程领域中的架构模式.

MVC架构模式由三部分组成, 分别是: 模型(Model), 视图(View)和控制器(Controller).

三层架构将业务应⽤划分为:表现层, 业务逻辑层, 数据访问层

MVC中, 视图和控制器合起来对应三层架构中的表现层. 模型对应三层架构中的业务逻辑层, 数据层, 以及实体类

⼆者其实是从不同⻆度对软件⼯程进⾏了抽象.

MVC模式强调数据和视图分离, 将数据展⽰和数据处理分开, 通过控制器对两者进⾏组合.

三层架构强调不同维度数据处理的⾼内聚和低耦合, 将交互界⾯, 业务处理和数据库操作的逻辑分开.

⻆度不同也就谈不上互相替代了,在⽇常的开发中可以经常看到两种共存的情况,⽐如我们设计模型层的时候往往也会拆分出业务逻辑层(Service层)和数据访问层(Dao层)。

但是⼆者的⽬的是相同的, 都是"解耦,分层,代码复⽤"

软件设计原则:⾼内聚低耦合.

⾼内聚指的是:⼀个模块中各个元素之间的联系的紧密程度,如果各个元素(语句、程序段)之间的联系程度越⾼,则内聚性越⾼,即 "⾼内聚"。

低耦合指的是:软件中各个层、模块之间的依赖关联程序越低越好。修改⼀处代码, 其他模块的代码改动越少越好.

⾼内聚低耦合⽭盾吗?

不⽭盾, ⾼内聚指的是⼀个模块中各个元素之间的联系的紧密程度, 低耦合指的是各个模块之间的紧

密程度         

应⽤分层的好处

降低层与层之间的依赖, 结构更加的明确, 利于各层逻辑的复⽤

开发⼈员可以只关注整个结构中的其中某⼀层, 极⼤地降低了维护成本和维护时间

可以很容易的⽤新的实现来替换原有层次的实现

有利于标准化

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

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

相关文章

day26作业

1使用多线程基于TCP协议的并发执行&#xff0c;一个服务器对应多个客户端实现通信实验 #include <myhead.h> //主线程负责监听客户端连接请求 //子线程负责数据收发 #define IP "192.168.60.77" #define PORT 5555 #define BACKLOG 10 typedef struct {struct…

【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!

大家好&#xff0c;欢迎来到程序视点&#xff01;我是小二哥&#xff01; 前言 在VUE项目开发中&#xff0c;一些数据常常被多个组件频繁使用&#xff0c;为了管理和维护这些数据&#xff0c;就出现了状态管理模式。 今天小二哥要给大家推荐的不是VueX&#xff0c;而是称为新…

【机器学习chp6】对数几率回归

推荐文章1&#xff0c;其中解释了负log似然损失等价于交叉熵损失。 【王木头从感知机到神经网络】-CSDN博客 推荐文章2&#xff0c;其中有牛顿法的介绍 【王木头梯度下降法优化】随机梯度下降、牛顿法、动量法、Nesterov、AdaGrad、RMSprop、Adam-CSDN博客 推荐文章3&#…

图像处理实验报告

实验一 图像处理的MATLAB基础 实验目的&#xff1a;熟悉数字图象处理的基本软件工具和操作 实验内容&#xff1a;Matlab应用复习&#xff0c;矩阵产生、操作&#xff1b;矩阵运算以及字符运算。 1.利用增量产生向量[0,2,4,6,8,10]。 2.利用magic(n)函数产生7维魔鬼矩阵A&am…

离散数学---概率, 期望

本文根据 MIT 计算机科学离散数学课程整理&#xff08;Lecture 22 ~ Lecture 24&#xff09;。 1 非负整数期望性质 用 N 表示非负整数集合&#xff0c;R 是 N 上的随机变量&#xff0c;则 R 的期望可以表示成&#xff1a; 证明&#xff1a; 换一个形式&#xff0c;把每一列…

GPU服务器厂家:科研服务器领域机遇与博弈,AMD 新UDNA 架构

科研服务器作为推动科学研究进步的核心基础设施&#xff0c;其性能与架构的创新对于整个科研生态有着极为关键的影响。AMD 全新推出的 UDNA 架构&#xff0c;引发了广泛的关注与讨论。 AMD UDNA 架构于科研服务器的产品数据与市场格局 AMD 在计算机硬件领域的影响力持续攀升&a…

STM32H7开发笔记(2)——H7外设之多路定时器中断

STM32H7开发笔记&#xff08;2&#xff09;——H7外设之多路定时器中断 文章目录 STM32H7开发笔记&#xff08;2&#xff09;——H7外设之多路定时器中断0.引言1.CubeMX配置2.软件编写 0.引言 本文PC端采用Win11STM32CubeMX4.1.0.0Keil5.24.2的配置&#xff0c;硬件使用STM32H…

【Linux】Linux入门实操——定时任务调度

一、crond调度 1. 概述 任务调度: 是指系统在某个时间执行的特定的命令或程序。任务调度分类 1. 系统工作 : 有些重要的工作必须周而复始地执行。如病毒扫描等 2. 用户工作 &#xff1a;用户可能希望执行某些程序&#xff0c;比如对mysql数据库的备份。 2. 基本语法 cron…

找到字符串中所有字母异位词(java)

题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词 示例 1: 输入: s "cbaebabacd", p "abc&…

Leetcode226. 翻转二叉树(HOT100)+Leetcode221. 最大正方形(HOT100)

链接 题解&#xff1a; 本题是要镜像反转二叉树&#xff0c;相当于从中间一分&#xff0c;然后把左子树和右子树对调&#xff0c;但又不是简单的对调&#xff0c;还要继续反转子树的子树&#xff0c;所以要用递归。 我们特判root是否为空&#xff08;否则出现nullptr->nul…

ISUP协议视频平台EasyCVR私有化视频平台新能源汽车充电停车管理方案的创新与实践

在环保意识提升和能源转型的大背景下&#xff0c;新能源汽车作为低碳出行的选择&#xff0c;正在全球迅速推广。但这种快速增长也引发了充电基础设施短缺和停车秩序混乱等挑战&#xff0c;特别是在城市中心和人口密集的居住区&#xff0c;这些问题更加明显。因此&#xff0c;开…

国际知名摄影测量与遥感专家、瑞士苏黎世联邦理工学院终身教授Armin Gruen莅临大势智慧参观交流

11月18日&#xff0c;瑞士苏黎世联邦理工学院终身教授、国际摄影测量与遥感学会荣誉会员、武汉大学测绘遥感信息工程国家重点实验室客座教授Armin Gruen莅临武汉大势智慧科技有限公司&#xff08;以下简称“大势智慧”&#xff09;参观交流。大势智慧董事长黄先锋亲自接待了Arm…

RTSP播放器EasyPlayer.js播放器分辨率高的视频在设置container的宽高较小时,会出现锯齿状的画面效果

流媒体播放器的核心技术及发展趋势展现了其在未来数字生活中的无限潜力。随着技术的不断进步和市场的持续发展&#xff0c;流媒体播放器将在内容创新、用户体验优化以及跨平台互通等方面取得新的突破。对于从业者而言&#xff0c;把握这些趋势并积极应对挑战将是实现成功的关键…

C# 数据结构之【树】C#树

以二叉树为例进行演示。二叉树每个节点最多有两个子节点。 1. 新建二叉树节点模型 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace DataStructure {class TreeNode{public int Data { get;…

Sqlite: Java使用、sqlite-devel

这里写目录标题 一、简介二、使用1. Java项目中&#xff08;1&#xff09;引入驱动&#xff08;2&#xff09;工具类&#xff08;3&#xff09;调用举例 2. sqlite-devel in linuxsqlite-devel使用 三、更多应用1. 数据类型2. 如何存储日期和时间3. 备份 一、简介 非常轻量级&…

MySQL深入:B+树的演化、索引和索引结构

提示&#xff1a;内容是读《MySQL技术内幕&#xff1a;InnoDB存储引擎》&#xff0c;笔记摘要 文章目录 二叉查找树平衡二叉树(AVL) B树(BTree)B树(BTree)InnoDB B树索引索引结构&#xff08;InnoDB B树&#xff09;B树存放的数据量 二叉查找树 在二叉查找树中&#xff0c;左子…

C语言-11-18笔记

1.C语言数据类型 类型存储大小值范围char1 字节-128 到 127 或 0 到 255unsigned char1 字节0 到 255signed char1 字节-128 到 127int2 或 4 字节-32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647unsigned int2 或 4 字节0 到 65,535 或 0 到 4,294,967,295short2 字节…

“乐鑫组件注册表”简介

当启动一个新的开发项目时&#xff0c;开发者们通常会利用库和驱动程序等现有的代码资源。这种做法不仅节省时间&#xff0c;还简化了项目的维护工作。本文将深入探讨乐鑫组件注册表的概念及其核心理念&#xff0c;旨在指导您高效地使用和贡献组件。 概念解析 ESP-IDF 的架构…

【人工智能】PyTorch、TensorFlow 和 Keras 全面解析与对比:深度学习框架的终极指南

文章目录 PyTorch 全面解析2.1 PyTorch 的发展历程2.2 PyTorch 的核心特点2.3 PyTorch 的应用场景 TensorFlow 全面解析3.1 TensorFlow 的发展历程3.2 TensorFlow 的核心特点3.3 TensorFlow 的应用场景 Keras 全面解析4.1 Keras 的发展历程4.2 Keras 的核心特点4.3 Keras 的应用…

Sigrity SPEED2000 TDR TDT Simulation模式如何进行时域阻抗仿真分析操作指导-差分信号

Sigrity SPEED2000 TDR TDT Simulation模式如何进行时域阻抗仿真分析操作指导-差分信号 Sigrity SPEED2000 TDR TDT Simulation模式如何进行时域阻抗仿真分析操作指导-单端信号详细介绍了单端信号如何进行TDR仿真分析,下面介绍如何对差分信号进行TDR分析,还是以下图为例进行分…