1 Star 0 Fork 0

刘洋 / ProductionPractice

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
note.md 44.56 KB
一键复制 编辑 原始数据 按行查看 历史
liuyang 提交于 2020-09-20 16:13 . 1

JDBC

什么是JDBC

java数据库连接(Java Database Connectivity)

有什么用

利用 Java 代码, 可以操作数据库。

怎么用

  1. 注册驱动
  2. 获取数据库连接
  3. 创建 Statement / PreparedStatement / 对象
  4. 执行SQL
  5. 处理结果
  6. 释放资源

示例

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/**
 * @author lujiapeng
 * @className JDBC01
 * @description JDBC的第一个例子
 **/
public class JDBC01 {
    public static void main( String[] args ) throws  Exception {
 // 01 : 注册驱动 ( 引入对应的 jar 包 )
 Class.forName("com.mysql.cj.jdbc.Driver") ;
 System.out.println("注册驱动成功");
 // 02 : 获取数据库连接
 // 在Java 中, 使用 java.sql.Connection 接口表示 一个 连接
 Connection connection ;
 String url = "jdbc:mysql://localhost:3306/ecut?serverTimezone=Asia/Shanghai" ;
 String username = "root" ;
 String password = "root" ;
 connection = DriverManager.getConnection(url , username , password) ;
 System.out.println( connection );
 System.out.println( "获取连接成功" );
 // 03 : 创建 Statement 对象
 Statement statement = connection.createStatement() ;
 // 04 : 执行SQL
 String SQL = "select * from country" ;
 boolean result = statement.execute( SQL ) ;
 System.out.println( result );

 // 05 : 处理结果
 ResultSet resultSet = statement.getResultSet();
 while( resultSet.next() ){
     int id = resultSet.getInt("id");
     String countryname = resultSet.getString("countryname");
     String countrycode = resultSet.getString("countrycode");
     System.out.println(id + " " + countryname + " " + countrycode );
 }
 // 最后一步,释放资源 : 先开的 后关闭
 resultSet.close();
 statement.close();
 connection.close();
    }
}

使用 JDBC 完成数据库的 增加、删除、修改、查询

  • 增加
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

/**
 * @author lujiapeng
 * @className JDBC02
 * @description 实现增加数据
 * @date 2020/9/7 14:43
 **/
public class JDBC02 {
    public static void main(String[] args) throws Exception{
 // 加载驱动
 // 用到的原理是 : 反射
 Class.forName("com.mysql.cj.jdbc.Driver") ;
 // 获取连接
 String url = "jdbc:mysql://localhost:3306/ecut?serverTimezone=Asia/Shanghai" ;
 String username = "root" ;
 String password = "root" ;
 Connection connection = DriverManager.getConnection(url , username , password ) ;
 // 获取 Statement / PreparedStatement / CallableStatement 对象
 // PreparedStatement 与 CallableStatement 都是 Statement 的 子接口

 Statement statement = connection.createStatement() ;

 // 执行SQL( 插入语句 )
 String SQL = "insert into country( countryname, countrycode) values ('南非共和国','NF') , ('埃及','AJ')" ;
 // 想要执行 insert、update、delete 语句,那么就需要 使用 executeUpdate 方法
 // executeUpdate 方法一般用于执行 DDL
 // 该方法返回  受SQL 影响的记录条数
 int executeUpdate = statement.executeUpdate(SQL);
 // 获取结果
 System.out.println( executeUpdate );

 // 关闭资源
 statement.close();
 connection.close();
    }
}
  • 练习 : 自己实现 删除、修改数据 。
  • 练习2: 自己实现 查询数据 ,并将结果输出。

常用对象

  • Connection : 表示一个连接

  • Statement : 用于执行一条SQL语句

    Statement执行过程

  1. 将 SQL 发给数据库
  2. SQL 会编译
  3. 执行SQL
  4. 再获取结果。
  • 常用方法: text execute( [String SQL] ) : 一般用于执行 任意SQL,返回boolean 类型 executeUpdate( String SQL ) : 一般用于执行 DML(insert 、update、delete) 和 DDL( create table 、drop table等) executeQuery( String SQL ) : 一般用于 静态 查询 SQL,例如: select * from country where id = 1;

  • ResultSet : 结果集,返回一个具体的结果 主要方法:

    • getXXX( int columnIndex ) : 根据指定的列数,获取结果
    • getXXX( String columnLabel) : 根据指定的别名,获取结果
  • PreparedStatement : 表示预编译SQL语句的对象。也就是将 SQL 语句,再执行之前,就发给数据库了,然后,每次都是替换 指定的参数即可。

    • 练习 : 使用 PreparedStatement 进行 增加、删除、修改、查询
  • CallableStatement : 用于 执行 存储过程。

事务

事务封装在 java.sql.Connection 中 。

  • commit() : 提交事务
  • rollback() : 回滚事务

封装工具类

目的 : 为了 程序的简单性 , 便于我们使用!可能不是那么复杂,功能性考虑的不是很好,只是提供一个思路。

package cn.ecut;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Objects;
import java.util.Properties;

/**
 * @author lujiapeng
 * @className JDBCHelper
 * @description JDBC工具类,可以叫做 JDBCHelper 或 JDBCUtil
 **/
public class JDBCHelper {
    private static String driverName ;
    private static String url ;
    private static String username ;
    private static String password ;
    private static boolean autoCommit ;
    private static int isolation ;

    private static Connection connection ;
    /**
     * 0、加载配置文件 :当类被加载之后,就直接 加载 配置文件
     */
    static{
 // 类代码块 : 当类加载的时候,就会被执行,而且比 构造方法先执行
 config();
    }
    private static void config(){
 // 创建一个对象,获取到资源文件
 Properties properties = new Properties() ;

 // 通过 Class 中的方法,可以获取到 指定的资源文件
 InputStream resourceAsStream = JDBCHelper.class.getResourceAsStream("/jdbc.properties");
 // 将流中的中的内容,加载到 properties 对象中
 try {
     properties.load( resourceAsStream );
     // 根据指定的属性名,获取 相应的内容(属性值)
     String connect = properties.getProperty("connect");
     String autocommit = properties.getProperty("jdbc.connection.transaction.autocommit");
     autoCommit = Boolean.valueOf( autocommit ) ;
     String i = properties.getProperty("jdbc.connection.transaction.isolation");
     isolation = Integer.valueOf( i ) ;
     driverName = properties.getProperty("jdbc.connection.mysql.driver");
      url = properties.getProperty("jdbc.connection.mysql.url") ;
      username = properties.getProperty("jdbc.connection.mysql.username") ;
      password = properties.getProperty("jdbc.connection.mysql.password") ;
 } catch (IOException e) {
     e.printStackTrace();
 }
    }

    /**
     * 1、加载驱动
     */
    private static boolean load(){
 try {
     Class.forName( driverName ) ;
     return true ;
 } catch (ClassNotFoundException e) {
     System.out.println("加载驱动异常:" + e.getMessage());
 }
 return false ;
    }
    /**
     * 2、建立连接
     */
    public static Connection connect(){
 if( load() ){
     try {
  connection = DriverManager.getConnection(url, username, password);
     } catch (SQLException e) {
  e.printStackTrace();
  System.out.println("建立连接失败" + e.getMessage() );
     }
 }
 return connection ;
    }
    /**
     * 3、设置事务是否是 自动提交的, 并且 还要设置 事务的隔离级别
     */
    public static void transaction(){
 if(Objects.isNull( connection)){
     connection = connect() ;
     try {
  connection.setAutoCommit(autoCommit);
     } catch (SQLException e) {
  e.printStackTrace();
     }
     try {
  connection.setTransactionIsolation(isolation);
     } catch (SQLException e) {
  e.printStackTrace();
     }
 }
    }
    /**
     * 4、创建 Statement 对象 或 PreparedStatement 对象
     */
    public static Statement statement(){
 Statement st = null ;
 if( Objects.isNull(connection )){
     connection = connect() ;
 }
 try {
     st = connection.createStatement() ;
 } catch (SQLException e) {
     e.printStackTrace();
 }
 return st ;
    }


    /**
     *
     * @param SQL
     * @param autoGeneratedKeys 是否需要自动生成主键
     * @return
     */
    public static PreparedStatement prepare( String SQL , boolean autoGeneratedKeys ){
 PreparedStatement ps = null ;
 if( Objects.isNull(connection )){
     connection = connect() ;
 }
 try {
     if( autoGeneratedKeys ) {
  ps = connection.prepareStatement(SQL , Statement.RETURN_GENERATED_KEYS);
     }else{
  ps = connection.prepareStatement( SQL ) ;
     }
 } catch (SQLException e) {
     e.printStackTrace();
 }
 return ps ;
    }

    /**
     * 5、执行 SQL : 查询、insert、delete、update
     */
    /**
     * 仅仅处理查询语句
     * @param SQL
     * @param params 可变长参数,在方法中当作数组来处理即可。
     * @return
     */
    public static ResultSet query( String SQL , Object... params ){
 if( SQL == null || SQL.trim().isEmpty() || !SQL.trim().toLowerCase().startsWith("select")){
     throw new RuntimeException("你的SQL语句为空,或不是查询语句") ;
 }
 ResultSet rs = null ;
 if(params.length > 0 ){
     PreparedStatement ps = prepare( SQL , false ) ;
     try {
  for( int  i = 0 ; i < params.length ; i ++ ){
      ps.setObject( i+1 , params[i]);
  }
  rs = ps.executeQuery() ;
     } catch (SQLException e) {
  e.printStackTrace();
     }
 }else{
     Statement st = statement() ;
     try {
  rs = st.executeQuery( SQL ) ;
     } catch (SQLException e) {
  e.printStackTrace();
     }
 }

 return rs ;
    }


    /**
     * 执行 Insert、update、delete等SQL
     * @param SQL
     * @param params
     * @return
     */
    public static boolean  execute( String SQL , Object... params ){
 if( SQL == null || SQL.trim().isEmpty() || SQL.trim().toLowerCase().startsWith("select")){
     throw new RuntimeException("你的SQL语句为空,或是 查询语句") ;
 }
 boolean r = false ;
 if(params.length > 0 ){
     PreparedStatement ps = prepare( SQL , false ) ;
     Connection c = null ;
     try {
  c = ps.getConnection() ;
     } catch (SQLException e) {
  e.printStackTrace();
     }
     try {
  for( int  i = 0 ; i < params.length ; i ++ ){
      ps.setObject( i+1 , params[i]);
  }
   ps.executeUpdate() ;
  r = true ;
  // 提交事务
  commit( c );
     } catch (SQLException e) {
  e.printStackTrace();
  rollback( c );
     }
 }else{
     Statement st = statement() ;
     Connection c = null ;
     try {
  c = st.getConnection() ;
     } catch (SQLException throwables) {
  throwables.printStackTrace();
     }
     try {
  st.executeUpdate( SQL ) ;
  r = true ;
  commit( c );
     } catch (SQLException e) {
  e.printStackTrace();
  rollback( c );
     }
 }
 return r ;
    }


    /**
     * 6、处理事务: 提交或 回滚事务
     */
    private static void commit( Connection c ){
 if( c != null && autoCommit ){
     try {
  c.commit();
     } catch (SQLException e) {
  e.printStackTrace();
     }
 }
    }
    private static void rollback( Connection c ){
 if( c != null && autoCommit ){
     try {
  c.rollback();
     } catch (SQLException e) {
  e.printStackTrace();
     }
 }
    }
    /**
     * 最后一步:释放资源
     */
    public static void release( Object o ){
 if(Objects.nonNull( o )){
     if( o instanceof ResultSet){
  ResultSet resultSet = ( ResultSet) o ;
  try {
      resultSet.close();
  } catch (SQLException e) {
      e.printStackTrace();
  }
     }
     if( o instanceof Statement){
  Statement st = ( Statement) o ;
  try {
      st.close();
  } catch (SQLException e) {
      e.printStackTrace();
  }
     }
     if( o instanceof Connection){
  Connection c = ( Connection) o ;
  try {
      c.close();
  } catch (SQLException e) {
      e.printStackTrace();
  }
     }
 }
    }
}

要求 : 自己能写出来!

前端

三大核心:HTML + CSS + JavaScript

备注:仅仅是应用

参考网站:w3school , 主要是知道上哪里去寻找参考文档(API)

方法与变量的定义

参看 javascript01.html

BOM

BOM : Browser Object Model 浏览器对象模型

window

  • setTimeout( 表达式或函数 , 毫秒值) : 表示 多少毫秒值之后执行一次 前面的表达式或函数
  • clearTimeout() : 清除 , 具体用法参看 javascript01.html

练习 : 熟练掌握这两个方法。

  • setInterval( 表达式或函数 , 毫秒值 ) : 表示 多少毫秒值之后执行 前面的表达式或函数
  • clearInterval()

练习 : 熟练掌握这两个方法。

Navigator

通过 userAgent 可以判断不同的浏览器。

Screen

相关的屏幕信息

  • 练习 : 测试 Screen 中 的 availHeight、availWidth、height、width

History

历史记录 : 就是以前访问过的url

  • back() : 后退 就是浏览器中的后退按钮
  • forward() : 前进,就是浏览器中的 前进按钮
  • go() : back() 和 forward() 底层都可以认为是使用了 go方法
go 方法 自行测试:
    eg : go(-1)、go(-2)、go(1) 、 go(2) 、 go(0)

Location

可以获取关于URL 的相关信息

  • reload: 刷新,需要明确知道

DOM

Document Object Model : 文档对象模型 每个载入浏览器的 HTML 文档都会成为 Document 对象。

  • 节点: 每个部分都是节点

    • 文档本身是文档节点
    • 所有 HTML 元素是元素节点
    • 所有 HTML 属性是属性节点
    • HTML 元素内的文本是文本节点
    • 注释是注释节点
  • 需要了解NodeType的使用,具体参看JavaScript06.html

  • 元素:开始标记、结束标记、及其中间内容。

操作

访问页面的元素

  • getElementsByTagName( "标记名称" )
  • getElementsByClassName( "class名称" )
  • getElementById( "元素的id" )
  • getElementsByName( "名称" )
  • querySelectorAll( "CSS选择器" ) 返回选择器选择的所有的元素组成的 "集合"
  • querySelector( "CSS选择器" ) 返回选择其选择的所有元素中的第一个

练习 : 自行查看效果 , 并使用 querySelector 和 querySelectorAll 熟悉选择器的使用。

新增

  • element.insertBefore( newChild , refChild )
  • element.appendChild( newChild )

相关使用:

  • 创建:document.createElement("标记名称");
  • 复制:document.cloneNode( true | false );

修改

替换节点:
  • element.replaceChild( newChild , refChild ): 父元素.replaceChild( newChild , refChild )
修改内容:
  • 对于 表单中的 input 来说,修改或获得其内容,用 value 属性
  • 对于 表单中的 textarea 来说,修改或获得其内容,用 value 或 innerHTML 属性
  • 对于 表单中的 option 来说,用 value 访问其取值 ( 向服务器发送的数据 ) ,用 text( innerHTML、innerText ) 访问显示的文本内容
  • 其它 的元素 都使用 innerHTML 或 innerText 属性来修改或获得其内容

如果是获取内容,则直接通过相应的属性来获取即可,比如 var content = div.innerHTML ; 如果要设置内容,则通过为 相应的属性赋值即可,比如 div.innerHTML = "新的内容" ;

#####修改样式:

修改 单个样式属性: 通过 元素的 style 属性来更改单个 属性对应的样式 原来 在 CSS 中写的所有的属性,比如 text-align , 其中的 减号 一律去掉,减号之后的那个字母大写即可 ( textAlign )

element.style.属性名 = 属性值 ;
比如: div.style.textAlign = "center" ;
修改一组:
  • 增加 class : element.classList.add( className )

  • 移除 class : element.classList.remove( className)

  • 判断是否包含指定的 class 名称: element.classList.contains( className )

    注意: element 必须是个 DOM 元素,才能访问 classList

删除

  • element.removeAttribute( attrName ) : 删除 element 上的指定名称的 属性
  • element.removeChild()

查 ( 访问 )

  • 通过直接选择来访问

    • getElementsByTagName( "标记名称" )
    • getElementsByClassName( "class名称" )
    • getElementById( "元素的id" )
    • getElementsByName( "名称" )
    • querySelectorAll( "CSS选择器" )
    • querySelector( "CSS选择器" )
  • 通过节点之间的关系来访问

    • element.parentNode 获得 element 元素的 父节点
    • element.previousSibling 返回 element 之前的那个兄弟节点 (相邻,可能是文本)
    • element.previousElementSibling 返回 element 之前的那个 兄弟 元素 (相邻节点)
    • element.nextElementSibling 返回 element 之后的那个 兄弟 元素 (相邻节点)
    • element.nextSibling 返回 element 之后的那个兄弟节点 (相邻,可能是文本)
    • element.childNodes 获得 element 元素的 所有 子节点 ( 含 文本 和 注释 )
    • element.attributes 获得 element 元素的 所有属性
    • element.firstChild 获得 element 元素的 第一个 子节点 ( 可能是 文本 )
    • element.firstElementChild 获得 element 元素的第一个 子元素
    • element.lastElementChild 获得 element 元素的最后一个 子元素
    • element.lastChild 获得 element 元素的 最后一个 子节点 ( 可能是 文本 )

练习 : 今天上午的内容(操作文档),全部练习。

JS事件

事件的直接使用

在JavaScript 中,直接在 标签中使用 onXXX 的形式,就可以被称为事件。

一般是指 有具体某一个操作(是通过 on 进行指定的)的时候,发生的事情(方法)

使用事件监听器

  • element.addEventListener( 事件名称 , 事件行为 ) ;
  • element.removeEventListener( 事件名称, 事件行为 ) ;

练习 : 将JSON 中的数据,通过事件的方式,打印在页面上。

JSON

JavaScript Object Notation

形式

{ key1 : value1 , key2: value2 .... }

key : 是字符串类型 , 但是 可以不用 英文双引号引用起来,而是当作一个属性来对待。(一般不会是一个数字) value : 任意类型 (一般都是对象、数组、字符串等)

JSON 现在已经作为一种前后端交互的手段,所以在JSON中,一般不会有方法。

解析 :一般 使用 JSON.parse()

JQuery

是一个优秀的 JavaScript 框架 ,封装了对应的JavaScript 常规操作。封装了大量关于DOM操作的内容。

jQuer 支持链式语法。

使用

需要引入JQuery.js文件,在JavaScript 脚本中,使用 jQuery 或 $ 来表示一个 jQuery 对象。

$函数

  • 可以将 一个或多个 DOM 元素,封装成 jQuery实例。
  • 可以通过选择器,将选中的元素封装成 jQuery 实例
  • 可以将 一个完整的HTML 字符串,封装成 jQuery 实例
  • 可以将一个函数,放入到 jQuery() 函数( $() )中,那么就表示 当页面加载完成之后,执行这段代码

选择器

基本上,选择器与 CSS 选择器没有什么太大区别!

常用方法

  • css() : jQuery实例.css( 属性名 , 属性值 )

  • addClass() : 操作了 class 属性,同时这个 方法的值,是可以不存在。

  • html() : 其实就是针对的 DOM 元素的 innerHTML 属性, 如果没有参数,表示获取;如果有参数表示设置。

  • text() : 其实就是针对的 DOM 元素的 innerText 属性, 如果没有参数,表示获取;如果有参数表示设置。

  • val() :其实就是针对于 DOM 元素的 value 属性。如果没有参数,表示获取;如果有参数表示设置。

  • noConflict() : 将 内部的 $ 替换成 其他符号

练习 : 剩下的方法可以自己调用,并体现效果。 after() 在匹配的元素之后插入内容。 append() 向匹配元素集合中的每个元素结尾插入由参数指定的内容。 appendTo() 向目标结尾插入匹配元素集合中的每个元素。 attr() 设置或返回匹配元素的属性和值。 before() 在每个匹配的元素之前插入内容。 text() 设置或返回匹配元素的内容。

DOM元素的操作

  • after() : jQuery 实例.after( newNode ) ; 会在调用的时候,在jQuery实例后边新增元素
  • append() : 追加,在 jQuery 实例内部 放置在最后。
  • appendTo() : 追加到那里去,具体格式 : jQuery实例.appendTo( jQuery实例2 ) ,将jQuery实例追加到 jQuery实例2 中
  • before() : 与 after() 相反
  • insertAfter() : 在哪里进行插入,插入到后方:jQuery实例.insertAfter( jQuery实例2) , 将jQuery实例插入到jQuery实例2的后方
  • insertBefore()
  • remove() : 没有参数, 谁调用,移除谁。
  • replaceWith() : jQuery实例.replaceWith( jQuery实例2) 将jQuery实例 替换成 jQuery实例2
  • clone() : 复制

练习 : 通过调用事件的方式,进行操作页面的元素。(增加、删除、修改【修改style、class、文本、value】)

事件

  • 直接调用方法 : click( function(){}) ;
  • 通过 bind() 或 unbind() 绑定/解绑事件 jQuery实例.bind( 事件名称 , [要传入到函数中的数据,] function(){} )

练习 : 使用 bind 或 jQuery 具体的方法,实现 三种及其 以上的 事件操作。 bind() 向匹配元素附加一个或更多事件处理器 click() 触发、或将函数绑定到指定元素的 click 事件 dblclick() 触发、或将函数绑定到指定元素的 double click 事件 focus() 触发、或将函数绑定到指定元素的 focus 事件

动画

  • fadeIn()

  • fadeOut()

  • fadeToggle()

  • slideDown()

  • slideToggle()

  • slideUp()

了解即可。

练习 : 实现 滑动效果(使用事件的方式)。 slideDown() slideUp() slideToggle()

AJAX( Asynchronous JavaScript and XML )

概述

XMLHttpRequest 是 AJAX 技术的核心。AJAX 依赖于 XMLHttpRequest 来完成与服务器的通信。

XMLHttpRequest 是 AJAX 中与服务器异步通信的核心;通过 XMLHttpRequest 的异步通信能力, 可以减轻服务器负担, 加快响应速度、 缩短用户等待时间

XMLHttpRequest 包含了一些基本的属性和方法,XMLHttpRequest 的异步通信能力正是依赖于这些属性和方法,XMLHttpRequest 中的属性和方法并不算多,但这些为数不多的属性和方法已经足够满足 AJAX 的基本需要

XMLHttpRequest 中基本的方法有

  • abort() : 停止发送当前请求
  • getAllResponseHeaders() : 获取服务器返回的全部响应头
  • getRequestHeader("headerLabel"):根据指定的请求头, 获取相应的值
  • open( "method" , "url" [ , asyncFlag , "uname" , "passwd" ] ) :建立与服务器 URL 的链接并设置请求的方法以及是否使用异步请求(默认为支持异步请求)
    • asyncFlag 处的为 true 表示支持异步请求, false 表示不支持。如果远程链接需要用户名和密码, 则可以在参数中提供。
  • send( content ) : 发送请求 ( 其中 content 是请求参数)
  • setRequestHeader( "label" , "value" ):发送请求之前, 先设置请求报头

XMLHttpRequest 中的常用属性

  • onreadystatechange:用于指定 XMLHttpRequest 对象状态改变时对应的时间处理函数

  • readyState:XMLHttpRequest 对象的处理状态

  • responseText:该属性用于获取服务器的响应文本

  • responseXML:该属性用于获取服务器响应的XML文档对象

  • status:对应服务器返回的状态代码(只有当服务器的响应完成时, 才会有该状态代码)

  • statusText : 对应服务器返回的状态文本信息(当服务器响应完成时)

  • onreadystatechange 属性 :用于指定一个函数 ,这个函数负责处理 XMLHttpRequest 状态变化时的事件

  • readyState 属性 : 对应 XMLHttpRequest 对象的状态。 XMLHttpRequest 的状态有 - 0 : 表示 XMLHttpRequest 对象还没有完成初始化 - 1 : 表示 XMLHttpRequest 对象开始发送请求 - 2 : 表示 XMLHttpRequest 对象请求发送完成 - 3 : 表示 XMLHttpRequest 对象开始读取服务器响应信息 - 4 : 表示 XMLHttpRequest 对象读取服务器响应结束

  • status 属性 : 对应服务器响应代码, 用于判断服务器响应是否正确

  • statusText 属性:用于获取服务器响应码对应的响应信息。 无论响应代码是什么, 只要生成了响应, 就可以获取响应信息。

  • responseText 属性:获取服务器发送来的文本信息(如果服务器发送的是文本信息)。异步数据传输中, JSON 格式的数据通常使用该属性获取

  • responseXML 属性 : 如果服务器响应发送的是 XML 格式的数据, 用该属性获取。(早期的 AJAX 应用中, 传输的数据都是 XML 格式的)

使用XMLHttpRequest进行异步通信的步骤

  • 初始化 XMLHttpRequest 对象 : 视不同浏览器创建 XMLHttpRequest 对象
  • 打开与服务器的连接 : 使用 open() 方法开启连接
  • 设置监听 XMLHttpRequest 状态改变的事件处理函数。可以在 onreadystatechange 之后直接书写函数,也可以单独书写函数, 然后在这里指定函数名即可。
  • 设置请求报头。一般要设置跟当前请求有关的报头, 比如编码等。使用 setRequestHeader() 方法设定
  • 发送请求。向服务器发请求, 如果是 POST 请求, 可以发送参数, 否则发送 null 即可。

步骤详解:

open( "method" , "url" , asyncFlag , "uname" , "passwd" )
		method
			用于指定请求的方法, 可以是 GET 或者 POST 请求
			这里请求的方式不同, 之后的 send() 使用可能也不同
		url 需要连接的资源
		asyncFlag 是否进行异步请求 ( 默认为 是 )
			true 表示执行异步请求, 默认值
			false 表示不执行异步请求
		uname 和 passwd 为可选参数
			仅当服务器需要用户名和密码时发送

使用 onreadystatechange 属性指定事件处理函数
		直接在属性之后书写匿名函数
	
使用 setRequestHeader() 方法设定请求的报头
		一般设置 Content-Type 报头
		可以设置为application/x-www-form-urlencoded或multipart/form-data
		比如:setRequestHeader( "Content-Type" , "application/x-www-form-urlencoded");
	
发送请求:send()
		如果是post请求,则data形式是username=zhangsanfeng&password=hello2016
		比如:data="username=zhangsanfeng&password=2016";
		如果参数值中有中文,比如张三丰,则用encodeURI对中文进行编码
		data = "username="+encodeURI("张三丰")+"&password=2016";
	
		如果是get请求,则send方法不能发送数据,传入null即可
		send( data );
	
回调函数( 回调信息 ):
		就是在readyState == 4 的时候可以处理的函数
		比如要显示数据的区域,或者是处理相应的数据

练习 : 学会使用 原生AJAX 发送和获取数据 。 服务器返回的所有数据,都是JSON 类型。

使用jQuery 发送并获取数据。

Servlet 与 JSP

杂项

  • 推荐书籍:《HeadFirst-Servlets&JSP.pdf》、《Servlet和JSP核心编程》上下两卷

  • 修改pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>cn.ecut</groupId>
  <artifactId>servlet</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>servlet Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- 根据自己的 Project SDK 来确定版本 -->
    <maven.compiler.source>14</maven.compiler.source>
    <maven.compiler.target>14</maven.compiler.target>
    <maven.compiler.compilerVersion>14</maven.compiler.compilerVersion>
  </properties>

  <!-- 依赖,就是jar包  -->
  <dependencies>
    <!-- junit 单元测试包 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <finalName>servlet</finalName>
    <plugins>

      <!-- Maven Resource Plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.1.0</version>
        <configuration>
          <encoding>${project.build.sourceEncoding}</encoding>
        </configuration>
      </plugin>

      <!-- Maven Compiler Plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
        <configuration>
          <source>${maven.compiler.source}</source>
          <target>${maven.compiler.target}</target>
          <compilerVersion>${maven.compiler.compilerVersion}</compilerVersion>
          <encoding>${project.build.sourceEncoding}</encoding>
        </configuration>
      </plugin>

      <!-- Maven Jetty Plugin -->
      <plugin>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>9.4.30.v20200611</version>
        <configuration>
          <httpConnector>
            <port>8080</port>
          </httpConnector>
          <useTestClasspath>true</useTestClasspath>
          <webAppConfig>
            <!-- 这里指定在浏览器访问时,当前Web应用的根路径 -->
            <contextPath>/</contextPath>
            <!-- 默认描述符文件 jetty.xml 需要放在 工程 根目录下( 也就是跟pom.xml在同一层次) -->
            <defaultsDescriptor>jetty.xml</defaultsDescriptor>
          </webAppConfig>
        </configuration>
      </plugin>

      <!-- Maven Tomcat Plugin -->
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <port>8080</port>
          <!-- 这里指定在浏览器访问时,当前Web应用的根路径 -->
          <path>/</path>
          <uriEncoding>UTF-8</uriEncoding>
          <useBodyEncodingForURI>true</useBodyEncodingForURI>
        </configuration>
      </plugin>

    </plugins>
  </build>
</project>
  • 了解如何启动
在 IDEA 工具的右侧,点开 Maven -> 要运行的应用程序 -> Plugins -> jetty -> 双击jetty:run
  • 修改web.xml 中的欢迎页面
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
							 http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         id="WebApp_ID"
         version="4.0" metadata-complete="false" >

    <!-- 自定义欢迎页面(访问应用程序的 / 时,出现的第一个页面) -->
    <welcome-file-list>
        <welcome-file>/pages/kak/haha/index.html</welcome-file>
    </welcome-file-list>
</web-app>

什么是 Servlet

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性, 主要功能在于交互式地浏览和生成数据,生成动态Web内容。 狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。——百度百科

我的第一个Servlet

实现 javax.servlet.Servlet 接口。这个接口其中定义了所有Servlet 必须实现的方法,可以理解成一个根接口。

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

/**
 * @author lujiapeng
 * @className FirstServlet
 * @description 第一个Servlet
 * @date 2020/9/10 15:19
 **/
public class FirstServlet implements javax.servlet.Servlet{
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("FirstServlet#init方法执行了");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("FirstServlet#service方法");
    }

    @Override
    public String getServletInfo() {
        return "我的第一个Servlet";
    }

    @Override
    public void destroy() {
        System.out.println("被销毁了");
    }
}

修改配置文件:web.xml

    <servlet>
        <!-- servlet-name 中的值,随便写 -->
        <servlet-name>haha</servlet-name>
        <!-- 将 指定的Servlet 类,“注册” 到整个容器之中
            值:全限定类名 ( 包名 + 类名 )
          -->
        <servlet-class>cn.ecut.servlet.FirstServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <!-- 这里的 servlet-name 与  上边的一致  -->
        <servlet-name>haha</servlet-name>
        <!-- 是 需要 访问的 路径  -->
        <url-pattern>/haha</url-pattern>
    </servlet-mapping>

创建Servlet 的方式

  • 实现 javax.servlet.Servlet 接口
  • 继承 javax.servlet.GenericServlet 类
  • 继承 javax.servlet.http.HttpServlet 类 ,重写 doXXX 方法
  • 继承 javax.servlet.http.HttpServlet 类 ,重写 protected void service(HttpServletRequest request, HttpServletResponse response)... 方法

生命周期

  1. 类加载
  2. 执行构造方法,创建实例
  3. init方法执行
  4. service 方法 反复对外提供服务
  5. 当类被卸载的时候,destroy 方法执行。

练习 : 四种实现的方式都需要走通,并且 在 index.html 页面上,能够点击,访问到对应的Servlet

Request

请求仅仅针对于 单次。

Request 对象 封装了 对HTTP请求的一些方法 。仅仅列出来一些常用的方法。

获取请求行中内容的方法

  • String getServerName(): 获取请求的服务器的名称,一般是个IP地址或域名
  • int getPort(): 返回当前请求的服务器的端口号
  • String getRequestURL() :获取本次请求对应的URL
  • String getMethod():获取本次请求的请求方式 ,可能是get 或 post方式
  • String getRequestURI:获取本次请求对应的URI
  • String getProtocol():获取本次请求对应的协议和版本号
  • String getQueryString():获取本次请求中的查询字符串(一般是链接中?之后的那部分)

获取请求报头中的名字的方法

  • Enumeration getHeaderNames() 获得所有的请求报头的名称
  • String getHeader ( String headerName) : 一个通用的根据请求报头的名称 获得取值的方法

获取参数的值

  • String getParameter( String name ) :获取请求中name 对应的参数的值
  • String[] getParameterValues( String name ):获取请求中name对应的参数的值
  • Enumeration getParameterNames():获得请求中所有的请求参数的名称
  • Map<String , String[]> getParameterMap():获得请求中所有的参数名称-参数值对应的集合

获取/设置请求编码

  • String getCharacterEncoding():获取编码名称
  • void setCharacterEncoding( String encodingName ): 设置编码

上传文件

  • Part getPart( String name ) // 适用于单个文件上传
  • Collection getParts()// 适用于多个文件上传

其他常用方法

  • request#getContextPath() : 获取上下文路径
  • request#setAttribute( String name , Object value )
  • request#getAttribute( String name )
  • request#removeAttribute( String name )

Response

就是 服务器给客户端 发送的 数据。

常用方法

  • setCharacterEncoding( String value ) : 设置指定的编码
  • setHeader( String name , String value ) : 设置已经存在的响应头
  • addHeader( String name , String value ) : 添加响应头 ,可以是不存在响应头
  • setContentType( String value ) : 设置 ContentType 的值。
  • setStatus( int sc ) : 设置响应状态
  • sendError( int sc , String msg ) : 发送错误
  • sendError( int sc ) : 发送错误

会话追踪

Cookie

在JavaEE中,对应的对象是javax.servlet.http.Cookie。

  • 创建 Cookie 的方式
  • 获取 Cookie 的方式
  • 需要知道内部的方法 使用,同时需要了解 Cookie 的存活时间。

session

session 某种意义上 基于 Cookie ,如果 Cookie 禁用了,那么 session 就不能使用!

session 对应的接口是 :javax.servlet.http.HttpSession。

一个特点 :当访问多个页面的时候,可以利用 session 来实现会话追踪。

  • 获取Session : HttpServletRequest#getSession()
  • setAttribute( String name , Object value ) ;
  • getAttribute( String name ) ; 返回类型为 Object
  • removeAttribute(String name)
  • invalidate() : 废弃 session
  • 配置session的过期时间:在配置文件中使用具体的配置进行操作。(约定大于配置、配置大于代码)
  • getMaxInactiveInterval() : 获取session 的过期时间

URL重写

  1. 需要获取session ,主要是获取 session 的id ,也就是浏览器中的 jsessionid
  2. url重写 : response.encodeRedirectURL( String url );
  3. 重定向 : response.sendRedirect( 已经编码过后的url )

隐藏表单域

<input type="hidden" value="">

调度( Dispatcher )

重定向(redirect)

刘备-----> 徐庶 (你去找诸葛亮) 刘备-----> 诸葛亮

  • 重定向会导致地址栏发生变化
  • 本质:就是在 response 中使用了 302 状态码,同时在 location 中,设置了 要访问的 路径
  • 重定向,会访问两次服务器

代码参看 cn.ecut.dispatcher.XushuServlet 和 cn.ecut.dispatcher.ZhugeliangServlet

RequestDispatcher

定义一个对象,该对象接收来自客户端的请求并将其发送到服务器上的任何资源(例如servlet、HTML文件或JSP文件)。

获取

  • ServletContext.getRequestDispatcher(java.lang.String)
  • ServletContext.getNamedDispatcher(java.lang.String)
  • ServletRequest.getRequestDispatcher(java.lang.String)

转发

  • RequestDispatcher # forward( ServletRequest request, ServletResponse response )

  • 是在 服务器内部完成的转发,所以在 浏览器的地址栏中不会有任何改变。

  • 面试: 重定向和转发有什么区别 ?

练习 :使用转发 ,转发到 HTML 文件。

包含

  • RequestDispatcher # include( ServletRequest request, ServletResponse response )

练习 :包含指定的 HTML 文件。

杂项

注解

为了简化开发, 可以使用注解,替换 web.xml 中的配置 。

对应的注解为 @WebServlet

  • value :是个数组,可以有多个路径。 表示了具体的映射路径( 在 web.xml 中进行的配置 url-pattern)
  • url-pattern : 与 value 一致

ServletConfig

关于 初始化参数的配置

  • 使用 web.xml 的配置方式
  • 使用注解的配置方式

ServletContext

这是一个关于 全局Servlet 的一个接口 。

  • getContextPath() : 获取上下文路径

获取方式

  • ServletConfig#getServletContext()
  • HttpServletRequest#getServletContext()
  • HttpSession#getServletContext()
  • GenericServlet#getServletContext()

有什么用

一般存放一些公共的资源(参数的配置) ,多个Servlet 都使用的资源,比如说编码,示例如下:

    <context-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </context-param>

具体使用如下:

@WebServlet("/applicationInitParamter")
public class ApplicationInitServlet extends HttpServlet  {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1、获取到具体的ServletContext
        ServletContext application = this.getServletContext();

        // 2、获取 全局的初始化参数
        Enumeration<String> initParameterNames = application.getInitParameterNames();
        while( initParameterNames.hasMoreElements() ){
            String s = initParameterNames.nextElement();
            String parameter = application.getInitParameter(s);
            System.out.println( parameter );
        }
    }
}

数据存取

是将 一些数据存放到 ServletContext 中,表示这些可以在任意的Servlet 中使用。

  • ServletContext#setAttribute( String key , Object value ) ;
  • ServletContext#getAttribute( String key ) : 通过key进行获取指定的值,返回一个Object

过滤器

是 浏览器在访问 Servlet之前,就需要执行的一个部分;也是 Servlet 访问之后,需要执行的一个部分。

对应的接口 : javax.servlet.Filter

具体的配置(web.xml)与 Servlet 的配置 差不多!具体参看 web.xml

完整的过滤器的使用:cn.ecut.filter.CharacterEncodingFilter.java

更多使用的是 配置,而不是注解。

练习 :开发一个 浏览器过滤器,如果是IE浏览器,那么就不允许访问,其余的浏览器可以访问(FireFox、Chrome等)。

JSP

Java Server Page 动态网页技术(现在基本没人用)

JSP的本质

就是Servlet : 因为 容器会将 .jsp 文件 "翻译" 成 .java 文件,其中 该文件 继承了 org.apache.jasper.runtime.HttpJspBase 而,HttpJspBase 又继承了 HttpServlet

JSP中可以存在什么东西

  • 指令: <%@ 指令名称 属性1=值1,属性2=值2,属性3=值3...%>
  • html代码、注释
  • 声明 : Java 代码 : 成员存在。形式:<%! 声明内容 %>
  • JS:JavaScript
  • EL表达式: 形式:${1+1}
  • 表达式 : <%=表达式内容%> , 定义在service方法中
  • JSP注释 <%-- 注释内容 --%>
  • Java代码 : <% Java代码 %>

指令

形式: <%@ 指令名称 属性1=值1,属性2=值2,属性3=值3...%>

有且仅有三个!

  • page
      isErrorPage : 指定当前页面是一个错误页面,错误通常指的是 500,服务器方面的错误。
      contentType : 用于指定响应报头 
      extends : 继承
      import : 用于导入包中的类
      isELIgnored : 是否忽略EL表达式
      buffer : 缓冲区,默认大小8kb。 缓冲区大小可以自由设置,但是如果设置为0,那么autoFlush就必须设置为true。
      autoFlush : 是否自动刷出
      pageEncoding : 当前页面的编码
      session : 如果设置成false,则不启用session
  • include : 包含 , 已经没有人使用了。 1. 是否可以包含图片 ? 2. 是否可以包含其他的jsp页面 ? 3. 是否可以包含 html页面 ? 4. 是否可以包含 .txt 文件 ?
  • taglib : 引入对应的标签库

JSP 内置对象

就是已经存在的对象,可以直接使用的对象。

要求 : 知道是什么东西,分别是什么,知道在哪里找。

声明在service方法中的内置对象:page、pageContext、config、request、response、session、application、out、exception

只有在指令中 指定 isErrorPage="true" 的时候,才可以看到 exception 对象

EL 表达式

形式 : ${表达式} 。

el 表达式就是一个字符串,只不过是有对应的类将其解析。

保留字: and eq gt true not lt empty instanceof or ne le false ge null div mod

内置对象 :

   pageContext : 用于获取其他对象(request、session、response等)
   pageScope : 对应 pageContext 所属的范围,其中,可以用户存取数据(setAttribute)
   requestScope : 对应 request 所属的范围,其中,可以用户存取数据(setAttribute)
   sessionScope : 对应 session 所属的范围,其中,可以用户存取数据(setAttribute)
   applicationScope : 对应 application 所属的范围,其中,可以用户存取数据(setAttribute)

如果想要在EL 表达式中访问 具体的 对象,那么就需要将对应的对象实例存放在某一个区域中。

区域有四个:

pageContext : 通常指 当前页面
request : 当前请求
session : 当前会话
application :整个web应用

如果 在 EL 表示中,想要访问一个集合,那么就需要进行判断(不为空)

EL运算符:

Addition: +、
Substraction: -、
Multiplication: *、
Division: /、 div、
Remainder: % 、 mod、
== :eq、
!=:ne、
< : lt、
>:gt、
<=:le、
>=: ge、
&&:and、
||:or、
!:not

标准标签库

导入依赖

<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

使用指令 taglib 导入标准标签库

  • set标签和remove标签
  • if : 学会判断
  • foreach : 迭代 List、Set、Map

练习 : 实现 隔行换色 !

额外补充

获取 Class 类型的几种方式

  1. 通过 指定的类.class 的方式获取 ,例如: java.lang.String.class 。
  2. 如果是基本数据类型或数组,也可以使用 .class 的方式获取 。例如:int.class ; int[].class ;
  3. 如果是引用类型,可以通过 运行时 实例 的 getClass方法,进行获取。例如:String s = "123" ; s.getClass() ;
  4. 通过 Class 类型的 静态方法,可以获取到对应的class 实例
Java
1
https://gitee.com/liu-yang-ee/production-practice.git
git@gitee.com:liu-yang-ee/production-practice.git
liu-yang-ee
production-practice
ProductionPractice
master

搜索帮助