JDBC
什么是JDBC
java数据库连接(Java Database Connectivity)
有什么用
利用 Java 代码, 可以操作数据库。
怎么用
- 注册驱动
- 获取数据库连接
- 创建 Statement / PreparedStatement / 对象
- 执行SQL
- 处理结果
- 释放资源
示例
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执行过程
- 将 SQL 发给数据库
- SQL 会编译
- 执行SQL
- 再获取结果。
- 常用方法:
```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() : 将 内部的 $ 替换成 其他符号
练习 : 剩下的方法可以自己调用,并体现效果。
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 具体的方法,实现 三种及其 以上的 事件操作。
动画
-
fadeIn()
-
fadeOut()
-
fadeToggle()
-
slideDown()
-
slideToggle()
-
slideUp()
了解即可。
练习 : 实现 滑动效果(使用事件的方式)。
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)… 方法
生命周期
- 类加载
- 执行构造方法,创建实例
- init方法执行
- service 方法 反复对外提供服务
- 当类被卸载的时候,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重写
- 需要获取session ,主要是获取 session 的id ,也就是浏览器中的 jsessionid
- url重写 : response.encodeRedirectURL( String url );
- 重定向 : 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 类型的几种方式
- 通过 指定的类.class 的方式获取 ,例如: java.lang.String.class 。
- 如果是基本数据类型或数组,也可以使用 .class 的方式获取 。例如:int.class ; int[].class ;
- 如果是引用类型,可以通过 运行时 实例 的 getClass方法,进行获取。例如:String s = “123” ; s.getClass() ;
- 通过 Class 类型的 静态方法,可以获取到对应的class 实例