九大内置对象
三. 内置对象(九大)
jsp页面中的内置对象, 指的是Tomcat将jsp页面翻译为
Servlet源代码
后, 内部提供的九大对象,叫做内置对象
内置对象 | 类型 | 简介 |
---|---|---|
pageContext | JSP页面容器 | |
requset | 客户端向放服务器发送请求消息 | |
response | 服务端向客户端发生响应消息 | |
session | 客户端和服务端的一次会话 | |
application | 可以放全局变量, 用来实现用户间数据共享 | |
config | 服务器配置信息, 可以初始化的参数 | |
out | 向客户端输出内容 | |
page | 当前JSP页面本身, 类似于Java类中的this关键字 | |
exception | 当前一个页面运行过程中发生异常时,就会产生这个对象 |
1. out对象
out.print() 向客户端输出字符串
out.flush() 将缓冲区中的内容输出到客户端
out.clearBuffer() 清除缓冲区中的内容
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>out内置对象</title>
</head>
<body>
<h1>演示out内置对象</h1>
<%
out.println("欢迎大家学习jsp九大内置对象<br/>");
out.flush();
// 页面内容没有发生变化,但是运行过程发生变化
// 先将第一句"欢迎大家学习jsp九大内置对象<br/>" 输出到客户端
// 然后再通过print输出后面的内容
out.print("第一:out对象演示<br/>");
out.print("第二:out对象的方法<br/>");
%>
</body>
</html>
2.request对象
注册页面-JspRegister.jsp
<body>
<form action="JspRegister2.jsp" method="post">
用户名: <input type="text" name="uname"> <br>
密码: <input type="password" name="upwd"> <br>
兴趣: <br>
足球<input type="checkbox" name="hobby" value="足球">
篮球<input type="checkbox" name="hobby" value="篮球">
羽毛球<input type="checkbox" name="hobby" value="羽毛球">
<br>
<input type="submit" value="注册">
</form>
<%--
表单:
用户名 : --- 文本框
密码: --- 密码框
兴趣:足球,篮球,羽毛球 --- 复选框
注册按钮 -- 可以提交
--%>
</body>
接受用户发送的数据–JspRegister2.jsp
<html>
<head>
<title>接收用户提交的数据</title>
</head>
<body>
<%--
用户发送注册请求: request
--%>
<%
// 将请求的编码与页面保持一致,设置为 UTF-8
request.setCharacterEncoding("UTF-8");
// 获取表单中name值为uname元素的 value值
String username = request.getParameter("uname");
// 获取表中name值为 upwd的元素的value值
String userupwd = request.getParameter("upwd");
// String[] hobbies 表示定义String类型的数组, 数组名称为hobbies,数组中的每一个元素必须是String类型
// int[] nums 表示定义 int类型的数组,数组名称为 nums, 数组中的每一个元素必须是int类型
// 获取表单中name值为hobby元素的value数组值
String[] hobbies = request.getParameterValues("hobby");
%>
<p>您注册的信息如下:</p>
用户名:<%=username%> <br>
密码:<%=userupwd%> <br>
爱好:<%
for (int i=0;i<hobbies.length;i++){
out.print(hobbies[i]+" ");
}
%>
<%--
["足球","篮球"]
0 1
--%>
</body>
3.response对象
登录页面
<html>
<head>
<title>登录页面</title>
</head>
<body>
<%--
JspLoginResponse1.jsp--登录页面
JspLoginResponse2.jsp--接收用户登录的信息
success.jsp--登录成功页面
--%>
<form action="JspLoginResponse2.jsp" method="post">
用户名: <input type="text" name="uname"> <br>
密码: <input type="password" name="upwd"> <br>
<input type="submit" value="登录">
</form>
</body>
</html>
接受登录信息
<%
request.setCharacterEncoding("UTF-8");
// 接受用户的登录名
String username = request.getParameter("uname");
// 接收用户登录密码
String userpwd = request.getParameter("upwd");
// 判断用户的用户名和密码是否正确
// 正确 --- 跳转到用户'登录成功'的界面success.jsp
if(username.equals("张三")&&userpwd.equals("abc")){
//跳转到登录成功的页面--通过 response
//response.sendRedirect("success.jsp");
request.getRequestDispatcher("success.jsp").forward(request,response);
}
%>
登录成功页面
<html>
<head>
<title>登录成功的页面</title>
</head>
<body>
<h3>登录成功,欢迎您:
<%
//显示用户的用户名
String username = request.getParameter("uname");
out.print(username); //null
%>
<%--
出现null
原因: 页面跳转的过程中, 数据丢失
解决:
返回RequestDispatcher对象,该对象的forward()方法用于转发请求
request.getRequestDispatcher("success.jsp")
--%>
</h3>
</body>
</html>
重定向和请求转发的区别
请求转发(forward()) | 重定向redirect() | |
---|---|---|
请求服务器的次数 | 1次 | 2次 |
是否保留第一次请求时resquest范围内的属性 | 保留 | 不保留 |
地址栏中的请求URL是否改变 | 不变 | 改变为重定向之后新目标URL,相当于在地址栏中重新输入url后按回车 |
response.getWriter() 与 out.write() 区别
<html>
<head>
<title>response.getWriter与out.write区别</title>
</head>
<body>
<%
// response.getWriter().write("response输出1 <br/>");
// response.getWriter().write("response输出2 <br/>");
// out.write("out输出1<br/>");
// out.write("out输出2<br/>");
%>
<%
out.write("out输出1<br/>");
out.flush();
out.write("out输出2<br/>");
response.getWriter().write("response输出1 <br/>");
response.getWriter().write("response输出2 <br/>");
<%--
当jsp页面所有代码执行完之后会做两个操作:
1.执行out.flush(),将out缓冲区中的内容追加到response缓冲区末尾
2.会执行response的刷新操作,把全部数据写给客户端
--%>
%>
</body>
</html>
4. 四大域对象
pageContext:在当前的jsp页面范围内有效
request:一次请求内有效
session:一次会话范围内有效
application:整个web工程内部有效
作用:对数据进行存储,但是存储的范围不同
<html>
<head>
<title>演示四大域对象</title>
</head>
<body>
<%
//为四个域对象设置值
pageContext.setAttribute("key", "pageContext");
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
%>
<%--将四大域对象的值输出到客户端--%>
pageContext域中是否有值 <%=pageContext.getAttribute("key")%> <br>
request域中是否有值 <%=request.getAttribute("key")%> <br>
seesion域中是否有值 <%=session.getAttribute("key")%> <br>
application域中是否有值 <%=application.getAttribute("key")%> <br>
<%
//pageContext域中是否有值 null
request.getRequestDispatcher("JspDemo9-1.jsp").forward(request, response);
%>
<%--单独请求JspDemo9-1.jsp页面,request域中是否有值 null--%>
<%--关闭浏览器,请求JspDemo9-1.jsp, session域中的值为null--%>
<%--重启服务,直接访问JspDemo9-1.jsp,application域中是否有值 null--%>
</body>
</html>
5. session 和 cookie
1.cookie
会话
:用户打开浏览器, 访问web服务器的资源, 会话建立,直到有一方断开连接, 会话结束; 在一次会话中, 可以包含多次请求和响应
会话跟踪技术
: 一种维护浏览器状态的方法, 服务器需要识别多次请求是否来自同一个浏览器,以便在同一会话的多次请求中共享数据
客户端会话跟踪技术: Cookie
服务端会话跟踪技术: Session
2.Cookie的基本使用
Cookie:是一个客户端的会话技术,将数据保存都客户端, 以后每次请求都携带Cookie数据进行访问
发送Cookie
1.创建Cookie对象, 设置数据
Cookie cookie = new Cookie(“key”,“value”)
2.发送Cookie到客户端, 使用response对象
response.addCookie(cookie);
获取Cookie
1.获取客户端所携带的所有的Cookie.使用 request对象
Cookie[] cookies = request.getCookies();
2.遍历数组,获取每一个Cookie对象:for
3.使用Cookie对象获取数据
cookie.getName()
cookie.getValue()
3.Cookie的原理
Cookie是基于HTTP协议实现的
- 响应头: set-cookie
- 请求头: cookie
Cookie使用细节
- Cookie存活时间:
默认情况下, Cookie保存在浏览器中, 当浏览器关闭, 内容释放, 则Cookie被销毁
setMaxAge(int seconds) 设置Cookie存活时间
正数: 将Cookie写入浏览器所在电脑的硬盘,持久化存储, 到时间自动删除
负数: 默认值, Cookie存储在当前浏览器内存中, 当浏览器关闭,则Cookie销毁
零: 删除当前Cookie- cookie存储中文
cookie不能直接存储中文
如果需要存储, 需要进行转码, URL编码
setCookie
<html>
<head>
<title>设置cookie</title>
</head>
<body>
<%
//存储中文需要转码
String value = "张三";
URLEncoder.encode(value, "UTF-8");
System.out.println("存储数据:"+value);
//1.创建cookie对象
Cookie cookie = new Cookie("username",value);
// 设置cookie存活时间 (7天)
cookie.setMaxAge(7*24*60*60);
//2.发送Cookie
response.addCookie(cookie);
%>
</body>
</html>
getCookie
<html>
<head>
<title>获取Cookie</title>
</head>
<body>
<%
//1. 获取cookie
Cookie[] cookies = request.getCookies();
//System.out.println(cookies); //数组的地址
//[{username:zs},{JSESSIONID:C7D8B4EE1C6F3B491D0FBF1096916412}]
//2. 遍历数组,获取每一个cookie的值 -- for
for(Cookie cookie:cookies){
String name=cookie.getName(); // username
if ("username".equals(name)){
String value = cookie.getValue();
System.out.println(name+":"+value);
break;
}
}
%>
</body>
</html>
2.Session
服务器端的会话跟踪技术, 将数据保存到服务器端
1.获取session对象
HttpSession session1 = request.getSession();
2. Session对象的功能
void setAttribute(String name,Object:o): 存储数据到Session中
Object getAttribute(String name): 根据Session的key,获取值
void removeAttribute(String name): 根据key,删除该键值对
<html>
<head>
<title>存储数据到session中</title>
</head>
<body>
<%
//1.获取Session对象
HttpSession session1 = request.getSession();
//2.为Session对象存值
session1.setAttribute("username","ls");
%>
</body>
</html>
<html>
<head>
<title>获取Session中的数据</title>
</head>
<body>
<%
//1.获取Session对象
HttpSession session1 = request.getSession();
//2.获取Session对象中的值
Object name = session1.getAttribute("username");
System.out.println(name);
%>
</body>
</html>
总结-session和cookie异同
相同点: 两者都是一种记录用户状态的的机制, 都是为了减少客户端和服务器端之间传输的冗余数据, 提高两者之间的传输速率
不同点
- cookie可以存在浏览器或者本地,Session只能存在服务器端
- Session比Cookie更具有安全性(Cookie有安全隐患, 通过拦截或者本地文件中找到cookie后进行攻击)
- Session占据服务器性能, Session过多, 增加服务器压力
- Session可以存贮任意java对象, Cookie只能存储String类型的对象
- 单个Cookie保存数据不能超过4k,很多浏览器限制一个站点最多保存20个Cookie,但是Session是没有大小限制的,只和服务器的内存有关
二.JSP连接数据库
# mysql数据的命令
-- mysql -uroot -proot #进入数据库
-- show databases; #查看数据库
-- use 数据库名; #使用数据库
-- show tables; #查看数据库表
-- select * from account; #查询数据库表
CREATE DATABASE javaweb2305 CHARSET UTF8;
USE javaweb2305;
DROP TABLE IF EXISTS account;
# 创建数据库表
CREATE TABLE account(
id accountint PRIMARY KEY AUTO_INCREMENT,
uname VARCHAR(10),
money DOUBLE(10,2)account
);
#插入数据account
INSERT INTO account(uname,money) VALUES('zs',1000),('ls',1000);
在idea中连接数据库
演示JDBC连接数据库
//演示JDBC连接数据库
public class JDBCDemo1 {
public static void main(String[] args) throws Exception {
//1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2. 获取数据库链接
String url="jdbc:mysql://127.0.0.1:3306/javaweb2305";
String username="root";
String password="root";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 定义SQL
String sql = "UPDATE account set money=3000 WHERE id=1;";
//4. 执行sql -- 获取执行sql语句的对象
Statement stmt = conn.createStatement();
//5. 执行sql语句
int count = stmt.executeUpdate(sql);
//6. 判断是否执行成功
System.out.println(count);//1
//7. 释放资源
stmt.close();
conn.close();
}
}
2.1 JDBC概念
JDBC是使用java语言操作数据的一套API
本质: 官方定义了一套操作所有关系型数据库的规则,即 接口
我们可以使用这套接口编程, 真正执行的代码是驱动包中的实现类
使用步骤:
- 注册驱动: Class.forName(“com.mysql.jdbc.Driver”);
- 获取连接: Connection conn = DriverManager.getConnection(url, username, password);
- 定义SQL语句: String sql = “UPDATE account set money=3000 WHERE id=1”;
- 获取执行sql语句的对象: Statement stmt = conn.createStatement();
- 执行SQL : int count = stmt.executeUpdate(sql);
- 处理返回结果
- 释放资源
2.2 JDBC API详解
DriverManager
Connection
Statement
ResultSet
PrepareStatment
1. DriverManager
1.注册驱动:
Class.forName(“com.mysql.jdbc.Driver”);
提示:
如果MYSQL 5之后的驱动包, 可以省略注册的步骤
自动加载jar包中 META-INF/services/java.sql.Driver文件中的驱动类
2.获取数据库连接
static Connection getConnection(String url,String user, String password)
参数:
- url: 连接地址
- 语法: jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2
- jdbc:mysql//127.0.0.1:3306/javaweb2305
- 注意:
- 如果连接的是本地mysql服务器, 并且服务器默认端口是3306, URL可以简写: jdbc:/mysql:///数据库名称?参数键值对
配置useSSL=false参数, 禁用安全连接方式
- user: 连接数据库用户名
- password: 连接数据库用户密码
2. Connection
Connection(数据库连接对象) 作用:
- 获取执行SQL的对象
- 普通执行SQL对象 : Statement createStatement()
- 预编译SQL的执行对象: 防止SQL注入 PreparedStatement preparedStatement ()
- 执行存储过程的对象: CallableStatement prepareCall(sql)
- 管理事务
- mysql事务管理:
开启事务: BEGIN;
提交事务: COMMIT;
回滚事务: ROLLBACK;- JDBC事务管理:
开启事务:setAutoCommint(boolean true) – true:自动提交事务; false手动提交事务–开启事务
提交事务:commit()
回滚事务:rollback()
/**
* 演示 Statement
*/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo3_Statement {
public static void main(String[] args) throws Exception {
// 1.注册驱动
// Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接对象
String url = "jdbc:mysql:///javaweb2306?useSSL=false";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
// 3. 定义SQL
String sql1 = "UPDATE account set money=3000 WHERE id=1";
String sql2 = "UPDATE account set money=5000 WHERE id=2";
// 4. 获取执行sql语句的对象
Statement stmt = conn.createStatement();
// 5.执行sql -- 返回数据
// 两条sql,要么同时成功,要么同时失败
// 需要用事务管理起来, 在sql语句执行之前 开启事务
// 使用try/catch 实现事务的回滚
try {
//开启事务
conn.setAutoCommit(false);
// 执行sql1和sql2语句
int count1 = stmt.executeUpdate(sql1);
System.out.println(count1);
// 造一个异常
//int i = 3/0;
int count2 = stmt.executeUpdate(sql2);
System.out.println(count2);
//提交事务
conn.commit();
}catch(SQLException throwables){
conn.rollback();
throwables.printStackTrace();
}
// 7. 释放资源
stmt.close();
conn.close();
}
}
补充: 事务
概念 :数据库事务是一种机制, 一个操作序列, 包含了一组数据库操作的指令
事务把所有的命令作为一个整体向系统提交或撤销操作请求, 即 这一组数据库的命令要么同时成功,要么同时失败
事务是一个不可分割的逻辑单元
3. Statement
Statement作用: 执行SQL语句
执行SQL语句:
- int excuteUpdate(sql) : 执行DML,DDL语句
返回值:
– (1) DML语句影响的行数
– (2) DDL语句执行后, 执行成功也可能返回0;- ResultSet excuteQuery(sql):执行DQL语句
– 返回值: ResultSet结果集对象
数据库:
DDL: 对表
和库
执行 增改操作,涉及的关键字CREATE、ALTER、DROP、SHOW
DML: 对数据表
的增删改操作,涉及的关键字:INSERT UPDATE DELETE
DQL: 对数据的查询
操作,涉及关键字:SELECT
# DDL 对数据库对象进行操作的语言
SHOW DATABASES ;
CREATE database mydb2305 CHARSET =UTF8;
SHOW CREATE DATABASE mydb2305;
USE mydb2305;
DROP DATABASE mydb2305;
# DDL 对数据库表对象进行操作的语言
CREATE TABLE stu( id INT);
SHOW TABLES;
DESC stu;
SHOW CREATE TABLE stu;
RENAME TABLE stu TO student;
DROP TABLE stu;
# DML语言: DML是对表中数据 进行操作的语言,涉及的关键字:INSERT UPDATE DELETE
INSERT INTO stu values (1);
UPDATE stu set id=2 WHERE id=1;
DELETE FROM stu WHERE id=1;
# DQL语句 查询语句
SELECT * FROM stu;
// 执行DML语句
@Test
public void testDML() throws Exception{
// 1.注册驱动
// Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接对象
String url = "jdbc:mysql:///javaweb2306?useSSL=false";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
// 3. 定义SQL -- 执行DML语句
String sql = "UPDATE account set money=1000 WHERE id=1";
// 4. 获取执行sql语句的对象
Statement stmt = conn.createStatement();
// 5.执行sql -- 返回数据 int
int count = stmt.executeUpdate(sql);
System.out.println(count);
// 7. 释放资源
stmt.close();
conn.close();
}
// 执行DDL语句
@Test
public void testDDL() throws Exception{
// 1.注册驱动
// Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接对象
String url = "jdbc:mysql:///javaweb2306?useSSL=false";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
// 3. 定义SQL -- 执行DDL语句
String sql = "CREATE DATABASE mydb2306 CHARSET=UTF8";
// 4. 获取执行sql语句的对象
Statement stmt = conn.createStatement();
// 5.执行sql -- 执行DDL语句,返回数据 int
int count = stmt.executeUpdate(sql);
// 6.判断执行是否成功
if(count>0){
System.out.println("数据库创建成功");
}else{
System.out.println("数据库创建失败");
}
// 7. 释放资源
stmt.close();
conn.close();
}
**4. ResultSet **
获取查询的结果
- boolean next(): (1) 将光标放在当前位置的前一行 (2)判断当前行是否为有效行
返回值: true 有效行, 当前行有数据
false 无效行. 当前行没有数据- xx getxxx(参数): 获取数据
xxx : 数据类型; 比如: int getInt(参数); String getString(参数)
参数:
int:列的编号, 从1开始
String: 列的名称
@Test
public void testDQL() throws Exception{
// 2.获取连接对象
String url = "jdbc:mysql:///javaweb2306?useSSL=false";
String username = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, username, password);
// 3. 定义SQL -- 执行DQL语句-查询
String sql = "SELECT * FROM account";
// 4. 获取执行sql语句的对象
Statement stmt = conn.createStatement();
// 5.执行sql -- 执行DQL语句,返回值ResultSet
ResultSet rs = stmt.executeQuery(sql);
// rs是一个结果集对象, 打印出来是一个对象地址
// 6.判断执行是否成功
// System.out.println(rs);
while(rs.next()){
// 获取数据库内容
int id = rs.getInt(1);
System.out.println(id);// 1,2
String uname = rs.getString(2);
System.out.println(uname);//zs,ls
String uname1 = rs.getString("uname");
System.out.println(uname1);
// money
double money = rs.getDouble(3);
double money1 = rs.getDouble("money");
}
// 7. 释放资源
stmt.close();
conn.close();
}
5.PreparedStatement
PreparedStatement作用: 预编译SQL语句并执行, 预防SQL注入问题
SQL注入: 是通过操作输入来修改实现定义好的SQL语句, 用以达到执行代码对服务器进行攻击的方法
@Test
// 演示登录操作
public void testLogin() throws SQLException {
//2. 获取数据库链接
String url="jdbc:mysql:///javaweb2305?useSSL=false";
String username="root";
String password="root";
Connection conn = DriverManager.getConnection(url, username, password);
String uname="zs"; //abc
String upwd="'or'1'='1"; //特定的字符
//3. 定义SQL
String sql = "SELECT * FROM student where uname='"+uname+"' and upwd='"+upwd+"'";
/**
* SQL注入原因:
* 当前SQL语句:SELECT * FROM student where uname='zs' and upwd=''or'1'='1'"
* uname='zs' and upwd='' true and false = false
* '1'='1' 结果true
* false or true ===> true
* 所以 where条件为true
* 所以 可以查询出所有的数据
*/
//4. 执行sql -- 获取执行sql语句的对象
Statement stmt = conn.createStatement();
//5. 执行sql语句
ResultSet rs = stmt.executeQuery(sql);
//6. 判断是否执行成功
if (rs.next()){
System.out.println("登陆成功");
}else{
System.out.println("登录失败");
}
//7. 释放资源
stmt.close();
conn.close();
}
解决SQL注入步骤
1.获取PreparedStatement对象
- SQL语句中的参数值,用 ? 占位符代替
String sql = “SELECT * FROM student where uname=? and upwd=?”;- 通过conn获取prepareStatement对象,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);2.设置参数值
- PreparedStatement对象: setXXX(参数1,参数2): 给占位符 ? 赋值
xxx: 数据类型,如setString(参数1,参数2)
参数:
- 参数1: ?的位置编号,从1开始
- 参数2: ?的值3.执行SQL
- excuteUpdate() / excuteQuery()
// 解决sql注入
public void testLoginSql() throws SQLException {
//2. 获取数据库链接
String url="jdbc:mysql:///javaweb2305?useSSL=false";
String username="root";
String password="root";
Connection conn = DriverManager.getConnection(url, username, password);
String uname="zs"; //abc
String upwd="abc"; //特定的字符
//3. 定义SQL--SQL语句中的参数,用 ? 占位符代替
String sql = "SELECT * FROM student where uname=? and upwd=?";
//4. 执行sql -- 获取prepareStatement对象,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);
// 设置参数 setInt(参数1,参数2); setString(参数1,参数2)
// 参数1: ?的位置编号, 从 1 开始
// 参数2: ?的值
pstmt.setString(1,uname);//设置用户名
pstmt.setString(2, upwd);//设置密码
//5. 执行sql语句 executeQuery()/excuteUpdate()
ResultSet rs = pstmt.executeQuery();
//6. 判断是否执行成功
if (rs.next()){
System.out.println("登陆成功");
}else{
System.out.println("登录失败");
}
//7. 释放资源
pstmt.close();
conn.close();
}
JDBC
mysql 或者 MariaDB10.5
可视化工具 HS, SQLyag, Navicate
mysql-conn.jar – qq群获取
create database db charset=“UTF8”
create table student(
id int,
username char(20)
password char(20)
)
inset
update
delete
select