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

【SpringBoot】从零开始全面解析SpringMVC (三)

在这里插入图片描述

本篇博客给大家带来的是SpringBoot的知识点, 本篇是SpringBoot入门, 介绍SpringMVC相关知识.
🐎文章专栏: JavaEE进阶
🚀若有问题 评论区见
欢迎大家点赞 评论 收藏 分享
如果你不知道分享给谁,那就分享给薯条.
你们的支持是我不断创作的动力 .

王子,公主请阅🚀

  • 要开心
    • 要快乐
      • 顺便进步
  • 1. 综合练习
    • 1.1 留言板
      • 1.1.1 准备工作
      • 1.1.2 约定前后端交互接口
      • 1.1.3 实现服务器代码:
    • 1.2 图书管理系统
      • 1.2.1 准备工作
    • 1.2.2 约定前后端交互接口
      • 1.2.3 服务器代码
      • 调整前端页面代码
  • 2. 应用分层
    • 2.1 分层结构介绍
    • 2.2 代码重构
    • 2.3 应用分层的好处
  • 3. 总结
    • 3.1 注解
    • 3.2 Cookie 和 Session

要开心

要快乐

顺便进步

1. 综合练习

1.1 留言板

在这里插入图片描述


需求:
界面如上图所示👆
1. 输入留言信息, 点击提交. 后端把数据存储起来.
2. 页面展示输入得表白墙的信息.

1.1.1 准备工作

码云链接: 薯条不要番茄酱

在这里插入图片描述

1.1.2 约定前后端交互接口

Ⅰ 发布留言
url : /message/publish .
param(参数) : from,to,say .
return : true / false .


Ⅱ 查询留言
url : /message/getList.
param : 无
return : form 对 to 说了 say

1.1.3 实现服务器代码:


Ⅰ 写代码之前,介绍一个新的工具包 lombok.

Lombok是一个Java工具库,通过添加注解的方式简化Java的开发.


① 引入依赖

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


② 使用

lombok 通过一些注解的方式, 可以帮助我们消除一些冗长代码, 使代码看起来简洁一些. 就比如: 上面写的 Student 对象, 无需自己写 get , set , toString方法. 只需写一个注解 @Data就可以了.

import lombok.Data;@Data
public class Student {private String name;private Integer id;private int age;
}


③ 原理解释

加了 @Data 注解之后, Idea 反编译的class文件.

在这里插入图片描述

这不是真正的字节码文件, 而是Idea根据字节码进行反编译后的文件.
反编译是将可执行的程序代码转换为某种形式的高级编程语言, 使其具有更易读的格式. 反编译是一种逆向工程,它的作用与编译器的作用相反.

在这里插入图片描述

④ 更多使用

如果觉得 @Data生成的方法太多, lombok 也提供了一些更精细粒度的注解.

在这里插入图片描述


Ⅱ 更快捷引入依赖

① 安装插件EditStarter, 重启Idea.

在这里插入图片描述

② 在pom.xml 文件中, 单击右键, 选择Generate, 操作如下图所示

在这里插入图片描述

③ 进入 Edit Starters的编辑界面, 添加对应依赖即可.

在这里插入图片描述

Ⅲ 实现服务器代码

定义留言对象

import lombok.Data;@Data
public class MessageInfo {private String from;private String to;private String say;
}


创建 MessageController 类

import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;
import java.util.List;@RequestMapping("/message")
@RestController
public class MessageController {List<MessageInfo> messageInfos = new ArrayList<>();@RequestMapping("/publish")public Boolean publish(MessageInfo messageInfo) {//校验信息if(!StringUtils.hasLength(messageInfo.getFrom())|| !StringUtils.hasLength(messageInfo.getTo())|| !StringUtils.hasLength(messageInfo.getSay())) {return false;}//把信息存起来方便下一个方法获取messageInfos.add(messageInfo);return true;}@RequestMapping("/getList")public List<MessageInfo> getList() {return messageInfos;}
}


前端页面代码

<!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>AB: hello</div> --></div><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script><script>function submit() {$.ajax({url: "/message/publish",type: "get",data: {from: $("#from").val(),to: $("#to").val(),say: $("#say").val()},//http响应成功success:function(result) {if(result == false) {alert("输入不合法");}else {//展示信息//1. 构造节点var divE = "<div>"+from+ "对" + to + "说:" + say + "</div>";//2. 把节点添加到页面上$(".container").append(divE);//3. 清空输入框的值$("#from").val("");$("#to").val("");$("#say").val("");}}});}</script>
</body></html>

1.2 图书管理系统


需求:
1. 登录: 用户输入账号,密码完成登录功能.
2. 列表展示: 展示图书.

在这里插入图片描述
在这里插入图片描述

1.2.1 准备工作


创建新项目,引入依赖.

在这里插入图片描述

将前端代码复制到 static 目录下.

在这里插入图片描述

1.2.2 约定前后端交互接口

先实现其中的两个功能: 用户登录 和 图书列表展示.

需求分析:

1. 用户登录
url : /user/login
param : userName 和 password
return : String(提示)


2. 图书列表展示 1. url : /book/getBookList
2. param : 无
3. return : 图书列表

1.2.3 服务器代码


创建图书类

import lombok.Data;import java.math.BigDecimal;@Data
public class BookInfo {private Integer id;private String bookName;private String author;private Integer num;private BigDecimal price;private String publishName;private Integer status;//对于可枚举的属性(以后可能会改的属性),通常用数字表示: 1-可借阅, 2-不可借阅private String statusCN;
}


创建UserController, 实现登录验证接口.

import jakarta.servlet.http.HttpSession;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/user")
@RestController
public class UserController {@RequestMapping("/login")public String  login(String userName, String password, HttpSession session) {//校验用户信息是否合法.if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {return "用户名或密码为空";}//判断用户名和密码是否正确//理论上应该从数据库中获取, 但是目前还没学习 mybatis, 所以先这么写.if(!"admin".equals(userName) || !"admin".equals(password)) {return "用户名或密码错误";}session.setAttribute("userName",userName);return "";}
}


创建BookController, 获取图书列表

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;@RequestMapping("/book")
@RestController
public class BookController {@RequestMapping("/getBookList")public List<BookInfo> getBookList() {List<BookInfo> bookInfos = new ArrayList<>();//mock(模拟) 数据for (int i = 1; i <= 15; i++) {BookInfo bookInfo = new BookInfo();bookInfo.setId(i);bookInfo.setBookName("图书"+i);bookInfo.setAuthor("作者"+i);bookInfo.setNum(i*2+1);bookInfo.setPrice(new BigDecimal(i*3));bookInfo.setPublishName("出版社"+i);if(i % 5 == 0) {bookInfo.setStatus(2);bookInfo.setStatusCN("不可借阅");}else {bookInfo.setStatus(1);bookInfo.setStatusCN("可借阅");}bookInfos.add(bookInfo);}return bookInfos;}
}

调整前端页面代码


登录页面:

<!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({url : "/user/login",type : "post",data : {userName : $("#userName").val(),password : $("#password").val(),},success:function(result) {if(result != "") {alert("用户名或密码错误,请重新输入");}else {location.href = "book_list.html";}}});}</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({url:"/book/getBookList",type:"get",success:function(books) {var finnalHtml = "";for(var book of books) {finnalHtml += '<tr>';finnalHtml += '<td><input type="checkbox" name="selectBook" value="1" id="selectBook" class="book-select"></td>';finnalHtml += '<td>'+book.id+'</td>';finnalHtml += '<td>'+book.bookName+'</td>';finnalHtml += '<td>'+book.author+'</td>';finnalHtml += '<td>'+book.num+'</td>';finnalHtml += '<td>'+book.price+'</td>';finnalHtml += '<td>'+book.publishName+'</td>';finnalHtml += '<td>'+book.statusCN+'</td>';finnalHtml += '<td>';finnalHtml += '<div class="op">';finnalHtml += '<a href="book_update.html?bookId='+book.id+'">修改</a>';finnalHtml += '<a href="javascript:void(0)" onclick="deleteBook('+book.id+')">删除</a>';finnalHtml += '</div>';finnalHtml += '</td>';finnalHtml += '</tr>';}$("tbody").html(finnalHtml);}});}//翻页信息$("#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>

2. 应用分层


通过上面的练习, 我们学习了Spring MVC简单功能的开发, 但是我们也发现了一些问题。
目前我们程序的代码有点"杂乱", 然而当前只是"一点点功能"的开发. 如果我们把整个项目功能完成代码会更加的"杂乱无章"(文件乱, 代码内容也乱)。


基于此, 咱们接下来学习应用分层.

2.1 分层结构介绍


Ⅰ 什么是应用分层?

应用分层 是一种软件开发设计思想, 它将应用程序分成N个层次, 这N个层次分别负责各自的职责, 多个层次之间协同提供完整的功能. 根据项目的复杂度, 把项目分成三层, 四层或者更多层.
常见的MVC设计模式, 就是应用分层的一种具体体现.


Ⅱ 应用分层的目的

在最开始的时候,为了让项目快速上线,我们通常是不考虑分层的. 但是随着业务越来越复杂,大量的
代码混在一起,会出现逻辑不清晰、各模块相互依赖、代码扩展性差、改动一处就牵动全局的问题。 所以学习对项进行分层就是我们程序员的必修课了.


Ⅲ 如何分层

“MVC” 就是把整体的系统分成了 Model(模型), View(视图)和 Controller(控制器)三个层次,也就是将用户视图和业务处理隔开,并且通过控制器连接起来,很好地实现
了表现和逻辑的解耦,是一种标准的软件分层架构。

在这里插入图片描述

目前更主流的开发方式是 “前后端分离” 的方式, 后端开发工程师不再需要关注前端的实现, 对于Java后端开发者, 又有了一种新的分层架构: 把整体架构分为表现层、业务逻辑层和数据层. 这种分层方式也称之为"三层架构".

1. 表现层: 就是展示数据结果和接受用户指令的,是最靠近用户的一层;
2. 业务逻辑层: 负责处理业务逻辑, 里面有复杂业务的具体实现;
3. 数据层: 负责存储和管理与应用程序相关的数据。


按照上面的层次划分, Spring MVC 站在后端开发人员的角度上, 也进行了支持, 把上面的代码划分为三个部分:

在这里插入图片描述
请求处理、响应数据:负责,接收页面的请求,给页面响应数据.
逻辑处理: 负责业务逻辑处理的代码.
数据访问: 负责业务数据的维护操作,包括增、删、改、查等操作.


这三个部分, 在Spring的实现中, 均有体现:
在这里插入图片描述

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

2.2 代码重构

使用上面的分层思想, 来对代码进行改造。

先创建对应的包路径, 并把代码移到对应的目录

com.fhao.book.controller
com.fhao.book.service
com.fhao.book.dao
com.fhao.book.model

在这里插入图片描述

在dao 目录下创建 BookDao文件 在service 目录下创建 BookService文件:

在这里插入图片描述

将 BookController 中的代码改写成👇:

@RequestMapping("/getBookList")public List<BookInfo> getBookList() {BookService bookService = new BookService();return bookService.getBookList();}


BookDao文件 中的代码:

public List<BookInfo> mockData() {//理论上该方法应该从数据库获取, 此处先mock 数据.List<BookInfo> bookInfos = new ArrayList<>();for (int i = 1; i <= 15; i++) {BookInfo bookInfo = new BookInfo();bookInfo.setId(i);bookInfo.setBookName("图书"+i);bookInfo.setAuthor("作者"+i);bookInfo.setNum(i*2+1);bookInfo.setPrice(new BigDecimal(i*3));bookInfo.setPublishName("出版社"+i);if(i % 5 == 0) {bookInfo.setStatus(2);bookInfo.setStatusCN("不可借阅");}else {bookInfo.setStatus(1);bookInfo.setStatusCN("可借阅");}bookInfos.add(bookInfo);}return bookInfos;}


BookService文件 中的代码

    public List<BookInfo> getBookList() {BookDao bookDao = new BookDao();List<BookInfo> bookInfos = bookDao.mockData();for(BookInfo bookInfo : bookInfos) {if(bookInfo.getStatus() == 2) {bookInfo.setStatusCN("不可借阅");}else {bookInfo.setStatusCN("可借阅");}}return bookInfos;}

2.3 应用分层的好处


1. 降低层与层之间的依赖, 结构更加的明确, 利于各层逻辑的复用.
2. 开发人员可以只关注整个结构中的其中某一层, 极大地降低了维护成本和维护时间.
3. 可以很容易的用新的实现来替换原有层次的实现.
4. 有利于标准化.


3. 总结

3.1 注解


学习Spring MVC, 其实就是学习各种Web开发需要用的到注解。

a. @RequestMapping: 路由映射

b. @RequestParam: 后端参数重命名

c. @RequestBody: 接收JSON类型的参数

d. @PathVariable: 接收路径参数

e. @RequestPart: 上传文件

f. @ResponseBody: 返回数据

g. @CookieValue: 从Cookie中获取值

h. @SessionAttribute: 从Session中获取值

i. @RequestHeader: 从Header中获取值

j. @Controller: 定义一个控制器, Spring 框架启动时加载, 把这个对象交给Spring管理. 默认返回
视图.

k. @RestController: @ResponseBody + @Controller 返回数据

3.2 Cookie 和 Session


Cookie 和Session都是会话机制, Cookie是客户端机制, Session是服务端机制. 二者通过 SessionId来关联. Spring MVC内置 HttpServletRequest 和HttpServletResponse 两个对象. 需要使用时, 直接在方法中添加对应参数即可, Cookie 和 Session 可以从HttpServletRequest 中来获取, 也可以直接使用 HttpServletResponse 设置Http响应状态码.




本篇博客到这里就结束啦, 感谢观看 ❤❤❤

🐎期待与你的下一次相遇😊😊😊

相关文章:

【SpringBoot】从零开始全面解析SpringMVC (三)

本篇博客给大家带来的是SpringBoot的知识点, 本篇是SpringBoot入门, 介绍SpringMVC相关知识. &#x1f40e;文章专栏: JavaEE进阶 &#x1f680;若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,…...

DeerFlow安装配置及使用案例

DeerFlow安装配置及使用案例 简介 ​ DeerFlow项目由字节跳动技术团队发起和主导开发&#xff0c;作为一个开源深度研究框架&#xff0c;于2025年年初正式开源。该项目基于LangStack生态&#xff0c;构建于LangChain与LangGraph的开源技术栈之上&#xff0c;充分利用语言模型…...

吉林省建筑工程专业技术人员职称评审实施办法

吉林省人力资源和社会保障厅 吉林省建筑工程专业技术人员职称评审实施办法 吉林省建筑工程技术人才之技术员评审条件 吉林省建筑工程技术人才之助理工程师评审条件 吉林省建筑工程技术人才之工程师评审条件 吉林省建筑工程技术人才之高级工程师评审条件 吉林省建筑工程技术人才…...

React组件开发流程-03.1

此章先以一个完整的例子来全面了解下React组件开发的流程&#xff0c;主要是以代码为主&#xff0c;在不同的章节中会把重点标出来&#xff0c;要完成的例子如下&#xff0c;也可从官网中找到。 React组件开发流程 这只是一个通用流程&#xff0c;在熟悉后不需要完全遵从。 …...

Vue 中 v-model 的三种使用方式对比与实践

在 Vue 3 中&#xff0c;v-model 是组件双向数据绑定的核心特性。随着 Vue 的版本演进&#xff0c;v-model 的使用方式也在不断优化。本文将基于您提供的代码示例&#xff0c;详细分析三种不同的 v-model 实现方式&#xff1a;基础用法、useVModel Hook&#xff08;vueuse/core…...

Adminer:一个基于Web的轻量级数据库管理工具

Adminer 是一个由单个 PHP 文件实现的免费数据库管理工具&#xff0c;支持 MySQL、MariaDB、PostgreSQL、CockroachDB、SQLite、SQL Server、Oracle、Elasticsearch、SimpleDB、MongoDB、Firebird、Clickhouse 等数据库。 Adminer 支持的主要功能如下&#xff1a; 连接数据库服…...

Linux笔记---内核态与用户态

用户态&#xff08;User Mode&#xff09; 权限级别&#xff1a;较低&#xff0c;限制应用程序直接访问硬件或关键系统资源。 适用场景&#xff1a;普通应用程序的运行环境。 限制&#xff1a;无法执行特权指令&#xff08;如操作I/O端口、修改内存管理单元配置等&#xff09…...

MFC 编程中 OnInitDialog 函数

核心作用 对话框初始化入口 &#xff1a;创建完成后第一个执行的函数。是对话框的起点。控件操作安全期 &#xff1a;此时所有控件已创建完成。可以安全地进行控件的初始化、属性设置等操作。界面布局最佳时机 &#xff1a;窗口显示前完成初始化设置。可以进行布局调整、数据初…...

Java高频面试之并发编程-18

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天又来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;详细说说synchronized synchronized 是 Java 中实现线程同步的核心关键字&#xff0c;用于解决多线程环境下的资源竞争…...

深入探究AKS Workload Identity

Azure Kubernetes 服务 (AKS) 提供了一项名为 Workload Identity 的强大功能&#xff0c;它可以增强安全性并简化在 Kubernetes 集群中运行的应用程序的身份验证。以下是 Workload Identity 在 AKS 环境中的工作原理概述&#xff1a; AKS 中的 Workload Identity 允许 Pod 无需…...

【MySQL基础】MySQL基础:MySQL基本操作与架构

MySQL学习&#xff1a; https://blog.csdn.net/2301_80220607/category_12971838.html?spm1001.2014.3001.5482 前言&#xff1a; 这里是MySQL学习的第一篇&#xff0c;本篇主要是讲解一些MySQL的基础操作&#xff0c;但这并不是重点&#xff0c;本篇我们主要是要理解MySQL…...

【线下沙龙】NineData x Apache Doris x 阿里云联合举办数据库技术Meetup,5月24日深圳见!

5月24日下午&#xff0c;NineData 将联合 Apache Doris、阿里云一起&#xff0c;在深圳举办数据库技术Meetup。本次技术沙龙聚焦「数据实时分析」与「数据同步迁移」 两大核心领域&#xff0c;针对企业数据战略中的痛点&#xff0c;特邀行业资深技术大咖&#xff0c;结合多年技…...

【Unity网络编程知识】Unity的 UnityWebRequest相关类学习

1、UnityWebRequest类介绍 UnityWebRequest是一个unity提供的一个模块化的系统类&#xff0c;用于构成HTTP请求和处理HTTP响应&#xff0c;它主要目标是让unity游戏和Web服务端进行交互&#xff0c;它将之前WWW的相关功能都集成在了其中&#xff0c;所以新版本中都建议使用unit…...

STM32实战指南——DHT11温湿度传感器驱动开发与避坑指南

知识点1【DHT11的概述】 1、概述 DHT是一款温湿度一体化的数字传感器&#xff08;无需AD转换&#xff09;。 2、驱动方式 通过单片机等微处理器简单的电路连接就能实时采集本地湿度和温度。DHT11与单片机之间采用单总线进行通信&#xff0c;仅需要一个IO口。 相对于单片机…...

SVG 与 Canvas 技术调研对比

在 画布 中进行 大量矩形框绘制 时&#xff0c;SVG 和 Canvas 都是可行的技术方案&#xff0c;但它们适用于不同的场景&#xff0c;技术特性也有明显区别。下面我从性能、灵活性、可维护性、适用场景等方面做一个系统性的对比&#xff0c;帮助你做出更合适的选择。 &#x1f9e…...

Ubuntu 远程桌面配置指南

概述: 本文主要介绍在Ubuntu 22.04中通过VNC实现远程连接的方法。首先需安装图形化界面和VNC工具x11vnc,设置开机启动服务;然后在Windows客户端用VNC Viewer通过局域网IP和端口5900连接。 总结: 一、VNC配置与安装 安装图形化界面 在Ubuntu 22.04中需先安装: sudo apt …...

146. LRU 缓存

一、题目 二、思路 题目要求 O(1) 的平均时间复杂度运行 -> 使用Map空间换时间 Map<Integer, Node>Map 通过 key 直接找到对应节点 getNode(key) -> Node记得只要查过该节点之后就应该把该节点放到最前面 pushFront(Node)put 元素后&#xff0c;在map中添加&…...

微信学习之导航功能

先看这个功能的效果&#xff1a; 然后开始学习吧。 一、我们这里用的是vant的Grid控件&#xff0c;首先我们导入&#xff1a; { "usingComponents": {"van-search": "vant/weapp/search/index","my-swiper":"../../components…...

MySQL替换瀚高数据库报错: TO_DAYS()不存在(APP)

文章目录 环境症状问题原因解决方案报错编码 环境 系统平台&#xff1a;中标麒麟&#xff08;海光&#xff09;7,中标麒麟&#xff08;飞腾&#xff09;7 版本&#xff1a;4.5 症状 MySQL替换为瀚高数据库进行应用系统适配报错&#xff1a;TO_DAYS&#xff08;&#xff09;不…...

FPGA:高速接口JESD204B以及FPGA实现

本文将先介绍JESD204B高速接口的基本概念和特性&#xff0c;然后详细说明如何基于Xilinx Kintex-7系列FPGA实现JESD204B高速接口。 一、JESD204B高速接口介绍 JESD204B是由JEDEC&#xff08;固态技术协会&#xff09;制定的一种高速串行通信标准&#xff0c;主要用于数据转换器…...

HarmonyOS Navigation组件深度解析与应用实践

HarmonyOS Navigation组件深度解析与应用实践 一、组件架构与核心能力 HarmonyOS Navigation组件作为路由导航的根视图容器&#xff0c;采用三层架构设计&#xff1a; 标题层&#xff1a;支持主副标题配置&#xff0c;提供Mini/Free/Full三种显示模式内容层&#xff1a;默认…...

C#中的ThreadStart委托

ThreadStart 委托&#xff1a; ThreadStart 是 .NET 中的一个内置委托类型&#xff0c;表示无参数且无返回值的方法。其定义如下&#xff1a; public delegate void ThreadStart(); 通常用于定义线程的入口方法。 List<ThreadStart>&#xff1a; 这是一个泛型集合&…...

Spring boot 集成 Knife4j

knife4j官网&#xff1a;https://doc.xiaominfo.com/docs/quick-start 1. 引入Knife4j相关依赖 <!-- knife4j--> <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version…...

基于Java在高德地图面查询检索中使用WGS84坐标的一种方法-以某商场的POI数据检索为例

前言 随着移动互联网的飞速发展&#xff0c;基于位置的服务&#xff08;LBS&#xff09;需求日益增长&#xff0c;越来越多的应用需要从地图中检索特定区域内的地理信息&#xff0c;例如商业场所、公共服务设施等。商场作为城市商业活动的重要载体&#xff0c;其周边的地理信息…...

6K型护套连接器DLJ0601(2000)-00

6K型护套连接器DLJ0601(2000)-00简介 6K型护套连接器DLJ0601(2000)-00是一种用于电气连接的组件&#xff0c;广泛应用于工业设备、通信系统和电子设备中。该连接器设计紧凑&#xff0c;具有高可靠性和耐用性&#xff0c;适用于多种环境条件下的电气连接需求。 主要特点 高可…...

Hexo的Next主题的Config文件内方便修改的参数(Chat-Gpt)

这是对 Hexo 的 Next 主题 _config.yml 文件各部分配置项的中文解释&#xff0c;帮助你更方便地进行定制&#xff1a; &#x1f680; 核心设置 cache / minify cache.enable: 启用缓存&#xff0c;加快生成速度。minify: 是否压缩生成的 HTML/CSS/JS。 custom_file_path 自…...

【three】给立方体的每个面加载不同贴图

效果图&#xff1a; 主要代码&#xff1a; initCube() {let _this thisconst geometry new Three.BoxGeometry(1, .3, .5)let TextureLoader new Three.TextureLoader()let mater1TextureLoader.load(require(/assets/images/bg2.jpg),function (texture){console.log(tex…...

vscode怎么关闭自动定位文件

关闭自动定位文件功能 方式1 在设置中搜索: explorer.autoReveal 方式2 直接在settings.json中增加"explorer.autoReveal": false 添加类似jetbrains IDE的文件定位功能 可以直接安装插件市场搜索niushuaibing.vs-location, 安装后会有文件定位按钮, 点击后即可…...

2025-5-19Vue3快速上手

1、toRefs和toRef 当解构一个响应式对象&#xff08;如 reactive 创建的对象&#xff09;时&#xff0c;直接解构会失去响应性&#xff0c;此时可用 toRefs或toRef 保持响应性 toRef 的核心作用是将对象的属性转换为 ref&#xff0c;保持与原属性的双向绑定&#xff0c;无论原…...

HDMI 屏幕 电脑HDMI HDMI采集卡的关系

一、HDMI接口方向性原理 普通设备的HDMI接口方向&#xff1a; 电脑的HDMI接口&#xff1a;无论是显卡还是主板上的HDMI&#xff0c;均为输出端&#xff08;信号源&#xff09;&#xff0c;只能向外发送视频信号&#xff0c;无法接收输入信号。 显示器的HDMI接口&#xff1a;均…...

JESD204 ip核使用与例程分析(二)

JESD204 ip核使用与例程分析(二) JESD204时钟方案专用差分时钟对例程分析jesd204_0_transport_layer_demapperjesd204_0_sig_chkjesd204_0_clockingjesd204_0 ip核port寄存器AXI-LITE寄存器配置jesd204_phy ip核JESD204时钟方案 图3-1所示为最通用、灵活的时钟解决方案。在图…...

如何使用VCS+XA加密verilog和spice网表

如果要交付verilog&#xff0c;但是需要对方进行VCS仿真&#xff0c;那么可以用以下方法&#xff1a; 一、基于编译指令的局部加密​ ​适用场景​&#xff1a;需精确控制加密范围&#xff08;如仅加密核心算法或敏感逻辑&#xff09;。 ​实现步骤​&#xff1a; ​代码标注…...

Grafana之Dashboard(仪表盘)

在前面的小节中介绍了Grafana中4中常用的可视化面板的使用&#xff0c;通过在面板中使用PromQL表达式&#xff0c;Grafana能够方便的将Prometheus返回的数据进行可视化展示。例如&#xff0c;在展示主机CPU使用率时&#xff0c;我们使用了如下表达式&#xff1a; 1 - (avg(ira…...

AOSP 中常见的键值对存储方式全解析(适用于系统开发与应用开发)

在 Android 系统开发&#xff08;AOSP&#xff09;中&#xff0c;键值对&#xff08;Key-Value&#xff09;存储是一种基础且广泛使用的数据持久化方式。从系统属性、用户设置&#xff0c;到应用配置&#xff0c;都依赖于这种结构的存储方式。本文将全面梳理 AOSP 中主流的键值…...

集合进阶2

Java不可变集合、Stream流与方法引用深度解析 一、不可变集合&#xff08;Immutable Collections&#xff09;进阶指南 1.1 不可变集合核心特性 防御性编程&#xff1a;防止外部修改数据&#xff08;如传递集合给第三方库时&#xff09;线程安全&#xff1a;天然支持多线程读…...

eMMC深度解析:嵌入式多媒体卡的硬件电路设计要点

一、eMMC 技术深度解析 1.定义与背景 eMMC&#xff08;Embedded Multi Media Card&#xff09;是一种专为嵌入式系统设计的非易失性存储解决方案&#xff0c;它将 NAND 闪存、主控芯片和接口协议封装在一个 BGA&#xff08;Ball Grid Array&#xff09;封装中。其核心目标是简…...

【SPIN】PROMELA语言编程入门同步机制(SPIN学习系列--4)

同步机制 PROMELA 不包含信号量、锁或监控器等常见的同步原语&#xff0c;而是通过语句的**可执行性&#xff08;executability&#xff09;**概念来建模同步机制。计算机系统的架构限制了同步机制的设计&#xff1a;本章主要介绍适用于共享内存系统的同步机制&#xff0c;第7…...

整数的个数

【描述】 给定k&#xff08;1< k < 100&#xff09;个正整数&#xff0c;其中每个数都是大于等于1&#xff0c;小于等于10的数。写程序计算给定的k个正整数中&#xff0c;1&#xff0c;5和10出现的次数。 【输入】 输入有两行&#xff1a;第一行包含一个正整数k&#xff…...

AWS EKS IP 耗尽:原因、解决方案和最佳实践

想象一下&#xff0c;您的 AWS EKS 集群在生产环境中运行顺畅&#xff0c;所有 CI/CD 管道运行正常&#xff0c;服务优雅地扩展&#xff0c;一切都像自动驾驶模式一样。——直到有一天&#xff0c;新的 Pod 无法启动。 您深入研究 kubectl get pods 命令&#xff0c;发现一堆 P…...

艾默生流量计与Profibus DP主站转Modbus RTU/TCP网关通讯案例

艾默生流量计与Profibus DP主站转Modbus RTU/TCP网关通讯案例 在现代工业自动化控制系统中&#xff0c;艾默生流量计因其高精度、稳定性和易用性而备受青睐。然而&#xff0c;为了实现与不同协议设备之间的无缝通信&#xff0c;经常需要借助专业的通讯网关进行协议转换。本文将…...

Python测试单例模式

单例模式的核心思想 单例模式确保一个类只有一个实例&#xff0c;并提供一个全局访问点。这在需要控制资源访问&#xff08;如配置文件、数据库连接等&#xff09;时非常有用。 一个简单的示例&#xff1a; import threading import timeclass Singleton:instance Nonelock…...

Linux架构篇、第五章_06Jenkins 触发器全面解析与实战指南

Linux架构篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;jenkins触发器的介绍与使用 版本号: 1.0,0 作者: laowang 日期: 2025.05.16 适用环境:rocky9.5 文档说明 本文档为《jenkins 触发器的介绍与…...

如何快速更换电脑浏览器ip:教程与注意事项

无论是为了访问地域限制内容、保护隐私&#xff0c;还是解决网络问题&#xff0c;快速更换浏览器IP地址的需求日益增多。以下是快速更换电脑浏览器IP地址的几种常用方法及注意事项&#xff0c;结合了多种场景下的解决方案&#xff1a; 一、快速更换浏览器IP的方法 1. 代理服务…...

《黑马前端ajax+node.js+webpack+git教程》(笔记)——ajax教程(axios教程)

黑马程序员前端AJAX入门到实战全套教程&#xff0c;包含学前端框架必会的&#xff08;ajaxnode.jswebpackgit&#xff09;&#xff0c;一套全覆盖 文章目录 框架前置导学AJAX-Day01-01.AJAX入门与axios使用什么是AJAX如何使用AJAX使用axios获取数据案例axios语法尝试获取数据代…...

超级管理员租户资源初始化与授权管理设计方案

背景说明 在多租户系统中&#xff0c;资源&#xff08;如功能模块、系统菜单、服务能力等&#xff09;需按租户维度进行授权管理。超级管理员在创建新租户时&#xff0c;需要初始化该租户的资源授权信息。 两种可选方案 方案描述方案 A&#xff1a;前端传入选中的资源列表创…...

【Python训练营打卡】day30 @浙大疏锦行

DAY 30 模块和库的导入 知识点回顾&#xff1a; 1. 导入官方库的三种手段 2. 导入自定义库/模块的方式 3. 导入库/模块的核心逻辑&#xff1a;找到根目录&#xff08;python解释器的目录和终端的目录不一致&#xff09; 作业&#xff1a;自己新建几个不同路径文件尝试下如何…...

微前端记录

微前端 实习过程中&#xff0c;做了些微前端方向的调研&#xff0c;记录下 微前端将前端拆分为独立的可以单独运行&#xff0c;测试&#xff0c;部署的代码&#xff0c; 具有技术栈无关&#xff0c;多团队&#xff0c;多业务线协作的特点。 前端现有的页面&#xff0c;分为单页…...

词嵌入基础

一 前言 最近在学习NLP方面知识&#xff0c;在此记录一下词嵌入的技术。 二 词袋法 1.理论 就是统计一个句子或文章中&#xff0c;词语出现的次数。这方法有去重词袋法&#xff0c;无去重词袋法。 a 原理与案例 chinese_docs ["我爱自然语言处理","自然语…...

CSS之网页元素的显示与隐藏(旧土豆网遮罩案例)

网页元素的显示与隐藏。 很多网页的侧边栏都会出现广告&#xff0c;我们点击关闭时&#xff0c;广告会消失不见&#xff0c;但若重新刷新网页页面&#xff0c;则广告会重新出现。网页的广告并非是真的被删除了&#xff0c;而是被暂时的隐藏起来了。 • display • visibil…...

关于 Web 漏洞原理与利用:2. XSS(跨站脚本攻击)

一、原理&#xff1a; 用户输入未过滤被执行 攻击者输入的内容&#xff0c;如果没有被正确处理&#xff08;过滤/转义&#xff09;&#xff0c;被网页原样输出到浏览器中&#xff0c;那么这些内容就可能会被浏览器当成代码执行&#xff0c;这就是 XSS&#xff08;跨站脚本攻击…...