1、网络通信概述
端口号
TCP通信的步骤:
服务器端先启动,服务器端不会主动请求客户端,必须客户端请求服务器端,客户端和服务器端就会建立一个逻辑连接,而这个连接中会包含一个IO对象,客户端和服务器端就可以使用这个对象进行通信,通信的数据不仅仅是字符,因此这个IO对象是字节流对象。
1.1 TCP通信的客户端
TCP通信的客户端:向服务器发送连接请求,给服务器发送数据,读取服务器回写的数据
- 构造方法
- Socket(String host,int port):创建一个流套接字并将其链接到指定主机的指定端口
- 参数
- String host:服务器主机的名称/服务器的IP地址
- in port:服务器的端口号
- 成员方法
- getOutputStream()
- getInputStream()
- close()
- 实现步骤:
- 创建一个客户端对象Socket,构造方法中绑定服务器的IP地址和端口号
- 使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
- 使用网络字节输出流OutputStream对象中的方法write,给服务器发送数据
- 使用Socket对象中的方法getInputStream(),获取网络字节输入流对象InputStream对象
- 使用网络字节输入流对象InputStream对象中的方法read,读取服务器回写的数据
- 释放资源
- 注意:
- 客户端和服务器端进行交互,必须使用Socket中提供的网络流,不能使用自己创建的流对象
- 当我们创建客户端对象Socket时,就会去请求服务器和服务器经过3次握手建立连接通路
- 如果服务器没有启动,那么就会抛出异常
- 如果服务器已经启动,那么就可以进行交互了
public class TcpSocket {
public static void main(String[] args) throws IOException {
//创建客户端对象
Socket socket = new Socket("127.0.0.1", 8888);
//获取网络流对象
OutputStream os = socket.getOutputStream();
//向服务器端发送数据
os.write("你好服务器".getBytes());
//获取网络流对象,读取服务器回写的数据
InputStream is = socket.getInputStream();
//处理
byte[] bytes=new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//释放资源
socket.close();
}
}
1.2 TCP通信的服务器端
TCP通信的服务器端:接收客户端的请求,读取客户端发送的信息,给客户端回写信息
ServerSocket:
- 构造方法
- ServerSocket(int port):向系统申请一个固定的端口号,不然客户端就找不到该服务器了
- 服务器端必须明确一件事情,必须知道是哪个客户端发出的请求,所以可以使用accept方法获取请求的客户端对象Socket
- accept()
- 实现步骤
- 创建服务器对象ServerSocket并和系统要指定的端口号
- 使用ServerSocket中的方法accept获取客户端对象Scoket
- 使用Socket对象中的方法getInputStream(),获取网络字节输入流对象InputStream对象
- 使用网络字节输入流对象InputStream对象中的方法read,读取客户端发送的数据
- 使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
- 使用网络字节输出流OutputStream对象中的方法write,给客户端回写数据
- 释放资源(Scoket,ServerScoket)
public class TcpServer {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象
ServerSocket server = new ServerSocket(8888);
//获取客户端对象
Socket socket = server.accept();
//获取客户端对象的网络字节输入流
InputStream is = socket.getInputStream();
byte[] bytes=new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//获取客户端对象的网络字节输出流
OutputStream os = socket.getOutputStream();
//回写数据
os.write("我已经受到你的数据了".getBytes());
//释放资源
socket.close();
server.close();
}
}
1.3 文件上传的案例
public class TcpSocket {
public static void main(String[] args) throws IOException {
//创建本地字节输入流读取本地文件
FileInputStream fis = new FileInputStream("D:\\IDEA_Project\\Experiment\\experiment\\src\\test\\a.jpg");
//创建客户端Socket对象,获取网络字节输出流
Socket socket = new Socket("127.0.0.1", 8888);
OutputStream os = socket.getOutputStream();
//读取本地的文件,发送给服务器
byte[] bytes=new byte[1024];
int len=0;
while ((len=fis.read(bytes))!=-1){
os.write(bytes,0,len);
}
//创建网络字节输入流,读取服务器发来的信息
InputStream is = socket.getInputStream();
while ((len=is.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
//释放资源
fis.close();
socket.close();
}
}
public class TcpServer {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象
ServerSocket server = new ServerSocket(8888);
//创建本地字节输出流
FileOutputStream fos = new FileOutputStream("C:\\Users\\Julia\\Desktop\\b.jpg");
//获取客户端对象
Socket socket = server.accept();
//通过socket对象获取网络字节输入流读取客户端发来的信息
InputStream is = socket.getInputStream();
int len=0;
byte[] bytes=new byte[1024];
while ((len=is.read(bytes))!=-1){
//将读取到客户端发来的信息写入到服务器端的硬盘上
fos.write(bytes,0,len);
}
//创建网络字节输出流,向客户端回写数据
OutputStream os = socket.getOutputStream();
os.write("上传成功".getBytes());
//释放资源
fos.close();
socket.close();
server.close();
}
}
文件上传案例阻塞问题:
客户端中第一个 while ((len=fis.read(bytes))!=-1),读取本地文件,结束标记是读取到-1结束,但是while循环不会读取到-1,因此就不会把结束标记传给服务器,在服务器的while ((len=is.read(bytes))!=-1)中,永远读取不到结束标记,因此进入阻塞状态,一直循环等待结束标记,后面的回写代码就不会被执行。同样的,在客户端的第二个read中,读取不到服务器的回写数据,进入到阻塞状态。
解决:上传完文件,给服务器写一个结束标志
void shutdownOutput()
socket.shutdownOutput()
文件上传案例优化:
优化文件的命名规则、不让服务器上传完就停止(让服务器一直处于监听状态)、使用多线程来提高效率(有一个客户端要上传,就开启一个多线程)
public class TcpServer {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象
ServerSocket server = new ServerSocket(8888);
//创建本地字节输出流
File file=new File("C:\\Users\\Julia\\Desktop");
if(!file.exists()){ //如果文件不存在就创建
file.mkdirs();
}
String filename=System.currentTimeMillis()+new Random().nextInt(9999)+".jpg";
FileOutputStream fos = new FileOutputStream(file+"\\"+filename);
//让服务器一直处于监听状态,有一个客户端都不关闭
while (true){
//获取客户端对象
Socket socket = server.accept();
//每次有一个客户端要上传文件,就开启一个线程
new Thread(new Runnable() {
@Override
public void run() {
try {
//通过socket对象获取网络字节输入流读取客户端发来的信息
InputStream is = socket.getInputStream();
int len=0;
byte[] bytes=new byte[1024];
while ((len=is.read(bytes))!=-1){
//将读取到客户端发来的信息写入到服务器端的硬盘上
fos.write(bytes,0,len);
}
//创建网络字节输出流,向客户端回写数据
OutputStream os = socket.getOutputStream();
os.write("上传成功".getBytes());
//释放资源
fos.close();
socket.close();
}catch (IOException e){
System.out.println(e);
}
}
}).start();
}
//关闭服务器
//server.close();
}
}
1.4 模拟BS服务器案例
public class TcpServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8080);
//浏览器解析服务器回写的html页面,页面中如果有图片,那么浏览器就会单独开启一个线程,读取图片
//需要让服务器一直处于监听状态,以应对客户端的每一次请求
while (true){
//获取客户端对象
Socket socket = server.accept();
//为了提高效率,每有一个请求,就开启一个线程来处理
new Thread(new Runnable() {
@Override
public void run() {
try {
//获取网络字节输入流
InputStream is = socket.getInputStream();
//把is网络字节输入流转换为字符缓冲输入流
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//读取请求信息的第一行
String line = br.readLine(); //GET /test/web/index.html HTTP/1.1
//获取/test/web/index.html
String[] arr = line.split(" ");
//获取test/web/index.html
String htmlPath = arr[1].substring(1);
//创建一个本地字节输入流,读取要访问的html
FileInputStream fis = new FileInputStream(htmlPath);
//使用网络字节输出流写到网页上
OutputStream os = socket.getOutputStream();
//写入HTTP响应头,固定写法
os.write("HTTP/1.1 200 OK\r\n".getBytes());
os.write("Content-Type:text/html\r\n".getBytes());
//必须要写入空行,否则浏览器不解析
os.write("\r\n".getBytes());
byte[] bytes=new byte[1024];
int len=0;
while ((len=fis.read(bytes))!=-1){
os.write(bytes,0,len);
}
//释放资源
fis.close();
socket.close();
}catch (IOException e){
System.out.println(e);
}
}
}).start();
}
//关闭浏览器
//server.close();
}
}
2、JDBC
概念:Java DataBase Connectivity:Java 数据库连接。Java语言操作数据库
本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
步骤:
- 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
- 注册驱动
- 获取数据库连接对象 Connection
- 定义sql
- 获取执行sql语句的对象 Statement
- 执行sql,接收返回结果
- 处理结果
- 释放资源
1、导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
新建包libs(一般和src放在同一级目录下) -》将mysql-connector-java-5.1.37-bin.jar复制到libs目录下 -》右键点击 Add As Library(将jar包加入到工作项目中)
public class JdbcDemo1 {
public static void main(String[] args) throws Exception {
//1.导入驱动jar包
//2.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db4", "root", "root");
//定义sql语句
String sql="update account set balance=500 where id=1";
//获取执行sql的对象
Statement stmt = conn.createStatement();
//执行sql
int count = stmt.executeUpdate(sql);
//处理结果
System.out.println(count);
//释放资源
stmt.close();
conn.close();
}
}
JDBC的五个对象:
-
DriverManager:驱动管理对象
- 功能
- 注册驱动:告诉程序该使用哪一个驱动jar包。static void registerDriver(Driver driver),但是写代码时用Class.forName(“com.mysql.jdbc.Driver”),因为在com.mysql.jdbc.Driver中存在静态代码块,因此将Class对象加载进来时会自动执行静态代码块中的代码。
- 获取数据库连接:static Connection getConnection(String url,String user,String password)。注意:url为指定连接的路径,语法:jdbc:mysql://ip地址(域名):端口号/数据库名称。如果连接的是本机的mysql服务器,并且mysql服务器默认端口是3306,则url可以简写为jdbc:mysql:///数据库名称
- 功能
-
Connection:数据库连接对象
- 功能:
- 获取执行sql的对象
- Statement createStatement()
- PreparedStatement preparedStatement(String sql)
- 管理事务
- 开启事务:void setAutoCommit(boolean autoCommit),调用该方法,设置参数为false为开启事务
- 提交事务:commit()
- 回滚事务:rollback()
- 功能:
-
Statement:执行静态sql的对象
- 执行sql
- boolean execute(String sql):可以执行任何的sql
- int executeUpdate(String sql):执行DML(insert、update、delete)语句,DDL(create、alter、drop)语句,返回值是影响的行数,可以通过这个影响的行数判断是否执行成功,返回值>0则执行成功。
- ResultSet executeQuery(String sql):执行DQL(select)语句
- 执行sql
-
ResultSet:结果集对象,封装查询结果
- boolean next():游标向下移动一行,判断是否有数据,如果有则返回true,没有则返回false
- getXXX(参数):获取数据,xxx代表数据类型,参数:1、int,代表列的编号,从1开始。如getString(1)表示获取第一列的值 2、String,列的名称
-
PreparedStatement:执行动态sql的对象
insert语句:
优化:无论是否成功,都要释放资源,因此要对异常进行try…catch处理:
public class JdbcDemo1 {
public static void main(String[] args){
Connection conn =null;
Statement stmt =null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/db4", "root", "root");
String sql="insert into account values(null,'王五',3000)";
stmt=conn.createStatement();
int count = stmt.executeUpdate(sql);
System.out.println(count);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
//要避免空指针异常
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
DDL语句:
public class JdbcDemo1 {
public static void main(String[] args){
Connection conn =null;
Statement stmt =null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn=DriverManager.getConnection("jdbc:mysql:///db4", "root", "root");
String sql="create table student (id int,name varchar(20))";
stmt=conn.createStatement();
int count = stmt.executeUpdate(sql);
System.out.println(count);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
ResultSet:
public class JdbcDemo1 {
public static void main(String[] args){
Connection conn =null;
Statement stmt =null;
ResultSet rs=null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn=DriverManager.getConnection("jdbc:mysql:///db4", "root", "root");
String sql="select * from account";
stmt=conn.createStatement();
rs= stmt.executeQuery(sql);
while (rs.next()){
int id = rs.getInt(1);
String name = rs.getString("name");
double balance = rs.getDouble(3);
System.out.println(id+" "+name+" "+balance);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
2.1 JDBC工具类:JDBCUtils
注意:这里的jdbc.properties是配置文件,需要放在src目录下:
/**
* JDBC工具类
*/
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
static {
//读取资源文件获取值
try {
//创建Properties集合类
Properties pro = new Properties();
//获取src路径下文件的方式
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");
String path = res.getPath();
//加载文件
pro.load(new FileReader(path));
//获取数据赋值
url = pro.getProperty("url");
user=pro.getProperty("user");
password=pro.getProperty("password");
driver=pro.getProperty("driver");
//注册驱动
Class.forName(driver);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取连接
* @return 连接对象
*/
public static Connection getConnection() throws SQLException {
//需求:不想传递参数,还得保证工具类的通用性。
//解决方案:配置文件,只需要读取jdbc.properties就可以拿到url和user和password了
//但是文件的读取只需要做一次就可以了,因此把文件读取放到上面的静态代码块
return DriverManager.getConnection(url,user,password);
}
/**
* 释放资源
* @param stmt
* @param conn
*/
public static void close(Statement stmt,Connection conn){
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 释放资源
* @param rs
* @param stmt
* @param conn
*/
public static void close(ResultSet rs,Statement stmt,Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
public class JdbcDemo1 {
public static void main(String[] args){
Connection conn =null;
Statement stmt =null;
ResultSet rs =null;
//注册驱动,获取数据库连接对象
try {
conn = JDBCUtils.getConnection();
//定义sql语句
String sql="select * from account";
//获取执行sql语句的对象
stmt=conn.createStatement();
//执行sql
rs=stmt.executeQuery(sql);
while (rs.next()){
int id = rs.getInt(1);
String name = rs.getString("name");
double balance = rs.getDouble(3);
System.out.println(id+" "+name+" "+balance);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JDBCUtils.close(rs,stmt,conn);
}
}
}
登录案例:
需求:通过键盘录入用户名和密码,判断用户是否成功
步骤:
- 创建数据库表 user
- 连接数据库,判断是否登录成功
CREATE TABLE USER(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(32),
PASSWORD VARCHAR(32)
);`在这里插入代码片`
INSERT INTO USER VALUES(NULL,'Julia','123');
INSERT INTO USER VALUES(NULL,'Tom','234');
public class JdbcDemo1 {
//登录方法
public static boolean login(String username,String password){
if(username==null||password==null){
return false;
}
//连接数据库,判断是否登录成功
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
//注册驱动,获取数据库连接对象
conn = JDBCUtils.getConnection();
//定义SQL
String sql="select * from user where username='"+username+"' and password='"+password+"'";
stmt=conn.createStatement();
rs = stmt.executeQuery(sql);
//判断有没有查询出数据,如果有则成功
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JDBCUtils.close(rs,stmt,conn);
}
return false;
}
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名");
String username = scanner.next();
System.out.println("请输入密码");
String password = scanner.next();
if(login(username,password)){
System.out.println("恭喜你登录成功");
}else {
System.out.println("用户名或密码错误!");
}
}
}
PreparedStatement对象:优化上面的登录案例
Sql注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接,会造成安全性问题
- 输入用户随便,输入密码: a’ or ‘a’ ='a
- sql: select * from user where username=‘sdhsdh’ and password=‘a’ or ‘a’=‘a’
预编译sql:参数使用?作为占位符
public class JdbcDemo1 {
//登录方法
public static boolean login(String username,String password){
if(username==null||password==null){
return false;
}
//连接数据库,判断是否登录成功
Connection conn=null;
PreparedStatement pstmt=null;
ResultSet rs=null;
try {
//注册驱动,获取数据库连接对象
conn = JDBCUtils.getConnection();
//定义SQL
String sql="select * from user where username= ? and password=?";
//获取sql的执行对象
pstmt=conn.prepareStatement(sql);
//给问号赋值
pstmt.setString(1,username);
pstmt.setString(2,password);
//执行sql语句
rs=pstmt.executeQuery();
//判断有没有查询出数据,如果有则成功
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JDBCUtils.close(rs,pstmt,conn);
}
return false;
}
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名");
String username = scanner.next();
System.out.println("请输入密码");
String password = scanner.next();
if(login(username,password)){
System.out.println("恭喜你登录成功");
}else {
System.out.println("用户名或密码错误!");
}
}
}
2.2 JDBC事务管理(转账案例)
事务:一个包含多个步骤的业务操作,如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
使用的是Connection对象来管理事务
操作:
- 开启事务:setAutoCommit(boolean autoCommit),参数为false为开启事务。在执行sql前开启事务
- 提交事务:commit(),当所有的sql都执行完提交事务
- 回滚事务:rollback(),在catch中回滚事务
public class JdbcDemo1 {
public static void main(String[] args){
Connection conn =null;
PreparedStatement pstmt1=null;
PreparedStatement pstmt2=null;
try {
conn= JDBCUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
//定义sql语句 转账
String sql1="update account set balance=balance-? where id=?";
String sql2="update account set balance=balance+? where id=?";
pstmt1=conn.prepareStatement(sql1);
pstmt2=conn.prepareStatement(sql2);
//给问号赋值
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
//执行sql语句
pstmt1.executeUpdate();
pstmt2.executeUpdate();
//提交事务
conn.commit();
} catch (Exception e) {
//不论出现什么异常,都回滚
try {
if(conn!=null)
conn.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
}finally {
//释放资源
JDBCUtils.close(pstmt1,conn);
JDBCUtils.close(pstmt2,null);
}
}
}
2.3 数据库连接池
数据库连接池:
- 概念:其实就是一个容器(集合),存放数据库连接的容器。当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完后,会将连接对象归还给容器
- 好处
- 节约资源
- 用户访问高效
- 实现
- 标准接口:DataSource接口 javax.sql包下的
- 获取连接:getConnection()
- 一般我们不去实现它,由数据库厂商来实现
- C3P0:数据库连接池技术
- Druid:数据库连接池实现技术,由阿里巴巴提供
- 归还连接:如果连接对象是从连接池获取的,那么Connection.close()则不会再关闭连接,而是归还连接
2.3.1 数据库连接池_c3p0
使用步骤:
- 导入jar包(两个) c3p0-0.9.5.2.jar 和mchange-commons-java-0.2.12.jar,不要忘记导入数据库的驱动jar包
- 定义配置文件
- 名称:c3p0.properties 或c3p0-config.xml
- 路径:直接将文件放在src目录下即可
- 创建核心对象 数据库连接池对象 ComboPooledDataSource
- 获取连接:getConnection()
public class C3P0Demo {
public static void main(String[] args) throws Exception {
//创建数据库连接池对象
DataSource ds = new ComboPooledDataSource();
//获取数据库连接对象
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
2.3.2 数据库连接池_druid
步骤:
- 导入jar包 druid-1.0.9.jar
- 定义配置文件
- 是properties形式的
- 可以叫任意名称,可以放在任意目录下
- 加载配置文件,用properties
- 获取数据库连接池对象:通过工厂来获取,DruidDataSourceFactory
- 获取连接:getConnection()
public class DruidDemo {
public static void main(String[] args) throws Exception {
//导入包
//定义配置文件
//加载配置文件
Properties pro = new Properties();
InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//获取连接池对象
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
//获取数据库连接对象
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
2.3.3 Druid_工具类
定义工具类:
- 定义一个类 JDBCUtils
- 提供静态代码块加载配置文件,初始化连接池对象
- 提供方法
- 获取连接方法:通过数据库连接池获取连接
- 释放资源
- 获取连接池的方法
public class JDBCUtils {
private static DataSource ds;
static {
try {
//加载配置文件
Properties pro = new Properties();
pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
//获取ds
ds= DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接对象
* @return 数据库连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 释放资源
* @param stmt
* @param conn
*/
public static void close(Statement stmt,Connection conn){
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close(); //归还连接
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 释放资源
* @param rs
* @param stmt
* @param conn
*/
public static void close(ResultSet rs,Statement stmt, Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 获取连接池的方法
*/
public static DataSource getDataSource(){
return ds;
}
}
druid_工具类测试:
public class DruidDemo {
public static void main(String[] args){
//获取数据库连接对象
Connection conn = null;
PreparedStatement pstmt =null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
//定义sql
String sql="select * from account where balance=?";
//获取执行sql的对象
pstmt = conn.prepareStatement(sql);
//给?赋值
pstmt.setDouble(1,3000);
//执行sql
rs = pstmt.executeQuery();
//遍历结果集
while (rs.next()){
int id = rs.getInt(1);
String name = rs.getString("name");
double balance = rs.getDouble(3);
System.out.println(id+" "+name+" "+balance);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
JDBCUtils.close(rs,pstmt,conn);
}
}
}
2.4 JDBCTemplate
Spring框架对JDBC的简单封装,提供了一个JDBCTemplate对象简化JDBC的开发
步骤:
- 导入jar包(五个)
- 创建JdbcTemplate对象,依赖于数据源DataSource
- JdbcTemplate template=new JdbcTemplated(ds);
- 调用JDBCTemplate的方法来完成CRUD的操作
- update方法:执行DML语句
- queryForMap:查询结果集并封装为map集合,将列名作为key,将值作为value,将这条记录封装为map
- 注意:该方法查询的结果集的长度只能为1
- queryForList:查询结果集并封装为list集合:将每一条记录封装成map,再将map封装成list集合
- query:查询结果集并封装为javaBean对象
- query的参数:RowMapper,一般我们使用BeanPropertyRowMapper实现类,可以完成数据到javaBean的自动封装。new BeanPropertyRowMapper<类型>(类型.class)
- queryForObject:查询结果集并封装为对象。一般用于聚合函数的查询
public class DruidDemo {
public static void main(String[] args){
//创建jdbcTemplate对象
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
//执行方法
String sql="update account set balance =? where id=?";
int count = template.update(sql, 5000, 6);
System.out.println(count);
//不需要再释放连接了,因为他会自动释放资源
}
}
public class DruidDemo {
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
//使用Junit单元测试,可以使方法独立运行
@Test
public void test1(){
//查询id为1的记录并封装为map
String sql="select * from account where id=?";
Map<String, Object> map = template.queryForMap(sql,1);
System.out.println(map); //{id=1, name=zhangsan, balance=10000}
}
@Test
public void test2(){
//查询所有的记录封装为list集合
String sql="select * from account";
List<Map<String, Object>> maps = template.queryForList(sql);
for (Map<String, Object> map : maps) {
System.out.println(map);
}
/**
* 打印结果为:
* {id=1, name=zhangsan, balance=10000}
* {id=2, name=lisi, balance=1500}
* {id=3, name=Lisa, balance=3000}
* {id=4, name=Mary, balance=2000}
* {id=5, name=Mary, balance=2000}
* {id=6, name=王五, balance=5000}
*/
}
@Test
public void test3(){
//查询所有记录,将其封装为javaBean对象并封装到list集合中
String sql="select * from account";
//两个参数,第二个参数是告诉他要封装为什么对象,自己实现封装过程
List<Account> list = template.query(sql, new RowMapper<Account>() {
@Override
public Account mapRow(ResultSet rs, int i) throws SQLException {
Account account=new Account();
int id = rs.getInt("id");
String name = rs.getString("name");
double balance = rs.getDouble("balance");
account.setId(id);
account.setName(name);
account.setBalance(balance);
return account;
}
});
//遍历list集合
for (Account account : list) {
System.out.println(account);
}
}
@Test
public void test4(){
String sql="select * from account";
//第二个参数告诉他要封装为什么对象,并把class类传给他,并且让他自己实现封装
List<Account> list = template.query(sql, new BeanPropertyRowMapper<Account>(Account.class));
//遍历list
for (Account account : list) {
System.out.println(account);
}
}
@Test
public void test5(){
//查询总记录数
String sql="select count(id) from account";
//第2个参数传递希望的返回值结果类型
Long count = template.queryForObject(sql, Long.class);
System.out.println(count);
}
}
3、HTML&CSS
JavaWeb:使用Java语言开发基于互联网的项目
软件架构:
C/S:
- 优点:用户体验好。
- 缺点:开发、安装、部署、维护麻烦
B/S:
- 优点:开发、安装、部署、维护简单
- 缺点:如果应用过大,用户的体验可能受到影响。对硬件要求过高。
- 资源分类
- 静态资源
- 所有用户访问得到的结果一样
- 如:文本,图片,音频,视频,HTML,CSS,JavaScript
- 如果用户访问的是静态资源,那么服务器就会直接将静态资源发送给浏览器,浏览器中内置了静态资源的解析引擎,可以展示静态资源
- 动态资源
- 使用动态网页技术发布的资源
- 所有用户访问得到的结果可能不一样
- 如:jsp/servlet,php,asp
- 如果用户访问的是动态资源,那么服务器就会执行动态资源,转换为静态资源再发送给浏览器
- 静态资源
3.1 HTML
概念:Hyper Text Markup Language 超文本标记语言
基础入门:
- 文件标签:构成html最基本的标签
- html:html文档的根标签
- head:头标签,用于去指定html文档的属性,引入外部资源
- title:标题标签
- body:体标签
- :html5中定义该文档是html文档
- 文本标签:和文本有关的标签
- < h1>–< h6>:标题标签
- < p>:段落标签
- < br>:换行
- < hr>:展示一条水平线:属性:color、width、size、align
- < b>:字体加粗
- < i>:字体斜体
- < font>:字体标签。属性:color、size、face(字体)
- < center>:文本居中。
- 图片标签:< img>展示图片
- 属性:src、align、width、height、alt
- 相对路径:./表示当前目录,当前html文档与图片的相对位置。…/表示上一级目录
- 列表标签:
- 有序列表:ol,li。属性:type:指定具体显示的样子;start:起始的位置
- 无序列表:ul,li。属性:type(disc、square、circle)
- 链接标签:< a>。属性:href:跳转的资源位置。target(_self、_blank)指定打开资源的方式
- 特殊的写法:< a href=“mailto:邮件收信人”>发送邮件< /a>
- 表格标签:
- table,属性:border(边框)、width(表格宽度)、cellpadding(单元格和内容之间的空白)、cellspacing(单元格之间的空白)、bgcolor(表格的背景色)、aligns(表格的对齐方式)
- tr:行 属性:bgcolor(tr的背景色)、aligns(tr的对齐方式,修改里面的文本的对齐方式)
- td:单元格。属性:colspan:合并行。rowspan:合并列
- th:表头的单元格
- < caption>:表格的标题
- < thead>:表示表格的头部分
- < tbody>:表示表格的体部分
- < tfoot>:表示表格的脚部分
- span:文本在一行展示,行内标签,内联标签
- div:每一个div会占满一整行,块级标签
- 语义化标签:< header>、< footer>,没有任何样式,但是有语义化,提高程序的可读性
- 表单标签:form:用于采集用户输入的数据,用于和服务器进行交互。表单中的数据要想被提交,必须指定name属性
- 属性:action:提交数据的url
- method:指定提交方式,一共7种,两种比较常用(get、post)
- get:请求的参数会在地址栏显示(会封装到请求行中)。请求参数的长度是有限制的。不太安全。
- post:请求参数不会在地址栏显示,会在请求体中。请求参数的大小是没有限制的。较为安全。
- 表单项标签
- input:可以通过type属性值改变样式。type属性的取值:text(文本输入框、placeholder给一个框的提示信息)、password(密码输入框)、radio(单选框,默认选中为checked),注意要想让多个单选框实现单选的效果,name属性的值必须一样;一般会给每一个单选框提供value属性,指定被选中后提交的值、checkbox(复选框,也需要提供value值以供提交,默认选中为checked)。label,点击label会让输入框获取焦点。file(文件选择框)。hidden(隐藏域,看不见,但是可以提交一些信息)。submit(提交按钮,提交表单)、button(普通按钮)、image(图片提交按钮,可以提交表单)
- 例子:
<form action="#" method="get">
<label for="name">用户名:</label>
<input type="text" id="name" name="username" placeholder="请输入用户名"><br>
<label for="password">密码:</label>
<input type="password" name="password" placeholder="请输入密码" id="password"><br>
性别:<input type="radio" name="sex" value="male"> 男
<input type="radio" name="sex" value="female"> 女 <br>
爱好:<input type="checkbox" name="aihao" value="swim">游泳
<input type="checkbox" name="aihao" value="java">java
<input type="checkbox" name="aihao" value="sing">唱歌 <br>
上传文件: <input type="file" name="file"> <br>
隐藏域: <input type="hidden" name="hidden" value="aaa"> <br>
色器: <input type="color" name="color"> <br>
生日: <input type="date" name="birth"> <br>
<input type="datetime-local" name="birth"> <br>
邮箱: <input type="email" name="email"> <br>
年龄: <input type="number" name="age"> <br>
<input type="submit" value="提交">
</form>
- select:下拉列表。属性:name
- 列表项:option。属性:value。默认选中:selected
- textarea:文本域。属性:cols(指定列数,每一行有多少个字符)、rows(指定有多少行)、name
创建静态网页项目:
HTML要显示一些特殊字符:
案例:旅游网站的首页:
步骤:
1、使用table来完成布局
2、如果某一行只有一个单元格,则使用< tr>< td>< /td>< /tr>
3、如果一行有多个单元格,则使用表格的嵌套< tr>< td>< table>< /table>< /td>< /tr>
页面效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"> <!--指定字符集是中文-->
<title>黑马旅游网</title>
</head>
<body>
<!--采用table来完成布局-->
<!--最外层的表格,用于整个页面的布局-->
<table align="center" width="100%">
<!--第1行-->
<tr>
<td>
<img src="../image/top_banner.jpg" alt="" width="100%">
</td>
</tr>
<!--第2行-->
<tr>
<td>
<table align="center" width="100%">
<tr>
<td><img src="../image/logo.jpg" alt=""></td>
<td><img src="../image/search.png" alt=""></td>
<td><img src="../image/hotel_tel.png" alt=""></td>
</tr>
</table>
</td>
</tr>
<!--第3行-->
<tr>
<td>
<table align="center" width="100%">
<tr bgcolor="orange" align="center" height="45">
<td><a href="">首页</a></td>
<td><a href="">首页</a></td>
<td><a href="">首页</a></td>
<td><a href="">首页</a></td>
<td><a href="">首页</a></td>
<td><a href="">首页</a></td>
<td><a href="">首页</a></td>
<td><a href="">首页</a></td>
<td><a href="">首页</a></td>
</tr>
</table>
</td>
</tr>
<!--第4行-->
<tr>
<td>
<img src="../image/banner_3.jpg" alt="" width="100%">
</td>
</tr>
<!--第5行-->
<tr>
<td>
<img src="../image/icon_5.jpg" alt="">
<font>黑马精选</font>
<hr color="orange" size="3px">
</td>
</tr>
<!--第6行-->
<tr>
<td>
<table align="center" width="95%">
<tr>
<td>
<img src="../image/jiangxuan_1.jpg" alt="">
<p>上海的哈达阿呆挨打司法打算戴大哥大动感啊大大的</p>
<font color="red">¥998</font>
</td>
<td>
<img src="../image/jiangxuan_1.jpg" alt="">
<p>上海的哈达阿呆挨打司法打算戴大哥大动感啊大大的</p>
<font color="red">¥998</font>
</td>
<td>
<img src="../image/jiangxuan_1.jpg" alt="">
<p>上海的哈达阿呆挨打司法打算戴大哥大动感啊大大的</p>
<font color="red">¥998</font>
</td>
<td>
<img src="../image/jiangxuan_1.jpg" alt="">
<p>上海的哈达阿呆挨打司法打算戴大哥大动感啊大大的</p>
<font color="red">¥998</font>
</td>
</tr>
</table>
</td>
</tr>
<!--第7行-->
<tr>
<td>
<img src="../image/icon_6.jpg" alt="">
<font>国内游</font>
<hr color="orange" size="3px">
</td>
</tr>
<!--第8行-->
<tr>
<td>
<table align="center" width="100%">
<tr>
<td rowspan="2">
<img src="../image/jiangwai_1.jpg" alt="">
</td>
<td>
<img src="../image/jiangxuan_2.jpg" alt="">
<p>hadahdafhdahdasada</p>
<font color="red">¥699</font>
</td>
<td>
<img src="../image/jiangxuan_2.jpg" alt="">
<p>hadahdafhdahdasada</p>
<font color="red">¥699</font>
</td>
<td>
<img src="../image/jiangxuan_2.jpg" alt="">
<p>hadahdafhdahdasada</p>
<font color="red">¥699</font>
</td>
</tr>
<tr>
<td>
<img src="../image/jiangxuan_2.jpg" alt="">
<p>hadahdafhdahdasada</p>
<font color="red">¥699</font>
</td>
<td>
<img src="../image/jiangxuan_2.jpg" alt="">
<p>hadahdafhdahdasada</p>
<font color="red">¥699</font>
</td>
<td>
<img src="../image/jiangxuan_2.jpg" alt="">
<p>hadahdafhdahdasada</p>
<font color="red">¥699</font>
</td>
</tr>
</table>
</td>
</tr>
<!--第9行-->
<tr>
<td>
<img src="../image/footer_service.png" alt="" width="100%">
</td>
</tr>
<!--第10行-->
<tr bgcolor="orange">
<td>
<center>
<font color="#696969" size="3px">江苏传智播客教育科技股份有限公司 <br>
版权所有Copyright 2006-2018, All Rights Reserved 苏ICP备16007882</font>
</center>
</td>
</tr>
</table>
</body>
</html>
案例:注册页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"> <!--指定字符集是中文-->
<title>hello</title>
</head>
<body>
<form action="#" method="post">
<table align="center" border="1">
<tr>
<td>
<label for="name">用户名</label>
</td>
<td>
<input type="text" name="username" id="name" placeholder="请输入账号">
</td>
</tr>
<tr>
<td><label for="password">密码</label></td>
<td>
<input type="password" name="password" id="password" placeholder="请输入密码">
</td>
</tr>
<tr>
<td><label for="email">邮箱</label></td>
<td><input type="email" name="email" id="email" placeholder="请输入email"></td>
</tr>
<tr>
<td><label for="name1">姓名</label></td>
<td><input type="text" name="name1" id="name1" placeholder="请输入真实姓名"></td>
</tr>
<tr>
<td><label for="phone">手机号</label></td>
<td><input type="text" name="phone" id="phone" placeholder="请输入您的手机号"></td>
</tr>
<tr>
<td>性别</td>
<td>
<input type="radio" name="sex" value="male"> 男
<input type="radio" name="sex" value="femal"> 女
</td>
</tr>
<tr>
<td>出生年月</td>
<td><input type="date" name="birth"></td>
</tr>
<tr>
<td>验证码</td>
<td><input type="text" name="code"><img src="../image/verify_code.jpg" alt=""></td>
</tr>
<tr align="center">
<td colspan="2"><input type="submit" value="注册"></td>
</tr>
</table>
</form>
</body>
</html>
3.2 CSS
Cascading Style Sheets:层叠样式表。页面美化和布局控制。
好处:
- 功能强大
- 将内容展示和样式控制相分离,降低耦合度(解耦),让分工协作更容易,提高开发效率
CSS的使用:与html结合
- 内联样式:在标签中使用style属性指定css代码。如:< div style=“color: red”>hello< /div>,作用域只能作用在当前标签里面,这种方式不常用。
- 内部样式:在head标签内定义style标签,style标签的标签体内容就是css代码。如:< style> div{ color: red; } < /style>,作用域只能作用在这一个页面里面
- 外部样式:定义css的资源文件,在head标签内,定义link标签,引入外部的资源文件。在引入的页面都可以生效。
选择器:筛选具有相似特征的元素。
分类:
- 基础选择器:
- id选择器:选择具体id属性值的元素。标识:#
- 元素选择器:选择具有相同标签名称的元素 标识:元素名称
- 类选择器:选择具有相同class属性值的元素 标识: .class属性值
- 扩展选择器
- 一个*号,表示选择所有元素,语法 *{}
- 并集选择器:语法:选择器1,选择器2{}
- 子选择器:语法:选择器1 选择器2{}(筛选选择器1下的选择器2元素)
- 父选择器:语法:选择器1>选择器2{} (筛选选择器2的父元素选择器1)
- 属性选择器:选择元素名称,属性名=属性值的元素。语法:元素名称[属性名=“属性值”]{}
- 伪类选择器:选择一些元素所具有的状态。语法:元素:状态{}
注意事项:每一对属性需要用分号隔开,最后一个不用分号。
属性:
- 字体、文字
- font-size:字体大小
- color:文本颜色
- text-align:对齐方式
- line-height:行高
- 背景
- background:复合属性
- 边框
- border:设置边框,复合属性
- 尺寸
- width:宽度
- height:高度
- 盒子模型:控制布局
- margin:外边距
- padding:内边距
- 默认情况下,内边距会影响整个盒子的大小。可以设置盒子的属性,让width和height就是盒子的固定大小,box-sizing:border-box
- float
- left:左浮动
- right:右浮动
案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"> <!--指定字符集是中文-->
<title>hello</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
background:url("../image/register_bg.png") no-repeat center;
}
.rg_layout{
border: 8px solid black;
width: 900px;
height: 500px;
background-color: #fff;
/*让div水平居中*/
margin: auto;
margin-top: 15px;
}
.rg_left{
float: left;
margin: 15px;
}
.rg_left p:first-child{
font-size: 20px;
color: orange;
}
.rg_left p:last-child{
font-size: 20px;
color: dimgrey;
}
.rg_center{
float: left;
width: 450px;
}
.rg_right{
float: right;
margin: 15px;
}
.rg_right p{
font-size: 10px;
}
.rg_right p a{
color: indianred;
}
.td_left{
text-align: right;
width: 100px;
height: 45px;
}
.td_right{
padding-left: 50px;
}
.text{
width: 251px;
height: 32px;
border:1px solid grey;
padding: 10px;
}
#code{
width: 110px;
height: 32px;
/*设置图片垂直居中*/
vertical-align: middle;
}
#btn{
width: 150px;
height: 40px;
background-color: yellow;
border: 1px solid yellow;
}
</style>
</head>
<body>
<div class="rg_layout">
<div class="rg_left">
<p>新用户注册</p>
<p>USER REGISTER</p>
</div>
<div class="rg_center">
<div class="rg_form">
<form action="#" method="post">
<table>
<tr>
<td class="td_left">
<label for="name">用户名</label>
</td>
<td class="td_right">
<input type="text" name="username" id="name" placeholder="请输入账号" class="text">
</td>
</tr>
<tr>
<td class="td_left"><label for="password">密码</label></td>
<td class="td_right">
<input type="password" name="password" id="password" placeholder="请输入密码" class="text">
</td>
</tr>
<tr>
<td class="td_left"><label for="email">邮箱</label></td>
<td class="td_right"><input type="email" name="email" id="email" placeholder="请输入email" class="text"></td>
</tr>
<tr>
<td class="td_left"><label for="name1">姓名</label></td>
<td class="td_right"><input type="text" name="name1" id="name1" placeholder="请输入真实姓名" class="text"></td>
</tr>
<tr>
<td class="td_left"><label for="phone">手机号</label></td>
<td class="td_right"><input type="text" name="phone" id="phone" placeholder="请输入您的手机号" class="text"></td>
</tr>
<tr>
<td class="td_left">性别</td>
<td class="td_right">
<input type="radio" name="sex" value="male"> 男
<input type="radio" name="sex" value="femal"> 女
</td>
</tr>
<tr>
<td class="td_left">出生年月</td>
<td class="td_right"><input type="date" name="birth"></td>
</tr>
<tr>
<td class="td_left">验证码</td>
<td class="td_right"><input type="text" name="code"><img src="../image/verify_code.jpg" alt="" id="code"></td>
</tr>
<tr align="center">
<td colspan="2"><input type="submit" value="注册" id="btn"></td>
</tr>
</table>
</form>
</div>
</div>
<div class="rg_right">
<p>已有账号?<a href="#">立即登录</a></p>
</div>
</div>
</body>
</html>
4、JavaScript
一门客户端脚本语言,运行在客户端浏览器中的。每一个浏览器都有JavaScript的解析引擎。
脚本语言:不需要进行编译,直接就可以被浏览器解析执行。
功能:
- 可以增强用户和页面的交互,可以控制html元素,使得页面有一些动态效果,增强用户体验。
JavaScript=ECMAScript+JavaScript自己特有的东西(BOM+DOM)
基本语法:
内部js:定义script标签,标签体内容就是js代码
外部js:定义script标签,通过src属性引入外部的js文件
注意:script可以定义在html页面的任何地方,但是定义位置会影响执行顺序;可以定义多个script标签
原始数据类型:
- number:数字。整数/小数/NaN(一个不是数字的数字类型)
- string:字符串。字符/字符串
- boolean:true/false
- null:一个对象为空的占位符
- undefined:未定义。如果一个变量没有给初始化值,则会默认为undefined
变量定义的语法:var 变量名=初始化值。要知道变量是什么类型的,用typeof方法。特殊:null运算后得到的是object
其他类型转number:
注意:正负号
在JS中,如果运算数并不是运算符所要求的数据类型,引擎会自动的将运算数进行类型转换。
- 其他类型转number
- string转number:根据字面值转换,如果字面值转换不了数字,则转为NAN(不是数字的数字)
- boolean转number:true转为1,false转为number
<script>
var a= +"string";
a++;
document.write(typeof(a)); //number
document.write(a); //NAN
var flag1=+ true;
var flag2=+ false;
document.write(typeof(flag1));//number
document.write(flag1+1); //2
document.write(flag2+1); //1
</script>
比较运算:
- 类型相同,直接比较(根据字典逐一按位比较)
- 类型不同,先进行类型转换,再比较
其他类型转boolean:
- number:0或NAN为假,其他为真
- string:除了空字符串为假,其他都是true
- null和undefined:都是false
- 对象:所有对象都为true
<script>
//number
var num =3;
document.write(!!num); //true
var num2=0;
document.write(!!num2); //false
var num3=NaN;
document.write(!!num3); //false
//string
var str1="hello";
document.write(!!str1); //true
var str2="";
document.write(!!str2); //false
//null&undefined
var a=null;
document.write(!!a); //false
var b=undefined;
document.write(!!b); //false
//对象
var date=new Date();
document.write(!!date); //true
</script>
案例:九九乘法表:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"> <!--指定字符集是中文-->
<title>hello</title>
<style>
td{
border: 1px solid black;
}
</style>
<script>
document.write("<table align='center'>");
document.write("<caption align='center'>"+"九九乘法表"+"</caption>>");
for(var i=1;i<=9;i++){
document.write("<tr>");
for(var j=1;j<=i;j++){
document.write("<td>");
document.write(i+"*"+j+"="+(i*j)+"  ");
document.write("</td>");
}
document.write("</tr>");
}
document.write("</table>")
</script>
</head>
<body>
</body>
</html>
4.1 JavaScript对象
Date日期对象:
<script>
var date=new Date();
document.write(date+"<br>");
//返回本地字符串时间格式
document.write(date.toLocaleString());
//返回毫秒值
document.write(date.getTime());
</script>
Function函数对象:
- 创建
- var fun=new Function(形式参数列表,方法体)——不常用
- function 方法名称(形式参数列表){方法体}——不用写形参类型
- var 方法名=function(形式参数列表){方法体}
- 调用:方法名称(形式参数列表)
- 特点:
- 在方法中声明了一个隐藏的内置对象(数组),arguments,封装了所有的实际参数
- 属性
- length:形参的个数
//求任意个数的和
function add() {
var sum=0;
for(var i =0;i<arguments.length;i++){
sum+=arguments[i];
}
return sum;
}
var res=add(1,2,3);
alert(res);
Array数组对象:
- 创建
- var arr=new Array(元素列表)
- var arr=new Array(默认长度)
- var arr=[元素列表]
- 属性
- length:数组的长度
- 方法
- join(参数):将数组中的元素按照指定的分隔符拼接为字符串(默认按逗号分隔)
- push:添加元素
- 特点
- 元素类型可变
- 数组的长度是可变的
Math数学对象:
- 创建
- 不用创建,直接使用
- 方法
- random:返回0-1之间的随机数(含0不含1)
- ceil:向上取整
- round:四舍五入
- floor:向下取整
- 属性:PI
//随机产生1-100之间的整数
var num=Math.floor(Math.random()*100)+1;
document.write(num)
RegExp正则表达式对象:
正则表达式:定义字符串的组成规则
- 单个字符:[]
- 如:[a] (表示只有一个字符a)、[ab] (表示只有一个字符a或b)、[a-zA-Z0-9_]
- 特殊符号代表特殊含义的单个字符
- \d:单个数字字符 [0-9]
- \w:单个单词字符 [a-zA-Z0-9_]
- 量词符号
- *(出现0次或多次)、?(出现0次或1次)、+(出现1次或多次)、{m,n}(表示 m<=次数<=n,注意,如果m缺省,表示至多出现n次;如果n缺省,表示最少m次)
- 开始结束符号
- ^开始
- $结束
正则表达式对象:
- 创建
- var reg=new RegExp(“正则表达式”)
- var reg=/正则表达式/
- 方法
- test:验证指定字符串是否符合正则定义的规范
var reg1=new RegExp("^\\w{6,12}$");
var reg2=/^\w{6,12}$/;
var flag=reg2.test("zhangsan");
alert(flag);
Global对象:
- 特点:全局对象,这个Global中封装的方法不需要对象就可以直接调用
- 方法
- encodeURI():url编码
- decodeURI():url解码
- encodeURIComponent():url编码,编码的字符更多
- decodeURIComponent():url解码,解码的字符更多
- parseInt():将字符串转数字——逐一判断每一个字符是否是数字,将前面数字部分转化成number
- isNaN():判断一个值是不是NaN
- eval():将JavaScript的字符串转换成JavaScript的代码执行
4.2 BOM对象
概念:Browser Object Model 浏览器对象模型
- 将浏览器的各个组成部分封装成对象
组成: - Window:窗口对象
- Navigator:浏览器对象
- Screen:显示器屏幕
- History:历史记录对象
- Location:地址栏对象
4.2.1 Window:窗口对象
- 方法:
- 与弹出框有关的方法
- alert():警告框
- confirm():确认取消框。若用户点击确定按钮,则方法返回true,若用户点击取消,方法返回false
- prompt():显示可提示用户输入的对话框。返回值是获取用户输入的值。
- 与打开关闭有关的方法
- close():关闭浏览器窗口(谁调用我,我关谁)。
- open():打开一个新的浏览器窗口,可以传递打开窗口的url。方法返回一个新的window对象
- 与定时器有关的方法
- setTimeout():一次性定时器。参数:js代码或方法对象;毫秒值。返回定时器唯一标识,用来取消定时器时使用
- clearTimeOut():取消定时器。参数传递定时器对象id
- setInterval():循环定时器
- clearInterval():取消循环定时器
- 与弹出框有关的方法
- 特点:
- Window不需要创建可以直接使用。window.方法名()
- window引用可以省略,方法名()
- 属性
- 获取其他BOM对象,location,history,Screen,Navigator
- 获取dom对象。document
案例1:轮播图
<img src="../image/banner_1.jpg" width="100%" id="img">
<script>
//修改图片src的方法
var num=1;
function fun() {
num++;
//判断number是否大于3
if(num>3){
num=1;
}
var img=document.getElementById("img");
img.src="../image/banner_"+num+".jpg";
}
//定义定时器
setInterval(fun,3000);
</script>
4.2.2 Location:地址栏对象
- 创建:window.location/location
- 方法
- reload():重新加载当前文档
- href():设置或返回完整的URL
案例2:自动跳转首页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
<style>
#time{
color: red;
}
p{
text-align: center;
}
</style>
</head>
<body>
<p> <span id="time">5</span>秒之后,自动跳转到首页...</p>
<script>
var num=5;
var time = document.getElementById("time");
function fun() {
num--;
if(num==0){
//跳转
location.href="http://www.baidu.com";
}
time.innerText=num;
}
setInterval(fun,1000);
</script>
</body>
</html>
4.2.3 History:历史记录对象
- 创建 window.history/history
- 方法
- back():加载history列表中的前一个URL
- forward():加载history列表中的后一个URL
- go():可以前进也可以后退
- 属性
- length:返回当前浏览器历史列表中的URL数量
4.3 DOM对象
DOM对象模型:Document Object Model 文档对象模型
将标记语言文档的各个组成部分,封装为对象,可以使用这些对象,对标记语言文档进行CRUD动态操作。
核心DOM模型:
- Document:文档对象
- 方法
- 获取element对象:getElementById()、getElementsByTagName()、getElementsByClassName()、
- 创建其他dom对象:createAttribute(name)、createComment()、createElement()、createTextNode()
- Element:元素对象
- 获取/创建:通过document来获取和创建
- 方法:removeAttribute()删除属性、setAttribute()设置属性
- Node:节点对象,其他5个的父对象
- 特点:所有dom对象都可以被认为成一个节点
- 方法:CRUDdom树的方法
- appendChild():向节点的子节点列表结尾添加新的子节点
- removeChild():删除(并返回)当前节点指定的子节点
- replaceChild():用新的节点替换子节点
- 属性:parentNode:返回当前节点的父节点
超链接的功能:
1、可以被点击,样式
2、点击后跳转到href指定的url
需求:保留1功能,去掉2功能。实现:href=“javascript:void(0);”
案例3 动态表格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
<style>
div{
text-align: center;
margin: 50px;
}
table{
width: 500px;
border: 1px solid black;
margin: auto;
}
tr,td,th{
border: 1px solid black;
text-align: center;
}
</style>
</head>
<body>
<div>
<input type="text" name="id" placeholder="请输入编号" id="id">
<input type="text" name="name" placeholder="请输入姓名" id="name">
<input type="text" name="sex" placeholder="请输入性别" id="sex">
<input type="button" value="添加" id="add">
</div>
<table id="table">
<caption>学生信息表</caption>
<tr>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>操作</th>
</tr>
<tr>
<td>1</td>
<td>令狐冲</td>
<td>男</td>
<td><a href="javascript:void(0)" onclick="del_row(this)">删除</a></td>
</tr>
<tr>
<td>2</td>
<td>任我行</td>
<td>男</td>
<td><a href="javascript:void(0)" onclick="del_row(this)">删除</a></td>
</tr>
<tr>
<td>3</td>
<td>岳不群</td>
<td>?</td>
<td><a href="javascript:void(0)" onclick="del_row(this)">删除</a></td>
</tr>
</table>
<script>
//添加
var add = document.getElementById(`add`);
add.onclick=function () {
//获取文本框中值
var id = document.getElementById("id").value;
var name = document.getElementById("name").value;
var sex = document.getElementById("sex").value;
//创建td,将文本框中的内容放进去
var td1 = document.createElement("td");
td1.innerText=id;
var td2 = document.createElement("td");
td2.innerText=name;
var td3 = document.createElement("td");
td3.innerText=sex;
var td4 = document.createElement("td");
var a = document.createElement("a");
a.innerText="删除";
a.setAttribute("href","javascript:void(0);");
a.setAttribute("onclick","del_row(this)");
td4.appendChild(a);
//创建tr,将td放进去
var tr = document.createElement("tr");
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
tr.appendChild(td4);
//将tr放进table中
document.getElementById("table").appendChild(tr);
};
//删除
function del_row(obj) {
//此时obj为点的a对象
//若要删除这一行tr,那么需要获取到table
var table = obj.parentNode.parentNode.parentNode;
table.removeChild(obj.parentNode.parentNode);
}
</script>
</body>
</html>
HTML DOM模型:
- 标签体的设置和获取:innerHTML
- 使用html元素对象的属性
- 设置样式
- 使用元素的style属性来设置:如div1.style.border=“1px solid black”
- 提前定义好类选择器样式,通过元素的className属性来设置其class属性值
4.4 事件
事件:某些操作:如:单击、双击、键盘按下、鼠标移动
事件源:组件。如:按钮,文本输入框…
监听器:代码。
注册监听:将事件源和事件,监听器结合在一起。当事件源上发生了某个事件。则触发执行某个监听器代码。
常见的事件:
- 点击事件
- onclick():单击事件
- ondblclick():双击事件
- 焦点事件
- onblur():失去焦点。一般用于表单校验
- onfocus():获得焦点
- 加载事件 onload()
- 鼠标事件
- onmousemove 鼠标被移动
- onmouseout 鼠标从某元素移开
- onmouseover 鼠标移到某元素之上
- onmousedown 鼠标被按下
- 定义方法时,定义一个形参,接受event对象
- event对象的button属性可以鼠标那个键被点击了
- onmouseup 鼠标被松开
- 键盘事件
- onkeydown 键盘某个按键被按下
- event对象的keyCode属性可以知道键盘按下哪个键
- onkeyup 某个按键被松开
- onkeypress 键盘按下并松开
- onkeydown 键盘某个按键被按下
- 选中和改变
- onchange 域的内容被改变
- onselect 文本被选中
- 表单事件
- onsubmit 表单提交,可以阻止表单提交。方法返回false则表单提交被阻止
- onreset
案例4 表格全选
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
<style>
table{
margin: auto;
width: 500px;
border: 1px solid black;
}
tr,td,th{
border: 1px solid black;
text-align: center;
}
div{
text-align: center;
margin-top: 10px;
}
</style>
</head>
<body>
<table>
<caption>学生信息表</caption>
<tr>
<th><input type="checkbox" name="checkbox" id="cb"></th>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>操作</th>
</tr>
<tr>
<td><input type="checkbox" name="checkbox"></td>
<td>1</td>
<td>令狐冲</td>
<td>男</td>
<td><a href="javascript:void(0)">删除</a></td>
</tr>
<tr>
<td><input type="checkbox" name="checkbox"></td>
<td>2</td>
<td>任我行</td>
<td>男</td>
<td><a href="javascript:void(0)">删除</a></td>
</tr>
<tr>
<td><input type="checkbox" name="checkbox"></td>
<td>3</td>
<td>岳不群</td>
<td>男</td>
<td><a href="javascript:void(0)">删除</a></td>
</tr>
</table>
<div>
<input type="button" value="全选" id="all">
<input type="button" value="全不选" id="notall">
<input type="button" value="反选" id="rev">
</div>
<script>
var all = document.getElementById("all");
var notall = document.getElementById("notall");
var rev = document.getElementById("rev");
var checkboxs = document.getElementsByName("checkbox");
//点击全选
all.onclick=function () {
//获取所有的checkbox都选上
for(var i=0;i<checkboxs.length;i++){
checkboxs[i].checked=true;
}
};
//点击全不选
notall.onclick=function () {
//将所有checkbox都不选
for(var i=0;i<checkboxs.length;i++){
checkboxs[i].checked=false;
}
};
//点击反选
rev.onclick=function () {
//将所有的已经选的变成不选,不选的变成选
for(var i =0;i<checkboxs.length;i++){
if(checkboxs[i].checked){
checkboxs[i].checked=false;
}else{
checkboxs[i].checked=true;
}
}
};
//点击了第一个checkbox后让下面所有的checkbox都与他的状态相等
var cb = document.getElementById("cb");
cb.onclick=function () {
for(var i=1;i<checkboxs.length;i++){
checkboxs[i].checked=this.checked;
}
};
var trs = document.getElementsByTagName("tr");
for(var i=0;i<trs.length;i++){
trs[i].onmouseover=function () {
this.style.backgroundColor="pink";
};
trs[i].onmouseout=function () {
this.style.backgroundColor="white";
}
}
</script>
</body>
</html>
案例5 表单检验
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"> <!--指定字符集是中文-->
<title>hello</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
background:url("../image/register_bg.png") no-repeat center;
}
.rg_layout{
border: 8px solid black;
width: 900px;
height: 500px;
background-color: #fff;
/*让div水平居中*/
margin: auto;
margin-top: 15px;
}
.rg_left{
float: left;
margin: 15px;
}
.rg_left p:first-child{
font-size: 20px;
color: orange;
}
.rg_left p:last-child{
font-size: 20px;
color: dimgrey;
}
.rg_center{
float: left;
width: 450px;
}
.rg_right{
float: right;
margin: 15px;
}
.rg_right p{
font-size: 10px;
}
.rg_right p a{
color: indianred;
}
.td_left{
text-align: right;
width: 100px;
height: 45px;
}
.td_right{
padding-left: 50px;
}
.text{
width: 251px;
height: 32px;
border:1px solid grey;
padding: 10px;
}
#code{
width: 110px;
height: 32px;
/*设置图片垂直居中*/
vertical-align: middle;
}
#btn{
width: 150px;
height: 40px;
background-color: yellow;
border: 1px solid yellow;
}
.error{
color: red;
font-size: 12px;
}
</style>
</head>
<body>
<div class="rg_layout">
<div class="rg_left">
<p>新用户注册</p>
<p>USER REGISTER</p>
</div>
<div class="rg_center">
<div class="rg_form">
<form action="#" method="get" id="form">
<table>
<tr>
<td class="td_left">
<label for="name">用户名</label>
</td>
<td class="td_right">
<input type="text" name="username" id="name" placeholder="请输入用户名" class="text">
<span id="s_username" class="error"></span>
</td>
</tr>
<tr>
<td class="td_left"><label for="password">密码</label></td>
<td class="td_right">
<input type="password" name="password" id="password" placeholder="请输入密码" class="text">
<span id="s_password" class="error"></span>
</td>
</tr>
<tr>
<td class="td_left"><label for="email">邮箱</label></td>
<td class="td_right"><input type="email" name="email" id="email" placeholder="请输入email" class="text"></td>
</tr>
<tr>
<td class="td_left"><label for="name1">姓名</label></td>
<td class="td_right"><input type="text" name="name1" id="name1" placeholder="请输入真实姓名" class="text"></td>
</tr>
<tr>
<td class="td_left"><label for="phone">手机号</label></td>
<td class="td_right"><input type="text" name="phone" id="phone" placeholder="请输入您的手机号" class="text"></td>
</tr>
<tr>
<td class="td_left">性别</td>
<td class="td_right">
<input type="radio" name="sex" value="male"> 男
<input type="radio" name="sex" value="femal"> 女
</td>
</tr>
<tr>
<td class="td_left">出生年月</td>
<td class="td_right"><input type="date" name="birth"></td>
</tr>
<tr>
<td class="td_left">验证码</td>
<td class="td_right"><input type="text" name="code"><img src="../image/verify_code.jpg" alt="" id="code"></td>
</tr>
<tr align="center">
<td colspan="2"><input type="submit" value="注册" id="btn"></td>
</tr>
</table>
</form>
</div>
</div>
<div class="rg_right">
<p>已有账号?<a href="#">立即登录</a></p>
</div>
</div>
<script>
//给表单绑定onsubmit事件,监听器中监听每一个校验结果
//定义一些方法分别校验各个表单项
//校验用户名
function checkUsername(){
//正则表达式
var name=document.getElementById("name").value;
//var reg=new RegExp("\\w{6,12}");
var reg=/^\w{6,12}$/;
var flag=reg.test(name);
var username = document.getElementById("s_username");
if(flag){
//提示绿色的对勾
username.innerHTML="<img width='35px' height='25px' src='../image/gou.png'>";
}else {
//提示红色的用户名有误
username.innerText="用户名输入有误";
}
return flag;
}
//校验密码
function checkPassword(){
var password=document.getElementById("password").value;
var reg=/^\w{6,12}$/;
var flag=reg.test(password);
var password2 = document.getElementById("s_password");
if(flag){
//提示绿色的对勾
password2.innerHTML="<img width='35px' height='25px' src='../image/gou.png'>";
}else {
password2.innerText="密码格式有误";
}
return flag;
}
document.getElementById("form").onclick=function () {
//调用用户校验方法
//调用密码校验方法
return checkUsername() && checkPassword();
};
//给用户名和密码框绑定离焦事件
document.getElementById("name").onblur=checkUsername;
document.getElementById("password").onblur=checkPassword;
</script>
</body>
</html>
5、Bootstrap
Bootstrap:一个前端开发的框架
Bootstrap中文网
快速入门:
- 下载bootstrap
- 在项目中将这三个文件夹复制,还要记得引入jquery-3.2.1.min.js
- 创建一个HTML页面,引入必要的资源文件
基本摸版:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap Template</title>
<!-- Bootstrap -->
<link href="../css/bootstrap.min.css" rel="stylesheet">
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="../js/jquery-3.2.1.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="../js/bootstrap.min.js"></script>
</head>
<body>
<h1>你好,世界!</h1>
</body>
</html>
5.1 Bootstrap_栅格系统
响应式布局:依赖于栅格系统,将一行平均分成12个格子,可以指定一个元素占几个格子。
步骤:
- 定义容器:相当于table
- 容器的分类:container(有留白)/container-fluid(100%的宽度)
- 定义行:相当于tr。样式:row
- 定义元素,指定该元素在不同设备上所占的格子数。样式:col-设备代号-格子数目
- 设备代号
- xs:相当于手机 例如:col-xs-12
- sm:相当于pad
- md:中等屏幕,相当于笔记本电脑桌面
- lg:大屏幕,大桌面显示器
- 设备代号
注意:如果超出12,会自动换行。栅格类属性可以向上兼容。如果真实设备宽度小于了设置栅格类属性的设备代号代码的最小值,默认会一个元素占满一整行。
全局CSS样式
- 按钮:class=“btn btn-default”
- 图片:class=“img-responsive”(图片在任意设备都占100%)、图片形状:class=“img-rounded”、class=“img-circle”、class=“img-thumbnail”
- 表格:class=“table table-bordered table-hover”
- 表单:给表单项添加form-control、给form加class=“form-horizontal”
组件:
- 导航条:class=“navbar navbar-inverse”、class=“navbar navbar-default”
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<!--定义汉堡按钮-->
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<!--定义汉堡按钮中的线的条数-->
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">首页</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
<li><a href="#">Link</a></li>
<!--定义下拉列表-->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
<!--定义搜索框-->
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
- 分页条:
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
- JS插件:轮播图(Carousel)
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
<li data-target="#carousel-example-generic" data-slide-to="1"></li>
<li data-target="#carousel-example-generic" data-slide-to="2"></li>
</ol>
<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="..." alt="...">
</div>
<div class="item">
<img src="..." alt="...">
</div>
</div>
<!-- Controls -->
<a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
案例:旅游网:利用栅格系统来布局
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap Template</title>
<!-- Bootstrap -->
<link href="../css/bootstrap.min.css" rel="stylesheet">
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="../js/jquery-3.2.1.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="../js/bootstrap.min.js"></script>
<style>
.margintop{
margin-top: 10px;
}
.search-input{
float: left;
border: 2px solid #ffc900;
width: 400px;
height: 35px;
padding-left: 5px;
margin-top: 15px;
}
.search-btn{
float: left;
height: 35px;
border: 2px solid #ffc900;
width: 90px;
background-color: #ffc900;
text-align: center;
line-height: 35px;
margin-top: 15px;
}
.bottomline{
border-bottom: 2px solid #ffc900;
padding: 5px;
}
</style>
</head>
<body>
<!--页眉部分-->
<header class="container-fluid">
<!--分成四行-->
<div class="row">
<img src="../image/top_banner.jpg" class="img-responsive">
</div>
<div class="row margintop">
<div class="col-md-3"><img src="../image/logo.jpg" class="img-responsive"></div>
<div class="col-md-5">
<input type="text" placeholder="请输入线路名称" class="search-input">
<a href="javascript:void(0)" class="search-btn">搜索</a>
</div>
<div class="col-md-4"><img src="../image/hotel_tel.png"></div>
</div>
<div class="row">
<!--导航栏-->
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<!--定义汉堡按钮-->
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<!--定义汉堡按钮中的线的条数-->
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">首页</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
</div>
<div class="row">
<!--轮播图-->
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
<li data-target="#carousel-example-generic" data-slide-to="1"></li>
<li data-target="#carousel-example-generic" data-slide-to="2"></li>
</ol>
<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="../image/banner_1.jpg" alt="...">
</div>
<div class="item">
<img src="../image/banner_2.jpg" alt="...">
</div>
<div class="item">
<img src="../image/banner_3.jpg" alt="...">
</div>
</div>
<!-- Controls -->
<a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
</div>
</header>
<!--主体部分-->
<div class="container margintop">
<div class="row bottomline">
<img src="../image/icon_5.jpg">
<span>黑马精选</span>
</div>
<div class="row margintop">
<div class="col-md-3">
<div class="thumbnail">
<img src="../image/jiangxuan_3.jpg">
<p>上海飞三亚4晚自由行(春节销售+亲子游+自由行)</p>
<font color="red">¥699</font>
</div>
</div>
<div class="col-md-3">
<div class="thumbnail">
<img src="../image/jiangxuan_3.jpg">
<p>上海飞三亚4晚自由行(春节销售+亲子游+自由行)</p>
<font color="red">¥699</font>
</div>
</div>
<div class="col-md-3">
<div class="thumbnail">
<img src="../image/jiangxuan_3.jpg">
<p>上海飞三亚4晚自由行(春节销售+亲子游+自由行)</p>
<font color="red">¥699</font>
</div>
</div>
<div class="col-md-3">
<div class="thumbnail">
<img src="../image/jiangxuan_3.jpg">
<p>上海飞三亚4晚自由行(春节销售+亲子游+自由行)</p>
<font color="red">¥699</font>
</div>
</div>
</div>
<div class="row bottomline">
<img src="../image/icon_6.jpg">
<span>国内游</span>
</div>
<div class="row margintop">
<div class="col-md-4">
<img src="../image/guonei_1.jpg" class="img-responsive">
</div>
<div class="col-md-8">
<div class="row">
<div class="col-md-4">
<div class="thumbnail">
<img src="../image/jiangxuan_3.jpg">
<p>上海飞三亚4晚自由dasfaasfafafaf行(春节销售+亲子游+自由行)</p>
<font color="red">¥699</font>
</div>
</div>
<div class="col-md-4">
<div class="thumbnail">
<img src="../image/jiangxuan_3.jpg">
<p>上海飞三亚4晚自由fafafafafafasfafasf行(春节销售+亲子游+自由行)</p>
<font color="red">¥699</font>
</div>
</div>
<div class="col-md-4">
<div class="thumbnail">
<img src="../image/jiangxuan_3.jpg">
<p>上海飞三亚4晚自由行(春节fafafasfafafasfa销售+亲子游+自由行)</p>
<font color="red">¥699</font>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="thumbnail">
<img src="../image/jiangxuan_3.jpg">
<p>上海飞三亚4晚自由行(春节fasfasfasfasfasfa销售+亲子游+自由行)</p>
<font color="red">¥699</font>
</div>
</div>
<div class="col-md-4">
<div class="thumbnail">
<img src="../image/jiangxuan_3.jpg">
<p>上海飞三亚4晚自由行(春节fafafafafafafas销售+亲子游+自由行)</p>
<font color="red">¥699</font>
</div>
</div>
<div class="col-md-4">
<div class="thumbnail">
<img src="../image/jiangxuan_3.jpg">
<p>上海飞三亚4晚自由行(春节fasffsdfsfafafafafa销售+亲子游+自由行)</p>
<font color="red">¥699</font>
</div>
</div>
</div>
</div>
</div>
</div>
<!--页脚部分-->
<footer class="container-fluid">
<div class="row">
<img src="../image/footer_service.png" class="img-responsive">
</div>
<div class="row" style="background-color: #ffc900">
<center>
<font color="#696969" size="3px">江苏传智播客教育科技股份有限公司 <br>
版权所有Copyright 2006-2018, All Rights Reserved 苏ICP备16007882</font>
</center>
</div>
</footer>
</body>
</html>
6、XML
XML:可扩展标记语言
6.1 XML基础
功能:存储数据(配置文件)、在网络中传输
xml与html的区别:
- xml标签都是自定义的,html的标签是预定义的
- xml语法严格,html语法松散
- xml是存储数据的,html是展示数据的
xml文档基本语法:
- 文档声明 <?xml 属性列表 ?>
- version:版本号
- encoding:编码方式。告知解析引擎当前文档使用的字符集。默认值:ISO- 8859-1
- standalone:是否独立(yes/no),依赖于其他文件或不依赖其他文件
- CDATA区的内容会被原样展示
- 格式:<!CDATA[数据]>
<?xml version='1.0' encoding='gbk' ?>
<users>
<user id='1'>
<name>zhangsaan</name>
<age>21</age>
<gender>male</gender>
</user>
<user id='2'>
<name>lisi</name>
<age>20</age>
<gender>male</gender>
</user>
</users>
6.2 XML约束
约束:规定xml的书写规则
分类:
- DTD:一种简单的约束技术
- Schema:一种复杂的约束技术
引入:
DTD:
- 引入dtd文档到xml文档中
- 内部dtd:将约束规则定义在xml文档中
- 外部dtd:将约束的规则定义在外部的dtd文件中
- 本地:< !DOCTYPE 根标签名 SYSTEM “dtd文件的位置”>
- 网络:< !DOCTYPE 根标签名 PUBLIC “dtd文件位置URL”>
6.3 XML解析
解析:操作xml文档,将文档中的数据读取到内存中
解析XML的方式:
- DOM:将文档一次性加载进内存,形成一棵DOM树
- 优点:操作方便,可以对文档进行CRUD所有操作
- 缺点:占内存
- SAX:逐行读取,基于事件驱动的
- 优点:不占内存。
- 缺点:只能读取。
xml常见解析器:
- JASP:sum公司提供的解析器,支持DOM和SAX两种思想
- DOM4J:一款优秀的解析器,是基于DOM解析
- Jsoup:方便
- PULL:安卓操作系统内置解析器,SAX方式的
Jsoup:
步骤:
- 导入jar包 jsoup-1.11.2.jar
- 获取Document对象
- 获取对应的标签Element对象
- 获取数据
Jsoup快速入门:
student.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<students>
<student number="heima_0001">
<name>tom</name>
<age>18</age>
<sex>male</sex>
</student>
<student number="heima_0002">
<name>jack</name>
<age>18</age>
<sex>female</sex>
</student>
</students>
package jsoup;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.File;
import java.io.IOException;
public class JsoupDemo1 {
public static void main(String[] args) throws IOException {
//获取Document对象,根据xml文档获得
//获取student.xml的路径
String path = JsoupDemo1.class.getClassLoader().getResource("student.xml").getPath();
//加载文档进内存
Document document = Jsoup.parse(new File(path), "utf-8");
//获取元素对象
Elements elements = document.getElementsByTag("name");
//获取第一个name的Element对象
Element element = elements.get(0);
//获取数据
String name = element.text();
System.out.println(name);
}
}
对象的使用:
- Jsoup:工具类,可以解析html或xml文档,返回Document
- parse(File in,String charsetName):解析xml或html文件的
- parse(String html):解析xml或html字符串的
- parse(URL url,int timeoutMillis):通过网络路径获取指定的html或xml文档对象
- Document:文档对象,代表内存中的dom树
- 获取Element对象
- getElementsByTag(String tagName)根据标签名称获取元素对象集合
- getElementsByAttribute(String key):根据属性名称获取元素对象集合
- getElementsByAttributeValue(String key,String value):根据对应的属性名和属性值获取元素对象集合
- 获取Element对象
- Elements:元素Element对象的集合,可以当做ArrayList< Element>来使用
- Element:元素对象
- 获取子元素对象
- getElementsByTag(String tagName)根据标签名称获取元素对象集合
- getElementsByAttribute(String key):根据属性名称获取元素对象集合
- getElementsByAttributeValue(String key,String value):根据对应的属性名和属性值获取元素对象集合
- 获取属性值:String attr(String key):根据属性名称获取属性值
- 获取文本内容:
- String text():获取文本内容
- String html():获取标签体的所有内容
- 获取子元素对象
- Node:节点对象,是Document和Element的父类
快捷的查询方式:
- Selector(根据选择器查询):document.select("#itcast")、document.select(“student[number=‘1’]”);document.select(“student[number=‘1’] > age”);
- Xpath
- 使用Xpath需要导入jar包 JsoupXpath-0.3.2.jar
public class JsoupDemo1 {
public static void main(String[] args) throws XpathSyntaxErrorException, IOException {
//获取Document对象,根据xml文档获得
//获取student.xml的路径
String path = JsoupDemo1.class.getClassLoader().getResource("student.xml").getPath();
//加载文档进内存
Document document = Jsoup.parse(new File(path), "utf-8");
//根据document对象创建JxDocument对象
JXDocument jxDocument=new JXDocument(document);
//结合Xpath语法查询
//查询所有的student标签
List<JXNode> jxNodes = jxDocument.selN("//student");
//查询所有student下的name标签
List<JXNode> jxNodes1 = jxDocument.selN("//student/name");
//查询student标签下带有id属性的name标签
List<JXNode> jxNodes2 = jxDocument.selN("//student/name[@id]");
//查询student标签下带有id属性的name标签,并且id的属性值为itcast
List<JXNode> jxNodes3 = jxDocument.selN("//student/name[@id='itcast']");
}
}