JavaWeb
客户端与服务器
CS与BS
软件使用方式上两种划分
C/S:Client/Server PC客户端、服务器架构
特点:
在服务器当中就主要是一个数据库,把所有的业务逻辑以及界面都交给客户端完成
优点
较为安全,用户界面丰富,用户体验好
缺点
每次升级都要重新安装,针对于不同的操作系统开发,可移植性差
B/S:Browser/Server 浏览器/服务器架构
特点:
基于浏览器访问的应用
把业务层交给服务器来完成,客户端仅仅做界面的渲染和数据的交换
优点
只开发服务器端,可以跨平台、移植性很强
缺点
安全性比较低,用户体验较差
Web资源
什么是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协议
什么是协议
约束双方规范的一个准则
什么是HTTP协议
HTTP,超文本传输协议(HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议
所有的WWW文件都必须遵守这个标准
设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法
约束请求与响应的归规则
HTTP组成部分
请求
响应
请求与响应都是成对存在的
请求的发送方式
1.通过浏览器的地址栏
2.通过html当中的form表单
3.通过a链接的href
4.src属性
Http请求
-
请求行
请求方式:POST,GET
请求的资源:Myxq/login.html?username=myxq&pwd=1234
协议版本
HTTP/1.0,发送请求,创建一次连接,获得一个web资源,连接断开
HTTP/1.1,发送请求,创建一次连接,获得多个web资源,保持连接。 -
请求头
请求头是客户端发送给服务器端的一些信息
使用键值对表示key:value
常见请求头
- Referer:浏览器通知服务器,当前请求来自何处。如果是直接访问,则不会有这个头。常用于:防盗链
- If-Modified-Since;浏览器通知服务器,本地缓存的最后变更时间。 Cookie:用于存放浏览器缓存的cookie信息。
- User-Agent:浏览器通知服务器,客户端浏览器与操作系统相关信息
- Connection:保持连接状态。
- Keep-Alive:连接中,close 已关闭 Host:请求的服务器主机名
- Content-Length;请求体的长度
- Content-Type:如果是POST请求,会有这个头,默认值为application/x-www-form-urlencoded,表示请求体内容使用url编码
- Accept:浏览器可支持的MIME类型。文件类型的一种描述方式 text/html ,html文件吗,text/css,css文件,text/javascript,js文件 image/*,所有图片文件
- Accept-Encoding: 浏览器通知服务器,浏览器支持的数据压缩格式。如:GZIP压缩
- Accept-Language:浏览器通知服务器,浏览器支持的语言
自动的把客户端的信息发送给服务器
- 请求体
当请求方式是post的时,请求体会有请求的参数 如果请求方式为get,那么请求参数不会出现在请求体中,会拼接在url地址后面
示意图
Http响应
- 响应行
Http协议
状态码
200 :请求成功
302 :请求重定向
304 :请求资源没有改变,访问本地缓存。
404:请求资源不存在。通常是用户路径编写错误,也可能是服务器资源已删除。
500 :服务器内部错误。通常程序抛异常。
其它状态码
- 成功
200 OK
201 已创建
202 接收
203 非认证信息
204 无内容
205 重置内容
206 部分内容- 重定向
300 多路选择
301 永久转移
302 暂时转移
303 参见其它
304 未修改(Not Modified)
305 使用代理- 客户方错误
401 未认证
402 需要付费
403 禁止(Forbidden)
404 未找到(Not Found)
405 方法不允许
406 不接受
407 需要代理认证
408 请求超时
409 冲突
410 失败
411 需要长度
412 条件失败
413 请求实体太大
414 请求URI太长
415 不支持媒体类型- 服务器错误
500 服务器内部错误
501 未实现(Not Implemented)
502 网关失败
504 网关超时
- 响应头
服务器端将信息以键值对的形式返回给客户端
常见请求头
- Location:指定响应的路径,需要与状态码302配合使用,完成跳转
- Content-Type:响应正文的类型(MIME类型)
- Content-Disposition:通过浏览器以下载方式解析正文
- Set-Cookie:服务器向浏览器写入cookie
- Content-Encoding:服务器使用的压缩格式
- Content-length:响应正文的长度
- Refresh:定时刷新
- Server:服务器名称,默认值:Apache-Coyote/1.1。可以通过conf/server.xml配置进行修改
- Last-Modified:服务器通知浏览器,文件的最后修改时间
自动的把服务器端的信息传给客户端
- 响应体
响应体是服务器回写给客户端的页面正文
浏览器将正文加载到内存
然后解析渲染显示页面内容
图示
请求方式
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就是为了从服务器段取得数据
Tomcat服务器
Java分类
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规范
JavaEE的共有13个技术规范
13个技术规范:
- JDBC: java数据连接,是一种用于执行SQL语句的Java API
- JNDI:Java命名和目录接口。
- EJB: EJB是sun的JavaEE服务器端组件模型,设计目标与核心应用是部署分布式应用程序。
- RMI:远程方法调用,能够让在某个java虚拟机上的对象调用本地对象一样的 调用另一个java虚拟机中高的对象上的方法。
- JSP: java服务器页面,是一个动态内容模板,实现了Html语法中的java扩展。
- Servlet: Servlet是一种小型的Java程序,它扩展了Web服务器的功能。
- XML:是一种可扩展的标记语言
- JMS:是一个Java平台中关于面向消息中间件(MOM)的API, 用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
- Java IDL:Java IDL支持的是一个瞬间的CORBA对象,即在对象服务器处理过程中有效。
- JTS:组件事务监视器,TPM 是一个程序,它代表应用程序协调分布式事务的执行。
- JTA:JTA允许应用程序执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据。
- JavaMail:提供给开发者处理电子邮件相关的编程接口。
- JAF:JAF是一个专用的数据处理框架,它用于封装数据,并为应用程序提供访问和操作数据的接口。
sun公司定义了这么多标准,其它公司的人都可以来去根据我这些标准来做JavaEE程序
常见JavaWeb应用服务器
- weblogic:oracle公司的大型收费web服务器 支持全部javaEE规范
- websphere:IBM公司的大型收费web服务器 支持全部的javaEE规范
- Tomcat:Apache开源组织下的开源免费的中小型的web应用服务器
支持javaEE中的servlet和 jsp规范
Tomcat下载与安装
下载地址:https://tomcat.apache.org/download-80.cgi
下载完毕后,解压自己任意指定目录
目录介绍
- bin:脚本程序,可执行的命令
- conf:配置目录,内部有一个server.xml核心配置文件
- lib:依赖库目录
- logs:日志目录
- temps:临时文件目录
- webapps:web应用发布目录,把开发的项目放到该目录当中运行
- work: tomcat处理jsp的工作目录
启动Tomcat
- 进入到解压目录
- 找到bin目录
- 找到startup.bat双击启动脚本
1. 没有配置JAVA_HOME
在启动过程当中如果没有配置Java_home,就会一闪没了
要在环境变量当中配置JAVA_HOME
2. 端口冲突: 默认的端口是8080
解决方式
- 把占用的端口杀死
netstat -aov 查看端口占用情况 记下占用端口的pid
到任务管理器当中查看任务详细信息,把对应pid给关掉- 到config目录当中修改核心配置文件server.xml
找到<Connector prot="8080"
进行修改
- 通过浏览器访问:http://localhost:8080看到以下界面
返回的就是一个页面
这个页面可以在webapps目录当中的ROOT文件夹当中找到 - shutdown.bat停止脚本
web应用目录结构
webName:
html、jsp、js文件
WEB-INF
classes目录:Java类字节码文件
lib目录:Java类运行时需要的jar包
web.xml文件:当前整个web应用的核心配置文件,可以到ROOT当中复制一个过来
WEB-INF目录下当前的资源不能直接通过浏览器访问,是保护的, 外界不能直接访问
里面都是我们的字节码
相关jar包
使用开发工具构建web工程
- 创建javaEE项目
- 加载Tomcat插件
部署项目
启动tomcat - 访问http://lcalhost:8080
Tomcat优化启动速度
- 在web.xml上添加 absolute-ordering标签
<?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>
- 删除Tomcat下的webapps目录下除Root文件夹的其他文件夹
- 在Root项目下的web.xml中添加absolute-ordering标签
发布程序详解
Context
docBase: web应用的文件路径
path:URL入口
reloadable:字节码变化服务器是否重新加载web应用
tomcat服务器体系结构
- Server整个Servlet容器组合,可以包含一个或多个< Service>
- service:它由一个或者多个Connector组成,以及一个Engine,负责处理所有Connector所获得的客户请求。
- Connector:客户端与程序交互组件,负责接收请求以及向客户端返回响应。
- Engine:处理连接器接收到请求
- Host:虚拟主机
- Context:一个Context对应于一个Web Application
虚拟主机
- 输入网址时, 就会先到host文件当中查找有没有对应的IP地址,如何有就直接访问该IP地址
- 如果没有,就会到外网去找DNS服务器进行域名与IP地址的解析,查找
- 多个域名可以访问同一个IP
- 一个IP对应一台电脑
Servlet
什么是Servlet
Servlet 运行在服务端的Java小程序,是sun公司提供一套规范(接口)
- servlet接收响应请求
- filter过滤器
- listener监听器 用来处理客户端请求、响应给浏览器的动态资源 servlet的实质就是java代码,通过java的API动态的向客户端输出内容
以后写的程序就不在是在本地执行了。而是编译成字节码,放到服务器上来去执行。
编写程序时,不需要有main函数了。因为写完后,就把编写的程序编译成字节码,放到服务器上面。当前发送就一个请求的时候,服务器就会按照一定规则调用编写的代码
Servlet快速入门
1.创建一个web工程
2.在JavaResource中src下创建一个包名称为com.myxq.servlet
3.在创建的servlet包当中创建一个class文件起名为FirstServlet
4.进入该class实现一个Servlet接口,实现它未实现的方法
重点看service方法
在该方法当中写入一句话进行输出
5.在web.xml当中进行配置
反射
类的加载时机制
当程序要使用某个类时,如果该类还未被加载到内存中
系统会通过加载,连接,初始化三步来实现对这个类进行初始化
- 加载
就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。 - 连接
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值 - 初始化
初始化成员变量等等
加载时机
- 创建类的实例
- 访问类的静态变量,或者为静态变量赋值
- 调用类的静态方法
- 初始化某个类的子类
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
类加载器
什么是类加载器classLoader
负责将.class文件加载到内存中,并为之生成对应的Class对象。
虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。
类加载器分类
- 根类加载器
也被称为引导类加载器,负责Java核心类的加载 比如System,String等。在JDK中JRE的lib目录下rt.jar文件中- 扩展类加载器
负责JRE的扩展目录中jar包的加载。 在JDK中JRE的lib目录下ext目录- 系统类加载器
负责在JVM启动时加载来自java命令的class文件 以及classpath环境变量所指定的jar包和类路径
什么是反射
创建一个对象的三个阶段
1.源文件阶段 .java的文件
2.字节码阶段 .class
3. 创建对象阶段 new 对象名称
内省:在运行时能够获取JavaBean当中的属性名称和get与set方法
反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
想要使用反射,就必须得要获取字节码文件
获取字节码文件
- Object类的getClass()方法:判断两个对象是否是同一个字节码文件
- 静态属性class:当作静态方法的锁对象
- Class类中静态方法forName() :读取配置文件
示例
通过字节码创建对象
- 通过无参构造创建对象
- 获取字节码
- 调用字节码的newInstance()方法
- 通过有参构造创建对象
- 获取字节码的构造器
clazz.getConstructor(type.class)
因为在反射阶段操作的都是字节码,不知道具体的类型,只有在创建对象的时候才去给实际参数 - 通过构造器创建对象
调用构造器的newInstance方法并传入参数
- 获取字节码的构造器
获取字段
- 获取公共的字段
- 获取私有的字段
获取方法
越过数组泛型检测
数组如果定义好了泛型就不能添加泛型以外的类型
可以通过反射来去实现添加以外的类型
在一个Integer泛型的数组当中添加字符串类型
Servlet创建过程
Servlet生命周期
Servlet什么时候被创建
- 默认情况下第一次访问的时候创建
- 可以通过配置文件设置服务器启动的时候就创建
init方法
servlet对象创建的时候调用
默认第一次访问时创建
service方法
每次请求都会执行一次
destroy方法
servlet对象销毁的时候执行
默认服务器关闭时销毁
load-on-startup
对象在服务器启动时就创建
值为数字代表优先级
数据越小,优先级越高,不能为负数
Servlet配置信息
< 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
不写任何资源名称的时候,会访问欢迎页面
默认从上往下找
httpServlet
使用注解创建Servlet
现在创建Servlet存在的问题
每一次都要去实现Servlet接口
都要去做配置web.xml
从Servlet3.0开始可以直接使用注解的形式来去使用Servlet
-
创建Servlet
在创建好的Servlet上面有会有一个@WebServlet(name="/Servlet")
这个就是一个注解
就相当于在代码上添加了一个小插件。
贴上这个注解后,就不用再去做配置文件,会在内部自动帮你去做
括号当中的内容就是url-patten的内容,要在地址栏当中path后面跟的内容 -
使用注解时的注意点
在web.xml当中要有一个配置
metadata-complete:是否扫描类当中定义的注解,值为true和false,当为true的时候不扫描,为false扫描,要使用注解就要把此值设置为false
HttpServlet
直接new的Servlet它是一个HttpServlet
它是GenericServlet的子类, GenericServlet实现了Servlet接口,HttpServlet是专门负责处理http请求与响应的,以后创建Servlet时,直接使用httpServlet
HttpServlet方法
service:每一次发送请求的时候就会调用,当写了service就会不再调用
get或post:
doGet:当发送get请求时调用
doPost:当发送post请求的时候调用
内部方法调用过程
- 当接收到一个请求时, tomcat就会找对应的service方法
- 如果当中servlet当中没有存在service方法,就会到它的父类当中去找
- 在父类当中找到service是参数为ServletRequest,在会内部把参数转为httpServlet
- 转换完毕后会再继续调用参数为httpServletRequest的service方法
5. 在此方法当中会获取参数的类型,根据不同的参数类型再去调用不同的方法
上下文对象-请求对象-响应对象
ServletContext
什么是ServletContext
ServletContext代表是一个web应用的上下文对象(web应用对象)
里面封装的都是web应用信息
一个ServletContext对应一个应用
ServletContext的生命周期
在服务器一启动的时候就会创建
在服务器关闭的时候销毁
如何获得上下文
- 通过init方法当中一个参数ServletConfig来获取
- 直接在HttpServlet当中获取
this.getServletContext
这种方法本质还是通过config来去获取的
获取全局的初始化参数
初始化参数不能再某一个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
//在会你写的名称前面自动拼接上当前工程的绝对地址
ServletContext是一个域对象
- 什么是域?
能够存储数据 - 域对象
能够存取数据数据就的对象 - ServletContext域对象的作用范围
整个web应用
所有的web资源都可以进行存取数据
数据是可以共享的 - 获取完ServletContext之后向里面写数据
context.setAttribute(String name,Object value); - 获取完ServletContext之后,通过name取出存放的数据
context.getAttribute(String name); - 获取完ServletContext之后,删除指定名称的值
Context.removeAttribute(String name);
只要是一个域对象上,基本上里面都有这几个方法
response
response响应过程
- 在去发送一个请求时, 会找到tomcat引擎
- 引擎会找到对应的web应用
并且会创建request对象和response对象 - 找到应用后, 会执行应用的web.xml再去根据url-patten的内容创建Servlet对象
- 并且会调用Servlet对象的service方法,并且把创建的request对象和response对象传入到方法当中
拿到response对象后, 自己可以往响应当中写入一些自己给客户端的内容
通过response.getwrite().wirte("写的内容")方法进行写入 - 写的内容,是存到一个response缓冲区当中
- 当方法执行结束之后, tomcat就会从response缓冲区当中取出数据
取出你的数据同时,它自己还会自动的往里面添加一些服务器相关的信息进去
所以响应给浏览器时, 可以看到除了自己写的内容, 还会有一些服务器相关的信息
学习响应
通过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秒后要去跳转的地址
*/
设置响应体
- 通过write方法来写
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");
- 通过OutPutStream来写
FileInputSteam
read方法读取一个字节
read(byte[] b)
一次读取多个字节,并存放到数组b中
上面是一次一滴一滴给你,这种是一次装一水桶再给你
读取全部的数据
FileOutputSteam
write():一次性写一个字符
write(buffer): 一个性写多个字符
write(buffer,0,len): 一次性写指定个数的字符
response注意点
getWrite()和getOutputSteam不能同时调用
下载功能
需求:把服务器当中的文件直接下载到电脑当中
下载文件
- 直接使用a标签来去下载
有些内容会浏览器自动解析
浏览器不能解析的文件才会被下载
- 通过发送Servlet请求来去下载
- 通过发送一个Servlet请求,把文件名发送给服务器
- 发送给服务器后,接收到文件名参数,获取文件的绝对地址
- 通过流的形式来去写到浏览器
- 还得要告诉文件是什么类型
浏览器是以MIME的类型来识别类型
this.getServletContext().getMimeType(“文件名称”)
设置响应的类型
res.setContentType("MIME类型") - 设置响应头,告诉浏览器不要去解析,是以附件的形式打开,
res.setHeader("Content-Dsiposition","attachment;filename="+文件名)
步骤
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");
}
}
}
request
学习请求
如何获取请求行, 请求头,请求体
获取请求行
获取请求方法
String getMethod()
获取请求资源
String getRequestURL()
获取应用名称
String getContextPath()
获取get查询参数
String getQueryString()
获取请求头
-
获取所有的请求头名称
-
获取指定的头信息
3.打印所有的请求头和请求头内容
referer
告诉服务器我是从哪个页面链接过来的
注意事项通过以下方式发送请求才会获取
- 直接用< a href="">
- 用Submit或提交的表单(POST或GET)
- 用JAvaScript提交的表单(POST或GET)
通过以下方式不会有referer
- 从收藏夹链接
- 单击主页或自定义的地址
- 在浏览器中直接输地址
获取请求体
- 获取一个值
req.getParameter("名称")
2. 获取多个值
req.getParameterValues("名称")//返回的是一个数组
3. 获取所有请求参数名称
req.getParameterNames()//返回的是一个枚举
4.获取所有请求参数
req.getParameterMap()//获取所有请求参数的key-value集合Map<String,String[]>
解决中文乱码问题
什么时候使用get方式与post方式
- 发送的参数不需要写到数据库当中使用get
- 发送的参数需要保存到数据库当中使用post
form一般提交数据的数据为post
造成乱码的原因:发送请求时, 会对参数进行编码,编码使用的是ISO8859-1 不支持中文,所以乱码
通用解决办法
- 获取对应的参数
- 通过iso8859-1转回二进制位,再以utf-8的形式转成字符串
- 存在的问题,每一个参数都必须得要转回二进制位,再转为字符串 request方法解决中文乱码
只适用于post
请求转发
重定向与请求转发的区别
重定向
- 找servlet1,通过设置响应,告诉浏览器, 再让浏览器发送请求到servlet2
- 发两次请求
- 地址栏会发生变化
请求转发
- 请求转发只需要发送一次直接,找servlet1,在servlet1当中直接转发给servlet2,不要再告诉浏览器
- 只发送一次请求
- 浏览器地址栏当中还是servlet1,不会发生变化
实现转发
- 通过请求对象获取一个转发器
request.getRequestDispatcher(String path)
返回一个RequestDispatcher- 通过转发器进行转发
调用转发器的forward方法进行转发 disp.forward(req,rep)
request域对象
在一次请求过程当中
request是共享的。在一个servlet当中设置的参数,转发到另外一个servlet,取出来的是同一个
生命周期:
1. 创建:发送一个请求时创建一个request对象
2. 销毁:请求结束,浏览器给出响应时,销毁
作用范围: 一次请求当中
客户端地址与服务器端地址
客户端地址
客户端访问服务器使用的地址
服务器外部地址
在写的时候要写上web应用的名称 /应用名称/资源
服务器地址
在服务内部当中使用的地址
不需要写web应用名称 /资源名称
lombok安装
- 什么是lombok
是一款小巧的代码生成工具
自动生成getter与setter方法
提高开发效率 代码简洁,直观,减少大量冗余代码
减少后期的维护成本
-
安装lombok
下载:https://projectlombok.org/download -
使用lombok
在类上添加注解
常用注解- @Data
该注解相当于同时加上以下注解@Setter - @Getter,@ToString,@EqualsAndHashCode,作用于类中
@Setter @Getter
作用于属性上,自动生成get,set方法.
也可直接作用于类上,全部属性都添加 - @ToString
生成toString方法,默认情况下,会输出类名、所有属性,属性会按照顺序输出,以逗号分割。 - @EqualsAndHashCode
生成equals和hascode方法 - @NoArgsConstructor
无参构造器 - @AllArgsConstructor
全参构造器
- @Data
cookie与Session
会话技术
什么是会话
用户开一个浏览器
点击多个超链接,访问服务器多个web资源
然后关闭浏览器,整个过程称之为一个会话。
和打电话一样,电话接收,开始会话,电话 挂断,结束会话
会话技术解决什么问题
保持各个客户端自己的数据
每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,程序要想办法为每个用户保存这些数据
cookie
学习Cookie
服务器怎样把Cookie写 给客户端
创建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在客户端的存储时间
cookie.setMaxAge(int seconds);
设置的时间为秒
如果设置持久化时间,cookie信息会被持久化到浏览器的磁盘文件里
过期会自动删除
设置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
如果想删除客户端的已经存储的cookie信息
使用同名同路径的持久化时间为0的cookie进行覆盖即可
服务器如何获取客户端携带的cookie
通过Request对象的getCookies()方法
获取的是所有的cookie
要进行遍历,找出自己名称的那一个
示例代码
记录上次登录时间
需求:访问时,显示上次的登录时间
步骤
- 第一次访问时,获取当前的时间,并把它写到cookie当中,响应给浏览器
- 第一次访问,告诉用户是第一次访问
- 用户下次访问时,获取用户携带的cookie,把日期在浏览器当中显示,记录最新的cookie
示例代码
session
session简介
Session技术是将数据存储在服务器端的技术
会为每个客户端都创建一块内存空间存储客户的数据
客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内存空间
Session需要借助于Cookie存储客户的唯一性标识SESSIONID
Session如何办到在一个servlet当中存数据,在别的servlet当中取出当初存储的数据
每一个用户访问服务器时,会给该用户分配他自己对应的存储空间
并且创建的存储空间有一个编号我们称为SessionID
第一次访问时,会把对应的sessionID以Cookie的形式写给浏览器
下次再访问时, 会携带sessionID,找到当初创建的那个存储空间
在对应的存储空间当中取出数据
学习Session
如何获取Session对象
HttpSession session = request.getSession();
获得专属于当前会话的Session对象
如果服务器端没有该会话的Session对象,会创建一个新的Session返回
如果已经有了属于该会话的Session直接将已有的Session返回
本质就是根据SESSIONID判断该客户端是否在服务器上已经存在session了
怎么样向session当中存取数据
Session对象也是一个域对象
session.setAttribute(String name,Object obj);
session.getAttribute(String name);
session.removeAttribute(String name);
其它两个域对象
servletContext域
request域
session的生命周期
-
创建
第一次执行request.getSession()时创建 -
销毁
服务器关闭时
session过期/失效(默认30分钟)
是从最后一次操作结束时计时
手动销毁
session.invadate
浏览器关闭,session就销毁,这句话是不正确的
作用范围
默认在一次会话中,也就是说在,一次会话中任何资源公用一个session对象
JsessioID持久化
默认情况下,第一次获取session对象时, 会帮你创建一个session,可以获取该Session的ID
会自动的把id写到cookie当中
存在的问题
第一次访问sevlet1时存储一些数据
在第二个servlet当中直接取数据,可以直接取到
把浏览器关闭
直接到第二个servlet当中取数据,发现取不到数据了。
原因
因为访问的时候要求带着jsessionID.由于默认情况下,存储cookie是会话级别的,关闭浏览器,就没有了。所以再次打开浏览器。访问资源时,没有jsessionID. 就会创建一个新的session. 就取不到数据了
解决办法
在写数据时,自己手动去把sessionID写到cookie当中
写的时候,设置持久化时间
注意,key值一定是和它自动生成的key值是一样的
JSP
JSP简介
什么是JSP
JSP全名为Java Server Pages 中文名叫java服务器页面
它是在传统的网页HTML文件(.htm,.html)中插入Java程序段和JSP标记
后缀名为(*.jsp)。
其根本是一个简化的Servlet设计
为什么要有JSP
直接使用Html文件是没有办法输出Java当中的信息
使用servlet来去输出一个网页非常的麻烦
于是就出现了jsp,又能写html,又能写Java代码
JSP的工作原理
jsp本质就是一个servlet
jsp在第一次被访问时会被Web容器翻译成servlet
第一次访问
index.jsp
index_jsp.java
编译成index_jsp.class运行
可以在Tomcat的work目录中可以找到
下次一次访问时, 会看一下里面的内容有没有发生变化,如果变化了, 从新翻译加载
整个过程是全局web.xml当中有一个叫
翻译的过程就是JspServlet做的
JSP的组成部分
静态数据,如HTML
JSP脚本元素和变量
JSP指令,如include指令
JSP标签动作
用户自定义标签
JSP脚本元素和变量
在JSP当中写Java代码
<%java代码%>
内部的java代码翻译到service方法的内部
<%=java变量或表达式>
会被翻译成service方法内部out.print()
<%!java代码%>
会被翻译成servlet的成员的内容
JSP注释
HTML注释:< !--注释内容-->
可见范围 jsp源码、翻译后的servlet、页面
**Java注释://单行注释 / 多行注释 /
可见范围 jsp源码 翻译后的servlet,页面中看不到
Jsp注释
<%--注释内容--%>
可见范围 jsp源码可见
JSP指令
什么是指令
JSP指令用于设置整个JSP页面的相关信息
以及用于JSP页面与其它容器之间的通信
有哪些指令
page指令
用于设定整个JSP页面的属性和相关功能
page指令共有11个属性
- contentType
contentType属性指定JSP页面的MIME和编码格式- pageEncoding
pageEncoding属性用来指定JSP文件的编码格式- import
在JSP中引入Java的包和类,多个包之间以逗号隔开- session
指定当前页面是否能获得当前用户的session对象 缺省是true 如果指定为false,那么在该页面中无法使用session,使用的话会提示500错误- errorPage
如果当前页面发生异常
网页会重定向到errorPage所指定的页面进行处理- isErrorPage
允许指定的JSP页面为错误处理页面- language属性
指定页面中使用的脚本语言种类 目前只支持java- extends
用于指定该JSP生成的servlet继承自哪个父类 必须指定包名加类名- buffer
用来设置输出流缓冲区
缓冲区的作用就是为了提高IO性能 也就是说减少write的次数- autoFlush
用来指定当输出流缓冲区满了的时候,是否自动刷新缓冲区- isThreadSafe :缺省值为true 指定该JSP文件是否支持多线程访问
- info
用来设置该jsp文件的介绍信息- isELIgnored
用来标示是否支持EL表达式
多个属性之间使用空格隔开
include指令
作用:
表示在JSP编译时插入一个包含文件或者代码的文件
include指令所包含的文件名不能是一个变量url,只能是静态的文件名
静态包含
将两个jsp页面接着到一起, 然后再翻译成servlet
taglib指令
作用
声明JSP文件使用了标签库
有哪些标签库
JSP标准标签库
第三方标签库
自定义标签库
标签动作
页面包含
<jsp:include page="被包含的页面"></jsp:include>
动态包含
各自翻译自己的页面,然后再引入
请求转发
<jsp:forward page="要转发的资源"></jsp:forward>
隐式对象
jsp被翻译成servlet之后,service方法中有9个对象定义并初始化完毕
可以直接使用这9个对象
1. out
out的类型:JspWriter
out作用就是想客户端输出内容 out.write()
out缓冲区默认8kb
可以设置成0 代表关闭out缓冲区内容直接写到respons缓冲区
out写的内容写到out缓冲区当中
最后再把out缓冲区当中的内容合并到response缓冲区当中
2.request
得到用户请求信息对象
3. response
服务器向客户端的响应对象
4. config
服务器配置,可以取得初始化参数
5. session
用来保存用户会话的信息
6. application
所有用户的共享信息,就是servletContext
7. page
指当前页面转换后的Servlet类的实例
8. pageContext
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()
9. exception
表示JSP页面所发生的异常,在错误页中才起作用
只有是错误页面的时候,才会有该对象
EL/JSTL
EL表达式
什么是EL表达式
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内置11对象
- pageScope: 获取JSP中pageScope域中的数据
- requestScope : 获取JSP中requestScope域中的数据
- sessionScope: 获取JSP中sessionScope域中的数据
- applicationScope : 获取JSP中applicationScope域中的数据
- param: request.getParameter()
- paramValues : rquest.getParameterValues()
- header : request.getHeader(name)
- headerValues : request.getHeaderValues()
- initParam : this.getServletContext().getInitParameter(name)
- cookie: request.getCookies()---cookie.getName()---cookie.getValue()
- pageContext : pageContext获得其他八大对象 获取当前项目的名称 $
EL执行表达式
内部可以进行运算,只要有结果
${1+1}
${empty user}
${user==null?true:false}
JSTL
什么是JSTL
JSTL(JSP Standard Tag Library),JSP标准标签库
可以嵌入在jsp页面中使用标签的形式完成业务逻辑等功能
jstl出现的目的同el一样也是要代替jsp页面中的脚本代码
JSTL标准标签库有5个子库
- Core :核心库 http://java.sun.com/jsp/jstl/core 前缀:c
- I18N:国际化库 http://java.sun.com/jsp/jstl/fmt 前缀:fmt
- SQL http://java.sun.com/jsp/jstl/sql 前缀:sql
- XML http://java.sun.com/jsp/jstl/xml 前缀:x
- Functions http://java.sun.com/jsp/jstl/functions 前缀:fn
把JSTL标签库jar包引入工程当中
引入标签库
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
if标签
<c:if test="${1==1 }">满足条件时,中间的内容才会显示出来</c:if>
通过是结合EL表达式一起使用,EL从域中取数据,使用JSTL进行判断或者遍历
if标签使用
需求:用户登录成功时, 进入首页中,显示用户名
步骤
1.登录成功时,把用户写到session域当中
2.在首页当中进行判断,从session域当中取数据
3.通过EL结合JSTL进行判断
foreach标签
第一种:普通循环
第二种:增加for循环
遍历字符串集合
遍历对象集合
遍历map
JavaEE开发模式
什么是开发模式
模式在开发过程中总结出的“套路”,总结出的一套约定俗成的设计模式
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个监听器
- 注册监听器
监听器与事件源相绑定
- 响应行为
监听到事件源变化时,去做什么事情
监听器划分
三个监听域对象的创建与销毁
- ServletContextListener
- HttpSessionListener
- ServletRequestListener
三个监听域对象当中属性变化
- ServletContextAttributeListener
- HttpSessionAttributeListener
- ServletRequestAttributeListener
域监听器
ServletContext域监听器
监听ServletContext域的创建与销毁的监听器ServletContextListener
ServletContext域生命周期
服务器启动创建
服务器关闭销毁
监听器的编写步骤
- 编写一个监听器类去实现监听器接口
- 覆盖监听器的方法
3. 需要在web.xml中进行配置
作用:
初始化的工作:初始化对象 初始化数据 加载数据库驱动 连接池的初始化
加载一些初始化的配置文件
任务调度
Session中对象存储监听
一个对象存储到session当中的几种状态
绑定状态
就一个对象被放到session域中
解绑状态
就是这个对象从session域中移除了
钝化状态
是将session内存中的对象持久化(序列化)到磁盘
活化状态
就是将磁盘上的对象再次恢复到session内存中
过滤器
过滤器介绍
什么是过滤器
filter是对客户端访问资源的过滤,符合条件放行,不符合条件不放行
并且可以对目标资源访问前后进行逻辑处理
过滤器编写步骤
- 编写一个过滤器的类实现Filter接口
- 实现接口中尚未实现的方法(着重实现doFilter方法)
- 在web.xml中进行配置(主要是配置要对哪些资源进行过滤)
配置filter-class,
配置filter-mapping,对哪些资源进行过滤
代码演示
- 实现filter接口
- web.xml配置
访问一个资源的时候,会被过滤器拦截
要在过滤器当中进行放行之后, 才能够访问到对应的servlet
chain.doFilter(req,res)
过滤器的访问流程
在发送一个请求时, web容器会先到filter当中,创建三个参数,
res,req,chain
在过滤器当中,放行之后,才能够访问到对应的资源 中间的过滤器可能有多个,在一个过滤器当中,可以调用另外一个过滤器
也有可能过滤器没有拦截所有的资源,有些资源可以直接被访问
filter生命周期
init方法
当filter对象创建时调用
当服务器启动时创建
因为有可能一个filter对应多个servlet
启动时, 先把filter准备好, 访问资源时就可以进行过滤了
filterconfig
当前filter对象的配置信息
和servletConfig差不多, 获取名称,参数
获取servletContext对象
先有的ServletContext
dofitter
当匹配到mapping时调用dofilter
参数
res
req
FilterChain
过滤器链对象
内部维护着各个filter的索引,并且知道所有filter的顺序
是根据mapping的顺序来执行的
destroy
当filter对象销毁时调用
关闭服务器时销毁对象
和servletContext的生命周期是一样
配置
mapping
完全匹配 目录匹配 扩展名匹配
servlet_name
可以把路径直接指定某一个servlet
可以有多个servlet_name
开发中基本上使用的都是mapping
dispatcher
配置请求的形式,不是请求方式,是页面跳转的形式
形式分类
- REQUEST:默认值,代表直接访问某个资源时执行filter
- ERROR: 发生错误时 进行跳转是执行filter
- INCLUDE:包含资源时执行filter
- FORWARD:转发时才执行filter,转发之后, 才去执行filter