对LitJson开源插件的自定义尝试

简介

   LitJson是一款知名的Json字符串数据转换的插件,基于.Net开发,使用C#作为开发语言。本文旨在基于所学的编程知识以及对LitJson源码的理解来尝试对LitJson插件进行自定义。

自定义思路

(一)问题

       结合我在使用LitJson过程中遇到的问题,主要针对四个常见问题进行自定义:

问题1:当我们通过RegisterExporter方法自定义指定类型的序列化规则时,对于类型控制更加严格,而当我对Type类型自定义序列化规则时出现了序列化深度溢出的问题,我根据LitJson的源码进行了调试。首先我们通过RegisterExporter方法需要指定泛型,这个指定的序列化类型以编译时类型存储于字典中,因为typeof(T)获取的是编译时类型,而在WriteValue方法中对于非基本类型需要通过obj.GetType()获取一个obj对象的Type实例,而在代码运行过程中此方法将返回一个运行时类型,这个运行时类型被认为与我们存入字典中的对应类型不同。这在外部看来我只是希望自定义Type类型的序列化规则能够成功执行,而在对Type类型变量进行序列化时却未能执行我自定义的序列化规则,导致这个原因的问题就是对于Type而言,字典中存储的是System.Type,而obj.GetType()获取的Type实例是System.RuntimeType,所以二者不相同,未通过字典的ContainsKey检测,于是无法调用针对Type类型的自定义序列化规则,从而导致序列化深度溢出。

问题2:某些字段或属性我们不希望被序列化。

问题3:某些私有字段或属性我们希望能够被序列化。

问题4:同一类型的字段或属性在不同的结构中的序列化规则可能有所不同,所以全局的序列化规则将不适用,我们需要扩展出局部的序列化规则,以便于用户能够在不同结构中对同一类型的字段或属性的序列化规则进行自定义,这将进一步提高该插件的灵活性,反序列化亦是如此。优先级应为局部规则>全局规则。

(二)解决方案

       针对上述四个问题的解决方案如下:

方案1:原本字典的ContainsKey检测更加严格,是通过Type.Equals()进行检测的,所以不会包括派生关系的检测,实际上obj is xxx通过is关键字判断也是会有派生关系的检测的,既然对于基本类型的检测是放宽了检测的严格程度,那么对于非基本类型也可以放宽一下检测的严格程度,于是我们引入了可过渡检测的策略,这个策略的实现是通过Type.IsAssignableFrom()来实现的,我们通过obj.GetType()获取的类型如果能够转换为字典中存放的类型,那么就被认为通过字典的ContainsKey检测。我们应该让用户来控制是否开启可过渡检测,因为并非所有类型都像Type类型一样特殊,而默认不开启可过渡检测,可过渡检测仅用于针对某些特殊类型的检测处理,默认情况下我们对序列化类型的控制依旧严格。当用户自定义的某个类型的序列化规则无法正常执行时,可以考虑使用该方法作为替补方案。


当我们通过RegisterExporter所注册的类型(编译时类型)与运行时通过GetType()获取的类型(运行时类型)不同,导致未通过字典的ContainsKey检测而无法执行自定义的序列化规则,此方法可开启派生关系的可过渡检测,如果当前运行时类型可以转换为所注册的编译时类型(允许具有派生关系的类型的转换),那么我们就认为通过字典的ContainsKey检测并执行对应编译时类型的自定义序列化规则。当一个对象的编译时类型和运行时类型不同时可以考虑使用这个方法作为辅助方法,例如Type类型、接口类型、抽象类类型的字段或属性。

方案2:定义一个JsonIgnore的Attribute,用于标记不进行序列化的字段或属性,在JsonMapper的WriteValue和ReadValue方法中添加检测代码。

方案3:定义一个JsonInclude的Attribute,用于标记进行序列化的私有字段或属性,在JsonMapper的WriteValue和ReadValue方法中添加检测代码。

方案4:设字段或属性类型为A,定义字段或属性所在结构的类型为B,序列化或反序列化规则为C,Json数据类型D。

序列化:原有的对应关系是A=>C(字段或属性类型对应序列化规则),即<Type,ExportFunc>,现在我们需要建立的新的对应关系是(A+B)=>C(字段或属性类型+定义字段或属性所在结构的类型共同对应序列化规则),即

<Type, <Type,ExportFunc>>。

反序列化:原有的对应关系是(A+D)=>C(字段或属性类型+Json数据类型对应反序列化规则),即<Type,<Type,ImportFunc>>,现在我们需要建立的新的对应关系是(A+B+D)=>C(字段或属性类型+定义字段或属性所在结构的类型+Json数据类型对应反序列化规则),即<<Type,Type>,<Type,ImportFunc>>。

建议:对于这种嵌套过多的关系,建议定义一个单独的类或结构体来存储它们的关系。

       方案1-4分别对应问题1-4,其中方案1涉及自定义特性[JsonAssignable],方案2涉及自定义特性[JsonIgnore],方案3涉及自定义特性[JsonInclude],方案4涉及自定义特性[ExporterTarget]

(三)特性

 全称:JsonAssignableAttribute

缩写:[JsonAssignable]

使用范围:field、property

限制:不允许继承、不允许重复标记

说明:该Attribute用于标记需要进行可过渡性检测的字段或属性。 

全称:JsonIgnoreAttribute

简写:[JsonIgnore]

使用范围:fieldproperty

限制:不允许继承、不允许重复标记

说明:定义用于标记不进行序列化的字段或属性的Attribute

全称:JsonIncludeAttribute

简写:[JsonInclude]

使用范围:fieldproperty

限制:不允许继承、不允许重复标记

说明:定义用于标记待序列化的私有字段或属性的Attribute

全称:ExporterTargetAttribute(Type classType)

缩写:[ExporterTarget]

使用范围:classstruct、interface

限制:不允许继承、不允许重复标记

说明:当使用RegisterExporter<T,TClass>(ExporterFunc<T> exporter)方法时,必须使用该Attribute标记对应序列化字段或属性所在的类。

(四)其它自定义 

1. LitJson基于.NET开发,使用的是C#语言,所以可以应用于Unity3D游戏开发中,在本次自定义中我对Unity中常用的数据结构的序列化和反序列化进行了扩展,包括Vector2, Vector3, 

Vector4, Rect, Quaternion, Color, Bounds,以及C#的Type类型。


2. 修改方法

//原方法:
public static void RegisterExporter<T>(ExporterFunc<T> exporter)
//修改后的方法:
public static void RegisterExporter<T>(ExporterFunc<T> exporter, bool assignable = false)

3. 添加方法

public static void RegisterExporter<T, TClass>(ExporterFunc<T> exporter, bool assignable = false)

4. 添加方法

public static void RegisterImporter<TJson, TValue, TClass>(ImporterFunc<TJson, TValue> importer)

5. 添加方法

public static void RegisterImporterWithReader<TValue>(ImporterFunc<CustomReader, TValue> importer)

6. 添加方法

public static void RegisterImporterWithReader<TValue, TClass>(ImporterFunc<CustomReader, TValue> importer)

7. 添加类CustomReader和ReaderData

测试代码(C#)

公共测试脚本test.cs

interface IPerson
{string mName { get; set; }int mAge { get; set; }
}class PersonD : IPerson
{public string mName { get => name; set => name = value; }public int mAge { get => age; set => age = value; }public string mSex { get => sex; set => sex = value; }string name;int age;string sex;public override string ToString(){return $"[mName:{mName}, mAge:{mAge}, mSex:{mSex}]";}
}abstract class House
{public string mName;public float mSize;
}

(1)测试JsonAssignable特性:公共接口类型字段

using LitJson.Extensions;
using UnityEditor;
using UnityEngine;
using LitJson;namespace JATest
{class ja_test1{[MenuItem("LitJsonTest/JsonAssignable Test/Run the Test1")]static void Test(){Debug.Log(new string('*', 80));Debug.Log("<b><color=green>【测试JsonAssignable特性:公共接口类型字段】</color></b>");PersonD person = new PersonD{mName = "Mike",mAge = 18,mSex = "Male"};JAHouseA houseA = new JAHouseA(){mName = "HouseA",mSize = 100,person = person};string jsonStr = JsonMapper.ToJson(houseA);Debug.Log(jsonStr);JAHouseA houseA1 = JsonMapper.ToObject<JAHouseA>(jsonStr);Debug.Log(houseA1);Debug.Log(new string('*', 80));}}class JAHouseA : House{[JsonAssignable] public IPerson person;public override string ToString(){return $"[mName:{mName}, mSize:{mSize}, person:{person}]";}}
}

(2)测试JsonAssignable特性:公共抽象类类型字段 

using LitJson.Extensions;
using UnityEditor;
using UnityEngine;
using LitJson;namespace JATest
{class ja_test2{[MenuItem("LitJsonTest/JsonAssignable Test/Run the Test2")]static void Test(){Debug.Log(new string('*', 80));Debug.Log("<b><color=green>【测试JsonAssignable特性:公共抽象类类型字段】</color></b>");JAHouseB houseB = new JAHouseB(){mName = "HouseA",mSize = 100};JAPersonA person = new JAPersonA{mName = "Mike",mAge = 18,house = houseB};string jsonStr = JsonMapper.ToJson(person);Debug.Log(jsonStr);JAPersonA personA = JsonMapper.ToObject<JAPersonA>(jsonStr);Debug.Log(personA);Debug.Log(new string('*', 80));}}class JAHouseB : House{public override string ToString(){return $"[mName:{mName}, mSize:{mSize}]";}}class JAPersonA : IPerson{public string mName { get; set; }public int mAge { get; set; }[JsonAssignable] public House house;public override string ToString(){return $"[mName:{mName}, mAge:{mAge}, house:{house}]";}}
}

(3)测试JsonIgnore特性:忽略公共字段

using UnityEditor;
using UnityEngine;
using LitJson;
using LitJson.Extensions;namespace JIATest
{class jig_test1{[MenuItem("LitJsonTest/JsonIgnore Test/Run the Test1")]static void Test(){Debug.Log(new string('*', 80));Debug.Log("<b><color=green>【测试JsonIgnore特性:忽略公共字段】</color></b>");JIAPerson person = new JIAPerson{mName = "Mike",mAge = 18};JIAHouseA houseA = new JIAHouseA(){mName = "HouseA",mSize = 100,person = person};string jsonStr = JsonMapper.ToJson(houseA);Debug.Log(jsonStr);JIAHouseA houseA1 = JsonMapper.ToObject<JIAHouseA>(jsonStr);Debug.Log(houseA1);Debug.Log(new string('*', 80));}}class JIAPerson : IPerson{public string mName { get; set; }public int mAge { get; set; }}class JIAHouseA : House{[JsonIgnore] public JIAPerson person;public JIAHouseA() { }public JIAHouseA(JIAPerson person) { this.person = person; }public override string ToString(){return $"[mName:{mName}, mSize:{mSize}, person:{person}]";}}
}

(4)测试JsonInclude特性:私有自定义类型字段

using LitJson.Extensions;
using UnityEngine;
using UnityEditor;
using LitJson;namespace JITest
{class ji_test1{[MenuItem("LitJsonTest/JsonInclude Test/Run the Test1")]static void Test(){Debug.Log(new string('*', 80));Debug.Log("<b><color=green>【测试JsonInclude特性:私有自定义类型字段】</color></b>");PersonD person = new PersonD{mName = "Mike",mAge = 18,mSex = "Male"};JIHouseA houseA = new JIHouseA(person){mName = "HouseA",mSize = 100};string jsonStr = JsonMapper.ToJson(houseA);Debug.Log(jsonStr);JIHouseA houseA1 = JsonMapper.ToObject<JIHouseA>(jsonStr);Debug.Log(houseA1);Debug.Log(new string('*', 80));}}class JIHouseA : House{[JsonInclude] private PersonD person;// 必要条件:当有多个构造函数时应主动声明公共无参构造函数public JIHouseA() { }public JIHouseA(PersonD person) { this.person = person; }public override string ToString(){return $"[mName:{mName}, mSize:{mSize}, person:{person}]";}}
}

(5)测试JsonInclude特性:私有自定义类型数组、列表和字典字段序列化和反序列化测试

using LitJson.Extensions;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEditor;
using LitJson;namespace JITest
{class ji_test2{[MenuItem("LitJsonTest/JsonInclude Test/Run the Test2")]static void Test(){Debug.Log(new string('*', 80));Debug.Log("<b><color=green>【测试JsonInclude特性:私有自定义类型数组、列表和字典字段序列化和反序列化测试】</color></b>");PersonD personD = new PersonD(){mName = "Mike",mAge = 20,mSex = "Male"};PersonD personD2 = new PersonD(){mName = "Lucy",mAge = 26,mSex = "Female"};PersonD personD3 = new PersonD(){mName = "Jack",mAge = 8,mSex = "Male"};HouseF houseF = new HouseF(){mName = "HouseF",mSize = 100};houseF[0] = personD;houseF[1] = personD2;houseF[2] = personD3;houseF.AddToList(personD);houseF.AddToList(personD2);houseF.AddToList(personD3);houseF.AddToDict(personD.mName, personD);houseF.AddToDict(personD2.mName, personD2);houseF.AddToDict(personD3.mName, personD3);string jsonStr = JsonMapper.ToJson(houseF);Debug.Log(jsonStr);HouseF houseF1 = JsonMapper.ToObject<HouseF>(jsonStr);Debug.Log(houseF1);Debug.Log(new string('*', 80));}}class HouseF : House{[JsonInclude] private PersonD[] persons; // 用于测试私有自定义类型数组[JsonInclude] private List<PersonD> personList; // 用于测试私有自定义类型列表[JsonInclude] private Dictionary<string, PersonD> personDict; // 用于测试私有自定义类型字典private int index;public HouseF(){persons = new PersonD[3];personList = new List<PersonD>();personDict = new Dictionary<string, PersonD>();index = 0;}public void AddToList(PersonD person){personList.Add(person);}public void AddToDict(string name, PersonD person){personDict[name] = person;}public PersonD this[int index]{get{if (index >= 0 && index <= this.index) return persons[index];return null;}set { if (index >= 0 && index < 3) persons[index] = value; }}public override string ToString(){StringBuilder stringBuilder = new StringBuilder($"[mName:{mName}, mSize:{mSize}, ");stringBuilder.Append("Array:{");for (int i = 0; i < persons.Length; i++){stringBuilder.Append(persons[i] + ",");}stringBuilder.Append("}, List:{");for (int i = 0; i < personList.Count; i++){stringBuilder.Append(personList[i] + ",");}stringBuilder.Append("}, Dict:{");foreach (string key in personDict.Keys){stringBuilder.Append(personDict[key] + ",");}stringBuilder.Append("}]");return stringBuilder.ToString();}}
}

 (6)测试ExporterTarget特性:相同的自定义类型公共字段在不同的类中序列化规则不同

using UnityEditor;
using UnityEngine;
using LitJson;
using LitJson.Extensions;namespace ETTest
{class et_test1{[MenuItem("LitJsonTest/ExporterTarget Test/Run the Test1")]static void Test(){Debug.Log(new string('*', 80));Debug.Log("<b><color=green>【测试ExporterTarget特性:相同的自定义类型公共字段在不同的类中序列化规则不同】</color></b>");ETPersonA person = new ETPersonA{mName = "Mike",mAge = 18};ETHouseA houseA = new ETHouseA(){mName = "HouseA",mSize = 100,person = person};ETHouseB houseB = new ETHouseB(){mName = "HouseB",mSize = 50,person = person};string jsonStr = JsonMapper.ToJson(houseA);Debug.Log(jsonStr);ETHouseA houseA1 = JsonMapper.ToObject<ETHouseA>(jsonStr);Debug.Log(houseA1);Debug.Log(new string('-', 80));jsonStr = JsonMapper.ToJson(houseB);Debug.Log(jsonStr);ETHouseB houseB1 = JsonMapper.ToObject<ETHouseB>(jsonStr);Debug.Log(houseB1);Debug.Log(new string('*', 80));}}class ETPersonA : IPerson{public string mName { get; set; }public int mAge { get; set; }public override string ToString(){return $"[mName:{mName}, mAge:{mAge}]";}}[ExporterTarget(typeof(ETHouseA))]class ETHouseA : House{public ETPersonA person;static ETHouseA(){JsonMapper.RegisterExporter<ETPersonA, ETHouseA>((d, writer) =>{writer.WriteObjectStart();writer.WriteProperty("ETPersonA", "ETHouseA_ETPersonA");writer.WriteObjectEnd();});}public override string ToString(){return $"[mName:{mName}, mSize:{mSize}, person:{person}]";}}[ExporterTarget(typeof(ETHouseB))]class ETHouseB : House{public ETPersonA person;static ETHouseB(){JsonMapper.RegisterExporter<ETPersonA, ETHouseB>((d, writer) =>{writer.WriteObjectStart();writer.WriteProperty("ETPersonA", "ETHouseB_ETPersonA");writer.WriteObjectEnd();});}public override string ToString(){return $"[mName:{mName}, mSize:{mSize}, person:{person}]";}}
}

(7)Json4Unity:Type类型变量的序列化和反序列化 

using UnityEditor;
using UnityEngine;
using LitJson;
using System;namespace JUTest
{class ju_test1{[MenuItem("LitJsonTest/Json4Unity Test/Run the Test1")]static void Test(){Debug.Log(new string('*', 80));Debug.Log("<b><color=green>【Json4Unity:Type类型变量的序列化和反序列化】</color></b>");JUHouseA houseA = new JUHouseA{mName = "HouseA",mSize = 100,type = typeof(PersonD)};string jsonStr = JsonMapper.ToJson(houseA);Debug.Log(jsonStr);houseA = JsonMapper.ToObject<JUHouseA>(jsonStr);Debug.Log(houseA);Debug.Log(new string('*', 80));}class JUHouseA : House{public Type type;public override string ToString(){return $"[mName:{mName}, mSize:{mSize}, type:{type}]";}}}
}

(8)Json4Unity:Unity常见数据结构Vector2,Vector3,Vector4,Rect,Quaternion,Color,

Bounds的序列化和反序列化

using UnityEditor;
using UnityEngine;
using LitJson;namespace JUTest
{class ju_test2{[MenuItem("LitJsonTest/Json4Unity Test/Run the Test2")]static void Test(){Debug.Log(new string('*', 80));Debug.Log("<b><color=green>【Json4Unity:Unity常见数据结构Vector2,Vector3,Vector4,Rect,Quaternion,Color,Bounds的序列化和反序列化】</color></b>");JUData data = new JUData{mVec2 = new Vector2(2, 3),mVec3 = new Vector3(2, 3, 4),mVec4 = new Vector4(2, 3, 4, 5),mRect = new Rect(2, 3, 4, 5),mQuat = new Quaternion(2, 3, 4, 5),mColor = new Color(3, 2, 4, 5)};data.mBounds = new Bounds(data.mVec3, data.mVec3);string jsonStr = JsonMapper.ToJson(data);Debug.Log(jsonStr);data = JsonMapper.ToObject<JUData>(jsonStr);Debug.Log(data);Debug.Log(new string('*', 80));}class JUData{public Vector2 mVec2;public Vector3 mVec3;public Vector4 mVec4;public Rect mRect;public Quaternion mQuat;public Color mColor;public Bounds mBounds;public override string ToString(){return $"[Vector2:{mVec2},Vector3:{mVec3},Vector4:{mVec4},Rect:{mRect},Quaternion:{mQuat},Color:{mColor},Bounds:{mBounds}]";}}}
}

(9)相同的自定义类型公共字段在不同的类中反序列化规则不同

using UnityEditor;
using UnityEngine;
using LitJson;namespace OtherTest
{class ot_test1{[MenuItem("LitJsonTest/Other Test/Run the Test1")]static void Test(){Debug.Log(new string('*', 80));Debug.Log("<b><color=green>【相同的自定义类型公共字段在不同的类中反序列化规则不同】</color></b>");OTPersonA person = new OTPersonA{mName = "Mike",mAge = 18};OTHouseA houseA = new OTHouseA(){mName = "HouseA",mSize = 100,person = person};OTHouseB houseB = new OTHouseB(){mName = "HouseB",mSize = 50,person = person};string jsonStr = JsonMapper.ToJson(houseA);Debug.Log(jsonStr);OTHouseA houseA1 = JsonMapper.ToObject<OTHouseA>(jsonStr);Debug.Log(houseA1);Debug.Log(new string('-', 80));jsonStr = JsonMapper.ToJson(houseB);Debug.Log(jsonStr);OTHouseB houseB1 = JsonMapper.ToObject<OTHouseB>(jsonStr);Debug.Log(houseB1);Debug.Log(new string('*', 80));}}class OTPersonA : IPerson{public string mName { get; set; }public int mAge { get; set; }public override string ToString(){return $"[mName:{mName}, mAge:{mAge}]";}}class OTHouseA : House{public OTPersonA person;static OTHouseA(){JsonMapper.RegisterImporterWithReader<OTPersonA, OTHouseA>(reader =>{ReaderData[] readerDatas = new ReaderData[2];for (int i = 0; i < reader.count; i++){readerDatas[i] = reader.GetData();}return new OTPersonA{mName = (string)readerDatas[0].propertyValue,mAge = (int)readerDatas[1].propertyValue};});}public override string ToString(){return $"[mName:{mName}, mSize:{mSize}, person:{person}]";}}class OTHouseB : House{public OTPersonA person;static OTHouseB(){JsonMapper.RegisterImporterWithReader<OTPersonA, OTHouseB>(reader =>{ReaderData[] readerDatas = new ReaderData[2];for (int i = 0; i < reader.count; i++){readerDatas[i] = reader.GetData();}return new OTPersonA{mName = (string)readerDatas[0].propertyValue,mAge = (int)readerDatas[1].propertyValue};});}public override string ToString(){return $"[mName:{mName}, mSize:{mSize}, person:{person}]";}}
}

(10)对自定义类型公共字段自定义反序列化规则

using UnityEditor;
using UnityEngine;
using LitJson;namespace OtherTest
{class ot_test2{[MenuItem("LitJsonTest/Other Test/Run the Test2")]static void Test(){Debug.Log(new string('*', 80));Debug.Log("<b><color=green>【对自定义类型公共字段自定义反序列化规则】</color></b>");OTPersonA person = new OTPersonA{mName = "Mike",mAge = 18};OTHouseC houseC = new OTHouseC{mName = "HouseC",mSize = 100,person = person};string jsonStr = JsonMapper.ToJson(houseC);Debug.Log(jsonStr);OTHouseC houseC1 = JsonMapper.ToObject<OTHouseC>(jsonStr);Debug.Log(houseC1);}}class OTHouseC : House{public OTPersonA person;static OTHouseC(){JsonMapper.RegisterImporterWithReader(reader =>{ReaderData[] readerDatas = new ReaderData[2];for (int i = 0; i < reader.count; i++){readerDatas[i] = reader.GetData();}return new OTPersonA{mName = (string)readerDatas[0].propertyValue,mAge = (int)readerDatas[1].propertyValue};});}public override string ToString(){return $"[mName:{mName}, mSize:{mSize}, person:{person}]";}}
}

总结

      对自定义内容进行了十项单元测试,且测试均通过,但未对自定义内容之间的组合使用进行联调测试(确实没啥时间),有热心网友请帮忙测试一下吧。

      本文基于LitJson进行自定义,扩展了以下功能:

       1.对C#的Type类型,以及接口类型或抽象类类型的字段或属性进行序列化和反序列化;

       2.标记指定公有字段或属性不进行序列化和反序列化;

       3.标记指定非公有字段或属性进行序列化和反序列化;

       4.根据所在类不同,自定义同类型字段或属性的序列化或反序列化的局部规则;

       5.对Unity3D中常见数据结构的序列化和反序列化进行扩展。

资源下载

百度网盘(提取码:1314)官网地址

使用声明:LitJson为开源插件,但请保护原作者基本权益以及尊重原作者的创作成果,合理合法进行使用,从本文直接或间接下载则默认同意并悉知该声明。

如果这篇文章对你有帮助,请给作者点个赞吧!

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

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

相关文章

Selenium基础

1. selenium简介 用于实现自动化测试的 python 包&#xff0c;使用前需要安装对应浏览器驱动 from time import sleep from selenium import webdriver option webdriver.ChromeOptions() # 指定chrome存储路径的二进制形式 option.binary_locationD:\Chrome\Google\Chrome\Ap…

企业计算机服务器中了halo勒索病毒怎么办,halo勒索病毒解密工具流程

随着网络技术的不断应用与发展&#xff0c;越来越多的企业开始利用网络开展各项工作业务&#xff0c;网络为企业的发展与生产生活提供了极大便利。但网络中的勒索病毒攻击企业服务器的事件频发&#xff0c;给企业的数据安全带来了严重威胁&#xff0c;数据安全问题一直是企业关…

pytorch CV入门 - 汇总

初次编辑&#xff1a;2024/2/14&#xff1b;最后编辑&#xff1a;2024/3/9 参考网站-微软教程&#xff1a;https://learn.microsoft.com/en-us/training/modules/intro-computer-vision-pytorch 更多的内容可以参考本作者其他专栏&#xff1a; Pytorch基础&#xff1a;https…

ArrayList 源码解析和设计思路

ArrayList 一、继承体系二、接口继承三、标记接口四、设计目的五、框架总体结构六、工作原理七、创建List对象初始化&#xff1f;还是add()添加元素初始化?七、add(E e)添加元素八、remove&#xff08;int index&#xff09;删除元素八、线程安全问题 一、继承体系 ArrayLis…

智慧城市革命,物联网技术如何改变城市治理与生活方式

随着科技的不断进步&#xff0c;智慧城市已经成为现代城市发展的重要方向之一。物联网技术作为智慧城市的重要支撑&#xff0c;正深刻改变着城市的治理模式和居民的生活方式。本文将探讨智慧城市革命&#xff0c;以及物联网技术如何改变城市治理与生活方式&#xff0c;同时介绍…

Python Web开发记录 Day12:Django part6 用户登录

名人说&#xff1a;东边日出西边雨&#xff0c;道是无晴却有晴。——刘禹锡《竹枝词》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1、登录界面2、用户名密码校验3、cookie与session配置①cookie与session②配置…

STM32CubeMX与HAL库开发教程八(串口应用/轮询/中断/DMA/不定长数据收发)

目录 前言 初识串口-轮询模式 串口中断模式收发 串口DMA模式 蓝牙模块与数据包解析 前言 前面我们简单介绍过串口的原理和初步的使用方式&#xff0c;例如怎么配置和简单的收发&#xff0c;同时我们对串口有了一个初步的了解&#xff0c;这里我们来深入的来使用一下串口 …

Linux服务器(RedHat、CentOS系)安全相关巡检shell脚本

提示&#xff1a;巡检脚本可以使用crontab定时执行&#xff0c;人工根据执行结束时间点统一收集报告文件即可。 #!/bin/bash# Define output file current_date$(date "%Y%m%d") # Gets the current date in YYYYMMDD format echo >server_security_inspection_r…

Leetcode 第 126 场双周赛 Problem C 替换字符串中的问号使分数最小(Java + 排序 + 贪心)

文章目录 题目思路Java 排序 贪心第一步&#xff1a;第二步&#xff1a;第三步&#xff1a; 复杂度Code 题目 Problem: 100249. 替换字符串中的问号使分数最小给你一个字符串 s 。s[i] 要么是小写英文字母&#xff0c;要么是问号 ‘?’ 。对于长度为 m 且 只 含有小写英文字…

任职资格中的一些面试题和知识点

目录 一、计算机数据结构基本概念理解&#xff1a;1. 数组基本概念优缺点以及如何改进常用的操作底层实现还有哪些容易问到的问题&#xff1a;关于数组的一些衍生数据结构和算法问题 2. 链表基本概念&#xff1a;链表的节点是什么&#xff1f;每个节点包含哪些信息&#xff1f;…

【计算机网络】https的工作原理以及和http的区别

目录 前言 1. HTTP协议存在的问题 2. 什么是HTTPS协议&#xff1f; 3. HTTP和HTTPS有哪些区别&#xff1f; 4. HTTPS的工作原理 加密方式 前言 在日常的Web项目练习中&#xff0c;我们会发现老师会让我们在打开服务器之后使用 http://localhost/...进行项目效果测试和预览…

2.26OS分类,中断(内,外),系统调用,操作系统结构、引导,虚拟机(两类VMM),进程

外核可以申请分配连续的磁盘块以支持频繁的随机访问&#xff0c;其它的方式是采用虚拟存储 分层结构

MongoDB yum安装教程

1 配置yum源 cat /etc/yum.repos.d/mongodb-org-6.0.repo ##################################################### [mongodb-org-6.0] nameMongoDB Repository baseurlhttps://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/6.0/x86_64/ gpgcheck1 enabled1 gpgkeyht…

iPhone 的健康数据采用的是 FHIR 传输格式

虽然感觉 FHIR 的数据传输格式还是有点繁琐的&#xff0c;但貌似现在也是唯一的事实上的标准。 通过 iPhone 健康上面查看的数据来看&#xff0c;有关健康的数据还是使用 FHIR 的数据传输格式。 不管怎么样&#xff0c;针对老旧的数据传输格式来看&#xff0c;FHIR 至少目前还是…

实现HBase表和RDB表的转化(附Java源码资源)

实现HBase表和RDB表的转化 一、引入 转化为HBase表的三大来源&#xff1a;RDB Table、Client API、Files 如何构造通用性的代码模板实现向HBase表的转换&#xff0c;是一个值得考虑的问题。这篇文章着重讲解RDB表向HBase表的转换。 首先&#xff0c;我们需要分别构造rdb和hba…

学习开发小程序的起航日记

2024年3月16日 不知不觉中三月份还只剩了一半的光景&#xff0c;我想写的内容还很多没有写&#xff0c;或者更应该说&#xff0c;是想积累的还有很多。现在最应该去完善Java的内容&#xff0c;可还是想先等等。想等搞清楚小程序部分&#xff0c;想等积累完小程序的内容。 这几…

PBOOTCMS在nginx虚拟主机location配置中添加规则

PBOOTCMS在nginx虚拟主机location配置中添加规则&#xff0c;规则如下&#xff1a; 1、X版本使用如下规则&#xff1a; location / { if (!-e $request_filename){ rewrite ^/(.*)$ /index.php/$1 last; } } 2、X版本使用如下规则&#xff1a; location / { if (!-e $reques…

Golang 泛型定义类型的时候前面 ~ 代表什么意思

先看代码&#xff0c;定义一个简单的泛型 c1 里面一个 int &#xff0c;定义一个函数goods 下面 main函数进行调用, 如果直接传int 类型是不会报错的,但是如果传自定义类型的b就会报错。 type c1 interface {int }func goods[T c1](a T) {fmt.Println(a) }type myint intfunc …

网络安全——关于防火墙

网络安全防火墙是很重要的部分&#xff0c;关于防火墙我们要知道&#xff0c;他默认所有流量都是黑名单&#xff0c;只有开启允许通过才可以。 我们通过一个实验来学防火墙命令。 防火墙要登录才能使用&#xff0c;用户名是admin,默认密码是Admin123&#xff0c;在第一次登录…

Visual Studio配置libtorch(cuda安装一步到位)

Visual Studio配置libtorch visual Studio安装cuDNN安装CUDAToolkit安装libtorch下载Visual Studio配置libtorch(cuda版本配置) visual Studio安装 visual Studio点击安装 具体的安装和配置过程这里就不进行细讲了&#xff0c;可以参考我这篇博客Visual Studio配置OpenCV(保姆…