JDBC
概念:Java Database Connectivity ,Java数据库连接,即Java语言操作数据库
JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类
步骤
- 导入驱动jar包
- 注册驱动
- 获取数据库连接对象 Connection
- 定义sql
- 获取执行sql语句的对象 Statement
- 执行sql,接收返回结果
- 处理结果
- 释放资源
import java.sql.*;
/**
* @Author: 2019012364 袁梦达 3班
*/
public class JdbcDemo01 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf-8&useSSL=false", "root", "root");
String sql = "insert into account values(5, 'ego', 2000)";
statement = connection.createStatement();
int count = statement.executeUpdate(sql);
System.out.println(count);
if(count > 0){
System.out.println("打印成功!");
}else {
System.out.println("打印失败!");
}
} catch (ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
if (statement != null) {
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
DriverManager:驱动管理对象
功能:
-
注册驱动:告诉程序该使用哪一个数据库驱动jar
static void registerDriver(Driver driver):注册与给定的驱动程序DriverManager
写代码使用:Class.forName(“com.mysql.jdbc.Driver”);
因为com.mysql.jdbc.Driver类中存在静态代码块
static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } }
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤
-
获取数据库连接
方法:static Connection getConnection(String url, String user, String password)
参数:
-
url:指定连接的路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
例子:jdbc:mysql://localhost:3306/db3
细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则可以简写为jdbc:mysql:///数据库名称
-
user:用户名
-
password:密码
-
Connection:数据库连接对象
功能:
- 获取执行sql对象
- Statement createStatement( )
- PreparedStatement preparedStatement(String sql)
- 管理事务
- 开启事务: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)语句
返回值:影响的行数,可以通过影响的行数判断DML是否执行成功
-
ResultSet executeQuery(String sql):执行DQL(select)语句
ResultSet:结果集对象
-
boolean next( ):游标向下移动一行
-
getXxx( 参数):获取数据,Xxx代表数据类型
参数:
- int:代表列的编号,从1开始
- String:代表列的名称
import java.sql.*;
/**
* @Author: 2019012364 袁梦达 3班
*/
public class JdbcDemo01 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql:///db1?useUnicode=true&characterEncoding=utf-8&useSSL=false", "root", "root");
String sql = "select * from account";
statement = connection.createStatement();
rs = statement.executeQuery(sql);
rs.next();
int id = rs.getInt("id");
String name = rs.getString("name");
int money = rs.getInt("money");
System.out.println(id + "----" + name + "-----" + money);
} catch (ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
if (statement != null) {
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
PreparedStatement:执行sql的对象
-
SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接,会造成安全性问题
例如:随便输入用户名,密码输入’a’ or ‘a’ = ‘a’,则sql语句为:select * from user where username = ‘fdsff’ and password = ‘a’ or ‘a’ = ‘a’
-
解决sql注入问题:使用PreparedStatement对象
-
预编译的SQL:参数使用?作为占位符
-
步骤:
-
导入驱动jar包
-
注册驱动
-
获取数据库连接对象 Connection
-
定义sql
- 注意:sql的参数使用?作为占位符。如:select * from user where username = ? and password = ?
-
获取执行sql语句的对象 PreparedStatement:Connection.preparedStatement(String sql)
-
给?赋值
方法:setXxx(参数1, 参数2)
参数1:?的位置编号,从1开始
参数2:?的值
-
执行sql,接收返回结果,不需要传递sql语句
-
处理结果
-
释放资源
-
JDBC工具类
目的:抽取共性方法,简化书写
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
/**
* @Author: 2019012364 袁梦达 3班
*/
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
/**
* 文件的读取,只需执行一次即可拿到这些值,使用静态代码块
*/
static {
//读取资源文件获取值
try{
//1.创建Properties集合
Properties pro = new Properties();
//获取src路径下文件的方式----ClassLoader类加载器
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
URL resource = classLoader.getResource("jdbc.properties");
String path = resource.getPath();
//2.加载文件
pro.load(new FileReader(path));
//3.获取数据,赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//4.注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取连接
* @return 连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
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 throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
/**
* 释放资源
* @param stmt
* @param conn
* @param rs
*/
public static void close(Statement stmt, Connection conn, ResultSet rs){
if(stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
import java.sql.*;
/**
* @Author: 2019012364 袁梦达 3班
*/
public class JdbcDemo01 {
public static void main(String[] args) {
Connection conn= null;
Statement statement = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
String sql = "select * from account";
statement = conn.createStatement();
rs = statement.executeQuery(sql);
while (rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
int money = rs.getInt("money");
System.out.println(id + "----" + name + "-----" + money);
}
}catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JDBCUtils.close(statement, conn, rs);
}
}
}
数据库连接池
概念
其实就是一个容器(集合),存放数据库连接的容器。
当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户访问数据库时,从容器中获取连接对象用户访问完之后,会将连接对象归还给容器。
好处:节约资源,用户访问高效
实现
-
标准接口:DataSource javax.sql包下的
方法:
- 获取连接:getConnection( )
- 归还连接:Connection.close( )。如果连接对象Connection是从连接池中获取的,那么调用close( )方法不会关闭连接,而是归还连接
-
一般我们不去实现它,由数据库厂商来实现
- C3P0:数据库连接池技术
- Druid:数据库连接池实现技术,由阿里巴巴提供
C3P0
步骤:
- 导入jar包
- 定义配置文件:
- 名称:c3p0.properties 或者 c3p0-config.xml
- 路径:直接将文件放在src目录下即可
- 创建核心对象:数据库连接池对象 ComboPooledDataSource
- 获取连接:getConnection
Druid
步骤:
- 导入jar包
- 定义配置文件:
- 是properties形式的
- 可以叫任意名称,可以放在任意目录下
- 加载配置文件
- 获取数据库连接池对象:通过工厂类来获取 DruidDataSourceFactory
- 获取连接:getConnection
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
/**
* @Author: 2019012364 袁梦达 3班
*/
public class DruidDemo {
public static void main(String[] args) throws Exception {
//1.加载配置文件
Properties pro = new Properties();
InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//2.获取数据库连接池对象
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
//3.获取连接
Connection conn = ds.getConnection();
System.out.println(conn);
}
}
Druid连接池工具类
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* @Author: 2019012364 袁梦达 3班
*/
public class DruidUtils {
private static DataSource ds;
static {
try {
//1.加载配置文件
Properties pro = new Properties();
pro.load(DruidUtils.class.getClassLoader().getResourceAsStream("druid.propertis"));
//2.获取DataSource
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* 释放资源
*/
public static void close(Statement stmt, Connection conn){
if(stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void close(Statement stmt, Connection conn, ResultSet rs){
if(stmt != null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
/**
* 获取连接池
*/
public static DataSource getDataSource(){
return ds;
}
}
JdbcTemplate
Spring框架对JDBC简单封装,提供了一个JdbcTemplate对象简化JDBC的开发
步骤:
-
导入jar包
-
创建JdbcTemplate对象,依赖于数据源DataSource
JdbcTemplate template = new JdbcTemplate(ds);
-
使用JdbcTemplate方法来完成CRUD的操作
-
update( ):执行DML(增删改)语句
-
queryForMap( ):查询结果将结果集封装为map集合。将列名作为key,将值作为value。注意:这个方法查询的结果集长度只能是1,即只能查询一行
-
queryForList( ):查询结果将结果集封装为list集合。将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
-
query( ):查询结果将结果封装为JavaBean对象。
query参数:RowMapper
一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装。
new BeanPropertyRowMapper<类名>(类名.class)
-
queryForObject( ):查询结果将结果封装为对象
一般用于聚合函数的查询
-
XML
概述
-
概念:Extensible Markup Langu 可扩展标记语言
可扩展:标签都是自定义的。
-
功能:
存储数据
- 配置文件
- 在网络中传输
-
与html的区别:
- xml标签都是自定义的,html标签都是预定义的
- xml语法严格,html语法松散
- xml是存储数据的,html是展示数据的
语法
-
基本语法
- xml文档的后缀名 .xml
- xml第一行必须定义为文档声明
- xml文档中有且仅有一个根标签
- 属性值必须使用引号(单双都可以)引起来
- 标签必须正确关闭
- xml标签名称区分大小写
-
快速入门
<?xml version='1.0' ?> <users> <user id='1'> <name>zhangsan</name> <age>18</age> </user> <user id='2'> <name>lisi</name> <age>18</age> </user> </users>
-
组成部分
-
文档声明
-
格式:<?xml 属性列表 ?>
-
属性列表:
-
version:版本号,必须写的属性
-
encoding:编码方式。告知解析引擎当前文档使用的字符集,默认值:IOS-8859-1
-
standalone:是否独立
取值:
yes:不依赖其他文件
no:依赖其他文件
-
-
-
指令:结合CSS
<?xml-stylesheet type="text/css" href="a.css" ?>
-
标签:标签名称自定义的
规则:
- 名称可以含字母、数字以及其他的字符
- 名称不能以数字或者标点符号开始
- 名称不能以字符 “xml”(或者 XML、Xml)开始
- 名称不能包含空格
-
属性:id属性值唯一
-
文本:
CDATA区:在该区域中的数据会被原样展示
格式:<![CDATA[ 数据 ]]>
-
文本
-
约束
概念:规定xml文档的书写规则
分类:
1. DTD:一种简单的约束技术
2. Schema:一种复杂的约束技术
DTD:
- 引入dtd文档到xml文档中
- 内部dtd:将约束规则定义在xml文档中
- 外部dtd:将约束规则定义在外部的dtd文件中
- 本地:
- 网络:
解析
概念:操作xml文档,将文档中的数据读取到内存中
操作xml文档:
- 解析(读取):将文档中的数据读取到内存中
- 写入:将内存中的数据保存到xml文档中。持久化的存储
解析xml的方式:
-
DOM:将标记语言文档一次性加载进内存,在内存中形成一颗DOM树
优点:操作方便,可以对文档进行CRUD的所有操作
缺点:占内存
-
SAX:逐行读取,基于事件驱动的。
优点:不占内存
缺点:只能读取不能增删改
xml常见的解析器:
- JAXP:sun公司提供的解析器,支持dom和sax
- DOM4J:一款非常优秀的解析器
- Jsoup
- PULL:Android操作系统内置的解析器,sax方式
Jsoup
步骤:
- 导入jar包
- 获取Document对象
- 获取对应的标签(Element对象)
- 获取数据
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;
/**
* @Author: 2019012364 袁梦达 3班
*/
public class JsoupDemo {
public static void main(String[] args) throws IOException {
String path = JsoupDemo.class.getClassLoader().getResource("a.xml").getPath();
Document document = Jsoup.parse(new File(path), "GBK");
Elements elements = document.getElementsByTag("name");
Element element = elements.get(0);
System.out.println(element.text());
}
}
对象:
-
Jsoup:工具类,可以解析html或xml文档,返回Document
parse:解析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对象
getElementById(Stirng id):根据id属性值获取唯一的element对象
getElementByTag(String tagName):根据标签名获取元素对象集合
getElementByAttribute(String key):根据属性名获取元素对象集合
getElementByAttributeValue(String key,String value):根据属性名和shu’xing值获取元素对象集合
-
Elements:元素Element对象的集合。可以当作ArrayList来使用
-
Element:元素对象
-
获取子元素对象
getElementById(Stirng id):根据id属性值获取唯一的element对象
getElementByTag(String tagName):根据标签名获取元素对象集合
getElementByAttribute(String key):根据属性名获取元素对象集合
getElementByAttributeValue(String key,String value):根据属性名和shu’xing值获取元素对象集合
-
获取属性值
String attr(String key):根据属性名称获取属性值
-
获取文本内容
String text( ):获取纯文本内容
String html( ):获取标签体的所有内容(包括子标签的标签和文本内容)
-
-
Node:节点对象
是Document和Element的父类
快捷查询方式
-
selector:选择器
方法:Element select(String cssQuery)
参数的语法和css的选择器一样
-
XPath:
-
JXDocument jxDocument = new JXDocument(document);
-
根据XPath语法查询。
-
Tomcat
服务器:安装了服务器软件的计算机
服务器软件:接收用户的请求,处理请求,做出响应
web服务器软件:接收用户的请求,处理请求,做出响应,可以部署web项目,让用户通过浏览器来访问这些项目
常见的java相关的web服务器软件:
- webLogic:oracle公司,大型的JavaEE服务器,支持所有JavaEE规范
- webSphere:IBM公司
- JBOSS:JBOSS公司
- Tomcat:Apache基金组织,中小型的JavaEE服务器,仅仅支持少量的JavaEE规范,开源的。
配置:
部署项目的方式:
-
直接将项目放到webapps目录下即可
简化部署:将项目打成一个war包,再将war包放置webapps目录下,war包会自动解压缩
- 配置conf\server.xml文件
在标签体中配置
docBase:项目存放的路径
path:虚拟目录
- 在conf\Ctalina\localhost创建任意名称的xml文件。在文件中编写
虚拟目录:xml文件的名称
java动态项目的目录结构:
--项目的根目录
--WEB-INF目录
--web.xml:web项目的核心配置文件
--classes目录:放置字节码文件的目录
--lib目录:放置依赖的jar包
Servlet
概念:全称server applet,运行在服务端的小程序。Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则
步骤:
-
创建JavaEE项目
-
定义一个类,实现Servlet接口
-
实现接口中的抽象方法
-
配置Servlet
<servlet> <servlet-name>demo</servlet-name> <servlet-class>ServletDemo</servlet-class> </servlet> <servlet-mapping> <servlet-name>demo</servlet-name> <url-pattern>/demo</url-pattern> </servlet-mapping>
执行原理:
- 当服务器接收到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
- 查找web.xml文件是否有对应的标签体内容
- 如果有,则会找到对应的全类名
- tomcat会将字节码文件加载进内存,并且创建其对象
- 调用其方法
Servlet的生命周期
-
被创建:执行init方法,只执行一次
Servlet什么时候被创建?
-
默认情况下,第一次被访问时Servlet被创建
-
可以配置执行Servlet的创建时机,在标签下配置
-
第一次被访问时创建
的值为负数
-
在服务器启动时创建
的值为0或正整数
-
Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
- 多个用户同时访问时可能存在线程安全问题
- 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对其修改值
-
-
提供服务:执行service方法,执行多次
-
被销毁:执行destroy方法,只执行一次
只有服务器正常关闭时,才会执行destroy方法(在Servlet被销毁前执行,释放资源)
Servlet3.0:
好处:支持注解配置,不需要web.xml
在类上使用@WebServlet注解,进行配置:@WebServlet(“资源路径”)
Servlet体系结构:
Servlet ---- 接口
|
GenericServlet ---- 抽象类
|
HttpServlet ---- 抽象类
-
GenericServlet:将Servlet接口中的其他方法做了默认的空实现,只将service( )方法作为抽象。
将来定义Servlet类时,可以继承GenericServlet,实现service( )方法即可
-
HttpServlet:对Http协议的一种封装,简化操作
- 定义类继承HttpServlet
- 复写doGet/doPost方法
Servlet相关配置:
- urlpartten:Servlet访问路径
- 一个Servlet可以定义多个访问路径:@WebServlet({"/a", “/b”, “/c”})
- 路径定义规则:
- /xxx
- /xxx/xxx:多层路径,目录结构
- *.do
Request
-
request对象和response对象的原理
- request和response对象是由服务器创建的。我们来使用它们
- request对象是来获取请求消息,response对象是来设置响应消息
-
request继承体系结构:
ServletRequest ---- 接口
| 继承
HttpServletRequest ---- 接口
| 实现
RequestFacade ---- 类(tomcat)
-
request功能:
-
获取请求消息数据
-
获取请求行数据
-
GET /day14/demo?name=zhangsan HTTP/1.1
-
方法:
-
获取请求方式:GET
String getMethod( )
-
获取虚拟目录:/day14
String getContextPath( )
-
后获取Servlet路径:/demo
String getServletPath( )
-
获取get方式请求参数:name=zhansan
String getQueryString( )
-
获取请求URI:
String getRequestURI( ):/day14/demo
StringBuffer getRequestURL( ): http://localhost/day14/demo
-
获取协议及版本:HTTP/1.1
String getProtocol( )
-
获取客户机的IP地址:
String getRemoteAddr( )
-
-
-
获取请求头数据
方法:
- String getHeader(String name):通过请求头的名称获取请求头的值
- Enumeration getHeaderNames( ):获取所有的请求头名称
-
获取请求体数据:
只有POST请求方式才有请求体,在请求体中封装了POST请求的请求参数
步骤:
- 获取流对象
- BufferedReader getReader( ):获取字符输入流,只能操作字符数据
- ServletInputStream getInputStream( ):获取字节输入流,可以操作所有类型数据
- 再从流对象中拿数据
- 获取流对象
-
-
其他功能
-
获取请求参数通用方式:无论get还是post请求方式都可以使用下列方式来获取请求参数
- String getParameter(String name):根据参数名称获取参数值
- String[ ] getParameterValues(String name):根据参数名称获取参数值的数组
- Enumertation getParameterNames( ):获取所有请求的参数名称
- Map<String , String[ ]> getParameterMap( ):获取所有参数的Map集合
中文乱码问题:
-
get方式:tomcat 8已经将get方式乱码问题解决了
-
post方式:会乱码
解决:在获取参数前,设置request的编码
request.setCharacterEncoding(“utf-8d”)
-
请求转发:一种在服务器内部的资源跳转方式
- 步骤:
- 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
- 特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器的内部资源中
- 转发是一次请求
- 步骤:
-
共享数据:
域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
- setAttribute(String name, Object obj):存储数据
- getAttribute(String name):通过键获取值
- removeAttribute(String name):通过键移除键值对
-
获取ServletContext:
-
概念:代表整个web应用,可以和程序的容器(服务器)来通信
-
获取:
- 通过request对象获取:request.getServletContext( )
- 通过HttpServlet获取:this.getServletContext( )
-
功能:
-
获取MIME类型:
MIME类型:在互联网通信过程中定义的一种文件类型数据
格式:大类型/小类型 text/html image/jpeg
获取:String getMimeType(String file)
-
域对象:共享数据
- setAttribute(String name, Object value)
- getAttribute(String name)
- removeAttribute(String name)
ServletContext对象范围:所有用户所有请求数据
-
获取文件的真实(服务器)路径
方法:String getRealPath(String path)
-
-
-
-
BeanUtils工具类,简化数据封装
-
用于封装JavaBean
-
JavaBean:标准的Java类
- 要求:
- 类必须被public修饰
- 必须提供空参的构造器
- 成员变量必须使用private修饰
- 提供公共的setter和getter方法
- 功能:封装数据
- 要求:
-
概念:
成员变量
属性:setter和getter方法截取后的产物
例如:getUsername( ) --> Username --> username
-
方法:
- setProperty( )
- getProperty( )
- populate(Object obj, Map map):将map集合的键值对信息,封装到对应的JavaBean对象中
-
Response
功能:设置响应消息
-
设置响应行
- 格式:HTTP/1.1 200 ok
- 设置状态码:setStatus(int sc)
-
设置响应头:setHeader(String name, String value)
-
设置响应体:
使用步骤:
-
获取输出流
字符输出流:PrintWriter getWriter( )
字节输出流:ServletOutputStream getOutputStream( )
-
使用输出流将数据输出到客户浏览器
-
案例:
-
完成重定向:资源跳转的方式
// //访问Demo1,会自动跳转到Demo2 // System.out.println("Demo1......"); // //1.设置状态码302 // resp.setStatus(302); // //设置响应头 // resp.setHeader("location", "/ResponseDemo2"); //简化写法 resp.sendRedirect("/ResponseDemo2");
重定向的特点:
- 地址栏发生变化
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求,不可以使用request对象共享数据
转发的特点:
- 转发地址栏路径不变
- 转发只能访问当前服务器下的资源
- 转发是一次请求,可以使用request对象共享数据
路径写法:
- 路径的分类
- 相对路径
- 绝对路径:建议虚拟目录动态获取:request.getContextPath( )
-
服务器输出字符数据到浏览器
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * @author 86156 */ @WebServlet("/ResponseDemo3") public class ResponseDemo3 extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // //设置编码 可以不写 // resp.setCharacterEncoding("utf-8"); // //告诉浏览器编码,并建议浏览器使用该编码 // resp.setHeader("content-type", "text/html;charset=utf-8"); //简化写法 resp.setContentType("text/html;charset=utf-8"); //获取字符输出流 PrintWriter writer = resp.getWriter(); //输出数据 writer.write("你好Ego"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } }
-
服务器输出字节数据到浏览器
import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * @author 86156 */ @WebServlet("/ResponseDemo4") public class ResponseDemo4 extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); ServletOutputStream os = resp.getOutputStream(); os.write("你好Ego".getBytes("utf-8")); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } }
-
验证码
import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; @SuppressWarnings("all") /** * @author 86156 */ @WebServlet("/checkcode") public class CheckCode extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { int height = 50; int width = 100; //1.创建图片对象 BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //2.美化图片 //2.1填充背景色 Graphics g = img.getGraphics(); //画笔对象 g.setColor(Color.PINK); //设置画笔颜色 g.fillRect(0, 0, width, height); //2.2画边框 g.setColor(Color.BLUE); g.drawRect(0, 0, width - 1, height - 1); //2.3写验证码 String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; Random random = new Random(); for(int i = 1; i <= 4; i++){ int index = random.nextInt(str.length()); char ch = str.charAt(index); g.drawString(ch + "", width / 5 * i, height / 2); } //2.4画干扰线 g.setColor(Color.GREEN); for(int i = 0; i < 10; i++){ int x1 = random.nextInt(width); int x2 = random.nextInt(width); int y1 = random.nextInt(height); int y2 = random.nextInt(height); g.drawLine(x1, y1, x2, y2); } //3.输出到页面中 ImageIO.write(img, "jpg", resp.getOutputStream()); } }
##ServletContext
-
概念:代表整个web应用,可以和程序的容器(服务器)来通信
-
获取:
- 通过request对象获取:request.getServletContext( )
- 通过HttpServlet获取:this.getServletContext( )
-
功能:
-
获取MIME类型:
MIME类型:在互联网通信过程中定义的一种文件类型数据
格式:大类型/小类型 text/html image/jpeg
获取:String getMimeType(String file)
-
域对象:共享数据
- setAttribute(String name, Object value)
- getAttribute(String name)
- removeAttribute(String name)
ServletContext对象范围:所有用户所有请求数据
-
获取文件的真实(服务器)路径
方法:String getRealPath(String path)
-
会话技术
- 会话:一次会话中包含多次请求和响应
- 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
- 功能:在一次会话的范围内多次请求间,共享数据
- 方式:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
Cookie
-
概念:客户端会话技术,将数据保存到客户端
-
步骤:
-
创建Cookie对象,绑定数据
new Cookie(String name, String value)
-
发送Cookie对象
response.addCookie(Cookie cookie)
-
获取Cookie,拿到数据
Cookie[ ] request.getCookies( )
-
-
实现原理
基于响应头set-cookie和请求头cookie实现
-
cookie的细节
-
一次可不可以发送多个cookie?
可以,可以创建多个Cookie对象,使用response多次调用addCookie发送即可
-
cookie在浏览器中保存多长时间?
-
默认情况下,当浏览器关闭后,Cookie数据被销毁
-
持久化存储:
setMaxAge(int seconds)
seconds:
- 正数:将Cookie数据写到硬盘的文件中。持久化存储,数字表示存活时间
- 负数:默认值
- 零:删除cookie信息
-
-
cookie能不能存中文?
在tomcat 8之前 ,cookie不能直接存储中文数据
需要将中文数据转码—一般采用URL编码
在tomcat 8之后,cookie支持中文数据,但是特殊字符还是不支持,建议使用URL编码存储,URL解码解析
-
cookie获取范围多大?
-
假设在一个tomcat服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
默认情况下cookie不能共享
setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录。如果要共享,则可以将path设置为"/"
-
不同的tomcat服务器间cookie共享问题
setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
如:setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中cookie可以共享
-
-
-
Cookie的特点和作用
- cookie存储数据在客户端浏览器
- 浏览器对于单个cookie的大小有限制(4kb),对同一个域名下的总cookie数量也有限制(20个)
作用:
- cookie一般用于存储少量的不太敏感的数据
- 在不登录的情况下,完成服务器对客户端的身份识别
JSP入门
-
概念:Java Server Pages:Java服务器端页面
可以理解为:一个特殊的页面,其中既可以指定定义HTML标签,又可以定义Java代码。
用于简化书写。
-
原理:
JSP本质上就是一个Servlet
-
JSP的脚本:JSP定义Java代码的方式
- <% 代码 %>:定义的Java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么
- <%! 代码 %>:定义的Java代码,在jsp转换后的Java类的成员位置
- <%= 代码 %>:定义的Java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么
-
JSP的内置对象
一共有9个内置对象
-
request
-
response
-
out:字符输出流对象。可以将数据输出到页面上。和response.getWriter( )类似
response.getWriter( )和out.writer( )区别:tomcat服务器做出响应之前,会先找response缓冲区数据,再找out缓冲区数据。所以response.getWriter( )数据输出永远在out.writer( )之前
-
Session
-
概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。
-
步骤:
-
获取HttpSession对象:
HttpSession session = request.getSession( );
-
使用HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name, Object value)void removeAttribute(String name)
-
-
原理:Session的实现是依赖于Cookie的
-
细节:
-
当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
不是(默认情况下)。
如果需要相同,则可以创建Cookie,键位JSESSIONID,设置最大存活时间,让cookie持久化保存
Cookie c = new Cookie("JSESSIONID", session.getId()); c.setMaxAge(60*60); response.addCookie(c);
-
客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
不是。
但是要确保数据不丢失,
session的钝化:在服务器正常关闭之前,将session对象序列化到硬盘上
session的活化:在服务器启动后,将session文件转化为内存中的session对象(反序列化)
-
session的失效时间?
- 服务器关闭
- session对象调用invalidate( )
- session默认失效时间为30分钟
-
-
session的特点:
- session用于存储一次会话的多次请求数据,存在服务器端
- session可以存储任意类型,任意大小的数据
-
session与cookie的区别:
- session存储数据在服务器端,cookie在客户端
- session没有数据大小限制,cookie有限制
- session数据安全,cookie相对不安全
JSP进阶
-
指令
作用:用于配置JSP页面,导入资源文件
格式:
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 …%>
分类:
-
page :配置JSP页面
- contentType:等同于response.setContentType( )
- 设置响应体的mime类型以及字符集
- 设置当前JSP页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
- import:导包
- errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
- isErrorPage:标识当前页面是否是错误页面
- true:是,可以使用内置对象exception
- false:否,默认值。不可以使用内置对象exception
-
taglib:导入资源
<%@taglib prefix="c" uri="" %>
-
include:页面包含的。导入页面的资源文件
<%@include file="demo2.jsp"%>
-
-
注释
-
HTML注释:
:只能注释HTML代码片段 -
JSP注释:
<%-- --%>:可以注释所有
-
-
内置对象
在JSP页面中不需要创建,直接使用的对象
一共有9个:
变量名 真实类型 作用
- pageContext PageContext 当前页面共享数据
- request HttpServletRequest 一次请求访问的多个资源(转发)
- session HttpSession 一次会话的多个请求间
- application ServletContext 所有用户间共享数据
- response HttpServletResponse 响应对象
- page Object 当前页面(Servlet)的对象 this
- out JspWriter 输出对象,数据输出到页面上
- config ServletConfig Servlet的配置对象
- exception Throwable 异常对象
MVC开发模式
-
MVC:
- M:Model,模型。JavaBean
- 完成具体的业务操作,如:查询数据库,封装对象
- V:View,视图。JSP
- 展示数据
- C:Controller,控制器。Servlet
- 获取用户的输入
- 调用模型
- 将数据交给视图进行展示
优点:
- 耦合性低,方便维护,利于分工协作
- 重用性高
缺点:使得项目架构变得复杂,对开发人员要求高
- M:Model,模型。JavaBean
EL表达式
-
概念:Expression Language 表达式语言
-
作用:替换和简化jsp页面中Java代码的编写
-
语法:${ 表达式 }
-
注意:jsp默认支持EL表达式,如果要忽略EL表达式
- 设置JSP中page指令:isELIgnored=“true” 忽略当前jsp页面中有所的EL表达式
- \${ 表达式 }:忽略当前这个EL表达式
-
使用:
-
运算
运算符:
-
算数运算符: + - * /(div) %(mod)
-
比较运算符: > < >= <= == !=
-
逻辑运算符:&&(and) ||(or) !(not)
-
空运算符:empty
功能:用于判断字符串、集合、数组对象是否为null或长度是否为0
-
-
获取值
-
EL表达式只能从域对象中获取值
-
语法:
-
${域名称.键名}:从指定域中获取指定键的值
域名称:
- pageScope --> pageContext
- requestScope --> request
- sessionScope --> session
- applicationScope --> application(ServletContext)
-
${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止
-
获取对象、List集合、Map集合的值
-
对象:${域名称.键名.属性名}
本质上会调用对象的getter方法
-
List集合:${域名称.键名[索引]}
-
Map集合:
${域名称.键名.key名称}
${域名称.键名[“key名称”]}
-
-
-
-
隐式对象:
EL表达式有11个隐式对象
pageContext:
获取jsp其他8个内置对象
${pageContext.request.contextPath}:动态获取虚拟目录
Filter过滤器
-
###概念
web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能
过滤器的作用:
- 一般用于完成通用的操作。如:登陆验证,统一编码处理,敏感字符过滤…
快速入门
- 定义一个类,实现接口Filter
- 复写方法
- 配置拦截路径
- web.xml
- 注解
package com.ego.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*")
public class FilterDemo implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器执行.....");
//放行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
过滤器细节
-
web.xml配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <filter> <filter-name>demo1</filter-name> <filter-class>com.ego.filter.FilterDemo</filter-class> </filter> <filter-mapping> <filter-name>demo1</filter-name> <!--拦截路径--> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
-
过滤器执行流程
执行过滤器上的语句,然后访问资源,回来时执行过滤器下的语句
-
过滤器生命周期方法
- init:在服务器启动时,会创建Filter对象,然后调用init方法。只执行一次,用于加载资源
- doFilter:每一次请求被拦截资源时,会执行。执行多次
- destroy:在服务器关闭后,Filter对象被销毁。如果服务器正常关闭,则会执行destroy方法。只执行一次,用于释放资源
-
过滤器配置详解
-
拦截路径配置:
- 具体资源路径:/index.jsp 只有访问index.jsp资源时,过滤器才会执行
- 拦截目录:/user/* 访问/user下的所有资源时,过滤器都会被执行
- 后缀名拦截:*.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
- 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
-
拦截方式配置:资源被访问的方式
-
注解配置:
设置dispatcherTypes属性:
- REQUEST:默认值。浏览器直接请求资源
- FORWARD:转发访问资源
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
-
web.xml配置
设置标签即可
-
-
-
过滤器链(配置多个过滤器)
执行顺序:如果有两个过滤器
- 过滤器1
- 过滤器2
- 资源执行
- 过滤器2
- 过滤器1
过滤器先后顺序问题:
-
注解配置:按照类名的字符串比较规则比较,值小的先执行
如:AFilter和BFilter,AFilter先执行
-
web.xml配置:谁定义在上边,谁先执行
Listener监听器
事件监听机制
- 事件:一件事情
- 事件源:事件发生的地方
- 监听器:一个对象
- 注册监听:将事件、事件源、监听器绑定在一起。当事件源上发生某个事件时,执行监听器代码
两个基础方法
ServletContextListener:监听ServletContext对象的创建和销毁
- void contextDestroyed(SerlvetContextEvent sce):ServletContext对象被销毁之前会调用该方法
- void contextInitialized(ServletContextEvent sce):ServletContext对象创建后会调用该方法
步骤:
- 定义一个类,实现ServletContextListener接口
- 复写方法
- 配置
- web.xml
- 注解