SpringMVC——對Ajax的處理(包含 JSON 類型)

来源:http://www.cnblogs.com/solverpeng/archive/2016/08/30/5821726.html
-Advertisement-
Play Games

一、首先要搞明白的一些事情。 1.從客戶端來看,需要搞明白: (1)要發送什麼樣格式的 JSON 數據才能被伺服器端的 SpringMVC 很便捷的處理,怎麼才能讓我們寫更少的代碼,如何做好 JSON 數據和實體之間的對應。 (2)如何組織這些發送的數據。 2.從伺服器端來看,需要搞明白: (1)S ...


一、首先要搞明白的一些事情。

1.從客戶端來看,需要搞明白:

(1)要發送什麼樣格式的 JSON 數據才能被伺服器端的 SpringMVC 很便捷的處理,怎麼才能讓我們寫更少的代碼,如何做好 JSON 數據和實體之間的對應。

(2)如何組織這些發送的數據。

2.從伺服器端來看,需要搞明白:

(1)SpringMVC 如何返回 JSON 數據。

(2)SpringMVC 如何處理請求的複雜數據。

3.$.ajax 的幾個參數:

(1)contentType:

contentType: 'application/json;charset=utf-8',作為請求頭,用來告訴伺服器消息的主體是序列化後的 JSON 字元串。除了低版本的 ie 瀏覽器外,各大瀏覽器都原生支持 JSON.stringify() 對對象進行序列化。

(2)dataType:預期伺服器返回的數據類型。

4.SpringMVC 是如何處理 JSON 數據的

5.總體的思想:

(1)SpringMVC 能完成的,儘量藉助於 SpringMVC,而不是我們手動的去解析。

(2)SpringMVC 解析不了的,儘量藉助於第三方的 Jar 包來解析。

(3)SpringMVC 和 第三方 Jar 包解決不了的時候,我們再自己去解析。

 

二、想要搞明白第一個問題,前提是先要搞明白第一個問題:SpringMVC 是如何處理 JSON 數據的。

1.使用 HttpMessageConverter<T> 來處理  JSON 數據的。

Spring 的 HttpMessageConverter<T> 負責將請求信息轉換為一個對象,將對象輸出為響應信息。

2.API

(1)boolean canRead(Class<?> clazz, MediaType mediaType);

轉換器是否可將請求信息轉換為 clazz 類型的對象,同時支持指定的 MIME 類型,如: text/html,application/json 等。

(2)boolean canWrite(Class<?> clazz, MediaType mediaType);

轉換器是否可以將 clazz 類型的對象寫到響應中,響應支持的類型在 mediaType 中定義。

(3)List<MediaType> getSupportedMediaTypes();

改轉換器支持的 MediaType 類型。

(4)T read(Class<? extends T> clazz, HttpInputMessage inputMessage);

將請求信息流轉換為 clazz 類型的對象。

(5)void write(T t, MediaType contentType, HttpOutputMessage outputMessage)。

將 T 類型的對象寫到響應輸出流中,同時指定 MediaType。

3.實現類

3.從上圖可以看出,Spring 預設支持使用 Jackson來處理 JSON 問題。添加 Jackson Jar 包後,來看 RequestMappingHadlerAdapter 裝配的 HttpMessageConverter:

導入的 Jackson Jar 包:

4.具體的處理方法:

(1)使用 @RequestBody 和 HttpEntity<T> 對請求進行處理。

(2)使用 @ResponseBody 和 ResponseEntity<T> 對響應進行處理。

(3)@RequestBody 對處理方法的入參進行標註。

(4)@ResponseBody 對處理方法的簽名進行標註。

(5)HttpEntity<T> 和 ResponseEntity<T> 作為處理方法的入參使用。

具體的使用方法會在下麵例子中進行說明。

5.@RequestBody 和 @ResponseBody 是可以同時使用的。

 

三、上面簡單介紹了 SpringMVC 是怎麼處理 JSON 數據的,現在來看第二個問題:發送什麼樣格式的 JSON 數據才能被伺服器端的 SpringMVC 很便捷的處理,這裡主要指的是請求的 JSON 字元串和實體的映射。

以一個簡單的實體為例:Person

/**
 * @author solverpeng
 * @create 2016-08-12-10:50
 */
public class Person {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @NotBlank(message = "人名不能為空")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
Person.java

(1)對於簡單的一個Person 對象來說,我們甚至都不需要藉助於 JSON 就可以完成請求的數據與實體之間的映射。

請求:

$("#testJson").click(function () {
    $.ajax({
        url: "testJson",
        type: "post",
        data: {
            name : "abc",
            age : "23"
        },
        success: function (result) {
            console.log(result);
        }
    });
});

handler 方法:

@RequestMapping("/testJson")
public Person testJson(Person person) {
    System.out.println("person:" + person);
    return person;
}

(2)對於Person數組來說,需要發送什麼樣的格式才能被 SpringMVC 直接處理?

請求:

$("#testJson6").click(function () {
    $.ajax({
        url: "testJson6",
        type: "post",
        data:'[{ "name": "Brett", "age":"12" }, { "name": "Jason", "age":"23" }, { "name": "Elliotte", "age":"33" }]',
        contentType: "application/json; charset=utf-8",
        success: function (result) {
            console.log(result);
        }
    });
});

handler 方法:

@RequestMapping("/testJson6")
public String testJson6(@RequestBody List<Person> persons) {
    System.out.println("persons:" + persons);
    return "success";
}

註意:

(1)需要指定 "contentType",同時需要註意的是:發送的請求數據不在 Form data 中,而是在 Request Payload 中。關於 [Request Payload] ,在後面說明。

(2)必須要指定 @RequestBody ,否則無法解析。

 

四、第三個問題:如何組織這些數據以及SpringMVC 如何處理這些數據,做好映射。

(1)說明:

上面說的兩個例子,僅僅是最簡單的一種形式。現在對其進行擴展,在四里,所說的 SpringMVC 如何處理這些數據,不僅僅指的是SpringMVC,也包括SpringMVC處理不了,使用第三方來處理,或者第三方處理不了,我自己來處理。

同時這裡的數據也不僅僅指的 JSON 類型的數據。

(2)對於非表單的 Ajax 提交,這裡只提供比較簡單的一種方式。還是以上面的 Person 為例。

e1:

數據的組織與請求的發送:

var personList = [];
personList.push({name: "李四",age: "23"});
personList.push({name: "張三",age: "12"});
$("#testJson5").click(function () {
    $.ajax({
        type: "POST",
        url: "testJson5",
        data: JSON.stringify(personList),//將對象序列化成JSON字元串
        contentType: 'application/json;charset=utf-8', //設置請求頭信息
        success: function (data) {
        },
        error: function (res) {
        }
    });
});

handler 方法:

@RequestMapping("/testJson5")
public String testJson5(@RequestBody List<Person> persons) {
    System.out.println(persons);
    return "success";
}

(3)基於表單的 Ajax 提交。

提供一個序列化方法:

$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

還有一種序列化方式:

★單表單情況:

表單:

<form action="" method="post">
    First Name:<input type="text" name="firstName" maxlength="12" size="12"/> <br/>
    Last Name:<input type="text" name="lastName" maxlength="36" size="12"/> <br/>
    Gender:<br/>
    Male:<input type="radio" name="gender" value="1"/><br/>
    Female:<input type="radio" name="gender" value="0"/><br/>
    Favorite Food:<br/>
    Steak:<input type="checkbox" name="foods" value="Steak"/><br/>
    Pizza:<input type="checkbox" name="foods" value="Pizza"/><br/>
    Chicken:<input type="checkbox" name="foods" value="Chicken"/><br/>
    <textarea wrap="physical" cols="20" name="quote" rows="5">Enter your favorite quote!</textarea><br/>
    Select a Level of Education:<br/>
    <select name="education">
        <option value="Jr.High">Jr.High</option>
        <option value="HighSchool">HighSchool</option>
        <option value="College">College</option>
    </select><br/>
    Select your favorite time of day:<br/>
    <select size="3" name="tOfD">
        <option value="Morning">Morning</option>
        <option value="Day">Day</option>
        <option value="Night">Night</option>
    </select>

    <p><input type="submit"/></p>
</form>

對應的實體:

/**
 * @author solverpeng
 * @create 2016-08-16-11:14
 */
public class Student {
    private String firstName;
    private String lastName;
    private Integer gender;
    private List<String> foods;
    private String quote;
    private String education;
    private String tOfD;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public List<String> getFoods() {
        return foods;
    }

    public void setFoods(List<String> foods) {
        this.foods = foods;
    }

    public String getQuote() {
        return quote;
    }

    public void setQuote(String quote) {
        this.quote = quote;
    }

    public String getEducation() {
        return education;
    }

    public void setEducation(String education) {
        this.education = education;
    }

    public String gettOfD() {
        return tOfD;
    }

    public void settOfD(String tOfD) {
        this.tOfD = tOfD;
    }

    @Override
    public String toString() {
        return "Student{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", gender=" + gender +
                ", foods=" + foods +
                ", quote='" + quote + '\'' +
                ", education='" + education + '\'' +
                ", tOfD='" + tOfD + '\'' +
                '}';
    }
}
Student.java

e1:使用 serializeObject()

序列化後的值:

JSON.stringify($('form').serializeObject()):

{"firstName":"jack","lastName":"lily","gender":"1","foods":["Pizza","Chicken"],"quote":"hello hello","education":"Jr.High","tOfD":"Day"}

請求:

$(function() {
    $('form').submit(function() {
        $.ajax({
            url : "testStudent",
            data : JSON.stringify($('form').serializeObject()),
            contentType : "application/json;charset=utf-8",
            type : "post",
            success : function (result) {
                console.log(result);
            }
        });
        return false;
    });
});

e11:SpringMVC自身進行處理

handler 方法:

@RequestMapping("/testStudent")
public String testStudent(@RequestBody Student student) {
    System.out.println(student);
    return "success";
}

e12:引入第三方 Jar 包進行處理。

準備:

導入 sl4j jar 包,同時添加 JsonUtil 工具類。

public final class JsonUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class);

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    /**
     * 將 POJO 轉換為 JSON
     */
    public static <T> String toJson(T obj) {
        String json;

        try {
            json = OBJECT_MAPPER.writeValueAsString(obj);
        } catch(JsonProcessingException e) {
            LOGGER.error("convert POJO to JSON failure", e);
            throw new RuntimeException(e);
        }

        return json;
    }

    /**
     * 將 JSON 轉換為 POJO
     */
    public static <T> T fromJson(String json, Class<T> type) {
        T pojo;
        try {
            pojo = OBJECT_MAPPER.readValue(json, type);
        } catch(IOException e) {
            LOGGER.error("convert JSON to POJO failure", e);
            throw new RuntimeException(e);
        }
        return pojo;
    }

}
JsonUtil.java

後端處理:

@RequestMapping("/testStudent")
public String testStudent(@RequestBody String inputBody) {
    Student student = JsonUtil.fromJson(inputBody, Student.class);
    System.out.println(student);
    return "success";
}

都可以正常列印 Student 對象。

e2:使用 serialize()

序列化後的值:

$('form').serialize():

firstName=jack&lastName=lily&gender=1&foods=Pizza&foods=Chicken&quote=hello+hello&education=Jr.High&tOfD=Day

請求:

$(function() {
    $('form').submit(function() {
        $.ajax({
            url : "testStudent",
            data : $('form').serialize(),
            type : "post",
            success : function (result) {
                console.log(result);
            }
        });
        return false;
    });
});

handler 方法:

@RequestMapping("/testStudent")
public String testStudent(Student student) {
    System.out.println(student);
    return "success";
}

可以正常列印 Student 對象。

e1 和 e2 對比說明:

e1提交的 JSON 數據,e2 提交的不是 JSON 格式的數據。e1 的請求參數存放在 [Request Payload] 中,而 e2 的請求參數存放在 Form Data 中。

★單表單複雜數據

表單還是上面的 Student 表單,但是在表單外增加了:

<span id="amount">33</span>

需求是:通過 Ajax 發送表單數據的同時,同時發送 "amount" 。

經過測試,我就直接說結論了,有興趣的童鞋可以自行探索,有新的發現歡迎和我交流。

結論:

不能對這樣的數據,指定 "contentType:application/json",否則後端SpringMVC或者第三方的Jar 包 不能進行自動的解析,增加瞭解析的複雜度,所以將 json 串傳入後臺,在後臺進行解析。

e1:serializeObject()

請求:

$(function() {
    $('form').submit(function() {
        $.ajax({
            url : "testStudent",
            data : {
                amount : $("#amount").text(),
                student : JSON.stringify($('form').serializeObject())
            },
            type : "post",
            success : function (result) {
                console.log(result);
            }
        });
        return false;
    });
});

後端處理:使用第三方工具類進行解析

@RequestMapping("/testStudent")
public String testStudent(@RequestParam("student") String studentStr, String amount) {
    Student student = JsonUtil.fromJson(studentStr, Student.class);
    System.out.println("student:" + student);
    System.out.println("amount:" + amount);
    return "success";
}

可以正常列印。

e2:serialize()

請求:

$(function() {
    $('form').submit(function() {
        $.ajax({
            url : "testStudent",
            data : {
                amount : $("#amount").text(),
                student : $('form').serialize()
            },
            type : "post",
            success : function (result) {
                console.log(result);
            }
        });
        return false;
    });
});

Handler 方法:

e1:嘗試讓 SpringMVC 來解析:

@RequestMapping("/testStudent")
public String testStudent(@RequestParam("student") Student student, String amount) {
    System.out.println("student:" + student);
    System.out.println("amount:" + amount);
    return "success";
}

結果:請求無法到達 handler 方法

e2:

@RequestMapping("/testStudent")
public String testStudent(Student student, String amount) {
    System.out.println("student:" + student);
    System.out.println("amount:" + amount);
    return "success";
}

結果:請求可以正常到達目標 Handler 方法,但是無法映射 Student 對象。

方案:自己解析,編寫自定義的類型轉換器:

public class String2StudentConverter implements Converter<String, Student>{
    @Override
    public Student convert(String source) {
        return InjectUtil.convert2Obj(source, Student.class);
    }
}

這裡我編寫了一個通用的類型轉換器:

用來轉換形如: 

firstName=jack&lastName=lily&gender=1&foods=Steak&foods=Pizza&quote=Enter+your+favorite+quote!&education=Jr.High&tOfD=Day 到 Student 對象。

/**
 * @author solverpeng
 * @create 2016-08-22-17:37
 */
public final class InjectUtil<T> {
    private static final Logger LOGGER = LoggerFactory.getLogger(InjectUtil.class);

    public static <T> T converter2Obj(String source, Class<T> tClass) {
        T t = null;
        try {
            t = tClass.newInstance();
            Map<String, Object> params = new HashMap<String, Object>();
            if(source != null && source.length() > 0) {
                String[] fields = source.split("&");
                for(String field : fields) {
                    String[] fieldKeyValue = field.split("\\=");
                    String fieldKey = fieldKeyValue[0];
                    String fieldValue = fieldKeyValue[1];
                    if (params.containsKey(fieldKey)) {
                        Object keyValueRetrieved = params.get(fieldKey);
                        if (keyValueRetrieved instanceof String) {
                            ArrayList<String> values = new ArrayList<>();
                            values.add(keyValueRetrieved.toString());
                            values.add(fieldValue);
                            params.put(fieldKey, values);
                        } else {
                            ((ArrayList<String>) keyValueRetrieved).add(fieldValue);
                        }
                    } else {
                        params.put(fieldKey, fieldValue);
                    }
                }
            }
            BeanUtils.populate(t, params);
        } catch(InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            LOGGER.error("String convert to Bean failure!", e);
        }
        return t;
    }

}

不要忘記在 SpringMVC 中添加自定義的轉換器。

e3:也可以在 handler 方法中來調用上面我編寫的通用的類型轉換器來完成解析。

@RequestMapping("/testStudent")
public String testStudent(@RequestParam("student") String studentStr, String amount) {
    System.out.println("studentStr:" + studentStr);
    System.out.println("amount:" + amount);
    return "success";
}

說明:對於複雜數據來說,我們藉助不了 SpringMVC,只能藉助於第三方,或是自己來編寫解析器來解析。

★多表單一次提交

表單數據:

<form action="" method="post" id="form2">
    First Name:<input type="text" name="firstName" maxlength="12" size="12"/> <br/>
    Last Name:<input type="text" name="lastName" maxlength="36" size="12"/> <br/>
    Gender:<br/>
    Male:<input type="radio" name="gender" value="1"/><br/>
    Female:<input type="radio" name="gender" value="0"/><br/>
    &lt;%&ndash;Favorite Food:<br/>
    Steak:<input type="checkbox" name="foods" value="Steak"/><br/>
    Pizza:<input type="checkbox" name="foods" value="Pizza"/><br/>
    Chicken:<input type="checkbox" name="foods" value="Chicken"/><br/>&ndash;%&gt;
    <textarea wrap="physical" cols="20" name="quote" rows="5">Enter your favorite quote!</textarea><br/>
    Select a Level of Education:<br/>
    <select name="education">
        <option value="Jr.High">Jr.High</option>
        <option value="HighSchool">HighSchool</option>
        <option value="College">College</option>
    </select><br/>
    Select your favorite time of day:<br/>
    <select size="3" name="tOfD">
        <option value="Morning">Morning</option>
        <option value="Day">Day</option>
        <option value="Night">Night</option>
    </select>
    <p><input type="submit"/></p>
</form>
<form action="" method="post" id="form1">
    First Name:<input type="text" name="firstName" maxlength="12" size="12"/> <br/>
    Last Name:<input type="text" name="lastName" maxlength="36" size="12"/> <br/>
    Gender:<br/>
    Male:<input type="radio" name="gender" value="1"/><br/>
    Female:<input type="radio" name="gender" value="0"/><br/>
   &lt;%&ndash; Favorite Food:<br/>
    Steak:<input type="checkbox" name="foods" value="Steak"/><br/>
    Pizza:<input type="checkbox" name="foods" value="Pizza"/><br/>
    Chicken:<input type="checkbox" name="foods" value="Chicken"/><br/>&ndash;%&gt;
    <textarea wrap="physical" cols="20" name="quote" rows="5">Enter your favorite quote!</textarea><br/>
    Select a Level of Education:<br/>
    <select name="education">
        <option value="Jr.High">Jr.High</option>
        <option value="HighSchool">HighSchool</option>
        <option value="College">College</option>
    </select><br/>
    Select your favorite time of day:<br/>
    <select size="3" name="tOfD">
        	   

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

-Advertisement-
Play Games
更多相關文章
  • 開始之前: 1. 本博文為原創,轉載請註明出處 2. 作者非電腦科班出身,如有錯誤,請多指正 開始啦啦啦啦啦 從開始接觸spring起,聽到最多的就是Ioc(控制反轉)和AOP(面向切麵編程)啦。Spring的官方文檔給出了這樣一個框架圖(><看起來好深奧~~)。不過本篇要介紹的所謂的控制反轉,就 ...
  • return返回值: python函數都有返回值,函數體內無return,預設返回值None, 函數參數: 1、普通參數 嚴格按照順序,將實際參數賦值給形式參數,一一對應。 例: 2、預設參數 必須放在參數列表的最後,且實際參數可以預設和覆蓋。 例: 3、指定參數 實際參數賦值給指定的形式參數。 例 ...
  • 易語言MySql註冊登錄 用到的主要易語言命令: 連接MySql (, , , , ) 執行SQL語句 (, ) 取記錄集 () 讀欄位值 (, , ) 釋放記錄集 () 斷開MySql () 命令介紹: ①、連接MySql (, , , , ):顧名思義,這條命令是用來連接你的MySql資料庫的, ...
  • 安裝 phoenix framework 安裝 phoenix 很簡單: 安裝之後,mix 的子命令中就多了 phoenix 相關的內容了。 phoenix 工程介紹 接下來,我們創建一個 phoenix 的工程。 phoenix 是個完整的 web 框架,包括 controller,view以及m ...
  • * ResultSet 結果集:封裝了使用JDBC 進行查詢的結果 * 1. 調用Statement 對象的 executeQuery(sql) 方法可以得到結果集 * 2. ResultSet 返回的實際上就是一張數據表,有一個指針指向數據表的第一行的前面, * 可以調用next()方法檢測下一行 ...
  • C 語言基本數據類型:字元型(char)整形(short, int, long)浮點型(float, double) 註:如下類型位元組數指一般情況,不同的平臺會有所不同,具體平臺可以用sizeof 關鍵字測試一下. -2147483648~~2147483647 0~~4294967295 -3.4 ...
  • 聲明:此文章轉載自 http://my.oschina.net/goldenshaw/blog/304493 許多時候,字元集與編碼這兩個概念常被混為一談,但兩者是有差別的,作為深入理解的第一步,首先要明確: 字元集與字元集編碼是兩個不同層面的概念 charset是character set的簡寫, ...
  • 說明:iOS 原生 Edit 透明框 適用:Berlin Firemonkey 方法:在 StyleLookup 輸入 transparentedit 效果: 如果有圖片 Image 在這二個 Edit 的上方,效果如下: 說明:iOS 原生 Edit 設定框色 適用:Berlin Firemonk ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...