05、JavaWeb启程——JDBC详解
创始人
2024-01-16 18:24:54

1、JDBC概述

1、持久化概述

【简介】: 持久化指的是把内存中的数据存储到可掉电存储设备中以供之后使用。

2、JDBC概述

【简介】: JDBC是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一的访问。

【JDBC本质】: 其实就是Java官方提供的一套规范,帮助开发人员快速实现不同关系型数据库的连接。

【图解JDBC作用】:
在这里插入图片描述
在这里插入图片描述

2、JDBC快速入门

1、环境准备

  • 拷贝 MySQL 的 JDBC 驱动,到 Java 项目中: mysql-connector-java-5.1.26-bin.jar
  • 注意: 是 jar 包,不是 zip 包.
  • 选择 jar,把 jar 引用到 classpath 路径.idea 项目中创建一个目录 lib右键 lib 目录,点 Add as Library

2、JDBC开发流程

  • 加载数据库驱动
  • 获取连接对象
  • 创建获取语句对象
  • 执行SQL语句
  • 释放资源

3、JDBC快速入门

1、创建数据库和表

CREATE DATABASE demo;
CREATE TABLE t_student(
id BIGINT PRIMARY KEY AUTO_INCREMENT, 
name VARCHAR(20), 
age INT,
email VARCHAR(20)
);

2、完成插入功能

public class JdbcInsert {public static void main(String[] args) {try {// 1、加载数据库驱动Class.forName("com.mysql.jdbc.Driver");// 2、获取数据库连接Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "admin");// 3、创建语句对象Statement statement=connection.createStatement();// 4、执行sqlString sql="INSERT INTO student(name,age,email)VALUES('张三',18,'15651321@qq.com')";statement.execute(sql);// 5、释放资源statement.close();connection.close();} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();}}
}

3、JDBC功能类详解

1、DriverManager类

【DriverManager】: 驱动管理对象,主要用于加载注册关系型数据库的Driver类以及获取关系型数据库的连接对象。

【加载数据库驱动】:

  • 注册给定的数据库驱动对象:
public static void registerDriver(java.sql.Driver driver)throws SQLException {registerDriver(driver, null);}
  • 获取连接对象
/**
* 参数:
* url:指定连接某一个数据库的路径
* username:连接数据库的账号
* password:连接数据库的密码
**/public static Connection getConnection(String url,String user, String password) throws SQLException {java.util.Properties info = new java.util.Properties();if (user != null) {info.put("user", user);}if (password != null) {info.put("password", password);}return (getConnection(url, info, Reflection.getCallerClass()));}

2、Connection类

【简介】: 关系型数据库连接对象,相当于Java程序和数据的通信桥梁。

【获取执行语句对象】:

  • 获取静态语句执行对象:
Statement createStatement() throws SQLException;
  • 获取预编译语句执行对象:
PreparedStatement prepareStatement(String sql) throws SQLException;

3、Statement类

【简介】: 静态SQL语句执行对象,用于执行字符串的SQL语句。

  • 执行DML/DDL语句:
/**
* 返回值:受影响行数
* 参数:insert、update、delete、create语句
*/
int executeUpdate(String sql) throws SQLException;
  • 执行DQL语句:
ResultSet executeQuery(String sql) throws SQLException;
  • 释放资源
// 关闭Statement对象
void close() throws SQLException;

4、DAO思想

1、DAO思想引入

在这里插入图片描述
没有dao的时候我们会存在大量的代码重复。

2、DAO介绍和方法设计

【简介】: DAO(数据库访问对象)是一个面向对象的数据库接口。将所有对数据源访问操作抽象封装在一个公共API中。

【设计图解】:
在这里插入图片描述

3、DAO开发规范

【命名规范】:

  • DAO 接口 : 表示对某个模型的 CRUD 操作做规范,以 I 开头,interface
    • 标准:IXxxDAO
    • 例: IEmployeeDAO/IStudentDAO
  • DAO 实现类: 表示对某个 DAO 接口的实现
    • 标准:XxxDAOImpl
    • 例:EmployeeDAOImpl/StudentDAOImpl
  • DAO 测试类: 测试 DAO 组件中的所有方法
    • 标准:XxxDAOTest: XxxDAO 组件的测试类,
    • 例:EmployeeDAOTest,StudentDAOTest

4、根据DAO规范搭建项目

  1. 创建项目
  2. 导入数据库驱动包
  3. 创建表和模型包以及模型对象 (domain/Student)
package cn.simplelife.daodemo.domain;import lombok.*;import java.math.BigDecimal;/*** @ClassName Student* @Description* @Author simplelife* @Date 2022/10/3 18:21* @Version 1.0*/@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
public class Student {private Long id;private String name;private Integer age;private String email;
}
  1. 创建 DAO 包和 DAO 接口,设计 DAO 接口方法 (dao/IStudentDAO)
package cn.simplelife.daodemo.dao;import cn.simplelife.daodemo.domain.Student;import java.util.List;/*** @ClassName IStudentDao* @Description* @Author simplelife* @Date 2022/10/3 18:25* @Version 1.0*/public interface IStudentDAO {/*** 插入一个学生信息* @param student 要插入的学生信息*/void insert(Student student);/*** 根据id删除一个学生信息* @param id 要删除的学生id*/void delete(Long id);/*** 根据学生id修改学生id* @param student 要修改学生的id和新的信息*/void update(Student student);/*** 根据学生的id查询学生的信息* @param id 要查询的学生id* @return 返回一个学生信息*/Student selectOne(Long id);/*** 查询所有的学生信息* @return 返回所有的学生信息列表*/List selectList();
}
  1. 创建 DAO 实现包,实现 DAO 接口(dao.impl/StudentDAOImpl)
package cn.simplelife.daodemo.dao.impl;import cn.simplelife.daodemo.dao.IStudentDAO;
import cn.simplelife.daodemo.domain.Student;import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;/*** @ClassName StudentDaoImpl* @Description* @Author simplelife* @Date 2022/10/3 18:24* @Version 1.0*/public class StudentDAOImpl implements IStudentDAO {@Overridepublic void insert(Student student) {Connection connection = null;PreparedStatement preparedStatement = null;try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "INSERT INTO student(name,age,email)VALUES(?,?,?)";preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, student.getName());preparedStatement.setInt(2, student.getAge());preparedStatement.setString(3, student.getEmail());preparedStatement.execute();} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}@Overridepublic void delete(Long id) {Connection connection = null;PreparedStatement preparedStatement = null;try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "DELETE FROM student WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setLong(1, id);preparedStatement.execute();} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}@Overridepublic void update(Student student) {Connection connection = null;PreparedStatement preparedStatement = null;try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "UPDATE student SET name=?, age=?, email=? WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, student.getName());preparedStatement.setInt(2, student.getAge());preparedStatement.setString(3, student.getEmail());preparedStatement.setLong(4, student.getId());preparedStatement.execute();} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}@Overridepublic Student selectOne(Long id) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;Student student = new Student();try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "SELECT * FROM student WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setLong(1, id);resultSet = preparedStatement.executeQuery();if (resultSet.next()) {long resultId = resultSet.getLong("id");String name = resultSet.getString("name");int age = resultSet.getInt("age");String email = resultSet.getString("email");student.setId(resultId);student.setName(name);student.setAge(age);student.setEmail(email);}} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}return student;}@Overridepublic List selectList() {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;List list = new ArrayList<>();Student student = null;try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "SELECT * FROM student";preparedStatement = connection.prepareStatement(sql);resultSet = preparedStatement.executeQuery();while (resultSet.next()) {long resultId = resultSet.getLong("id");String name = resultSet.getString("name");int age = resultSet.getInt("age");String email = resultSet.getString("email");student = new Student(resultId, name, age, email);list.add(student);}} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}return list;}
}
  1. 创建测试目录,生成测试类和方法(test/StudentDAOTest)
package cn.simplelife.daodemo.test;import cn.simplelife.daodemo.dao.IStudentDAO;
import cn.simplelife.daodemo.dao.impl.StudentDAOImpl;
import cn.simplelife.daodemo.domain.Student;
import org.junit.Test;import java.util.List;/*** @ClassName StudentDAOTest* @Description* @Author simplelife* @Date 2022/10/3 18:40* @Version 1.0*/public class StudentDAOTest {private IStudentDAO studentDAO = new StudentDAOImpl();@Testpublic void insert() {studentDAO.insert(new Student(null, "王五", 52, "6521@qq.com"));}@Testpublic void delete() {studentDAO.delete(2L);}@Testpublic void update() {Student student = new Student();student.setId(4L);student.setName("李四");student.setAge(18);student.setEmail("156321@qq.com");studentDAO.update(student);}@Testpublic void selectOne() {Student student = studentDAO.selectOne(4L);System.out.println(student);}@Testpublic void selectList() {List students = studentDAO.selectList();System.out.println(students);}
}

5、预编译语句对象

1、预编译语句对象简介

【简介】: PrepareStatement接口:是Statement接口的子接口,享有Statement中的方法。使用预编译语句对象,sql语句中使用?做占位符。

2、API详解

  • Connection API:
 PreparedStatement conn对象的.prepareStatement(String sql);
  • PreparedStatement API:
//设置第几个占位符的真正参数值. Xxx 表示数据类型,比如 String,int,long,Date等.
void setXxx(int parameterIndex,Xxx value); //设置第几个占位符的真正参数值.
void setObject(int parameterIndex, Object x); //执行DDL/DML语句. 注意:没有参数 // 若当前 SQL是 DDL语句,则返回 0.// 若当前 SQL是 DML语句,则返回受影响的行数.
int executeUpdate(); //执行DQL语句,返回结果集.
ResultSet executeQuery(); //释放资源
close(); 

【举例】:

public void insert(Student student) {Connection connection = null;PreparedStatement preparedStatement = null;try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "INSERT INTO student(name,age,email)VALUES(?,?,?)";preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, student.getName());preparedStatement.setInt(2, student.getAge());preparedStatement.setString(3, student.getEmail());preparedStatement.execute();} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}

6、重构设计

1、抽取JDBCUtil工具类

package cn.simplelife.homework.utils;import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;/*** 与操作数据库相关的工具*/
public class JDBCUtils {/*** 私有化构造器防止外部创建对象*/private JDBCUtils() {}/*** 私有化静态的Properties对象*/private static Properties properties;static {// 1、获取类加载器ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();// 2、获取文件并将其转为输入流InputStream resourceAsStream = contextClassLoader.getResourceAsStream("db.properties");try {// 3、判断输入流是否为空if (resourceAsStream != null) {// 4、加载流文件properties = new Properties();properties.load(resourceAsStream);}// 5、加载数据库驱动Class.forName(properties.getProperty("driverClassName"));} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}/*** 获取数据库连接对象** @return 返回获取的连接对象*/public static Connection getConnection() {try {return DriverManager.getConnection(properties.getProperty("url"), properties.getProperty("username"), properties.getProperty("password"));} catch (SQLException e) {e.printStackTrace();}return null;}/*** 关闭资源** @param connection 关闭获取的连接* @param statement  关闭静态sql执行资源* @param resultSet  关闭结果集资源*/public static void close(Connection connection, Statement statement, ResultSet resultSet) {if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}

2、抽取db.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/student
username=root
password=????

7、JDBC事务操作

【简介】: 事务是指将一组操作括为一个单元,为确保数据库中数据的一致性,数据操作是成组的单元,当单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。

1、事务的属性

  • 原子性:事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
  • 一致性:保证数据的完整性. 事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
  • 隔离性:事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
  • 持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。

2、事务操作步骤

  • 定义开始一个事务,然后对数据进行修改操作。
  • 执行过程中如果没有问题就提交事务,此时修改将会被永久的保存起来。
  • 如果在执行过程中发生异常,回滚事务,数据库管理系统会将放弃您的所有的修改而回到开始事务的状态。

3、操作事务的模板

try{
//取消事务自动提交机制,设置为手动提交
connection对象.setAutoCommit(false);
//操作1
//操作2
//异常
//操作3
//....
//所有操作成功则 手动提交事务
connection对象.commit();
}catch(Exception e){
//处理异常
//出现异常 回滚事务
connection对象.rollback();
}

4、事务举例

  • Account类
package cn.simplelife.work.domain;import lombok.*;import java.math.BigDecimal;/*** @ClassName Account* @Description* @Author simplelife* @Date 2022/10/4 20:16* @Version 1.0*/
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class Account {private Long id;private String name;private BigDecimal balance;
}
  • IAccountDAO接口
package cn.simplelife.work.dao;import cn.simplelife.work.domain.Account;import java.math.BigDecimal;/*** @ClassName IAccountDAO* @Description* @Author simplelife* @Date 2022/10/4 20:38* @Version 1.0*/public interface IAccountDAO {/*** 转账** @param sourceAccount 源账户* @param targetAccount 目标账户* @param money         转账金额*/void transfer(Account sourceAccount, Account targetAccount, BigDecimal money);
}
  • IAccountDAOImpl实现类
package cn.simplelife.work.dao.Impl;import cn.simplelife.work.dao.IAccountDAO;
import cn.simplelife.work.domain.Account;
import cn.simplelife.work.utils.JDBCUtils;import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** @ClassName IAccountDAOImpl* @Description* @Author simplelife* @Date 2022/10/4 20:43* @Version 1.0*/public class IAccountDAOImpl implements IAccountDAO {@Overridepublic void transfer(Account sourceAccount, Account targetAccount, BigDecimal money) {Connection connection = JDBCUtils.getConnection();PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {if (connection != null) {// 1、判断是否有足够的余额String sql = "SELECT * FROM account WHERE id=? AND balance>=1000";preparedStatement = connection.prepareStatement(sql);preparedStatement.setLong(1, sourceAccount.getId());resultSet = preparedStatement.executeQuery();// 2、余额不足开启提醒if (!resultSet.next()) {System.out.println("账户余额不足!请充值!");return;}// 3、余额充足开始转账sql = "UPDATE account SET balance = balance-? WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setBigDecimal(1, money);preparedStatement.setLong(2, sourceAccount.getId());preparedStatement.executeUpdate();// 模拟停电int i = 10 / 0;// 4、账户价钱sql = "UPDATE account SET balance = balance+? WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setBigDecimal(1, money);preparedStatement.setLong(2, targetAccount.getId());preparedStatement.executeUpdate();}} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.close(connection, preparedStatement, resultSet);}}
}
  • 测试类
package cn.simplelife.work.dao.test;import cn.simplelife.work.dao.IAccountDAO;
import cn.simplelife.work.dao.Impl.IAccountDAOImpl;
import cn.simplelife.work.domain.Account;
import cn.simplelife.work.utils.DataSourceUtils;
import org.junit.Test;import java.math.BigDecimal;
import java.sql.Connection;import static org.junit.Assert.*;/*** @ClassName IAccountDAOImplTest* @Description* @Author simplelife* @Date 2022/10/4 21:15* @Version 1.0*/public class IAccountDAOImplTest {private IAccountDAO accountDAO = new IAccountDAOImpl();@Testpublic void transfer() {Account sourceAccount = new Account();Account targetAccount = new Account();sourceAccount.setId(1L);targetAccount.setId(2L);accountDAO.transfer(sourceAccount, targetAccount, new BigDecimal("1000"));}
}

5、事务使用注意事项

  • 默认情况下,事务在执行完DML操作之后就会自动提交。
  • 查询操作实际上不需要事务,但是,我们在开发中都把查询放入事务中。
  • 开发中,代码完全正确,没有异常,但是数据库中数据没有变化,可能是没有提交事务。
  • 在 MySQL 中,只有 InnoDB 存储引擎支持事务,支持外键,MyISAM 不支持事务。

8、SQL注入详解

1、Statement 和 PreparedStatement 的区别

  • PreparedStatement 具有更好的可读性,可维护性。
  • PreparedStatement 可以提供更好的性能。Mysql不支持PreparedStatement 性能优化。
  • PreparedStatement 更安全可以防止sql注入。

9、连接池思想

1、连接池引入和介绍

【简介】: 普通的 JDBC 数据库连接(Connectiond对象)使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码得花费 0.05s~1s 的时间, 时间成本比较大 。

【图解】:
在这里插入图片描述
【基本属性】: 连接池存了连接对象,而连接对象依赖四要素,所以四要素是基本要求。

【其他属性】:

  • 初始化连接数:5 在连接池中事先准备好5个Connection对象
  • 最多连接数:10 在连接池中最多有10个Connection对象,其他客户端进入等待状态
  • 最少连接数 : 3 在连接池中最少存在3个Connection对象
  • 最长等待时间:5 min 使用5分钟来申请获取 Connection 对象,如果时间到还没有申请到,则提示,自
    动放弃
  • 最长超时时间:10min 如果你在10分钟之内没有任何动作,则认为是自动放弃 Connection 对象.

2、druid连接池的使用

  • 拷贝 jar: druid-1.0.15.jar
  • 抽取db.properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/student
username=root
password=????
  • 创建工具类
package cn.simplelife.work.utils;import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;/*** @ClassName DataSourceUtils* @Description* @Author simplelife* @Date 2022/10/14 9:34* @Version 1.0*/public class DataSourceUtils {private DataSourceUtils() {}private static DataSource dataSource = null;static {InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties");try {if (resourceAsStream != null) {Properties properties = new Properties();properties.load(resourceAsStream);// 调用工厂中的方法创建连接池对象dataSource = DruidDataSourceFactory.createDataSource(properties);}} catch (Exception e) {e.printStackTrace();}}/*** 获取数据库连接对象** @return 返回一个数据库连接对象*/public static Connection getConnection() {try {return dataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return null;}public static void close(Connection connection, Statement statement, ResultSet resultSet){if (resultSet!=null){try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement!=null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...