三、spring成長之路——springIOC容器詳解(上)

来源:https://www.cnblogs.com/hu1056043921/archive/2018/04/18/8878238.html
-Advertisement-
Play Games

[TOC] 一、springIOC : ​ 簡單的說就是將對象的創建,屬性的的設置交給spring容器進行管理,而不再由用戶自己創建,當用戶需要使用該介面或者類的時候,直接註入就可以了,spring容器會自動幫助用戶創建對象。 1.創建maven應用程式 【pom.xml】 ​ 1.引入spring ...


[TOC]

一、springIOC

控制反轉和依賴註入

​ 簡單的說就是將對象的創建,屬性的的設置交給spring容器進行管理,而不再由用戶自己創建,當用戶需要使用該介面或者類的時候,直接註入就可以了,spring容器會自動幫助用戶創建對象。

1.創建maven應用程式

【pom.xml】

​ 1.引入spring依賴,junit依賴

​ 2.引入maven插件——java編譯插件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.itcloud</groupId>
  <artifactId>resource</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>resource</name>
  <url>http://maven.apache.org</url>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.3.15.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
         <version>3.7.0</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

該依賴會下載下麵jar

<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
  • org.springframework:spring-aop:4.3.15.RELEASE
  • org.springframework:spring-beans:4.3.15.RELEASE
  • org.springframework:spring-core:4.3.15.RELEASE
  • org.springframework:spring-expression:4.3.15.RELEASE

2.springIOC基礎

基本概念:springIOC主要作用是用來管理javaBean的容器,將java對象以及對象和對象之間的關係交由Spring容器管理。

在沒有spring容器之前對介面或者類進行實例化的時候都需要使用new關鍵字,來進行對象的創建,那麼自從有了spring,那麼這些事情就交給了spring來做了。

2.1.瞭解spring的幾種註入方式

【Teacher.java】

​ getter和setter方法在這裡都會被省略。

一個老師對應多個學生,老師pojo類中包含setter註入,和List集合註入

public class Teacher implements Serializable {
    private Long id;
    private String name;
    private Integer age;
    private List<Student> students;
}

【Student.java】

一個學生對應一個老師,學生包含多種註入方式,有setter,Properties類註入,map註入以及構造方法註入

註意點,

​ 1.如果添加了有參構造方法(沒有參構造),那麼在進行註入的時候必須要進行構造方法的註入

​ 2.如果既有有參構造和無參構造可以不進行構造方法的註入

public class Student implements Serializable {
    private Long id;
    private String name;
    private Teacher teacher;

    private Properties pro;

    private Map<String,Object> map;
    public Student(){}
    public Student(Long id, String name){
        this.id = id;
        this.name = name;
    }
}

【applicationContext.xml】**創建spring容器

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="student" class="com.itcloud.pojo.Student">
        <property name="id" value="1"/>
        <property name="name" value="小明"/>
    </bean>

    <bean id="student2" class="com.itcloud.pojo.Student">
        <!-- 構造方法註入 -->
        <!--每一個標簽都代表一個構造方法的屬性,按照參數在構造方法中的順序進行註入-->
        <constructor-arg value="2"/>
        <constructor-arg>
            <value>張三</value>
        </constructor-arg>
        
        
        <property name="teacher" ref="teacher" />
        <!-- map註入 -->
        <property name="map">
            <map>
                <entry key="1" value="語文" />
                <entry key="2" value="數學" />
            </map>
        </property>
    <!-- Properties註入 -->
        <property name="pro">
            <props>
                <prop key="身高">1.8</prop>
                <prop key="體重">70kg</prop>
            </props>
        </property>
    </bean>


    <bean id="teacher" class="com.itcloud.pojo.Teacher">

        <property name="id" value="100023" />
        <property name="name" value="王老師" />
        <property name="age" value="30" />
        <!-- list集合註入 -->
        <property name="students">
            <list>
                <ref bean="student2" />
                <ref bean="student" />
            </list>
        </property>
    </bean>
</beans>

【TestIOC.java】進行數據的測試,debug觀察數據

package com.itcloud.pojo;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestIOC {

    //載入spring容器
    private ApplicationContext context =
            new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");

    @Test
    public void testStudent() {
        //context.getBean()獲取spring容器中管理的bean,參數為Id
        Student stu1 = (Student) context.getBean("student");

        Student stu2 = context.getBean("student2", Student.class);

        Teacher teacher = context.getBean("teacher", Teacher.class);

        System.out.println("---------------------");
    }
}
2.2.p標簽和c標簽的註入方式

​ p代表的就是屬性,c代表的就是構造方法。

添加標簽頭,引入p和c

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

實例

c:id="3" c:name="smith"就是構造方法中的兩個參數 id和name,p:teacher-ref="teacher"為類中中的屬性teacher

<bean id="student3" class="com.itcloud.pojo.Student" c:id="3" c:name="smith" p:teacher-ref="teacher"/>
2.3.bean之間的繼承關係

兩個關鍵欄位parentabstract

1.此時student3會繼承student中的id,和name屬性,這個是parent的作用,非必須標簽

2.abstract表示student這個bean無法被實例化,即無法再代碼中獲取這個bean,也無法被外部所引用,非必須標簽

​ 例如:ref="student"是錯的

<bean id="student" class="com.itcloud.pojo.Student" abstract="true">
    <property name="id" value="1"/>
    <property name="name" value="小明"/>
</bean>
<bean id="student3" class="com.itcloud.pojo.Student" parent="student" p:teacher-ref="teacher"/>
2.4.bean的作用域

概述

作用域 描述
單例(singleton) (預設)每一個Spring IoC容器都擁有唯一的一個實例對象
原型(prototype) 一個Bean定義,任意多個對象

scope="singleton"預設值,只會產生一個實例化對象

scope="prototype"原型,每次獲取bean的時候都會獲取一個新的實例化對象

<bean id="student4" class="com.itcloud.pojo.Student" parent="student" p:teacher-ref="teacher" scope="singleton"/>
2.6.bean的生命周期

兩個關鍵點:

​ 1.<bean/>標簽中的欄位:init-method=""表示bean初始化(構造方法)之後調用的方法 destroy-method=""容器關閉之後調用的方法.

​ 2. bean的後置處理器,需要實現方法,BeanPostProcessor這個類,兩個方法:

postProcessBeforeInitialization():在每個bean初始化後(構造方法)調用一次(在init-method方法之前被調用)。

postProcessAfterInitialization():在init-method之後被調用,destroy-method之前被調用

實現案例0001

【LifeCycle.java】

package com.itcloud.pojo;

public class LifeCycle {

    public LifeCycle(){
        System.out.println("構造方法初始化..........");
    }

    public void init(){
        System.out.println("init()初始化方法.......");
    }

    public void destory(){
        System.out.println("destory()銷毀方法.......");
    }
}

【applicationContext.xml】

init-method="init" destroy-method="destory"

<bean id="lifeCycle" class="com.itcloud.pojo.LifeCycle" init-method="init" destroy-method="destory"></bean>

【TestIOC.java】測試

public class TestIOC {

    //載入spring容器
    private ClassPathXmlApplicationContext context =
            new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");

    @Test
    public void testStudent() {
     
        LifeCycle lifeCycle = context.getBean("lifeCycle", LifeCycle.class);
        context.close();
        //測試結果
        /*
信息: Loading XML bean definitions from class path resource [spring/applicationContext.xml]
構造方法初始化..........
init()初始化方法.......

四月 08, 2018 10:09:34 上午 org.springframework.context.support.ClassPathXmlApplicationContext doClose

信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@27ddd392: startup date [Sun Apr 08 10:09:33 CST 2018]; root of context hierarchy
destroy()銷毀方法.......
        */
    }
}

第二個關鍵點實現案例0002

【CycleProcessor.java】

package com.itcloud.pojo;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;


public class CycleProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        System.out.println("CycleProcessor start....." + name);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
        System.out.println("CycleProcessor end....." + name);
        return bean;
    }
}

【TestIOC.java】測試類不變,測試結果:

/*
構造方法初始化..........
CycleProcessor start.....lifeCycle
init()初始化方法.......
CycleProcessor end.....lifeCycle
四月 08, 2018 10:13:31 上午 org.springframework.context.support.ClassPathXmlApplicationContext doClose

信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@58c1670b: startup date [Sun Apr 08 10:13:00 CST 2018]; root of context hierarchy
destroy()銷毀方法.......
*/
2.7.工廠註入(瞭解即可)

註意點,如果工廠方法有參數,通過<constructor-arg value="xxx"></constructor-arg>進行參數匹配

靜態工廠註入

public class StudentFactory {

    public static Student getInstance(){
        Student stu = new Student();
        stu.setId(10L);
        stu.setName("小十");
        return stu;
    }
}
<bean id="student6" class="com.itcloud.pojo.StudentFactory" factory-method="getInstance"></bean>

測試

Student stu = context.getBean("student6", Student.class);

實例工廠註入

package com.itcloud.pojo;

public class TeacherFactory {
    public Teacher getInstance(Long id, String name){
        Teacher teacher = new Teacher();
        teacher.setId(id);
        teacher.setName(name);
        return teacher;
    }
}
<!-- 實例工廠必須單獨配置一個bean -->
    <bean id="teacherFactory" class="com.itcloud.pojo.TeacherFactory"/>
    <bean id="teacher2" factory-bean="teacherFactory" factory-method="getInstance">
        <constructor-arg>
            <value>222</value>
        </constructor-arg>
        <constructor-arg name="name" value="張老師" />

    </bean>

測試

Teacher teacher = context.getBean("teacher2", Teacher.class);

FactoryBean配置

跳轉標誌

package com.itcloud.pojo;

import org.springframework.beans.factory.FactoryBean;

public class TeacherFactoryBean implements FactoryBean {

    private String name;

    @Override
    public Object getObject() throws Exception {
        Teacher teacher = new Teacher();
        teacher.setName(name);
        return teacher;
    }

    @Override
    public Class<?> getObjectType() {
        return Teacher.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    public void setName(String name) {
        this.name = name;
    }
}
<!--FactoryBean方法配置bean-->
    <bean id="teacherBean" class="com.itcloud.pojo.TeacherFactoryBean">
        <property name="name" value="李老師"/>
    </bean>
Teacher teacher = context.getBean("teacherBean", Teacher.class);

3.spring註解註入

​ 三個註解將類註入到spring容器中,註意點:註解預設註入的Id為當前類的名稱首字母小寫

  • @Repository主要用於dao,數據訪問層
  • @Service用於Service層,調用數據訪問層的方法,進行邏輯操作
  • @Component用戶普通類的註冊,用戶自己定義的組件

我們知道Service層一定會調用dao層的相關方法,dao層已經被註冊到Spring容器之中,這是後就需要使用Spring為我們提供的註解來引用對應的實例

  • @Autowired按照類型進行匹配,如果一個介面存在兩個子類,可以配合@Qualifier註解來使用
  • @Resource按照名稱進行匹配,
3.1簡單應用應用案例

【applicationContext-annotation.xml】支持註解配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"                     xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 此配置表示com.itcloud包及其子包支持註解配置 -->
    <context:component-scan base-package="com.itcloud">
        
    </context:component-scan>
</beans>

【UserDAO.java】

package com.itcloud.dao;

public interface UserDAO {
    //用戶更新
    int update();
}

【UserDAOImpl.java】註意點:@Repository的value的值預設是(userDAOImpl)

@Repository
public class UserDAOImpl implements UserDAO {


    @Override
    public int update() {
        System.out.println("進行資料庫語句編寫");
        return 0;
    }
}

【UserService.java】

package com.itcloud.service;

public interface UserService {
    int doUpdate();
}

【UserServiceImpl.java】@Service的value的預設值是:userServiceImpl

ackage com.itcloud.service.impl;

import com.itcloud.dao.UserDAO;
import com.itcloud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDAO userDAO;

    @Override
    public int doUpdate() {
        System.out.println("UserServiceImpl update()方法開始....");
        userDAO.update();
        return 0;
    }
}

測試

context.getBean("userDAOImpl");//結果:userDAOImpl@127 即:獲取到UserDAO的對象

理解bean之間的相互調用

我們在UserServiceImpl這個類中可以看到如下這句話,這句話表示的意思就是引用外部bean,在沒有Spring之前我們引入外部bean的過程是:private UserDAO userDAO = new UserDAOImpl(),在有了Spring之後,spring會自動幫我們進行對象的創建,以及維護對象之間的關係。

    @Autowired
    private UserDAO userDAO;

測試Autowired

    @Test
    public void testAnnotation(){
        UserService userService = context.getBean(UserService.class);
        userService.doUpdate();
    }
//結果
/*
    UserServiceImpl update()方法開始....
    進行資料庫語句編寫
*/

前面提到,@Autowired是根據類型進行註入的,此時因為UserDAO只有一個子類,但是如果有兩個子類要怎麼書寫呢:

    //方案一,官方推薦
    @Autowired
    @Qualifier("userDAOImpl")
    private UserDAO userDAO;    
    //方案二
    @Resource(name = "userDAOImpl")
    private UserDAO userDAO;
    //或者
    @Resource
    private UserDAO userDAOImpl;
3.2理解開啟註解支持配置

【applicationContext-annotation.xml】

<context:component-scan base-package="com.itcloud">

</context:component-scan>

這裡也可以添加子元素,對註解數據進行過濾

最常用的過濾方式

<context:component-scan base-package="com.itcloud" use-default-filters="false">
        <!--只包含Service註解的bean,其他註解不會被掃描-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
    
    </context:component-scan>

use-default-filters="false"不使用預設過濾方式,如果為true的話,<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/> 表示的意思只是將@Service包含進來,其他註解也會包含的

<!--表示不掃描Repository註解-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>

4.spring引用外部屬性文件

4.1 applicationContext.xml文件配置bean並且註入屬性文件中的內容

【value.properties】定義一個外部屬性文件

value.driverName=com.mysql.jdbc.Driver
value.url=jdbc:mysql://localhost:3306/test
value.username=root
value.password=123456

【DataSource.java】定義屬性類

package com.itcloud.value;

public class DataSource {

    private String driverName;

    private String username;

    private String password;

    private String url;
    //getter setter方法略

}

【applicationContext-annotation.xml】在spring配置文件中獲取屬性文件內容

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder location="classpath:properties/value.properties"/>
    <bean id="dataSource" class="com.itcloud.value.DataSource">
        <property name="username" value="${value.username}"/>
        <property name="password" value="${value.password}"/>
        <property name="driverName" value="${value.driverName}"/>
        <property name="url" value="${value.url}"/>
    </bean>
</beans>

此時,當spring容器載入的時候,DataSource.java 被實例化, value.properties屬性文件中的內容會被註入到DataSource中。

4.2不通過配置文件的方式讀取屬性

【applicationContext-annotation.xml】開啟註解配置

<context:component-scan base-package="com.itcloud"/>
<context:property-placeholder location="classpath:properties/value.properties"/>
<!--<bean id="dataSource" class="com.itcloud.value.DataSource">-->
        <!--<property name="username" value="${value.username}"/>-->
        <!--<property name="password" value="${value.password}"/>-->
        <!--<property name="driverName" value="${value.driverName}"/>-->
        <!--<property name="url" value="${value.url}"/>-->

<!--</bean>-->

【DataSource.java】 此時可以沒有setter方法

package com.itcloud.value;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class DataSource {

    @Value("${value.driverName}")
    private String driverName;

    @Value("${value.username}")
    private String username;

    @Value("${value.password}")
    private String password;

    @Value("${value.url}")
    private String url;
}

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

-Advertisement-
Play Games
更多相關文章
  • MyBatis—Spring 項目 目前大部分的 Java 互聯網項目,都是用 Spring MVC + Spring + MyBatis 搭建平臺的。 使用 "Spring IoC" 可以有效的管理各類的 Java 資源,達到即插即拔的功能;通過 "Spring AOP" 框架,資料庫事務可以委托 ...
  • 內容:日曆對象獲取時間,設置時間,日期偏移 通過工廠化獲得對象。getInstance();get() 獲取時間信息 美國的星期是從星期天開始的,所以會有點問題set()設置方法,設置時間 //解答三月一日的前一天就是 Calendar c = Calendar.getInstance(); int ...
  • 集合的迭代器 任何集合都有迭代器。 任何集合類,都必須能以某種方式存取元素,否則這個集合容器就沒有任何意義。 迭代器,也是一種模式(也叫迭代器模式)。在java中它是一個對象,其目的是遍歷並選中其中的每個元素,而使用者(客戶端)無需知道裡面的具體細節。迭代器要足夠的“輕量”——創建迭代器的代價小。所 ...
  • Github項目地址: https://github.com/JtvDeemo/elementary arithmetic PSP ||||| |: |: |: |: | | PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘 ...
  • SocketServer其實是對socket更高級的封裝正如官網上說的:The socketserver module simplifies the task of writing network servers. 我們可以先打開以下SocketServer的源碼,看一下源碼中整體的框架 從上圖我們 ...
  • 比如:如果在微信小程式中要遍歷輸出 0-9 的數,我們會使用for迴圈 確實結果也是這樣: 但是,如果我在迴圈時同時調用wx的api介面10次,那麼輸出的結果就會不同(這是產生了閉關的效應) eg:每次調用一次wx.showToast()介面,併在成功時輸出迴圈的值。 結果: 可以看到輸出了10次1 ...
  • 數組排序 目錄 一. 冒泡排序 二. 選擇排序 三. 優化選擇排序 一. 冒泡排序 將數組元素按【從小到大排序】為例 思路:依次對臨近的兩個元素對比,將最大值放在數組最後;再將剩餘的元素對比,大值放在剩餘元素的最後. . . 以此迴圈,最後元素就是按從小到大排列。 1.1. 做之前,先瞭解這個操作: ...
  • 絕大數人都知道mp3格式編碼,以及aac,amr等壓縮格式編碼。 而在語音通信界有一個強悍的音頻格式編碼opus. 經過實測,壓縮比最高可以達到1:10。 100KB 壓縮後 10KB 雖然是有損壓縮, 但是根據實際對比試聽, 幾乎聽不出差別。 而且還原度還比mp3高,壓縮比也比mp3高。 用來壓縮 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...