黑马程序员技术交流社区
标题: 【石家庄校区】笔记 [打印本页]
作者: 、呵呵呵 时间: 2018-5-21 15:16
标题: 【石家庄校区】笔记
本帖最后由 小石姐姐 于 2018-5-23 15:58 编辑
笔记
JDBC
Java Data Base Connectivity ( Java数据库连接 )
数据库驱动 连各个设备 ( 应用 ) 之间通信的桥梁
JDBC的开发步骤第一步 : 加载驱动第二步 : 获得连接第三步 : 基本操作第四步 : 释放资源工具类package JDBCUtils;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtils {
private static final String driverClassName;
private static final String url;
private static final String username;
private static final String password;
static{
Properties properties= new Properties();
try {
properties.load(new FileInputStream("src/db.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
driverClassName=properties.getProperty("driverClassName");
url=properties.getProperty("url");
username=properties.getProperty("username");
password=properties.getProperty("password");
}
/**
* 注册驱动的方法
*/
public static void loadDriver(){
try {
Class.forName(driverClassName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获得连接的方法
*/
public static Connection getConnection(){
Connection conn = null;
try{
// 将驱动一并注册:
loadDriver();
// 获得连接
conn = DriverManager.getConnection(url,username, password);
}catch(Exception e){
e.printStackTrace();
}
return conn;
}
/**
* 释放资源的方法
*/
public static void release(Statement stmt,Connection conn){
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
public static void release(ResultSet rs,Statement stmt,Connection conn){
// 资源释放:
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}配置文件
dcName=com.mysql.jdbc.Driver
url=jdbc:mysql:///web_test3
username=root
password=123查询多条数据
@Test
/**
* 查询操作
*/
public void demo4(){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL:
String sql = "select * from user";
// 预编译SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数:
// 执行SQL:
rs = pstmt.executeQuery();
// 遍历结果集:
while(rs.next()){
System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(rs, pstmt, conn);
}
}查询一条记录在like模糊查询后面直接写 ? ,如何在设置参数哪里在写 % 或者 _
@Test
public void demo4(){
Connection conn = null;
statement stmt = null;
ResultSet rs = null;
try{
注册驱动:
Class.forName("com.mysql.jdbc.Driver");
获得连接:
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3","root","123");
执行操作:
创建执行SQL语句对象
stmt = conn.preparedStatement ();
编写SQL语句:
String sql = "select * from user where id=4"; [如果能确定查出一条记录,可以不用while循环,如果不确定用while循环也可以]
执行SQL语句:
rs = stmt.executeUpdate (sql);
//[可以在这里写循环]
if(num > 0){
syso(rs.getInt("id")+" ");
syso(rs.getString("username")+" ");
syso(rs.getString("password")+" ");
syso(rs.getString("nickame")+" ");
syso(rs.getString("age")+" ");
}
}catch(Execption e){
e.prinStackTrace()
} }finally{
标准资源释放代码;
if(stmt != null){
try{
stmt.close();
}catch(SQLException e){
e.printStackTrace();
}
stmt = null;
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
conn = null;
}
if(rs != null){
try{
rs.close();
}catch(SQLException e){
e.printStackTrace();
}
rs = null;
}
}添加操作
@Test
/**
* 保存操作
*/
public void demo1(){
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL语句:
String sql = "insert into user values (null,?,?,?,?)";
// 预编译SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数:
pstmt.setString(1, "eee");
pstmt.setString(2, "abc");
pstmt.setString(3, "旺财");
pstmt.setInt(4, 32);
// 执行SQL
int num = pstmt.executeUpdate();
if(num > 0){
System.out.println("保存成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(pstmt, conn);
}
}修改操作
@Test
/**
* 修改操作
*/
public void demo2(){
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL语句:
String sql = "update user set username = ?,password =?,nickname=?,age = ? where id = ?";
// 预编译SQL:
pstmt = conn.prepareStatement(sql);
// 设置参数:
pstmt.setString(1, "abc");
pstmt.setString(2, "1234");
pstmt.setString(3, "旺旺");
pstmt.setInt(4, 23);
pstmt.setInt(5, 6);
// 执行SQL:
int num = pstmt.executeUpdate();
if(num > 0){
System.out.println("修改成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(pstmt, conn);
}
}删除操作
@Test
/**
* 删除操作
*/
public void demo3(){
Connection conn = null;
PreparedStatement pstmt = null;
try{
// 获得连接:
conn = JDBCUtils.getConnection();
// 编写SQL语句:
String sql = "delete from user where id = ?";
// 预编译SQL
pstmt = conn.prepareStatement(sql);
// 设置参数:
pstmt.setInt(1, 4);
// 执行SQL:
int num = pstmt.executeUpdate();
if(num > 0){
System.out.println("删除成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
JDBCUtils.release(pstmt, conn);
}
}工具类测试
public void JDBCDemo3{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
获得连接
conn = JDBCUtils.getConntion();
创建执行SQL语句对象
stmt = conn.preparedStatement ();
编写SQL
String sql = "select * from user";
执行查询
re.stmt.executeQuery(sql);
遍历结果集
while(rs.next()){
syso(rs.getInt("id")+" ");
syso(rs.getString("username")+" ");
syso(rs.getString("password")+" ");
syso(rs.getString("nickame")+" ");
syso(rs.getString("age")+" ");
}
}catch(Exception e){
e.printStackTrace();
}finally{
释放资源
JDBCUtils.release(rs,stmt,conn);
}
}批量处理
API介绍DriverManager 驱动管理类
作用一注册驱动 Class.forName("com.mysql.jdbc.Driver"); [ 固定写法 ]
作用二获得连接 getConnection (url , user , password ) ;
url : 与数据库连接的路径
user :与数据库连接的用户名
password:与数据库连接的密码
url 的写法
jdbc:mysql://localhost:3306/web_test3
jdbc :连接数据库的协议
mysql :是jdbc的子协议
localhost :连接的MySQL数据库服务器的主机地址 ( 连接是本机就可以写成localhost ) 如果连接不是本机的,就需要写上连接主机的IP地址
3306 :MySQL数据库服务器的端口号
web_test3 :
Connection 数据库连接对象
作用一创建执行SQL语句的对象 名字 . preparedStatement ( "这里写SQL语句" ) ; [ 有返回值,用sql的那个接收,起个变量名字 ]
执行SQL语句对象 statement :执行SQL
CallableStatement :执行数据库中存储过程
PreparedStatement :执行SQL对SQL进行预处理 , 解决SQL注入漏洞 [常用的]
作用二管理事务 setAutoCommit :指定事务管理
commit ( ) :提交
rollback ( ) :回滚
Statement 执行SQL语句
作用一执行SQL语句 boolean execute ( sql语句 )
执行查询 , 修改 , 添加 , 删除的SQL语句 [ 返回true ]
ResultSet executeQuery ( sql语句 )
执行查询 ( 执行select语句 )
int executeUpdate ( sql语句 )
执行修改 , 添加 , 删除的SQL语句
作用二执行批处理 addBatch :添加批处理
clearBatch :清除批处理
executeBatch :执行批处理
在的代码里实际用的Statement 是 PreparedStatement 的父接口
PreparedStatement : ps
执行查询:
ResultSet rs = ps . executeQuery ( ) ;
执行增 , 删, 改
int row = ps . executeUpdate ( ) ;
ResultSet 结果集 通过 select 语句的查询结果
结果集遍历 next ( ) :将光标移到下一行
while(rs.next()){
syso(rs.getInt("id")+" ");
syso(rs.getString("username")+" ");
syso(rs.getString("password")+" ");
syso(rs.getString("nickame")+" ");
syso(rs.getString("age")+" ");
}结果集获取 getXXX ( ) :方法通常都会有一个重载的方法
getXXX ( int columnlndex列号 ) :传入列号
getXXX ( String columnName列名 ) :传入列名
getObject ( String columnName ) :通用
while (rs.next){
rs.getXXX (String columnName列名) ;
XXX 是 int string 等等;
columnName默认使用列名,如果起了别名,就用别名
}JDBC资源释放 JDBC城西执行完之后,要释放资源,通常是 ResultSet , Statement , Connection
Connection对象是非常稀有的. 这个对象一定要做到尽量晚创建,今早释放掉
将资源释放的代码写到 finally
finally{
标准资源释放代码;
if( rs != null ){
try{
rs.close();
}catch( SQLException e ){
e.printStackTrace();
}
rs = null;
}
}DBUtils的使用ResultSetHandler的实现类ArrayHandler 和 ArrayListHandler
了解就好!!!ArrayHandler将一条记录封装到一个数组当中,这个数组应该是Object [ ]
ArrayListHandler将多条记录封装到一个装有Object数组的List集合中
重要!!!BeanHandler 将一条记录封装到一个JavaBean中
BeanListHandler 将多条记录封装到一个装有JavaBean的List集合中
错误解决办法实体类私有名字和数据类字段名不一致时,采用表字段别名的方式匹配封装
一个JavaBean的属性不是实体类里面的私有定义的,而是根据get/set方法来获取,
实体类里面,加上无参方法,因为JavaBean默认使用无参
商城会用到!!!MapHeadler 将一条记录封装到一个Map集合中,Map的key是列名,Map的value就是表中列的记录值
MapListHeadler 将多条记录封装到一个装有Map的List集合中
ColumnListHandler(了解) 将数据中的某列的值封装到List集合中
ScalarHandler(计数用) 将单个值封装
KeyedHandler(了解) 将多条记录封装到一个装有Map集合中的Map集合中,而且外面的Map的key是可以指定的
XML可扩展标记语言,用户自定义标签!!!
作用:传输 和 存取数据 ,软件的配置文件
XML作为配置文件的方式完成模拟Tomcat
XML使用区分大小写,不能有空格,标签必须有结束
文档声明 通常出现在XML的第一行第一列的位置!!!
< ?xml 属性名 ="属性值"属性名 ="属性值“。。。? >
version :必须有 。 使用1.0版本
encoding :字符集,是使用浏览器打开的时候采用的默认的字符集的编码
standalone :描述XML文档是否需要依赖其他的文档
注释 <!-- 这是注释 --> 快捷键 :Ctrl + Shift + /
元素(标签)
名称中不能包含冒号(:)
属性 命名规则和元素一致
属性需要使用引号!
特殊字符和CDATA区 CDATA区【character Data】
格式: < ![ CDATA [ ] ] >
重点!!!XML解析方式 从XML文档中获得想要的数据(通过代码完成的)
XML的解析方式( ):
DOM解析:DOM:Document Object Model【能做增删改】
SAX解析:Simple Api for XML
优缺点针对这两种解析方式,不同的公司提供了不同的API的实现
JAXP :SUN公司提供的一套XML的解析的API
JDOM :开源组织提供了一套XML的解析的API-jdom
DOM4J :开源组织提供了一套XML的解析的API-dom4j
pull :主要应用在Android手机端解析XML
了解!!!DOM4J解析XML步骤分析【第一步】导入 jar 包 .dom4j-1.6.1.jar
【第二步】创建解析器
【第三步】解析文档获得代表文档的Document对象
【第四步】获得根节点
【第五步】从根节点下查找其他的节点
代码实现重点!!!Xpachdom4j支持XPath的 jar 包
dom4j的XPath支持的API:
List document . selectNodes ( String xPath );
Node document . selectSingleNode ( String xPath );
代码实现了解!!!模拟Tomcat重点!!!XML约束 就是用来约束XML的文档中可以出现那些标签,标签是否有顺序,出现次数
用来规范XML的写法
约束的种类及区别
DTD 和 Schema
区别 : 1,DTD语法自称一体的,Schema语法就是XML的语法
2,Schema的语法就是XML的语法所有更容易被解析器所解析
3,Schema支持名称空间
4,Schema有比DTD更加强大的语义和语法的约束
了解!!!编写DTD约束XML文档 内部DTD :< ! DOCTYPE persons [ ] >
外部DTD
一种本地DTD :<!DOCTYPE persons SYSTEM ”unknown.dtd“>
一种网络DTD :<!DOCTYPE persons PUBLIC”//UNKNOWN/“ ”unknown.dtd“>
DTD的语法
元素:
<!ELEMENT 元素名 元素类型 >
元素类型:
EMPTY:
ANY :
子元素
是否有序:使用逗号(,)或者竖线(|)表示
出现的次数:?:零次或一次 +:一次或多次 *零次或多次
PCDATA
属性:
<!ATTLIST 元素名称 属性名称 属性类型 属性约束 >
属性类型:
ID类型:表示属性值需要是唯一的
CDATA类型:普通的字符串
枚举:
属性约束:↓↓↓↓↓出现Parse的时候就是有地方解析错了
代码实现编写Schema约束XML文档.xsd后缀名
代码实现被约束的XML文档,代码实现
tomcat
一个Web项目需要通过tomcat服务器被其他人访问到
软件的架构
C / S 架构的软件 :
Client / Server 客户端和服务器端的软件。都需要安装在PC端安装的软件,比如QQ,迅雷
优点:效果炫 ,一部分代码写到客户端(速度快)
缺点:服务器端更新,客户端都需要更新
B / S 架构的软件 :
Browser / Server 浏览器端和服务端的软件,不需要安装到PC端,只需要有一个浏览器即可,比如 京东,网银。。。
优点:服务器更新,客户端浏览器不需要进行更新
缺点:效果不炫,所有的代码运行都在服务端,导致服务器压力过大
效果:使用HTML5,CSS3可以做出很炫效果
服务器压力:搭建服务器的集群,而且还有 AJAX 技术
Web的资源
静态资源:
HTML,CSS,JS,图片。。
动态资源:
PHP :
ASP :
Servlet / JSP :
服务器
硬件:其实就是一台配置很高的电脑
软件:必须在一台电脑上安装服务器软件,这台电脑成为Web服务器
常见Web服务器【中间件】
Apache :发布PHP的,LAMP:Linux,Apache,MySQL,PHP
IIS :发布ASP的
WebSphere :IBM公司研发,收费的大型服务器软件,支持EE所有的开发规范
WebLogic :BEA公司研发,收发的大型服务器软件,支持EE所有的开发规范
Tomcat :Apache组织研发,免费小型服务器软件,支持Servlet/JSP的开发规范
JBoos :
Web动态资源目录结构
Website
|-----静态资源
|-----WEB-INF【路径】【动态必须有】
|-----web.xml :必须的
|-----classes :有没有一样
|-----lib :有没有一样
Tomcat目录结构
Server.xml :tomcat 核心
bin :tomcat 的执行的文件
conf :tomcat 的配置文件
logs :tomcat 的运行的日志文件
lib :tomcat 运行的需要的jar包
temp :tomcat 产生临时文件存放的路径
webapps :tomcat 发布的web项目的路径
work :tomcat 运行JSP的时候,JSP翻译成Servlet的代码存放的路径
发布WEB项目到Tomcat中
1 ,把一个项目打包成 . war 包,然后在放入webapps下
配置 tomcat虚拟路径
2,tomcat\conf\Catalina\localhost:新建一个xxx.xml,写< Context docBase=""/>,访问路径:xxx
Tomcat常见问题
【没有配置 JAVA_HOME 引发 tomcat 一闪小时】
一定要配置 JAVA_HOME 环境变量
【端口号冲突的问题】
第一种:将占用端口的应用结束
netstat -ano
打开任务管理器把应用结束
第二种:修改自身应用的端口号
tomcat / comf / server.xml里面的port后面的端口号
HTTP协议
用来规定浏览器(客户端)与服务器(服务端)之间需要遵守的规则【数据传递】
规定了双方交换数据的格式
特点
基于请求和响应的模型,【现有请求后又响应,必须成对出现】【端口号:80】
HTTP请求部分
请求行
提交方式:
GET :提交的参数会显示到地址栏上,在请求行中地址后面,有大小限制,没有请求体
POST :提交的参数不会显示到地址栏上,在请求体中,没有大小限制,有请求体
提交路径:都是固定的
协议版本:都是固定的
请求头
都是键值对的形式显示,一般一个key对应一个value,也有个别的是一个key对应多个value
User-Agent :代表浏览器的类型。-----可以看浏览器是用什么进行编码的【比如IE使用URLEncdor】
Referer :代表的是网页的来源。-----防盗链
If-Modified-Since :通常与响应中的头Last-Modified一起使用查找本地缓存
请求体
就是POST提交方式的提交的参数
HTTP响应部分
响应行
协议版本
状态码
200 :成功
302 :重定向
304:查找本地缓存
404:访问资源不存在【检查路径】
500:服务器内部错误
状态码描述
响应头
键值对的形式,一个key对应一个value,也有一个key对应多个value
Last-Modified :与请求中的If-Modified-Since一起使用查找本地缓存
Content-Dispostion :文件下载的时候使用的一个头信息【下载的时候有用】
Location :重定向的跳转的路径
Refresh :定时刷新 / 定时跳转
响应体
显示到浏览器的内容
Servlet
运行在WEB服务器上的小的Java程序,用来接收和响应从客户端发送过来的请求,通常使用HTTP协议
SUN公司提供的动态页面开发技术
作用
处理客户端浏览器发送的请求,并且可以对请求做出响应
使用
编写一个类实现Servlet接口
方法service 为用户处理请求和响应的方法
ServletRequest req:请求
http://ip:port/projectName/地址串
如果要访问一个servlet,这个地址串跟web.xml中配置的url-pattern有关系
String request.getParameter(String name):
String [] request.getParameterValues(String name):
Map< String,String[]> request.getParameterMap():
ServletString getParameter(String name) :用于接收一个名称对应一个值的数据
String [] getParameterValues(String name ) :用于接收一个名称对应多个值的数据
Map getParameterMap() :用于接收表单中的所有的数据,Map的key是表单提交的名称,Map的value是提交参数的值
Enumeration getParameterName() :用于获取表单中提交的所有的
Servlet生命周期 就是一个对象从创建到销毁的过程
servlet 生命周期:servlet从创建到销毁的过程
何时创建:用户第一次访问Servlet创建Servlet的示例
何时销毁:当项目从服务器中移除的时候,或者关闭服务器的时候
默认第一次用户访问Servlet的时候,服务器就会创建一个Servlet实例,里面的init方法就会执行,之后的每一次请求都以多线程的方式访问service方法,在service方法内部会根据请求方式不同调用不同的doXXX方法,当Servlet从服务器中移除或者关闭服务器的时候,Servlet实例就会销毁,destroy方法就会执行,并且Servlet从头到尾只创建一次
Servlet相关配置优化 有一些资源需要初始化,这个时候很耗时
第一次访问的时候初始化资源(耗时的步骤)以后访问都无需在初始化
那么优化的时候把这个耗时的操作放到服务器启动的时候
配置 Servlet默认在第一次访问的时候创建,启动时创建好,进行对Servlet的配置:
在web . xml 中在 < servlet > < /servlet >标签中设置:
< load-on-startup > 2 < /load-on-startup > :传入整数,越小优先级越高,从2开始
url-pattern的配置第一种: 完全路径匹配 :以 / 开始 eg:/ServletDemo4 或者 /aaa/ServletDemo5
第二种 目录匹配 :以 / 开始 需要以 * 结束 eg:/*或者 /aaa/ *
第三种 扩展名匹配 :以 * 开始 *.do或者 *.action
如果访问地址:
优先级 完全路径匹配 > 目录匹配 > 扩展名匹配
【 * 号可以匹配所有字符】【一次请求只有一次响应】
开发中路径的编写 相对路径:都是需要找位置相对关系 , 不能以/ 开始
./ 当前路径 ../ 上一级目录
绝对路径:不需要找位置相对关系 , 以 / 开始的 【写绝对路径】
绝对路径中分为客户端路径和服务器端路径:
客户端路径一定要加工程名 /day09/ServletDemo6
服务器端路径不需要加工程名 /ServletDemo6
定时跳转页面 使用HTTP协议中的Refresh头信息
addHeader(String naem , String value); 针对一个key对应多个value的响应头
setheader(String name,String value); 针对一个key对应一个value的响应头
重要ServletContext能存取数据,【域对象】,有一个变量存起来,在别的地方也能获得到
1,用来获得全局初始化参数
2,用来获得文件的MIME的类型【文件上传下载的时候】
3,作为域对象存取数据
SetAttribute( Object object ) 【存数据】
getAttribute( String name ) 【取数据】
removeAttribute( String name ) 【移除数据】作用范围:整个web应有的范围【整个Web项目】
创建:服务器启动的时候,tomcat服务器为每个web项目创建一个单独ServletContext对象
销毁:服务器关闭的时候或者移除的时候
4,用来读取web项目下的文件
Enumeration :枚举 【想象成集合,遍历】
hasMoreElements() 用while遍历(括号里写前面的){
这里面写 nextElement }
response读取Web工程下的文件 用绝对路径
getProperty:获取属性文件里面的值
ServletContext读取Web项目[有Servlet环境的]读取属性文件步骤 获得SerletContext
ServletContext conntext = this.getServletContext();
第一步: 获取路径; InputStream getResourceAsStream(String path)
InputStream is = context.getResourceAsStream(属性文件的绝对路径);
第二步: 创建一个属性对象
Properties pp = new Properties();
第三步: 属性对象使用load()方法获取路径
pp.load ( is );
第四步: String a =pp.getProperty("driverClass");
.........url.......username.......password......
setArrribute(String name,Object value); 存数据
Object getAttribute(String name); 读数据【有返回值】
removeAttribute(String name) 移除数据
ServletContext读取全局初始化参数 getInitParameter(String name):获取名字
获得全部的参数名字:
Enumeration< String > e = this.getServletContext().getInitParamterNames();
遍历:
while(e.hasMoreElements()){
String name = e.nextElement();
获取value值
String value = this.getServletContext().getInitParameter( name );
}
编写工具类读取属性文件Properties【没有servlet环境的】步骤如下: 编写静态类,使用类的加载器来读取文件
类的加载器用来加载class文件,将class文件加载到内存
//传入fileName属性名,和key属性文件里面的key
public static String readFile(String key,String fileName){
InputStream is = ReadFileUtils.class.getClassLoader().getResourceAsStream(fileName);
Properties PP = new Properties();
pp.load(is);
String value = pp.getProperty(key);
return value;
} String driverClass = pp.getProperty("driverClass"); String url = pp.getProperty("url"); String username = pp.getProperty("username"); String password = pp.getProperty("password");
Response响应对象 从服务器向浏览器输出内容
setStatus(int sc):设置状态码【响应行】
file:///C:/Users/Administrator/Desktop/%25E5%259B%25BE%25E7%2589%2587/%25E5%25BE%25AE%25E4%25BF%25A1%25E5%259B%25BE%25E7%2589%2587_20180516111706.png?lastModify=1526886402
文件下载的核心思想IO流的 读 / 写
inpuptStream in = new FileInputStream(“服务器上的路径”);【读】
Outputstream os = response.getOutputStream ( ) ; 【写】
模板代码读,写
int len = 0;
byte [] b = new byte[1024];
while((len = is.read(b))!=-1){
os.write(b,0,len);
}
is.close();file:///C:/Users/Administrator/Desktop/%25E5%259B%25BE%25E7%2589%2587/%25E5%25BE%25AE%25E4%25BF%25A1%25E5%259B%25BE%25E7%2589%2587_20180516151920.png?lastModify=1526886402
页面响应的方法: getOutputStream();
getWriter ( ) ;
这两个方法是互斥的
做出响应的时候只能使用其中的一种流响应
输出中文乱码的处理:
字节流:【文件下载】response. getOutputStream().write("hello Response....".getBytes());
设置浏览器默认打开的编码
resposne.setHeader(“Content-Type”,“text;charset=UTF-8”);
设置中文字节取出的时候编码
“中文”.getBytes ( "UTF-8" );
字符流: response.getWriter().println("Hello Writer Response");
response的字符流的缓冲区的默认的编码是ISO-8859-1根本不支持中文
设置浏览器打开的时候的编码
resposne.setHeader(“Content-Type”,“text;charset=UTF-8”);
设置response的缓冲区的编码
response.setCharacterEncoding(“UTF-8”);
简化的写法:response.setContentType( "text/html;charset=UTF-8" );
request request代表用户的请求
Request的API获得客户端信息: 获得请求的方式
getMethod();
获得请求的路径
getRequestURL();
获得客户机相关的信息IP地址
getRemoteAddr();
获得工程名
getContextPath();
获得表单参数 : String request. getParameter ( String name )
String[] request. getParameterValues ( String name )
Map< String ,String[] > request. getParameterMao ();
域对象:请求乱码的解决 POST: request.setCharacterEncoding(“UTF-8 ”);【设置在接收参数之前】
GET:
String name = new String (request.getParameter("需要被编码的").getBytes("ISO-88599"),"UTF-8");
Request作为域对象存取数据 方法
setAttribute(String name,String value);
Object getAttribute( String name );
removeAttribute ( String name ) ;
作用范围
一次请求的范围
创建和销毁:
创建:客户端向服务器发送了一次请求以后,服务器就会创建一个request的对象
销毁:当服务器对这次请求做出了响应之后
重定向和转发的区别(redirect和forward的区别) 重定向:【地址栏会发生变化】【两次请求两次响应】【需要加工程名】【可以跳转任意网站】【存数据不能取到】
response.sendRedirect ( "客户端路径" );
转发:【地址栏不变】【一次请求一次响应】【不需要加工程名】【只能在服务器内部进行转发】【能存取数据】
request.setAttribute ( "name","张三" );【存数据】
request.getRequestDispatcher ( "服务器路径" ).forward ( request , response );【转发】
会话技术 用户打开浏览器,访问很多网页,到最后关掉,其过程称之为一次会话,私有的数据,保存在会话技术
Cookie方法 将数据保存到客户端浏览器
向浏览器保存数据:HttpServletResponse有一个方法
void addCookie(Cookie cookie);
response . addCookie (coo );
获得浏览器带过来的Cookie:HttpServletRequest有一个方法:
Cookie [ ] get Cookies ( ) ;
cookie [ ] cookis = request . getCookies ( ) ;
创建一个Cookie对象:
Cookie(String name , String value);
Cookie coo = new Cokie(“指定名字”,“给什么值”);
获得Cookie的名称和值
getName();getValue();
设置Cookie的有效域名
setDomain(String domain);
设置Cookie的有效路径【删除持久性的Cookie】
setPath(String path);
coo.setPath ( )
设置Cookie的有效时间【等多长时间,在规定时间操作,时间重置,接着等】
setMaxAge(int age);
coo.setMaxAge ( 单位是秒 )
Cookie的分类会话级别的Cookie:默认的Cookie,关闭浏览器Cookie就会销毁
持久级别的Cookie:可以设置Cookie的有效时间,那么关闭浏览器Cookie还会存在,手动销毁持久性Cookie.setMaxAge ( 0 ) ----前提是有效路径必须一致
删除持久性的Cookie Cookie cookie = new Cookie(“跟前面名称一样”,null);
cookie . setPath ("跟前面路径一样") ;
cookie . setMaxAge ( 0 ) ;
response . addCookie ( cookie ) ;
response . sendRedirect ( "跳转的路径" ) ;
Cookie存中文 编码
Cookie cookie = new Cookie ( "aa" , URLEncoder . encode ( "中文" , "UTF-8" ) ) ;
response . addCookie ( cookie ) ;
file:///C:/Users/Administrator/Desktop/%25E5%259B%25BE%25E7%2589%2587/%25E5%25BE%25AE%25E4%25BF%25A1%25E5%259B%25BE%25E7%2589%2587_20180517165717.png?lastModify=1526886418
解码
String a = URLDecoder . decode ( 获取的值,“UTF-8” );
file:///C:/Users/Administrator/Desktop/%25E5%259B%25BE%25E7%2589%2587/%25E5%25BE%25AE%25E4%25BF%25A1%25E5%259B%25BE%25E7%2589%2587_20180517165721.png?lastModify=1526886418
Session 将数据保存到服务器端
JSP Java Server Pages(Java服务器端页面)。JSP = Java代码 + HtML的元素 + JSP内置东西
JSP执行过程
JSP会被编译成Servlet
在JSP里面写代码 < %! Java代码 % > :翻译成类中的成员部分,定义成员变量,成员方法,定义类,Servlet是线程不安全,尽量少在类中定义成员属性!!【基本不用这个】
< % Java代码 % > :翻译成类的service方法内部的内容,定义变量,定义类,直接写代码块【可以写循环】
< %= Java代码 % > :翻译成service方法内部的out . print ( ) 【在页面打印了】
会话技术 用户打开浏览器,访问很多网页,到最后关掉,其过程称之为一次会话,私有的数据,保存在会话技术
Cookie方法 将数据保存到客户端浏览器,有大小和个数的限制
向浏览器保存数据:HttpServletResponse有一个方法
void addCookie(Cookie cookie);
response . addCookie (coo );
获得浏览器带过来的Cookie:HttpServletRequest有一个方法:
Cookie [ ] get Cookies ( ) ;
cookie [ ] cookis = request . getCookies ( ) ;
创建一个Cookie对象:
Cookie(String name , String value);
Cookie coo = new Cokie(“指定名字”,“给什么值”);
获得Cookie的名称和值
getName();getValue();
设置Cookie的有效域名
setDomain(String domain);
设置Cookie的有效路径【删除持久性的Cookie】
setPath(String path);
coo.setPath ( )
设置Cookie的有效时间【等多长时间,在规定时间操作,时间重置,接着等】
setMaxAge(int age);
coo.setMaxAge ( 单位是秒 )
Cookie的分类会话级别的Cookie:默认的Cookie,关闭浏览器Cookie就会销毁
持久级别的Cookie:可以设置Cookie的有效时间,那么关闭浏览器Cookie还会存在,手动销毁持久性Cookie.setMaxAge ( 0 ) ----前提是有效路径必须一致
删除持久性的Cookie Cookie cookie = new Cookie(“跟前面名称一样”,null);
cookie . setPath ("跟前面路径一样") ;
cookie . setMaxAge ( 0 ) ;
response . addCookie ( cookie ) ;
response . sendRedirect ( "跳转的路径" ) ;
Cookie中文 编码
Cookie cookie = new Cookie ( "aa" , URLEncoder . encode ( "中文" , "UTF-8" ) ) ;
response . addCookie ( cookie ) ;
file:///C:/Users/Administrator/Desktop/%25E5%259B%25BE%25E7%2589%2587/%25E5%25BE%25AE%25E4%25BF%25A1%25E5%259B%25BE%25E7%2589%2587_20180517165717.png?lastModify=1526886437
解码
String a = URLDecoder . decode ( 获取的值,“UTF-8” );
file:///C:/Users/Administrator/Desktop/%25E5%259B%25BE%25E7%2589%2587/%25E5%25BE%25AE%25E4%25BF%25A1%25E5%259B%25BE%25E7%2589%2587_20180517165721.png?lastModify=1526886437
Session【HTTPSession】【域对象】
将数据保存到服务器端,没有大小和个数的限制,执行原理:基于Cookie
获得Session
request . getSession ( ) ;
HttpSession session = request . getSession ( ) ;
存数据
.session.setAttribute ( String name , Object value ) ;
Object value = session . getAttribute ( String name );
移除数据
removeAttribute( String name );
创建:
服务器端第一次调用getSession ( ) 的时候创建 session
销毁:【三种】
第一种:session过期【默认30分钟】
【在web.xml里面】
<session-config>
<session-timeout>这写时间,单位:分钟</session-timeout>
</session-config> 第二种:非正常关闭服务器直接销毁 ,正常关闭session保存到硬盘里,
第三种:手动调用session . invalidate ( ) ;
作用范围:
多次请求【一次会话】【转发和重定向都能获得Session里面的值】
【根本原因:存SessionID的cookie默认是会话级别的】
登陆的核心 【要把用户信息保存到Session里面,任何在别的页面获取Session里面用户的值,判断Session里面用户信息等不等与null】
JSP Java Server Pages(Java服务器端页面)。JSP = Java代码 + HtML的元素 + JSP内置东西
JSP执行过程
JSP会被编译成Servlet类,编译这个Servlet的类,生成class文件,得到执行,并且不用配置web.xml
在JSP里面写代码【脚本】 < %! Java代码 % > :翻译成类中的成员部分,定义成员变量,成员方法,定义类,Servlet是线程不安全,尽量少在类中定义成员属性!!【基本不用这个】
< % Java代码 % > :翻译成类的service方法内部的内容,定义变量,定义类,直接写代码块【可以写循环】
< %= Java代码 % > :翻译成service方法内部的out . print ( ) 【在页面打印了,代码后面不能加分号】
JSP的东西注释 < !-- 注释 -- > :HTML注释【存在于生成的HTML中】
<//单行,//多行,/ 两个星/文档注释> :Java代码注释**
【源码中也有翻译成Servlet后注释也存在,但是当执行完JSP后生成HTML后,注释就消失了】
< %-- 注释 --% > :JSP注释
【只存在与源代码,翻译成Servlet后,JSP的注释就消失了】
指令【3大指令】 语法
< %@指令的名称 属性名称=“属性值” 属性名称=“属性值”....等等% >
page指令: < %@ page % > :设置JSP的【通过属性设置JSP参数】
errorPage :设置错误友好页面的提示【路径不用加工程名,下面一起】
isErrorPage :通过这个设置显示JSP的错误信息【上面的一起使用】
设置全局的错误友好页面,在web.xml设置:
< error-page >
< error-code > 404 < /error-code >
< location > 404.jsp < /location >
< /error-page >
//写一个404的JSP的页面,然后有错误就跳转到这个404.jspinclude指令: 静态包含,指示JSP包含其他页面的,其他页面不需要前后,只写内容就好,
< %@include file = "页面路径" % >
taglib指令: 指示JSP引入标签库
< %@ taglib url="标签的rul的路径" prefix=“标签的别名”% >
内置对象【9大内置对象】 在JSP中可以直接使用的对象,在< %在这里面用,内置对象 . 方法% >
内置对象 真实对象 里面的方法,使用真实对象在API里面查
request HTTPServletRequest getParameter () ,setAttribute ()
response【域对象】 HttpServletResponse setHeader () ; getOutputStream
session 【域对象】 HttpSession setAttribute () ;getAttribute ()
application ServletContext setAttribute () ;getAttribute ()
page Object toString () ;wait ()
pageContext【域对象】PageContext setAttribute () ;getAttribute ()
config ServletConfig getServletName();getServletContext()
out JspWriter wtite () ;print ()
exception Throwable getMessage () ; getCause ()
page内置对象 :真实对象是Object,就是JSP翻译成Servlet后的类的引用
out内置对象 :out和response.getWriter不是同一个对象
out 真实对象是JapWriter,response获得Writer是PrintWriter响应只能是response做
pageContext内置对象【技能拔高的点】
< %= pageContext . findAttribute ("被查找的名称") %> :查找
获得其他的8个内置对象【getXXX方法获得】 :编写通用性代码或者框架的时候
向JSP的四个域中存取数据
PageScope :当前页面中有效 pageContext PageContext
RequestScope :一次请求范围 request HttpServletRequest
SessionScope :一次会话范围 session HttpSession
ApplicationScope :应用范围 application ServletContext
向其他三个域范围存值【图第一个是往自己里面存值】
file:///C:/Users/Administrator/Desktop/%25E5%259B%25BE%25E7%2589%2587/%25E5%25BE%25AE%25E4%25BF%25A1%25E5%259B%25BE%25E7%2589%2587_20180519165518.png?lastModify=1526886437
取出值【图第一个是取自己里面的值】
file:///C:/Users/Administrator/Desktop/%25E5%259B%25BE%25E7%2589%2587/%25E5%25BE%25AE%25E4%25BF%25A1%25E5%259B%25BE%25E7%2589%2587_20180519165620.png?lastModify=1526886437
动作标签【一系列的】 作用:简化代码
< jsp: forward / > :用于页面转发
< jsp: forward page="转发的路径" >< /jsp: forward >
< jsp: include / > :用于页面包含(动态包含)
< jsp: include page=“被包含路径” >< /jsp: include >
< jsp: param / > :用于带有路径的标签下,传递参数
静态包含和动态包含的区别【< %@include % > 和 < jsp:include >的区别】
静态包含:相当于源代码的拷贝,只会翻译成一个Java类,有一个执行结果
动态包含:各自分别去翻译,各自执行,最终包含的是执行的结果
EL 简化JSP的代码,简化尖括号 < % % >
语法:$ {EL表达式}
四个方面功能获取数据【 必须放在JSP的四个域里,然后才能获取,以什么名字存到域中,就以什么名字取出来,存的什么类型,取出来就是什么类型 】
数组,List集合: [ ] ------基本用来遍历
map,Java对象: . . 属性
获取单个值数据 ${ pageScope.name } -----取出指定域里面的单个值
${ name } -----取出域从小到大查找,然后取出单个值
name的类似findAttribute("name")先从page域中查找,没找到去request域中查找,没找到去session域中查找,没找到就去application域中找,都没找到返回" " 空,啥也不显示获取数组数据
String [] arrs = {"哈哈","呵呵","嘿嘿"};
pageContext.setAttribute("arrs",arrs); -----存入到域中
${ arrs } -----直接全部取出获取List集合数据
List<String> list = new ArrayList<String>();
list.add("哈哈");
list.add("呵呵");
list.add("嘿嘿");
pageContext.setAttribute("list",list); -----存入到域中
${ list }
${ list[0] } -----[]用于有下表的数据(数组,list集合)获取Map集合数据
Map<String,String> map = new HashMap<String,String>();
map.put("aaa","哈哈");
map.put("bbb","呵呵");
map.put("ccc","嘿嘿");
pageContext.setAttribute("map",map); -----存入到域中
${ map.aaa } -----点(.)用于有属性的数据(map,对象)
mao的特殊情况
存入: map.put("ddd.eee","嗯嗯");
取出数据: ${ map["ddd.eee"] }获取对象数据
User user = new User (1,"aaa","123") ----需要先创建以恶搞User类
pageContext.setAttribute("user",user); -----存入到域中
${ user.id } -----获取id获取对象的集合数据
User user1 = new User (1,"aaa","123") ----需要先创建一个User类 User user2 = new User (2,"bbb","123")
User user3 = new User (3,"ccc","123")
List<User> user = new ArrayList<User>();
pageContext.setAttribute("user",user); -----存入到域中
${ user1[0].id } - ${ user1[1].name } - ${ user1[2].sex }
${ user2[0].id } - ${ user2[1].name } - ${ user2[2].sex }
${ user3[0].id } - ${ user3[1].name } - ${ user3[2].sex }执行运算算数运算
pageContext.setAttribute("n1",20); -----存入到域中
pageContext.setAttribute("n2",10); -----存入到域中
${ n1+n2 } ---- +,-,*,/ 都这样写逻辑运算
${ n1 < n2 } - ${ n1 lt n2 } ----- less than 小于
${ n1 > n2 } - ${ n1 gt n2 } ----- great than 大于
${ n1 <= n2 } - ${ n1 le n2 } ----- less equal 小于等于
${ n1 >= n2 } - ${ n1 ge n2 } ----- great equal 大于的等于
${ n1 == n2 } - ${ n1 eq n2 } ----- equal 等于关系运算
${ n1 < n2 && n3 < n4 } --- ${ n1 < n2 and n3 < n4 } --- &&
${ n1 < n2 || n3 < n4 } --- ${ n1 < n2 or n3 < n4 } --- ||
${ !(n1 < n2) } --- ${ not(n1 < n2) } --- !() not()三元运算执行
${ n1 < n2 ? "正确":"错误" }empty运算
${ user == null } --- ${ empty user } ---是否 为空(empty)
${ user != null } --- ${ not empty user } ---是否 不为空(not empty)操作web开发的常用对象 pageScope,requestScope,sessionScope,applicationScope ---获取JSP域中的数据
${ 用什么名字存的,这里就用什么名字取出来 } ---取数据
param ,paramValues --接收请求的参数【用不到】
${ param.id } ---比如 param里面有id,直接.(点)获取就好
${ paramValues.hobby } ---直接取出数组
${ paramValues.hobby[0] } ---数组取出单个值 header ,headerValues ---获取请求头信息【用不到】
${ header["User-Agent"] } ---特殊情况
${ header.写你想获取的的名字 } initParam ---获取全局初始化参数【用不到】
前提需要 web.xml 配置了一个
${ initParam.username } ----去除了username的全局初始化参数cookie ---Web开发中的cookie
${ cookie.history.value } ---获取cookie里面的history的value(值)
${ cookie固定的.cookie的名字是啥,中间写啥,value固定的 }pageContext ----Web开发中的pageContext
${ pageContext.request.remoteAddr } -----获取IP地址
${ pageContext.request.contextPath } -----获取工程名字,比如(day11) 调用Java中方法:------很少用
JSTLcore(核心标签)fmt(国际标签)xml(XML标签)sql(SQL标签)fn(JSTL提供EL函数库)
core(核心标签)
引标签库:<%@ taglib url="http://java.sun.com/jsp/jst1/core prefix="c" %>
<c:set var ="n1" value="30" scope="page"></c:set> ---往page域里面存入名字叫n1
<c:set var ="n2" value="20" scope="page"></c:set>
<c:if test="${ n1 < n2 }"> n1小于n2 </c:if>
<c:if test="${ n1 >= n2 }"> n1大于等于n2 </c:if> --因为没有else,所以下一个if,需要从新写一个JSTL的常用标签
<c:out value="${ city }" default="北京"></c:out> ------city有值输出city的值,没有输出北京
<c:out value="<h1>标题1</h1>" escapeXml="false"></c:out>< c:if >判断
<c:set var ="n1" value="30" scope="page"></c:set> ---往page域里面存入名字叫n1
<c:set var ="n2" value="20" scope="page"></c:set>
<c:if test="${ n1 < n2 }"> n1小于n2 </c:if>
因为这个if没有else,所以别的判断,只能在写一个<c:if></c:if>
<c:if test="${ n1 < n2 }" var="flag" scope="page"> n1小n2 </c:if>【不要这样写】
把判断的结果,放到page域里面,名字是flag
<c:if test="S{ flag }"> n1小于n2 </c:if> ---判断上面的【不要这样写】遍历< c:forEach >var 是变量,items是等待遍历的对象,begin是那个开始,end是到多少,step是+多少,varStatus里面有两个 一个index下标索引,另一个count遍历到第几个了
遍历数组
String [] arrs ={"哈哈","呵呵","嘿嘿"}; ---创建数组
pageContext.serAttribute("arrs",arrs); ---放到page域里面
<c:forEach var="i" items="${ arrs }"> </c:forEach> ---遍历数组遍历List集合
List list = new ArrayList();
list.add("哈哈");
list.add("呵呵"); items表示待遍历的
list.add("嘿嘿");
pageContext.serAttribute("list",list); ---放到page域里面
<c:forEach var="i" items="${ list }"> ${ i } </c:forEach> ---遍历List集合Map集合遍历
Map<String,String> map = new HashMap<String,String>();
map.put("aaa","哈哈");
pageContext.serAttribute("map",map); ---放到page域里面
<c:forEach var="entry" items="${ map }"> ---遍历Map
${ entry.key } -- ${ entry.value } ---取出key 和 value
</c:forEach>遍历从1到10
<c:forEach var="i" begin="1" end="10" step="2"> ${ i } </c:forEach>遍历从100到300还根据条件变颜色
<c:forEach var="i" begin="100" end="300" step="5" varStatus="status">
<c:if test="${ status.count % 3 == 0 }">
<font color="red">S{ i }</font>
</c:if>
<c:if test="${ status.count % 3 != 0 }">
S{ i }
</c:if>EL的函数库操作字符串的
${ fn:contains("Hello World","Hello") } ----包不包含hello
${ fn:length("HelloWorld") } ---字符串的长度
${ fn:toLowerCase("ABCDE") } ---大写转小写
${ fn:split("a-b-c-d","-") } ---根据-切分,取出来是个数组,然后遍历一个动态网页
创建一个商品列表页面
创建一个表格,
MVC开发模式:JavaBean + JSP + Servlet,就是MVC设计模式
M:Model 模型层 JavaBean
V:View 视图层 JSP
C:Controller 控制层 Servlet
file:///C:/Users/Administrator/Desktop/%25E5%259B%25BE%25E7%2589%2587/%25E5%25BE%25AE%25E4%25BF%25A1%25E5%259B%25BE%25E7%2589%2587_20180520171532.png?lastModify=1526886450
file:///C:/Users/Administrator/Desktop/%25E5%259B%25BE%25E7%2589%2587/%25E5%25BE%25AE%25E4%25BF%25A1%25E5%259B%25BE%25E7%2589%2587_20180520151852.png?lastModify=1526886450
接收&封装
//接收全部数据数据
Map<String,String[]> map = request.getParameterMap();
//创建对象
User user = new User();
//封装全部数据数据
BeanUtils.populate(user,map);Servlet:接收数据
Servlet:创建对象
Servlet:封装数据
service:调用业务处理层
Dao:调用Dao,并返回处理完的结果
Servlet 转发到JSP
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |