软件使用方式上两种划分 C/S:Client/Server PC客户端、服务器架构 特点:
在服务器当中就主要是一个数据库,把所有的业务逻辑以及界面都交给客户端完成
优点
较为安全,用户界面丰富,用户体验好
缺点
每次升级都要重新安装,针对于不同的操作系统开发,可移植性差
B/S:Browser/Server 浏览器/服务器架构 特点:
基于浏览器访问的应用 把业务层交给服务器来完成,客户端仅仅做界面的渲染和数据的交换
优点
只开发服务器端,可以跨平台、移植性很强
缺点
安全性比较低,用户体验较差
什么是Web
WEB网页,它用于表示网络主机上供外界访问的资源。
Web资源分类 静态Web资源
指web页面中供人们浏览的数据始终是不变。
动态Web资源
指web页面中供人们浏览的数据是由程序产生的,不同时间点访问web页面看到的内容各不相同。
web资源存放在哪里
所有的web资源都放在一个web服务器当中 web服务器就是可以供外界访问web资源的一个软件 web资源放到指定的目录当中,就可以通过对应的端口在浏览器当中访问到。
URL地址
协议://主机地址:端口号/资源地址 http://www.it666.com:80/index.html
客户端
浏览器 Android程序 iOS程序 微信小程序
客户端
浏览器 Android程序 iOS程序 微信小程序
当我们在浏览器当中访问一个网址的时候,为什么就能看到一个页面 一个网址对应的其实是一个IP地址 一个IP地址对应一台电脑 通过IP地址找到对应的电脑 电脑当中安装的有web服务器,通过端口号找到对应服务器 找到对应服务器,服务器把页面返回给你 这样的一个过程就是http请求的过程
BS结构流程图
请求
把客户端请求发送给服务器
响应
服务器把你要的数据发送给客户端
请求与响应都要一定的格式
约定好客户端以什么样的格式把数据给服务器 约定好服务器以什么样的格式把数据给客户端 这个约定使用的就是HTTP协议
约束双方规范的一个准则
HTTP,超文本传输协议(HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议 所有的WWW文件都必须遵守这个标准 设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法 约束请求与响应的归规则
请求 响应 请求与响应都是成对存在的
1.通过浏览器的地址栏 2.通过html当中的form表单 3.通过a链接的href 4.src属性
自动的把客户端的信息发送给服务器
当请求方式是post的时,请求体会有请求的参数 如果请求方式为get,那么请求参数不会出现在请求体中,会拼接在url地址后面
示意图
200 :请求成功 302 :请求重定向 304 :请求资源没有改变,访问本地缓存。 404:请求资源不存在。通常是用户路径编写错误,也可能是服务器资源已删除。 500 :服务器内部错误。通常程序抛异常。
其它状态码
自动的把服务器端的信息传给客户端
响应体是服务器回写给客户端的页面正文 浏览器将正文加载到内存 然后解析渲染显示页面内容
图示
8种请求类型
1.OPTIONS 返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性 2.HEAD 请求指定的页面信息,并返回头部信息 3.GET 请求指定的页面信息,并返回实体主体 4.POST 向指定资源提交数据进行处理请求 5.PUT 向指定资源位置上传其最新内容 6.DELETE 请求服务器删除Request-URL所标识的资源 7.TRACE 回显服务器收到的请求,主要用于测试或诊断 8.CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
常用两种请求 GET
GET 方法向页面请求发送参数 地址和参数信息中间用 ? 字符分隔 http://www.it666.com/hello?key1=value1&key2=value2 查询字符串会显示在地址栏的URL中,不安全,请不要使用GET请求提交敏感数据 GET 方法有大小限制:请求字符串中最多只能有 1024 个字符 GET请求能够被缓存 GET请求会保存在浏览器的浏览记录中 可以添加书签 编码类型为application/x-www-form-urlencoded 只允许ASCII字符类型,不能用二进制流 点击刷新时,不会有反应 GET请求主要用以获取数据
POST
POST 方法向页面请求发送参数 使用POST方法时,查询字符串在POST信息中单独存在,和HTTP请求一起发送到服务器 编码类型为:application/x-www-form-urlencoded or multipart/form-data. 请为二进制数据使用multipart编码 没有历史记录 参数类型没有限制,可以是字符串也可以是二进制流 数据不会显示在地址栏中,也不会缓存下来或保存在浏览记录中,所以看POST求情比GET请求安全,但也不是最安全的方式。如需要传送敏感数据,请使用加密方式传输 查询字符串不会显示在地址栏中 Post传输的数据量大,可以达到2M,而Get方法由于受到URL长度限制,只能传递大约1024字节. Post就是为了将数据传送到服务器段,Get就是为了从服务器段取得数据
JavaSE
Java的标准版,一般用来开发桌面应用程序, 但是在开发桌面应用程序上相对VB,Delphi,VC++并没有什么优势。
JavaEE
也就是Java Enterprise Edition,Java的企业版 开发JavaWeb应用程序,初级的一般是用JSP(Java Server Pages)+servlet+Javabean来开发的 大型的网站一般是使用框架来开发的,struts,hibernate,spring , Mybatis
JavaME
JavaME,Java Micro Edition,Java的微型版 诺基亚手机上运行的Java程序就是指用这个版本开发的程序。
JavaEE的共有13个技术规范
13个技术规范:
sun公司定义了这么多标准,其它公司的人都可以来去根据我这些标准来做JavaEE程序
常见JavaWeb应用服务器
下载地址:https://tomcat.apache.org/download-80.cgi 下载完毕后,解压自己任意指定目录 目录介绍
启动Tomcat
解决方式
找到<Connector prot=“8080” 进行修改
返回的就是一个页面 这个页面可以在webapps目录当中的ROOT文件夹当中找到
webName:
html、jsp、js文件
WEB-INF
classes目录:Java类字节码文件 lib目录:Java类运行时需要的jar包 web.xml文件:当前整个web应用的核心配置文件,可以到ROOT当中复制一个过来 WEB-INF目录下当前的资源不能直接通过浏览器访问,是保护的, 外界不能直接访问 里面都是我们的字节码 相关jar包
部署项目
启动tomcat
<?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">
<absolute-ordering></absolute-ordering>
</web-app>
Context docBase: web应用的文件路径 path:URL入口 reloadable:字节码变化服务器是否重新加载web应用
tomcat服务器体系结构
虚拟主机
Servlet 运行在服务端的Java小程序,是sun公司提供一套规范(接口)
以后写的程序就不在是在本地执行了。而是编译成字节码,放到服务器上来去执行。 编写程序时,不需要有main函数了。因为写完后,就把编写的程序编译成字节码,放到服务器上面。当前发送就一个请求的时候,服务器就会按照一定规则调用编写的代码
1.创建一个web工程 2.在JavaResource中src下创建一个包名称为com.myxq.servlet 3.在创建的servlet包当中创建一个class文件起名为FirstServlet 4.进入该class实现一个Servlet接口,实现它未实现的方法 重点看service方法 在该方法当中写入一句话进行输出 5.在web.xml当中进行配置
当程序要使用某个类时,如果该类还未被加载到内存中
系统会通过加载,连接,初始化三步来实现对这个类进行初始化
什么是类加载器classLoader
负责将.class文件加载到内存中,并为之生成对应的Class对象。 虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。
类加载器分类
创建一个对象的三个阶段
1.源文件阶段 .java的文件 2.字节码阶段 .class 3. 创建对象阶段 new 对象名称
内省:在运行时能够获取JavaBean当中的属性名称和get与set方法
反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意一个方法和属性; 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 想要使用反射,就必须得要获取字节码文件
获取字节码文件
通过字节码创建对象
获取字段
获取方法
越过数组泛型检测 数组如果定义好了泛型就不能添加泛型以外的类型 可以通过反射来去实现添加以外的类型 在一个Integer泛型的数组当中添加字符串类型
Servlet创建过程
Servlet什么时候被创建
init方法
servlet对象创建的时候调用 默认第一次访问时创建
service方法
每次请求都会执行一次
destroy方法
servlet对象销毁的时候执行 默认服务器关闭时销毁
load-on-startup
对象在服务器启动时就创建 值为数字代表优先级 数据越小,优先级越高,不能为负数
< init-params>
< init-name>名称</init-name>
< init-value>值</init-value>
config参数
该servlert的配置信息 获得web.xml当中参数 初始化参数 获取servletContext对象
url-patten 1.完全匹配
2.目录匹配
3.扩展名匹配
缺省Servlet 访问的资源不存在时,就会找缺省的地址
<url-patten>/</url-patten>
全局Web.xml
对于部署在服务器上的所有应用都有效 先到自己工程当中找web.xml配置 再到全局web.xml当中去找配置 如果两个当中有相同的配置,自己当中配置的内容会生效
静态资源加载过程 1. 在path后面写的静态资源名称index.html或者是其它的.html它都是会找ur-patten当中有没有匹配的内容 2. 如果有,就加载对应的servlet,如果没有就到自己配置当中找缺省的url-patten 3. 如果自己配置文件当中没有缺省的,就会找全局配置缺省的url-patten 4. 在全局配置当中有一个缺省的url-patten 对应的是default的Servlet 5. defaultServlet内部会到当前访问的工程根目录当中去找对应的名称的静态资源,如果有,就把里面的内容逐行读出。响应给浏览器。 如果没有,就会报404错误
欢迎页面
Welcome-file-list 不写任何资源名称的时候,会访问欢迎页面 默认从上往下找
使用注解创建Servlet 现在创建Servlet存在的问题 每一次都要去实现Servlet接口 都要去做配置web.xml 从Servlet3.0开始可以直接使用注解的形式来去使用Servlet
在创建好的Servlet上面有会有一个@WebServlet(name="/Servlet") 这个就是一个注解 就相当于在代码上添加了一个小插件。 贴上这个注解后,就不用再去做配置文件,会在内部自动帮你去做 括号当中的内容就是url-patten的内容,要在地址栏当中path后面跟的内容
HttpServlet 直接new的Servlet它是一个HttpServlet 它是GenericServlet的子类, GenericServlet实现了Servlet接口,HttpServlet是专门负责处理http请求与响应的,以后创建Servlet时,直接使用httpServlet
HttpServlet方法 service:每一次发送请求的时候就会调用,当写了service就会不再调用 get或post: doGet:当发送get请求时调用 doPost:当发送post请求的时候调用
内部方法调用过程
ServletContext代表是一个web应用的上下文对象(web应用对象) 里面封装的都是web应用信息 一个ServletContext对应一个应用
在服务器一启动的时候就会创建 在服务器关闭的时候销毁
初始化参数不能再某一个Servlet当中来去配置。在最外层来去配置
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200711173749361.png)
获得Web应用中某一个资源的资源的绝对路径
context.getRealPath("文件")
//相对的是web应有根目录
context.getRealPath("index.html")
//D:\Java\Tomcat\apache-tomcat-7.0.85\webapps\bei\index.html
//在会你写的名称前面自动拼接上当前工程的绝对地址
只要是一个域对象上,基本上里面都有这几个方法
通过response设置响应行,响应头 ,响应体
response.setState(Int code)
add
add代表添加新的内容
addHeader(String name,String value)
addIntHeader(String name,int value)
addDateHeader(String name,date)
示例
set
set代表设置,已经存在的内容
setHeader(String name,String value)
setIntHeader(String name,int value)
setDateHeader(String name,Date value)
添加两个相同的name
重定向 什么是重定向
到服务器当中去找servlet1 servlet1当中没有这个资源,告诉你去找servlet2 再去发送一个请求到servlet2
重定向状态码:302
特点:
设置重定向 设置响应码 设置响应头
封装的重写向 每次都要写状态码,和location比较麻烦 就给封装了一个方法
response.sendRedirect("/bei/servlet2")
定时刷新重定向
response.setHeader("refresh","5;url=http://www.baidu.com")
/*
5代表5秒
url的值为5秒后要去跳转的地址
*/
response.getwrite().wirte(“要写的内容”)
默认情况下写的中文内容会乱码 把写的内容存到缓存区中使用的是ISO8859 ISO8859不支持中文,所以会乱码
在存之前设置可以设置存放的编码
response.setCharacterEncoding("UTF-8")
告知浏览器使用的是utf-8编码
response.setHeader("Content-Type", "text/html;charset=UTF-8");
示例
上面代码只需要写第二句就行, tomcat看到设置了为utf-8的编码,它在存在的时候也会使用utf-8的编码 使用封装写法
response.setContentType("text/html;charset=UTF-8");
read(byte[] b) 一次读取多个字节,并存放到数组b中 上面是一次一滴一滴给你,这种是一次装一水桶再给你
读取全部的数据
FileOutputSteam write():一次性写一个字符 write(buffer): 一个性写多个字符 write(buffer,0,len): 一次性写指定个数的字符
response注意点 getWrite()和getOutputSteam不能同时调用
需求:把服务器当中的文件直接下载到电脑当中
下载文件
步骤
1.接收文件名参数 2.获取mime类型 3.设置浏览器响应类型 4.告诉浏览器以附件形式下载 5.获取文件的绝对路径 6.读取文件流 7.获取输出流 8.把内容写出到输出流
//1.接收文件名参数
String filename = request.getParameter("filename");
String mime = this.getServletContext().getMimeType(filename);
response.setContentType(mime);
response.setHeader("Content-Disposition", "attachment;filename="+filename);
//2.获取文件的绝对路径
String path = this.getServletContext().getRealPath("download/"+filename);
System.out.println(path);
//3.读取文件流
FileInputStream in = new FileInputStream(path);
//4.获取输出流
ServletOutputStream out = response.getOutputStream();
//5.把内容写出到输出流
byte[] buffer = new byte[1024];
int len = 0;
while((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
解决中文名称乱码问题
高版本tomcat中的新特性:就是严格按照 RFC 3986规范进行访问解析,而 RFC 3986规范定义了Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ]) …/conf/catalina.properties中,找到最后注释掉的一行 #tomcat.util.http.parser.HttpParser.requestTargetAllow=| ,改成tomcat.util.http.parser.HttpParser.requestTargetAllow=|{},表示把{}放行
1.把获取的字符串参数的字节码获取,再重新使用utf-8编码 2.在设置以附件形式打开时, 不同的浏览器会对默认的名字进行解码 所以根据不同的浏览器,要对名称进行编码之后,再放入文件名
对文件名进行编码
不同的浏览器编码不一样 要先获取agent,取出浏览器的类型 根据不同的浏览器类型进行编码
步骤 1.接收文件名称 2.获取mimeType 3.设置浏览器响应类型 4.先对传入的参数转成二进制流,再使用UTF-8进行编码 5.获取浏览器的信息 6.判断是哪一种浏览器,根据不同的浏览器获取一个编码的文件名 7.设置以附件形式下载,传的名称是编码过的名称 8.获取文件的绝对路径 9.读取文件流 10.获取输出流 11.把文件写到响应当中 示例代码
// 获取客户端信息
String agent = request.getHeader("User-Agent");
// 定义一个变量记录编码之后的名字
String filenameEncoder = "";
if (agent.contains("MSIE")) {
// IE编码
filenameEncoder = URLEncoder.encode(filename, "utf-8");
filenameEncoder = filenameEncoder.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐编码
BASE64Encoder base64Encoder = new BASE64Encoder();
filenameEncoder = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 浏览器编码
filenameEncoder = URLEncoder.encode(filename, "utf-8");
}
CheckCodeServlet 生成图片验证码的Servlet
package com.it666.code;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
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;
@WebServlet("/CheckCodeServlet")
public class CheckCodeServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 集合中保存所有成语
private List<String> words = new ArrayList<String>();
@Override
public void init() throws ServletException {
// 初始化阶段,读取new_words.txt
// web工程中读取 文件,必须使用绝对磁盘路径
String path = getServletContext().getRealPath("/WEB-INF/words.txt");
try {
BufferedReader reader = new BufferedReader(new FileReader(path));
String line;
//把读的成语全部添加到一个集合当中
while ((line = reader.readLine()) != null) {
words.add(line);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 禁止缓存
response.setHeader("Cache-Control", "no-cache");
//设置过期时间为立即过期
response.setDateHeader("Expires", 0);
int width = 120;
int height = 30;
// 步骤一 绘制一张内存中图片
BufferedImage bufferedImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
// 步骤二 图片绘制背景颜色 ---通过绘图对象
Graphics graphics = bufferedImage.getGraphics();// 得到画图对象 --- 画笔
// 绘制任何图形之前 都必须指定一个颜色
graphics.setColor(getRandColor(200, 250));
graphics.fillRect(0, 0, width, height);
// 步骤三 绘制边框
graphics.setColor(Color.WHITE);
graphics.drawRect(0, 0, width - 1, height - 1);
// 步骤四 四个随机数字
Graphics2D graphics2d = (Graphics2D) graphics;
// 设置输出字体
graphics2d.setFont(new Font("宋体", Font.BOLD, 18));
Random random = new Random();// 生成随机数
int index = random.nextInt(words.size());
String word = words.get(index);// 获得成语
System.out.println(word);
// 定义x坐标
int x = 10;
for (int i = 0; i < word.length(); i++) {
// 随机颜色
graphics2d.setColor(new Color(20 + random.nextInt(110), 20 + random
.nextInt(110), 20 + random.nextInt(110)));
// 旋转 -30 --- 30度
int jiaodu = random.nextInt(60) - 30;
// 换算弧度
double theta = jiaodu * Math.PI / 180;
// 获得字母数字
char c = word.charAt(i);
// 将c 输出到图片
graphics2d.rotate(theta, x, 20);
graphics2d.drawString(String.valueOf(c), x, 20);
graphics2d.rotate(-theta, x, 20);
x += 30;
}
// 将验证码内容保存session
//request.getSession().setAttribute("checkcode_session", word);
//把生成的验证码存放到全局域对象当中
this.getServletContext().setAttribute("checkCode", word);
// 步骤五 绘制干扰线
graphics.setColor(getRandColor(160, 200));
int x1;
int x2;
int y1;
int y2;
for (int i = 0; i < 30; i++) {
x1 = random.nextInt(width);
x2 = random.nextInt(12);
y1 = random.nextInt(height);
y2 = random.nextInt(12);
graphics.drawLine(x1, y1, x1 + x2, x2 + y2);
}
// 将上面图片输出到浏览器 ImageIO
graphics.dispose();// 释放资源
//将图片写到response.getOutputStream()中
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
/**
* 取其某一范围的color
*
* @param fc
* int 范围参数1
* @param bc
* int 范围参数2
* @return Color
*/
private Color getRandColor(int fc, int bc) {
// 取其随机颜色
Random random = new Random();
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
}
words.txt 词库
码蚁小强
行尸走肉
金蝉脱壳
百里挑一
金玉满堂
背水一战
霸王别姬
天上人间
不吐不快
海阔天空
情非得已
满腹经纶
兵临城下
春暖花开
插翅难逃
黄道吉日
天下无双
偷天换日
两小无猜
卧虎藏龙
珠光宝气
簪缨世族
花花公子
绘声绘影
国色天香
相亲相爱
八仙过海
金玉良缘
掌上明珠
皆大欢喜
逍遥法外
生财有道
极乐世界
情不自禁
愚公移山
龙生九子
精卫填海
海市蜃楼
高山流水
卧薪尝胆
壮志凌云
金枝玉叶
四海一家
穿针引线
无忧无虑
无地自容
三位一体
落叶归根
相见恨晚
惊天动地
滔滔不绝
相濡以沫
长生不死
原来如此
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function change(obg) {
obg.src="CheckCodeServlet?time="+new Date().getTime();
}
</script>
</head>
<body>
<form action="registServlet">
<img src="CheckCodeServlet" onclick="change(this)"><br>
<input type="text" placeholder="请输入验证码" name="code"><br>
<input type="submit" value="验证">
</form>
</body>
</html>
registServlet 验证
@WebServlet(value = "/registServlet")
public class registServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String code = req.getParameter("code");
String checkCode =(String) this.getServletContext().getAttribute("checkCode");
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
System.out.println(checkCode);
System.out.println(code);
if(code.equals(checkCode)){
resp.getWriter().write("验证成功");
}else{
resp.getWriter().write("验证失败");
resp.setHeader("refresh","3;url=/javaweb01");
}
}
}
如何获取请求行, 请求头,请求体
获取请求方法
String getMethod()
获取请求资源
String getRequestURL()
获取应用名称
String getContextPath()
获取get查询参数
String getQueryString()
3.打印所有的请求头和请求头内容
referer 告诉服务器我是从哪个页面链接过来的
注意事项 通过以下方式发送请求才会获取
通过以下方式不会有referer
req.getParameter("名称")
2. 获取多个值
req.getParameterValues("名称")//返回的是一个数组
3. 获取所有请求参数名称
req.getParameterNames()//返回的是一个枚举
4.获取所有请求参数
req.getParameterMap()//获取所有请求参数的key-value集合Map<String,String[]>
什么时候使用get方式与post方式
造成乱码的原因:发送请求时, 会对参数进行编码,编码使用的是ISO8859-1 不支持中文,所以乱码 通用解决办法
重定向与请求转发的区别
重定向
请求转发
实现转发
request域对象 在一次请求过程当中 request是共享的。在一个servlet当中设置的参数,转发到另外一个servlet,取出来的是同一个
生命周期: 1. 创建:发送一个请求时创建一个request对象 2. 销毁:请求结束,浏览器给出响应时,销毁 作用范围: 一次请求当中
客户端地址与服务器端地址 客户端地址
客户端访问服务器使用的地址 服务器外部地址 在写的时候要写上web应用的名称 /应用名称/资源
服务器地址
在服务内部当中使用的地址 不需要写web应用名称 /资源名称
是一款小巧的代码生成工具 自动生成getter与setter方法 提高开发效率 代码简洁,直观,减少大量冗余代码 减少后期的维护成本
什么是会话
用户开一个浏览器 点击多个超链接,访问服务器多个web资源 然后关闭浏览器,整个过程称之为一个会话。 和打电话一样,电话接收,开始会话,电话 挂断,结束会话
会话技术解决什么问题
保持各个客户端自己的数据 每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,程序要想办法为每个用户保存这些数据
服务器怎样把Cookie写 给客户端
Cookie cookie = new Cookie(String cookieName,String cookieValue);
cookie会以响应头的形式发送给客户端 Cookie只能存储非中文的字符串
向客户端发送cookie
response.addCookie(cookie名称)
访问 第一次访问时, 请求头当中没有cookie 第一次访问时, 响应当中会看到set-cookie 再一次访问时, 请求头当中就能够看到cookie信息 访问服务器的任何资源,一般情况下都会把cookie带去过
默认cookie的会话级别
打开浏览器,关闭浏览器为一次会话 如果不设置持久化时间,cookie会存储在浏览器的内存中,浏览器关闭 cookie信息销毁
设置Cookie在客户端的存储时间
cookie.setMaxAge(int seconds);
设置的时间为秒 如果设置持久化时间,cookie信息会被持久化到浏览器的磁盘文件里 过期会自动删除
访问某一个资源时,要不要带cookie信息 如何每一外资源都携带,会影响传输速度
如果不设置携带路径 默认情况下会在访问创建cookie的web资源相同的路径 都携带cookie信息
在myxq/CookieServlet下创建的cookie
在myxq/下的index.jsp访问时会携带cookie
不是在myxq下,不会携带cookie
设置携带路径
cookie.setPath(String path);
cookie.setPath(“/CookiePro/cookieServlet”);
只有访问cookieServlet才携带cookie信息
cookie.setPath(“/CookiePro”);
访问指定的工程时, 都会携带cookie信息
cookie.setPath(“/”);
访问服务器下部署的所有工程时都会携带cookie
如果想删除客户端的已经存储的cookie信息 使用同名同路径的持久化时间为0的cookie进行覆盖即可
通过Request对象的getCookies()方法 获取的是所有的cookie 要进行遍历,找出自己名称的那一个 示例代码
需求:访问时,显示上次的登录时间 步骤
示例代码
session简介
Session技术是将数据存储在服务器端的技术 会为每个客户端都创建一块内存空间存储客户的数据 客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内存空间 Session需要借助于Cookie存储客户的唯一性标识SESSIONID
Session如何办到在一个servlet当中存数据,在别的servlet当中取出当初存储的数据
每一个用户访问服务器时,会给该用户分配他自己对应的存储空间 并且创建的存储空间有一个编号我们称为SessionID 第一次访问时,会把对应的sessionID以Cookie的形式写给浏览器 下次再访问时, 会携带sessionID,找到当初创建的那个存储空间 在对应的存储空间当中取出数据
HttpSession session = request.getSession();
获得专属于当前会话的Session对象 如果服务器端没有该会话的Session对象,会创建一个新的Session返回 如果已经有了属于该会话的Session直接将已有的Session返回 本质就是根据SESSIONID判断该客户端是否在服务器上已经存在session了
Session对象也是一个域对象
session.setAttribute(String name,Object obj);
session.getAttribute(String name);
session.removeAttribute(String name);
其它两个域对象 servletContext域 request域
session.invadate
浏览器关闭,session就销毁,这句话是不正确的
作用范围
默认在一次会话中,也就是说在,一次会话中任何资源公用一个session对象
默认情况下,第一次获取session对象时, 会帮你创建一个session,可以获取该Session的ID 会自动的把id写到cookie当中
存在的问题 第一次访问sevlet1时存储一些数据 在第二个servlet当中直接取数据,可以直接取到 把浏览器关闭 直接到第二个servlet当中取数据,发现取不到数据了。
原因 因为访问的时候要求带着jsessionID.由于默认情况下,存储cookie是会话级别的,关闭浏览器,就没有了。所以再次打开浏览器。访问资源时,没有jsessionID. 就会创建一个新的session. 就取不到数据了
解决办法 在写数据时,自己手动去把sessionID写到cookie当中 写的时候,设置持久化时间 注意,key值一定是和它自动生成的key值是一样的
JSP全名为Java Server Pages 中文名叫java服务器页面 它是在传统的网页HTML文件(.htm,.html)中插入Java程序段和JSP标记 后缀名为(*.jsp)。 其根本是一个简化的Servlet设计
直接使用Html文件是没有办法输出Java当中的信息 使用servlet来去输出一个网页非常的麻烦 于是就出现了jsp,又能写html,又能写Java代码
jsp本质就是一个servlet jsp在第一次被访问时会被Web容器翻译成servlet 第一次访问 index.jsp index_jsp.java
编译成index_jsp.class运行
可以在Tomcat的work目录中可以找到 下次一次访问时, 会看一下里面的内容有没有发生变化,如果变化了, 从新翻译加载 整个过程是全局web.xml当中有一个叫
翻译的过程就是JspServlet做的
静态数据,如HTML JSP脚本元素和变量 JSP指令,如include指令 JSP标签动作 用户自定义标签
<%java代码%> 内部的java代码翻译到service方法的内部
<%=java变量或表达式> 会被翻译成service方法内部out.print()
<%!java代码%> 会被翻译成servlet的成员的内容
HTML注释:< !–注释内容–> 可见范围 jsp源码、翻译后的servlet、页面
**Java注释://单行注释 / 多行注释 / 可见范围 jsp源码 翻译后的servlet,页面中看不到
Jsp注释 <%–注释内容–%> 可见范围 jsp源码可见
JSP指令用于设置整个JSP页面的相关信息 以及用于JSP页面与其它容器之间的通信
用于设定整个JSP页面的属性和相关功能 page指令共有11个属性
多个属性之间使用空格隔开
作用: 表示在JSP编译时插入一个包含文件或者代码的文件 include指令所包含的文件名不能是一个变量url,只能是静态的文件名
静态包含 将两个jsp页面接着到一起, 然后再翻译成servlet
作用
声明JSP文件使用了标签库 有哪些标签库 JSP标准标签库 第三方标签库 自定义标签库
页面包含
<jsp:include page="被包含的页面"></jsp:include>
动态包含 各自翻译自己的页面,然后再引入
请求转发
<jsp:forward page="要转发的资源"></jsp:forward>
jsp被翻译成servlet之后,service方法中有9个对象定义并初始化完毕
可以直接使用这9个对象
out的类型:JspWriter out作用就是想客户端输出内容 out.write() out缓冲区默认8kb 可以设置成0 代表关闭out缓冲区内容直接写到respons缓冲区 out写的内容写到out缓冲区当中 最后再把out缓冲区当中的内容合并到response缓冲区当中
得到用户请求信息对象
服务器向客户端的响应对象
服务器配置,可以取得初始化参数
用来保存用户会话的信息
所有用户的共享信息,就是servletContext
指当前页面转换后的Servlet类的实例
jsp页面的上下文对象
是一个域对象
setAttribute(String name,Object obj)
getAttribute(String name)
removeAttrbute(String name)
可以向指定的其他域中存取数据
setAttribute(String name,Object obj,int scope)
setAttribute(“name”,"lk",PageContext.REQUEST_SCOPE);
getAttribute(String name,int scope);
getAttribute("lk",PageContext.REQUEST_SCOPE);
removeAttrbute(String name,int scope);
findAttribute(String name);
自动到所有的域当中找数据
从小到大的范围搜索数据
依次从pageContext域,request域,session域,application域中获取属性
在某个域中获取后将不在向后寻找
可以获得其他8大隐式对象
pageContext.getRequest()
pageContext.getSession()
表示JSP页面所发生的异常,在错误页中才起作用 只有是错误页面的时候,才会有该对象
EL(Express Lanuage)表达式可以嵌入在jsp页面内部 减少jsp脚本的编写 EL出现的目的是要替代jsp页面中脚本的编写。
EL最主要的作用是获得四大域中的数据
从四大域当中取数据
pageContext
${pageScope.key};
request
${requestScope.key}
session
${sessionScope.key}
application
${applicationScope.key}
简写
${EL表达式}
EL从四个域中获得某个值${key} 依次从pageContext域,request域,session域,application域中 获取属性 在某个域中获取后将不在向后寻找
EL执行表达式 内部可以进行运算,只要有结果
${1+1}
${empty user}
${user==null?true:false}
JSTL(JSP Standard Tag Library),JSP标准标签库 可以嵌入在jsp页面中使用标签的形式完成业务逻辑等功能 jstl出现的目的同el一样也是要代替jsp页面中的脚本代码
JSTL标准标签库有5个子库
把JSTL标签库jar包引入工程当中 引入标签库
<%@ taglib uri=“http://java.sun.com/jsp/jstl/core” prefix=“c”%>
<c:if test="${1==1 }">满足条件时,中间的内容才会显示出来</c:if>
通过是结合EL表达式一起使用,EL从域中取数据,使用JSTL进行判断或者遍历
if标签使用 需求:用户登录成功时, 进入首页中,显示用户名 步骤 1.登录成功时,把用户写到session域当中
2.在首页当中进行判断,从session域当中取数据 3.通过EL结合JSTL进行判断
遍历字符串集合
遍历对象集合
遍历map
什么是开发模式 模式在开发过程中总结出的“套路”,总结出的一套约定俗成的设计模式
JavaEE模式 model1模式
技术组成 :jsp+javaBean 弊端:业务多时,导致jsp页面容易混乱
model2模式
jsp+servlet+javaBean:优点 开发中使用各个技术擅长的方面 servlet擅长java的业务代码 jsp擅长页面的展示
MVC
Model:javaBean 封装数据 View:JSP 页面展示 Controller:servlet 获取数据,对数据进行封装,传递数据、指定页面显示
三层架构
web层:与客户端交互 service层:复杂业务逻辑 dao层:与数据库进行交互
当某一个对象发生某一个事件时,通知另一个对象,让另一个对象做某事
定义好协议 遵守协议 成为代理 调用代理方法
监听器的内部使用的就是代理模式
能监听某个对象的状态变化的组件 监听域对象的变化
被监听的对象: request session servletContext
监听事件源的对象 8个监听器
监听器与事件源相绑定
监听到事件源变化时,去做什么事情
监听ServletContext域的创建与销毁的监听器ServletContextListener
ServletContext域生命周期 服务器启动创建 服务器关闭销毁
作用:
初始化的工作:初始化对象 初始化数据 加载数据库驱动 连接池的初始化 加载一些初始化的配置文件 任务调度
就一个对象被放到session域中
就是这个对象从session域中移除了
是将session内存中的对象持久化(序列化)到磁盘
就是将磁盘上的对象再次恢复到session内存中
filter是对客户端访问资源的过滤,符合条件放行,不符合条件不放行 并且可以对目标资源访问前后进行逻辑处理
访问一个资源的时候,会被过滤器拦截 要在过滤器当中进行放行之后, 才能够访问到对应的servlet
chain.doFilter(req,res)
在发送一个请求时, web容器会先到filter当中,创建三个参数, res,req,chain 在过滤器当中,放行之后,才能够访问到对应的资源 中间的过滤器可能有多个,在一个过滤器当中,可以调用另外一个过滤器 也有可能过滤器没有拦截所有的资源,有些资源可以直接被访问
当filter对象创建时调用
当服务器启动时创建 因为有可能一个filter对应多个servlet 启动时, 先把filter准备好, 访问资源时就可以进行过滤了
filterconfig
当前filter对象的配置信息 和servletConfig差不多, 获取名称,参数 获取servletContext对象 先有的ServletContext
当匹配到mapping时调用dofilter
参数
res
req
FilterChain
过滤器链对象
内部维护着各个filter的索引,并且知道所有filter的顺序
是根据mapping的顺序来执行的
当filter对象销毁时调用
关闭服务器时销毁对象 和servletContext的生命周期是一样
完全匹配 目录匹配 扩展名匹配
可以把路径直接指定某一个servlet 可以有多个servlet_name 开发中基本上使用的都是mapping
配置请求的形式,不是请求方式,是页面跳转的形式
形式分类