序列化与反序列化

【一】序列化跟反序列化

在这里插入图片描述

# api接口开发,最核心最常见的一个过程就是序列化,所谓序列化就是把数据转换格式,序列化可以分两个阶段:【序列化值的是转换数据格式:序列化,返序列化】

# 序列化: 把我们识别的数据转换成指定的格式提供给别人
# 序列化: 表模型对象 ---> json格式字符串--->给前端

python后端:把python的对象【字典,列表,对象】---》转成json/xml格式字符串过程称之为序列化

例如:我们在django中获取到的数据默认是模型对象(qs/单个对象),但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人。

# 反序列化:把别人提供的数据转换/还原成我们需要的格式。
# 反序列化: json字符串--->保存到数据库

例如:前端js提供过来的json/xml数据,对于python而言就是字符串,我们需要进行反序列化换成模型类对象,这样我们才能把数据保存到数据库中

# js 如何把对象序列化成字符串:【JSON.stringify()】,把字符串饭序列化成对象:【JSON.parse()】

【1】序列化(Serialization)

​ 序列化是将对象转换为字节流或其他格式的过程。这通常涉及将对象的状态转换为可以存储或传输的格式,例如字节流、JSON、XML等。序列化的目的是将对象持久化,以便将其保存到文件中、通过网络发送给其他系统或在内存中进行传输。

​ 在序列化过程中,对象的属性值被提取,并根据指定的格式转换为序列化后的表示形式。在Java中,常用的序列化技术是Java序列化(Java Serialization)或JSON序列化(使用类库如Jackson或Gson),而在其他语言中也有类似的序列化技术。

【2】反序列化(Deserialization):

​ 反序列化是序列化的逆过程,即将序列化后的数据重新转换为对象的过程。在反序列化过程中,从序列化后的数据中提取信息,并根据原始对象的类定义重新构建对象,使其恢复到原始对象的状态。

​ 反序列化的目的是从序列化后的数据中重新创建对象,以便对其进行操作或在程序中使用。与序列化类似,反序列化也是在存储、通信或对象传输等场景中常见的操作。

小结

​ 总的来说,序列化和反序列化是在计算机中用于对象持久化、数据传输和通信的重要概念,它们允许将对象转换为字节流或其他格式,并在需要时重新构建对象。

具体示例

class TaskView(View):
    def post(self, request):
        # body gen body的使用方法
        print(request.body)
        ta = request.body
        da = json.loads(ta)
import pickle

# 定义一个对象
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

# 创建一个 Person 对象
person = Person("Alice", 30)

# 序列化对象到文件
with open("person.pickle", "wb") as file:
    pickle.dump(person, file)

# 从文件中反序列化对象
with open("person.pickle", "rb") as file:
    loaded_person = pickle.load(file)

# 打印反序列化后的对象属性
print("Name:", loaded_person.name)
print("Age:", loaded_person.age)

【二】FBV跟CBV的区别

FBV(Function-Based Views)和CBV(Class-Based Views)是两种不同的视图编写方式,它们有一些区别:

  1. 实现方式:
    • FBV(Function-Based Views): 使用函数来编写视图。每个视图是一个独立的函数,接收HTTP请求并返回HTTP响应。
    • CBV(Class-Based Views): 使用类来编写视图。每个视图是一个类,它可以包含多个方法来处理不同的HTTP请求方法(如GET、POST等)。
  2. 代码复用:
    • FBV: 函数的复用性较差,通常需要将相同的代码复制粘贴到不同的视图函数中。
    • CBV: 类的继承机制使得代码的复用性更好。你可以创建一个通用的基类视图,并在不同的子类视图中重写或添加特定的方法。
  3. 代码结构:
    • FBV: 每个视图通常都是一个独立的函数,因此在文件中可能会有多个视图函数,使得文件结构较为扁平。
    • CBV: 视图通常是一个类,因此在文件中可能会有多个视图类,使得文件结构更加模块化和组织化。
  4. 学习曲线:
    • FBV: 对于初学者来说,函数式视图可能更容易理解和上手,因为它们更接近于普通的Python函数。
    • CBV: 对于复杂的应用程序和视图逻辑,类视图提供了更多的结构化和组织化,但也需要一定的学习曲线。

​ 总的来说,FBV适用于简单的视图逻辑和快速开发,而CBV适用于需要更多结构化和可扩展性的项目。选择使用哪种视图方式取决于你的项目需求和个人偏好。

【三】

【1】FBV的接口具体示例

限制条件

  • 1 django —》创建表 Task 任务表

    • -id
      -task_id:唯一,不要用id自增–》时间戳/uuid python 中如何生成uuid 唯一(unique=True)
      -task_name:任务名 建立索引 (index=True)
      -task_time:任务执行时间
      -task_desc:任务描述
  • 2 使用mysql

  • 3 写 5个 接口

    • 查询所有,查询单个,新增一个,删除一个,修改一个
'''http://127.0.0.1:8000/task/add --->增加一个记录--》post请求方式
    http://127.0.0.1:8000/task/get/id--->查询这条记录-——》get请求方式
    http://127.0.0.1:8000/task/update/id--->更新这条记录》post请求方式
    http://127.0.0.1:8000/task/delete/id--->删除---》post请求方式
    http://127.0.0.1:8000/task/get/--->查询所有记录-——》get请求方式 '''
  • 4 使用requests模块,发送请求实现功能

    ''' -单线程
    -使用多线程 并发 增加记录
    	Thread '''
    

1.路由层

from django.contrib import admin
from django.urls import path
from Api01 import views

app_name = 'Api01'

urlpatterns = [
    path('admin/', admin.site.urls),

    path('task/add/', views.add_task, name='add_task'),

    path('task/get/<str:id>', views.get_task, name='get_task'),

    path('task/update/<str:id>', views.update_task, name='update_task'),

    path('task/delete/<int:id>', views.delete_task, name='delete_task'),

    path('task/get/', views.get_all_tasks, name='get_all_tasks'),

    path('add/', views.add),
]

2.视图层

from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from Api01.models import Task




# 添加任务
def add_task(request):
    if request.method == 'POST':
        try:
            task_id = request.POST.get('task_id')
            task_name = request.POST.get('task_name')
            task_time = request.POST.get('task_time')
            task_desc = request.POST.get('task_desc')
            Task.objects.create(task_desc=task_desc,task_time=task_time,task_name=task_name,task_id=task_id)
            return JsonResponse({'code': 100, 'msg': '创建成功'})
        except Exception as e:
            return JsonResponse({'code': 200, 'msg': '创建失败,错误信息:{}'.format(str(e))})
    else:
        return JsonResponse({'code': 200, 'msg': '请求方法错误'})


# 更改任务
# views.py

def get_task(request, id):
    try:
        task = Task.objects.get(id=id)
        result = {
            'task_id': task.task_id,
            'task_name': task.task_name,
            'task_time': task.task_time.strftime('%Y-%m-%d'),
            'task_desc': task.task_desc
        }
        return JsonResponse({'code': 100, 'msg': '查询成功', 'result': result})
    except Task.DoesNotExist:
        return JsonResponse({'code': 200, 'msg': '任务记录不存在'})

def add(requst):
    return render(requst, 'succeess.html')

# 更新一条任务记录
# views.py

def update_task(request, id):

    if request.method == 'POST':
        try:

            task_name = request.POST.get('task_name')

            task_time = request.POST.get('task_time')

            task_desc = request.POST.get('task_desc')

            Task.objects.filter(pk=id).update(task_desc=task_desc,task_time=task_time,task_name=task_name)

            return JsonResponse({'code': 100, 'msg': '更新成功'})
        except Task.DoesNotExist:
            return JsonResponse({'code': 200, 'msg': '任务记录不存在'})
        except Exception as e:
            return JsonResponse({'code': 200, 'msg': '更新失败,错误信息:{}'.format(str(e))})
    else:
        return JsonResponse({'code': 200, 'msg': '请求方法错误'})



# 删除一条任务记录
# views.py

def delete_task(request, id):
    if request.method == 'POST':
        try:
            task = Task.objects.get(id=id)
            task.delete()

            return JsonResponse({'code': 100, 'msg': '删除成功'})
        except Task.DoesNotExist:
            return JsonResponse({'code': 200, 'msg': '任务记录不存在'})
        except Exception as e:
            return JsonResponse({'code': 200, 'msg': '删除失败,错误信息:{}'.format(str(e))})
    else:
        return JsonResponse({'code': 200, 'msg': '请求方法错误'})


# 查询所有任务记录
def get_all_tasks(request):

    tasks = Task.objects.all()
    results = []
    for task in tasks:
        result = {
            'task_id': task.task_id,
            'task_name': task.task_name,
            'task_time': task.task_time.strftime('%Y-%m-%d'),
            'task_desc': task.task_desc
        }
        results.append(result)
    return JsonResponse({'code': 100, 'msg': '查询成功', 'results': results})


def delete(request,id):
    if request.method == 'POST':
        # 创建任务记录
        Task.objects.filter(id = int(id)).delete()
        return JsonResponse({'code': 100, 'msg': '创建成功'})

3.创建一个test测试接口文件

import random
import string
import threading
from threading import Thread
import time
import uuid

import requests
from fake_useragent import UserAgent
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'three.settings')

import django
django.setup()


headers = {
    'User-Agent': UserAgent().random,
}

base_url = 'http://127.0.0.1:8000/task/'

from datetime import date
from Api01.models import Task  # 导入你的Task模型

# 创建多个Task对象并保存到数据库
def add_tasks(task_name,task_desc):

    data = {
        "task_name": task_name,
        "task_desc": task_desc,
        "task_time": time.strftime('%Y-%m-%d'),
        "task_id":uuid.uuid1()  # 转换为字符串
    }

    url = "http://127.0.0.1:8000/task/add/"  # 请替换为你的服务器地址# 设置请求头
    response = requests.post(url=url, data =data)
    print(response.json())


def teadinfg(num_data):
    data_list = []
    for i in range(1,num_data + 1):
        task_name = f'Task {i}'
        task_desc = f'Task {i}'
        data = Thread(target=add_tasks,args=(task_name,task_desc))
        data_list.append(data)
        data.start()

    for data in data_list:
        data.join()

teadinfg(50)


# 查询
def get(id):
    url = base_url + f'get/{id}'
    response = requests.get(url=url, headers=headers)
    # print(response.text)
    print(response.json())
# get('6')

# 查询全部
def get_all():
    url = base_url + 'get/'
    response = requests.get(url=url, headers=headers)
    for info in response.json().get('results'):
        print(info)

# get_all()
# 增加
def add():
    task_name = input('task_name:>>>').strip()
    task_desc = input('task_desc:>>>').strip()
    data = {
        "task_name": task_name,
        "task_desc": task_desc,
        "task_time": time.strftime('%Y-%m-%d'),
        "task_id":uuid.uuid4()  # 转换为字符串
    }
    url = "http://127.0.0.1:8000/task/add/"  # 请替换为你的服务器地址# 设置请求头
    response = requests.post(url=url, data =data)
    print(response.json())

# add()

# 更新指定任务
def update(id):
    task_name = input('任务名称:>>>>').strip()
    task_time = time.strftime("%Y-%m-%d")
    task_desc = input('任务内容:>>>>').strip()
    data = {
        'task_name':task_name,
        'task_time':task_time,
        'task_desc':task_desc,
    }
    url = base_url + f'update/{id}'
    response = requests.post(url=url,headers=headers,data=data)
    # print(response.text)
    print(response.json())

# update('6')
# 删除指定任务
def delete(id):
    url = base_url + f'delete/{id}'
    response = requests.post(url=url, headers=headers)
    print(response.json())

# delete(12)

【2】CBV的接口具体示例

1.先创建一个UserLog表

class UserLog(models.Model):
    ip = models.CharField(max_length=100)
    time = models.DateTimeField(auto_now_add=True)
    method = models.CharField(max_length=10)
    path = models.CharField(max_length=255)
    user_agent = models.CharField(max_length=255)

    def __str__(self):
        return f"IP: {self.ip}, Time: {self.time}, Method: {self.method}, Path: {self.path}, User Agent: {self.user_agent}"

    class Meta:
        db_table = 'UserLog'

2.在创建一个路由分发

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('task_api/', include('task_api.urls')),
]

3.在子路由写一个正则表达式

from django.urls import path,include,re_path
from task_api.views import TaskView

urlpatterns = [
    re_path(r'(?P<id>\d+)?/?$', TaskView.as_view()),
]
  • (?P<id>\d+): 这是一个命名捕获组,使用 (?P<name>pattern) 的语法,其中 name 是捕获组的名称,pattern 是要匹配的模式。在这里,捕获组的名称是 id,它用于捕获一个或多个数字(\d+)。
  • ?: 这个问号表示前面的模式是可选的。换句话说,这个模式要么出现一次,要么不出现。
  • /?: 这表示匹配零个或一个斜杠 /。问号 ? 表示前面的斜杠是可选的。
  • $: 这个美元符号表示匹配字符串的结尾。

4.在视图层定义CBV

import json
from django.http import JsonResponse
from django.views import View
from .models import Task
import time
import uuid

class TaskView(View):
    def post(self, request):
        # body gen body的使用方法
        # print(request.body)
        # ta = request.body
        # da = json.loads(ta)


        task_name = request.POST.get('task_name')
        task_desc = request.POST.get('task_desc')
        task_time = time.strftime('%Y-%m-%d')
        task_id = uuid.uuid4()

        # 保存任务到数据库
        Task.objects.create(
            task_name=task_name,
            task_desc=task_desc,
            task_time=task_time,
            task_id=task_id
        )

        return JsonResponse({'message': 'Task 添加成功!'})

    def get(self, request, id=None):

        if id:
            try:
                task = Task.objects.get(id=id)
                print(task)
                data = {
                    'task_name': task.task_name,
                    'task_desc': task.task_desc,
                    'task_time': task.task_time,
                    'task_id': task.task_id
                }
                print(data)
                return JsonResponse(data)
            except Task.DoesNotExist:
                return JsonResponse({'error': 'Task 未能发现数据'}, status=404)
        else:
            tasks = Task.objects.all()
            data = [{'task_name': task.task_name, 'task_desc': task.task_desc, 'task_time': task.task_time, 'task_id': task.task_id} for task in tasks]
            return JsonResponse({'results': data})

    def put(self, request, id):
        try:
            print(request.body)
            data = request.body
            calssdatda = json.loads(data)
            print(calssdatda)
            print(type(calssdatda))
            # <class 'dict'>



            task = Task.objects.get(id=id)
            print(task)
            task_name = calssdatda.get('task_name')
            print(task_name)
            task_desc = calssdatda.get('task_desc')
            task_time = time.strftime('%Y-%m-%d')

            # 更新任务信息

            task.task_name = task_name
            task.task_desc = task_desc
            task.task_time = task_time
            task.save()

            return JsonResponse({'message': 'Task 更新成功'})
        except Task.DoesNotExist:
            return JsonResponse({'error': '未找到数据'}, status=404)


    def delete(self,request,id):
        try:
            Task.objects.filter(pk=id).delete()

            return JsonResponse({'message': 'Task 删除成功'})
        except Task.DoesNotExist:
            return JsonResponse({'error': '未找到数据'}, status=404)

5.写一个中间件进行预处理

from django.utils.deprecation import MiddlewareMixin


from task_api.models import UserLog
class LogMiddleware(MiddlewareMixin):
    def process_request(self, request):
        # 获取请求相关信息
        # 通过访问 request.META 字典,获取了请求的客户端 IP 地址。'REMOTE_ADDR'
        # 是一个 HTTP 头的键,它存储了客户端的 IP 地址。这个 IP 地址可以用来识别请求的来源。
        ip = request.META.get('REMOTE_ADDR')
        print( request.META)
        # 获取了请求的方法
        method = request.method
        # 获取了请求的路径。request.get_full_path() 方法返回了当前请求的完整路径,包括查询参数(如果有)。
        path = request.get_full_path()
        # 获取了客户端的用户代理(User-Agent)。用户代理是一个字符串,用于标识客户端浏览器或其他用户代理程序的信息,如浏览器类型、版本号等。
        user_agent = request.META.get('HTTP_USER_AGENT')

        # 将信息记录到数据库中
        UserLog.objects.create(ip=ip, method=method, path=path, user_agent=user_agent)

6.settings.py进行

  • 添加’task_api.middleware.LogMiddleware',ALLOWED_HOSTS = ["*"]
ALLOWED_HOSTS = ["*"]


MIDDLEWARE = [

    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'task_api.middleware.LogMiddleware',
]

7.别人访问你的ip地址

  • 先打开cmd

  • # ipconfig
    

在这里插入图片描述

  • 在检查本地防火墙是否打开

  • 在这里插入图片描述

这些只是准备工作

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

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

相关文章

使用frp实现内网穿透教程

文章目录 简介frp 是什么&#xff1f;为什么选择 frp&#xff1f; 概念工作原理代理类型 内网穿透教程服务端安装和配置本地Windows&#xff08;客户端&#xff09;安装和配置本地Linux虚拟机&#xff08;客户端&#xff09;安装和配置使用 systemd 管理服务端注意事项 简介 f…

openapi3和openapi2的注解区别

最近在该项目&#xff0c;发现openapi3版本相比起2版本已经发生了很大的变化&#xff0c;原来的注解全部失效了&#xff0c;取而代之的是新的注解

基于Transformer深度学习的翻译模型(英->中)源码系统

第一步&#xff1a;Transformer介绍 Transformer是一种基于注意力机制的序列到序列模型&#xff0c;它在机器翻译任务中表现出色并逐渐成为自然语言处理领域的主流模型。Transformer模型的核心思想是使用自注意力机制&#xff08;self-attention&#xff09;来捕捉输入序列中各…

【Java系列】给大家出一些JavaSE基础第七天的内容案例 , 让大家更好的理解与掌握

面向对象 好的&#xff0c;以下是一些Java面向对象基础的案例&#xff1a; 案例一 1. 定义一个学生类Student&#xff0c;包含姓名、年龄、性别等属性&#xff0c;以及学习、吃饭等行为。然后创建一个学生对象&#xff0c;调用其行为方法。 public class Student {private St…

Linux驱动开发:深入理解I2C时序

目录标题 I2C简介I2C时序关键点Linux内核中的I2C时序处理I2C适配器I2C算法I2C核心 代码示例&#xff1a;I2C设备访问调试I2C时序问题 在Linux驱动开发中&#xff0c;理解和正确处理I2C时序对于确保I2C设备正常工作至关重要。本文将详细介绍I2C通信协议的时序特征&#xff0c;并…

西门子程序专业备份软件BUDdy for S7和使用说明

西门子程序专业备份软件BUDdy for S7和使用说明

基于Springboot的web后端开发三层架构上手实操

引言 我们拿到了xml文件 我们要将将xml文件中的数据加载并解析 完成数据的处理 并且返回给前端页面(result格式) 1.将xml文件放在resources目录下 xml是我们需要解析的文件 查看xml文件 2.在springboot中引入dom4j依赖 解析xml需要在springboot中引入dom4j依赖 这边我们…

Docker——部署LNMP架构

目录 一、LNMP架构概述 1.项目环境 2.服务器环境 3.需求 二、搭建Linux系统基础镜像 三、部署Nginx 1.建立工作目录 2.编写Dockerfile脚本 3.准备Nginx.conf配置文件 4.生成镜像 5.创建自定义网络 6.启动镜像容器 7.验证Nginx 三、部署Mysql 1.建立工作目录 2.编…

【STM32+HAL】读取电池电量

一、准备工作 有关CUBEMX的初始化配置&#xff0c;参见我的另一篇blog&#xff1a;【STM32HAL】CUBEMX初始化配置 有关定时器触发ADC模式配置&#xff0c;详见【STM32HAL】ADC采集波形实现 有关软件触发ADC模式配置&#xff0c;详见【STM32HAL】三轴按键PS2摇杆 二、所用工具…

Python赋值运算符

目录 赋值运算符 将值赋给变量&#xff1a; 做加法运算之后完成赋值&#xff1a; 做减法运算之后完成赋值&#xff1a;- 做乘法运算之后完成赋值&#xff1a;* 做除法运算之后完成赋值&#xff1a;/ 做整除运算之后完成赋值&#xff1a;// 做幂次运算之后完成赋值&#xff1a;*…

自动驾驶框架 UniAD环境部署

感谢大佬们的开源工作 UniAD-github地址-YYDS更多bev算法部署参考如果您觉得本帖对您有帮助&#xff0c;感谢您一键三连支持一波^_^ 统一自动驾驶框架 (UniAD) &#xff0c;第一个将全栈驾驶任务整合到一个深度神经网络中的框架&#xff0c;并可以发挥每个子任务以及各个模块的…

【MySQL 数据宝典】【索引原理】- 004 优化示例-join in exist

一、join 优化原理 1.1 基本连接方式介绍 JOIN 是 MySQL 用来进行联表操作的&#xff0c;用来匹配两个表的数据&#xff0c;筛选并合并出符合我们要求的结果集。 1.2 驱动表的定义 1.2.1 什么是驱动表 多表关联查询时,第一个被处理的表就是驱动表,使用驱动表去关联其他表.驱…

基于springboot的考勤管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

Zynq 7000 系列中成功执行BootROM的条件

Zynq 7000设备的启动需要正确的电压序列和I/O引脚控制。BootROM的流程由复位类型、启动模式引脚设置以及启动映像来控制。BootROM对所选启动设备的引脚连接有特定的要求。 Zynq 7000 SoC设备具有电源、时钟和复位要求&#xff0c;这些要求必须得到满足&#xff0c;才能成功执行…

java:SpringBootWeb请求响应

Servlet 用java编写的服务器端程序 客户端发送请求至服务器 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器 服务器将响应返回给客户端 javaweb的工作原理 在SpringBoot进行web程序开发时,内置了一个核心的Servlet程序DispatcherServlet,称之…

RocketMQ快速入门:namesrv、broker、dashboard的作用及消息发送、消费流程(三)

0. 引言 接触rocketmq之后&#xff0c;大家首当其冲的就会发现需要安装3个组件&#xff1a;namesrv, broker, dashboard&#xff0c;其中dashboard也叫console&#xff0c;为选装。而这几个组件之前的关系是什么呢&#xff0c;消息发送和接收的过程是如何传递的呢&#xff0c;…

应用实战 | 别踩白块小游戏,邀请大家来PK挑战~

“踩白块会输”是一个简单的微信小程序游戏&#xff0c;灵感来自当年火热的别踩白块游戏&#xff0c;程序内分成三个模块&#xff1a;手残模式、经典模式和极速模式&#xff0c;分别对应由易到难的三种玩法&#xff0c;可以查看游戏排名。动画效果采用JS实现&#xff0c;小程序…

Spark-机器学习(6)分类学习之支持向量机

在之前的文章中&#xff0c;我们学习了分类学习之朴素贝叶斯算法&#xff0c;并带来简单案例&#xff0c;学习用法。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢…

基于YOLOV8+Pyqt5无人机航拍太阳能电池板检测系统

1.YOLOv8的基本原理 YOLOv8是一种前沿的目标检测技术&#xff0c;它基于先前YOLO版本在目标检测任务上的成功&#xff0c;进一步提升了性能和灵活性&#xff0c;在精度和速度方面都具有尖端性能。在之前YOLO 版本的基础上&#xff0c;YOLOv8 引入了新的功能和优化&#xff0c;…

SpringBoot 常用注解总结超详细(面试)

目录 一、组件相关&#x1f381; Controller Service Repository Component 二、依赖注入相关&#x1f349; Autowired Resource 根据类型注入&#xff08;By Type&#xff09; 根据名称注入&#xff08;By Name&#xff09; 区别 Qualifier Resource 和 Qualifie…
最新文章