当前位置: 首页 > news >正文

Spring Web入门练习

加法计算器

约定前后端交互接⼝

约定 "前后端交互接⼝" 是进⾏ 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 sessionHttpSession 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 pagelocation.href = "index.html"}else {//current pagealert("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 messageprivate 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,返回truesession.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) {//获取复选框的idvar 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层)。

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

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

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

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

⾼内聚低耦合⽭盾吗?

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

密程度         

应⽤分层的好处

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

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

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

有利于标准化

相关文章:

Spring Web入门练习

加法计算器 约定前后端交互接⼝ 约定 "前后端交互接⼝" 是进⾏ Web 开发中的关键环节. 接⼝⼜叫 API&#xff08;Application Programming Interface), 我们⼀般讲到接⼝或者 API&#xff0c;指的都是同⼀个东西. 是指应⽤程序对外提供的服务的描述, ⽤于交换信息…...

计算机毕业设计 | SpringBoot+vue汽车资讯网站 汽车购买咨询管理系统(附源码+论文)

1&#xff0c;绪论 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理汽车资讯网站的相关信息成为必然…...

stm32下的ADC转换(江科协 HAL版)

十二. ADC采样 文章目录 十二. ADC采样12.1 ADC的采样原理12.2 STM32的采样基本过程1.引脚与GPIO端口的对应关系2.ADC规则组的四种转换模式(**)2.2 关于转换模式与配置之间的关系 12.3 ADC的时钟12.4 代码实现(ADC单通道 & ADC多通道)1. 单通道采样2. 多通道采样 19.ADC模数…...

解决IntelliJ IDEA的Plugins无法访问Marketplace去下载插件

勾选Auto-detect proxy setting并填入 https://plugins.jetbrains.com 代理URL&#xff0c;可以先做检查连接&#xff1a;...

react 如何修改弹出的modal的标题

原来标题的样子&#xff1a; 修改为&#xff1a; 实现方式&#xff1a; <Modal title<span>股价趋势/{this.state.pccode}</span> visible{this.state.isPriceModalOpen} style{{ top: 20 }} width{1320} height{400} footer{null} onCancel{()>this.hideMo…...

C#中的二维数组的应用:探索物理含义与数据结构的奇妙融合

在C#编程中&#xff0c;二维数组&#xff08;或矩阵&#xff09;是一种重要的数据结构&#xff0c;它不仅能够高效地存储和组织数据&#xff0c;还能通过其行、列和交叉点&#xff08;备注&#xff1a;此处相交处通常称为“元素”或“单元格”&#xff0c;代表二维数组中的一个…...

HTML5拖拽API学习 托拽排序和可托拽课程表

文章目录 前言拖拽API核心概念拖拽式使用流程例子注意事项综合例子&#x1f330; 可拖拽课程表拖拽排序 前言 前端拖拽功能让网页元素可以通过鼠标或触摸操作移动。HTML5 提供了标准的拖拽API&#xff0c;简化了拖放操作的实现。以下是拖拽API的基本使用指南&#xff1a; 拖拽…...

内容补充页(相关公式解释)

from 学习日记_20241117_聚类方法&#xff08;高斯混合模型&#xff09; 学习日记_20241117_聚类方法&#xff08;高斯混合模型&#xff09; 公式 P ( Z k ) π k P(Zk) \pi_k P(Zk)πk​ 在高斯混合模型 (GMM) 中&#xff0c;公式 P ( Z k ) π k P(Zk) \pi_k P(Zk…...

vue中动态渲染静态图片资源

不报错且f12查看元素的时候&#xff0c;显示的src说明已经渲染到html的src上&#xff0c;但是就是不显示在页面上 原因 在vue上&#xff0c;动态渲染静态图片资源&#xff08;比如从assets文件夹加载的图片&#xff09;需要注意打包工具对静态资源的解析方式 由于vue2的脚手…...

管伊佳ERP,原名华夏ERP,一个简约易上手的国产ERP系统

JSH_ERP&#xff08;管伊佳ERP&#xff09;是一款开源、模块化的企业资源计划系统&#xff0c;旨在为中小企业提供高效的管理工具。它基于SpringBoot框架和SaaS模式&#xff0c;支持进销存、财务、生产等业务模块&#xff0c;包括零售、采购、销售、仓库和报表管理。 核心特点…...

学习虚幻C++开发日志——委托(持续更新中)

委托 官方文档&#xff1a;Delegates and Lamba Functions in Unreal Engine | 虚幻引擎 5.5 文档 | Epic Developer Community | Epic Developer Community 简单地说&#xff0c;委托就像是一个“函数指针”&#xff0c;但它更加安全和灵活。它允许程序在运行时动态地调用不…...

开窗函数 - first_value/last_value

1、开窗函数是什么&#xff1f; 开窗函数用于为行定义一个窗口&#xff08;这里的窗口是指运算将要操作的行的集合&#xff09;&#xff0c;它对一组值进行操作&#xff0c;不需要使用 GROUP BY 子句对数据进行分组&#xff0c;能够在同一行中同时返回基础行的列和聚合列。 2、…...

「一」HarmonyOS端云一体化概要

关于作者 白晓明 宁夏图尔科技有限公司董事长兼CEO、坚果派联合创始人 华为HDE、润和软件HiHope社区专家、鸿蒙KOL、仓颉KOL 华为开发者学堂/51CTO学堂/CSDN学堂认证讲师 开放原子开源基金会2023开源贡献之星 「目录」 「一」HarmonyOS端云一体化概要 「二」体验HarmonyOS端云一…...

nodejs21: 快速构建自定义设计样式Tailwind CSS

Tailwind CSS 是一个功能强大的低级 CSS 框架&#xff0c;只需书写 HTML 代码&#xff0c;无需书写 CSS&#xff0c;即可快速构建美观的网站。 1. 安装 Tailwind CSS React 项目中安装 Tailwind CSS&#xff1a; 1.1 安装 Tailwind CSS 和相关依赖 安装 Tailwind CSS: npm…...

从JSON数据提取嵌套字段并转换为独立列的简洁方法

从JSON数据提取嵌套字段并转换为独立列的简洁方法 在数据处理和数据分析的日常工作中&#xff0c;我们经常遇到复杂的嵌套数据结构&#xff0c;特别是嵌入在JSON字段中的数据。这些数据往往需要解析并展开成独立的列&#xff0c;以便后续分析和建模。本文将详细介绍如何在Pyth…...

湘潭大学软件工程算法设计与分析考试复习笔记(四)

回顾 湘潭大学软件工程算法设计与分析考试复习笔记&#xff08;一&#xff09;湘潭大学软件工程算法设计与分析考试复习笔记&#xff08;二&#xff09;湘潭大学软件工程算法设计与分析考试复习笔记&#xff08;三&#xff09; 前言 现在是晚上十一点&#xff0c;我平时是十…...

特征交叉-DeepCross Network学习

一 tensorflow官方实现 tensorflow的官方实现已经是V2版本 class Cross(tf.keras.layers.Layer):"""Cross Layer in Deep & Cross Network to learn explicit feature interactions.Args:projection_dim: int&#xff0c;低秩矩阵的维度&#xff0c;应该小…...

stm32cubemx+VSCODE+GCC+makefile 开发环境搭建

title: stm32cubemxVSCODEGCCmakefile 开发环境搭建 tags: FreertosHalstm32cubeMx 文章目录 内容往期内容导航第一步准备环境vscode 插件插件配置点灯 内容 往期内容导航 第一步准备环境 STM32CubeMXVSCODEMinGWOpenOcdarm-none-eabi-gcc 然后把上面下载的软件 3 4 5 bin 文…...

Go语言中的Defer机制详解与示例

在Go语言中&#xff0c;defer是一个关键字&#xff0c;用于确保资源的清理和释放&#xff0c;特别是在函数中创建的资源。defer语句会将其后的函数调用推迟到包含它的函数即将返回时执行。这使得defer成为处理文件关闭、数据库连接释放、解锁等资源清理操作的理想选择。 Defer…...

H.265流媒体播放器EasyPlayer.js H5流媒体播放器如何验证视频播放是否走硬解

随着技术的不断进步和5G网络的推广&#xff0c;中国流媒体播放器行业市场规模以及未来发展趋势都将持续保持稳定的增长&#xff0c;并将在未来几年迎来新的发展机遇。流媒体播放器将继续作为连接内容创作者和观众的重要桥梁&#xff0c;推动数字媒体产业的创新和发展。 EasyPla…...

ms-hot目录

1. ms-hot1...

vulfocus在线靶场:骑士cms_cve_2020_35339:latest 速通手册

目录 一、启动环境&#xff0c;访问页面&#xff0c;ip:端口号/index.php?madmin,进入后台管理页面&#xff0c;账号密码都是adminadmin 二、进入之后&#xff0c;根据图片所示&#xff0c;地址后追加一下代码&#xff0c;保存修改 ​三、新开标签页访问&#xff1a;①ip:端…...

AI Large Language Model

AI 的 Large Language model LLM , 大语言模型&#xff1a; 是AI的模型&#xff0c;专门设计用来处理自然语言相关任务。它们通过深度学习和庞大的训练数据集&#xff0c;在理解和生成自然语言文本方面表现出色。常见的 LLM 包括 OpenAI 的 GPT 系列、Google 的 PaLM 和 Meta…...

React Native的`react-native-reanimated`库中的`useAnimatedStyle`钩子来创建一个动画样式

React Native的react-native-reanimated库中的useAnimatedStyle钩子来创建一个动画样式&#xff0c;用于一个滑动视图的每个项目&#xff08;SliderItem&#xff09;。useAnimatedStyle钩子允许你根据动画值&#xff08;在这个例子中是scrollX&#xff09;来动态地设置组件的样…...

FastJson反序列化漏洞(CVE-2017-18349)

漏洞原理 原理就不多说了&#xff0c;可以去看我这篇文章&#xff0c;已经写得很详细了。 Java安全—log4j日志&FastJson序列化&JNDI注入-CSDN博客 影响版本 FastJson<1.2.24 复现过程 这里我是用vulfocus.cn这个漏洞平台去复现的&#xff0c;比较方便&#x…...

【优选算法篇】分治乾坤,万物归一:在重组中窥见无声的秩序

文章目录 分治专题&#xff08;二&#xff09;&#xff1a;归并排序的核心思想与进阶应用前言、第二章&#xff1a;归并排序的应用与延展2.1 归并排序&#xff08;medium&#xff09;解法&#xff08;归并排序&#xff09;C 代码实现易错点提示时间复杂度和空间复杂度 2.2 数组…...

C++:探索AVL树旋转的奥秘

文章目录 前言 AVL树为什么要旋转&#xff1f;一、插入一个值的大概过程1. 插入一个值的大致过程2. 平衡因子更新原则3. 旋转处理的目的 二、左单旋1. 左单旋旋转方式总处理图2. 左单旋具体会遇到的情况3. 左单旋代码总结 三、右单旋1. 右单旋旋转方式总处理图2. 右单旋具体会遇…...

2. Django中的URL调度器 (自定义路径转换器)

在 Django 中&#xff0c;URL 路由通常使用路径转换器&#xff08;path converters&#xff09;来匹配和捕获 URL 中的特定模式&#xff0c;例如整数、字符串或 slug 等。默认情况下&#xff0c;Django 提供了一些内置的路径转换器&#xff0c;如 <int>、<str>、&l…...

深度学习:神经网络中线性层的使用

深度学习&#xff1a;神经网络中线性层的使用 在神经网络中&#xff0c;线性层&#xff08;也称为全连接层或密集层&#xff09;是基础组件之一&#xff0c;用于执行输入数据的线性变换。通过这种变换&#xff0c;线性层可以重新组合输入数据的特征&#xff0c;并将其映射到新…...

【刷题】算法设计题+程序设计题【2】2019-2024

11.202019年真题*2BST二叉排序树分裂、双向冒泡排序 2019 真题 【2019 1】编写算法&#xff0c;将一棵二叉排序树 分解成两棵二叉排序树 t1和t2&#xff0c;使得t1中的所有结点关键字的值都小于x&#xff0c;t2中所有结点关键字都大于x。 typedef struct BSTNode{int data;str…...

国外的网站模板类网站/免费推广软件哪个好

在一些实际问题中&#xff0c;我们得到的样本数据都是多个维度的&#xff0c;即一个样本是用多个特征来表征的。比如在预测房价的问题中&#xff0c;影响房价y的因素有房子面积x1、卧室数量x2等。这里的x1,x2又被称为特征。很显然&#xff0c;这些特征的量纲和数值得量级都是不…...

网站上的文章用秀米可以做吗/google商店

1. 官网下载安装包并解压 解压Basler相机的驱动压缩包pylon_6.1.1.19861_x86_64_setup.tar.gz&#xff0c;解压之后有一个INSTALL文件和一个压缩包pylon_6.1.1.19861_x86_64.tar.gz。 2. 解压安装包里面的压缩包到指定的路径下 在computer->opt里面建文件夹pylon6&#xff0…...

企业网站可以做商城类/地推接单正规平台

求出满足以下条件的 n*m 的 01 矩阵个数&#xff1a; &#xff08;1&#xff09;第 i 行第 1~li 列恰好有 1 个 1。 &#xff08;2&#xff09;第 i 行第 ri~m 列恰好有 1 个 1。 &#xff08;3&#xff09;每列至多有 1 个 1 这题还是很有趣的&#xff0c;模拟一下样例就想出d…...

网站建设 的类型有哪些/seo工具在线访问

分享到一键分享QQ空间新浪微博百度云收藏人人网腾讯微博百度相册开心网腾讯朋友百度贴吧豆瓣网搜狐微博百度新首页QQ好友和讯微博更多...百度分享python实现爬取千万淘宝商品的方法作者&#xff1a;mingaixin 字体&#xff1a;[增加 减小] 类型&#xff1a;转载这篇文章主要介绍…...

花都营销型网站/产品软文

Oracle 19c&#xff0c;或者说是Oracle 12.2.0.3&#xff0c;是12c中稳定的版本&#xff0c;就像Oracle 11.2.0.4&#xff0c;是值得让客户做出升级决策&#xff0c;从Oracle支持的版本序列图中&#xff0c;就可以看出Oracle 19c所处的地位&#xff0c;Oracle 19c将稳定性作为此…...

怎么把网站做二维码/网络营销企业有哪些公司

2019独角兽企业重金招聘Python工程师标准>>> Grid Control 、Data Grid、Spreadsheet、Data Editor、TreeList&#xff1a; 超乎你想象&#xff01;WinForms Grid Control处理100万行数据到底有多快&#xff1f;WinForms界面控件初探&#xff1a;处理速度飞快的WinF…...