【iOS】—— block,KVC,KVO,Category等问题解答

文章目录

  • block
    • 1.block的原理是怎样的?本质是什么?
    • 2.__block的作用是什么?有什么使用注意点?
    • 3.block的属性修饰词为什么是copy?使用block有哪些使用注意?
    • 4.block在修改NSMutableArray,需不需要添加__block?
    • 5.关于block对不同种变量的捕获问题
      • 局部变量:
      • 全局变量
      • 静态全局变量
      • 静态局部变量
    • 6.block捕获变量的原理是什么?
    • 7.__block修饰符的作用
  • KVO
    • 1.iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)
      • 总结
    • 2.如何手动触发KVO?
    • 3.直接修改成员变量会触发KVO么?
  • KVC
    • 1.通过KVC修改属性会触发KVO么?
    • 2.KVC的赋值和取值的过程是怎样的?原理是什么?
      • 赋值:KVC赋值(setValue:forKey:)
      • 取值:KVC取值(valueForKey:)
  • Category
    • 1.Category的使用场合是什么?
    • 2.Category的实现原理
    • 3.Category和Class Extension的区别是什么?
    • 4.Category中有load方法吗?load方法是什么时候调用的?load方法继承吗?
    • 5.load、initialize方法的区别是什么?它们在category中的调用顺序是什么?以及出现继承时他们之间的调用过程?
      • 区别:
      • 在Category中的调用顺序:
      • 继承时它们之间的调用过程:
    • 6.Category能否添加成员变量?如果可以,如何给Category添加成员变量?

block

1.block的原理是怎样的?本质是什么?

在iOS中,Block是一种特殊的对象。封装了函数调用以及调用环境的OC对象。用于封装代码块。它可以作为参数传递给方法或函数,并且可以在稍后的时间点执行。

Block的本质是一个封装了一段代码以及其访问的变量的结构体。当定义一个Block时,它会捕获其所在作用域中的变量,并将这些变量的值复制到自己的内部结构中。这样,在Block执行时,即使变量已经超出了其作用域,仍然可以访问并使用这些变量的值。

block转成C++的源码:

//经过clang转换后的C++代码
struct __block_impl {
  void *isa;//指向所属类的指针
  int Flags;//标志性参数,暂时没用到所以默认为0
  int Reserved;//今后版本升级所需的区域大小。
  void *FuncPtr;//函数指针,指向实际执行的函数,也就是block中花括号里面的代码内容。
};

struct __main_block_impl_0 {
  struct __block_impl impl;//上面点1中的结构体的变量
  struct __main_block_desc_0* Desc;//上面点2中的结构体的指针 
  
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself {
	printf("Block\n");
}

static struct __main_block_desc_0 {
  size_t reserved;  //今后版本升级所需区域的大小(一般填0)
  size_t Block_size;   //Block的大小
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};

int main(int argc, const char * argv[]) {
	void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
	
	((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
    return 0;
}

关于block的具体细节可以看看之前的博客:【iOS】—— 浅看block源码
【iOS】—— 初识block

2.__block的作用是什么?有什么使用注意点?

在iOS中,__block是一个修饰符,用于在Block内部修改外部变量的值。它的作用是将外部变量在Block内部转为可修改的变量。

使用__block修符可以解决Block内部无法修改外部变的问题。默认情况下,Block内部能访问外部变量的,而不能修改它们。是,当你在外部量前面加上__block修饰符时,Block就可以修改这变量的值了。

以下是一些使用注意点:

  • __block修饰符只能于局部变量,不能用全局变量或静态变量。
  • 在Block部使用__block修的变量时,需要注意循环引用的问题如果Block被强引用并且同时引用了__block修饰的变,可能会导致环引用,造成内存漏。为了避免这种情况,可以在Block内部使用weakSelf来弱引用self,或者使用__weak饰符来修饰__block变量。
  • __block修饰的变量Block内部被修改,外部变量的值会被修改。这意味在Block执行完后,外部变量的值将保持被修改后的状态。
  • 在使用ARC(动引用计数)的情况下,__block饰符会自动处理内存管理。但是,在非ARC环境下,你需要手动处理__block变量的内存管理,确保Block执行完毕后释放它们。

3.block的属性修饰词为什么是copy?使用block有哪些使用注意?

  • block一旦没有进行copy操作,就不会在堆上。MRC 下 block 如果没有 copy 到堆上,值捕获不会对外部变量引用。 虽然 ARC 环境 strong 也可以修饰 Block,那是因为编译器会对 strong 修饰的 block 也会进行一次 copy 操作。
  • 因为Block的内存地址显示在栈区,栈区的特点就是创建的对象随时销毁,一旦销毁后续再次调用空对象就会造成程序崩溃。对Block进行copy操作之后,block存在堆区,所以在使用Block属性的时候Copy修饰。
  • 使用注意:循环引用问题

循环引用及强弱共舞可以看看之前的博客,上面有链接

4.block在修改NSMutableArray,需不需要添加__block?

不需要,给NSMutableArray添加元素时。__block修饰符主要用于在Block内部问和修改外部变量,以决Block内部对外部变量的捕获问题。而在修改NSMutableArray这样可变对象时,并不需要使用__block修饰符。因为NSMutableArray是一个指针类型的对象,当你在Block内部修改它,实际上是修改了指向该对象的指针,而是直接修改指针所指的对象本身。因此,无需使用__block修饰符来解决捕获问题。

5.关于block对不同种变量的捕获问题

先说结论:

  • 全局变量: 不捕获
  • 局部变量: 捕获值
  • 静态全局变量: 不捕获
  • 静态局部变量: 捕获指针
  • const修饰的局部常量:捕获值
  • const修饰的静态局部常量:捕获指针

局部变量:

    int dmy = 256;
    int val = 10;
    const char *fmt = "val = %d\n";
    void (^blk)(void) = ^{
        printf(fmt, val);
    };
    val = 2;
    fmt = "These values were changed. val = %d\n";
    blk();

输出结果:
在这里插入图片描述

全局变量

    void (^blk)(void) = ^{
        printf("%d\n", quanju);
    };
    quanju = 60;
    blk();

输出结果:
在这里插入图片描述

静态全局变量

    void (^blk)(void) = ^{
        printf("%d\n", jingquanju);
    };
    jingquanju = 60;
    blk();

在这里插入图片描述

静态局部变量

    int jingjubu = 10;
    void (^blk)(void) = ^{
        printf("%d\n", jingjubu);
    };
    jingjubu = 60;
    blk();

在这里插入图片描述

6.block捕获变量的原理是什么?

  • 在执行Block语法的时候,Block语法表达式所使用的自动变量的值是被保存进了Block的结构体实例中,也就是Block自身中。
  • 这里值得说明的一点是,如果Block外面还有很多自动变量,静态变量,等等,这些变量在Block里面并不会被使用到。那么这些变量并不会被Block捕获进来,也就是说并不会在构造函数里面传入它们的值。
  • Block捕获外部变量仅仅只捕获Block闭包里面会用到的值,其他用不到的值,它并不会去捕获。
    请添加图片描述

7.__block修饰符的作用

编译器会将__block变量包装成一个对象,变成对象后就可以根据指针地址在block内部去修改外部的变量,block通过__forwarding指针去修改变量的值

  • __block修饰对象类型的变量生成的结构体内部多了__Block_byref_id_object_copy__Block_byref_id_object_dispose两个函数,用来对对象类型的变量进行内存管理的操作。
  • __main_block_copy_0函数中会根据变量是强弱指针及有没有被__block修饰做出不同的处理,强指针在block内部产生强引用,弱指针在block内部产生弱引用。
  • 当修改__block修饰的变量时,是根据变量生成的结构体这里是__Block_byref_age_0找到其中__forwarding指针,__forwarding指针指向的是结构体自己因此可以找到变量进行修改。
  • 当block在栈中时,__Block_byref_age_0结构体内的__forwarding指针指向结构体自己。
  • 而当block被复制到堆中时,栈中的__Block_byref_age_0结构体也会被复制到堆中一份,而此时栈中的__Block_byref_age_0结构体中的__forwarding指针指向的就是堆中的__Block_byref_age_0结构体,堆中__Block_byref_age_0结构体内的__forwarding指针依然指向自己。

KVO

详解KVO的博客:【iOS】—— KVO再学习

1.iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)

  • 利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类
  • 当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数
  • 接着调用父类原来的setter方法;
  • 最后调用didChangeValueForKey,其内部会触发监听器(Oberser)的监听方法(observerValueForKeyPath:ofObject:change:context:);

总结

  • 主要用了isa-swizzling,修改了观察者的类信息,并且hooksetter方法,当setter方法调用时发送消息给所有观察者
  • 由上面源码可以看出对观察者、被观察者的引用都是Not Retain, 所以对象释放前一定要移除观察者。
  • 消息的发送主要由[self willChangeValueForKey: key], [self didChangeValueForKey: key]触发,并且必须成对出现,automaticallyNotifiesObserversForKey方法用来控制,是否要主要添加上述的两个方法,默认返回值为YES,如果返回NO则不会自动添加,也就是说setter的调用以及KVC修改都不会触发通知
  • + (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key
    此方法用来设置依赖关系,有时候需要某属性值随着同一对象的其他属性的改变而改变。可以通过事先将这样的依赖关系在类中注册,那么即便属性值间接地发生了改变,也会发送通知消息,被观察者类重写返回和key依赖的所有key集合
    内部实现也比较简单,将所有依赖关系存储在全局的dependentKeyTable中,然后hook了所有依赖的keysetter方法,当[self willChangeValueForKey: key], [self didChangeValueForKey: key]调用时会查找所有的依赖关系,然后发送消息
  • KVO内部多次用到了KVC
    • 重写 setValue:forKey
    • 使用valueForKey --- valueForKeyPath获取属性的值,尤其是在使用点语法的时候,只有valueForKeyPath可以获得深层次的属性值。
      所以KVO是基于KVC而实现的。

2.如何手动触发KVO?

  • 手动调用willChangeValueForKey:didChangeValueForKey:

3.直接修改成员变量会触发KVO么?

  • 不会触发KVO,KVO的本质是替换了setter方法的实现,所以只有通过set方法修改才会触发KVO。

KVC

详解KVC的博客:【iOS】—— KVC再学习

1.通过KVC修改属性会触发KVO么?

  • 会触发KVO。KVC在修改属性时,会调用willChangeValueForKey:didChangeValueForKey:方法;

2.KVC的赋值和取值的过程是怎样的?原理是什么?

赋值:KVC赋值(setValue:forKey:)

  • 首先会按照setKey_setKey的顺序查找方法,若找到方法,则直接调用方法并赋值;
  • 未找到方法,则调用+ (BOOL)accessInstanceVariablesDirectly;
  • accessInstanceVariablesDirectly方法返回YES,则按照_key_isKeykeyisKey的顺序查找成员变量,找到直接赋值,找不到则抛出异常;
  • accessInstanceVariablesDirectly方法返回NO,则直接抛出异常;
    在这里插入图片描述

取值:KVC取值(valueForKey:)

  • 首先会按照getKeykeyisKey_key的顺序查找方法,找到直接调用取值
  • 若未找到,则查看+ (BOOL)accessInstanceVariablesDirectly的返回值,若返回NO,则直接抛出异常;
  • 若返回的YES,则按照_key_isKeykeyisKey的顺序查找成员变量,找到则取值;
  • 找不到则抛出异常;
    在这里插入图片描述

Category

1.Category的使用场合是什么?

Category除了用来给类进行扩展外,还有一种比较高级的用法,就是用来拆分模块,将一个大的模块拆分成多个小的模块,方便进行维护和管理。什么意思呢?我就举一个很多开发人员都会存在的问题,就是AppDelegate这个类。这个类是刚创建项目时自动生成的,用来管理程序生命周期的。在刚创建项目时,这个类中是没有多少代码的,但是随着项目的进行,越来越多的代码会被放在这个类里面。比如说集成极光推送、友盟、百度地图、微信SDK等各种第三方框架时,这些第三方框架的初始化工作,甚至是相关的业务逻辑代码都会放在这个类里面,这就导致随着APP的功能越来越复杂,AppDelegate中的代码就会越来越多,有的甚至有几千行,看着就让人头皮发麻。

这时我们就可以利用Category来对AppDelegate进行拆分,首先我们就需要对AppDelegate中的代码进行划分,把同一种功能的代码抽取出来放在一个分类里面。比如说我可以新建一个极光推送的分类,然后把所有和极光推送有关的代码都抽出来放入这个分类,把所有和微信相关的代码抽出来放进微信的分类中,后面又有新的功要添加的话我只需要新建分类就好了。维护的时候要改什么功能的代码就直接找相应的分类就好了。

2.Category的实现原理

// 定义在objc-runtime-new.h文件中
struct category_t {
    const char *name; // 比如给Student添加分类,name就是Student的类名
    classref_t cls;
    struct method_list_t *instanceMethods; // 分类的实例方法列表
    struct method_list_t *classMethods; // 分类的类方法列表
    struct protocol_list_t *protocols; // 分类的协议列表
    struct property_list_t *instanceProperties; // 分类的实例属性列表
    struct property_list_t *_classProperties; // 分类的类属性列表
};
  • Category编译之后的底层结构是结构体struct category_t,里面存储着分类的对象方法、类方法、属性、协议信息。
  • 程序运行的时候,Runtime 会将Category的信息合并到类信息中(class类对象、mate-class元类对象),后合并的分类数据会插入到原来数据的前面;
  • 分类没有自己的class对象、和mate-class对象,因为一个类只有一个class对象、mate-class对象。

3.Category和Class Extension的区别是什么?

  • Class Extension是在编译的时候,它的数据都已经包含在类信息中了;
  • Category是在运行的时候,才将数据合并到类信息中。
  • 分类原则上只能增加方法,但是也可以通过关联属性增加属性
  • 拓展可以增加方法和属性,都是私有的。
  • 扩展只能在自身类中使用,而不是子类或者其他地方。
  • 类扩展是在编译阶段添加到类中,而分类是在运行时添加到类中

4.Category中有load方法吗?load方法是什么时候调用的?load方法继承吗?

  • +load方法。
  • +load方法会在Runtime加载类、分类的时候调用;
  • 每个类的+load方法只会调用一次;
  • 先调用类的+load方法,(按照编译顺序,先编译,先调用),调用子类的+load方法之前,会先调用父类的+load方法;
  • 再调用分类的+load方法,(按照编译顺序,先编译,先调用)。
  • 这里+load方法调用的顺序比较特别,没有先调用分类的+load方法,因为+load方法的调用机制不是objec_msgSend的方式,+load是直接找到方法地址进行调用的。
  • load方法能继承,不过一般不会手动调用load方法,都是系统自动调用。

5.load、initialize方法的区别是什么?它们在category中的调用顺序是什么?以及出现继承时他们之间的调用过程?

区别:

  • 调用时机
    load,当runtime加载类、分类时会调用。load方法总是在main函数之前调用,每个类、分类的load在运行时只调用一次
    initialize,在类第一次接收到消息时调用(先初始化父类,再初始化子类,每一个类只会被初始化一次)
  • 调用顺序
    load方法:先调用类的load,子类调用load方法之前会先调用父类的load,先编译的先调用;再调用分类的load方法,先编译的先调用
    initialize方法:先调用父类的initialize再调用当前类的initialize,如果子类没有实现initialize,则会调用父类的initialize;如果有分类,则调用最后编译的分类的initialize,就不调用本类的initialize了
  • 调用本质
    load,根据IMP地址直接调用(*load_method)(cls, SEL_load)
    initialize,通过objc_msgSend进行调用
  • 使用场景
    在load方法中实现方法交换(Method Swizzle)
    一般用于初始化全局变量或静态变量
  • 相同点
    两个方法会被自动调用,不需要手动调用他们
  • 区别
    load是通过直接函数地址调用,只会调用一次
    initialize是通过msgSend调用
    • 如果子类没有实现initialize,会调用父类的initialzie(所以父类的initialize会被调用很多次)
    • 分类如果实现了initialize,就会覆盖类本身的initailize

在Category中的调用顺序:

  • 如果有多个Category对同一个类实现了+load方法,它们的调用顺序是不确定的。编译器会将所有的+load方法放入一个全局的链表中,然后在运行时按照链的顺序依次调用。
  • 对于+initialize方法,如果一个类本身实现了+initialize方法,那么它会覆盖父类的+initialize方法。如果有多个Category对同一个类实现了+initialize方法,么只有最后一个被加载的Category的+initialize方法被调用。

继承时它们之间的调用过程:

  • 当一个类继承时,子类会继承父类的+load方法。父类的+load方法会在子的+load方法之前被调用。
  • 对于+initialize方法,子类如果没有实现自己的+initialize方法,继承父类的+initialize方法。父类的+initialize方法会在子类的+initialize方法之前被调用如果子类实现了自的+initialize方法,么父类的+initialize方法不被调用。

6.Category能否添加成员变量?如果可以,如何给Category添加成员变量?

不能直接给Category添加成员变量,但是可以间接实现Catecory有成员变量的效果。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

不止工具:音视频开发「利器」的新机遇

Boxing的制胜关键是快、准、稳&#xff0c;与“音视频开发”有异曲同工之妙。 数字化浪潮席卷、视频化形态加速、终端性能挑战加剧、端侧算力遭遇瓶颈...... 是否存在一种可能性&#xff0c;让所有企业从复杂的音视频开发工程中抽身&#xff0c;重新回归业务本身&#xff1f; …

消息队列总结(3)- RabbitMQ Kafka RocketMQ高可用方案

目录 1. 什么是高可用&#xff1f; 1.1 常见的高可用方法 1.2 消息队列的高可用 2. RabbitMQ的高可用方案 2.1 镜像队列 2.2 消息生产的确认机制 2.3 消息的持久化 3. Kafka的高可用方案 3.1 消息备份 3.2 ISR & IEO & HW 3.3 消息生产的确认机制 4. Rocke…

微信小程序开发使用echarts报错Cannot read property ‘getAttribute‘ of undefined

如图&#xff0c;我在小程序圈中的区域渲染echarts图标报错了&#xff0c;报错提示Cannot read property getAttribute of undefined 这里的canvas &#xff0c;width ,height,dpr获取为 undefined 分析问题&#xff1a; 初始化图表时传递错误的参数&#xff1a; 在 onShow 生…

Vue第四篇:html和js基础知识查漏补缺

1、a标签 定义超链接&#xff0c;用于从一个页面链接到另一个页面 target属性&#xff1a;打开目标URL的方式&#xff0c;_top为再当前窗口打开&#xff0c;_blank为新窗口打开 2、span标签 对文档中的行内元素进行组合&#xff0c;它提供了一种将文本的一部分或者文档的一部分…

MySQL 数据抽稀 每分钟取一条

假如原始数据为每5秒一个数据&#xff0c;现在想展示为每4分钟一条数据&#xff0c;先按照分钟数把除以4余数为0的行选出来&#xff0c;在按照 年月日 时分&#xff0c;做组内排序&#xff08;窗函数ROW_NUMBER&#xff09;&#xff0c;最后再拿出序号为1的行。 WITH data_01 …

了解Unity编辑器之组件篇UI(一)

UI组件&#xff1a;提供了用户交互&#xff0c;信息展示&#xff0c;用户导航等功能 一、Button&#xff1a;用于响应用户的点击事件 1.Interactable&#xff08;可交互&#xff09;&#xff1a;该属性控制按钮是否可以与用户交互&#xff0c;如果禁用则按钮无法被点击。可以通…

go使用gin结合jwt做登录功能

1、安装gin go get -u github.com/gin-gonic/gin 2、安装session go get github.com/gin-contrib/sessions 3、安装JWT鉴权 go get "github.com/golang-jwt/jwt/v4" 4、创建一个jwt的工具文件 package utilsimport ("errors""github.com/golan…

ubuntu挂载ext4文件系统

文章目录 1.虚拟机分配10G磁盘用来挂载ext4文件系统2.磁盘分区3.创建文件系统4.挂载文件系统5.卸载文件系统6.使用ior测试ext4三种日志模式&#xff08;1&#xff09;ordered&#xff08;2&#xff09;journal&#xff08;3&#xff09;writeback 1.虚拟机分配10G磁盘用来挂载e…

Flutter动画库:animations(路由过渡动画或者页面切换动画)

animations animations 是一个 Flutter 库&#xff0c;它提供了一组用于创建动画效果的工具和组件。这个库的核心重点是路由过渡动画或者页面切换动画 地址 https://pub-web.flutter-io.cn/packages/animations 安装 flutter pub add animations看了下官方文档和官方例子&a…

【深度学习】【Image Inpainting】Free-Form Image Inpainting with Gated Convolution

模型&#xff1a;DeepFillv2 (CVPR’2019) 论文&#xff1a;https://arxiv.org/abs/1806.03589 代码&#xff1a;https://github.com/JiahuiYu/generative_inpainting 文章目录 效果AbstractIntroductionRelated WorkAutomatic Image InpaintingGuided Image Inpainting and Sy…

第1章 获取数据库中的数据

CoreShop源程序是以数据库优先进行定义的&#xff0c;所以其本身不包含代码优先的定义&#xff0c;但本从更习惯于代码优先&#xff0c;所以为其定义了代码优先的定义。 1 CoreCms.Net.Model.Entities.SysRole using SqlSugar; using System.ComponentModel.DataAnnotations…

三十章:Segmenter:Transformer for Semantic Segmentation ——分割器:用于语义分割的Transformer

0.摘要 图像分割在单个图像块的级别上经常存在歧义&#xff0c;并需要上下文信息来达到标签一致性。在本文中&#xff0c;我们介绍了一种用于语义分割的Transformer模型- Segmenter。与基于卷积的方法相比&#xff0c;我们的方法允许在第一层和整个网络中对全局上下文进行建模。…

《PyTorch深度学习实践》

文章目录 1.线性模型2.梯度下降算法3.反向传播3.1原理3.2Tensor in PyTorch 4.用PyTorch实现线性模型 1.线性模型 2.梯度下降算法 # 梯度下降x_data [1.0,2.0,3.0] y_data [2.0,4.0,6.0]w 3.0def forward(x):return x*w# 损失函数 def cost(xs,ys):cost 0for x,y in zip(x…

基于 Flink SQL CDC 数据处理的终极武器

文章目录 一、传统的数据同步方案与 Flink SQL CDC 解决方案1.1 Flink SQL CDC 数据同步与原理解析1.2 基于日志的 CDC 方案介绍1.3 选择 Flink 作为 ETL 工具 二、 基于 Flink SQL CDC 的数据同步方案实践2.1 CDC Streaming ETL2.2 Flink-CDC实践之mysql案例 来源互联网多篇文…

华为OD机试真题 Java 实现【文件目录大小】【2023 B卷 100分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明4、再输入5、再输出6、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题…

spring-cloud-alibaba——nacos-server搭建

前言&#xff1a;组件版本关系&#xff0c;官方:组件版本关系 1,nacos-server搭建&#xff08;windows环境&#xff09;&#xff0c;下载地址nacos 选择对应的版本&#xff0c;这里以目前最新版2.2.3为例子,下载后解压 单机模式 修改\nacos-server-2.2.3\nacos\bin\startup.c…

分布式调用与高并发处理 Nginx

一、初识Nginx 1.1 Nginx概述 Nginx是一款轻量级的Web服务器、反向代理服务器&#xff0c;由于它的内存占用少&#xff0c;启动极快&#xff0c;高并发能力强&#xff0c;在互联网项目中广泛应用。Nginx 专为性能优化而开发&#xff0c;使用异步非阻塞事件驱动模型。 常见服务…

(2)前端控制器的扩展配置, 视图解析器类型以及MVC执行流程的概述

SpringMVC入门程序的扩展说明 注册前端控制器的细节 在web.xml文件注册SpringMVC的前端控制器DispatcherServlet时使用url-pattern标签中使用/和/*的区别 /可以匹配.html或.js或.css等方式的请求路径,但不匹配*.jsp的请求路径/*可以匹配所有请求(包括.jsp请求), 例如在过滤器…

【Linux Shell】基础知识

Linux Shell基础知识 一、Linux Shell基础概念1.1 Shell定义1.2 命令行提示符 二、初识Shell2.1 Shell定义2.2 登录Shell相关文件2.3 Shell中的变量变量类型变量的引用单引号\ 与双引号\" \"变量的删除与检查 2.4 Shell中的扩展大括号扩展{ }其他扩展 一、Linux Shel…

使用springboot进行后端开发100问

properties和yaml文件怎么互转 安装插件 properties文件和yaml文件区别 properties 文件通过“.”和“”赋值&#xff0c;值前不加空格&#xff0c;yaml通过“:”赋值&#xff0c;值前面加一个空格&#xff1b;yaml文件缩进用空格&#xff1b; properties只支持键值对&#x…