[spring] Spring MVC Thymeleaf(上)

[spring] Spring MVC & Thymeleaf(上)

本章内容主要过一下简单的 Spring MVC 的案例

简单来说,spring mvc 就是比较传统的网页开发流程,目前 boot 是可以比较轻松的配置 thymeleaf——毕竟 spring boot 内置对 thymeleaf 的支持

thymeleaf 是一个模板引擎,目前看起来是简单很多——我还依稀记得当年使用 JSP 写 spring mvc 的日子,那写的是真的很痛苦……

简单的 demo

这里就放一个超简单的 demo,能让页面跑起来就行

spring boot initializer

这里主要用的就是这 4 个包,下里用的案例会多一个依赖

在这里插入图片描述

实现简单 demo

因为是 spring mvc,所以肯定是需要有 Mocel-View-Controller 三个实现的。不过这个 demo 里面因为不涉及到数据的交互,所以没有 model

具体实现如下:

  • controller

    package com.example.thymeleafdemo.controller;import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;@Controller
    public class DemoController {// create a mapping for "/hello"@GetMapping("/hello")public String sayHello(Model model) {model.addAttribute("date", java.time.LocalDateTime.now());return "helloworld";}
    }
    • @Controller 的实现都比较熟悉了,这代表这是一个 Controller 的注解。因为这不是一个前后端分离的 rest api 实现,所以这里不需要使用 @RestController,也不需要做 request mapping

    • @GetMapping 这个就比较熟悉了,当用户访问 http://localhost:8080/hello 是就会调用当前方法

    • sayHello 是方法名,它返回的是一个字符串,而这个字符串代表着 view 的名字。以 thymeleaf 为例,spring mvc 会找到对应的模板渲染 view 层,这个也是下面会提到的

      实现的模板引擎的文件名为这里返回的字符串,即 helloworld.html

    • Model model 是 spring 在察觉到当前方法是 controller 的方法时,自动进行绑定的参数。view 层可以直接调用 model 里被添加的属性——model.addAttribute("date", java.time.LocalDateTime.now());,也就是 date 这个属性

  • view

    view 层具体在的位置位于 resources/templates 下:

    在这里插入图片描述

    实现为:

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8" /><link rel="stylesheet" th:href="@{/css/demo.css}" /><title>Title</title></head><body><p th:text="'Time on the server is ' + ${date}" class="funny"></p><script src="http://localhost:35729/livereload.js"></script></body>
    </html>
    

    这里的的视线相对比较简单,基础的 HTML 就不谈了

    • xmlns:th="http://www.thymeleaf.org 是 thymeleaf 的命名空间,也就是说下面都可以通过 th:<attr> 使用 thymeleaf 特有的属性

    • <link rel="stylesheet" th:href="@{/css/demo.css}" /> 使用的就是 thymeleaf 的语法,这里会自动解析路径去寻找对应的 css 文件,也就是在 static/css/demo.css 这个文件

    • <p th:text="'Time on the server is ' + ${date}" class="funny"></p> 这里用的是一个新的 thymeleaf 的语法,th:text 可以将后面的表达式,也就是 'Time on the server is ' + ${date} 写入到 element 中

      ${date} 就是在 controller 中传到 model 的属性,可以通过 ${} 的方式获得

    • <script src="http://localhost:35729/livereload.js"></script> 是一个热更新的脚本,在开启了 devtool 之后可以实现保存后 HTML 页面自动更新的功能

      换言之不需要刷新页面,也不需要重启服务器……就是稍微有些慢……

效果如下:

在这里插入图片描述

简述 MVC 的工作原理

在这里插入图片描述

这张图可以描述 spring mvc 的流程是什么样的

首先,浏览器会访问 front controller 组件——spring mvc 中一般指的是 DispatcherServlet,它会:

  • 集中处理所有的 HTTP 请求,并通过 URL mapping,将对应的 http 请求委托给对应的 handler/controller 进行处理
  • 解析 view 层
  • 处理 model,并与 model 和 view 层进行交互,实现 MVC 整体的数据交互

一般来说,front controller, controller, model, view 是四个比较高度抽象化的概念,它们的实施可以通过具体的组件去实现,如:

  • DispatcherServlet 是 front controller 的组件
  • @Controller & @RestController 是 controller 的 bean/class
  • @Model 显而易见的是 model 的组件
  • JSP/Thymeleaf 是 view 的组件等
  • spring 配置文件,如 XML,注解,java 配置文件等,也是 spring 的组件

总体来说,这些组件 spring 队伍已经进行实现完毕,并且内部完成了对应的配置,所以开发需要做的事情就是使用这些组件,将具体的业务填写完毕即可,如:

  • model

    声明必要的 entity 并添加对应的属性;通过 front controller 进行 controller 层和 view 层的沟通

  • view

    实现 thymeleaf/jsp 等支持的引擎模板,从 front controller 获取数据,并进行对应的处理以完成 UI 层面的渲染

  • controller

    与 service 层进行沟通,获取并处理对应的数据,并将其处理为 view 层所需的 model 送到 front controller 去

    一般来说,业务逻辑会从 controller 中抽离出来,以保证 SPR 和代码的低耦合性,不过这篇笔记不会涉及到 crud 的操作,因此可以暂时忽略 service 层

表单 demo

下面写一个 MVC 之间互动的 demo,这样可以更好理解上一个部分中比较抽象的概念

业务逻辑如下:

request mapping via /processForm
with data
view
controller

这里省略掉了 front controller 的存在,毕竟这部分是 spring 已经实现好并且封装起来的功能

具体的实现流程如下:

  1. 创建 controller

  2. 展示 view 层,即渲染引擎模板

    这里具体要实现的功能也分为两步:

    1. 创建对应的 controller 方法去显示 html 表单
    2. 创建 HTML 模板去显示页面

    这两步必须要全部实现,才能通过访问对应的 URL 渲染对应的模板引擎

  3. 处理 HTML 表单

    根据上面的流程图所说,view 需要通过 /processForm 去和 controller 进行交互,这个过程中,view 会将用户填写的数据传给 controller

    这一步处理的过程和上面大致是一样的逻辑:

    1. 创建对应的 controller 方法去处理传来的数据,并显示处理完的页面

    2. 创建 HTML 模板去显示页面

controller 初始代码

package com.example.thymeleafdemo.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class HelloWorldController {// need a controller method to show initial HTML form@RequestMapping("/showForm")public String showForm() {return "helloworld-form";}// need a controller method to process HTML form@RequestMapping("/processForm")public String processForm() {return "helloworld";}
}

这里没有什么特别复杂的地方,和上面简单 demo 提到的一样

模板引擎初始代码

这里要实现的是两个模板引擎,一个是 helloworld-form.html,用来显示表单,让用户填写数据;一个是 helloworld,这是 controller 收集了用户提交的数据后,新定向的页面,这里将会显示用户输入的数据

具体实现如下:

  • helloworld-form

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8" /><title>Hello World - Input Form</title></head><body><form th:action="@{/processForm}" method="get"><input type="text" name="studentName" placeholder="Student Name" /><input type="submit" value="Submit" /></form><script src="http://localhost:35729/livereload.js"></script></body>
    </html>
    
  • helloworld

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8" /><title>Title</title></head><body>Hello World of Spring!<br /><br />Student name: <span th:text="${param.studentName}"></span><script src="http://localhost:35729/livereload.js"></script></body>
    </html>
    

这里简单的过一遍两个模板都做了什么,第一个 helloworld-form 会渲染一个表单,用户可以通过表单输入数据,并且提交数据。这里提交的方式是 get,所以提交的数据会添加到 URL 路径上;同时 action 中的路径是 @{/processForm},这也是 thymeleaf 的语法,表示会 map 到对应的 /processForm,也就是 controller 中的 @RequestMapping("/processForm") 对应的方法

helloworld 会渲染已经处理好的数据,并且通过 URL 获取用户提交的数据并将其渲染到页面上,效果如下:

在这里插入图片描述

使用 model

之前是直接使用 query parameter 通过 URL 去进行数据传递,不过这只能用在 GET 方法上,如果要使用 POST,那么就需要使用 request body 进行和 controller 的沟通

这个情况下,controller 可以通过 HttpServletRequest 或者 @RequestParam("attributeName") 的方式,从模板引擎那里获取对应的资料,具体实现方式如下:

controller 修改:

    // need a controller method to read from data and add data to the model@RequestMapping("/processFormV2")public String formWithModel(HttpServletRequest request, Model model) {// read req param from html formString name = request.getParameter("studentName");// convert data to all capsname = name.toUpperCase();// create the messageString result = "Yo! " + name;// add message to the modelmodel.addAttribute("message", result);return "helloworld";}

注意这里是通过 HttpServletRequest 获取对应的数据,HttpServletRequest 通过 dependency injection 动态完成注入的。在使用 GetMapping 的情况下,HttpServletRequest 会从 URL 的 query string 上获取对应数据;在 PostMapping 的情况下,HttpServletRequest 会从 request body 中动态获取,默认的格式为 Content-Type: application/x-www-form-urlencoded

⚠️:我这里用的是 @RequestMapping("/processFormV2"),最好是使用单独的 PostMappingGetMapping 去增强安全性

HTML 部分省略了,主要就是修改一下 form 请求的地址,变更为 processFormV2,随后就是获取信息的方式为 The message: <span th:text="${message}"></span>

完成修改后的结果如下:

在这里插入图片描述

绑定 request params

这是上面提到的,使用注解的方式获取信息:

    // need a controller method to read from data and add data to the model@RequestMapping("/processFormV3")public String formWithModel(@RequestParam("studentName") String name, Model model) {// convert data to all capsname = name.toUpperCase();// create the messageString result = "Using Annotation! " + name;// add message to the modelmodel.addAttribute("message", result);return "helloworld";}

HTML 模板方面,同样将指向的地址从 v2 修改到 v3 就可以,效果如下:

在这里插入图片描述

GetMapping & PostMapping

这是上面提到的安全性问题,从开发实现的角度来说,其实不太需要特别在意 spring 底层是怎么完成依赖注入的。不过从语义化开发和安全性的角度,分别使用 @PostMapping@GetMapping 还是挺重要的,一般来说:

  • GET 是用来获取数据的(Retrieve),而 POST 是用来发送数据的(Create, Update, Delete)

  • GET 的数据传送通过 URL Query Param,而 POST 通过 body request

  • GET 的安全性更低,而 POST 安全性更高

  • GET 可以被用来保存书签,而 POST 不可以

  • GET 长度限制比较大,而 POST 的长度限制比较小

    一般情况下 GET 是够用的,毕竟好像有 8000 个左右的字符,我只遇到过一个情况被后台拒绝了……那就是老板想要穷举一堆 AND/OR 的操作让后台可以直接拼接到数据库了去搜索,结果就……超过限制了……

目前 HTML 模板中使用的都是 GET ,如果 Spring 这里使用 @PostMapping 的话,那么 spring 就会抛出 method not allow 的错:

在这里插入图片描述

所以这部分还是要注意的,如果特地规范了 @PostMapping@GetMapping,那么 HTML 部分也要进行对应的更新,如:

    @PostMapping("/showForm")public String showForm() {return "helloworld-form";}

以及

    @GetMapping("/processFormV3")public String formWithModel(@RequestParam("studentName") String name, Model model) {// convert data to all capsname = name.toUpperCase();// create the messageString result = "Using Annotation! " + name;// add message to the modelmodel.addAttribute("message", result);return "helloworld";}

更换成 POST 的效果展现如下:

在这里插入图片描述

这里数据就不会从 URL 中传递,反而是通过 request body:

在这里插入图片描述

数据绑定

前面一直手动获取 request body 中的数据,不过,其实 spring 也提供数据绑定,回顾一下这张图:

在这里插入图片描述

数据绑定就是直接对数据进行一个预处理,将数据绑定到对应的 POJO 上,省去了很多的手动操作。下面是具体的实现:

实现一个 POJO:

package com.example.thymeleafdemo.model;import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;@Data
@NoArgsConstructor
@ToString
public class Student {private String firstName;private String lastName;
}

更新 controller,使用新注解 @ModelAttribute

package com.example.thymeleafdemo.controller;import com.example.thymeleafdemo.model.Student;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;@Controller
public class StudentController {@GetMapping("/showStudentForm")public String showForm(Model model) {// create a student objStudent student = new Student();// add student obj to the modelmodel.addAttribute("student", student);return "student-form";}@PostMapping("/processStudentForm")public String processForm(@ModelAttribute("student") Student student) {// log the input dataSystem.out.println("student: " + student.toString());return "student-confirmation";}
}

⚠️:这里 @ModelAttribute("student") 的名字,必须要和下面 thymeleaf 中的 object 一致

更新 HTML 模板:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8" /><title>Student Form</title></head><body><h3>Student Registration Form</h3><formth:action="@{/processStudentForm}"th:object="${student}"method="post">First Name: <input type="text" th:field="*{firstName}" /><br /><br />Last Name: <input type="text" th:field="${student.lastName}" /><br /><br /><input type="submit" value="Submit" /><script src="http://localhost:35729/livereload.js"></script></form></body>
</html>

⚠️:这里的 th:object="${student}" 就是 @ModelAttribute("student") 中的 student,这里的名字必须一致

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8" /><title>Student Confirmation</title></head><body><h3>Student Confirmation</h3>The student is confirmed:<span th:text="${student.firstName} + ' ' + ${student.lastName}"></span><script src="http://localhost:35729/livereload.js"></script></body>
</html>

⚠️:这里的 student 是手动通过 model.addAttribute("student", student); 进行绑定的

最终效果如下:

在这里插入图片描述

在这里插入图片描述

thymeleaf 属性

这里新增一些比较常用的 thymeleaf 的表单属性的用法

下拉框

即 dropdown,一个比较死板的写法如下:

<select th:field="*{country}"><option th:value="Brazil">Brazil</option><option th:value="France">France</option><option th:value="Germany">Germany</option><option th:value="India">India</option>
</select>

在显示的页面新增代码:

<br /><br />Country: <span th:text="${student.country}"></span>

这时候更新一下 学生 这个 POJO,新增一个 country 的属性:

public class Student {private String firstName;private String lastName;private String country;
}

因为使用了数据绑定,所以 controller 部分的代码不需要进行任何的变动,实现效果如下:

在这里插入图片描述

动态获取下拉框

上面的代码是写死的,不过有的情况下,可能需要通过 properties 文件获取一些数据,这个时候就没有办法在 thymeleaf 写死所有的选项了

properties 文件更新如下:

countries=Brazil,France,Germany,India,Mexico,Spain,United States

这里新增的是一个关于国家的数组

这个时候就需要更新 controller 了,需要从 properties 文件中获取对应的国家,并且将其传到模板引擎中:

    @Value("${countries}")private List<String> countries;@GetMapping("/showStudentForm")public String showForm(Model model) {// create a student objStudent student = new Student();// add student obj to the modelmodel.addAttribute("student", student);// add the list of countries to the modelmodel.addAttribute("countries", countries);return "student-form";}

HTML 部分更新如下:

<select th:field="*{country}"><optionth:each="tempCountry : ${countries}"th:value="${tempCountry}"th:text="${tempCountry}"></option>
</select>

这里使用的是一个 thymeleaf 的 for 循环,最终展示效果如下:

在这里插入图片描述

单选

即 radio button,这里也通过两个方式实现,一个就是写死值的方式,另一个是通过 properties 文件导入

写死的方式如下:

Favorite Programming Language:<label><input type="radio" th:field="*{favoriteLanguage}" th:value="Go" />Go
</label>
<label><input type="radio" th:field="*{favoriteLanguage}" th:value="Java" />Java
</label>
<label><input type="radio" th:field="*{favoriteLanguage}" th:value="Python" />Python
</label>

其余需要更新的地方也只有 POJO,这里略过不提,展现效果如下:

在这里插入图片描述

动态获取单选

实现方法类似,这里也不多赘述

properties 文件更新:

languages=Go,Java,Python,Rust,TypeScript,JavaScript

controller 部分略过不提,下面是 HTML 的修改:

Favorite Programming Language:<div th:each="language : ${languages}"><label><input type="radio" th:field="*{favoriteLanguage}" th:value="${language}" /><span th:text="${language}"></span></label>
</div>

⚠️:这里的 for 循环是绑定在一个外部的 div 上,如果直接迭代 label,那就代表着一个 label 会对应不同的 input,就会影响具体的功能实现

最终渲染效果:

在这里插入图片描述

多选

也就是 checkbox,具体不多赘述,丢代码即可

两个 HTML 的修改:

Favorite Operation System:<inputtype="checkbox"id="Linux"th:field="*{favoriteOSs}"th:value="Linux"
/><label for="Linux">Linux</label>
<inputtype="checkbox"id="MacOS"th:field="*{favoriteOSs}"th:value="MacOS"
/><label for="MacOS">MacOS</label>
<inputtype="checkbox"id="ms"th:field="*{favoriteOSs}"th:value="'Microsoft Windows'"
/><label for="ms">Microsoft Windows</label>
Favorite Operating Systems: <span th:text="${student.favoriteOSs}"></span>

POJO:

private List<String> favoriteOSs;

效果如下:

在这里插入图片描述

循环渲染结果

这里的格式还是稍微有点奇怪的,因为多选的保存格式为 List<String>,尽管 toString() 的默认实现不是很奇怪,不过也可以稍微优化一下:

<ul><li th:each="favOs: ${student.favoriteOSs}" th:text="${favOs}"></li>
</ul>

在这里插入图片描述

动态渲染多选

具体实现也略过了,和之前的实现一样:

systems=Linux,MacOS,Microsoft Windows,Android,IOS
public class StudentController {@Value("${systems}")private List<String> systems;@GetMapping("/showStudentForm")public String showForm(Model model) {// ...model.addAttribute("systems", systems);// ...}
}
Favorite Operation System:<span th:each="system: ${systems}"><inputtype="checkbox"id="${system}"th:field="*{favoriteOSs}"th:value="${system}"/><label for="${system}" th:text="${system}"></label>
</span>

最终效果如下:

在这里插入图片描述

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

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

相关文章

未授权访问漏洞总结

以下总结了常见的未授权访问漏洞&#xff0c;还在持续更新中&#xff0c;遇到就会补充。欢迎大家关注~ 目录 FTP未授权访问&#xff08;21&#xff09; 漏洞原理 漏洞检测 漏洞利用 漏洞修复 LDAP未授权访问&#xff08;389&#xff09; 漏洞原理 漏洞检测 漏洞利用 …

Mongodb介绍及window环境安装

本文主要内容为nosql数据库-MongoDB介绍及window环境安装。 目录 什么是MongoDB&#xff1f; 主要特点 MongoDB 与Mysql对应 安装MongoDB 下载MongoDB 自定义安装 创建目录 配置环境变量 配置MongoDB服务 服务改为手动 启动与关闭 安装MongoDB Shell 下载安装包 …

三:SpringBoot的helloworld和使用Springboot的优点以及快速创建Springboot应用

三&#xff1a;SpringBoot的helloworld和使用Springboot的优点以及快速创建Springboot应用 一&#xff1a;HelloWorld [我们创建的是maven项目或者直接创建一个Spring] 1.1&#xff1a;创建一个maven 项目&#xff08;1】&#xff1a;需要自己手动写一个SpringBoot 的启动类同…

为什么网上这么多破解 Intellij IDEA 的工具,但是官方却不管呢?

大家好&#xff0c;我是小2&#xff0c;一个程序员~ 程序员小2 每天一篇技术重磅好文&#xff0c;涉及一线互联网大厂应用架构&#xff08;高可用、高性能、高稳定&#xff09;&#xff0c;AI、大数据、java架构等热门领域。 112篇原创内容 公众号 来源&#xff1a;Java知音…

基于Spring Boot+VUE旅游管理系统

1管理员功能模块 管理员通过点击后台管理&#xff0c;进入页面可以输入用户名、密码、角色进行登录相对应操作&#xff0c;如图1所示。 图1管理员登录界面 管理员通过点击后台管理&#xff0c;进入页面可以填写首页、个人中心、用户管理、旅游方案管理、旅游购买管理、系统管…

HarmonyOS NEXT 从不懂到 ToDo List 实例开发

本文将从一个前端开发者的角度出发&#xff0c;速通鸿蒙 Next 开发的方方面面&#xff0c;并最终开发一个 Todo List 小实例。 简介 首先&#xff0c;鸿蒙使用 ArkTS 作为原生开发语言。如果你熟悉 TypeScript 编程语言&#xff0c;那基本上可以无缝过渡&#xff0c;因为 Ark…

Linux常⽤服务器构建-samba

目录 1. 介绍 2. 安装 3. 配置 3.1 创建存放共享⽂件的路径 3.2 创建samba账户 4 重启samba 5. 访问共享⽂件 5.1 mac下访问⽅式 5.2 windows下访问⽅式 1. 介绍 Samba 是在 Linux 和 UNIX 系统上实现 SMB 协议的⼀个免费软件&#xff0c;能够完成在 windows 、 mac 操作系统…

统计分析方法-非参数检验-python

文章目录 前言非参数检验特点常见的非参数检验一、Cliffs Delta动机定义二、Wilcoxon Signed-Rank Test定义三、 Friedman检验适用场景公式python 代码Wilcoxon Signed-Rank Test和 cliffs deltaFriedman前言 记录一下自非参数检验的学习过程,如有不对请纠正。 非参数检验 …

[AI资讯·0618] 快手AI模型“可灵“在质量优于Sora,OpenAI和谷歌发布新技术推动AI视频推理发展,Gemini1.5Pro在该榜单中表现突出

AI资讯 陕西推出AI千亿级发展计划&#xff0c;五大产业集群&#xff0c;智算超3000P试了快手的视频AI&#xff0c;竟然有点领先“技术故障”背刺巴菲特&#xff0c;金融大模型到底靠不靠谱&#xff1f;Gemini视频推理遥遥领先GPT-4o&#xff0c;首个视频多模态基准Video-MME国…

dockerhub无法拉取镜像后,国内怎么拉取镜像?

一、比如你拉取的镜像在hub.docker 你要拉取的镜像前面加前缀&#xff1a; m.daocloud.io 这里比如我要拉取&#xff1a; nginx-ingress:latest 正常我们是 docker pull nginx/nginx-ingress 现在因为某些原因&#xff0c;我们需要下面这样写&#xff1a; docker pull …

重新定义DPU——中科驭数2024产品发布会,6月19日诚邀莅临!

数据中心正经历着前所未有的变革&#xff0c;DPU作为数据中心第三颗主力芯片&#xff0c;正引领行业步入一个高效、灵活的算力新时代。 中科驭数在业内率先完成三代DPU芯片研发迭代&#xff0c;并完成规模化商用落地。一路以来&#xff0c;我们衷心地感谢客户和合作伙伴的鼎力…

避雷!又6本期刊被On Hold!ELSEVIER旗下影响因子高达10+SSCI上榜

【SciencePub学术】继《INFORMATION SCIENCES》被On Hold 之后&#xff0c;又新增3本SCIE期刊、3本SSCI期刊被列入On Hold名单。其中包含ELSEVIER旗下影响因子高达10的《RESOURCES POLICY》。 官方现在对期刊质量的管控越来越严格了&#xff0c;被标记为On Hold后的期刊中&…

【自动驾驶】串口通信控制与反馈

文章目录 串口通信控制与反馈通讯协议上行数据帧解析下行数据帧解析串口通信控制与反馈 通讯协议 上行数据指的是机器人底盘向上位机发送的状态数据, 下行数据指的是上位机向机器人底盘发送的控制信息。 上行数据帧解析 机器人运动底盘通过串口发送的数据包格式,如下表所…

SQL Server入门-SSMS简单使用(2008R2版)-1

环境&#xff1a; win10&#xff0c;SQL Server 2008 R2 参考&#xff1a; SQL Server 新建数据库 - 菜鸟教程 https://www.cainiaoya.com/sqlserver/sql-server-create-db.html 第 2 课&#xff1a;编写 Transact-SQL | Microsoft Learn https://learn.microsoft.com/zh-cn/…

LabVIEW电池管理系统测试平台

随着混合动力汽车技术的快速发展&#xff0c;对电池管理系统&#xff08;BMS&#xff09;的测试需求显著增加。利用LabVIEW软件开发了一款电池管理系统测试平台&#xff0c;通过模拟电池行为验证BMS的控制策略&#xff0c;从而降低成本、缩短开发周期&#xff0c;并提高整车的能…

基于MYSQL的JAVA初级优化措施

世界是草台班子,这句话视乎很流行! 经历过几家创业公司的项目优化,以及大公司项目. 很多优化非常初级,用心点都能自己找出来! 其实主要原因当初是为了赶进度,能省则省.什么设计啊? 什么性能压测啊. 都省掉吧! 质量都要靠测试人员帮忙找出来,更何况是性能问题呢! 那怕是配齐了…

线上扭蛋机小程序开发,潮玩时代的创新发展

随着互联网的发展&#xff0c;扭蛋机市场也进行了创新发展&#xff0c;线上扭蛋机小程序为市场带来了新活力。扭蛋机小程序将传统的模式与互联网结合&#xff0c;打造一个便捷有趣的扭蛋机市场。 一、扭蛋机小程序 在扭蛋机小程序上&#xff0c;用户通过扭蛋机抽取各种系列的…

如何查看Linux系统中占用CPU资源高的进程

在Linux系统中&#xff0c;管理进程并监控其资源使用情况是一项重要的任务。当系统性能下降或响应变慢时&#xff0c;通常是由于某个或多个进程占用了过多的CPU资源。为了找出这些进程并采取相应的措施&#xff0c;我们可以使用多种命令行工具。以下是几种常用的方法&#xff0…

Ubuntu乌班图安装VIM文本编辑器工具

系列文章目录 Ubuntu-24.04-live-server-amd64安装界面中文版 Ubuntu-24.04-live-server-amd64启用ssh Ubuntu安装qemu-guest-agent 文章目录 系列文章目录前言一、安装VIM&#xff1f;二、VIM基本设置总结 前言 从centos转到Ubuntu发现默认安装没有vi 一、安装VIM&#xff1…

SpringMVC系列十一: 文件上传与自定义拦截器

文章目录 SpringMVC文件上传基本介绍需求分析 / 图解应用实例-代码实现 自定义拦截器什么是拦截器自定义拦截器执行流程分析图自定义拦截器应用实例快速入门注意事项和细节Debug执行流程 多个拦截器多个拦截器执行流程示意图应用实例1代码实现注意事项和细节 应用实例2 作业布置…