Spring MVC 高级框架的核心

news2024/9/22 23:28:38

目录

1. 什么是 Spring MVC

1.1 如何理解 MVC

1.2 Spring MVC 和 MVC 的关系

2. 如何学习 Spring  MVC

2.1 将浏览器和服务器连接起来

2.1.1 @RequestMapping, @GetMapping, @PostMapping 三个注解的区别

2.2 在程序中获取前端传递过来的参数

2.2.1 传递单个参数

2.2.2 传递多个参数

2.2.3 获取对象

2.2.4 获取表单参数

 2.2.4 获取 ajax 传递的普通对象

2.2.5 获取 JSON 对象

2.2.6 上传文件

2.2.7 获取 Cookie

2.2.8 获取 Session

2.2.8 获取 Header

2.2.9 后端参数重命名

2.2.10 获取URL中参数@PathVariable

2.2.11 设置参数必传@RequestParam

2.3 返回数据给前端

 2.3.1 返回静态页面

2.3.2 返回 text/html

 2.3.3 返回 JSON 对象

2.3.4 请求转发和请求重定向【了解】


1. 什么是 Spring MVC

  • Spring MVC就是整个 Spring Framework 中的一个 web 模块
  • 它是基于 Servlet API (HTTP 协议, request, response) 构建的.        

1.1 如何理解 MVC

MVC 的全称为 Model View Controller , 它是一种软件架构模式, 将 web 应用程序分为模型、视图、控制器三部分.

关系图:

>>> 如何理解上图三者之间的关系

假设用户需要买鞋, 发送一个 HTTP 请求, 请求会先来到 Controller 这里, Controller 就是接受前端向后端发送的请求的 , 它是第一站, 就相当于乘坐地铁要先过安检一样. Controller 首先会校验前端的参数是否是安全的, 如果安全, 就继续将请求分发给 Model, 广义上来说, Model 分为业务模型和数据模型, 请求来到 Model 这里时, 就会组合数据, 查询与鞋子相关的所有物品, 再把这些物品相关的数据返回给 Controller, 此时 Controller 拿到的只是一些数据, 用户看不懂, 所以需要再分发给 View , 然后再结合前端页面进行渲染, 最后把有动态数据的页面通过响应返回给用户.此时用户得到的就是一个包含了鞋子的页面了. 此时用户的请求就得到了完整的响应了. <<<

当然上图所示的 MVC 是最初的一个设计, 由于 Spring MVC 是和 Spring 一块诞生的, Spring 诞生的时候, 那时候还没有前后端分离的概念, 所以那时候的程序员是啥都要去做的, 前后端是融在一块的. 这个模型在当时来说是没有问题的, 但是放在今天来说已经不适用了. 不过 Spring MVC  它也在演化, 也在更新迭代, 只是名字还叫做 MVC, 对于 Java 程序猿来说, 只做后端的事情, Spring MVC 依然是一个 Web 框架, 只要是 Web 框架, 就可以实现 HTTP 响应, 只不过现在不需要再做数据渲染的事了. 只管把数据返回给前端就行了, 前端自己来处理.

1.2 Spring MVC 和 MVC 的关系

Spring MVC 和 MVC 的关系就和 IoC 和 DI 的关系一样, MVC 是一种思想, 而 Spring MVC 是一种具体的实现, 简单来说就是 Spring MVC 实现了 MVC.

2. 如何学习 Spring  MVC

学习 Spring MVC 只学三个东西:

  • 将浏览器和服务器连接起来
  • 在程序中获取前端传递过来的参数
  • 执行了相应业务逻辑后, 把执行结果返回给用户

2.1 将浏览器和服务器连接起来

我们连接用户和 Java 程序之前, 先要创建一个 Spring MVC 项目, 而 SpringMVC 项目就是基于 Spring MVC 项目本身是基于 Spring Boot 项目的 (前面的博客有详细讲解 - 创建 Spring Boot 项目)

此处我们只需要在创建的时候多添加一个 Spring Web 框架即可:

 Spring MVC 项目创建好了之后, 就可以进行编写代码了:

【代码示例】

@Controller  // 加载并注册类
@ResponseBody // 当前类返回的是非静态页面
@RequestMapping("/web") // 使用 "/web" 可以访问到当前类 (可省略)
public class WebController {
    @RequestMapping("/hello") // 使用 "/web" + "/hello" 可以访问到当前方法
    public String hello() {
        return "hello Spring MVC~";
    }
}

当我们写出这样一个代码的时候, 浏览器通过 http://127.0.0.1:8080/web/hello 的时候就可以映射到我们程序中的 hello() 方法.

  • @Controller :加上@Controller 注解是为了让 spring MVC 项目加载类,  加载类的时候, 才可以调用对应的 hello() 方法. 如果不加 @Controller 注解, 就不能正确访问到本地程序
  • @RequestMapping : 该注解既可以修饰方法, 也可以修饰类. 当它指修饰方法的时候, 只需要通过方法的路由就可以映射到对应的方法; 当修饰类和方法时, 就需要通过类的路由 + 方法的路由一起才能映射到对应的方法. 
  • @ResponseBody :  该注解表示当前类返回的是非静态页面, 如果不加该注解,                    访问方法时就会报错.

【注意事项】

1. @Controller 注解不能被 @Sevice, @Component 等其他类注解替代, 如果换成其他类注解, 访问时就会报错. 这样设计的原因或许就是防止滥用.

2. @RequestMapping 注解可以只给方法加,但不能只给类加.

3. 当我们返回的是静态页面的时候, 可以不加 @RequestBody 注解.

4. @RequestBody 注解 + @Controller 注解 = @RestController 注解, 可以替换.

2.1.1 @RequestMapping, @GetMapping, @PostMapping 三个注解的区别

前边代码使用的 @RequestMapping 注解, 可以正确访问到本地程序的方法, 且在浏览器通过 url 映射到本地程序本身就是 Get 请求, 那我们来看看 POST 请求是否也能正常访问到程序. 

通过 postman 构造了一个 POST 请求访问时, 可以看见输出我们想要的结果了 , 由此证明 2.6.13 版本后的 @RequestMapping 注解是既支持 GET 请求又支持 POST 请求的.

当你的程序想要只支持 GET 请求或者只支持 POST 请求的时候, 就可以使用 @GetMapping 和 @PostMapping 注解, 这俩注解和 @RequestMapping 是类似的用法, 使用相应的请求类型, 是能够正确映射到本地程序的.

【处理 Get 请求】

// 写法一(都适用)
@RequestMapping("/hello")

// 写法二
@RequestMapping(value="/hello", method=RequestMethod.GET)

// 写法三
@GetMapping("/hello")

【处理 Post 请求】

// 写法一
@RequestMapping(value = "/hello",method = RequestMethod.POST)

// 写法二
@PostMapping("/hello")

2.2 在程序中获取前端传递过来的参数

参数请求的类型无非就三种:

  • URL 传参(人为的)
  • ajax 传参
  • form 表单传参

2.2.1 传递单个参数

第一种获取方式(了解): 

URL 传参 :   http://127.0.0.1:8080/web/hello?name=zhangsan

1. 通过 Servlet 中的 request 方式获取, Spring MVC 是基于 Servlet API 的, 它内置了 HttpServletRequest, HttpServletResponse 对象, 只不过在 Spring MVC 中默认隐藏了这两个参数.

2.这是在学习 Servlet 的时候用的方法, 它还是比较麻烦的, 并且它拿到的参数永远是 String 类型的, 如果传递过来的参数是 int 类型的, 就需要强转,如果前端没传这个参数, 强转就会有空指针的问题.所以这种方式既麻烦, 又不安全.

第二种获取方式:

URL 传参: http://127.0.0.1:8080/web/get1?age=11

这种方式来获取前端传递过来的参数, 看起来就简单很多了, 这才是 Spring MVC 推荐获取参数的方法.

1. 这种写法获取 int 类型的参数时, 建议使用包装类, 如果前端不传递参数, 就会报错.

2. 前端传递过来的参数名字一定要和方法中的变量名要相同, 否则就获取不到.

2.2.2 传递多个参数

http://127.0.0.1:8080/web/get1/name=zhangsan&age=11

 浏览器访问结果: 

1. 前端传递多个参数, 后端可以不按顺序接收参数, 只要变量名对上了就可以. 获取参数的结果和参数名有关, 和顺序无关.

如果前端传递过来的参数不止两三个, 假设有一百个怎么办. 这时候就可以封装成对象来接受了.

2.2.3 获取对象

 使用 postman 传递参数.

1. 当前端传递成百上千个参数的时候, 我们就不再使用接收多个变量的方式了, 而是直接封装成对象来接收, 此时 Spring MVC 就会去这个实体类里解析它所有的属性, 然后调用属性的 setter 方法, 将传递过来的值根据 key 值设置进去.

2. 当某一天, 前端又突然加了几个参数时, 我们的方法是不需要做出改变的, 只需要给实体类 User 中扩充属性即可.(参数名要保证一致!!!)

3. 参数名是大小写敏感的, 如果大小写不一样, 依然获取不到参数. 建议全部使用小写, 不要使用小驼峰.

2.2.4 获取表单参数

前端代码:

 

 后端代码:

浏览器访问:  http://127.0.0.1:8080/login.html

输入姓名, 密码提交后, 显示运行结果:

form 表单传递参数时, 如果参数很多, 也可以使用获取对象的方式来接收, 代码的写法和前面是一样的.

 2.2.4 获取 ajax 传递的普通对象

前端通过 ajax 传参:

 后端代码:

>>> 当后端返回 map 类型的时候, Spring MVC 会自动识别键值对格式并帮我们转成 JSON 格式返回给前端.

打开 fiddler 抓包查看 Content-Type:

 >>> 前端传递过来的参数不是 JSON 对象, 只是简单的对象, 抓包查看 Content-Type:

2.2.5 获取 JSON 对象

后端代码: (@RequestBody 神奇注解)

 前端通过 postman 构造参数:

 执行结果:

>>> 此时再抓包查看请求中的 Content-Type:

此时请求的数据类型已经不再是 form-urlencoded, 而是变成了真正的 JSON 格式 的类型了.  body 中的数据格式也随之而变了.

1. 当前端传递过来 JSON 格式的数据时, 后端如果还使用前面的 "接收多个参数" 的形式来接收, 又或者是通过 "接收普通对象" 的方式来接收, 此时就接收不到数据了, 此时通过 postman 发送请求时, 响应里的键对应的 value 值就都为 null 了.

2. 接收 JSON 格式的数据时, 后端需要使用 @RequestBody 注解来实现, @RequestBody 注解就可以从 body 中拿到 JSON 格式的数据. 并且接收 JSON 对象时, 只能是以对象的形式来接收, 不能写成多个参数的形式.

3. @requestBody 注解只能接收 JSON 对象, 不能用于接收普通对象, 不能混着用, 需要配套使用.

2.2.6 上传文件

后端代码:

 前端通过 postman 构造:

1. 上传文件的时候, 我们使用 @RequestPart 注解来实现, 注解中的参数对应 postman 中的 key.

2. 保存文件的时候, 此处最好写绝对路径, 一般都是写绝对路径, 写相对路径的时候, 我这里是代码不会报错, 但是在路径下没有找到对应的图片.

2.2.7 获取 Cookie

【传统方式】Servlet 获取 Cookie

 通过开发者工具构造 Cookie :

浏览器访问: http://127.0.0.1:8080/web/getck

 【Spring MVC 中的方式】@CookieValue

获取一个 Cookie:

 获取多个 Cookie:

1. Spring MVC 中可以使用 @CookieValue  注解的方式实现更简单的获取 Cookie, 而 Servlet 时代的方式只有一个 getCookies() 方法, 如果你想要获取的 Cookie 有很多, 还是可以用原来的方式.

2. 在开发者工具里伪造的 Cookie 的默认级别是浏览器级别, 是存在内存中的, 关闭浏览器后再次访问就访问不到了.

2.2.8 获取 Session

在获取 session 之前, 先存储 session:

以前获取 Session 的方式:

 【Spring MVC 的方式】@SessionAttribute

获取 Session 时, 需要先设置 session , 否则就会报错, 因为@SessionAttribute 注解中的默认的 required(是否必须) 是为 true 的. 也可以手动将其改为 false, 这样先获取 getSession , 就不会报错, 只会显示 name: null.

 【玩个花活】

由于 Session 是依赖于 Cookie 的, 如果我们篡改了 SessionId, 浏览器是否还能访问到 ?

此时, 我们在设置 session 的情况下再去获取 session, 就会显示 null 了.

【理解 Cookie 和 Session 机制】

1. 当客户端访问服务器时, 浏览器会默认将当前网站的所有 Cookie 发送给后端, 原因就是因为 HTTP 是一个无状态的协议, 它不知道你是张三, 还是李四. 

2. 另外 sessionId 通过 Cookie 存储在客户端也是有原因的, 如果直接在 URL 中传输, 就很容易被篡改, 就像上面我伪造 sessionId 之后, 再次获取 session 就获取不到了.  而通过 Cookie 存储 sessionId, 想要篡改的成本就会很高, sessionId 会有过期时间, 其次, 用户重新登录该网站时, sessionId 会不断改变.

了解更多 Cookie ,Session 机制 : https://blog.csdn.net/xaiobit_hl/article/details/127487411

2.2.8 获取 Header

传统的方式就不啰嗦了, 直接演示 Spring MVC 的写法:

 浏览器访问: http://127.0.0.1:8080/web/get_head

2.2.9 后端参数重命名

有时候, 前端传过来的参数, 不符合后端的命名规则时, 这时候就要用到后端参数重命名了.

例如前端传递过来一个时间变量 t,  后端就会认为是 TM 什么魔法字符, 对于后端人员来说, 就需要使用 time 来接收, 否则代码 review 过不了. >>> 怎么解决?

1. 和前端人员协商 (难度大)

对于大公司来说, 前端人员和后端人员是分开干活的, 说先你找不找得到他是一个问题, 其次你找到他了, 他听不听你的又是一个问题. 又或者他有他的一套方法论, 他传一个 t , 不传一个 time, 我一个接口能节省这么多带宽, 如果有成千上万个人的话,  他可能会从节省网络带宽, 从性能等方面来说服你, 这时候各有各的说法, 问题就很难得到解决.

2. 使用 @ReuqestParam 注解来进行后端参数重命名

当前端不好配合, 我们拿他没招时, 就可以使用后端参数重命名来解决.

 浏览器访问: http://127.0.0.1:8080/web/rename?t=2022-12-6%2014:48:21

【注意】当我们使用了后端参数重命名时, 前端如果此时又觉得你的说法是对的, 将 t 改回 time 时, 那么此时再次访问, 就访问不到了. 所以一旦使用了后端参数重命名, 前端传递的参数就要和 @RequestParam() 注解中的变量保持一致. 当然也可以像前面那样将 required 改成 false.这样即使变量名对不上, 也不会报错.

2.2.10 获取URL中参数@PathVariable

此处讲到的 URL 中传参和普通的 URL 传参还不太一样

  • 普通 URL 传参: http://127.0.0.1:8080/web/hello?username=zhangsan&age=12
  • 特殊的 URL 传参 :  http://127.0.0.1:8080/web/hello/zhangsan/12

>>>为什么会有这样的 URL 传参呢, 其实就是为了提高在搜索引擎中的权重.

就好比我们在搜索引擎中搜索世界杯, 假设两家公司的规模都是差不多大的, 为什么搜出来的结果, 排名一个在前, 一个在后? 下面这两种写法就会引起这种区别: 

排在前面的公司的 URL : http://127.0.0.1:8080/世界杯/abc?name=cdef

排在后面的公司的 URL : http://127.0.0.1:8080/web/hello?param=世界杯

第一个 URL 中世界杯这个关键词出现在主 URL 中, 而第二个 URL 中世界杯关键词出现在 URL 后面的参数中, 而主 URL 的搜索引擎权重就会比参数中的搜索引擎权重高.

 Spring MVC 接收 URL 中参数的代码:

1. 获取 URL 中传递过来的特殊参数时, 需要两步, 首先 @RequestMapping 注解中需要使用花括号在路由后面跟上相应的参数, 其次就是需要使用 @PathVariable 注解.

2. 此处的 @PathVariable 注解也可以根据需求进行参数重命名. 

3. 特殊的 URL参数中不能出现带 '/' 的参数, 因为这些特殊的 URL 参数是通过 / 来区分层级的, 如果出现类似 'name/age' 这样一个完整的参数时, 那么程序访问时就会报错.

2.2.11 设置参数必传@RequestParam

其实前面讲到过的设置 required 参数就是来控制参数是否必传. 

如果我们的实际业务前端的参数是⼀个非必传的参数,我们可以通过设置 @RequestParam 中的 required=false 来避免不传递时报错, 默认是 required=true.

2.3 返回数据给前端

 2.3.1 返回静态页面

在 static  目录下新建一个 xxx.html 文件:

index.html:

Controller 代码:

2.3.2 返回 text/html

加上 @RestController 注解或者 @Controller + @ResponseBody, 返回String 等基本类型.

 2.3.3 返回 JSON 对象

当我们的返回类型为集合或者对象的时候, Spring MVC 会自动帮我们转成 JSON 格式的对象, 返回给前端.

浏览器访问 URL: http://127.0.0.1:8080/index

使用 fiddler 抓包查看 Content-Type.

2.3.4 请求转发和请求重定向【了解】

  • forward: 请求转发
  • redirect: 请求重定向

【举例说明】请求转发和请求重定向

假如 a 页面不用了, 换了新页面, 对于老用户, 还记住了原来的 a 页面, 于是就会对内帮助老用户请求转发到新页面, 对外(新用户), 就会显示访问失败,告诉浏览器你请求的页面不在我这, 你去其他网站请求.

【区别】forward VS redirect

1. 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发。
2. 请求重定向地址发生变化,请求转发地址不发生变化。
3. 请求重定向与直接访问新地址效果⼀致,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问。

本篇文章就到这里了, 谢谢观看!! 

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

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

相关文章

CSS 实现音频loding动画

前言 &#x1f44f;实现一个音频loading动画还蛮有趣的&#xff0c;速速来Get吧~ &#x1f947;文末分享源代码。记得点赞关注收藏&#xff01; 1.实现效果 2.实现步骤 定义css变量&#xff1a;父容器高度为–h&#xff0c;可以动态设置loading的高度 :root {--h: 80px;}父…

遗传算法在机器人路径规划中的应用研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 机器人运动规划是移动机器人导航的核心技术之一。40多年来,运动规划技术发展迅速,涌现出了许多规划算法,但因为环境描述方式差异…

JavaScript -- 数组及对象解构赋值方法总结

文章目录1 数组解构赋值1.1 保留默认值1.2 接受剩余的所有参数1.3 对函数执行结果解构1.4 交换两个变量的值1.5 二维数组结构2 对象的解构2.1 声明对象同时解构对象2.2 先声明再解构2.3 解构不存在的属性2.4 设置解构别名2.5 设置解构默认值1 数组解构赋值 案例&#xff1a;将…

红队隧道应用篇之Netsh端口转发

简介 netsh是从Windows 2000开始就有的一个用于配置网络设备的命令行工具 其中netsh interface portproxy是一个配置网络代理的命令, 可以配置ipv4或ipv6的端口转发代理以及双向端口转发代理 学习隧道应用前必须了解的知识:https://blog.csdn.net/xf555er/article/details/1…

LeetCode刷题复盘笔记—一文搞懂完全背包之279. 完全平方数问题(动态规划系列第十五篇)

今日主要总结一下动态规划完全背包的一道题目&#xff0c;279. 完全平方数 题目&#xff1a;279. 完全平方数 Leetcode题目地址 题目描述&#xff1a; 给你一个整数 n &#xff0c;返回 和为 n 的完全平方数的最少数量 。 完全平方数 是一个整数&#xff0c;其值等于另一个整…

技术开发93

技术开发93 业务内容&#xff1a; . 马达零部件 . 汽车零部件 . 音响用零部件 . 农用机零部件 . 建筑模具 公司简介&#xff1a; 资本金&#xff1a;2000万日元&#xff08;约120万元人民币&#xff09; 员工数&#xff1a;17名 成立时间&#xff1a;1923年4月 资格认…

Linux文件及目录管理操作

Linux文件及目录管理实验目的及要求1.了解Linux文件与目录的访问权限2.熟悉Linux文件与目录的打包和压缩3.掌握Linux文件与目录的相关管理操作实验原理实验步骤对文件管理和压缩归档进行了解&#xff0c;具体步骤如下&#xff1a;1.用mkdir命令在"/root"目录下创建一…

[附源码]Python计算机毕业设计Django线上社区管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

C#语言入门详解 第十七讲 (字段、属性、索引器、常量)

C#语言入门详解 第十七讲 &#xff08;字段、属性、索引器、常量&#xff09; 在C#语言中&#xff0c;类&#xff08;或结构体&#xff09;包含以下成员&#xff1a; 什么是字段 字段&#xff08;field&#xff09;是一种表示与对象或类型&#xff08;类与结构体&#xff0…

【传输层】概述、复用分用、UDP详解、UDP校验

文章目录传输层概述----为应用层服务TCP靠谱--大文件、时延大 与UDP不可靠--小文件、时延小传输层的寻址与端口------复用---应用层所有进程通过传输层再传输到网络层----------分用---------传输层从网络层收到数据后交付给指定应用程序套接字------Socket---IP&#xff1a;端…

足球冷知识:球队之间比分相同,怎么排名?

在足球比赛的小组赛中&#xff0c;往往会有胜、平、负三种结局&#xff0c;球队胜一场得三分、平一场得一分、输一场不得分。 如果球队积分相同&#xff0c;排名的时候&#xff0c;还会通过净胜球&#xff08;就是进球数减丢球数&#xff09;、相互交战的成绩、总进球数、球队累…

2023年天津美术学院专升本专业课报名缴费时间及考试安排

天津美术学院2023 年高职升本专业考试报名考试公告 一、报名时间 2022 年 12 月 9 日 10:00 至 12 月 12 日 17:00&#xff08;逾期不予补报&#xff0c;考生也不得再修改报名信息&#xff09; 注&#xff1a;每日 23:00 至次日 7:00 是报名系统维护时间&#xff0c;届时报名相…

搭建Python虚拟环境

搭建Python虚拟环境虚拟环境概述安装虚拟环境Windows环境下Linux环境下创建虚拟环境使用虚拟环境虚拟机环境下安装包PyCharm中使用虚拟环境虚拟环境 概述 为什么需要搭建Python的虚拟环境&#xff1f; 正常情况下&#xff0c;在一台电脑上, 想开发多个不同的项目, 需要用到同…

【GNN基础学习】图模块基本定义 || 图的邻接矩阵 || GNN中常见任务有哪些? || GNN消息传递方法 || 多层GCN有什么作用?

声明:仅学习使用~ 目录 一、图模块基本定义二、图的 邻接矩阵三、GNN中常见任务:点级别 任务、边级别 任务、图级别 任务。四、消息传递方法五、多层GCN的作用一、图模块基本定义 点、边、图。 对点的特征、边的特征、图的特征 等都要做重构。 借助于 图 这一结构,对事物…

39. 组合总和

39. 组合总和 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限制重…

C++并发编程

目录一、并发编程相关的基础概念1、操作系统&#xff08;Linux&#xff09;2、任务和通信3、多进程和多线程4、C中的多线程发展史二、pthread线程使用讲解和实战1、pthread基本使用2、线程的分离3、线程属性4、关于线程的几个值得注意的点三、线程的同步之互斥锁、读写锁、非阻…

MySQL 数据库主从复制

参考视频教程: https://www.bilibili.com/video/BV13a411q753?p172 参考博客: https://blog.csdn.net/main_Scanner01/article/details/124259050 1. 介绍 1.1 要点 主库(master): 负责增删改 从库(slave) : 负责查询 主从库关系: 一对多 1.2 步骤 ● master将改变记录到_…

宝塔部署node项目

宝塔linux&#xff1a;是一个linux运维面板&#xff0c;方便管理服务器。 安装服务器默认宝塔面板 使用步骤 到防火墙页面开启8888端口&#xff1a; 点击进入防火墙远程登录服务器。复制面板安全入口查询命令&#xff0c;获取面板安全入口。sudo /etc/init.d/bt default | gr…

快速入门Docker

目录 Docker简介 Dokcer环境配置 Docker HelloWorld运行原理解析 阿里云镜像仓库 常用命令 基本命令 镜像命令 容器命令 Docker简介 Docker 是基于Go语言实现的一个开源项目&#xff0c;通过对应组建的封装&#xff0c;分发&#xff0c;部署&#xff0c;运行等生命周期的管…

如何创建多语言WordPress网站[专家建议]

如果您想有效地接触广泛的国际受众&#xff0c;那么您应该考虑制作一个多语言WordPress网站。您知道吗&#xff0c;61.1% 的网站是英文的&#xff0c;但全球只有 25.9% 的用户实际上可以在线使用这种语言。 多语言功能意味着创建站点的两个或多个语言实例&#xff0c;在大多数…