10.5 搜索的優化版

来源:http://www.cnblogs.com/jiekzou/archive/2016/07/12/5661752.html
-Advertisement-
Play Games

目錄:ASP.NET MVC企業級實戰目錄 像www.verycd.com、博客園、淘寶、京東都有實現站內搜索功能,站內搜索無論在性能和用戶體驗上都非常不錯,本節,通過使用Lucene.Net來實現站內搜索。 演示效果預覽如下圖10-22~10-24所示。 圖10-22 圖10-23 圖10-24 ...


目錄:ASP.NET MVC企業級實戰目錄

像www.verycd.com、博客園、淘寶、京東都有實現站內搜索功能,站內搜索無論在性能和用戶體驗上都非常不錯,本節,通過使用Lucene.Net來實現站內搜索。

演示效果預覽如下圖10-22~10-24所示。

圖10-22

 

圖10-23

 

圖10-24

在10.4節,已經完成了搜索的第一個版本,但是還有許多地方需要優化。比如說,我要統計關鍵詞搜索的頻率高的詞,也即熱詞,以及像百度搜索那樣,在輸入關鍵字後,會自動把搜索相關的熱詞自動以下拉列表的形式帶出來。還有諸如搜索結果分頁,查看文章明細等。

10.5.1 熱詞統計

思路:

1、  首先,我們腦海裡要明確一點:搜索關鍵字的統計,實時性是不高的。也就是說我們可以定期的去進行統計。

2、  客戶的每一次搜索記錄,我們都需要存起來,這樣才能夠統計得到。

從第1點,我們腦海中就會呈現一張彙總統計表,從第2點中,我們會想到使用一張搜索記錄明細表。那方案就很明瞭了,只需要定期的從明細表中Group by查詢,然後把查詢結構放到彙總表中。怎麼放到彙總表中?是直接Update更新嗎?其實我們可以有更快捷的方式,那就是對彙總表先進行truncate,然後再進行insert操作。

表10-1 搜索彙總統計表SearchTotals

欄位名稱

欄位類型

說明

Id

char(36)

主鍵,採用Guid方式存儲

KeyWords

nvarchar(50)

搜索關鍵字

SearchCounts

int

搜索次數

表10-2 搜索明細表SearchDetails

欄位名稱

欄位類型

說明

Id

char(36)

主鍵,採用Guid方式存儲

KeyWords

nvarchar(50)

搜索關鍵字

SearchDateTime

datetime

搜索時間

操作步驟:

(1)在Models文件夾中,新建兩個類SearchTotal、SearchDetail。

SearchTotal.cs代碼:

using System;
using System.ComponentModel.DataAnnotations;

namespace SearchDemo.Models
{
    public class SearchTotal
    {
        public Guid Id { get; set; }
        [StringLength(50)]
        public string KeyWords { get; set; }
        public int SearchCounts { get; set; }
    }
}

SearchDetail.cs代碼:

using System;
using System.ComponentModel.DataAnnotations;

namespace SearchDemo.Models
{
    public class SearchDetail
    {
        public Guid Id { get; set; }
        [StringLength(50)]
        public string KeyWords { get; set; }
        public Nullable<DateTime> SearchDateTime { get; set; }
    }
}

(2)修改SearchDemoContext類,新增了屬性SearchTotal、SearchDetail。

using System.Data.Entity;

namespace SearchDemo.Models
{
    public class SearchDemoContext : DbContext
    {
        public SearchDemoContext() : base("name=SearchDemoContext") { }
        public DbSet<Article> Article { get; set; }
        //下麵兩個屬性是新增加的
        public DbSet<SearchTotal> SearchTotal { get; set; }
        public DbSet<SearchDetail> SearchDetail { get; set; }
    }
}

3)更新資料庫

由於修改了EF上下文,新增了兩個模型類,所以需要進行遷移更新資料庫操作。

將應用程式重新編譯,然後選擇工具->庫程式包管理器->程式包管理控制台。

打開控制台,輸入enable-migrations -force ,然後回車。回車後會在項目項目資源管理器中會出現Migrations文件夾,打開Configuration.cs 文件,將AutomaticMigrationsEnabled 值改為 true,然後在控制臺中輸入 update-database 運行。操作完成之後,會在資料庫SearchDemo中多新建兩張表SearchTotals、SearchDetails,而原來的Articles表保持不變。如圖10-20所示。

 

圖10-20

(4)保存搜索記錄

用戶在每次搜索的時候,要把搜索記錄存入SearchDetails表中。為了方便,這裡我是在用戶每次點擊搜索之後就立即往SearchDetails表中插入記錄了,也就是同步操作,而實際上,如果為了提升搜索的效率,我們可以採用非同步操作,即把搜索記錄的數據先寫入redis隊列中,後臺再開闢一個線程來監聽redis隊列,然後把隊列中的搜索記錄數據寫入到數據表中。因為在每次點擊搜索的時候,我們把記錄往redis寫和把記錄直接往關係型資料庫中寫的效率是相差很大的。

 //先將搜索的詞插入到明細表。
            SearchDetail _SearchDetail = new SearchDetail { Id = Guid.NewGuid(), KeyWords = kw, SearchDateTime = DateTime.Now };
            db.SearchDetail.Add(_SearchDetail);
            int r = db.SaveChanges();

(5)定時更新SearchTotals表記錄

看到這種定時任務操作,這裡可以採用Quartz.Net框架,為了方便,我把Quartz.Net的Job寄宿在控制台程式中,而實際工作中,我則更傾向於將其寄宿在Windows服務中。如果有必要,可以把這個定時更新SearchTotals表記錄的程式部署到獨立的伺服器,這樣可以減輕Web伺服器的壓力。

  1. 新建控制台程式QuartzNet,添加Quartz.dll和Common.Logging.dll的程式集引用,這裡採用Database First的方式,添加ADO.NET實體數據模型,把表SearchTotals、SearchDetails添加進來。

2.添加KeyWordsTotalService.cs類,裡面封裝兩個方法,清空SearchTotals表,然後把SearchDetails表的分組查詢結構插入到SearchTotals表,這裡我只統計近30天內的搜索明細。

namespace QuartzNet
{
    public class KeyWordsTotalService
    {
        private SearchDemoEntities db = new SearchDemoEntities();
        /// <summary>
        /// 將統計的明細表的數據插入。
        /// </summary>
        /// <returns></returns>
        public bool InsertKeyWordsRank()
        {
            string sql = "insert into SearchTotals(Id,KeyWords,SearchCounts) select newid(),KeyWords,count(*)  from SearchDetails where DateDiff(day,SearchDetails.SearchDateTime,
getdate())<=30 group by SearchDetails.KeyWords
"; return this.db.Database.ExecuteSqlCommand(sql) > 0; } /// <summary> /// 刪除彙總中的數據。 /// </summary> /// <returns></returns> public bool DeleteAllKeyWordsRank() { string sql = "truncate table SearchTotals"; return this.db.Database.ExecuteSqlCommand(sql) > 0; } } }

3. 添加TotalJob.cs類,繼承Ijob介面,並實現Execute方法。

namespace QuartzNet
{
    public class TotalJob : IJob
    {
        /// <summary>
        /// 將明細表中的數據插入到彙總表中。
        /// </summary>
        /// <param name="context"></param>
        public void Execute(JobExecutionContext context)
        {
            KeyWordsTotalService bll = new KeyWordsTotalService();
            bll.DeleteAllKeyWordsRank();
            bll.InsertKeyWordsRank();
        }
    }
}

4.修改Program.cs類

using Quartz;
using Quartz.Impl;
using System;

namespace QuartzNet
{
    class Program
    {
        static void Main(string[] args)
        {
            IScheduler sched;
            ISchedulerFactory sf = new StdSchedulerFactory();
            sched = sf.GetScheduler();
            JobDetail job = new JobDetail("job1", "group1", typeof(TotalJob));//IndexJob為實現了IJob介面的類
            DateTime ts = TriggerUtils.GetNextGivenSecondDate(null, 5);//5秒後開始第一次運行
            TimeSpan interval = TimeSpan.FromSeconds(50);//每隔50秒執行一次
            Trigger trigger = new SimpleTrigger("trigger1", "group1", "job1", "group1", ts, null,
                                                    SimpleTrigger.RepeatIndefinitely, interval);//每若幹時間運行一次,時間間隔可以放到配置文件中指定

            sched.AddJob(job, true);
            sched.ScheduleJob(trigger);
            sched.Start();
            Console.ReadKey();
        }
    }
}

這裡我是直接把Job和計劃都直接寫到代碼中了,理由還是因為方便。而實際工作中,我們應當把這些信息儘量寫到配置文件中,這樣後面改動起來方便,不需要修改代碼,只需要修改配置文件。

為了儘快看到效果,我這裡是每隔50秒就進行了一次統計操作,而在實際應用中,我們的時間間隔可能是幾個小時甚至一天,因為像這樣的大數據統計,對實時性的要求不高,我們可以儘量減少對資料庫的IO讀寫次數。

保持運行控制台程式QuartzNet,然後我們去進行搜索操作,這樣後臺就定期的生成了搜索統計記錄。

10.5.2 熱門搜索

10.5.2.1 展示熱門搜索

其實就是從表SearchTotals中按照搜索次數進行降序排列,然後取出數條記錄而已。

LastSearch控制器中的Index方法中添加如下代碼:

var keyWords = db.SearchTotal.OrderByDescending(a => a.SearchCounts).Select(x => x.KeyWords).Skip(0).Take(6).ToList();
            ViewBag.KeyWords = keyWords;

View視圖中

<div id="divKeyWords"><span>熱門搜索:</span>@if (ViewBag.KeyWords != null) {
             foreach (string v in ViewBag.KeyWords) { 
              <a href="#">@v</a>
             }
         }</div>

接下來,我想要實現如下圖10-21所示的效果:

 

圖10-21

當我點擊一個熱詞的時候,自動載入到文本框,並點擊“搜索”按鈕。

在View中添加代碼:

<script type="text/javascript">
    $(function () {
        $("#divKeyWords a").click(function () {
            $("#txtSearch").val($(this).html());
            $("#btnSearch").click();
        });
});
</script>
10.5.2.2 搜索下拉框

這裡我引入一個第三方js框架Autocomplete,它能在文本框中輸入文字的時候,自動從後臺抓去數據下拉列表。

雲盤中我提供了Autocomplete.rar,將其解壓,然後拷貝到SearchDemo項目中的lib目錄下。

在SearchDemo項目中的KeyWordsTotalService.cs類中添加方法

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;

namespace SearchDemo.Common
{
    public class KeyWordsTotalService
    {
        private SearchDemoContext db = new SearchDemoContext();

        public List<string> GetSearchMsg(string term)
        {
            try
            {
                //存在SQL註入的安全隱患
                //string sql = "select KeyWords from SearchTotals where KeyWords like '"+term.Trim()+"%'";
                //return db.Database.SqlQuery<string>(sql).ToList();
                string sql = "select KeyWords from SearchTotals where KeyWords like @term";
                return db.Database.SqlQuery<string>(sql, new SqlParameter("@term", term+"%")).ToList();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
    }
}

然後在LastSearch控制器中添加方法:

     /// <summary>
        /// 獲取客戶列表 模糊查詢
        /// </summary>
        /// <param name="term"></param>
        /// <returns></returns>
        public string GetKeyWordsList(string term)
        {
            if (string.IsNullOrWhiteSpace(term))
                return null;

            var list = new KeyWordsTotalService().GetSearchMsg(term);
            //序列化對象
            //儘量不要用JavaScriptSerializer,為什麼?性能差,完全可用Newtonsoft.Json來代替
            //System.Web.Script.Serialization.JavaScriptSerializer js = new System.Web.Script.Serialization.JavaScriptSerializer();
            //return js.Serialize(list.ToArray());
            return JsonConvert.SerializeObject(list.ToArray());
        }

我們來看View:

<link href="~/lib/Autocomplete/css/ui-lightness/jquery-ui-1.8.17.custom.css" rel="stylesheet" />
<script src="~/lib/Autocomplete/js/jquery-ui-1.8.17.custom.min.js"></script>
<script type="text/javascript">
    $(function () {
        $("#divKeyWords a").click(function () {
            $("#txtSearch").val($(this).html());
            $("#btnSearch").click();
        });
        getKeyWordsList("txtSearch");
    });
    //自動載入搜索列表
    function getKeyWordsList(txt) {
        if (txt == undefined || txt == "")
            return;
        $("#" + txt).autocomplete({
            source: "/LastSearch/GetKeyWordsList",
            minLength: 1
        });
    }
</script>

10.5.3 標題和內容都支持搜索並高亮展示

在10.4中,只支持在內容中對關鍵詞進行搜索,而實際上,我們可能既要支持在標題中搜索,也要在內容中搜索。

這裡引入了BooleanQuery,我們的查詢條件也添加了一個titleQuery。

搜索方法中,如下代碼有修改:

 PhraseQuery query = new PhraseQuery();//查詢條件
            PhraseQuery titleQuery = new PhraseQuery();//標題查詢條件
            List<string> lstkw = LuceneHelper.PanGuSplitWord(kw);//對用戶輸入的搜索條件進行拆分。

            foreach (string word in lstkw)            {
                query.Add(new Term("Content", word));//contains("Content",word)
                titleQuery.Add(new Term("Title", word));
            }
            query.SetSlop(100);//兩個詞的距離大於100(經驗值)就不放入搜索結果,因為距離太遠相關度就不高了

            BooleanQuery bq = new BooleanQuery();
            //Occur.Should 表示 Or , Must 表示 and 運算
            bq.Add(query, BooleanClause.Occur.SHOULD);
            bq.Add(titleQuery, BooleanClause.Occur.SHOULD);

            TopScoreDocCollector collector = TopScoreDocCollector.create(1000, true);//盛放查詢結果的容器
            searcher.Search(bq, null, collector);//使用query這個查詢條件進行搜索,搜索結果放入collector

10.5.4 與查詢、或查詢、分頁

前面我們在搜索的時候,其實採用的都是與查詢,也就是說,我輸入“諸葛亮周瑜”,則只會查找出,既存在諸葛亮,又存在周瑜的記錄。那麼有時候,我們是想查詢存在諸葛亮或者周瑜的記錄的,這也就是所謂的或查詢。

我在界面添加一個覆選框“或查詢”,來讓用戶決定採用何種方式進行查詢。

至於分頁,這裡採用MvcPager,關於MvcPager的使用方法請參見4.6.3。

View完整代碼預覽:

@{
    ViewBag.Title = "Index";
}
@model PagedList<SearchDemo.Models.SearchResult>
@using Webdiyer.WebControls.Mvc;
@using SearchDemo.Models;
<style type="text/css">
.search-text2{ display:block; width:528px; height:26px; line-height:26px; float:left; margin:3px 5px; border:1px solid gray; outline:none; font-family:'Microsoft Yahei'; font-size:14px;}
.search-btn2{width:102px; height:32px; line-height:32px; cursor:pointer; border:0px; background-color:#d6000f;font-family:'Microsoft Yahei'; font-size:16px;color:#f3f3f3;}
.search-list-con{width:640px; background-color:#fff; overflow:hidden; margin-top:0px; padding-bottom:15px; padding-top:5px;}
.search-list{width:600px; overflow:hidden; margin:15px 20px 0px 20px;}
.search-list dt{font-family:'Microsoft Yahei'; font-size:16px; line-height:20px; margin-bottom:7px; font-weight:normal;}
.search-list dt a{color:#2981a9;}
.search-list dt a em{ font-style:normal; color:#cc0000;}
#divKeyWords {text-align:left;width:520px;padding-left:4px;}
#divKeyWords a {text-decoration:none;}
#divKeyWords a:hover {color:red;}
</style>
<link href="~/lib/Autocomplete/css/ui-lightness/jquery-ui-1.8.17.custom.css" rel="stylesheet" />
@using(@Html.BeginForm(null, null, FormMethod.Get))
{
    @Html.Hidden("hidfIsOr")
    <div>@Html.TextBox("txtSearch", null, new { @class="search-text2"})<input type="submit" value="搜索" name="btnSearch" id="btnSearch"  class="search-btn2"/><input type="checkbox" id="isOr" value="false"/>或查詢</div>
    <div id="divKeyWords"><span>熱門搜索:</span>@if (ViewBag.KeyWords != null) {
             foreach (string v in ViewBag.KeyWords) { 
              <a href="#">@v</a>
             }
         }</div>
    <div class="search-list-con">
        <dl class="search-list">
            @if (Model != null&& Model.Count > 0)
            {
                foreach (var viewModel in Model)
                {
                <dt><a href="@viewModel.Url" target="_blank">@MvcHtmlString.Create(viewModel.Title)</a><span style="margin-left:50px;">@viewModel.CreateTime</span></dt>
                <dd>@MvcHtmlString.Create(viewModel.Msg)</dd>
                }
            } 
              @Html.Pager(Model, new PagerOptions
 {
     PageIndexParameterName = "id",
     ShowPageIndexBox = true,
     FirstPageText = "首頁",
     PrevPageText = "上一頁",
     NextPageText = "下一頁",
     LastPageText = "末頁",
     PageIndexBoxType = PageIndexBoxType.TextBox,
     PageIndexBoxWrapperFormatString = "請輸入頁數{0}",
     GoButtonText = "轉到"
 })
     <br />
     >>分頁 共有 @(Model==null? 0: Model.TotalItemCount) 篇文章 @(Model==null?0:Model.CurrentPageIndex)/@(Model==null?0:Model.TotalPageCount)
        </dl>
    </div>
    <div>@ViewData["ShowInfo"]</div>
}
<script type="text/javascript">
    $(function () {
        $("#divKeyWords a").click(function () {
            $("#txtSearch").val($(this).html());
            $("#btnSearch").click();
        });
        getKeyWordsList("txtSearch");
        $("#isOr").click(function () {
            if ($(this).attr("checked") == "checked") {
                $("#hidfIsOr").val(true);
            }
            else {
                $("#hidfIsOr").val(false);
            }
        });
        if ($("#hidfIsOr").val() == "true") {
            $("input[type='checkbox']").prop("checked", true);
        }
    });
    //自動載入搜索列表
    function getKeyWordsList(txt) {
        if (txt == undefined || txt == "")
            return;
        $("#" + txt).autocomplete({
            source: "/LastSearch/GetKeyWordsList",
            minLength: 1
        });
    }
</script>
<script src="~/lib/Autocomplete/js/jquery-ui-1.8.17.custom.min.js"></script>
View Code

然後,各位看官請再看LastSearch控制器中的方法:

 public class LastSearchController : Controller
    {
        //
        // GET: /LastSearch/

        string indexPath = System.Configuration.ConfigurationManager.AppSettings["lucenedir"];
        private SearchDemoContext db = new SearchDemoContext();

              public ActionResult Index(string txtSearch, bool? hidfIsOr, int id = 1)
        {
            PagedList<SearchResult> list = null;
            if (!string.IsNullOrEmpty(txtSearch))//如果點擊的是查詢按鈕
            {
                //list = Search(txtSearch);
                list = (hidfIsOr == null || hidfIsOr.Value == false) ? OrSearch(txtSearch, id) : AndSearch(txtSearch, id);
            }
            var keyWords = db.SearchTotal.OrderByDescending(a => a.SearchCounts).Select(x => x.KeyWords).Skip(0).Take(6	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題目描述 眾所周知,香港的黑社會組織猖獗,警方希望能摸清他們的內部構成情況,特派小生前往調查。經過長期的卧底,小生初步獲得了一些資料:整個組織有 n 個人,任何兩個認識的人不是朋友就是敵人。 而且滿足:①我朋友的朋友是我的朋友;②我敵人的敵人是我的朋友。所有是朋友的人組成一個團夥。 現在,警方委派你 ...
  • 以前學習ASP.NET MVC時,學習與應用,操作過數據顯示,添加,編輯,更新和刪除等功能。很多方法是相通的,看自己是怎樣來進行方便,快捷,高效率。今天Insus.NET寫的練習,是直接對綁定在Table的數據進行更新,刪除。在項目中,創建一個實體,也就是說,對資料庫時行通信,對數據進行操作: pu ...
  • 首先,新建一個MVC類型的Web項目: 然後在Model文件夾下定義一個Student實體: 然後新建一個Student控制器: 創建對應的Index視圖: 相對應的_StudentList分部視圖: 編譯一下:修改路由為Student控制器,Index方法,運行,我們就可以看到結果了 然後工作中還 ...
  • 開發程式的時候經常會引用一些第三方的DLL,然後編譯生成的exe文件就不能脫離這些DLL獨立運行了。 但是,很多時候我們本想開發一款只需要一個exe就能完美運行的小工具。那該怎麼辦呢? 下文介紹一種超簡單的方法,不用寫一行代碼就可輕鬆實現。 這裡我們需要用到一款名為Fody.Costura的工具。F ...
  • Mongodb是3.2.7版本 最近在學習mongodb資料庫在網上找到的都不是2.X版本以下的,因為驅動從2.X以後修改了很多,以前不支持linq現2.X也支持了, Mongodb 啟動服務就不說了現在就來看看基本的操作 上代碼: 首先定義一個模型用來測試操作 將mongob C#driver 添 ...
  • 前幾天看了.NET的EF(Entity Framework),發現居然有這麼先進的東西,只要操作幾個類就可以完成資料庫的增刪查改,而且可以用資料庫直接導出類(DB First)、也可以用類來生成資料庫(Code First),簡直太先進了。 之前用EF做一個API服務的網站,每次要添加一條方法就要在 ...
  • 最近研究C 相關的ORC技術,圖像識別一般C和C++這種底層語言做的比較多,C 主要是依托一些封裝好的組件進行調用,這裡介紹三種身份證識別的方法。 一:調用大公司API介面,百度、雲脈,文通科技都有相關的API介紹。 二:調用圖像處理類庫,EmguCV是OpenCV的一個跨平臺的.Net封裝,該封裝 ...
  • ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...