初学者之《复刻英雄联盟官网之人脸识别登录》②

编程入门 行业动态 更新时间:2024-10-22 11:35:40

初学者之《复刻英雄联盟官网之人脸识别登录》②

第3章 Web项目系统设计
第4章 Web项目系统实现


三、Web项目系统设计

在完成一个Web项目的开发过程和设计过程时,首先经历的就是整个项目的需求分析而其所具体的需求用例也需要通过开发人员对整个项目进行系统设计才能实现需求用例的功能目的。所以,在通过具体的Web项目系统设计时,首先要考虑的问题就是“这些需求用例怎么做?”,因此这个“怎么做”就成整个Web项目系统设计的核心,也只有了解了怎么做,去采用什么方法做,才能在后续整个项目的实现打好铺垫。在本章结中,主要涉及到的就是描述整个Web系统开发的总体设计思路,采用自顶向下逐层模块化的方法,构造整个Web系统的各部分模块,并使用相对应的模块图对项目中相关的模块进行详细描述,同时也利用到数据库相关的E-R图对数据库的组成结构进行详细描述;除此之外,还需要运用到面向对象的MVC架构视图,充分描述整个Web系统设计的分层结构。

1.Web系统功能模块划分

在整个系统的用例需求分析中,可以看到的是,总共有六个主要的用例需求,而对于这八个主要的用例需求,该Web系统就可以展开出主要的六个功能模块,这些功能模块分别包括首页浏览、英雄搜索、网站管理、以及用户的对战模拟、信息管理、登录注册等;每一部分的功能实现均相互独立,但其相互传输的数据依然存在,从而满足了模块独立性的内聚、耦合准则,下图3.1就是整个Web项目的一些功能模块图。

2.Web系统数据库设计

在该Web项目的系统设计中,数据库的设计当然就是必不可少的一个部分了,作为所有数据源存储的地方,数据库所具备的重要性在整个系统中的不可忽视的,而此项目所采取的数据库框架是一款优秀的持久层框架数据库框架——MyBatis。其实,对于一个项目来说,数据库的采用是极其重要的,而选择一个良好的数据库框架也更是重要的,其不仅可以更方便的处理数据信息并且保障数据信息的安全和方便数据信息的传输,同时更是增强了数据信息的管理能力,在降低了数据冗余度和节约系统资源的情况下,一个项目的开发和运行以及维护就会大大减少成本,同时不仅仅是对开发者的开发效率有利,同时也是对用户信息的一种保障。而在此次开发项目的过程中,主要涉及到三个阶段,其包括数据库的需求分析阶段以及数据库的概念设计阶段和逻辑设计阶段,其中之前的用例需求分析已经介绍到了所要实现的具体的项目功能需求;当前章节就根据所要实现的具体功能需求展开数据库的概念设计阶段和数据库的逻辑设计阶段。
  • Web系统数据库概念设计
    对于数据库的概念设计过程,其实就是一个将整个Web系统所划分的功能模块进行抽象化,从而生成各种实体类对象,而作为实体的用户实体,可以通过整个系统设计观察到;同时在该系统也需要用到英雄标签实体、英雄实体、比赛方式实体以及点券实体,在这四个实体中,相互之间均有联系;更具大致分析,英雄实体和用户实体所具备的关系就是1:N的关系,而英雄和英雄标签对应的关系就是M:N的关系。对于英雄和比赛场次的关系,可以知道的是,每场比赛都可以选这多个英雄,但是多个英雄不能参加多场比赛,所以它们的关系就是1:N的关系,同时对于用户和点券的对应关系也是1:N的关系。由以上的大致分析情况,该项目可得到具体的E-R图,如图3.2所示。
  • Web系统数据库逻辑设计
    在数据库完成基本的概念设计时就需要对数据库进行逻辑方面的逻辑设计了,因为一个好的数据库就必须做到数据之间具有一定的逻辑。在整个项目的数据库设计分析中,同时又通过实际的项目需求和E-R图的结构分析,可以得到的数据库表有以下几类:
    用户信息表、点券信息表、比赛方式信息表、英雄信息表以及英雄标签信息表等一共五张表,每一张表都会有对应的表信息内容,因为数据本就容易存在冗余或者杂乱的现象,所以通过详细的数据信息表对数据进行处理,无疑就是数据库逻辑设计阶段最重要的部分。
  • 用户信息表
    -对于用户信息表中的内容,主要包括的就是用户ID信息,用户名信息、召唤师名称信息、账户密码信息、头像信息、令牌信息、签名信息、英雄拥有信息,经验值信息,点券信息,人脸信息,创建时间以及修改时间信息,当然也包括用户的状态信息。在表中,将用户ID作为整个表的主键,而其中的用户状态信息也通过0,1来决定,所以其设定模式如果是正常在线状态就为1,如果是离线状态就为0,因而此表的详细逻辑设计就如表3.1所示。
  • 点券信息表
    点券信息表所描述的就是关于用户资产下的点券,与点券对应的信息也主要分为:其点券本身的数量信息,以及点券本身所要使用的消费记录以及其充值记录,点券是整个Web系统中很重要的一个角色,也只有当用户拥有了所谓的点券的资产,才能够进行其他的功能需求操作,以下的点券信息表详细的逻辑设计就如表3.2所示。
  • 比赛方式信息表
    所谓的比赛方式就是该Web项目中对战模拟下首选的一个选择内容,通过不同的比赛方式来记录不同的比赛数据,并将其比赛ID设为主键,在每一场比赛中,其主要涉及到的信息有:比赛场次的名称和该比赛场次被选中的次数,以及每场比赛获取的经验值、参赛记录。而其具体信息的详细逻辑设计就如表3.3所示,其主要也介绍了和比赛方式有关的数据成分以及数据关系。
  • 英雄信息表
    在英雄信息表中,其对应的就是相关英雄的信息,其主要的信息也包括:英雄的ID,英雄图片的绝对地址,某位英雄被使用的次数以及英雄的名称和英雄的点券价值,根据这些数据的基本逻辑关系,可以设计出对应的且详细的英雄信息表,其具体表格如表3.4所示。
  • 英雄标签信息表
    关于英雄标签信息表,其主要目的是给英雄赋予标签,更重要的也是对英雄进行分类,对于不同的标签,其所包含的英雄也不同,在此信息表中,主要涉及到了英雄标签信息中作为主键的ID,以及英雄标签的名称和英雄头像图片的绝对地址,其具体的详细设计信息如信息表3.5所示。

3.Web系统详细设计

在经过系统的概要设计阶段以及数据库的三个阶段之后,其主要的下一个阶段就是根据概要设计所涉及的内容进行系统性的详细设计,在对整个系统进行详细设计的同时首先要进行的就是对系统进行分层结构的具体化描述,其主要完成的内容也就是动态性的描述整个Web项目所要进行的动态行为,在这个过程中,需要涉及的就是对整个Web系统进行基础性的分层,以及详细描述其具体的动态行为的设计。
在前面的总体设计理念中也有介绍到,该项目的整个分层设计是采用的MVC架构的方式对系统采取分层的行为,其中主要包括的就是数据层(Model)、表现层(View)、控制层(Control),在不同的层级进行着不同的事物处理行为,主要其具有的优点就是可以提高项目中组件的重用,并降低了层与层之间的依赖,从而有利代码的标准化开发,其具体的层次结构也如图3.3所示。


在该项目中,玩家用户可根据前端的View视图层的内容对整个网站进行操作,而其具体操作的事件所涉及到的数据被浏览器进行处理,在经过此次处理之后的数据,又将被发送到数据的Control控制层,Control控制层将数据传达给Model业务层进行对应的事件处理。数据在Model业务层存留的事件被所调用的Mapper层相关的读写方法进行再次处理,从而使得数据被数据库进行了相应的读写操作。在经过第一回的数据传输时,其只是完成了数据到Web系统数据库的这个过程,但是其具体结果和信息并不能被玩家用户所看到的,所以这又需要进行数据回传,也就是将数据再通过Model业务层,Control控制层,输送到View视图层进行显示。由此可由图3.4所示。

  1. View视图层
    一个项目的直接观感自然少不了视图层的参与,而且其存在关键也是和用户进行良好交互的重要载体。其位于整个项目开发结构层次的最上层,其也主要在前端开发中进行,为用户提供更好的网页观感,图形化的界面也让用户更加容易接受,同时也能更有效的提高用户使用的频率,同时也能增强官网的浏览效益。而在整个项目中,视图层所运用到的技术框架也就是Jquery.js。但是对于前端而言,所要涉及到的内容也需要分为三部分,其中主要包括页面展示、API接口以及网络访问请求,因此根据分析,我们也可以得到关于前端视图层的详细设计描述框架图,而其具体内容如图3.5所示。
  2. Control控制层
    所谓的控制层,自然是实现了对于整个项目数据的控制,其主要位于View视图层之下,Model业务层之上的,其主要作用是用于接收View视图层中用户所操作的请求,并同时也在分析数据,解析与之相关的数据信息,最后根据需要和调用相关的业务层方法对数据进行处理,随后并将数据回传至View视图层。其中所包含的所有Controller都是继承于BaseController而实现的。由此可以得知,关于Control控制层的类图大致思路,但是此时需要定义一个用户控制器UserController,来确认他们之间的继承关系,并将其包含的服务定义为IuserService,通过这样的具体分析,我们可以得一个相对完整的控制层类图,其具体信息如图3.6所示。
  3. Model业务层
    在Control控制层之下的就是当前要介绍的业务层,其也是主要的核心层。在接收到Control控制层传来的数据时,其也会根据业务逻辑调用相关的代码,对数据的请求进行处理,并且同时也会在处理所需求的业务时,其也会向数据控制层请求相应的数据。在整个项目的设计里主要采用了遵循面向接口编程的原则。其目的就是为了将业务层中的各个类进行接口性定义,然后再对相应的接口方法进行实现。其中,实现接口的类就需要用到@Service进行注解然后使得服务能够自主的注入到业务层中。其中,所涉及到的业务层的接口都需要继承来自Iservice<>基类,而对于ServiceImpl<>类来说就是被业务层的实现类所继承,由此可得具体业务层类图为图3.7所示,其中User是自定义的实体,其DAO也由UserMapper定义。
  4. DAL数据层
    数据层就是名副其实的操作项目中所具有的数据的一个层次部分,它主要处于业务层之下,数据源之上,在此项目中主要引入了Mybatis,不仅支持定制化的SQL,更重要的是其存储过程和其高级映射几乎避免了很多其他数据库框架所存在的问题,在增、删、改、查等基本的数据操作功能实现中可用极少量代码即可实现,所以在引入Mybatis数据库的框架时,是大大提高了后端数据处理的效率。在DAL数据层中,主要分为数据访问对象层和实体层,而其具体内容也分为以下两部分介绍。
    数据访问对象层:其对数据进行的操作往往都是长久性的,其中实体层便用来定义具体的不同实体,而作为数据访问对象层为接口,是需要继承BaseMapper<>,从而用以访问Mybatis所提供的相关函数方法,在这里需要使用到@Repository进行注解。其具体的相关类图可如图3.8所示,其中有一个自定义的实体为user,和其对应的数据访问对象为UserMapper。

    实体层:该层是为了定义数据对象而存在的,其相关的数据对象将存放在Data文件夹中,每个Data类都对应与数据库中的一张表。因此,也需要使用注解对表名进行一定的说明,而对于每个变量所使用的注解就是指定的对应字段。其中也就需要使用到了Lombok提供的注解,该注解可以自动生成set方法和get方法,从而有了有参和无参的构造方法。

四、Web项目系统实现

本章主要介绍了网站的登录注册、点券充值、英雄购买以及签名更改和对战模拟等多个模块的实现,对这些模块中的关键技术和实现进行了详细介绍。

1.登录注册

 在整个登录注册模块中主要也分为四个部分,其分别包括用户的账户密码登录和用户的人脸识别登录,而注册中主要又包括用户基本信息注册和用户的人脸信息采集功能模块,所以其具体总共包含又四个页面,在之后的模块介绍中,部分功能也会涉及关键代码的介绍。但在人脸识别登录的页面里,人脸识别登录的实现的最为关键的。在如今的科技时代,人脸识别系统也变得更加普遍,而且也有很多平台都开放了人脸识别系统的API接口,所以该项目主要引入了百度大脑的人脸识别API接口。在解决整个问题的之时,首先就是需要通过百度云进入人脸识别控制台,即地址为:

https://console.bce.baidu/ai/?_=1528192333418&fromai=1#/ai/face/overview/index

然后就是通过创建人脸识别应用来获取API Key及Secret Key,并对接口进行调用的操作,然后又进行相关的基本配置。最后便可获取调用接口所需要的Access Token,由于人脸识别在线的接口主要针对的是HTTP API调用者,其调用API时也需要在URL上标志accesss_token参数,其具体代码段为:

#!/bin/bash-curl-i-k'https://aip.baidubce/oauth/2.0/token?grant_type=client_credentials&client_id=【百度云应用的AK】&client_secret=【百度云应用的SK】'

在获取到了Access Token并请求了URL的数据格式,服务器将返回参数如下:

{"refresh_token": "25.b55fe1d287227ca97aab219bb249b8ab.315360000.1798284651.282335-8574074",
    "expires_in": 2592000,
    "scope": "public wise_adapt",
    "session_key": "9mzdDZXu3dENdFZQurfg0Vz8slgSgvvOAUebNFzyzcpQ5EnbxbF+hfG9DQkpUVQdh4p6HbQcAiz5RmuBAja1JJGgIdJI",
    "access_token": "24.6c5e1ff107f0e8bcef8c46d3424a0e78.2592000.1485516651.282335-8574074",
    "session_secret": "dfac94a3489fe9fca7c3221cbf7525ff"}

然后准备接口的调用,这里需要用到接口调用工具是PostMan,其可以很快的对接口进行调用,当接口调用成功的时候,就需要搭配人脸信息采集的图片实现人脸识别登录。而这也就是人脸识别进行登录的部分。其主要的功能实现效果图如图4.2所示(涉及隐私此处未展示,见谅)

其用户的基本信息注册页面如图4.3所示。

当然,在人脸信息采集的方面其主要方法是进行人脸图片的采集,所以在使用人脸信息采集页面中,这里就需要调用主机的摄像头,然后进行图片截取,并对图片进行数据库保存,其具体的代码段为:

window.onload = function () {
	var canvas = document.getElementsByTagName('canvas')[0],
		context = canvas.getContext('2d'),
		video = document.getElementsByTagName("video")[0],
		snap = document.getElementById("snap"),
		close = document.getElementById("close"),
		start = document.getElementById("start"),
		MediaStreamTrack;
	start.addEventListener('click', function () {
		if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
			navigator.mediaDevices.getUserMedia({
					video: true,
					audio: true
			}).then(function (stream) {
					console.log(stream);
					MediaStreamTrack=typeof stream.stop==='function'?stream:stream.getTracks()[1];
					video.src=(window.URL).createObjectURL(stream);
					video.play();
			}).catch(function(err){
					console.log(err);});
		}else if(navigator.getMedia){
			navigator.getMedia({
				video: true
			}).then(function (stream) {
				console.log(stream);
				MediaStreamTrack=stream.getTracks()[1];
				video.src=(window.webkitURL).createObjectURL(stream);
				video.play();
			}).catch(function(err){
				console.log(err);});}});
	snap.addEventListener('click', function () {
		context.drawImage(video, 0, 0,200,150);});
	close.addEventListener('click', function () {
		MediaStreamTrack && MediaStreamTrack.stop();});}

以上就是在实现人脸识别登录和人脸信息采集的主要运用到的方法,其具体的功能实现如图4.4所示(涉及隐私此处未展示,见谅)

2.点券充值

对于点券充值模块中,设定了四个选项卡,其分别对应的就是不同的充值余额,并实现通过扫码来完成充值情况,其中二维码所设计的是自定义的充值完成的内容,其具体实现效果如图4.5所示。

而在该充值页面中,主要存在的是充值数据输入内容的实时监控问题,需要做到的是让输入框的内容和下方金额进行实时比例转换,而对于该问题的产生是存在于实时性的监控输入框的内容并将内容的数据进行一定的操作处理传送到所对的金额栏中,为了实现其具体的实时监控,其主要就要用它关于JQ中的方法input propertychange。所以其所涉及到的代码段为:

$(".recharge-select-num1-3").bind('input propertychange', function () {
            var recharge = parseInt($(this).val());
            var yuan = parseFloat($("#yuan").val());
            if ($(this).val() == 0) {
                yuan = '元';
                $("#yuan").html(yuan);
            }
            else {
                yuan = recharge / 100 + '元';
                $("#yuan").html(yuan);
            }
        });

而其具体实现的截图如图4.6所示。

3.英雄购买

再对于英雄购买的模块,就需要点券的参与才可以完成,当然这里具体实现的是使用点券对英雄进行购买当点击购买以后,在用户界面的英雄栏上会显示对应的英雄头像。其中英雄购买的具体页面显示如图4.7所示。

当英雄完成购买的时候,英雄的头像就会在我的英雄栏中进行显示,这里会涉及到一个动态生成li标签的功能代码,其具体代码段之一如下:

if ($(".buy-button1").val() == 1) {
       var li_str = '<li id="li">';
       var heroName1 = $(".recommend-hero-name")[0].innerHTML;
       var heroHead1 = $(".recommend-hero-head-img")[0].src;
       li_str += '<div class="user-hero-show-head">';
       li_str += '<img class="user-hero-show-head-img1"/></div>';
       li_str += '<div class="user-hero-show-name1">';
       li_str += '</div></li>';
       $('.user-hero-show').append(li_str);
       $('.user-hero-show-head-img1').attr('src', heroHead1);
          $('.user-hero-show-name1').text(heroName1);
          $("#buy1").css({
             "color": "#fff",
             "border": "1px solid #ccc",
             "background": "#ccc"});
          $("#buy1").text('已购买');
          $("#buy1").attr('disabled', 'disabled')}

而其功能所实现的页面效果也如图4.8所示。

4.签名更改

之后就是对于签名更改的模块了,在签名更改的模块中,主要涉及的就是数据库对于用户签名信息的存储,以便于信息的长久性维持在用户自己的页面上不会擅自被更改。而其具体功能实现页面如图4.9所示。
在进行签名更改的时候,如果文本输入框并没有内容的话,系统将提示请输入正确内容,而如果出现了长度大于的22的字符串,系统也会提示请输入正确内容,而这就是检测了标签内容的格式问题,当引用了图4.9中的文本内容,我们可以看到其结果显示的样式如图4.10所示。

5.生成饼状图

当然在当前的用户信息页面中,仍然需要涉及到一个根据比赛方式生成比例饼状图的功能,在生成饼状图的功能中,其目的就是为给用户带来了更好的观感,让数据在用户面前表现的更加的直白,每场比赛所进行的次数都按照点击的次数来算,每当点击一次就说明参加了一次比赛,一共有这四种比赛方式,但每种比赛方式的具体效果都差不多,但为的就是给项目添加一共饼状图生成的功能,所以其将数据库中所记录的比赛数据请求到了View视图层,以方便对比赛方式进行生成饼状图效果。而其具体的代码段,如图4.11所示:

class PieChart {constructor(data) {this.data = data;
       this.canvas = document.getElementById('canvas');
       this.ctx = this.canvas.getContext('2d');
         this.setRatio();
           this.x0 = this.canvas.width / 2;
       this.y0 = this.canvas.height / 2;
       this.radius = 63;
       this.addLine = 20;
       this.init();
       this.bindEvent();}
    setRatio() {var d = window.devicePixelRatio || 1;
       var cd = this.ctx.backingStorePixelRatio || 1;
       var r = d / cd;
            this.r = r;
            var w = this.canvas.width;
            var h = this.canvas.height + 60;
            this.canvas.width = r * w;
                this.canvas.height = r * h;
            this.canvas.style.width = w + 'px';
            this.canvas.style.height = h + 'px';}
         toAngle() {var t = 0;
            this.data.forEach(item => { t += item.num;});
            this.data.forEach((item, i) => {
               var angle = item.num / t * Math.PI * 2;
               item.angle = angle;
               item.color = this.randomColor();})}
            randomColor() {
               var r = Math.floor(Math.random() * 256);
               var g = Math.floor(Math.random() * 256);
               var b = Math.floor(Math.random() * 256);
               return "rgb(" + r + "," + g + "," + b + ")";}
            init() {this.toAngle();this.drawPie();}
            drawPie(x, y) {var start = 80;
               console.log(this.data);
               this.data.forEach((item, i) => {
               var end = start + item.angle;
               this.ctx.beginPath();
               this.ctx.moveTo(this.x0, this.y0);
               this.ctx.arc(this.x0, this.y0, this.radius, start, end, false)
               this.ctx.closePath();
               if (this.ctx.isPointInPath(x * this.r, y * this.r)) {
                  this.ctx.arc(this.x0, this.y0, this.radius + 10, start, end, false)
              this.ctx.fillStyle = item.color;
              this.ctx.fill();
              this.drawTitle(start, this.radius + 10, item, item.color)}
          else { this.ctx.fillStyle = item.color;
              this.ctx.fill();
              this.drawTitle(start, this.radius, item, item.color)}
              start = end; })}
    drawTitle(start, radius, item, color) {
        var lineLength = radius + this.addLine;
        var endX = lineLength * Math.cos(start + item.angle / 2);
        var endY = lineLength * Math.sin(start + item.angle / 2);
        var outX = this.x0 + endX;
        var outY = this.y0 + endY;
        this.ctx.beginPath();
        this.ctx.moveTo(this.x0, this.y0);
        this.ctx.lineTo(outX, outY);
        this.ctx.strokeStyle = color;
        this.ctx.stroke();
        var align = outX > this.x0 ? "left" : "right";
        this.ctx.font = "9px 微软雅黑 100";
        this.ctx.textAlign = align;
        this.ctx.textBaseline = "bottom";
        this.ctx.fillStyle = color;
        this.ctx.fillText(item.title, outX, outY - 3);
        var textW = this.ctx.measureText(item.title).width;
        this.ctx.moveTo(outX, outY);
        outX = outX > this.x0 ? outX + textW : outX - textW;
        this.ctx.lineTo(outX, outY);
        this.ctx.stroke();
             var number = outX < this.x0 ? "left" : "right";
             this.ctx.font = "9px 微软雅黑 100";
             this.ctx.textAlign = number;
             this.ctx.textBaseline = "top";
             this.ctx.fillStyle = "#fff";
             this.ctx.fillText(item.num, outX, outY + 5);}
          bindEvent() {
             this.canvas.addEventListener('mousemove', (e) => {
             let x = e.clientX - this.canvas.getBoundingClientRect().left;
             let y = e.clientY - this.canvas.getBoundingClientRect().top;
             this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
             this.drawPie(x, y); });}}
var data = [
   { title: "人机模式", num: id1 },
   { title: "匹配模式", num: id2 },
   { title: "大乱斗", num: id3 },
   { title: "云顶之奕", num: id4 },];
var pieChart = new PieChart(data);

而其具体的代码实现效果如图4.11所示。

6.对战模拟

最后一个模块,就是英雄对战的模拟,当你选中一个英雄的时候参加对应的赛事就可以得到对应的比赛数据,而其数据的得到方式就是确定每个英雄的ID所赋予的随机值,然后将自己选择的英雄的随机值与其他英雄进行比较,当选择英雄所具有的随机值大于系统随机选择的英雄的随机数,就判定该局为胜利局,否则就判定为失败局,最后通过数据统计,将具体信息显示在前端的用户信息页面上。在这里由于篇幅的问题,这里就选择对对战模拟的页面进行展示了,而其具体样式也如图4.12所示。


总结

在整个项目的开发中,我学会了一整套的开发流程,也是第一次感觉会这么真实,因为对于一个好的Web项目而言,采用合适的前端框架和后端框架以及数据库框架都是非常重要的。在此项目完成之前,我并不是特别了解项目开发的三层架构MVC。但是经过这次毕业设计的大项目,我对该架构的使用也有了基本的了解。针对该Web项目而言,其就是属于面向对象的产物,因为其主要目的就是为了和用户进行较强的交互性能。同时,在前端页面的编写的情况下,我花费了很长时间去完善各种布局,这也是第一次让我更加熟悉的掌握HTML+CSS+JS的相关知识。在十个页面中,曾花有六万多行去写前端,在后端数据库中也建立了相互之间信息独立的五个表的详细内容。在对整个Web系统进行三个阶段的分析时,也曾遇到了很多问题,但是也都一一克服了,毕业设计本就是一种自我的考验,在没有经历毕业设计的时候,对于数据库语言我也是不太熟悉,但是在完成整个项目的时候,就意识到数据库的重要性,为了方便数据的存储,同时为了更为高效的编制数据库表和链接数据库以及高效的对数据进行处理,才选择了最后的Mybatis框架,以方便对数据库的设计过程。在处理业务请求的时候,其对应的安全性以及数据的操作和基本回传都显得特别重要。一个网站是可以把用户信息进行维护的,同时也是可以提高相应交互性的,所以这是必定不能缺少的成分

欢迎来访一碗邹的开发生涯

更多推荐

初学者之《复刻英雄联盟官网之人脸识别登录》②

本文发布于:2023-06-14 01:51:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1424578.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:之人   官网   初学者   英雄   复刻

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!