一、Django的序列化方法

1、为什么要用序列化组件

做前后端分离的项目,我们前后端数据交互一般都选择JSON,JSON是一个轻量级的数据交互格式。
那么我们给前端数据的时候都要转成json格式,那就需要对我们从数据库拿到的数据进行序列化。

2、表的构建

  1. CHOICES = ((1, "python"), (2, "linux"), (3, "go"))
  2.  
  3. # 书籍表
  4. class Book(models.Model):
  5. title = models.CharField(max_length=64)
  6. category = models.IntegerField(choices=CHOICES) # 书籍分类
  7. pub_time = models.DateField()
  8. publisher = models.ForeignKey(to="Publisher")
  9. authors = models.ManyToManyField(to="Author")
  10.  
  11. class Meta:
  12. verbose_name = '书籍'
  13. verbose_name_plural = verbose_name
  14.  
  15. def __str__(self):
  16. return self.title
  17.  
  18. # 出版社表
  19. class Publisher(models.Model):
  20. title = models.CharField(max_length=64)
  21.  
  22. class Meta:
  23. verbose_name = '出版社'
  24. verbose_name_plural = verbose_name
  25.  
  26. def __str__(self):
  27. return self.title
  28.  
  29. # 作者表
  30. class Author(models.Model):
  31. name = models.CharField(max_length=32)
  32. class Meta:
  33. verbose_name = '作者'
  34. verbose_name_plural = verbose_name
  35.  
  36. def __str__(self):
  37. return self.name

3、希望构建的字典格式

  1. book_list = [
  2. {
  3. "id": 1,
  4. "title": "",
  5. "publisher": { # 外键
  6. "id": 1
  7. "title": ""
  8. },
  9. "authors": [{}, {}] # 多对多
  10. },
  11. {
  12. "id": 2,
  13. "title": "",
  14. "publisher": { # 外键
  15. "id": 1
  16. "title": ""
  17. },
  18. "authors": [{}, {}] # 多对多
  19. },
  20.  
  21. ]

4、方法一

  1. Django中使用Json模块序列化
  2. class BooksView(views.View):
  3. def get(self, request):
  4. book_queryset = Book.objects.values("id", "title", "pub_time", "publisher")
  5. book_list = list(book_queryset) # 把queryset类型转换成列表
  6. # 如果我们需要取外键关联的字段信息 需要循环获取外键 再去数据库查然后拼接成我们想要的
  7. ret = []
  8. for book in book_list:
  9. publisher_obj = Publisher.objects.filter(id=book["publisher"]).first()
  10. # 修改原字典中的publisher对应的值
  11. book["publisher"] = {
  12. "id": publisher_obj.id,
  13. "title": publisher_obj.title
  14. }
  15. # 把新的字典追加到一个空列表中
  16. ret.append(book)
  17. ret = json.dumps(ret, ensure_ascii=False, cls=MyJson)
  18. return HttpResponse(ret)
  19.  
  20. # json不能序列化时间字段,重写JSONEncoder里面的default方法解决
  21. class MyJson(json.JSONEncoder):
  22. def default(self, field):
  23. if isinstance(field, datetime.datetime):
  24. return field.strftime('%Y-%m-%d %H:%M:%S')
  25. elif isinstance(field, datetime.date):
  26. return field.strftime('%Y-%m-%d')
  27. else:
  28. return json.JSONEncoder.default(self, field)

5、方法二

  1. 使用JsonResponse,自动帮我们重写了JSONEncoder里面的default方法,解决时间字段的问题
  2. class BooksView(views.View):
  3. def get(self, request):
  4. book_queryset = Book.objects.values("id", "title", "pub_time", "publisher")
  5. book_list = list(book_queryset) # 把queryset类型转换成列表
  6. # 如果我们需要取外键关联的字段信息 需要循环获取外键 再去数据库查然后拼接成我们想要的
  7. ret = []
  8. for book in book_list:
  9. publisher_obj = Publisher.objects.filter(id=book["publisher"]).first()
  10. # 修改原字典中的publisher对应的值
  11. book["publisher"] = {
  12. "id": publisher_obj.id,
  13. "title": publisher_obj.title
  14. }
  15. # 把新的字典追加到一个空列表中
  16. ret.append(book)
  17. return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})

6、方法三

  1. 使用Django自带的序列化模块
  2. from django.core import serializers
  3.  
  4. # 能够得到我们要的效果 结构有点复杂
  5. class BooksView(views.View):
  6. def get(self, request):
  7. book_queryset = Book.objects.all()
  8. ret = serializers.serialize("json", book_queryset, ensure_ascii=False)
  9. return HttpResponse(ret)

二、DRF序列化的介绍

1、介绍

  1. 下载DRF模块:pip install djangorestframework
  2. 导入:
  3. from rest_framework.views import APIView
  4. from rest_framework.response import Response
  5.  
  6. 使用DRF默认的页面,需要在settingsAPP注册rest_framework
  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'rest_framework',
  9. ]
  1. 首先,我们要用DRF的序列化,就要遵循DRF框架的一些标准,
  2.   -- Django我们CBV继承类是View,现在DRF我们要用APIView
  3.   -- Django中返回的时候我们用HTTPResponseJsonResponserender DRF我们用Response

2、APIView跟View区别

  1. -- APIView继承了View
  2. -- APIViewas_view方法实现了csrf中间件的豁免(用DRF不需要再把settingscsrf中间件注释掉了)
  3. -- 重新封装了request
  4. request._request可以拿到旧的request
  5. request.query_params 旧的request.GET_request.GET
  6. request.data 除了GET请求外的所有的数据,_request.POST_request.FILES
    -- 序列化器对象.data
      存放序列化好的数据
      校验通过的数据存放到validated_data里,最后也会序列化封装到序列化对象.data里面返回给前端
      校验不通过,错误信息存到序列化对象.errors里面
    -- DRF有自己的序列化模块
      from rest_framework import serializers
  7. -- Response
  8.   继承了HttpResponse
  9.   携带HTTP标准状态码
  10.   做模板的渲染

3、使用方法

  1. -- 序列化(传数据到前端)
  2. -- 声明一个序列化器
  3. class BookSerializer(serializers.Serializer):
  4. id = serializers.IntegerField(required=False)
  5. title = serializers.CharField(max_length=32)
  6. pub_time = serializers.DateField()
  7. -- 视图里序列化我们的queryset或者某个对象
  8. # queryset需要声明many=True
  9. ser_obj = BookSerializer(queryset, many=True)
  10. # 具体的某个的对象则不需要声明
  11. ser_obj = BookSerializer(book_obj)
  12. return Response(ser_obj.data)
  13. -- 实现流程
  14. -- 如果指定了many=True
  15. -- queryset当成可迭代对象去循环 得到每个模型对象
  16. -- 把每个模型对象放入序列号器进行序列化
  17. -- 进行字段匹配 匹配上的字段进行序列化 匹配不上丢弃
  18. -- 必须满足序列化的所有字段要求
  19.  
  20. -- 反序列化(从前端获取数据)
  21. -- 获取前端传过来的数据
  22. -- 用序列化器进行校验
  23. # 新增一条数据
  24. ser_obj = BookSerializer(data=request.data)
  25. # 编辑某条数据
  26. # instance编辑哪个对象,data前端传过来要跟新的某些字段数据,partial表示允许部分跟新
  27. ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
  28. if ser_obj.is_valid():
  29. ser_obj.save()# 调用create/update方法
  30. return Response(ser_obj.data)
  31. else:
  32. return Response(ser_obj.errors)
  33. -- create方法
  34. create方法里用ORM操作创建新对象
  35. -- update方法
  36. update方法里用ORM操作创编辑对象

4、注意事项

  1. 1. 外键和多对多字段的序列化需要额外再设置序列化器
  2. 2. 序列化
  3. 序列化器的参数是querysetmany
  4. 3. 反序列化
  5. 序列化器的参数是data=提交上来的数据
  6. 4. 序列化器字段类型不统一的情况
  7. 反序列化要用的一些字段通过一些参数跟序列化区分开
  8. -- required=False
  9. -- read_only=True
  10. -- write_only=True
  11.  
  12. 5. 反序列化的验证
  13. is_valid()    --> 校验数据
  14. post请求中的save() --> 调用序列化器的create方法
      put请求中的save() --> 调用序列化器的update方法

三、DRF序列化示例

1、声明序列化器

  1. # serializers.py文件
  2.  
  3. from rest_framework import serializers
  4. from libsys.models import Book
  5.  
  6. CHOICES = ((1, "python"), (2, "linux"), (3, "go"))
  7.  
  8. # 继承serializers.Serializer
  9. class PublisherSerializer(serializers.Serializer):
  10. id = serializers.IntegerField()
  11. title = serializers.CharField(max_length=64)
  12.  
  13. class AuthorSerializer(serializers.Serializer):
  14. id = serializers.IntegerField()
  15. name = serializers.CharField(max_length=32)
  16.  
  17. # 字段的声明和models相类似
  18. class BookSerializer(serializers.Serializer):
  19. # POST校验的时候required=False声明不需要校验这个字段
  20. id = serializers.IntegerField(required=False)
  21.  
  22. title = serializers.CharField(max_length=64)
  23. pub_time = serializers.DateField()
  24.  
  25. # 选择字段,显示的是数字
  26. # category = serializers.ChoiceField(choices=CHOICES)
  27. # 把选择字段显示成字符类型,source参数后面跟的是ORM操作
  28. # read_only=True表示这个字段只在渲染前端的时候使用
  29. category = serializers.CharField(source='get_category_display', read_only=True)
  30. # write_only=True表示这个字段只在POST提交数据,做校验的时候使用
  31. post_category = serializers.IntegerField(write_only=True)
  32.  
  33. # 外键需要设置额外的序列化器对它进行序列化
  34. publisher = PublisherSerializer(read_only=True)
  35. publisher_id = serializers.IntegerField(write_only=True)
  36.  
  37. # 多对多字段需要设置额外的序列化器对它进行序列化,且声明many=True
  38. authors = AuthorSerializer(many=True, read_only=True)
  39. author_list = serializers.ListField(write_only=True)
  40.  
  41. def create(self, validated_data): # validated_data是通过校验的数据,最后也会封装到data里面
  42. #通过ORM操作给Book表增加数据
  43. book_obj = Book.objects.create(title=validated_data["title"], pub_time=validated_data["pub_time"],
  44. category=validated_data["post_category"], publisher_id=validated_data["publisher_id"])
  45. book_obj.authors.add(*validated_data["author_list"])
  46. return book_obj
  47.  
  48. def update(self, instance, validated_data):
  49. # 通过ORM操作给Book表编辑数据
  50. # instance就是book_obj
  51. instance.title = validated_data.get("title", instance.title)
  52. instance.pub_time = validated_data.get("pub_time", instance.pub_time)
  53. instance.category = validated_data.get("post_category", instance.category)
  54. instance.publisher_id = validated_data.get("publisher_id", instance.publisher_id)
  55. if validated_data.get("author_list", False):
  56. instance.authors.set(validated_data["author_list"])
  57. instance.save()
  58. return instance

2、在视图函数中调用

  1. from libsys.models import Book, Publisher, Author
  2. from rest_framework.views import APIView
  3. from rest_framework.response import Response
  4. from .serializers import BookSerializer
  5.  
  6. # Create your views here.
  7.  
  8. # 书籍列表
  9. class BookView(APIView):
  10. def get(self, request):
  11. book_queryset = Book.objects.all()
  12. # 声明一个序列化器
  13. # 用序列化器去序列化queryset(queryset有多个对象的时候,需要声明many=True)
  14. # 把数据提交到序列化器,跟序列化器的字段进行匹配,匹配成功就进行序列化
  15. ser_obj = BookSerializer(book_queryset, many=True)
  16. return Response(ser_obj.data)
  17.  
  18. # 新增书籍
  19. def post(self, request):
  20. # 前端传过来的数据应该也是这样的
  21. # {"id""title",
  22. # category: 1
  23. # publisher: 1
  24. # authors: [1, 2]
  25. # }
  26.  
  27. # 获取前端传过来的数据
  28. book_obj = request.data
  29. # 用序列化器做校验
  30. ser_obj = BookSerializer(data=book_obj)
  31. if ser_obj.is_valid():
  32. # 校验通过,新增书籍
  33. ser_obj.save() # 这里的save方法会去调用序列化器的create方法
  34. print(ser_obj.validated_data) # validated_data是通过校验的数据,也会封装到data里面
  35. return Response(ser_obj.data)
  36. # 校验不通过返回错误信息
  37. return Response(ser_obj.errors)
  38.  
  39. # 编辑书籍
  40. class BookEditView(APIView):
  41. def get(self, request, id):
  42. book_obj = Book.objects.filter(pk=id).first()
  43. ser_obj = BookSerializer(book_obj)
  44. return Response(ser_obj.data)
  45.  
  46. def put(self, request, id):
  47. book_obj = Book.objects.filter(id=id).first()
  48. ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
  49. if ser_obj.is_valid():
  50. ser_obj.save()
  51. return Response(ser_obj.data)
  52. return Response(ser_obj.errors)

四、验证

1、 单个字段的验证(局部钩子)

  1. class BookSerializer(serializers.Serializer):
  2. id = serializers.IntegerField(required=False)
  3. title = serializers.CharField(max_length=64)
  4. 其他字段...
  5.  
  6. # 局部钩子方法:validate_字段名,value 是提交过来的这个字段的数据
  7. def validate_title(self, value):
  8. # 定义校验规则:标题必须含有python、linux、go
  9. course_list = ['python', 'linux', 'go']
  10. for course in course_list:
  11. if course in value.lower():
  12. return value
  13. else:
  14. raise serializers.ValidationError('输入的书籍名不合法')

2、 多个字段的验证(全局钩子)

  1. class BookSerializer(serializers.Serializer):
  2. post_category = serializers.IntegerField(write_only=True)
  3. publisher_id = serializers.IntegerField(write_only=True)
  4. 其他字段...
  5.  
  6. # 全局钩子方法:validate,attrs 是前端传过来的所有的数据组成的字典
  7. def validate(self, attrs):
  8. # 定义校验规则:书籍分类和作者id不能超过3
  9. if attrs['post_category'] > 3 or attrs['publisher_id'] > 3:
  10. raise serializers.ValidationError('输入的图书分类或作者不存在')
  11. return attrs

3、 自定义校验规则

  1. def my_validate(value):
  2. if '周星星' in value:
  3. raise serializers.ValidationError('输入的书籍太帅,不合法')
  4. return value
  5.  
  6. class BookSerializer(serializers.Serializer):
  7. id = serializers.IntegerField(required=False)
  8. # validators声明校验的规则
  9. title = serializers.CharField(max_length=64, validators=[my_validate,])

4、校验的权重

自定义校验 > 局部钩子 > 全局钩子

五、ModelSerializer

1、介绍

跟Django的Form组件类似,我们使用DRF进行前后端数据交互,有很多需要序列化和反序列化的字段都跟models模型相关,
那么,DRF也给我们提供了跟模型紧密相关的序列化器:ModelSerializer
-- 继承serializers.ModelSerializer
-- 它和Form有点类似
-- 它会根据模型自动生成一组字段
-- 它默认实现了.update()以及.create()方法

2、定义ModelSerializer序列化器

  1. class BookSerializer(serializers.ModelSerializer):
  2. class Meta:
  3. model = Book
  4. fields = "__all__"
  5. # fields = ["id", "title", "pub_time"]
  6. # exclude = ["user"]
  7. # 分别是所有字段 包含某些字段 排除某些字段

3、外键关系的字段

  1. 当序列化类META中定义了depth时,这个序列化类中引用字段(外键)则自动变为只读
  2.  
  3. class BookSerializer(serializers.ModelSerializer):
  4. class Meta:
  5. model = Book
  6. fields = "__all__"
  7. # fields = ["id", "title", "pub_time"]
  8. # exclude = ["user"]
  9. # 分别是所有字段 包含某些字段 排除某些字段
  10.  
  11. # depth 代表找嵌套关系的第几层
  12. depth = 1

4、META中的其他参数

  1. class BookSerializer(serializers.ModelSerializer):
  2. class Meta:
  3. model = Book
  4. fields = "__all__"
  5. # fields = ["id", "title", "pub_time"]
  6. # exclude = ["user"]
  7. # 分别是所有字段 包含某些字段 排除某些字段
  8.  
  9. # depth 代表找嵌套关系的第几层
  10. depth = 1
  11.  
  12. # 只读字段
  13. read_only_fields = ["id"]
  14.  
  15. # 给某些字段设置额外参数
  16. extra_kwargs = {"title": {"validators": [my_validate,]}}

5、SerializerMethodField方法字段

  1. 外键关联的对象有很多字段我们是用不到的,如果都传给前端会有数据冗余,
  2. 就需要我们自己去定制序列化外键对象的哪些字段。
  3.  
  4. 使用了方法字段,它会自动去找对应的钩子函数(get_字段名),这个方法字段展示的值就是钩子函数的返回值
  5. 钩子函数的参数obj:就是序列化的每个模型对象 book_obj
  6.  
  7. class BookSerializer(serializers.ModelSerializer):
  8. # 方法字段
  9. # SerializerMethodField 会去找钩子方法 钩子方法的返回值给这个字段
  10. # 钩子函数:get_字段名称
  11. category_text = serializers.SerializerMethodField(read_only=True)
  12. publisher_info = serializers.SerializerMethodField(read_only=True)
  13. author_info = serializers.SerializerMethodField(read_only=True)
  14.  
  15. def get_category_text(self, obj):
  16. # obj就是序列化的每个模型对象 book_obj
  17. return obj.get_category_display()
  18.  
  19. def get_publisher_info(self, obj):
  20. return {"id": obj.publisher_id, "title": obj.publisher.title}
  21.  
  22. def get_author_info(self, obj):
  23. return [{"id": author.id, "name": author.name} for author in obj.authors.all()]
  24.  
  25. class Meta:
  26. model = Book
  27. fields = "__all__"

6、完整的ModelSerializer思路

  1. 因为depth会让我们外键变成只读,所以一般来说我们不用它,
  2. 因为如果是前端发数据过来(post,put等),我们对外键、多对多等字段进行验证是验证其在数据库的中真实值,
  3. 因此,把ModelSerializer序列化器fields代表的字段应该用于反序列化,而对序列化到前端的外键、多对多等字段的数据,
  4. 我们可以使用SerializerMethodField对其进行处理后展示到前端。
  5.  
  6. class BookSerializer(serializers.ModelSerializer):
  7. # 方法字段
  8. category_text = serializers.SerializerMethodField(read_only=True)
  9. publisher_info = serializers.SerializerMethodField(read_only=True)
  10. author_info = serializers.SerializerMethodField(read_only=True)
  11. # 方法字段的值,取决于它对应的方法字段的钩子函数的返回值
  12. def get_category_text(self, obj):
  13. # obj就是序列化的每个模型对象 book_obj
  14. return obj.get_category_display()
  15.  
  16. def get_publisher_info(self, obj):
  17. return {"id": obj.publisher_id, "title": obj.publisher.title}
  18.  
  19. def get_author_info(self, obj):
  20. return [{"id": author.id, "name": author.name} for author in obj.authors.all()]
  21.  
  22. class Meta:
  23. model = Book
  24. fields = "__all__"
  25. # fields = ["id", "title", "pub_time"]
  26. # exclude = ["user"]
  27. # 分别是所有字段 包含某些字段 排除某些字段
  28.  
  29. # depth 代表找嵌套关系的第几层
  30. # depth = 1
  31.  
  32. extra_kwargs = {
  33. "category": {'write_only': True},
  34. "publisher": {'write_only': True},
  35. "authors": {'write_only': True},
  36. }

DRF初识与序列化的更多相关文章

  1. DRF中的序列化器

    DRF中的序列化器详细应用   视图的功能:说白了就是接收前端请求,进行数据处理 (这里的处理包括:如果前端是GET请求,则构造查询集,将结果返回,这个过程为序列化:如果前端是POST请求,假如要对数 ...

  2. 【DRF框架】序列化组件

    DRF框架的序列化组件 在前后端分离的应用模式中,后端仅返回前端所需的数据,返回的数据类似是JSON,因此需要使用序列化组件进行序列化再将数据返回 使用JsonResponse做序列化 #  使用Js ...

  3. 经历了源码的痛苦,掌握DRF的核心序列化器

    目录 DRF的核心--序列化器 序列化器 什么是序列化和反序列化? 序列化 序列化demo 字段类型 字段参数 序列化自定制返回字段 方法一:在序列化类(serializers.py)中写 方法二:在 ...

  4. DRF分阶段序列化细化实例

    DRF是分两阶段进行的. 如果是API接收数据,则是先进行Parser,将外界接收的bytes数据分析成python数据类型,其间涉及encoding操作,再进行序列化,将python数据类型保存进数 ...

  5. drf:筛选,序列化

    1.基础 restful规范: - url:一般用名词 http://www.baidu.com/article (面向资源编程) - 根据请求方式的不同做不同操作:get,post,put,dele ...

  6. DRF项目之序列化器和视图重写方法的区别

    我们,都知道,DRF框架是一款高度封装的框架. 我们可以通过重写一些方法来实现自定义的功能. 今天,就来说说在视图中重写和序列化器中重写方法的区别. 在视图中重写方法: 接收请求,处理数据(业务逻辑) ...

  7. DRF框架之序列化器初体验

    首先,我们需要明白序列化和反序列化的过程指的是什么. 序列化操作:将模型数据 ---> 字典数据 --->JSON数据(响应JSON数据的操作) 反序列化操作:将JSON数据 ---> ...

  8. 二.drf之使用序列化编写视图

    总结:两功能序列化: a.拿到queryset --->idc = Idc.objects.all() b.将queryset给序列化成类---->serializer = IdcSeri ...

  9. day71:drf:API接口&Restful API规范&Django Rest Framework&drf中的序列化和反序列化功能

    目录 1.web应用模式 2.API接口 3.Restful API规范 4.序列化 5.Django Rest Framework 1.drf的简单介绍 2.drf的特点 3.如何安装drf 4.d ...

随机推荐

  1. vue2.x 在引用插件的时候,npm run dev跑正常 ,npm run build 报错vue-cli Unexpected token: punc (() [

    这是因为,引用的插件在node_modules里,并不在vue-cli的es6编译范围内,所以语法报错,修改方法:

  2. Html和Css学习笔记-html进阶-html5属性

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 此篇博客是我的复习笔记,html和css学的时间太久了,忘得差不多了,最近要使用一下,所以重新打开html的书略读,后记录了标签 ...

  3. ArcGIS API for JavaScript 4.2学习笔记[20] 使用缓冲区结合Query对象进行地震点查询【重温异步操作思想】

    这个例子相当复杂.我先简单说说这个例子是干啥的. 在UI上,提供了一个下拉框.两个滑动杆,以确定三个参数,使用这三个参数进行空间查询.这个例子就颇带空间查询的意思了. 第一个参数是油井类型,第二个参数 ...

  4. 虚拟机下centos7.x简易命令大全与试玩体验

    OS: liunxversion: centos7.xdate: 2019-01-18 1. cd  /                               : 进入服务器根目录2. cd . ...

  5. 使用 Nexus Repository Manager 搭建 npm 私服

    目录 环境 下载与安装 添加npm仓库 配置与验证npm仓库 发布自己的包 Nexus开启启动 脚注 环境 windows10(1803) Nexus Repository Manager OSS 3 ...

  6. Windows系统下搭建Git本地代码库

    近由于工作需要,要把工作代码做一下版本管理.工作代码也不方便放到github上,也不想付费建私密库,公司也没几个人,所以就想着搭建一个本地Git版本库,来做版本管理.搭建过程如下. 系统环境:Dell ...

  7. c#核心基础-委托

    委托是一个类型.C#中的委托是面向对象的,并且它是类型安全的 当创建委托实例的时候,创建的实例会包含一个调用列表,在调用列表中可以包含多个方法.每个方法称作一个调用实体.调用实体可以是静态方法,也可以 ...

  8. c/c++ 多线程 等待一次性事件 future概念

    多线程 等待一次性事件 future概念 背景:有时候,一个线程只等待另一个线程一次,而且需要它等待的线程的返回值. 案例:滴滴叫车时,点完了叫车按钮后,叫车的后台线程就启动了,去通知周围的出租车.这 ...

  9. 【Eclipse】springMVC介绍与配置

    SpringMCV介绍: Spring MVC是一种基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动的,也就是使用 ...

  10. Redis可视化工具 Redis Desktop Manager

    1.前言 从接触Redis也有两年,平时就使用它来做缓存层,它给我的印象就是很强大,内置的数据结构很齐全,加上Redis5.0的到来,新增了很多特色功能.而Redis5.0最大的新特性就是多出了一个数 ...