SpringMVC【校驗器、統一處理異常、RESTful、攔截器】

来源:https://www.cnblogs.com/Java3y/archive/2018/03/17/8592769.html
-Advertisement-
Play Games

前言 本博文主要講解的知識點如下: 校驗器 統一處理異常 RESTful 攔截器 Validation 在我們的Struts2中,我們是繼承ActionSupport來實現校驗的...它有兩種方式來實現校驗的功能 手寫代碼 XML配置 這兩種方式也是可以特定處理方法或者整個Action的 而Spri ...


前言

本博文主要講解的知識點如下:

  • 校驗器
  • 統一處理異常
  • RESTful
  • 攔截器

Validation

在我們的Struts2中,我們是繼承ActionSupport來實現校驗的...它有兩種方式來實現校驗的功能

  • 手寫代碼
  • XML配置
    • 這兩種方式也是可以特定處理方法或者整個Action的

而SpringMVC使用JSR-303(javaEE6規範的一部分)校驗規範,springmvc使用的是Hibernate Validator(和Hibernate的ORM無關)

快速入門

導入jar包

這裡寫圖片描述

配置校驗器



    
    <!-- 校驗器 -->
    <bean id="validator"
        class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <!-- 校驗器 -->
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
        <!-- 指定校驗使用的資源文件,如果不指定則預設使用classpath下的ValidationMessages.properties -->
        <property name="validationMessageSource" ref="messageSource" />
    </bean>

錯誤信息的校驗文件配置


    <!-- 校驗錯誤信息配置文件 -->
    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <!-- 資源文件名 -->
        <property name="basenames">
            <list>
                <value>classpath:CustomValidationMessages</value>
            </list>
        </property>
        <!-- 資源文件編碼格式 -->
        <property name="fileEncodings" value="utf-8" />
        <!-- 對資源文件內容緩存時間,單位秒 -->
        <property name="cacheSeconds" value="120" />
    </bean>

添加到自定義參數綁定的WebBindingInitializer中


    <!-- 自定義webBinder -->
    <bean id="customBinder"
        class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
        <!-- 配置validator -->
        <property name="validator" ref="validator" />
    </bean>

最終添加到適配器中


    <!-- 註解適配器 -->
    <bean
        class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <!-- 在webBindingInitializer中註入自定義屬性編輯器、自定義轉換器 -->
        <property name="webBindingInitializer" ref="customBinder"></property>
    </bean>

創建CustomValidationMessages配置文件

這裡寫圖片描述

定義規則

package entity;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;

public class Items {
    private Integer id;

    //商品名稱的長度請限制在1到30個字元
    @Size(min=1,max=30,message="{items.name.length.error}")
    private String name;

    private Float price;

    private String pic;

    //請輸入商品生產日期
    @NotNull(message="{items.createtime.is.notnull}")
    private Date createtime;

    private String detail;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name == null ? null : name.trim();
    }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        this.price = price;
    }

    public String getPic() {
        return pic;
    }

    public void setPic(String pic) {
        this.pic = pic == null ? null : pic.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail == null ? null : detail.trim();
    }
}

測試:




<%--
  Created by IntelliJ IDEA.
  User: ozc
  Date: 2017/8/11
  Time: 9:56
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>測試文件上傳</title>
</head>
<body>


<form action="${pageContext.request.contextPath}/validation.action" method="post" >
    名稱:<input type="text" name="name">
    日期:<input type="text" name="createtime">
    <input type="submit" value="submit">
</form>

</body>
</html>

Controller需要在校驗的參數上添加@Validation註解...拿到BindingResult對象...


    @RequestMapping("/validation")
    public void validation(@Validated Items items, BindingResult bindingResult) {

        List<ObjectError> allErrors = bindingResult.getAllErrors();
        for (ObjectError allError : allErrors) {
            System.out.println(allError.getDefaultMessage());
        }

    }

由於我在測試的時候,已經把日期轉換器關掉了,因此提示了字元串不能轉換成日期,但是名稱的校驗已經是出來了...

這裡寫圖片描述


分組校驗

分組校驗其實就是為了我們的校驗更加靈活,有的時候,我們並不需要把我們當前配置的屬性都進行校驗,而需要的是當前的方法僅僅校驗某些的屬性。那麼此時,我們就可以用到分組校驗了...

步驟:

  • 定義分組的介面【主要是標識】
  • 定於校驗規則屬於哪一各組
  • 在Controller方法中定義使用校驗分組

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述


統一異常處理

在我們之前SSH,使用Struts2的時候也配置過統一處理異常...

當時候是這麼乾的:

  • 在service層中自定義異常
  • 在action層也自定義異常
  • 對於Dao層的異常我們先不管【因為我們管不著,dao層的異常太致命了】
  • service層拋出異常,Action把service層的異常接住,通過service拋出的異常來判斷是否讓請求通過
  • 如果不通過,那麼接著拋出Action異常
  • 在Struts的配置文件中定義全局視圖,頁面顯示錯誤信息

詳情可看:http://blog.csdn.net/hon_3y/article/details/72772559

那麼我們這次的統一處理異常的方案是什麼呢????

我們知道Java中的異常可以分為兩類

  • 編譯時期異常
  • 運行期異常

對於運行期異常我們是無法掌控的,只能通過代碼質量、在系統測試時詳細測試等排除運行時異常

而對於編譯時期的異常,我們可以在代碼手動處理異常可以try/catch捕獲,可以向上拋出。

我們可以換個思路,自定義一個模塊化的異常信息,比如:商品類別的異常


public class CustomException extends Exception {
    
    //異常信息
    private String message;
    
    public CustomException(String message){
        super(message);
        this.message = message;
        
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
    
    

}

我們在查看Spring源碼的時候發現:前端控制器DispatcherServlet在進行HandlerMapping、調用HandlerAdapter執行Handler過程中,如果遇到異常,在系統中自定義統一的異常處理器,寫系統自己的異常處理代碼。。

這裡寫圖片描述

這裡寫圖片描述

我們也可以學著點,定義一個統一的處理器類來處理異常...

定義統一異常處理器類


public class CustomExceptionResolver implements HandlerExceptionResolver  {

    //前端控制器DispatcherServlet在進行HandlerMapping、調用HandlerAdapter執行Handler過程中,如果遇到異常就會執行此方法
    //handler最終要執行的Handler,它的真實身份是HandlerMethod
    //Exception ex就是接收到異常信息
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {
        //輸出異常
        ex.printStackTrace();
        
        //統一異常處理代碼
        //針對系統自定義的CustomException異常,就可以直接從異常類中獲取異常信息,將異常處理在錯誤頁面展示
        //異常信息
        String message = null;
        CustomException customException = null;
        //如果ex是系統 自定義的異常,直接取出異常信息
        if(ex instanceof CustomException){
            customException = (CustomException)ex;
        }else{
            //針對非CustomException異常,對這類重新構造成一個CustomException,異常信息為“未知錯誤”
            customException = new CustomException("未知錯誤");
        }

        //錯誤 信息
        message = customException.getMessage();
        
        request.setAttribute("message", message);

        
        try {
            //轉向到錯誤 頁面
            request.getRequestDispatcher("/WEB-INF/jsp/error.jsp").forward(request, response);
        } catch (ServletException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return new ModelAndView();
    }

}

配置統一異常處理器

    <!-- 定義統一異常處理器 -->
    <bean class="cn.itcast.ssm.exception.CustomExceptionResolver"></bean>

這裡寫圖片描述

RESTful支持

我們在學習webservice的時候可能就聽過RESTful這麼一個名詞,當時候與SOAP進行對比的...那麼RESTful究竟是什麼東東呢???

RESTful(Representational State Transfer)軟體開發理念,RESTful對http進行非常好的詮釋

如果一個架構支持RESTful,那麼就稱它為RESTful架構...

以下的文章供我們瞭解:

http://www.ruanyifeng.com/blog/2011/09/restful

綜合上面的解釋,我們總結一下什麼是RESTful架構:

  •   (1)每一個URI代表一種資源;
  •   (2)客戶端和伺服器之間,傳遞這種資源的某種表現層;
  •   (3)客戶端通過四個HTTP動詞,對伺服器端資源進行操作,實現"表現層狀態轉化"

關於RESTful冪等性的理解:http://www.oschina.net/translate/put-or-post

簡單來說,如果對象在請求的過程中會發生變化(以Java為例子,屬性被修改了),那麼此是非冪等的。多次重覆請求,結果還是不變的話,那麼就是冪等的。

PUT用於冪等請求,因此在更新的時候把所有的屬性都寫完整,那麼多次請求後,我們其他屬性是不會變的

在上邊的文章中,冪等被翻譯成“狀態統一性”。這就更好地理解了。

其實一般的架構並不能完全支持RESTful的,因此,只要我們的系統支持RESTful的某些功能,我們一般就稱作為支持RESTful架構...

url的RESTful實現

非RESTful的http的url:http://localhost:8080/items/editItems.action?id=1&....

RESTful的url是簡潔的:http:// localhost:8080/items/editItems/1

更改DispatcherServlet的配置

從上面我們可以發現,url並沒有.action尾碼的,因此我們要修改核心分配器的配置


    <!-- restful的配置 -->
    <servlet>
        <servlet-name>springmvc_rest</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 載入springmvc配置 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!-- 配置文件的地址 如果不配置contextConfigLocation, 預設查找的配置文件名稱classpath下的:servlet名稱+"-serlvet.xml"即:springmvc-serlvet.xml -->
            <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>

    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc_rest</servlet-name>
        <!-- rest方式配置為/ -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

在Controller上使用PathVariable註解來綁定對應的參數


    //根據商品id查看商品信息rest介面
    //@RequestMapping中指定restful方式的url中的參數,參數需要用{}包起來
    //@PathVariable將url中的{}包起參數和形參進行綁定
    @RequestMapping("/viewItems/{id}")
    public @ResponseBody ItemsCustom viewItems(@PathVariable("id") Integer id) throws Exception{
        //調用 service查詢商品信息
        ItemsCustom itemsCustom = itemsService.findItemsById(id);
        
        return itemsCustom;
        
    }

當DispatcherServlet攔截/開頭的所有請求,對靜態資源的訪問就報錯:我們需要配置對靜態資源的解析


    <!-- 靜態資源 解析 -->
    <mvc:resources location="/js/" mapping="/js/**" />
    <mvc:resources location="/img/" mapping="/img/**" />

/**就表示不管有多少層,都對其進行解析,/*代表的是當前層的所有資源..


SpringMVC攔截器

在Struts2中攔截器就是我們當時的核心,原來在SpringMVC中也是有攔截器的

用戶請求到DispatherServlet中,DispatherServlet調用HandlerMapping查找Handler,HandlerMapping返回一個攔截的鏈兒(多個攔截),springmvc中的攔截器是通過HandlerMapping發起的。

實現攔截器的介面:


public class HandlerInterceptor1 implements HandlerInterceptor {

    //在執行handler之前來執行的
    //用於用戶認證校驗、用戶許可權校驗
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        
        System.out.println("HandlerInterceptor1...preHandle");
        
        //如果返回false表示攔截不繼續執行handler,如果返回true表示放行
        return false;
    }
    //在執行handler返回modelAndView之前來執行
    //如果需要向頁面提供一些公用 的數據或配置一些視圖信息,使用此方法實現 從modelAndView入手
    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("HandlerInterceptor1...postHandle");
        
    }
    //執行handler之後執行此方法
    //作系統 統一異常處理,進行方法執行性能監控,在preHandle中設置一個時間點,在afterCompletion設置一個時間,兩個時間點的差就是執行時長
    //實現 系統 統一日誌記錄
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("HandlerInterceptor1...afterCompletion");
    }

}

配置攔截器


    <!--攔截器 -->
    <mvc:interceptors>
        <!--多個攔截器,順序執行 -->
        <!-- <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor1"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor2"></bean>
        </mvc:interceptor> -->
        
        <mvc:interceptor>
            <!-- /**可以攔截路徑不管多少層 -->
            <mvc:mapping path="/**" />
            <bean class="cn.itcast.ssm.controller.interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

測試執行順序

如果兩個攔截器都放行


測試結果:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle

HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle

HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion

總結:
執行preHandle是順序執行。
執行postHandle、afterCompletion是倒序執行

1 號放行和2號不放行


測試結果:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion

總結:
如果preHandle不放行,postHandle、afterCompletion都不執行。
只要有一個攔截器不放行,controller不能執行完成

1 號不放行和2號不放行


測試結果:
HandlerInterceptor1...preHandle
總結:
只有前邊的攔截器preHandle方法放行,下邊的攔截器的preHandle才執行。

日誌攔截器或異常攔截器要求

  • 將日誌攔截器或異常攔截器放在攔截器鏈兒中第一個位置,且preHandle方法放行

攔截器應用-身份認證

攔截器攔截


public class LoginInterceptor implements HandlerInterceptor {

    //在執行handler之前來執行的
    //用於用戶認證校驗、用戶許可權校驗
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        
        //得到請求的url
        String url = request.getRequestURI();
        
        //判斷是否是公開 地址
        //實際開發中需要公開 地址配置在配置文件中
        //...
        if(url.indexOf("login.action")>=0){
            //如果是公開 地址則放行
            return true;
        }
        
        //判斷用戶身份在session中是否存在
        HttpSession session = request.getSession();
        String usercode = (String) session.getAttribute("usercode");
        //如果用戶身份在session中存在放行
        if(usercode!=null){
            return true;
        }
        //執行到這裡攔截,跳轉到登陸頁面,用戶進行身份認證
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        
        //如果返回false表示攔截不繼續執行handler,如果返回true表示放行
        return false;
    }
    //在執行handler返回modelAndView之前來執行
    //如果需要向頁面提供一些公用 的數據或配置一些視圖信息,使用此方法實現 從modelAndView入手
    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("HandlerInterceptor1...postHandle");
        
    }
    //執行handler之後執行此方法
    //作系統 統一異常處理,進行方法執行性能監控,在preHandle中設置一個時間點,在afterCompletion設置一個時間,兩個時間點的差就是執行時長
    //實現 系統 統一日誌記錄
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("HandlerInterceptor1...afterCompletion");
    }

}

Controller


@Controller
public class LoginController {
    
    
    //用戶登陸提交方法
    @RequestMapping("/login")
    public String login(HttpSession session, String usercode,String password)throws Exception{
        
        //調用service校驗用戶賬號和密碼的正確性
        //..
        
        //如果service校驗通過,將用戶身份記錄到session
        session.setAttribute("usercode", usercode);
        //重定向到商品查詢頁面
        return "redirect:/items/queryItems.action";
    }
    
    //用戶退出
    @RequestMapping("/logout")
    public String logout(HttpSession session)throws Exception{
        
        //session失效
        session.invalidate();
        //重定向到商品查詢頁面
        return "redirect:/items/queryItems.action";
        
    }
    

}

總結

  • 使用Spring的校驗方式就是將要校驗的屬性前邊加上註解聲明。
  • **在Controller中的方法參數上加上@Validation註解。那麼SpringMVC內部就會幫我們對其進行處理(創建對應的bean,載入配置文件)**
  • BindingResult可以拿到我們校驗錯誤的提示
  • 分組校驗就是將讓我們的校驗更加靈活:某方法需要校驗這個屬性,而某方法不用校驗該屬性。我們就可以使用分組校驗了。
  • 對於處理異常,SpringMVC是用一個統一的異常處理器類的。實現了HandlerExceptionResolver介面。
  • 對模塊細分多個異常類,都交由我們的統一異常處理器類進行處理。
  • 對於RESTful規範,我們可以使用SpringMVC簡單地支持的。將SpringMVC的攔截.action改成是任意的。同時,如果是靜態的資源文件,我們應該設置不攔截。
  • 對於url上的參數,**我們可以使用@PathVariable將url中的{}包起參數和形參進行綁定**
  • SpringMVC的攔截器和Struts2的攔截器差不多。不過SpringMVC的攔截器配置起來比Struts2的要簡單。
    • 至於他們的攔截器鏈的調用順序,和Filter的是沒有差別的。

如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關註微信公眾號:Java3y


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

-Advertisement-
Play Games
更多相關文章
  • package com.swift.department; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; /*SQL語句的編寫 JDBC操作MySQL資料庫常用... ...
  • 運行python程式的方式可分為: 1.互動式(能快速得到結果,但是無法保存文件) 2.python程式路徑 Python解釋器啟動: 1. 先啟動python解釋器 2. 將盤裡的文件讀入記憶體 3.解釋 輸入輸出: 1.輸出: 2.輸入:input()接收用戶輸入,把用戶輸入的內容轉成字元串 變數 ...
  • 一、Python介紹 Python是著名的“龜叔”Guido van Rossum在1989年聖誕節期間,為了打發無聊的聖誕節而編寫的一個編程語言。 Python這個名字,來自“龜叔”所摯愛的電視劇Monty Python’s Flying Circus。他希望這個新的叫做Python的語言,能符合 ...
  • 一、導入方式:import time 二、時間戳的概念:指格林威治時間1970年01月01日00時00分00秒(北京時間1970年01月01日08時00分00秒)起至現在的總秒數。 三、常用函數: 1.time.loclatime([secs]) #返回時間元祖: print(time.loclat ...
  • 1. Django安裝 2. 創建項目 如需要中文,可以修改django支持中文環境,編輯settings.py文件,設定內容如下: 3. 配置資料庫 Django預設採用sqllite3資料庫作為數據持久存儲,實際工作中一般使用MySQL作為結構化數據存儲,在python2中使用python-My ...
  • //凱魯嘎吉 - 博客園 http://www.cnblogs.com/kailugaji/ 程式運行前的當前目錄: 程式運行結果: 當前目錄多了一個文件wrr.txt 打開該文件: 裡面已經有了剛剛輸入的內容: Hello world!I am RONGRONG WANG!My English n ...
  • Pandas用於數據處理: 使用示例: 1. 2.排序(預設升序) 3. ...
  • 說在前面:1.學習緣由及學習途徑: 在學了Python,c#(自認為未精通)之後,我決定學一下C++。 於是去網上找視頻教程,發現都不適合我這種有一定基礎的自學者,要麼是不完整的高級教程,要麼是零基礎的浪費時間。 於是向摯友購入一本二手《C++ primer plus》,在空餘時間翻一翻,自學。 2 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...