IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java - Mybatis 框架详解(一) -> 正文阅读

[Java知识库]Java - Mybatis 框架详解(一)

1. 前置SQL语句

  1. 创建名为tedu_ums的数据库;
CREATE DATABASE tedu_ums;
USE tedu_ums;
  1. 在以上数据库中,创建名为t_user的数据表,该表中应该至少包括id、用户名、密码、年龄、手机号码、电子邮箱这几个字段;
CREATE TABLE t_user (
	id INT AUTO_INCREMENT COMMENT '用户id',
	username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名',
	password VARCHAR(20) NOT NULL COMMENT '密码',
	age INT COMMENT '年龄',
	phone VARCHAR(20) COMMENT '手机号码',
	email VARCHAR(30) COMMENT '电子邮箱',
	PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
  1. 插入不少于10条数据,每条数据的各字段值尽量随机;
INSERT INTO t_user (username,password,phone,age) VALUES 
	('Henry', 'fdas', '13800138001', 26),
	('Zeo', 'vcvx', '13800138002', 21),
	('Alex', 'reer', '13800138003', 28),
	('Frank', 'jhgd', '13800138004', 22),
	('David', 'hgdf', '13800138005', 23),
	('Mike', 'cxvn', '13800138006', 20),
	('Lucy', 'qrec', '13800138007', 29),
	('Lily', 'rfdx', '13800138008', 24),
	('LiLei', 'nmhr', '13800138009', 27),
	('HanMM', 'uhjy', '13800138010', 32)
;
  1. 删除id=?的数据;
DELETE FROM t_user WHERE id=?;
  1. 一次性删除id=?、id=?、id=?的数据;
DELETE FROM t_user WHERE id IN (?,?,?);

DELETE FROM t_user WHERE id=? OR id=? OR id=?;
  1. 将id=?的数据的电子邮箱改为?;
UPDATE t_user SET email=? WHERE id=?;
  1. 将所有用户的密码全部改为?;
UPDATE t_user SET password=?;
  1. 统计当前表中用户的数量;
SELECT COUNT(*) FROM t_user;
  1. 查询id=?的用户的数据;
SELECT * FROM t_user WHERE ID=?;
  1. 查询用户名=?的用户的数据;
SELECT * FROM t_user WHERE username=?;
  1. 查询所有用户的数据;
SELECT * FROM t_user ORDER BY id;
  1. 查询年龄最大的那1个用户的数据(假设所有用户的年龄值都不同)。
SELECT * FROM t_user WHERE age=(SELECT MAX(age) FROM t_user);

SELECT * FROM t_user ORDER BY age DESC LIMIT 0,1;

2. MyBatis框架的作用

MyBatis框架最直接的作用就是简化持久层开发!

持久层:处理数据持久化的组件;

持久化:将数据永久的存储下来;

使用MyBatis框架处理增删改查时,只需要定义功能的抽象方法,并配置这个抽象方法对应的SQL语句即可!

3. 创建项目

创建Maven Project,勾选Create a simple ProjectGroup idcn.teduArtifact idMyBatisPackaingwar(不必要)。

创建完之后,还是应该:生成web.xml;添加Tomcat运行环境(不必要);从前序项目中复制依赖;从前序项目中复制spring.xml;从前序项目中复制web.xml中的配置。

此次使用MyBatis框架,需要添加mybatis的依赖:

<!-- MyBatis框架 -->
<!-- 可选版本:3.5.0~3.5.3 -->
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis</artifactId>
	<version>3.5.3</version>
</dependency>

MyBaits框架可以单独使用,但是,配置起来非常麻烦,通常会整合Spring框架一起使用,所以,还需要添加mybatis-spring的依赖:

<!-- MyBatis整合Spring -->
<!-- 可选版本:2.0.0~2.0.3 -->
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis-spring</artifactId>
	<version>2.0.3</version>
</dependency>

整合了Spring之后,还需要添加spring-context依赖,当然,也可以直接使用spring-webmvc依赖,因为其中包含了spring-context依赖,同时,因为底层实现依然使用了JDBC相关技术,所以,需要另行添加spring-jdbc依赖,该依赖的版本必须与spring-webmvc的版本完全相同:

<!-- Spring-JDBC -->
<!-- 版本:与spring-webmvc完全一致 -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-jdbc</artifactId>
	<version>????????</version>
</dependency>

另外,由于需要结合MySQL数据库编程,所以,还需要添加MySQL数据库连接的mysql-connector-java依赖:

<!-- MySQL -->
<!-- 可选版本:5.1.34~5.1.39,8.0.12~8.0.18 -->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>8.0.18</version>
</dependency>

然后,还应该添加数据库连接池commons-dbcp的依赖:

<!-- 数据库连接池 -->
<!-- 可选版本:1.2~1.4 -->
<dependency>
	<groupId>commons-dbcp</groupId>
	<artifactId>commons-dbcp</artifactId>
	<version>1.4</version>
</dependency>

最后,此次将通过单元测试检验开发的功能,所以,还需要添加junit的依赖。

另外,将spring.xml重命为spring-mvc.xml,将其复制一份,得到spring-dao.xml,删除spring-dao.xml中的配置。

4. 连接数据库

src/main/resources下创建db.properties文件,并在其中配置连接数据库的信息:

url=jdbc:mysql://localhost:3306/tedu_ums?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
driver=com.mysql.cj.jdbc.Driver
username=root
password=root
initialSize=2
maxActive=10

serverTimezone值只能是 Asia/ShanghaiAsia/Chongqing

然后,应该在spring-dao.xml中配置<util:properties>节点读取以上配置信息:

<!-- 读取连接数据库的配置文件 -->
<util:properties id="dbConfig" location="classpath:db.properties" />

然后,配置BasicDataSource,并把以上读取到的配置信息注入到相关属性中:

<!-- 数据源:BasicDataSource -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
	<property name="url" value="#{dbConfig.url}"/>
	<property name="driverClassName" value="#{dbConfig.driver}"/>
	<property name="username" value="#{dbConfig.username}"/>
	<property name="password" value="#{dbConfig.password}"/>
	<property name="initialSize" value="#{dbConfig.initialSize}"/>
	<property name="maxActive" value="#{dbConfig.maxActive}"/>
</bean>

完成后,可以在src/test/java下创建cn.tedu.mybatis.Tests测试类,以测试是否可以正确连接到数据库:

public class Tests {

	ClassPathXmlApplicationContext ac;
	
	@Test
	public void getConnection() throws SQLException {
		BasicDataSource dataSource = (BasicDataSource) ac.getBean("dataSource");
		Connection conn = dataSource.getConnection();
		System.out.println(conn);
	}
	
	@Before
	public void doBefore() {
		ac = new ClassPathXmlApplicationContext(
			"spring-dao.xml");
	}
	
	@After
	public void doAfter() {
		ac.close();
	}

}

5. 抽象方法

假设当前需要开发“向用户表中插入用户数据”的功能。

MyBatis要求相关的抽象方法都封装在接口中,所以,需要先创建cn.tedu.mybatis.UserMapper接口:

public interface UserMapper {

}

然后,在接口中声明要开发的功能对应的抽象方法,关于抽象方法的声明原则:

  1. 如果即将执行的SQL语句是增、删、改类型的SQL语句,应该将返回值声明为Integer,表示“受影响的行数”,也可以声明为void,表示不关心受影响的行数是多少;如果即将执行的SQL语句是查询类型的SQL语句,返回值可以按需设计,只要能够封装查询结果即可;

  2. 方法的名称可以自定义,但是,不允许出现重载的方法名

  3. 方法的参数列表可以根据执行SQL语句时需要哪些变量来决定,需要哪些变量,就添加哪些参数。

执行“插入用户数据”的SQL语句的格式大致是:

insert into t_user (username,password,age,phone,email) values (?,?,?,?,?);

所以,抽象方法可以设计为:

Integer xxx(String username, String password, Integer age, String phone, String email);

当然,参数的数量较多,或参数的数量可能发生变化时,所以,也可以将各数据进行封装:

public class User {
	private String username;
	private String password;
	private Integer age;
	private String phone;
	private String email;
}

则抽象方法还可以设计为:

public interface UesrMapper {
	Integer addnew(User user);
}

接下来,还需要配置接口文件的位置,所以在spring-dao.xml中配置MapperScannerConfigurer

<!-- 配置MapperScannerConfigurer -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<!-- 配置接口文件所在的包 -->
	<property name="basePackage" value="cn.tedu.mybatis" />
</bean>

6. SQL语句

src/main/resources下创建名为mappers的文件夹,在该文件夹下创建SomeMapper.xml文件(文章末尾附)。

打开SomeMapper.xml,首先,添加根节点<mapper>,并在该节点中配置namespace属性,属性值是对应的接口文件的全名:

<mapper namespace="cn.tedu.mybatis.UserMapper">

</mapper>

然后,根据即将要执行的SQL语句的种类选择子级节点,子节点的id属性的值是对应的抽象方法的名称,再在子级配置需要执行的SQL语句:

<!-- id属性:对应的抽象方法的名称 -->
<insert id="addnew">
	INSERT INTO t_user (
		username, password,
		age, phone,
		email
	) VALUES (
		#{username}, #{password},
		#{age}, #{phone},
		#{email}
	)
</insert>

注意:以上配置中,值列表部分的#{}的占位符里都是addnew()方法的参数User类型中的属性名!

然后,还需要配置SqlSessionFactoryBean,用于指定XML配置文件的位置使用哪个数据源连接数据库,所以,在spring-dao.xml中配置:

<!-- 配置SqlSessionFactoryBean -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
	<!-- 配置XML文件的位置 -->
	<property name="mapperLocations" value="classpath:mappers/*.xml" />
	<!-- 配置使用哪个数据源 -->
	<property name="dataSource" ref="dataSource" />
</bean>

最后,先测试类中添加新的全局变量:

UserMapper userMapper;

doBefore()中补充获取该对象的值:

@Before
public void doBefore() {
	ac = new ClassPathXmlApplicationContext(
		"spring-dao.xml");
	userMapper = ac.getBean(
		"userMapper", UserMapper.class);
}

然后,编写并执行单元测试:

@Test
public void addnew() {
	User user = new User();
	user.setUsername("Tommy");
	user.setPassword("o8ur");
	user.setAge(35);
	user.setPhone("13800138035");
	user.setEmail("tommy@163.com");
	Integer rows = userMapper.addnew(user);
	System.out.println("rows=" + rows);
}

7. 删除id=?的数据

UserMapper接口中添加抽象方法:

Integer deleteById(Integer id);

SomeMapper.xml中添加配置:

<delete id="deleteById">
	DELETE FROM t_user WHERE id=#{id}
</delete>

完成后,可以在Tests中编写单元测试:

@Test
public void deleteById() {
	Integer id = 5;
	Integer rows = userMapper.deleteById(id);
	System.out.println("rows=" + rows);
}

8. 将所有用户的密码全部改为?

UserMapper接口中添加抽象方法:

Integer updatePassword(String password);

SomeMapper.xml中添加配置:

<update id="updatePassword">
	UPDATE t_user SET password=#{password}
</update>

完成后,可以在Tests中编写单元测试:

@Test
public void updatePassword() {
	String password = "8888";
	Integer rows = userMapper.updatePassword(password);
	System.out.println("rows=" + rows);
}

9. 统计当前表中用户的数量

UserMapper接口中添加抽象方法:

Integer count();

SomeMapper.xml中添加配置:

<select id="count" resultType="java.lang.Integer">
	SELECT COUNT(*) FROM t_user;
</select>

注意:在配置<select>节点时,必须指定resultTyperesultMap属性中的某1个。

完成后,可以在Tests中编写单元测试:

@Test
public void count() {
	Integer count = userMapper.count();
	System.out.println("count=" + count);
}

10. 查询id=?的用户的数据

UserMapper接口中添加抽象方法:

User findById(Integer id);

SomeMapper.xml中添加配置:

<select id="findById" resultType="cn.tedu.mybatis.User">
	SELECT * FROM t_user WHERE id=#{id}
</select>

完成后,可以在Tests中编写单元测试:

@Test
public void findById() {
	Integer id = 1000;
	User result = userMapper.findById(id);
	System.out.println(result);
}

11. 查询所有用户的数据

UserMapper接口中添加抽象方法:

List<User> findAll();

SomeMapper.xml中添加配置:

<select id="findAll" resultType="cn.tedu.mybatis.User">
	SELECT * FROM t_user ORDER BY id
</select>

注意:如果查询的结果是某种对象,不管是查1个数据,还是查多个数据形成List集合,在配置SQL语句时,resultType都只用写对象归属的类型,即:查询结果是List集合时,只需要告诉MyBatis框架集合中放的是什么类型的数据即可!

完成后,可以在Tests中编写单元测试:

@Test
public void findAll() {
	List<User> list = userMapper.findAll();
	System.out.println("size=" + list.size());
	for (User item : list) {
		System.out.println(item);
	}
}

----------------------------------------

附1:关于提示Invalid bound statement (not found)的解决方案

出现以上错误提示的话,可能的原因有:

  1. spring-dao.xml中没有配置SqlSessionFactoryBeanmapperLocations属性,或者配置值是错误的,例如:存储XML文件的文件夹叫mappers,但是,配置值却是classpath:mapper/*.xml

  2. SomeMapper.xml中,根节点的namespace值有误;

  3. SomeMapper.xml中,子级的增删改查节点的id值不是抽象方法的名称;

pom.xml 完整依赖配置

<dependencies>
   <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>4.11</version>
     <scope>test</scope>
   </dependency>

   <!--  Spring 框架  -->
   <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-webmvc</artifactId>
     <version>4.3.8.RELEASE</version>
   </dependency>

   <!-- Spring-JDBC -->
   <!-- 版本:与spring-webmvc完全一致 -->
   <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-jdbc</artifactId>
     <version>4.3.8.RELEASE</version>
   </dependency>

   <!--  Thymeleaf模版  -->
   <dependency>
     <groupId>org.thymeleaf</groupId>
     <artifactId>thymeleaf</artifactId>
     <version>3.0.11.RELEASE</version>
   </dependency>

   <dependency>
     <groupId>org.thymeleaf</groupId>
     <artifactId>thymeleaf-spring4</artifactId>
     <version>3.0.11.RELEASE</version>
   </dependency>

   <!-- MyBatis框架 -->
   <!-- 可选版本:3.5.0~3.5.3 -->
   <dependency>
     <groupId>org.mybatis</groupId>
     <artifactId>mybatis</artifactId>
     <version>3.5.3</version>
   </dependency>

   <!-- MyBatis整合Spring -->
   <!-- 可选版本:2.0.0~2.0.3 -->
   <dependency>
     <groupId>org.mybatis</groupId>
     <artifactId>mybatis-spring</artifactId>
     <version>2.0.3</version>
   </dependency>

   <!-- MySQL -->
   <!-- 可选版本:5.1.34~5.1.39,8.0.12~8.0.18 -->
   <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>8.0.18</version>
   </dependency>

   <!-- 数据库连接池 -->
   <!-- 可选版本:1.2~1.4 -->
   <dependency>
     <groupId>commons-dbcp</groupId>
     <artifactId>commons-dbcp</artifactId>
     <version>1.4</version>
   </dependency>

 </dependencies>

完整的 spring-dao.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:context="http://www.springframework.org/schema/context"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
		http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">

        <!-- 读取连接数据库的配置文件 -->
        <util:properties id="dbConfig" location="classpath:db.properties"/>

        <!-- 数据源:BasicDataSource -->
        <bean id="basicDataSource" class="org.apache.commons.dbcp.BasicDataSource">
            <property name="url" value="#{dbConfig.url}"/>
            <property name="driverClassName" value="#{dbConfig.driver}"/>
            <property name="username" value="#{dbConfig.username}"/>
            <property name="password" value="#{dbConfig.password}"/>
            <property name="initialSize" value="#{dbConfig.initialSize}"/>
            <property name="maxActive" value="#{dbConfig.maxActive}"/>
        </bean>

        <!--  配置 MapperScannerConfigurer  -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="cn.tedu.mybatis"></property>
        </bean>

        <!--  配置 SqlSessionFactoryBean  -->
        <bean class="org.mybatis.spring.SqlSessionFactoryBean">
            <!--  配置xml文件位置 -->
            <property name="mapperLocations" value="classpath:mappers/*.xml"/>
            <!-- 配置数据源 -->
            <property name="dataSource" ref="basicDataSource"/>
        </bean>
</beans>

完整的 SomeMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"      
 "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">

<!-- namespace属性:接口的全名 -->
<mapper namespace="cn.tedu.mybatis.UserMapper">
    <insert id="createUser">
        INSERT INTO t_user (
            username, password, age, phone, email
        ) VALUES (
            #{ username }, #{ password }, #{ age }, #{ phone }, #{ email }
        )
    </insert>

    <delete id="deleteById">
        DELETE FROM t_user WHERE id = #{ id }
    </delete>

    <update id="updatePassword">
        UPDATE t_user SET password = #{ password }
    </update>

    <!--  查询语句必须要定义 resultType 或者 resultMap 属性,返回的值  -->
    <select id="selectCount" resultType="java.lang.Integer">
        SELECT COUNT(*) FROM t_user
    </select>

    <select id="findById" resultType="cn.tedu.mybatis.User">
        SELECT * FROM t_user WHERE id = #{ id }
    </select>
</mapper>

完整的 UserMapper类

package cn.tedu.mybatis;

public interface UserMapper {

    // 方法名称可以自定义,但是不能重载!!!(myBatis无法识别是调用哪个方法)
    // 方法的返回值是影响的行数(增删改)
    Integer createUser (User user);

    Integer deleteById (Integer id);

    Integer updatePassword (String password);

    Integer selectCount();

    User findById(Integer id);
}

完整的单元测试类

package cn.tedu.mybatis.mybatis;

import cn.tedu.mybatis.User;
import cn.tedu.mybatis.UserMapper;
import org.apache.commons.dbcp.BasicDataSource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.net.Inet4Address;
import java.sql.Connection;
import java.sql.SQLException;

public class Tests {
    MapperScannerConfigurer msc;
    ClassPathXmlApplicationContext ac;
    UserMapper userMapper;

    @Test
    public void getConnection () throws SQLException {
        BasicDataSource dataSource = (BasicDataSource) ac.getBean("basicDataSource");
        Connection conn = dataSource.getConnection();
        System.out.println(conn);
    }

    @Test
    public void createUser () {
        User user = new User();
        user.setUsername("Tom");
        user.setPassword("123456");
        user.setAge(25);
        user.setPhone("17520694906");
        user.setEmail("324224@qq.com");
        Integer rows =  userMapper.createUser(user);
        System.out.println("rows = " + rows);
    }

    @Test
    public void deleteById () {
        Integer id = 5;
        Integer rows = userMapper.deleteById(id);
        System.out.println("rows = " + rows);
    }

    @Test
    public void updatePassword () {
        String password = "123456";
        Integer rows = userMapper.updatePassword(password);
        System.out.println("rows = " + rows);
    }

    @Test
    public void selectCount () {
        Integer count = userMapper.selectCount();
        System.out.println("count = " + count);
    }

    @Test
    public void findById () {
        Integer id = 6;
        User user = userMapper.findById(id);
        System.out.println("user = " + user);
    }

    @Before
    public void doBefore () {
        ac = new ClassPathXmlApplicationContext("spring-dao.xml");
        userMapper = ac.getBean("userMapper", UserMapper.class);
    }

    @After
    public void doAfter () {
        ac.close();
    }
}

如果这篇文章有帮助到您,请简单给个赞吧,谢谢~

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-10-23 12:20:41  更:2021-10-23 12:22:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:05:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码