DjangoRestFramework之DRF初识

news/发布时间2024/5/10 23:54:12

一.Web应用两种开发模式

1、前后端不分离模式

也叫前后端混合开发模式, 需要后端写模板语言(DTL), 返回的是HTML页面,比如有BBS项目,图书管理系统。

在前后端不分离的项目中,模板渲染通常是在后端完成的。这种项目结构中,后端负责处理业务逻辑、与数据库交互,并最终生成 HTML 页面,将数据填充到模板中,然后将完整的 HTML 页面发送给浏览器进行渲染。
image

2、前后端不分离

从程序角度来看:

  • 1个Django程序,接收请求+处理+HTML模版+用户返回
  • 2个程序:
    • 前端:vue.js/react.js/angular.js
    • 后端:Django + DjangoRestFramework

从专业度角度来看:

  • 前端,专门写前端代码 + 部署 + 版本管理 + ajax请求获取
  • 后端,API接口文档,只专注于写后端接口, 返回 json, xml格式数据

在前后端分离的项目中,模板渲染通常是在前端完成。在这种项目结构下,后端主要负责提供数据接口(通常是 JSON 格式),而前端则负责将这些数据获取并渲染到页面上。

image

二、什么是drf?作用是什么

1、简介

DRF ( Django REST framework)是一个用于构建 Web API 的强大且灵活的工具包,基于 Django Web 框架。DRF 提供了一组用于快速开发 Web API 的工具和功能,使得构建 RESTful API 变得简单和高效。也使后端开发人员更方便的编写API接口。

DRF 的设计理念是使构建 Web API 变得简单、快速且易于维护。它与 Django 框架紧密集成,为开发者提供了丰富的功能和工具,使得构建强大的 RESTful API 成为可能。

2、作用

  1. 构建 RESTful API:DRF 提供了丰富的工具和功能,使开发者能够轻松地构建符合 REST 架构风格的 Web API。通过使用 DRF,开发者可以快速地创建支持标准 HTTP 方法(如 GET、POST、PUT、DELETE 等)的 API。

  2. 序列化和反序列化:DRF 提供了序列化器(Serializers),用于处理数据的序列化和反序列化操作。这使得在 API 请求和响应中处理复杂的数据结构变得更加简单和高效。

  3. 认证和权限控制:DRF 提供了灵活的认证和权限控制系统,开发者可以轻松地实现基于 token、session、OAuth 等各种认证方式,并定义细粒度的权限控制规则。

  4. 视图类:DRF 提供了多种视图类,包括基于类的视图(Class-based Views)和函数视图(Function-based Views),以及通用视图类(Generic Views),帮助开发者快速构建 API 视图。

  5. 路由:DRF 提供了简单而强大的路由系统,可以方便地映射 URL 到视图函数或类,从而定义 API 的端点。

  6. 文档生成:DRF 集成了强大的 API 文档生成工具,可以自动生成交互式的 API 文档,帮助开发者和用户了解 API 的结构、参数和用法。

三、API接口

1、什么是API接口?

API(Application Programming Interface)接口是一组定义和描述不同软件系统之间如何互相通信的规则集合。在软件开发中,API 接口允许不同的应用程序之间共享数据和功能,从而实现更高层次的集成和互操作性。

API 接口可以是不同形式的,其中最常见的是 Web API,它通过网络(通常是通过 HTTP 协议)暴露服务,并允许其他应用程序通过发送请求和接收响应的方式与之交互。

通俗一点来说,web后端提供给前端可以调用的访问拿到数据的东西接口可以称之为API接口。

2、API接口应该有哪些东西?

Web API接口和一般的url链接还是有区别的,Web API接口简单概括有下面四大特点:

  • url地址:长得像返回数据的url链接
    • https://api.map.baidu.com/place/v2/search
  • 请求方式:get、post、put、patch、delete
    • 采用get方式请求上方接口
  • 请求参数:Json格式或者XML格式的key-value类型数据
    • GET请求数据:地址栏中的数据----->request.GET
    • 请求体中数据:reqeust.POST'
      • 早些年 前后端交互使用XML格式,ajax其实就是异步JavaScript和XML
      • 后来 随着Json格式的出现,乃至今日都是主流
      • 未来 可能会有更高效、安全的交互格式会替代目前的Json格式
  • 响应结果:Json格式或者XML格式的数据

3、补充 Json格式与XML格式的区别

JSON(JavaScript Object Notation)和 XML(eXtensible Markup Language)都是用于在不同系统之间交换数据的常见格式,它们有以下几点区别:

  1. 语法

    • JSON:JSON 是一种轻量级的数据交换格式,采用键值对的方式表示数据。数据以键值对的形式存储,使用大括号 {} 表示对象,使用方括号 [] 表示数组。
    • XML:XML 是一种标记语言,使用标签(tag)来描述数据结构。XML 使用尖括号 <> 包围标签,标签可以嵌套表示复杂的数据结构。
  2. 可读性

    • JSON:JSON 的语法相对简洁,易于阅读和编写。对于人类来说更易于理解。
    • XML:XML 的语法相对繁琐,标签较多,使得文件相对冗长。但由于标签的结构清晰,有时也更易于理解复杂的数据结构。
  3. 数据体积

    • JSON:由于 JSON 的语法相对简洁,通常比 XML 更紧凑,数据体积更小,传输效率更高。
    • XML:XML 的冗长标签和结构使得数据文件相对较大,传输效率相对较低。
  4. 数据类型

    • JSON:JSON 支持基本数据类型(字符串、数字、布尔值、数组、对象)以及 null 值。对于简单的数据结构和前后端交互,JSON 更为常用。
    • XML:XML 可以描述更复杂的数据结构,并支持自定义数据类型和命名空间。在某些情况下,如配置文件或复杂的数据交换,XML 可能更适用。
  5. 解析和处理

    • JSON:JSON 的解析速度比 XML 更快,因为 JSON 的结构更简单。
    • XML:XML 的解析相对复杂,需要更多的处理步骤,解析速度比 JSON 慢。

总的来说,JSON 更适用于简单数据结构和前后端交互,而 XML 更适用于描述复杂数据结构和传输带有元数据的文档。在实际应用中,可以根据具体需求选择合适的格式。

四、API接口测试工具:Postman

1、安装

  • Postman下载安装教程-CSDN博客

2、使用

image

image

① :可以切换请求方法:post,put,get等

② params:参数:设置一些请求的参数的地方,通常适用于一些get的没有请求体的请求

③ authorization:鉴权:有些请求需要验证身份,采取不同的鉴权方式,携带内容,验证你的身份(和token的作用类似)

④ headers:请求头:携带请求的一些必要信息例如:Content-Type和token等

image

⑤ body:请求体:

  • none:没有请求体

  • form-data:表单格式的内容,即可上传键值对,又可以上传文件,选择不同的内容请求头的Content-Type对应值不同 x-www-form-urlencoded:只可以上传键值对

  • raw:原始数据(有text,javascript,json,html,xml)等不同格式的数据,按接口要求上传数据 选择text,则请求头是: text/plain

  • 选择javascript,则请求头是: application/javascript

  • 选择json,则请求头是: application/json (如果想以json格式传参,就用raw+json就行了)

  • 选择html,则请求头是: text/html

  • 选择application/xml,则请求头是: application/xml

  • binary:相当于Content-Type:application/octet-stream,只可以上传二进制数据,通常用来上传文件,由于没有键值,所以,一次只能上传一个文件

  • GraphQL:数据类型对参数具体的类型会有一定的标准

  • Cookies:验证身份的一种方式

⑥ Pre-request Script:预请求脚本也叫做前置脚本,在请求发生之前先发生的脚本,请求中需要用的一些内容,可太勇敢前置脚本获得

⑦ tests:后置脚本,请求之后发生的一些脚本,此接口的响应有一些其他接口用的内容,可通过tests传递出去

可以设置获取变量也可以设置断言方法

⑧ settings:设置:设置这个请求需要的一些条件,比如证书,请求头设置,等,根据需要设置

image

  • body:响应体
    • Pretty:响应展示的视图格式化显示:JSON,XML,HTML,Text,Auto这几种类型的响应

    • Raw:响应的原始文本,未格式化的

    • Preview:视图:一些html的响应方便查看

    • Visualize:可视化:一些图片验证码的响应就可以在此处查看

  • cookies:当响应中有cookies时会在这里显示
  • headers:响应头:展示响应头的信息
  • test results:测试结果:当在请求中有断言的时候,测试的结果会在此处展示

3、补充 body的编码格式

  • get 请求,可以在地址栏中带数据---》能不能在body体中带数据---》能!
    • -注意:可以提交到后端,但是django框架没有放在request.POST中,放在request.body中
  • urlencoded 编码格式---》请求体中--》name=%E5%BD%AD%E4%BA%8E%E6%99%8F&age=38
  • form-data格式:携带文件和数据
    • 文件:request.FILES.get('myfile')
    • 数据:request.POST.get()
    • request.body 能不能用,取决于文件大小,一般不用打印body(会报错)
      • 因为http是基于tcp的协议,而tcp是流式协议,一次性发达文件会报错
  • json格式
    • request.POST 是没有数据的
    • request.body 中有 ---> 需要自己在后端转成自己需要的格式数据

五、RESTful API规范

RESTful API 是一种基于 REST 架构风格设计的 API,它遵循一组约定和规范,以提供统一的接口,使得不同系统之间能够更轻松地进行通信和交互。以下是设计 RESTful API 时应遵循的一些规范:

1、数据的安全保障

  • url链接一般都采用https协议进行传输
  • 注:采用https协议,可以提高数据交互过程中的安全性

2、url地址中带接口标识

  • https://api.baidu.com
  • https://www.baidu.com/api/

3、url中带版本标识

  • 接口有版本
    • https://api.baidu.com/v1/login
    • https://api.baidu.com/v2/login

4、数据即是资源,均使用名词(可复数)

  • 以后所有接口路径中,尽量不出现动词
  • 接口一般都是完成前后台数据的交互,交互的数据我们称之为资源
    • https://api.baidu.com/v1/users
    • https://api.baidu.com/v1/books
    • https://api.baidu.com/v1/books/3

5、请求方式决定如何操作资源【增,删,改,查:curd】

  • https://api.baidu.com/books - get请求:获取所有书
  • ​ https://api.baidu.com/books/1 - get请求:获取主键为1的书
  • ​ https://api.baidu.com/books - post请求:新增一本书
  • ​ https://api.baidu.com/books/1 - put请求:整体修改主键为1的书
  • ​ https://api.baidu.com/books/1 - delete请求:删除主键为1的书

6、url中带搜索条件

  • 当我们发送请求需要对应参数时直接在对应请求url后携带即可

  • https://api.baidu.com/v1/user?username=bbs123&user_id=1

7、响应中带状态码

  • http响应状态码
    • 1xx :请求正在处理 --> 客户端看不到
    • 2xx :正常响应---> 经常看到的有
      • 200:请求成功
      • 201:创建成功
    • 3xx :重定向---》偶尔看到 301 和 302
    • 4xx :客户端异常---》403: 404
    • 5xx: 服务端错误 500
  • 有趣的状态码记忆方法:
    • https://www.sohu.com/a/278045231_120014184
  • 自定制状态码
    • 例如:mysql--> 连接连不上--> 有个错误提示信息:错误码,错误描述
    • 我们也可以自己定制,但是一定要把错误提示码对应的错误消息公布出来让别人知道

8、响应中带信息描述(错误,正常)

  • 例如:code,message

9、针对不同操作符合以下规范

  • 统一规范的错误响应格式,包括错误码、错误信息和可能的解决方案。客户端可以根据错误信息快速定位问题所在。

  • 比如:

  • GET /collection:返回资源对象的列表(数组)

    • {code:100,msg:成功,results:[{},{},
  • GET /collection/resource:返回单个资源对象 {}

    • {code:100,msg:成功,result:
  • POST /collection:返回新生成的资源对象 {}

  • PUT /collection/resource:返回完整的资源对象 {}

  • DELETE /collection/resource:返回一个空文档

10、返回数据中带链接

RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。

比如,当用户向api.example.com的根目录发出请求,会得到这样一个文档。

{"link": {"rel":   "collection https://www.example.com/zoos","href":  "https://api.example.com/zoos","title": "List of zoos","type":  "application/vnd.yourformat+json"
}}

上面代码表示,文档中有一个link属性,用户读取这个属性就知道下一步该调用什么API了。rel表示这个API与当前网址的关系(collection关系,并给出该collection的网址),href表示API的路径,title表示API的标题,type表示返回类型。

Hypermedia API的设计被称为HATEOAS。Github的API就是这种设计,访问api.github.com会得到一个所有可用API的网址列表。

六、序列化与反序列化

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

1、序列化

序列化: 把我们识别的数据转换成指定的格式提供给别人

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

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

2、反序列化

反序列化:把别人提供的数据转换/还原成我们需要的格式。

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

3、js中的序列化和反序列化

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

4、小结

  • 序列化:
    • drf称为 read(读取数据)
    • queryset --- > json
    • 返给前端
  • 反序列化:
    • drf称为 write(写入数据)
    • 字符串 --- > json
    • 接收前端的数据

七、初步编写API

1、基于drf实现

(1)安装

pip install djangorestframework

(2)注册

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','app01.apps.App01Config','rest_framework'
]

(3)返回数据界面

返回的是数据 + 嵌套好看的页面

路由

path('login/',views.login)
path('info/',views.InfoView.as_view())

视图

  • FBV
from rest_framework.response import Response
from rest_framework.decorators import api_view@api_view(["GET"])
def login(request):return Response({'status':True,'message':"success"})
  • CBV
from rest_framework.response import Response
from rest_framework.views import APIView
class InfoView(APIView):def get(self,request):Response({'status': True, 'message': "success"})

八、DRF快速使用

1、安装DRF

  • 使用pip包管理器,在终端中运行以下命令来安装DRF
pip install djangorestframework
  • 最新的drf,必须django 3.x以上,配置MySQL3.8版本以上

2、注册

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','app01.apps.App01Config','rest_framework'
]

3、创建表

import uuid
from django.db import modelsclass Task(models.Model):task_id = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)task_name = models.CharField(max_length=255, db_index=True)task_time = models.DateTimeField(auto_now_add=True)task_desc = models.TextField()

4、创建序列化器(Serializer):

  • 序列化器是DRF中一个重要的概念,它将Python对象转换为JSON等可被传输的格式,并可以反序列化接收到的数据。
  • 在你的应用程序中创建一个名为serializers.py的文件,并定义你的序列化器类。
  • 一个示例:
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):class Meta:model = Taskfields = '__all__'
  • 在这个示例中,我们使用ModelSerializer来自动创建序列化器类。

5、创建视图(View)

  • 在你的应用程序中创建一个名为views.py的文件,并定义视图类。
  • 一个示例:
from .models import Task
from .serializer import TaskSerializer
from rest_framework.viewsets import ModelViewSet
class TaskView(ModelViewSet):queryset = Task.objects.all()serializer_class = TaskSerializer

6、配置URL路由

  • 在你的应用程序的urls.py文件中,定义DRF的URL路由。
  • 一个示例:
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('task', TaskView, 'task')
urlpatterns = [
]
urlpatterns += router.urls
  • 通过上述配置,当访问127.0.0.1:8000/task/时,将会调用TaskView视图。

7、测试代码

import requests# res = requests.get('http://127.0.0.1:8000/app01/task/')
# print(res.text)
from threading import Thread# 多线程新增数据
def task(task_id, task_name):data = {"task_id": task_id,"task_name": task_name,"task_time": "2024-04-10 11:54:56","task_desc": "很重要,不能忘记"}res = requests.post('http://127.0.0.1:8000/app01/task/', json=data)print(res.text)if __name__ == '__main__':l = []for i in range(30):t = Thread(target=task, args=['asdfads-33-as-%s' % i, '任务00%s' % i])t.start()l.append(t)for i in l:i.join()

九、CBV源码剖析

(1)cbv写法:

  • 视图中写视图类,继承View,写跟请求方式同名的方法
class TaskView(View):def get(self,request):return 四件套
  • 在路径用写
path('task/', TaskView.as_view())
  • 如上写法,为什么能够执行

(2)前置条件

  • 前端请求,一旦路径匹配成功,就会执行
    • TaskView.as_view()(request传入,)
  • 入口在
    • TaskView.as_view()--->执行结果---》View中有个as_view类的绑定方法
@classmethod
def as_view(cls, **initkwargs):def view(request, *args, **kwargs):self = cls(**initkwargs)res=self.dispatch(request, *args, **kwargs)return resreturn view
  • 执行结果是view 的内存地址: 请求来了,执行view(request)
path('books/', view)
  • 执行 View类中的as_view方法中的内层的view函数,路由匹配成功,本质是在执行
self.dispatch(request, *args, **kwargs)
  • self是谁的对象?
    • BookView的对象
  • 去BookView中dispatch,找不到
    • 去父类,View中找到了
  • View这个类的dispatch
def dispatch(self, request, *args, **kwargs):# 取出请求方式,转成小写,判断在不在列表中  get请求在if request.method.lower() in self.http_method_names:# handler=getattr(BookView的对象,'get')   # handler就是BookView类中的get方法handler = getattr(self, request.method.lower())else:handler = self.http_method_not_allowed# 执行 BookView类中的get方法 (request)return handler(request, *args, **kwargs)
  • 最终本质跟写fbv的执行流程一样

(3)最终结论

  • 什么请求方式,就会执行视图类中的什么方法
# 1 在路由中:path('index/',IndexView.as_view())# 2 请求来了---》路由匹配成功--》执行 IndexView.as_view()(request)-看View类的as_view的返回结果[可以加括号执行]---》猜:函数内存地址# 3 View类的as_viewdef as_view(cls, **initkwargs):def view(request, *args, **kwargs):self = cls(**initkwargs) # cls--》IndexViewreturn self.dispatch(request, *args, **kwargs)return view
# 4 IndexView.as_view() 本质就是 --》view--》内存函数view# 5 IndexView.as_view()(request)---》view(request)
# 6 本质 执行 self.dispatch--》self 是对象--》谁的对象?视图类的对象IndexView类的对象return self.dispatch(request, *args, **kwargs)# 7 IndexView没有dispatch--》View类中的dispatch# request 当次请求的requetsdef dispatch(self, request, *args, **kwargs):#1 取出请求方式,转成小写,判断在不在列表中  get请求在#2 self.http_method_names if request.method.lower() in self.http_method_names:# 3 反射:去 self IndexView类的对象中通过字符串get找属性或方法# 找到了get方法,赋值给了handlerhandler = getattr(self, request.method.lower())else:handler = self.http_method_not_allowed# 4 执行handler--》本质是get(request)# 执行了IndexView类中的get方法--》把request传进去了return handler(request, *args, **kwargs)

十、基于APIView的5个接口使用

1、视图类

from rest_framework.response import Response
from rest_framework.views import APIView  # # APIView继承了djagno原来的View
from app01.serializer import TaskSerializer
from app01.models import Taskclass TaskView(APIView):def get(self, request):tasks = Task.objects.all()# drf提供了序列化类serialized_tasks = TaskSerializer(instance=tasks, many=True)  # 序列化return Response({'code': 100, 'msg': '查询所有成功', 'results': serialized_tasks.data})def post(self, request):serialized_task = TaskSerializer(data=request.data)  # 反序列化if serialized_task.is_valid():  # 数据校验---》有些不合法的禁止serialized_task.save()  # 保存到数据库中return Response({'code': 100, 'msg': '创建成功'})class TaskDetailView(APIView):def get(self, request, *args, **kwargs):try:task = Task.objects.filter(id=kwargs['id']).first()serialized_task = TaskSerializer(instance=task, many=False)  # 序列化return Response({'code': 100, 'msg': '查询单个成功', 'result': serialized_task.data})except Exception:return Response({'code': 200, 'msg': '任务不存在'})def put(self, request, *args, **kwargs):try:task = Task.objects.filter(id=kwargs['id']).first()serialized_task = TaskSerializer(instance=task, data=request.data)  # 反序列化if serialized_task.is_valid():  # 数据校验---》有些不合法的禁止task.save()  # 保存到数据库中return Response({'code': 100, 'msg': '更新成功'})except Exception:return Response({'code': 200, 'msg': '任务不存在'})def delete(self, request, *args, **kwargs):try:Task.objects.filter(id=kwargs['id']).delete()return Response({'code': 100, 'msg': '删除成功'})except Task.DoesNotExist:return Response({'code': 200, 'msg': '任务不存在'})

2、序列化类

from rest_framework import serializers
from .models import Taskclass TaskSerializer(serializers.ModelSerializer):class Meta:model = Taskfields = '__all__'

3、模型类

import uuid
from django.db import modelsclass UserLog(models.Model):ip = models.CharField(max_length=255)visit_time = models.DateTimeField(auto_now=True)method = models.CharField(max_length=32)path = models.CharField(max_length=64)user_agent = models.CharField(max_length=255)class Task(models.Model):task_id = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)task_name = models.CharField(max_length=255, db_index=True)task_time = models.DateTimeField(auto_now_add=True)task_desc = models.TextField()

4、路由

from django.urls import path
from app01 import viewsurlpatterns = [path('task/', views.TaskView.as_view()),path('task/<int:id>', views.TaskDetailView.as_view()),
]

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

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

相关文章

Unity组件

二、Mesh网格 1 Mesh Filter Mesh Filter 组件包含对网格的引用。该组件与同一个游戏对象上的 Mesh Renderer 组件配合使用;Mesh Renderer 组件渲染 Mesh Filter 组件引用的网格。用于将网格数据应用到 3D 模型上。它是实现 3D 模型的重要组成部分之一,可以定义模型的形状和结…

最好用的Python IDE,pycharm保姆级安装教程

简介 由于Python语法简单容易入门,并且Python在办公自动化等领域的功能非常强大,所以现在越来越多非IT行业的人也开始学起了Python,要学习和使用一门编程语言,一个好用的IDE是必不可少的,而对于Python来说,最好的IDE无疑是Pycharm。本文就给大家介绍一下如何从零到一来安…

2-58. 实现农作物的重复收割

修改 Crop修改 GridMapManager修改 EventHandler修改 GridMapManager修改 Crop修改 CropDataList_SO项目相关代码 代码仓库:https://gitee.com/nbda1121440/farm-tutorial.git 标签:20240410_1825

uniapp转译微信小程序动态样式语法问题(:style)

这样书写之后编译成微信小程序时会出现一下情况造成此类原因是因为 我们直接给了一个对象而不是字符串(即直接给字符串不会出现此类问题) 而微信不能直接识别 所以直接在动态赋值时加上中括号

实验一-密码引擎-3-加密API研究

一、微软的Crypto API CryptoAPI 系统体系结构 Web Crypto API CSP开发基础--CryptoAPI函数简介 Crypto API结构 基本加密函数用于连接到 CSP 的_上下文函数_。 这些函数使应用程序能够按名称选择特定的 CSP,或选择可以提供所需功能类别的特定 CSP。 用于生成和存储加密密钥的…

实验一-密码引擎-加密API的研究

一、任务详情 密码引擎API的主要标准和规范包括: 1 微软的Crypto API 2 RAS公司的PKCS#11标准 3 中国商用密码标准:GMT 0016-2012 智能密码钥匙密码应用接口规范,GMT 0018-2012密码设备应用接口规范等 研究以上API接口,总结他们的异同,并以龙脉GM3000Key为例,写出调用不同…