最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文弄懂Mybatis中介者模式

 更新時(shí)間:2023年06月11日 11:33:25   作者:Cosolar  
本文主要介紹了一文弄懂Mybatis中介者模式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、前言

中介者模式的核心思想是將對象間的交互行為集中在一個(gè)中介者對象中,從而降低對象之間的耦合度。在mybatis中,中介者模式被廣泛應(yīng)用于Session對象的創(chuàng)建和管理中。

具體來說,mybatis中的SqlSessionFactory就扮演了中介者的角色,它負(fù)責(zé)創(chuàng)建和管理SqlSession對象。SqlSession是mybatis中用于與數(shù)據(jù)庫交互的核心對象,而SqlSessionFactory則是創(chuàng)建SqlSession對象的工廠類。

當(dāng)應(yīng)用程序需要執(zhí)行一個(gè)操作(如查詢、添加或更新記錄)時(shí),它將向SqlSessionFactory請求一個(gè)SqlSession對象。SqlSessionFactory根據(jù)需要的配置信息(如數(shù)據(jù)庫連接信息、事務(wù)管理器等)創(chuàng)建一個(gè)新的SqlSession對象,并將其返回給應(yīng)用程序。

一旦應(yīng)用程序獲得了SqlSession對象,它就可以使用SqlSession對象來執(zhí)行數(shù)據(jù)庫操作。當(dāng)執(zhí)行完操作后,應(yīng)用程序需要調(diào)用SqlSession的close()方法關(guān)閉資源,SqlSession將會被歸還給SqlSessionFactory進(jìn)行資源回收。

通過將SqlSession對象的創(chuàng)建和管理職責(zé)交由SqlSessionFactory統(tǒng)一管理,不僅可以保證SqlSession對象的有效性和一致性,同時(shí)也可以避免重復(fù)創(chuàng)建和銷毀SqlSession對象的開銷,提高系統(tǒng)性能和穩(wěn)定性。

Mybatis是一個(gè)我項(xiàng)目開發(fā)中常用的非常優(yōu)秀的ORM框架,它可以幫我們快速、簡便地操作數(shù)據(jù)庫。本文將會按照Mybatis的原理手寫一個(gè)ORM框架,并通過利用中介者模式來實(shí)現(xiàn)JDBC方式操作數(shù)據(jù)庫的增強(qiáng)。

二、Mybatis工作原理

在開始實(shí)現(xiàn)ORM框架之前,我們需要先了解一下Mybatis的工作原理:

SqlSessionFactory:SqlSessionFactory是Mybatis的核心接口,它是一個(gè)工廠類,用于創(chuàng)建SqlSession對象。SqlSession是Mybatis的另一個(gè)核心接口,它提供了操作數(shù)據(jù)庫的方法和事務(wù)管理的功能。

Configuration:Configuration是Mybatis的配置類,它包含了Mybatis的所有配置,如數(shù)據(jù)源、映射關(guān)系等,用于生成SqlSessionFactory。

SqlSession:SqlSession是Mybatis的會話類,它與數(shù)據(jù)庫的連接是一一對應(yīng)的,負(fù)責(zé)與數(shù)據(jù)庫進(jìn)行交互。SqlSession中包含了一系列的操作數(shù)據(jù)庫的方法,如插入、更新、刪除、查詢等。

Mapper:Mapper是Mybatis的映射器,它定義了Java對象與SQL語句之間的映射關(guān)系,即將Java對象轉(zhuǎn)化為SQL語句,或?qū)QL語句轉(zhuǎn)化為Java對象。

Executor:Executor是Mybatis的執(zhí)行器,它負(fù)責(zé)執(zhí)行SQL語句,管理事務(wù)。Mybatis中有兩種類型的執(zhí)行器:SimpleExecutor和ReuseExecutor,SimpleExecutor會為每個(gè)SQL語句創(chuàng)建一個(gè)Statement對象,而ReuseExecutor則會復(fù)用Statement對象。

TypeHandler:TypeHandler是Mybatis的類型處理器,它用于將Java對象與數(shù)據(jù)庫中的數(shù)據(jù)類型進(jìn)行轉(zhuǎn)換。Mybatis中內(nèi)置了許多常用的類型處理器,如StringTypeHandler、IntegerTypeHandler等,可以根據(jù)需要進(jìn)行擴(kuò)展。

三、手寫ORM框架

我們將按照Mybatis的工作原理來手寫一個(gè)ORM框架,該框架支持基本的增刪改查操作。

1. 創(chuàng)建Configuration類

首先,我們需要?jiǎng)?chuàng)建一個(gè)Configuration類,該類負(fù)責(zé)讀取配置文件并生成SqlSessionFactory對象。

public class Configuration {
    private final Properties properties = new Properties(); // 存儲配置信息
    public Configuration(String configLocation) {
        InputStream is = null;
        try {
            is = Resources.getResourceAsStream(configLocation);
            properties.load(is);
        } catch (IOException e) {
            throw new RuntimeException("Config file not found!");
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public SqlSessionFactory buildSqlSessionFactory() {
        return new DefaultSqlSessionFactory(this);
    }
    // getter 方法省略...
}

2. 創(chuàng)建SqlSessionFactory和SqlSession類

接下來,我們需要?jiǎng)?chuàng)建SqlSessionFactory和SqlSession類。

public interface SqlSessionFactory {
    SqlSession openSession();
}
public interface SqlSession {
    int insert(String statementId, Object parameter);
    int update(String statementId, Object parameter);
    int delete(String statementId, Object parameter);
    <T> T selectOne(String statementId, Object parameter);
    <T> List<T> selectList(String statementId, Object parameter);
    void close();
}

3. 創(chuàng)建Executor類

然后,我們需要?jiǎng)?chuàng)建Executor類,該類負(fù)責(zé)執(zhí)行SQL語句,并返回結(jié)果。

public interface Executor {
    int insert(MappedStatement mappedStatement, Object parameter);
    int update(MappedStatement mappedStatement, Object parameter);
    int delete(MappedStatement mappedStatement, Object parameter);
    <T> T selectOne(MappedStatement mappedStatement, Object parameter);
    <E> List<E> selectList(MappedStatement mappedStatement, Object parameter);
}

4. 創(chuàng)建MappedStatement類

我們還需要?jiǎng)?chuàng)建MappedStatement類,該類保存了SQL語句和參數(shù)映射關(guān)系的信息。

public class MappedStatement {
    private String statementId; // SQL語句的ID
    private String sql; // SQL語句
    private Class<?> parameterType; // 參數(shù)類型
    private Class<?> resultType; // 返回值類型
    // getter、setter方法省略...
}

5. 創(chuàng)建MapperRegistry和MapperProxy類

最后,我們需要?jiǎng)?chuàng)建MapperRegistry和MapperProxy類,用于將Java對象與SQL語句之間進(jìn)行映射。

public class MapperRegistry {
    private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new ConcurrentHashMap<>();
    public <T> void addMapper(Class<T> type) {
        knownMappers.put(type, new MapperProxyFactory<>(type));
    }
    public <T> T getMapper(SqlSession sqlSession, Class<T> type) {
        MapperProxyFactory<?> mapperProxyFactory = knownMappers.get(type);
        if (mapperProxyFactory == null) {
            throw new RuntimeException("Mapper not found: " + type);
        }
        return (T) mapperProxyFactory.newInstance(sqlSession);
    }
}
public class MapperProxy<T> implements InvocationHandler {
    private final SqlSession sqlSession;
    private final Class<T> mapperInterface;
    public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface) {
        this.sqlSession = sqlSession;
        this.mapperInterface = mapperInterface;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 獲取MappedStatement對象
        String statementId = mapperInterface.getName() + "." + method.getName();
        MappedStatement mappedStatement = sqlSession.getConfiguration().getMappedStatement(statementId);
        // 調(diào)用Executor執(zhí)行SQL
        Object result = null;
        switch (mappedStatement.getSqlCommandType()) {
            case INSERT:
                result = sqlSession.insert(statementId, args[0]);
                break;
            case UPDATE:
                result = sqlSession.update(statementId, args[0]);
                break;
            case DELETE:
                result = sqlSession.delete(statementId, args[0]);
                break;
            case SELECT:
                if (method.getReturnType() == List.class) {
                    result = sqlSession.selectList(statementId, args[0]);
                } else {
                    result = sqlSession.selectOne(statementId, args[0]);
                }
                break;
            default:
                throw new RuntimeException("Unknown SqlCommandType: " + mappedStatement.getSqlCommandType());
        }
        return result;
    }
}

6. 在SqlSession中調(diào)用Executor

最后,在SqlSession的方法中,我們需要調(diào)用Executor來執(zhí)行SQL語句。

public class DefaultSqlSession implements SqlSession {
    private final Executor executor;
    private final Configuration configuration;
    public DefaultSqlSession(Configuration configuration) {
        this.executor = new SimpleExecutor(configuration);
        this.configuration = configuration;
    }
    @Override
    public int insert(String statementId, Object parameter) {
        MappedStatement mappedStatement = configuration.getMappedStatement(statementId);
        return executor.insert(mappedStatement, parameter);
    }
    @Override
    public int update(String statementId, Object parameter) {
        MappedStatement mappedStatement = configuration.getMappedStatement(statementId);
        return executor.update(mappedStatement, parameter);
    }
    @Override
    public int delete(String statementId, Object parameter) {
        MappedStatement mappedStatement = configuration.getMappedStatement(statementId);
        return executor.delete(mappedStatement, parameter);
    }
    @Override
    public <T> T selectOne(String statementId, Object parameter) {
        MappedStatement mappedStatement = configuration.getMappedStatement(statementId);
        return executor.selectOne(mappedStatement, parameter);
    }
    @Override
    public <T> List<T> selectList(String statementId, Object parameter) {
        MappedStatement mappedStatement = configuration.getMappedStatement(statementId);
        return executor.selectList(mappedStatement, parameter);
    }
    @Override
    public void close() {
        // 關(guān)閉Executor等資源
    }
}

7. 創(chuàng)建MapperProxyFactory類

在創(chuàng)建MapperRegistry時(shí),我們還需要?jiǎng)?chuàng)建一個(gè)MapperProxyFactory類,用于創(chuàng)建MapperProxy對象。

public class MapperProxyFactory<T> {
    private final Class<T> mapperInterface;
    public MapperProxyFactory(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
    }
    public T newInstance(SqlSession sqlSession) {
        return (T) Proxy.newProxyInstance(
                mapperInterface.getClassLoader(),
                new Class[]{mapperInterface},
                new MapperProxy<>(sqlSession, mapperInterface));
    }
}

到此為止,我們已經(jīng)手寫了一個(gè)簡單的ORM框架,并且可以進(jìn)行基本的增刪改查操作。

四、利用中介者模式增強(qiáng)JDBC方式操作數(shù)據(jù)庫

接下來,我們將利用中介者模式來增強(qiáng)JDBC方式操作數(shù)據(jù)庫的功能。

1. 創(chuàng)建DataSource類

首先,我們需要?jiǎng)?chuàng)建一個(gè)DataSource類,該類負(fù)責(zé)管理數(shù)據(jù)庫連接和釋放資源。

public class DataSource {
    private String url;
    private String username;
    private String password;
    private static final ThreadLocal<Connection> connectionHolder = new ThreadLocal<>();
    public DataSource(String url, String username, String password) {
        this.url = url;
        this.username = username;
        this.password = password;
    }
    public Connection getConnection() throws SQLException {
        Connection connection = connectionHolder.get();
        if (connection == null) {
            connection = DriverManager.getConnection(url, username, password);
            connectionHolder.set(connection);
        }
        return connection;
    }
    public void releaseConnection(Connection connection) throws SQLException {
        if (connection != null && !connection.isClosed()) {
            connection.close();
        }
        connectionHolder.remove();
    }
}

2. 創(chuàng)建JdbcExecutor類

然后,我們需要?jiǎng)?chuàng)建JdbcExecutor類,該類繼承自Executor類,用于執(zhí)行JDBC操作。

public class JdbcExecutor extends Executor {
    private final DataSource dataSource;
    public JdbcExecutor(Configuration configuration, DataSource dataSource) {
        super(configuration);
        this.dataSource = dataSource;
    }
    @Override
    public int insert(MappedStatement mappedStatement, Object parameter) {
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = dataSource.getConnection();
            statement = connection.prepareStatement(mappedStatement.getSql());
            statement.setObject(1, parameter);
            return statement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (statement != null) {
                    statement.close();
                }
                if (connection != null) {
                    dataSource.releaseConnection(connection);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public int update(MappedStatement mappedStatement, Object parameter) {
        // 類似insert方法,此處省略...
    }
    @Override
    public int delete(MappedStatement mappedStatement, Object parameter) {
        // 類似insert方法,此處省略...
    }
    @Override
    public <T> T selectOne(MappedStatement mappedStatement, Object parameter) {
        // 類似insert方法,此處省略...
    }
    @Override
    public <E> List<E> selectList(MappedStatement mappedStatement, Object parameter) {
        // 類似insert方法,此處省略...
    }
}

3. 創(chuàng)建JdbcSqlSession類

我們還需要?jiǎng)?chuàng)建一個(gè)JdbcSqlSession類,該類繼承自DefaultSqlSession類,用于創(chuàng)建JdbcExecutor對象。

public class JdbcSqlSession extends DefaultSqlSession {
    private final DataSource dataSource;
    public JdbcSqlSession(Configuration configuration, DataSource dataSource) {
        super(configuration);
        this.executor = new JdbcExecutor(configuration, dataSource);
        this.dataSource = dataSource;
    }
    @Override
    public void close() {
        // 關(guān)閉DataSource等資源
    }
}

4. 創(chuàng)建JdbcMapperRegistry類

接下來,我們需要?jiǎng)?chuàng)建JdbcMapperRegistry類,該類繼承自MapperRegistry類,用于創(chuàng)建JdbcMapperProxyFactory對象。

public class JdbcMapperRegistry extends MapperRegistry {
    private final DataSource dataSource;
    public JdbcMapperRegistry(Configuration configuration, DataSource dataSource) {
        super();
        this.dataSource = dataSource;
    }
    @Override
    public <T> void addMapper(Class<T> type) {
        super.addMapper(type);
        JdbcMapperProxyFactory<?> mapperProxyFactory = new JdbcMapperProxyFactory<>(dataSource, type);
        knownMappers.put(type, mapperProxyFactory);
    }
}

5. 創(chuàng)建JdbcMapperProxyFactory類

最后,我們需要?jiǎng)?chuàng)建JdbcMapperProxyFactory類,該類繼承自MapperProxyFactory類,用于創(chuàng)建JdbcMapperProxy對象。

public class JdbcMapperProxyFactory<T> extends MapperProxyFactory<T> {
    private final DataSource dataSource;
    public JdbcMapperProxyFactory(DataSource dataSource, Class<T> mapperInterface) {
        super(mapperInterface);
        this.dataSource = dataSource;
    }
    @Override
    public T newInstance(SqlSession sqlSession) {
        return (T) Proxy.newProxyInstance(
                mapperInterface.getClassLoader(),
                new Class[]{mapperInterface},
                new JdbcMapperProxy<>(sqlSession, dataSource, mapperInterface));
    }
}

6. 創(chuàng)建JdbcMapperProxy類

最后,我們還需要?jiǎng)?chuàng)建JdbcMapperProxy類,該類繼承自MapperProxy類,用于調(diào)用JdbcSqlSession的方法。

public class JdbcMapperProxy<T> extends MapperProxy<T> {
    private final DataSource dataSource;
    public JdbcMapperProxy(SqlSession sqlSession, DataSource dataSource, Class<T> mapperInterface) {
        super(sqlSession, mapperInterface);
        this.dataSource = dataSource;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 如果是Object類的方法,則直接調(diào)用父類的方法
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        }
        // 獲取MappedStatement對象
        String statementId = mapperInterface.getName() + "." + method.getName();
        MappedStatement mappedStatement = sqlSession.getConfiguration().getMappedStatement(statementId);
        // 根據(jù)配置文件中的useCache屬性來判斷是否開啟緩存
        if (mappedStatement.isUseCache()) {
            // TODO: 如果開啟了緩存,先從緩存中查找數(shù)據(jù),如果不存在再調(diào)用JdbcSqlSession中的方法
        }
        // 調(diào)用JdbcSqlSession的方法
        Object result;
        JdbcSqlSession jdbcSqlSession = new JdbcSqlSession(sqlSession.getConfiguration(), dataSource);
        try {
            result = method.invoke(jdbcSqlSession.getMapper(mapperInterface), args);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            jdbcSqlSession.close();
        }
        // 如果開啟了緩存,則將查詢結(jié)果添加到緩存中
        if (mappedStatement.isUseCache()) {
            // TODO: 將查詢結(jié)果添加到緩存中
        }
        return result;
    }
}

到此為止,我們利用中介者模式增強(qiáng)了JDBC方式操作數(shù)據(jù)庫的功能。通過使用中介者模式,我們可以讓JDBC操作數(shù)據(jù)庫更加方便快捷、靈活可擴(kuò)展。

五、小結(jié)一下

Mybatis,這個(gè)神奇的ORM框架,讓我們在操作數(shù)據(jù)庫的道路上披荊斬棘。沒錯(cuò),你沒有聽錯(cuò),它就是那個(gè)可以幫我們快速、簡便地操作數(shù)據(jù)庫的好伙伴。不過話說回來,你有沒有想過,如果這個(gè)世界上沒有Mybatis,那我們程序員豈不是要像遠(yuǎn)古時(shí)期惡劣的條件下編程,跟數(shù)據(jù)庫打交道會變得異常的困難。

但是別擔(dān)心,就算Mybatis哪天離我們而去了,我們也可以自己動(dòng)手寫一個(gè)ORM框架,用中介者模式來增強(qiáng)JDBC方式操作數(shù)據(jù)庫,這樣,我們就可以輕松愉悅地跟數(shù)據(jù)庫玩耍啦。所以,讓我們手握鍵盤,放聲歌唱,繼承Mybatis的精髓,創(chuàng)造更加屬于我們自己的數(shù)據(jù)庫操作方式吧!

我在本文中全面講解了如何按照Mybatis的原理手寫一個(gè)ORM框架,并利用中介者模式增強(qiáng)JDBC方式操作數(shù)據(jù)庫的功能。在實(shí)際開發(fā)中,ORM框架可以幫助我們快速、簡便地操作數(shù)據(jù)庫,而中介者模式則可以讓我們的程序更加靈活可擴(kuò)展。同時(shí),在使用ORM框架時(shí),我們需要注意管理數(shù)據(jù)庫連接和釋放資源等問題,以保證軟件系統(tǒng)的穩(wěn)定性和安全性。

到此這篇關(guān)于一文弄懂Mybatis中介者模式的文章就介紹到這了,更多相關(guān)Mybatis中介者模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java分頁查詢--分頁顯示(實(shí)例講解)

    Java分頁查詢--分頁顯示(實(shí)例講解)

    下面小編就為大家?guī)硪黄狫ava分頁查詢--分頁顯示(實(shí)例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • MyBatis使用嵌套查詢collection和association的實(shí)現(xiàn)

    MyBatis使用嵌套查詢collection和association的實(shí)現(xiàn)

    本文詳細(xì)介紹了使用MyBatis框架進(jìn)行數(shù)據(jù)庫操作時(shí),如何利用collection標(biāo)簽實(shí)現(xiàn)一對多的嵌套查詢和使用association標(biāo)簽實(shí)現(xiàn)一對一的嵌套查詢,感興趣的可以了解一下
    2024-09-09
  • idea使用Mybatis逆向工程插件詳情

    idea使用Mybatis逆向工程插件詳情

    這篇文章主要介紹了idea使用Mybatis逆向工程插件詳情,首先使用mybatis連接數(shù)據(jù)庫接著添加連接的mysql的信息,測試鏈接等過程,更多過程了解請參考下面文章的詳細(xì)內(nèi)容
    2022-01-01
  • SpringCloud負(fù)載均衡實(shí)現(xiàn)定向路由詳情

    SpringCloud負(fù)載均衡實(shí)現(xiàn)定向路由詳情

    這篇文章主要介紹了SpringCloud負(fù)載均衡實(shí)現(xiàn)定向路由詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • spring-cloud入門之spring-cloud-config(配置中心)

    spring-cloud入門之spring-cloud-config(配置中心)

    這篇文章主要介紹了spring-cloud入門之spring-cloud-config(配置中心),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • SpringBoot如何通過配置文件(yml,properties)限制文件上傳大小

    SpringBoot如何通過配置文件(yml,properties)限制文件上傳大小

    這篇文章主要介紹了SpringBoot如何通過配置文件(yml,properties)限制文件上傳大小,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • SpringBoot中獲取配置文件的注解詳解

    SpringBoot中獲取配置文件的注解詳解

    這篇文章主要介紹了SpringBoot中獲取配置文件的注解詳解, 一般情況下:如果我們只是在某個(gè)業(yè)務(wù)邏輯中需要獲取一下配置文件中的某項(xiàng)值,使用@Value,如果我們使用JavaBean來與配置文件進(jìn)行映射,我們直接使用@ConfigurationProperties,需要的朋友可以參考下
    2023-10-10
  • SpringBoot如何優(yōu)雅的實(shí)現(xiàn)重試功能

    SpringBoot如何優(yōu)雅的實(shí)現(xiàn)重試功能

    這篇文章主要詳細(xì)介紹了SpringBoot如何優(yōu)雅的實(shí)現(xiàn)重試功能的步驟詳解,文中有詳細(xì)的代碼示例,具有一定的參考價(jià)值,感興趣的同學(xué)可以借鑒閱讀
    2023-06-06
  • 基于SpringBoot實(shí)現(xiàn)離線應(yīng)用的4種實(shí)現(xiàn)方式

    基于SpringBoot實(shí)現(xiàn)離線應(yīng)用的4種實(shí)現(xiàn)方式

    在當(dāng)今高度依賴網(wǎng)絡(luò)的環(huán)境中,離線應(yīng)用的價(jià)值日益凸顯,而且具備離線工作能力已成為許多應(yīng)用的必備特性,本文將介紹基于SpringBoot實(shí)現(xiàn)離線應(yīng)用的4種不同方式
    2025-06-06
  • 基于Java+Selenium實(shí)現(xiàn)保存網(wǎng)站登錄數(shù)據(jù)的詳細(xì)指南

    基于Java+Selenium實(shí)現(xiàn)保存網(wǎng)站登錄數(shù)據(jù)的詳細(xì)指南

    在使用 Selenium 進(jìn)行自動(dòng)化測試時(shí),頻繁地手動(dòng)登錄網(wǎng)站可能會非常耗時(shí),為了提高效率,我們可以采取一些措施來保存網(wǎng)站的登錄數(shù)據(jù),本文將詳細(xì)介紹兩種常見的方法,需要的朋友可以參考下
    2025-08-08

最新評論

来安县| 香港| 黑水县| 建始县| 都江堰市| 偏关县| 尼玛县| 镇江市| 应用必备| 德保县| 嘉祥县| 通化县| 陆河县| 巧家县| 廊坊市| 隆子县| 郸城县| 郎溪县| 普安县| 区。| 郧西县| 富平县| 南陵县| 洪雅县| 鄯善县| 马关县| 朝阳区| 麻阳| 同德县| 衡山县| 依兰县| 新田县| 万州区| 明星| 张家川| 吉木乃县| 黔西| 南丰县| 阜平县| 兴安县| 武义县|