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

Spring MVC(上)

上一篇博客的补充:

一般出现这种问题,我们就要检查版本了

我们需要查看这几个地方是否版本是对的

注意: jdk版本运行取决于什么?
1.通过cmd运行,jdk版本就是你设置的环境变量
2.通过Idea运行,取决于该项目设置的JDK版本

创建项目的方式:

1> 我们上个博客用idea进行创建

2> 通过官网进行创建

3> 通过阿里云进行创建

4> 不基于任何页面,插件进行创建: 创建空的maven项目,自己写依赖,启动类.

1.  认识Spring MVC

        Spring MVC的概念:

        因为这一块的概念有些难懂,我会多写一些例子

        MVC是⼀种架构设计模式,也⼀种思想,而SpringMVC是对MVC思想的具体实现.除此之外,Spring MVC还是⼀个Web框架.总结来说Spring MVC是⼀个实现了MVC模式的Web框架.

简而言之:    Spring MVC就是把开发网站常用的jar包封装起来,它是一种web框架

        什么是框架:

        库->模块->框架(根据封装程度从小到大排序),就相当于把很多jar包放在一起封装起来.

        什么是Web:web就是网站

        什么是MVC:它是一种软件设计模式由: 模型,试图,控制器组成(后续会详细讲)     

        什么是Servlet : 它是一种规范,其他人根据这个规范来用不同方式来进行实现.比如Tomcat 是一个实现了 Java Servlet 规范的 Web 容器(Web Container),上一节我们晓得了Tomcat是一种内置在Spring Boot里面的服务器.再比如,单例模式是一种规范,我们可以用饿汉模式和懒汉模式来进行实现.

        再打个比方: servlet是自行车,Spring是电动车,Spring是基于servlet的一种实现.

        MVC设计模式:

        MVC是Model View Controller的缩写,它是软件⼯程中的⼀种软件架构设计模式,它把软件系统分为模型、视图和控制器三个基本部分.

 

                View(视图): 指我们看的见的部分,也就是在应用程序种专门用来和浏览器进行交互,展示数据的资源.

                Model(模型): 这个就是来处理业务逻辑,是应用程序的主要部分.

                Controller(控制器): 相当于一个分发器,它用来决定视图发过来的请求用哪个模型来进行处理,以及处理完之后再跳回哪个视图.也就是用来连接视图和模型.

        举个例子:去饭店吃饭
        客户进店之后,服务员来接待客⼾点餐,客户点完餐之后,把客⼾菜单交给前厅,前厅根据客户菜单给后厨下达命令.后厨负责做饭,做完之后,再根据菜单告诉服务员,这是X号餐桌客人的饭.
在这个过程中
服务员就是View(视图),负责接待客户,帮助客户点餐,以及给顾客端饭
前厅就是Controller(控制器),根据客户的点餐情况,来选择给哪个后厨下达命令.
后厨就是Model(模型),根据前厅的要求来完成客户的⽤餐需求

        Spring SpringBoot Spring MVC之间的关系

        我们通过一个例子来理解:

        Spring 相当于火车,Spring MVC类似于售卖火车票(卖票肯定是基于火车这个条件的),一开始我们卖票就是在火车站线下买票.

        Spring Boot类似于12306,它不仅具备线上卖票(比线下更高效)的功能,还封装了买保险,订酒店,订外卖...功能模块.

        总而言之,一个项目有很多模块,Spring MVC是其中的一个模块,Spring Boot把包括Spring MVC的很多模块都封装起来了.简而言之: Spring Boot 是封装了更多功能,这个功能包含了Spring MVC的功能.也就是Spring Boot更加的高级

        也就是说Spring Boot只是实现SpringMVC的其中⼀种方式而已.
SpringBoot可以添加很多依赖,借助这些依赖实现不同的功能.SpringBoot通过添加Spring Web MVC框架,来实现web功能.

        Spring MVC 比起平常的MVC它的浏览器和服务器的交互发生了一些变化.之前我们的视图要把请求发给控制器,而此时我们的浏览器就直接把请求发给控制器,视图此时更像是起到通道的作用

  2. 使用Spring MVC 用来进行浏览器和服务器的交互

        概念碎碎念     

        既然是Web框架,那么当用户在浏览器中输⼊了url之后,我们的Spring MVC项目就可以感知到用户的请求,并给予响应. 我们学习SpringMVC,重点也就是学习如何通过浏览器和用户程序进⾏交互.(学会了下面三个流程基本上掌握了Spring MVC)

        交互流程:

        1> 建立连接: 把浏览器(用户)和java程序连接起来,也就是输入一个url能够访问并且调用到我们写的后端程序.

        2> 请求: 浏览器发出的请求可能会带一些参数,在后端程序中要想办法获得参数,因此主要还是要实现获取参数的功能.

        3> 响应: 执行了业务逻辑之后,要把程序执行的结果返回给用户,也就是响应.

        比如用户去银行存款
                建立连接:去柜台
                请求:带着银行卡,向柜台服务员发出存款请求.
                响应:银行返回⼀张存折.

              2.1 建立连接

在SpringMVC中使用 @RequestMapping来实现URL路由映射,也就是浏览器连接程序的作用.

路由映射: 当用户访问⼀个URL时,将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射.(差不多就是一个通过地址找快递的过程)

        我们直接看代码

这里的另一个注解@RestController这个就是一个标记,让Spring去看被这个标记修饰的类里面的方法.

        1>  @RequestMapping修饰方法 

我们执行启动类,然后再浏览器输入url

执行结果:

        1>  @RequestMapping修饰类

这里有几个命名建议:

        1> 路径前面我们要加/

        2> 类路径和方法路径建议一起使用.方法路径的命名我们可以根据我们的类名前面的单词来命名.

                2.2 请求

        请求方式:

        1> post

        2> get

        2.2.1 使用前端form的方式来发起请求

这俩个是常用的,我们可以再html,form表单里面的action进行使用和设置

        

我们也可以打开Fiddler进行抓包,来看我们的请求方式

        2.2.2 我们使用Postman来构造我们的请求

        毕竟我们是后端开发,前端的内容我们可能不熟,因此我们可以使用Postman来进行构造

      Postman,可以让我们来发送请求,不必写html里面的form,我们直接进行设置就可以把我们的请求方式,请求的参数,url给构造好

        

刚刚是不带参数的,我们来看看带参数的怎么构造.(主意每次修改完代码之后一定要重新启动启动类进行刷新)

        1> 带一个参数(方法里面写)
String 类型

为空的时候的状况

为数字的情况:

这个说明我们传到我们后端的东西其实是一个字符串,然后再进行类型强制转化.我们可以看看下面的Integer类型,就很明显.

Integer类型

不带参数的情况

为非数字的参数:

这个就很明显了,我们的age传进来的是一个非数字的字符串,我们强转字符串之后发现参数和接受类型是不匹配的.

基本数据类型

不带参数的情况

传入的是非数字的参数

这个报错理由和上面的一样

         2> 带多个参数
                直接在方法里面多加入几个参数

      

                创建对象,直接在类里面增加参数(类里面写)

        但是每次如果我们要增加参数,我们修改的代码就很多,我们方法如果增加了一个参数,我们调用这个方法的其他方法的实参就要多一个,此时为了解决这个问题,我们就传入一个对象,以后要增加参数,直接在类里面增加就行.

        我们先写一个类,里面提供它的get和set还有toString方法

        然后设置对象的属性值:

        不设置对象的属性值:

        此时我们发现一个奇妙的事情,我们的属性值明明是基本数据类型,啥也没赋值并没有像刚刚的把基本数据类型作为方法的参数不赋值报错4XX.因为我们的对象构造出来默认就会给属性初始值了.在类里面创建对象,外面的int默认为0,Integer默认为null,在方法里面参数类型我们建议写Integer.

               后端参数重命名: 

        某些特殊的情况下,前端传递的参数key和我们后端接收的key可以不⼀致,比如前端传递了⼀个time给后端,⽽后端是使⽤createtime字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使⽤来 @RequestParam 重命名前后端的参数值.(前后端形参的名称不一致)

        参数重命名,参数必传的情况

        此时name是前端参数,userName是后端参数

        

        参数重命名,设置参数不必传的情况

             原理:

        3> 数组传参
        方法一: 一次性写进去

        方法二: 拆开写进去

        

        4> 集合传参

        刚刚的数组是不必要用什么标签的,因为默认是传的数组,然而我们要传集合的话需要使用:

@RequestMapping标签来标记这个传的是集合.相当于把接收到的字符数组重新赋值给list

        

        5> 传递json数据

        json语法介绍: json是一种数据格式,主要负责在不同语言的数据传递和交换

        语法:

        传输json对象(有在线编辑器,可以把格式进行压缩或者把压缩还原成有格式状态)

        此时我们使用的是@RequestBody这个注解表示我们接受的是请求里面的正文,不使用就接收不到.jason里面的请求正文不是key-value的形式,json传的是请求对象,因此Student接受不到参数,如果我们要拿到那个值,我们就要使用@RequestBody.

                
                JSON字符串和Java对象互转

        此时我们使用的是ObjectMapper来处理(底层是反射)

        1> JSON字符串->JAVA对象

        使用的是ObjectMapper里面的readValue()方法

        2> JAVA对象->JSON字符串

        使用的是ObjectMapper的writeValueAsString()方法

        6> 获取URL中参数@PathVariable

        注意@RequestMapping里面的设置我们的参数的格式/article/{articleId}/{name},这个对应的是和@PathVariable我们前端参数一致.(不能只传一个参数,参数的顺序不一样也不行)

        7> 上传⽂件@RequestPart

        重命名前端参数:

代码:

package org.xiaobai.springmvc_tets.MVCFistclass;import jakarta.websocket.server.PathParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.util.Arrays;
import java.util.List;@RequestMapping("/request")//Request,类路径取类名前面的东西进行命名
@RestController
public class RequestController {@RequestMapping("/hello")//1.建立连接public String say(){return "hello, Spring mvc";}@RequestMapping("/r1")public String r1(String name) {//后端接受到参数return "接收到参数,name: " + name;}@RequestMapping("/r2")public String r2(Integer age) {//传过来的都是String类型,然后我们进行强转//后端接受到参数return "接收到参数,age: " + age;}@RequestMapping("/r3")public String r3(int age) {//传过来的都是String类型,然后我们进行强转//后端接受到参数return "接收到参数,age: " + age;}@RequestMapping("/r4")public String r4(String name,Integer age) {//传过来的都是String类型,然后我们进行强转//后端接受到参数return "name: "+name+" age: " + age;}//TODO 在这里接口的定义为双方的协议,具体为一个方法
//    @RequestMapping("/r5")
//    public String r5(String name,Integer age,String nickName) {//传过来的都是String类型,然后我们进行强转
//        //后端接受到参数
//        return "name: "+name+" age: " + age;
//    }//参数越来越多,我们传过去接口要进行修改//此时我们就直接传个对象,后续增加接口,直接在类里面添加即可,不必修改接口@RequestMapping("/r5")public String r5(Student student){return "接受参数,student: " +student;}//name是商品名字还是人名呢?此时就可以对参数进行重命名@RequestMapping("/r6")public String r6(@RequestParam("name") String userName){//前面是前端参数,后面是后端参数return "接受参数,name: " + userName;}//实现只想重命名不想必传参数@RequestMapping("/r7")public String r7(@RequestParam(value = "name",required = false) String userName){//前面是前端参数,后面是后端参数return "接受参数,name: " + userName;}//TODO MVC第二节课//TODO 传数组//方法1,直接在key里面写多个value@RequestMapping("/r8")public String r8(String[] array){//前面是前端参数,后面是后端参数return "接受参数,array: " + Arrays.toString(array);}//方法2 相同的key,一个key一个value的来写//TODO 接受一个集合
//    @RequestMapping("/r9")
//    public String r9(@RequestParam() List<String> list){//相当于把接收到的字符数组重新赋值给list
//        return "接受参数,list: " + list;
//    }@RequestMapping("/r9")//参数不必传public String r9(@RequestParam(value = "list",required = false) List<String> list){//相当于把接收到的字符数组重新赋值给listreturn "接受参数,list: " + list;}//TODO 使用json(一种数据格式)来进行传参
//    @RequestMapping("/r10")//参数不必传
//    public String r10(Student student){//相当于把接收到的字符数组重新赋值给list
//        return "接受参数,student: " +student;
//    }@RequestMapping("/r10")public String r10(@RequestBody Student student){return "接受参数,student: " +student;}//TODO 获取url中的参数@RequestMapping("/article/{articleId}")//参数不必传public String r11(@PathVariable("articleId") Integer articleId1){//相当于把接收到的字符数组重新赋值给listreturn "接收到参数,articleId: " +articleId1;}//获取多个参数@RequestMapping("/article/{articleId}/{name}")//参数不必传public String r12(@PathVariable("articleId") Integer articleId1,@PathVariable("name")String name1){//相当于把接收到的字符数组重新赋值给listreturn "接收到参数,articleId: " +articleId1 +" name: " +name1;}//上传文件//part一般就代表文件
//    @RequestMapping("r13")//参数不必传
//    public String r13(MultipartFile file){
//       String orginalFilename = file.getOriginalFilename();
//       return "接收到文件,文件名称: " + orginalFilename;
//    }//文件重命名@RequestMapping("r13")//参数不必传public String r13(@RequestPart("file") MultipartFile imgfile){String orginalFilename = imgfile.getOriginalFilename();return "接收到文件,文件名称: " + orginalFilename;}}
8> 获取Cookie/Session(很重要)
        引入Cookie和Session

        诞生Cookie和Session的原因:默认状态下,http协议的客户端和服务器之间的通信,每一次豆是一个状态,没有区别.因此http协议是一个无状态协议,也就是同样的请求参数,对于服务器而言是一样的(没有记忆力,比如我们之前写的很多代码今天和明天跑出来的是一样的结果)但是我们实际开发种,我们希望在登录网站后第二次访问服务器的时候,服务器已经知道这个请求之前已经登录过了.第一次见,把你的信息存储下来,第二次见,直接从存储的地方取出来.但是一个服务器,无状态的才是好的,别人法多少个请求都不会影响结果(这个是后话了)

        因此像网站这种有记忆力的,可以在前端存储用户信息,也可以在后端存储用户信息.

        存储用户信息:
1. 客户端存: 我们的浏览器会给每个网站开辟一个固定的大小(存储内容的地方)让他去存储这些信息.这个地方就是cookie(前端)
2. 服务端存: 在服务器存储的地方就是session(后端)

         Cookie和Session的介绍

        会话:Seesion,它是服务端存储的一个信息
比如淘宝的在线客服,这个就是一个会话(短暂时间产生的对话),它就是客户和服务器之间的不中断的请求响应.

        在计算机领域,会话是⼀个客⼾与服务器之间的不中断的请求响应.对客⼾的每个请求,服务器能够识别出请求来⾃于同⼀个客⼾.当⼀个未知的客⼾向Web应⽤程序发送第⼀个请求时就开始了⼀个会话.当客⼾明确结束会话或服务器在⼀个时限内没有接受到客⼾的任何请求时,会话就结束了.
⽐如我们打客服电话
        每次打客服电话,是⼀个会话.挂断电话,会话就结束了下次再打客服电话,⼜是⼀个新的会话.
如果我们⻓时间不说话,没有新的请求,会话也会结束.

        交互过程简要概括:

1. 客户端 输入用户名和密码
2. 服务器,进行校验,校验成功返回信息:token/令牌(学生证)
3. 客户端访问时,带上token
4. 服务器校验token是否合法,合法就返回响应信息

        token是身份的证明,sessionID是身份证明的一种实现方式,因此,session是token,但是token不是session.

        服务器同⼀时刻收到的请求是很多的.服务器需要清楚的区分每个请求是从属于哪个⽤⼾,也就是属于哪个会话,就需要在服务器这边记录每个会话以及与⽤⼾的信息的对应关系.
Session是服务器为了保存⽤⼾信息⽽创建的⼀个特殊的对象.因此Session本质就是一个哈希表,存储了⼀些键值对结构.Key就是SessionID,Value就是⽤⼾信息(⽤⼾信息可以根据需求灵活设计).cookie里面存储了sessionID,服务器从cookie中获取SessionID进行查找 

        注意: 客户端保存用户信息的方式不止cookie一种      

                

        服务器和客户端之间的交互过程详细概括:

        1. 当用户端第一次登录的时候,服务器会在Session里面增加一个记录,然后我们把sessionId通过HTTP响应的Set-Cookie字段返回给客户端,也就是返回一个token(里面有sessionId),然后客户端里面的cookie就通过set-cookie设置了它的值,里面包含了sessionID.(cookie里面存储了sessionID,服务器从cookie中获取SessionID进行查找).

        2. 当后面客户端再次登录向服务器发送请求的时候带上cookie,客户端在收到请求后,通过cookie里面的SessionID拿到对应session的信息(id,用户名..)如果找到了就返回客户信息,如果没找到就在Session里面创建新的记录,把SessionId返回给客户端

        Session和Cookie的区别

        Cookie是客户端保存用户信息的⼀种机制.Session是服务器端保存用户信息的⼀种机制.
Cookie和Session之间主要是通过SessionId关联起来的,SessionId是Cookie和Session之间的桥梁Cookie和Session经常会在⼀起配合使⽤.但是不是必须配合.完全可以⽤Cookie来保存⼀些数据在客⼾端.这些数据不⼀定是⽤户⾝份信息,也不⼀定是SessionId. Session中的sessionId也不需要⾮得通过Cookie/Set-Cookie传递,⽐如通过URL传递.

        注意: Session默认是保存在内存中的.如果重启服务器则Session数据就会丢失.

        获取Cookie
        方法一:使用Servlet内置对象

先去设置一下cookie(cookie的信息是可以直接在浏览器进行伪造的,因此服务器是需要进行辨别的)信息,启动程序,按f12,设置cookie信息.

浏览器点击刷新,出现了结果:

或者在postman里面设置

       代码解析:

 

        方法二:

        升级的点:

运行结果:

        获取Session
        方法一:使用Servlet内置对象

先设置session:

获取session:

方法二:

        升级内容:

        运行结果:

方法三:

        升级内容:

运行结果:

9> 获取Header
        方法一:使用Servlet内置对象

注意:抓啥,我们设置啥

        

        方法二:

升级:

运行结果:

        2.3 响应

                2.3.1 返回视图(@Controller)

        我们想返回的是html这个页面,而不是返回字符串,因此这个不是我们想要的结果

       但是此时我们换一个注解把@RestController换为@Controller试试.此时出现了我们想要的页面了.

        接下来我来@RestController和@Controller这俩个注解的区别,早期我们的MVC,我们的后端会返回视图,现在我们开发更加流行前后端分离的模式,我们java不再处理前端的内容,因此MVC也发生了一些改变,Controller:接收参数,返回响应.我们后端就只是根据参数,然后返回我们的数据,不会再返回一个页面了(这个数据怎么展示在页面是前端的问题)前后端进行分离了.@RestController(返回的是数据) = @Controller(返回视图) + @ResponseBody(返回的是数据,牛逼一点).因此@RestController是个复合注解

注意:@RestController,@Controller都只能修饰类,不能修饰方法,@ResponseBody方法和类都能修饰,如果作用在类上,表示该类的所有方法,返回的都是数据,如果作用在方法上,表示该方法返回的是数据.

        我们来看看@RestController的源码:

                2.3.2 返回数据(@ResponseBody)

                

        

                2.3.3 返回HTML代码片段

                2.3.4 返回JSON对象

                2.3.5 设置状态码

        SpringMVC会根据我们⽅法的返回结果⾃动设置响应状态码,程序员也可以⼿动指定状态码通过SpringMVC的内置对象HttpServletResponse提供的⽅法来进⾏设置.注意:我们设置的状态码不影响页面的展示        

补充概念:REST
接口设计的架构风格REST:资源表现层状态转移,网络上所有的资源,资源的表现形式有图片,world...形式.浏览器访问资源,资源的状态发生变化(增删改查).
基于它产生了RESTful API(这个就是接口:程序写好了,程序员告诉用户怎么去用).比如我们同样使用这个url,http://127.0.0.1:8080/blog,但是我们的请求分别是get和post,get就是获取谋篇博客的资源.post就是提交博客.也就是一个url对应的操作是不同的,但是企业中一般会把get和post这个功能放进代码里面,一般会使用http://127.0.0.1:8080/getBlog

                2.3.6设置Header(了解即可)

        Http响应报头也会向客户端传递⼀些附加信息,比如服务程序的名称,请求的资源已移动到新地址等,如:Content-Type,Local等.我们通过@RequestMapping来进行实现.先来看看它的源码

        我们通过设置produces属性的值,设置响应的报头Content-Type

代码:后端

package org.xiaobai.springmvc_tets.MVCFistclass;import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;@RequestMapping("/res")
//@RestController
@Controller//换了一个注解,返回的是视图
public class ResponseController {//TODO 返回静态页面@RequestMapping("/index")public String index() {return "/index.html";//这个返回的只是一个字符串,我们要的是一个数据,我们把上面的注解进行修改}@ResponseBody//返回的是数据@RequestMapping("/indexData")public String indexD() {return "返回数据";//这个返回的只是一个字符串,我们要的是一个数据,我们把上面的注解进行修改}//TODO 返回HTML代码片段@ResponseBody@RequestMapping("/indexData2")public String indexD2() {//我们返回的数据里面有HTML代码的时候,它就会进行解析return "<h1>我是中国人</h1>";//这个返回的只是一个字符串,我们要的是一个数据,我们把上面的注解进行修改}//TODO 返回对象@ResponseBody@RequestMapping("/getMap")public HashMap<String,String> getMap(){HashMap<String,String> map = new HashMap<>();map.put("k1","v1");map.put("k2","v2");map.put("k3","v3");return map;}//TODO 设置状态码@ResponseBody@RequestMapping("/getMap2")public String setStatus(HttpServletResponse response){response.setStatus(418);return "设置状态码";}//TODO 设置Header//method()//produces()@ResponseBody@RequestMapping(value = "/setContentType",produces = "application/json")//设置返回值类型public String setContentType(){return "{\"OK\":1}";}}

前端:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>hello,Spring MVC,我是Index页面
</body>
</html>

相关文章:

Spring MVC(上)

上一篇博客的补充: 一般出现这种问题,我们就要检查版本了 我们需要查看这几个地方是否版本是对的 注意: jdk版本运行取决于什么? 1.通过cmd运行,jdk版本就是你设置的环境变量 2.通过Idea运行,取决于该项目设置的JDK版本 创建项目的方式: 1> 我们上个博客用idea进行创建 2…...

【优选算法---归并排序衍生题目】剑指offer51---数组中的逆序对、计算右侧小于当前元素的个数、翻转对

一、剑指offer51---数组中的逆序对 题目链接: LCR 170. 交易逆序对的总数 - 力扣&#xff08;LeetCode&#xff09; 题目介绍&#xff1a; 在数组中的两个数字&#xff0c;如果前面⼀个数字大于后面的数字&#xff0c;则这两个数字组成⼀个逆序对。输入一个数组&#xff0c…...

单体到微服务:电商平台架构的演变与可扩展性探索

目录 一、整体理解可扩展性 二、从电商平台架构发展看架构的可扩展性 &#xff08;一&#xff09;单体架构 &#xff08;二&#xff09;分布式架构 &#xff08;三&#xff09;SOA架构 &#xff08;四&#xff09;微服务架构 三、1号店App服务端架构升级说明 &#xff…...

clickhouse-副本和分片

1、副本 1.1、概述 集群是副本和分片的基础&#xff0c;它将ClickHouse的服务拓扑由单节点延伸到多个节点&#xff0c;但它并不像Hadoop生态的某些系统那样&#xff0c;要求所有节点组成一个单一的大集群。ClickHouse的集群配置非常灵活&#xff0c;用户既可以将所有节点组成…...

C语言版解法力扣题:将整数按权重排序

1.题目描述 我们将整数 x 的 权重 定义为按照下述规则将 x 变成 1 所需要的步数&#xff1a; 如果 x 是偶数&#xff0c;那么 x x / 2 如果 x 是奇数&#xff0c;那么 x 3 * x 1 比方说&#xff0c;x3 的权重为 7 。因为 3 需要 7 步变成 1 &#xff08;3 --> 10 -->…...

ubuntu18.04升级到ubuntu20.04

为了使用qt6&#xff0c;在ubuntu18.04上各种折腾失败&#xff0c;无奈只能升级到ubuntu20.04, 按照网上的教程没成功。自己摸索了 lsb_release -a df -h sudo apt update sudo apt upgrade -y sudo apt dist-upgrade -y sudo apt autoremove -y sudo apt clean sudo apt inst…...

【我的 PWN 学习手札】IO_FILE 之 stdin任意地址写

我们知道&#xff0c;stdin会往“缓冲区”先读入数据&#xff0c;如果我们劫持这个所谓“缓冲区”到其他地址呢&#xff1f;是否可以读入数据到任意地址&#xff1f;答案是肯定的。 注意&#xff01;代码中的“-------”分隔&#xff0c;是为了区分一条调用链上不同代码片段&am…...

<mutex>注释 11:重新思考与猜测、补充锁的睡眠与唤醒机制,结合 linux0.11 操作系统代码的辅助(上)

&#xff08;46&#xff09;问题的起源&#xff1a; 因为上面的内核代码&#xff0c;我们编写多线程代码时&#xff0c;对手里的家伙事不那么自信。但我们知道&#xff0c;多线程在竞争锁时&#xff0c;若得不到锁&#xff0c;会进入睡眠&#xff0c;并会在被唤醒后重新尝试得…...

C/C++圣诞树

系列文章 序号直达链接1C/C爱心代码2C/C跳动的爱心3C/C李峋同款跳动的爱心代码4C/C满屏飘字表白代码5C/C大雪纷飞代码6C/C烟花代码7C/C黑客帝国同款字母雨8C/C樱花树代码9C/C奥特曼代码10C/C精美圣诞树11C/C俄罗斯方块12C/C贪吃蛇13C/C孤单又灿烂的神-鬼怪14C/C闪烁的爱心15C…...

upload-labs-master第21关超详细教程

目录 环境配置解题思路利用漏洞 操作演示 环境配置 需要的东西 phpstudy-2018 链接&#xff1a; phpstudy-2018 提取码&#xff1a;0278 32 位 vc 9 和 11 运行库 链接&#xff1a; 运行库 提取码&#xff1a;0278 upload-labs-master 靶场 链接&#xff1a; upload-lasb-ma…...

Python基础——数学运算

目录 1. 算术运算符 2. 比较运算符 3. 赋值运算符 4. 逻辑运算符 5. 成员运算符 6. 身份运算符 7. 三目运算符 Python数学计算通过多种运算符来执行&#xff0c;常用的运算符类型包括算术运算符、比较运算符、赋值运算符、逻辑运算符、成员运算符、身份运算符、三目…...

ubuntu 安装更新 ollama新版本

ubuntu 安装更新 ollama新版本 我这里是 2024-12-18 ollama 版本是 0.5.3 1手动下载 ollama-linux-amd64.tgz https://github.com/ollama/ollama/releases 2下载脚本 https://ollama.com/install.sh install.sh 和 ollama-linux-amd64.tgz 在相同路径下 修改&#xff1a;…...

汽车IVI中控开发入门及进阶(45):凌阳科技车载娱乐芯片

概述: Sunplus科技有限公司成立于1990年,是一家领先的多媒体和汽车应用芯片提供商,如DVD播放器、便携式DVD播放器、家庭娱乐音频产品、汽车信息娱乐和高级驾驶辅助系统(ADAS)。与此同时,凌阳正在为消费类、便携式和连接设备上的广泛应用提供高速I/O IP、高性能数据转换I…...

Linux export命令

本文来自智谱清言 --------- 在Linux系统中&#xff0c;export 是一个用来设置环境变量的命令。 环境变量是操作系统运行时用于存储有关系统环境的信息的变量&#xff0c;它们对于用户和程序都是可访问的。下面是关于 export 命令的一些基本用法&#xff1a; 基本语法 ba…...

AI自我进化的新篇章:谷歌DeepMind推出苏格拉底式学习,语言游戏解锁无限潜能

各位AI爱好者、技术研究者&#xff0c;大家好&#xff01;今天我们来聊聊一个令人兴奋的AI研究新进展——谷歌DeepMind推出的“苏格拉底式学习”方法。这项研究的独特之处在于&#xff0c;它让AI在没有外部数据的情况下&#xff0c;通过“语言游戏”实现自我进化&#xff0c;这…...

【BUG】记一次context canceled的报错

文章目录 案例分析gorm源码解读gin context 生命周期context什么时候cancel的什么时候context会被动cancel掉呢&#xff1f; 野生协程如何处理 案例分析 报错信息 {"L":"ERROR","T":"2024-12-17T11:11:33.0050800","file"…...

JAVA前端开发中type=“danger“和 type=“text“的区别

在前端开发中&#xff0c;type 属性通常用于指定按钮或其他元素的样式或行为。不同的框架和库可能对 type 属性有不同的定义和用法。常见的框架包括 Bootstrap、Ant Design&#xff08;antd&#xff09;、Element Plus 等。下面我将分别介绍在这些框架中 type"danger"…...

sqlite3 支持位运算 和view和 triger

数据设置条件以后可以.根据门限自动调整其他的值 由数据库记录修改时间,及记录-> 网元设备的告警产生时间,设置超时清除时间,记录系统的原始时间戳 CPp 有 sqlite 支持 json 导出字符串,json 库将字符串,映射为结构体 triger update table 更新到一个 可设置参数列表 ,view …...

Mysql复习(一)

数据库系统的核心是&#xff08; 数据库管理系统 &#xff09;。 以下的标识符中符合标识符命名规则的有几个?&#xff08;3个&#xff09; 3abc7, abc73, bc73a, c73ab,*73abc 标识符的第一个字符允许包括哪些符号?&#xff08; _ 或者 或者 #&#xff09; 关系表达式运算的…...

Redis bitmaps 使用

应用场景&#xff1a; 记录id为 1 的用户&#xff0c;2024年12月签到情况&#xff0c;并统计&#xff1b; 记录 1号签到 zxys-redis:0>setbit 1:202412 1 1 记录 2号签到 zxys-redis:0>setbit 1:202412 2 1 记录 3号未签到 zxys-redis:0>setbit 1:202412 3 0 …...

计算无人机俯拍图像的地面采样距离(GSD)矩阵

引言 在无人机遥感、测绘和精细农业等领域&#xff0c;地面采样距离&#xff08;Ground Sampling Distance&#xff0c;简称 GSD&#xff09;是一个非常重要的指标。GSD 是指图像中每个像素在地面上实际代表的物理距离&#xff0c;通常以米或厘米为单位。GSD 决定了图像的空间…...

Java基础 | 数据库的命名规范

数据库的命名规范 1. 基本原则2. 命名规范详解2.1 命名禁止项2.2 命名规范3. 通用字段规范4. 特殊表命名建议 1. 基本原则 统一性&#xff1a;全库采用一致的命名规范简洁性&#xff1a;在表达清晰的前提下尽量简短规范性&#xff1a;遵循数据库标准规范可读性&#xff1a;命名…...

计算机网络基础(2):网络安全/ 网络通信介质

1. 网络安全威胁 网络安全&#xff1a;目的就是要让网络入侵者进不了网络系统&#xff0c;及时强行攻入网络&#xff0c;也拿不走信息&#xff0c;改不了数据&#xff0c;看不懂信息。 事发后能审查追踪到破坏者&#xff0c;让破坏者跑不掉。 网络威胁来自多方面&#xff1a…...

Reactor

文章目录 正确的理解发送double free问题 1.把我们的reactor进行拆分2.链接管理3.Reactor的理论 listensock只需要设置_recv_cb&#xff0c;而其他sock&#xff0c;读&#xff0c;写&#xff0c;异常 所以今天写nullptr其实就不太对&#xff0c;添加为空就没办法去响应事件 获…...

介绍 Html 和 Html 5 的关系与区别

HTML&#xff08;HyperText Markup Language&#xff09;是构建网页的标准标记语言&#xff0c;而 HTML5 是 HTML 的最新版本&#xff0c;包含了一些新的功能、元素、API 和属性。HTML5 相对于早期版本的 HTML&#xff08;比如 HTML4&#xff09;有许多重要的改进和变化。以下是…...

已有 containerd 的情况下部署二进制 docker 共存

文章目录 [toc]学习目的开始学习dockerd启动 containerd准备配置文件启动 containerd 启动 docker准备配置文件启动 docker 环境验证停止 docker 和 containerd 学习目的 使用容器的方式做一些部署的交付&#xff0c;相对方便很多&#xff0c;不需要担心别人的环境缺少需要的依…...

Springboot @Transactional使用时需注意的几个问题

一、事务的隔离级别 在Springboot应用中&#xff0c;如果我们想实现方法一旦执行有异常产生&#xff0c;就触发事务回滚&#xff0c;可以在方法上面添加Transactional注解。如果应用采用mysql数据库&#xff0c;虽然mysql本身也有事务隔离机制&#xff0c;但在Sping数据库的应…...

西游记战力排名、笔记等

文章目录 战力排名对西游记的理解各个版本游戏题材西游记关卡和妖怪 西游记家喻户晓&#xff0c;没有谁不知道吧&#xff0c;无论是电视剧、影视&#xff0c;还是小说&#xff0c;乃至游戏&#xff0c;很多地方都有西游记的身影。 虽然知道&#xff0c;但总不如对三国啊、水浒啊…...

(2024.12)Ubuntu20.04安装ZED-SDK

一.官网地址 ZED SDK 4.2 - Download | Stereolabs 选择适配版本进行下载 二.安装程序 下载完成后&#xff0c;进入文件目录&#xff0c;打开终端&#xff0c;输入&#xff1a; chmod x ZED_SDK_Ubuntu20_cuda11.8_v4.2.2.zstd.run ./ZED_SDK_Ubuntu20_cuda11.8_v4.2.2.zst…...

Pytorch | 从零构建GoogleNet对CIFAR10进行分类

Pytorch | 从零构建GoogleNet对CIFAR10进行分类 CIFAR10数据集GoogleNet网络结构特点网络整体架构应用与影响Inceptionv1到Inceptionv2 GoogleNet结构代码详解结构代码代码详解Inception 类初始化方法前向传播 forward GoogleNet 类初始化方法前向传播 forward 训练过程和测试结…...

蓝桥杯刷题——day9

蓝桥杯刷题——day9 题目一题干解题思路一代码解题思路二代码 题目二题干解题思路代码 题目一 题干 小蓝最近在研究一种浮点数的表示方法&#xff1a;R格式。对于一个大于0的浮点数d&#xff0c;可以用R格式的整数来表示。给定一个转换参数n&#xff0c;将浮点数转换为R格式整…...

ffmpeg翻页转场动效的安装及使用

文章目录 前言一、背景二、选型分析2.1 ffmpeg自带的xfade滤镜2.2 ffmpeg使用GL Transition库2.3 xfade-easing项目三、安装3.1、安装依赖([参考](https://trac.ffmpeg.org/wiki/CompilationGuide/macOS#InstallingdependencieswithHomebrew))3.2、获取ffmpeg源码3.3、融合xf…...

分布式刚度编织,让可穿戴触觉更出色 ——Haptiknit

大家好&#xff01;今天来了解一项非常有趣的科技成果 ——“Haptiknit&#xff1a;用于可穿戴触觉的分布式刚度编织”——《Haptiknit: Distributed stiffness knitting for wearable haptics》发表于《SCIENCE ROBOTICS》。在现代科技发展中&#xff0c;可穿戴触觉设备越来越…...

Elasticsearch:什么是查询语言?

查询语言定义 查询语言包括数据库查询语言 (database query language - DQL)&#xff0c;是一种用于查询和从数据库检索信息的专用计算机语言。它充当用户和数据库之间的接口&#xff0c;使用户能够管理来自数据库管理系统 (database management system - DBMS) 的数据。 最广…...

PyQt介绍

**PyQt 和 PySide (Qt for Python) 简介** **PyQt** 和 **PySide** 是 Python 中用于开发图形用户界面 (GUI) 应用程序的两个主要框架&#xff0c;它们都是基于 Qt 库的绑定。Qt 是一个跨平台的应用程序开发框架&#xff0c;广泛用于创建图形用户界面、应用程序开发以及嵌入式…...

Oracle 数据库函数的用法(一)

Oracle数据库提供了大量的内置函数&#xff0c;可以用于完成各种操作&#xff0c;如字符串操作&#xff0c;数学计算&#xff0c;日期时间处理&#xff0c;条件判断&#xff0c;序列生成&#xff0c;聚合统计等。以下是一些常用的Oracle数据库函数&#xff1a; 一、oracle 使用…...

labelme标签批量转换数据集json_to_dataset

文章目录 labelme标签批量转换数据集json_to_dataset转换原理单张图片转换多张图片批量转换bat脚本循环法 标注图片提取标注图片转单通道 labelme标签批量转换数据集json_to_dataset 转自labelme批量制作数据集教程。 转换原理 在安装了labelme的虚拟环境中有一个labelme_js…...

《QT 5.14.1 搭建 opencv 环境全攻略》

《QT 5.14.1 搭建 opencv 环境全攻略》 一、引言二、准备工作&#xff08;一&#xff09;软件下载&#xff08;二&#xff09;系统环境确认 三、安装 QT 5.14.1&#xff08;一&#xff09;安装包下载与运行&#xff08;二&#xff09;环境变量配置 四、OpenCV 安装与配置&#…...

Sentry日志管理thinkphp8 tp8 sentry9 sentry8 php8.x配置步骤, tp8自定义异常处理类使用方法

tp8的默认使用的就是composer来管理第三方包, 所以直接使用 composer 来安装 sentry9 即可. 同时tp8和tp5的配置方式不太一样, 这里我们直接使用自定义异常类来处理Sentry的异常. 1. 安装 sentry9 包 # 安装 sentry9 包 composer require "tekintian/sentry9-php" …...

MySQL 基础:开启数据库之旅

MySQL 基础&#xff1a;开启数据库之旅 在当今数字化的时代&#xff0c;数据扮演着至关重要的角色&#xff0c;而数据库管理系统则是存储、管理和操作这些数据的强大工具。MySQL 作为一款广受欢迎的开源关系型数据库管理系统&#xff0c;被广泛应用于各类网站、应用程序以及企业…...

OpenTK 中帧缓存的深度解析与应用实践

摘要: 本文深入探讨了 OpenTK 中帧缓存的使用。首先介绍了帧缓存的基本概念与在图形渲染管线中的关键地位,包括其与颜色缓存、深度缓存、模板缓存等各类缓存的关联。接着详细阐述了帧缓存对象(FBO)的创建、绑定与解绑等操作,深入分析了纹理附件、渲染缓冲区附件在 FBO 中的…...

stm32制作CAN适配器5--WinUsb上位机编写

上次我们要stm32制作了一个基于winusb有canfd适配器&#xff0c;今天我们来制作一个上位机程序来进行报文收发。 上位机还是用以前写好的&#xff0c;只是更改下dll文件。 项目链接器&#xff0c;输入&#xff0c;附加依赖项中增加winusb.lib winusb初始化&#xff1a;#incl…...

【时间之外】IT人求职和创业应知【71】-专利费

目录 2025 ICT产业趋势年会召开&#xff0c;2024年度ICT十大新闻重磅揭晓 海纳致远数字科技申请定制化插件驱动的数据分析专利 阿波罗智联取得语音数据的处理方法、装置、设备和存储介质专利 心勿贪&#xff0c;贵知足。 感谢所有打开这个页面的朋友。人生不如意&#xff0…...

springboot vue 会员营销系统

springboot vue 会员营销系统介绍 演示地址&#xff1a; 开源版本&#xff1a;http://8.146.211.120:8083/ 完整版本&#xff1a;http://8.146.211.120:8086/ 移动端 http://8.146.211.120:8087/ 简介 欢迎使用springboot vue会员营销系统。本项目包含会员储值卡、套餐卡、计…...

Kafka快速扫描

Architecture 系统间解耦&#xff0c;异步通信&#xff0c;削峰填谷 Topic 消息主题&#xff0c;用于存储消息 Partition 分区&#xff0c;通过扩大分区&#xff0c;可以提高存储量 Broker 部署Kafka服务的设备 Leader kafka主分区 Follwer kafka从分区 高性能之道&#xff1a…...

scala基础学习(数据类型)-字符串

文章目录 scala中的字符串引号单引号双引号三引号 常用内置函数length 获取字符串长度charAt 字符串元素访问substring 获取字串indexOf 获取字串位置replace 字符串替换toLowerCase,toUpperCase 字符串大小写转换trim 去除首位空白符split 字符串切割以及查看startsWith,endsW…...

网络架构与IP技术:4K/IP演播室制作的关键支撑

随着科技的不断发展&#xff0c;广播电视行业也在不断迭代更新&#xff0c;其中4K/IP演播室技术的应用成了一个引人注目的焦点。4K超高清技术和IP网络技术的结合&#xff0c;不仅提升了节目制作的画质和效果&#xff0c;还为节目制作带来了更高的效率和灵活性。那么4K超高清技术…...

如何优雅的关闭GoWeb服务器

以下内容均为Let’s Go Further内容节选以及作者本人理解。 这里创建了一个后台进程用于捕获关闭信号&#xff0c;在后台进程中&#xff0c;主要内容为&#xff1a; 创建一个缓冲通道 quit使用signal.Notify函数监听并捕获关机信号SIGINT,SIGTERM&#xff0c;在捕获关机信号后…...

Python爬虫(5) --爬取网页视频

文章目录 爬虫爬取视频指定url发送请求UA伪装请求页面 获取想要的数据解析定位定位音视频位置 存放视频完整代码实现总结 爬虫 Python 爬虫是一种自动化工具&#xff0c;用于从互联网上抓取网页数据并提取有用的信息。Python 因其简洁的语法和丰富的库支持&#xff08;如 requ…...

simulink离散传递函数得到差分方程并用C语言实现

一. 创建连续时间的传递函数 G ( s ) s 2 217 s s 2 384 s 8989 G(s) \frac{s^2217s}{s^2384s8989} G(s)s2384s8989s2217s​ 二. 离散连续时间的传递函数G(s) 2.1 在matlab中用c2d函数双线性变换法离散G(s)&#xff0c; 下面是matlab脚本代码 % 创建连续时间传递函数 …...