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

SpringMVC-RESTful架构风格

目录

RESTful架构风格

1、RESTful概述

2、RESTful的六大原则

3、RESTful的实现

4、HiddenHttpMethodFilter

RESTful风格的CRUD

1、环境搭建

2、功能需求

3、功能:访问首页

4、功能:查询所有数据

5、功能:删除一条数据

6、功能:添加一条数据

SpringMVC处理静态资源

1、tomcat自己的web.xml

2、关于DefaultServlet


RESTful架构风格

1、RESTful概述

什么是REST

REST:Representational State Transfer,表述层资源状态转移。(表现层:视图+控制器)

它是在2000年,由Http协议的主要编写者Roy Fielding提出的,他觉得所有人都在胡乱使用Http,违背了他的设计思想。他就站出来,规定了一个web应用的,功能强、性能好、适宜通信的架构。这就是REST,它指的是一组架构约束条件和原则

如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构风格

REST本身并没有创造新的技术、组件或服务,简单来说,REST的目的就是设立规定,促使人们更好地使用Http协议。理论上REST架构风格并不是绑定在HTTP上,只不过目前HTTP是唯一与REST相关的实例。

不遵守REST规范,也能编写出web应用,这就类似于不使用设计模式也能开发程序一样。但基本都在使用。

资源

项目最终会部署到服务器上,被访问。

服务器中,万物皆资源。每个资源都是服务器上的一个可命名的抽象概念。

与面向对象的设计理念类似,资源是以名词为核心来组织的,而不是方法

资源可以是一个文件,一张数据库表,或是更抽象的概念,比如一个视图,一个参数之类。

一个资源可以由一个或多个URI来标识。

URI

URI既是资源的名称,也是资源在web上的地址。客户端通过URI与资源进行交互。

REST 是面向资源的,这个概念非常重要,而资源是通过 URI 进行暴露。 URI 的设计只要负责把资源通过合理方式暴露出来就可以了。对资源的操作与它无关,操作是通过 HTTP动词来体现,所以REST 通过 URI 暴露资源时,会强调不要在 URI 中出现动词。

资源的状态表述

资源的表述,指某个资源在某个特定时刻的状态的描述。这种状态,可以在客户端-服务器之间交换。

资源的表述可以有多种格式,例如HTML、XML、JSON、纯文本、图片、音视频等。

统一资源在请求-响应方向的表述,通常使用不同的格式

资源状态表述的转移

状态转移,指在客户端-服务器端之间转移 资源状态的表述。

通过转义和操作资源的表述,来实现间接操作资源的目的。

2、RESTful的六大原则

Roy Fielding在提出RESTful时,也阐述了REST架构的6大原则。他希望所有web应用都符合这六个特征,相当于是web应用的设计原则

如果某个服务违反了其他任意一项准则,严格意义上不能称之为RESTful风格。

1、C-S架构

数据的存储在Server端,Client端只需使用就行。两端彻底分离的好处使client端代码的可移植性变强,Server端的拓展性变强。两端单独开发,互不干扰。

2、无状态

http请求本身就是无状态的,基于C-S架构,客户端的每一次请求都必须带有充分的信息,才能够让服务端识别。

服务端能够根据请求的各种参数,无需保存客户端的状态,将响应正确返回给客户端。

无状态的好处:无状态的特征大大提高的服务端的健壮性和可拓展性。

无状态的坏处:每次请求必须携带身份状态信息,造成传输数据的冗余。但影响很细微,可以忽略

3、统一资源接口

这个才是REST架构的核心,统一的接口对于RESTful服务非常重要。客户端只需要关注实现接口就可以,接口的可读性加强,使用人员方便调用。

4、一致的数据格式

5、系统分层

客户端通常无法表明自己是直接还是间接与端服务器进行连接,分层时同样要考虑安全策略。

6、可缓存

管理得当的缓存会部分地或完全地除去客户端和服务端之间的交互,进一步改善性能和延展性。

3、RESTful的实现

REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。

具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。 它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源

操作传统方式REST风格
查询操作getUserById?id=1user/1 --> get请求方式
保存操作saveUseruser --> post请求方式
删除操作deleteUser?id=1user/1 --> delete请求方式
更新操作updateUseruser --> put请求方式

4、HiddenHttpMethodFilter

由于浏览器只支持发送get和post方式的请求,那么该如何发送put和delete请求呢?

SpringMVC 提供了 HiddenHttpMethodFilter 帮助我们将 POST 请求转换为 DELETE 或 PUT 请求

HiddenHttpMethodFilter如何使用?

HiddenHttpMethodFilter 处理put和delete请求的条件:

  • 当前请求的请求方式必须为post
  • 当前请求必须传输请求参数_method

满足以上条件,HiddenHttpMethodFilter 过滤器就会将当前请求的请求方式转换为请求参数_method的值,因此请求参数_method的值才是最终的请求方式

在web.xml中注册HiddenHttpMethodFilter

<filter><filter-name>HiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping><filter-name>HiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

注意,在web.xml中注册时,必须先注册CharacterEncodingFilter,再注册HiddenHttpMethodFilter

即先注册字符编码过滤器,再注册Http隐藏方法过滤器

HiddenHttpMethodFilter需要获取请求方式,也属于请求参数,那就必须在设置好字符编码之后再去获取。

在前端页面中,使用隐藏域传递请求参数_method

<form th:action="@{/user}" method="post">修改用户信息<input type="hidden" name="_method" value="put"/>用户名:<input type="test" name="username"/>密码:<input type="password" name="password"/><input type="submit" value="提交">
</form><br>

此时,点击提交按钮,发出的就是一个put类型的请求

RESTful风格的CRUD

1、环境搭建

创建实体类

public class Employee {private Integer id;private String lastName;private String email;//1 male, 0 femaleprivate Integer gender;...
}

创建DAO,使用map集合模拟数据库资源

@Repository
public class EmployeeDAO {private static Map<Integer, Employee> employees = null;static {employees = new HashMap<Integer, Employee>();employees.put(1001, new Employee(1001, "E-AA", "aa@163.com", 1));employees.put(1002, new Employee(1002, "E-BB", "bb@163.com", 1));employees.put(1003, new Employee(1003, "E-CC", "cc@163.com", 0));employees.put(1004, new Employee(1004, "E-DD", "dd@163.com", 0));employees.put(1005, new Employee(1005, "E-EE", "ee@163.com", 1));}private static Integer initId = 1006;public void save(Employee employee) {if (employee.getId() == null) {employee.setId(initId++);}employees.put(employee.getId(), employee);}public Collection<Employee> getAll() {return employees.values();}public Employee get(Integer id) {return employees.get(id);}public void delete(Integer id) {employees.remove(id);}
}

@Repository 持久层组件标记

创建Controlle

public class EmployeeController {private EmployeeDAO employeeDAO;}

创建私有成员变量DAO,后续使用依赖注入

2、功能需求

功能URL 地址请求方式
访问首页/GET
查询全部数据/employeeGET
删除/employee/2DELETE
跳转到添加数据页面/toAddGET
执行保存/employeePOST
跳转到更新数据页面/employee/2GET
执行更新/employeePUT

使用RESTful风格,对相同资源的不同操作,请求地址相同,不同请求方式对应不同的操作。

3、功能:访问首页

由于只是页面跳转的功能,可以使用view-controller标签配置。

<mvc:view-controller path="/" view-name="index"/><mvc:annotation-driven />

首页的前端页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>Title</title></head><body><h3>RESTful风格的员工CRUD系统</h3><a th:href="@{/employee}">查看所有员工信息</a></body>
</html>

4、功能:查询所有数据

分析

不使用ajax异步访问,就只能先获取数据,再转发到其他页面来展示。

传参流程

首页点击超链接,被Spring前端控制器拦截,匹配到控制器方法;

控制器方法中,执行DAO的相应方法,将结果存入request域对象中,并转发到结果页面;

结果页面上,使用视图模板引擎获取域对象中的相关数据,并展示。

控制器方法

@GetMapping("/employee")
public String getEmployeeList(Model model){Collection<Employee> employeeList = employeeDAO.getAll();model.addAttribute("employeeList", employeeList);return "employee_list";
}

前端页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>员工信息</title></head><body><table border="1" cellspacing="0" cellpadding="0" style="text-align: center"><tr><th colspan="5">全部员工信息</th></tr><tr><th>id</th><th>lastName</th><th>email</th><th>gender</th><th>options</th></tr><tr th:each="employee : ${employeeList}"><td th:text="${employee.id}"></td><td th:text="${employee.lastName}"></td><td th:text="${employee.email}"></td><td th:text="${employee.gender}"></td><td><a href="">Delete</a><a href="">Update</a></td></tr></table></body>
</html>

效果

5、功能:删除一条数据

分析

  1. 删除操作,需要使用DELETE请求方式,则需要在Delete超链接上,绑定一个post表单的提交事件,该表单使用隐藏域,设置_method为DELETE

  2. 点击删除超链接,需要传递该行的员工id,动态获取数据并拼接。拼接有两种方法

 <!--方法一--><a th:href="@{/employee/}+${employee.id}">Delete</a><!--方法二--><a th:href="@{'/employee/'+${employee.id}}">Delete</a>

步骤

  1. 创建发送delete请求方式的form表单
  2. 给delete超链接绑定事件
  3. 引入vue.js
  4. 给delete超链接绑定单击事件
  5. 通过vue处理单击事件
  6. 编写控制器方法,获取前端请求携带的id信息,调用DAO,根据id删除该数据

创建发送delete请求方式的form表单

<form id="deleteForm" method="post"><input type="hidden" name="_method" value="delete"/>
</form>

引入vue.js

<script type="text/javascript" th:src="@{/static/js/vue.js}"></script>

需要在webapp下创建static/js目录,放入vue.js

给delete超链接绑定单击事件

<a @click="deleteEmployee" th:href="@{'/employee/'+${employee.id}}">Delete</a>

这里做了两件事情:

  1. 给超链接绑定了单击事件,方法名称为deleteEmployee
  2. 拼接了请求路径,用RESTful风格传参,请求路径包含该行的id值

通过vue处理单击事件

<script type="text/javascript">var vue = new Vue({el:"#dataTable",methods:{deleteEmployee:function (event){//获取deleteForm这个表单元素var deleteForm = document.getElementById("deleteForm");//获取当前触发事件的href属性,即employee/1001deleteForm.action = event.target.href;//提交表单deleteForm.submit();//取消默认行为,阻止submit跳转页面event.preventDefault();}}});
</script>

注意

如果不做配置,vue.js无法被获取到,单击事件也就不起作用。

因为SpringMVC默认无法访问静态资源。vue.js会被前端控制器 / 拦截到,显然没有它对应的控制器方法,返回了404

需要在SpringMVC配置文件中,引入默认的servlet,开放对静态资源的访问

<mvc:default-servlet-handler/>

静态资源在访问时,会先被前端控制器进行处理,如果前端控制器找不到对应的请求映射,就会交给默认的servlet来处理。如果默认的servlet找到了相对应的资源,就访问资源。如果找不到,就返回404。

控制器方法

@DeleteMapping("/employee/{id}")
public String delEmployee(@PathVariable Integer id){employeeDAO.delete(id);return "redirect:/employee";
}

6、功能:添加一条数据

在前端页面,设置添加员工的入口

<th>options(<a th:href="@{/toAdd}">添加员工</a>)</th>

效果

点击“添加员工”,跳转到添加员工的页面。用view-controller实现

<mvc:view-controller path="/toAdd" view-name="employee_add"/>

 编写添加页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>添加员工信息</title></head><body><form th:action="@{/employee}" method="post">lastName:<input type="text" name="lastName"/><br>email:<input type="text" name="email"/><br>gender:<input type="radio" name="gender" value="1"/>男<input type="radio" name="gender" value="0"/>女<br><input type="submit" value="提交"/><input type="reset" value="重置"/></form></body>
</html>

样式

控制器方法

@GetMapping("/employee/{id}")
public String getEmployeeById(@PathVariable Integer id, Model model){//根据id获取员工对象Employee employee = employeeDAO.get(id);//将员工对象存入request域中,用于数据回显model.addAttribute("employee", employee);return "employee_update";
}@PutMapping("/employee")
public String updateEmployee(Employee employee){employeeDAO.save(employee);return "redirect:/employee";
}

 修改的前端页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>更新员工数据</title></head><body><form th:action="@{/employee}" method="post"><input type="hidden" name="_method" value="put"/><input type="hidden" name="id" th:value="${employee.id}"/>lastName:<input type="text" name="lastName" th:value="${employee.lastName}"/><br>email:<input type="text" name="email" th:value="${employee.lastName}"/><br>gender:<input type="radio" name="gender" value="1" th:field="${employee.gender}"/>男<input type="radio" name="gender" value="0" th:field="${employee.gender}"/>女<br><input type="submit" value="提交"/><input type="reset" value="重置"/></form></body>
</html>
  1. 注意这里实现勾选框 回显的方式

th:field="${employee.gender}"可用于单选框或复选框的回显

若单选框的value和employee.gender的值一致,则添加checked="checked"属性

     2. 注意,需要使用隐藏域传递id,达到覆盖原有数据的目的

SpringMVC处理静态资源

传统的web项目中,负责处理静态资源的是“默认的Servlet”

1、tomcat自己的web.xml

存放位置

tomcat目录下的conf目录内。

tomcat的web.xml,和工程中web.xml的关系

tomcat的web.xml文件,是全局配置,作用于部署在tomcat的所有web应用。

web应用中的web.xml,只针对于自身。

如果当前应用内的web.xml配置,与tomcat的web.xml配置产生了冲突,则以web应用的配置为准。

2、关于DefaultServlet

tomcat的web.xml中,注册了DefaultServlet

<servlet><servlet-name>default</servlet-name><servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class><init-param><param-name>debug</param-name><param-value>0</param-value></init-param><init-param><param-name>listings</param-name><param-value>false</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>default</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

DefaultServlet的url-pattern是 / 说明访问所有资源(除了jsp)时,都会进入DefaultServlet。

在SpringMVC中,DefaultServlet和DispacherServlet产生了冲突。冲突时,以当前工程中的配置为准,也就是DispacherServlet。

就是说,所有的请求都会被DispacherServlet处理。

但DispacherServlet处理请求的方式是,将请求地址与控制器方法的映射路径匹配,直到找到相对应的请求映射。但这种方式无法访问静态资源。例如需要访问vue.js资源,而此路径并没有相对应的控制器方法,所以会报404,找不到该资源。

而DefaultServlet可以找到vue.js这个请求的资源。

所以SpringMVC默认不能访问静态资源,必须手动开启对静态资源的访问,在核心配置中进行如下的配置:

<!--开启对静态资源的访问-->
<mvc:default-servlet-handler/>

但此时,所有的请求都将被DefaultServlet处理,则只能访问到静态资源,请求映射将全部失效

所以,还需要配置开启注解驱动的标签

<!--开启mvc注解驱动-->
<mvc:annotation-driven>

同时配置这两个标签,就能实现,请求先被DispacherServlet处理,如果找不到,再被DefaultServlet处理

关于控制台信息

如果不添加日志功能,只有DispacherServlet的处理结果会被输出,而DefaultServlet的结果不会显示。

 

 

相关文章:

SpringMVC-RESTful架构风格

目录 RESTful架构风格 1、RESTful概述 2、RESTful的六大原则 3、RESTful的实现 4、HiddenHttpMethodFilter RESTful风格的CRUD 1、环境搭建 2、功能需求 3、功能&#xff1a;访问首页 4、功能&#xff1a;查询所有数据 5、功能&#xff1a;删除一条数据 6、功能&…...

consistency-starter

使用说明 建议在B端使用,不推荐C端使用 功能 事务提交之后推送MQ a. 当一个程序中有多个MQ需要推送时,可以在事务内任意位置调用发送MQ方法,而不会因为程序报错而导致数据不一致问题.事务提交之后发起子线程执行异步任务程序中灵活指定时间执行子任务 a. 例如:业务要求执行A业…...

【Json】Spring Boot整合Json与Json数组

Spring Boot整合Json与Json数组 文章目录 Spring Boot整合Json与Json数组一&#xff0c;引入依赖二&#xff0c;常见Json数据格式-2.1 Json格式-2.2 数组格式-2.3 Json数组格式 三&#xff0c;在Java中如何使用-3.1 Json格式-3.2 数组格式-3.3 Json数组格式 四&#xff0c;Json…...

Adobe Photoshop 软件下载

Adobe Photoshop&#xff0c;简称“PS”&#xff0c;是由Adobe Systems开发和发行的图像处理软件。Photoshop主要处理以像素所构成的数字图像。 时至今日&#xff0c;Adobe Photoshop 已经成为当今世界上最流行、应用最广泛的图像处理软件。不但设计专业的学生要系统的学习这个…...

[ES6]解构与赋值

[ES6]解构与赋值 解构模型对象属性解构函数参数解构字符串的解构数组解构REST 运算符参与的解构--...数组解构属性解构 解构的赋值 解构赋值是对赋值运算符的扩展。 通过解构&#xff0c;可以更加简单的获取复杂对象的属性 解构模型 解构的源&#xff0c;解构赋值表达式的右…...

2023年3月 青少年软件编程(C语言) 等级考试试卷(五级)

1. 拼点游戏 C和S两位同学一起玩拼点游戏。有一堆白色卡牌和一堆蓝色卡牌&#xff0c;每张卡牌上写了一个整数点数。C随机抽取n张白色卡牌&#xff0c;S随机抽取n张蓝色卡牌&#xff0c;他们进行n回合拼点&#xff0c;每次两人各出一张卡牌&#xff0c;点数大者获得三颗巧克力&…...

Unity之ShaderGraph入门

前言 随着Unity版本的不断升级&#xff0c;URP&#xff08;可编程渲染管线&#xff09;也越来越普及了。不管是从效果还是性能&#xff0c;都是吊打老版的build-in-shader。所以无论如何我们都要开始 拥抱URP&#xff0c;升级Unity的时候到了。 引擎版本 我这里选择了Unity …...

Spring-学习修改尚硅谷最新教程笔记

二、Spring 1、Spring简介 1.1、Spring概述 官网地址&#xff1a;https://spring.io/ Spring 是最受欢迎的企业级 Java 应用程序开发框架&#xff0c;数以百万的来自世界各地的开发人员使用 Spring 框架来创建性能好、易于测试、可重用的代码。 Spring 框架是一个开源的 Jav…...

CPU寄存器的分类与Intel 8086 的eax,ebx,ecx,edx

目录 一、CPU中的寄存器分类 1.用户可见寄存器 2.控制和状态寄存器 一、CPU中的寄存器分类 大致分为两类: 一类属于用户可见寄存器&#xff0c;对这类寄存器编程&#xff0c;以及通过优化使CPU因使用这类寄存器&#xff0c;而减少对主存的访问次数&#xff0c; 另一类属于控…...

如何快速上手Vue框架?

编译软件&#xff1a;IntelliJ IDEA 2019.2.4 x64 运行环境&#xff1a;Google浏览器 Vue框架版本&#xff1a;Vue.js v2.7.14 目录 一. 框架是什么&#xff1f;二. 怎么写一个Vue程序&#xff08;以IDEA举例&#xff09;&#xff1f;三. 什么是声明式渲染?3.1 声明式3.2 渲染…...

Android进阶宝典—App响应时间优化

响应时间&#xff0c;它是用来衡量系统运行效率的一个重要指标。评价一个应用的响应时间&#xff0c;可以从用户感知和系统性能这两个角度来考量。 响应时间的长短&#xff0c;可能影响用户对某个功能、某个应用、乃至某个系统的使用。毕竟如果有选择&#xff0c;没有哪个人会愿…...

100天涨薪4k,从功能测试到自动化测试,我整理的3000字超全学习指南

去年6月份&#xff0c;由于经济压力让我下定决心进阶自动化测试&#xff0c;已经24的我做了3年功能测试&#xff0c;坐标广州薪资定格在8k&#xff0c;可能是生活过的太安逸&#xff0c;觉得8000的工资也够了&#xff0c;但是生活总是多变的&#xff0c;女朋友的突然怀孕&#…...

Pytorch剪枝api测试和结果

Pytorch 官方给出的prune接口 下面是基于prune的接口进行剪枝的方法步骤 1、首先prune接口在 torch.nn.utils.prune中&#xff0c;目前支持的剪枝方法有&#xff1a; RandomUnstructuredL1UnstructuredRandomStructuredLnStructuredCustomFromMask ps&#xff1a;非结构性剪…...

微服务下网关聚合Swagger文档、starter统一配置Swagger

一、starter实现统一配置微服务文档 把Swagger配置中的公共部分抽取出来Swagger与SpringBoot整合中&#xff0c;可能会由于版本问题出现各种问题 1、制作starter 参考&#xff1a; 【SpringBoot】自定义启动器 Starter【保姆级教程】用starter实现Oauth2中资源服务的统一配置用…...

剑指 Offer第二版:机器人的运动范围、正则表达式匹配、表示数值的字符串

剑指 Offer第二版 13. 机器人的运动范围19. 正则表达式匹配20. 表示数值的字符串 13. 机器人的运动范围 题目&#xff1a;地上有一个m行n列的方格&#xff0c;从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动&#xff0c;它每次可以向左、右、上、下移…...

Delaunay三角网生成算法

目录 一、分而治之算法二、三角网生长算法三、逐点插入算法四、约束Delaunay三角网1、方法一1、原始点云2、构网结果 1、方法二1、原始点云2、普通Delaunay3、约束Delaunay Delaunay三角剖分分为直接三角剖分和间接三角剖分。间接三角剖分首先计算为Voronoi图,然后由Voronoi图产…...

hashcode是什么?有什么作用?

文章目录 &#xff08;1&#xff09;hashcode()方法的作用&#xff08;2&#xff09;equals和hashcode的关系&#xff08;3&#xff09;百度百科&#xff08;4&#xff09;小白解释 Java中Object有一个方法&#xff1a; public native int hashcode(); &#xff08;1&#xff0…...

【人体姿态估计】(一)原理介绍

【人体姿态估计】&#xff08;一&#xff09;原理介绍 一、背景 人体姿态估计本质上是一个关键点检测的项目&#xff1b; 关键点检测在生活中的应用十分广泛&#xff0c;包括人脸识别、手势识别&#xff0c;而人体姿态估计则是对身体的关键点进行检测&#xff1b; 本文将介…...

一种新的流:为 Java 加入生成器(Generator)特性

作者&#xff1a;文镭(依来) 前言 这篇文章不是工具推荐&#xff0c;也不是应用案例分享。其主题思想&#xff0c;是介绍一种全新的设计模式。它既拥有抽象的数学美感&#xff0c;仅仅从一个简单接口出发&#xff0c;就能推演出庞大的特性集合&#xff0c;引出许多全新概念。…...

《数据结构C++版》实验一:线性表的顺序存储结构

实验目的 1、实现线性表的顺序存储结构 2、熟悉C++程序的基本结构,掌握程序中的头文件、实现文件和主文件之间的相互关系及各自的作用 3、熟悉顺序表的基本操作方式,掌握顺序表相关操作的具体实现 实验内容 对顺序存储的线性表进行一些基本操作。主要包括: (1)插入:操作…...

ChatGPT的开源平替,终于来了!

最近这段时间&#xff0c;一个号称全球最大ChatGPT开源平替项目Open Assistant引起了大家的注意。 这不最近还登上了GitHub的Trending热榜。 https://github.com/LAION-AI/Open-Assistant 根据官方的介绍&#xff0c;Open Assistant也是一个对话式的大型语言模型项目&#xff…...

Redis基础

Redis6 1. NoSQL数据库简介 1.1 技术发展 技术的分类 1、解决功能性的问题&#xff1a;Java、Jsp、RDBMS、Tomcat、HTML、Linux、JDBC、SVN。 2、解决扩展性的问题&#xff1a;Struts、Spring、SpringMVC、Hibernate、Mybatis。 3、解决性能的问题&#xff1a;NoSQL、Jav…...

为什么重视安全的公司都在用SSL安全证书?

我们今天来讲一讲为什么重视安全的公司都在用SSL证书 SSL证书是什么&#xff1f; SSL安全证书是由权威认证机构颁发的&#xff0c;是CA机构将公钥和相关信息写入一个文件&#xff0c;CA机构用他们的私钥对我们的公钥和相关信息进行签名后&#xff0c;将签名信息也写入这个文件…...

嵌入式QT (使用 Qt Designer 开发)

一、使用 UI 设计器开发程序 1.1、 在 UI 文件添加一个按钮 1.2、在 UI 文件里连接信号与槽 所谓信号即是一个对象发出的信号&#xff0c;槽即是当这个对象发出这个信号时&#xff0c;对应连接的槽就发被执行或者触发。 UI 设计器里信号与槽的连接方法一&#xff1a; 在主窗…...

每日一个小技巧:今天告诉你拍照识别文字的软件有哪些

在现代社会里&#xff0c;手机已经成为了人们生活中必不可少的工具。它的功能众多&#xff0c;比如通讯、上网、拍照以及导航等&#xff0c;为我们的生活带来了许多便利。除此之外&#xff0c;手机还能帮助我们解决一些实际的问题&#xff0c;例如&#xff0c;当你需要识别图片…...

多版本VersionARXDBG

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、一级标题二级标题三级标题四级标题五级标题六级标题总结前言 提示:这里可以添加本文要记录的大概内容: VersionARXDBG,多版本,2023.4.22-4.23两天时间,分别研究了在多版本编译ARXDB…...

# 生成器

生成器 生成器是什么&#xff1f; 生成器&#xff08;generator&#xff09;是一种用来生成数据的对象。它们是普通函数的一种特殊形式&#xff0c;可以用来控制数据的生成过程。 生成器有什么优势&#xff1f; 使用生成器的优势在于它们可以在生成数据的同时控制数据的生成过程…...

Netty 源码解析(上)

序 Netty的影响力以及使用场景就不用多说了&#xff0c; 去年10月份后&#xff0c;就着手研究Netty源码&#xff0c;之前研究过Spring源码&#xff0c;MyBatis源码&#xff0c;java.util.concurrent源码&#xff0c;tomcat源码&#xff0c;发现一个特点&#xff0c;之前的源码都…...

Vue 消息订阅与发布

消息订阅与发布&#xff0c;也可以实现任意组件之间的通信。 订阅者&#xff1a;就相当于是我们&#xff0c;用于接收数据。 发布者&#xff1a;就相当于是媒体&#xff0c;用于传递数据。 安装消息订阅与发布插件&#xff1a; 在原生 JS 中 不太容易实现消息订阅与发布&…...

如何在你的云服务器/云主机上更新并使用最新版本的python(python3.11)

更新并使用最新版本的python3.11 第一步&#xff0c;登录云服务器&#xff0c;并更新系统包 打开您的终端&#xff08;Terminal&#xff09;或使用任意SSH客户端&#xff0c;输入如下命令来登录云主机&#xff1a; ssh 用户名IP地址 在输入密码后&#xff0c;您将成功登录到云…...