第四章:Request和Response
第一节:Request与Response原理和继承体系
1.1 Request对象和Response对象原理
- request和response对象是由服务器创建的,我们只是来使用它们而已
- request对象是来获取请求消息的,response对象是来设置响应消息的
1.2 request对象继承体系结构
ServletRequest
:是一个接口HttpServletRequset
:是一个接口,继承自ServletRequest
org.apache.catalina.connector.RequestFacade
:是一个类,实现HttpServletRequset
接口,由Tomcat编写
第二节:Request获取请求数据
2.1 获取请求消息数据
1、获取请求行数据
GET/day14/demo01?name=zhangsan HTTP/1.1
方法:
-
获取请求方式:GET
String getMethod()
-
获取虚拟目录:/day14
String getContextPath()
-
获取Servlet路径:/demo01
String getServletPath()
-
获取GET方式的请求参数:name=zhangsan
String getQueryString()
-
获取请求的URI:/day14/demo01
String getRequestURI()
:/day14/demo01String getRequsetURL()
:http://localhost/day14/demo01 -
获取协议及版本号:HTTP/1.1
String getProtocol()
-
获取客户机的IP地址:
String getRemoteAddr()
2、获取请求头数据
方法:
-
通过请求头的名称获取头的值
String getHeader(String name)
-
获取所有的请求头名称
Enumeration<String> getHeaderNames()
Enumeration<String>
:枚举接口,可以理解为迭代器,把它当作迭代器使用
3、获取请求体数据
**请求体:**只有post请求方式,才有请求体,在请求体中封装了post请求的请求参数
步骤:
-
获取流对象
BufferedReader getReader()
:获取字符输入流,只能操作字符数据ServletInputStream getInputStream()
:获取字节输入流,可以操作所有类型数据 -
再从流对象中拿数据
2.2 其他功能
1、获取请求参数通用方式
不论post还是get都能使用下列方法
String getParameter(String name)
:根据参数名称获取参数值String[] getParamaterValues(String name)
:根据参数名称获取参数值的数组Enumeration<String> getParameterNames()
:获取所有请求的参数名称Map<String,String[]> getParameterMap()
:获取所有参数的map集合
2、请求转发
**请求转发:**一种在服务器内部的资源跳转方式
- 步骤:
- 通过request对象获取请求转发器对象:
RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象来进行转发:
forward(ServletRequest request,ServletResponse response)
- 通过request对象获取请求转发器对象:
- 特点:
- 浏览器地址栏路径没有发生变化
- 只能转发到当前的服务器内部资源中
- 转发是一次请求
3、共享数据
**域对象:**一个有作用范围的对象,可以在范围内共享数据
**request域:**代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
viod setAttribute(String name,Object obj)
:存储数据Object getAttribute(String name)
:通过键获取值void removeAttribute(String name)
:通过键移除键值对
4、获取ServletContext
ServletContext getServletContext()
:获取ServletContext
2.3 中文乱码问题
**get方式:**tomcat 8 已经将get方式乱码问题解决了
**post方式:**会乱码
**解决:**在获取参数前,设置request的编码
request.setCharacterEncoding("utf-8");
第三节:案例-用户登录
用户登陆案例需求:
- 编写login.html登陆界面
- 使用Druid数据库连接池技术,操作mysql,all中userlogin表
- 使用JDBCTemplate技术封装JDBC
- 登陆成功跳转到SuccessServlet展示:登陆成功!用户名欢迎您
- 登陆失败跳转到FFailServlet展示:登陆失败,用户名或密码错误
开发步骤:
- 创建项目,导入html页面配置文件与jar包
- 创建数据库的环境
- 创建实体类
- 创建UserDao类,提供login()方法
- 创建类UserDao2,提供login方法
- 创建LoginServlet2类
- form表单的action写法:虚拟目录+Servlet的资源路径
- BeanUtils工具类,简化数据封装
3.2 BeanUtils介绍
BeanUtils工具类:简化数据封装
-
JavaBean:标准的Java类
- 要求:
- 类必须被public修饰
- 必须提供空参的构造方法
- 成员变量必须使用private修饰
- 提供公共setter和getter方法
- 功能:封装数据
- 要求:
-
概念:
-
成员变量
-
属性:setter和getter方法截取后的产物
例如:getUsername()---->Useername---->username
-
-
方法
- setProperty()
- getProperty()
- populate(Object,Map):将Map集合的键值对信息,封装到对应的JavaBean对象中
第四节:HTTP响应协议
4.1 概述
**请求消息:**客户端发送给服务器端的数据
- 数据格式:
- 请求行
- 请求头
- 请求空行
- 请求体
**响应消息:**服务器端发送给客户端的数据
-
数据格式:
-
响应行
-
组成:协议/版本 响应状态码 状态码描述
-
响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
-
状态码都是三位数字
-
分类:
-
1xx:服务器接收客户端消息但没有接收完成,等待一段时间后,发送1xx状态码
-
2xx:成功。代表:200
-
3xx:重定向。代表:302(重定向) 304(访问缓存)
-
4xx:客户端错误。
代表:404(请求路径没有对应的资源)
405(请求方式没有对应的doxx方法)
-
5xx:服务器端错误。代表:500(服务器内部出现异常)
-
-
-
-
响应头
-
格式:头名称:值
-
常见的响应头:
-
Content-Type:服务器告诉客户端本次的响应消息体数据格式以及编码格式
-
Content-disposition:服务器告诉客户端以什么格式打开响应体数据
值:
- in-line:默认值,在当前页面内打开
- attachment;filename=xxx:以附件形式打开响应体。文件下载
-
-
-
响应空行
-
响应体:真实的传输的数据
-
-
响应的字符串格式:
HTTP/1.1 200 OK content-type: text/html date: Thu, 15 Apr 2021 09:48:43 GMT x-frame-options: SameOrigin X-Content-Type-Options: nosniff x-xss-protection: 1; mode=block accept-ranges: bytes cache-control: private, must-revalidate last-modified: Thu, 15 Apr 2021 09:47:07 GMT content-length: 155 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello Response</title> </head> <body> Hello Response </body> </html>
第五节:response之重定向
5.1 response功能
功能:设置响应消息
-
设置响应行
- 格式:HTTP/1.1 200 ok
- 设置状态码:
setStatus(int sc)
-
设置响应头
setHeader(String name,String value)
-
设置响应体
使用步骤:
- 获取输出流
- 字符输出流:
PrintWriter getWriter()
- 字节输出流:
ServletOutputStream getOutputStream()
- 字符输出流:
- 使用数据流,将数据输出到客户端浏览器
- 获取输出流
5.2 案例
-
完成重定向
-
**重定向:**资源跳转的方式
-
代码实现
setHeader(String name,String value)
sendRedirect(String value)
-
重定向(redirect)的特点:
- 地址栏发生变化
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求,不能使用request共享数据
转发(forward)的特点:
- 转发地址栏路径不变
- 转发只能访问当前服务器下的资源
- 转发是一次请求,可以使用request对象共享资源
-
路径写法
-
-
服务器输出字符数据到浏览器
步骤:
-
获取字符输出流
ServletOutputStream sos=resp.getOutputStream();
-
输出数据
sos.write("你好".getBytes("utf-8"));
注意:
乱码问题:
-
PrintWriter pw=resp.getWriter();
获取的流默认编码是ISO-8859-1的 -
设置该流的默认编码
-
告诉浏览器响应体使用的编码
简单的形式(在获取流之前):
resp.setContentType("text/html;charset=utf-8");
复杂的形式:
resp.setHeader("content-type","text/html;charset=utf-8");
-
-
服务器输出字节数据到浏览器
-
验证码
- 实质:是一张图片
- 目的:防止恶意表单注册
5.3 路径
相对路径
通过相对路径不可以确定唯一资源
如:./index.html
不以/开头,以.开头的路径
**规则:**找到当前资源和目标资源之间的相对位置关系
**./😗*当前目录
…/:后退一级目录
绝对路径
通过绝对路径可以确定唯一资源
如:http://localhost/day15/responseDemo02
可以省略为:/day15/responseDemo02
以/开头的路径
**规则:**判断定义的路径是给谁用的(判断请求将来从哪发出)
-
给客户端浏览器:需要加虚拟目录(项目的访问路径)
建议虚拟目录动态获取:
request.getContextPath()
<a>,<form>,重定向...
-
给服务器:不需要加虚拟目录
转发路径
5.4 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)
- 方法:
-
5.5 文件下载案例
文件下载需求:
- 页面显示超链接
- 点击超链接后弹出下载提示框
- 完成图片文件的下载
分析:
-
超链接指向的资源如果能被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框。不满足需求
-
任何资源都必须弹出下载提示框
-
任何响应头设置资源的打开方式:
content-disposition:attachment;filename-xxx
步骤:
- 定义页面,编辑超链接href属性,指向Servlet,传递资源的名称filename
- 定义Servlet
- 获取文件的名称
- 使用字节输入流加载文件进内存
- 指定responese的响应头:
content-disposition:attachment;filename-xxx
- 将数据写出到response输出流
问题:
中文文件问题:
解决思路:
- 获取客户端使用的浏览器版本信息
- 根据不同的版本信息,设置filename的编码方式不同
@WebServlet(urlPatterns = "/downLoadServlet")
public class downLoadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求参数,文件名称
String filename=req.getParameter("filename");
//2.使用字节输入流进内存
//2.1找到文件服务器路径
ServletContext sc=this.getServletContext();
String realPath=sc.getRealPath("/img/"+filename);
//2.2用字节流关联
FileInputStream fs=new FileInputStream(realPath);
//3.设置response的响应头
//3.1设置响应头类型:content-type
String mimeType=sc.getMimeType(filename);//获取文件的mime类型
resp.setHeader("content-type",mimeType);
//3.2设置响应头打开方式:content-disposition
//解决中文文件名问题
//1.获取user-agent请求头
String agent=req.getHeader("user-agent");
//2.使用工具类方法编码文件名
filename=DowmLoadUtils.getFilename(agent,filename);
resp.setHeader("content-disposition","attachment;filename="+filename);
//3.将输入流的数据写出到输出流中
ServletOutputStream sos=resp.getOutputStream();
byte[] bytes=new byte[1024];
int len=0;
while ((len=fs.read(bytes))!=-1){
sos.write(bytes,0,len);
}
fs.close();
}
第五章:Cookie和session
第一节:Cookie快速入门
1.1 会话技术
**会话:**一次会话中包含多次请求和响应
**一次会话:**浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
**会话功能:**在一次会话的范围内的多次请求间共享资源
方式:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
1.2 Cookie快速入门
-
**概念:**客户端会话技术,将数据保存到客户端
-
使用步骤:
-
创建Cookie对象,绑定数据
new Cookie(String name,String value)
-
发送Cookie对象
response.addCookie(Cookie cookie)
-
获取Cookie,拿到数据
Cookie[] request.getCookies()
-
-
实现原理:
-
Cookie的细节
-
一次可不可以发送多个Cookie?
可以创建多个Cookie对象,使用response调用多次
addCookie()
方法发送Cookie即可 -
Cookie在浏览器中保存多长时间?
-
默认情况下,当浏览器关闭后,Cookie数据被销毁
-
设置Cookie的生命周期,使它持久化存储
setMaxAge(int seconds)
- 正数:持久化将Cookie数据写入到硬盘文件中,持久化存储。也是Cookie的存活时间
- 负数:默认值,当浏览器关闭后,Cookie数据被销毁
- 0:删除Cookie信息
-
-
Cookie能不能存中文?
-
在tomcat 8之前,Cookie中不能直接存储中文数据
需要将中文数据转码----一般采用URL编码(%E3)
URLEncoder.encode(lastTime,"utf-8");
-
在tomcat 8之后,Cookie支持中文数据.但对特殊字符还是不支持,建议使用URL编码存储,再用URL进行解码取出
URLDecoder.decode(lastTime,"utf-8")
-
-
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一般用于存储少量的不太敏感的数据
- 在不登陆的情况下,完成服务器对客户端的身份识别
-
**案例:**记住上一次访问时间
- 需求:
- 访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问
- 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
- 分析:
- 可以采用Cookie来完成
- 在服务器中的Servlet判断是否有一个名为lastTime的Cookie
- 有:不是第一次访问
- 欢迎回来,您上次访问时间为:。。。
- 写回Cookie
- 没有:是第一次访问
- 响应数据:您好,欢迎您首次访问
- 写回Cookie:lastTime=。。。
- 有:不是第一次访问
- 需求:
第二节:JSP入门学习
2.1 概念
**Java Server Pages:**Java服务器端页面,可理解为一个特殊的页面,其中即可以直接定义HTML的标签,又可以定义Java代码,用于简化书写
2.2 JSP原理
JSP本质上就是一个Servlet
2.3 JSP脚本
**JSP脚本:**JSP定义Java代码的方式
<% Java代码 %>
:定义的Java代码在service方法中。service方法中可以定义什么,该脚本中就可以定义什么<%! Java代码 %>
:定义的Java代码,在JSP转换后的Java类成员位置<%= Java代码 %>
:定义的Java代码,会输出到页面上。输出语句中可以定义什么,他就可以定义什么
2.4 JSP的内置对象
在JSP页面中不需要获取和创建,可以直接使用的对象
JSP一共有9个内置对象,其中的3个为:
-
request
-
response
-
out
:字符输出流对象,可以将数据输出到页面上,和response.getWriter()
类似response.getWriter()
和out.print()
的区别:在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据。即:response.getWriter()
数据输出永远在out.print()
之前,建议统一使用out输出,不使用response输出
第三节:Session入门学习
3.1 概念
**Session:**服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。HttpSession
3.2 快速入门
HttpSession对象:
Object getAttribute(String name)
void setAttribute(String name,Object value)
void removeAttribute(String name)
3.3 原理分析
服务器如何确保一次会话范围内,多次获取的Session对象是同一个?
Session的实现是依赖于Cookie的
3.4 Session细节
-
当客户端关闭后,服务器不关闭,两次获取session不是同一个
默认情况下:不是
如果需要相同,则可以创建Cookie,Cookie的键为
JSESSIONID
,设置最大存活时间,让Cookie持久化保存Cookie cookie=new Cookie("JSESSIONID",session.getId()); cookie.setMaxAge(60*60); response.addCookie(cookie);
-
客户端不关闭,服务器关闭后,两次获取的session不是同一个
虽然session对象不是同一个,但是要确保数据不丢失
- **session的钝化:**在服务器正常关闭之前,将session对象系列化到硬盘上
- **session的活化:**在服务器启动后,将session文件转化为内存中的session对象即可
-
Session什么时候被销毁
-
服务器关闭
-
session对象调用
void invalidate()
方法,自己销毁自己 -
session默认失效时间为30分钟
选择性的配置修改:在
web.xml
文件下找到:<session-config> <session-timeout>30</session-timeout> </session-config>
-
-
session的特点:
- session用于存储一次会话的多次请求的数据,存在服务器端
- session可以存储任意类型、任意大小的数据
-
session与cookie的区别:
- session存储在服务器端,cookie存储在客户端
- session没有数据大小限制,cookie有大小限制
- session数据安全,cookie数据相对不安全
3.5 案例:验证码
案例需求:
1.访问带有验证码的登录页面login.html
2.用户输入验证码、密码以及用户名
如果用户名和密码输入有误,跳转登录页面,提示:用户名或密码错误
如果验证码输入有误,跳转登录页面,提示:验证码错误
如果全部正确,则跳转到主页success.jsp,显示:用户名,欢迎您
分析:
第四章:JSP,EL和JSTL
4.1 JSP基础语法
-
指令
**作用:**用于配置JSP页面,导入资源页面
格式:
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
分类:
-
**page:**配置JSP页面的
contentType
:等同于response.setContentType()
- 设置响应体的mime类型以及字符集
- 设置当前JSP页面的编码(只能是高级的开发工具才能生效,如果使用低级工具,则需要设置
pageEncoding
属性设置当前页面的字符集编码)
language
:现在只能写Javabuffer
:缓冲区的大小,默认为8kb- **
import
:**导包 errorPage
:当前页面发生异常后会自动跳转到指定页面isErrorPage
:标识当前页面是否是错误页面- **true:**是,可以使用内置对象execption
- **false:**否。默认值,不可以使用内置对象execption
-
**include:**页面包含的。导入页面的资源文件
<%@ include file="文件名"%>
-
**taglib:**导入资源
<%@taglib prefix="" uri="" %>
**prefix:**前缀,自定义的
-
-
注释
-
html注释:
<!-- -->
:只能注释html代码片段 -
JSP注释:
<%-- --%>
:可以注释所有,且不能通过浏览器response查看注释。推荐使用此注释
-
-
内置对象:在jsp页面中不需要创建,直接使用的对象
变量名 | 真实类型 | 作用 |
---|---|---|
pageContext | PageContext | 当前页面共享数据,还可以获取其它八个内置对象 |
request | HttpServletRequest | 一次请求访问的多个资源(转发) |
session | HttpSession | 一次会话的多个请求间 |
application | ServletContext | 所有用户间共享数据 |
response | HttpServletResponse | 响应对象 |
page | Object | 当前页面(Servlet)的对象 |
out | JspWriter | 输出对象,可以把数据输出到页面上 |
config | ServletConfig | Servlet的配置对象 |
execption | Throwable | 异常对象 |
4.2 MVC开发模式
-
JSP演变历史
- 早期只有servlet,只能使用response输出标签数据,非常麻烦
- 后来有jap,简化了Servlet的开发,如果过度使用jsp,在jsp中既写大量的Java代码,又写html表,造成难以维护,难以分工协作
- 再后来,Javaweb开发借鉴mvc开发模式,使得程序的设计更加合理性
-
MVC
-
M:Model,模型。
JavaBean
完成具体的业务操作,如:查询数据库,封装对象
-
V:View,视图。
JSP
展示数据
-
C:Controller,控制器。
Servlet
- 获取用户的输入
- 调用模型
- 将数据交给视图进行展示
-
-
优点:
- 耦合性低,方便维护,可以利于分工协作
- 重用性高
- 生命周期成本低
- 部署快
- 可维护性高
- 有利于软件工程管理
-
缺点:
使得项目架构变得复杂,对开发人员要求高很多
4.3 EL表达式
-
**概念:**Expression Language 表达式语言
-
**作用:**替换和简化jsp页面中Java代码的编写
-
语法:
${表达式}
-
注意:
jsp默认支持EL表达式
如果要忽略EL表达式:
- 设置jsp中page指令中:
isELIgnored="true"
忽略当前jsp页面中所有的el表达式 \${表达式}
:忽略当前这个el表达式
- 设置jsp中page指令中:
-
使用:
-
运算
运算符:
-
算数运算符:
+ - * /(div) %(mod)
-
比较运算符:
> < <= >= == !=
-
逻辑运算符:
&&(and) ||(or) !(not)
-
空运算符:
empty
功能:用于判断字符串、集合、数组对象是否为null并且长度是否为0
${empty list}
:判断字符串、集合、数组对象是否为null或者长度为0${not empty str}
:表示判断字符串、集合、数组对象是否不为null,并且长度>0
-
-
获取值
-
el表达式只能从域对象中获取值
-
语法:
-
${域名称.键名}
:从指定域中获取指定键的值域名称:
pageScore--->pageContext
requestScope----->request
sessionScope------>session
applicationScope------->application(ServletContext)
举例:在request域中存储了name=张三
获取:
${requsetScope.name}
-
${键名}
:表示依次从最小的域中查找是否有该键对应的值,直到找到为止 -
获取对象、List集合、Map集合的值
-
对象:
${域名称.键名.属性名}
本质上会去调用对象的getter方法
-
List集合:
${域名称.键名[索引]}
-
Map集合:
${域名称.键名.key名称}
或${域名称.键名["key名称"]}
-
-
-
隐式对象
EL表达式中有11个隐式对象
pageContext
:- 获取jsp其他八个内置对象:
${pageContext.request.contextPath}
:动态获取虚拟目录
- 获取jsp其他八个内置对象:
-
-
4.4 JSTL常用标签
-
概念:
JavaServer Pages Tag Library
JSP标准标签库是由Apache组织提供的开源的免费的jsp标签
-
**作用:**用于简化和替换jsp页面上的Java代码
-
使用步骤:
-
导入jstl相关jar包
下载页面有4个jar包: Impl: taglibs-standard-impl-1.2.5.jar JSTL实现类库 Spec: taglibs-standard-spec-1.2.5.jar JSTL标准接口 EL: taglibs-standard-jstlel-1.2.5.jar JSTL1.0标签-EL相关 Compat: taglibs-standard-compat-1.2.5.jar 兼容版本 从README得知: 如果不使用JSTL1.0标签,可以忽略taglibs-standard-jstlel包, README没有介绍taglibs-standard-compat包,估计应该是兼容以前版本标签库, 所以一般只需要 taglibs-standard-impl 和 taglibs-standard-spec 两个jar包
-
引入标签库:taglib指令:
<%@ taglib %>
-
使用标签
-
-
常用的JSTL标签:
-
**if:**相当于Java代码的if语句
- 属性:
test
是必须属性,接收boolean表达式- 若boolean表达式为true,则显示标签体内容,若boolean表达式为false,则不显示标签体内容
- 一般情况下,test属性值会结合el表达式一起使用
- 注意:
c:if标签没有else情况,想要else情况则可以再定义一个c:if标签
- 属性:
-
choose:相当于Java代码的switch语句
- 使用choose标签声明 相当于switch声明
- 使用when标签做判断 相当于case
- 使用otherwise标签做其他情况的声明 相当于default
-
foreach:相当于Java代码的for语句
-
完成重复的操作
-
属性:
begin:
开始值
end
:结束值
var
:临时变量
step
:步长
varStatus
:循环状态对象
index
:容器中元素的索引,从0开始
count
:循环次数,从1开始
-
-
遍历容器
-
属性:
items
:容器对象
var
:容器中元素的临时变量
varStatus
:循环状态对象
index
:容器中元素的索引,从0开始
count
:循环次数,从1开始 -
-
-
-
练习:
需求:在request域中存有User对象的list集合,需要使用jstl+el将list集合数据展示到jsp页面中的表格table中
4.5 综合案例
综合练习:
- 简单功能
- 列表查询
- 登录
- 添加
- 删除
- 修改
- 复杂功能
- 删除选中
- 分页查询
- 复杂条件查询
第五章:Filter和Listener
5.1 Filter概述
生活中的过滤器:纯净器、空气净化器、土匪
**web中的过滤器:**当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能
**过滤器的作用:**一般用于完成通用的操作,如登录验证、统一编码处理、敏感字符过滤…
5.2 Filter快速入门
- 步骤:
- 定义一个类,实现接口
Filter
- 复写方法
- 配置拦截路径
web.xml
- 注解配置:
urlPatterns = "/被拦截的文件路径"
- 定义一个类,实现接口
5.3 Filter细节
-
web.xml配置
<filter> <filter-name>Filterxml</filter-name> <filter-class>Filter路径</filter-class> </filter> <filter-mapping> <filter-name>Filterxml</filter-name> <url-pattern>拦截路径</url-pattern> </filter-mapping>
-
过滤器执行流程
- 执行过滤器
- 执行放行后的资源
- 回来执行过滤器放行代码下的代码
-
过滤器生命周期方法
init()
:在服务器启动后,会创建Filter对象,然后调用init
方法,只执行一次。用于加载资源destroy()
:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法,只执行一次,用于释放资源doFilter()
:每一次请求被拦截资源时,会执行,执行多次
-
过滤器配置详解
- 拦截路径配置:
- 具体资源路径:
/index.jsp
:只有访问index.jsp时,过滤器才会被执行 - 目录拦截:
/user/*
:访问/user下的所有资源时,过滤器都会被执行 - 后缀名拦截:
*.jsp
:访问所有jsp资源时,过滤器都会被执行 - 拦截所有资源:
/*
:访问所有资源时,过滤器都会被执行
- 具体资源路径:
- 拦截方式配置:资源被访问的方式
- 注解配置:
- 设置
dispatcherTypes
属性,取值为:DispatcherType.REQUEST
:默认值,浏览器直接请求资源DispatcherType.FORWARD
:转发来访问资源DispatcherType.INCLUDE
:包含访问资源DispatcherType.ERROR
:错误跳转资源DispatcherType.ASYNC
:异步访问资源
- 设置
- web.xml配置:
- 设置
<dispatcher></dispatcher>
标签即可REQUEST
:默认值,浏览器直接请求资源FORWARD
:转发来访问资源INCLUDE
:包含访问资源ERROR
:错误跳转资源ASYNC
:异步访问资源
- 设置
- 注解配置:
- 拦截路径配置:
-
过滤器链(配置多个过滤器)
-
执行顺序:如果有两个过滤器:过滤器1和过滤器2
- 过滤器1
- 过滤器2
- 资源执行
- 过滤器2
- 过滤器1
-
先后顺序问题:
-
注解配置:按照类名的字符串比较规则比较,值小的先执行
如:
AFilter
和BFilter
:AFilter
就先执行了 -
web.xml
配置:<filter-mapping>
谁定义在上边,谁先执行
-
-
5.4 案例
-
登录验证:
需求: 1.访问案例的资源,验证其是否登录 2.如果登陆了则直接放行 如果没有登陆,则跳转到登录页面,提示"您尚未登陆,请先登录"
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //1.强制转换 HttpServletRequest request=(HttpServletRequest) req; //1.获取资源请求路径 String uri=request.getRequestURI(); //2.判断是否是登录相关的资源,要注意排除掉css/js/图片/验证码等资源 if (uri.contains("/login.jsp")||uri.contains("/checkServlet")||uri.contains(".css")||uri.contains(".js")||uri.contains("/CheckPic")||uri.contains("/UserServletImpl")){ //包含,证明用户就是想登录,放行 chain.doFilter(req,resp); } else { //不包含,需要验证用户是否登录 //3.从session获取user Object admin=request.getSession().getAttribute("admin"); if (admin!=null){ //登录了,放行 chain.doFilter(req,resp); } else { //没有登录 request.setAttribute("login_msg","您尚未登陆,请登录"); request.getRequestDispatcher("/UserList/login.jsp").forward(req,resp); } } }
-
敏感词汇过滤:
需求: 1.对案例录入的数据进行敏感词汇过滤 2.敏感词汇参考(敏感词汇.txt) 3.如果是敏感词汇,替换为*** 分析: 1.对request对象进行增强。增强获取参数相关方法 2.放行。c
增强对象的功能:
-
设计模式:一些通用的解决固定问题的方式
-
装饰模式:
-
代理模式:
-
概念:
- 真实对象:被代理的对象
- 代理对象
- 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的
-
实现方式:
-
静态代理:在有一个类文件描述代理模式
-
动态代理:在内存中形成代理类
实现步骤:
- 代理对象和真实对象实现相同的接口
- 获取代理对象
Proxy.newProxyInstance()
- 使用代理对象调用方法
- 增强方法
方法参数:
invoke(Object proxy, Method method, Object[] args)
- proxy:代理对象
- method:代理对象调用的方法,被封装为的对象
- args:代理对象调用方法时,传递的实际参数
增强方式:
- 增强参数列表
- 增强返回值类型
- 增强方法体执行逻辑
-
-
-
-
5.5 Listener:监听器
**概念:**web的三大组件之一
-
事件监听机制
- 事件 :一件事情
- 事件源:事件发生的地方
- 监听器:一个对象
- 注册监听:将事件、事件源、监听器绑定在一起。当事件源发生某个事件后,执行监听器代码
-
servletContextListener
:监听SerletContext对象的创建和替换- 方法:
void contextDestroyed(ServletContextEvent sce)
:SerletContext对象被销毁之前会调用该方法void contextInitialized(ServletContextEvent sce)
:SerletContext对象创建后会调用该方法-
步骤:
-
定义一个类,实现
servletContextListener
接口 -
复写方法
-
配置
-
web.xml
<listener> <listener-class>web.Listener.ContextLoaderListener</listener-class> </listener>
指定初始化参数:
<context-param> <param-name>ContextLoaderListener.java</param-name> <param-value>/WEB-INF/classes/applicationContext.xml</param-value> </context-param>
-
-
第六章:JQuery
第一节:JQuery基础
1.1 概念
JQuery:一个JavaScript框架,简化js开发,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。JQuery设计的宗旨是:write less,do more
,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,简化HTML文档操作、事件处理、动画设计和Ajax交互
**JavaScript框架:**本质上就是一些js文件,封装了js的原生代码而已
1.2 快速入门
-
步骤:
-
下载JQuery
目前JQuery有三个大版本: 1.x:兼容ie678,使用最为广泛,官方只做bug维护 功能不再新增,因此一般项目来说,使用1.x版本就可以了 最终版本:1.12.4(2016年5月20日) 2.x:不兼容ie678,很少有人使用,官方只做bug维护 功能不再新增,如果不考虑兼容低版本的浏览器就可以使用2.x 最终版本:2.2.4(2016年5月20日) 3.x:不兼容ie678,只支持最新的浏览器,除非特殊要求 一般不会使用3.x版本的,很多老的JQuery插件不支持这个版本 目前该版本是官方主要更新维护的版本
jquery xxx.js与jquery xxx.min.js的区别: 1.jquery xxx.js:开发版本,给程序员看的,有良好的缩进和注释,体积小一点 2.jquery xxx.min.js:生产版本,程序中使用,没有缩进,体积小一点,程序加载更快
-
导入JQuery的js文件:导入
min.js
文件 -
使用
var div1=$("#div1"); alert(div1.html());
-
1.3 JQuery对象和JS对象区别与转换
- JQuery对象在操作时,更加方便
- JQuery对象和js对象方法不通用
- 两者相互转换:
- jq—>js:
jq对象[索引]
或jq对象.get(索引)
- js—>jq:
$(js对象)
- jq—>js:
1.4 JQuery事件绑定和入口函数
**选择器:**筛选具有相似特征的元素(标签)
基本语法:
-
事件绑定:
$("").click(function (){ });
-
入口函数:
$(function (){ })//jquery入口函数(dom文档加载完成后执行该函数中的代码)
window.onload
和$(function)
区别:window.onload
只能定义一次,如果定义多次,后边的会将前边的覆盖掉$(function)
可以定义多次
-
样式控制:
$("#div1").css("background-color","red");
$("#div2").css("backgroundColor","pink");
第二节:JQuery选择器
2.1 基本选择器
-
标签选择器(元素选择器)
语法:
$("html标签名")
获得所有匹配标签名称的元素 -
id选择器
语法:
$("#id"的属性值)
获得与指定id属性值匹配的元素 -
类选择器
语法:
$(".class的属性值")
获得与指定的class属性值匹配的元素 -
并集选择器
语法:
$("选择器1,选择器2,...")
获得多个选择器选中的所有元素
2.2 层级选择器
-
后代选择器
语法:
$("A B")
选择A元素内部的所有B元素 -
子选择器
语法:
$("A>B")
选择A元素内部的所有B子元素
2.3 属性选择器
-
属性名称选择器
语法:
$("A[属性名]")
包含指定属性的选择器 -
属性选择器
语法:
$("A[属性名='值']")
包含指定属性等于指定值的选择器语法:
$("A[属性名!='值']")
包含多个属性条件不为指定值的选择器语法:
$("A[属性名^='值']")
包含多个属性条件以"值"为开始的选择器语法:
$("A[属性名$='值']")
包含多个属性条件以"值"为结束的选择器语法:
$("A[属性名*='值']")
包含多个属性条件包含"值"的选择器 -
复合属性选择器
语法:
$("A[属性名='值'][]...")
包含多个属性条件的选择器
2.4 过滤选择器
-
首元素选择器
语法:
:first
获得选择的元素中的第一个元素 -
尾元素选择器
语法:
:last
获得选择的元素中最后一个元素 -
非元素选择器
语法:
:not(selecter)
不包括指定内容的元素 -
偶数选择器
语法:
:even
偶数,从0开始计数 -
奇数选择器
语法:
:odd
奇数,从0开始计数 -
等于索引选择器
语法:
:eq(index)
指定索引元素 -
大于索引选择器
语法:
:gt(index)
大于指定索引元素 -
小于索引元素
语法:
:lt(index)
小于指定索引元素 -
标题选择器
语法:
:header
获取标题元素(h1-h6),固定写法
2.5 表单过滤选择器
-
可用元素选择器
语法:
:enabled
获得可用元素 -
不可用元素选择器
语法:
:disabled
获得不可用元素 -
选中选择器
语法:
:checked
获得单选/复选框选中的元素 -
选中选择器
语法:
:selected
获得下拉框选中的元素
第三节:DOM操作
3.1 内容操作
-
html()
:获取/设置元素的标签体内容<a><font>内容</font></a>
----><font>内容</font>
获取:
$("#myinput").html();
设置:
$("#myinput").html("<p>李四</p>");
-
text()
:获取/设置元素的标签体纯文本内容<a><font>内容</font></a>
---->内容
获取:
$("#myinput").text();
设置:
$("#myinput").text("李四");
-
val()
:获取/设置元素的value
属性值获取:
$("#myinput").val();
设置:
$("#myinput").val("李四");
3.2 属性操作
-
通用属性操作
attr()
:获取/设置(改变、增加)元素的属性removeAttr()
:删除属性prop()
:获取/设置(改变、增加)元素的属性removeProp()
:删除属性
attr()
和prop()
的区别?- 如果操作的是元素的固有属性,则建议使用
prop()
- 如果操作的是元素的自定义属性,则建议使用
attr()
-
对class属性操作
-
addClass()
:添加class属性值 -
removeClass()
:删除class属性值 -
toggleClass()
:切换class属性toggleClass("one")
:判断如果元素对象上存在class=“one”,则将属性值one删除掉;如果元素对象上不存在class=“one”,则添加 -
css()
:改变styly属性
-
3.3 CRUD操作
-
append()
:父元素将子元素追加到末尾对象1.append(对象2)
:将对象2添加到对象1内部,并且在末尾 -
prepend()
:父元素将子元素追加到开头对象1.prepend(对象2)
:将对象2添加到对象1内部,并且在开头 -
appendTo()
:子元素将父元素追加到末尾对象1.appendTo(对象2)
:将对象1添加到对象2,并且在末尾 -
prependTo()
:子元素将父元素追加到开头对象1.prependTo(对象2)
:将对象1添加到对象2内部,并且在开头 -
after()
:添加元素到元素后边对象1.after(对象2)
:将对象2添加到对象1后边,对象1和对象2是兄弟关系 -
before()
:添加元素到元素前边对象1.before(对象2)
:将对象2添加到对象1前边,对象1和对象2是兄弟关系 -
insertAfter()
:对象1.insertAfter(对象2)
:将对象1添加到对象2前边,对象1和对象2是兄弟关系 -
insertBefore()
:对象1.insertBefore(对象2)
:将对象1添加到对象2后边,对象1和对象2是兄弟关系 -
remove()
:移除元素对象.remove()
:将对象删除掉 -
empty()
:清空元素的所有子元素(后代元素)对象.empty()
:将对象的后代元素全部清空,但是保留当前对象以及其属性节点
第四节: 动画和遍历
4.1 动画
-
默认显示和隐藏方式
-
show([speed,[easing],[fn]])
参数:
-
**speed:**动画速度。三个预定义的值:(
"slow","normal","fast",毫秒值
) -
**easing:**切换效果。默认是
swing
,可用参数:liner
swing
:动画执行时,效果是先慢中间快,最后又慢liner
:动画执行时,速度是匀速的 -
**fn:**在动画完成时执行的函数,每个元素执行一次
-
-
hide([speed,[easing],[fn]])
-
toggle([speed],[easing],[fn])
-
-
滑动显示和隐藏方式
slideDown([speed],[easing],[fn])
slideUp([speed],[easing],[fn])
slideToggle([speed],[easing],[fn])
-
淡入淡出显示和隐藏方式
fadeIn([speed],[easing],[fn])
fadeOut([speed],[easing],[fn])
fadeToggle([speed,[easing],[fn]])
4.2 Jquery遍历
-
js的遍历方式
for(初始化值;循环结束条件;步长)
-
jq的遍历方式
-
jq对象.each(callback)
-
callback
:是function(index,element)
函数 -
index(索引) element(元素对象)
-
如果当前function返回为false,则结束循环(break)
如果当前function返回为true,则结束本次循环(continue)$("#city li").each(function (index,element){ alert(this.innerText) //3.2 第二种:在回调函数中定义参数 index(索引) element(元素对象) //如果是上海结束循环 if ("上海"===$(element).html()) { //如果当前function返回为false,则结束循环(break) //如果当前function返回为true,则结束本次循环(continue) return false } alert(index+":"+$(element).html()) })
-
-
$.each(object,[callback])
现阶段和
jq.each()
使用差不多 -
for..of:
JQuery3.0 之后才提供的方式
for(li of $("#city li")){ alert($(li).html()) }
-
第五节:JQuery事件绑定和切换
5.1 事件绑定
-
jq对象.事件方法(回调函数);
jq常用方法:
$("#name").focus();//让文本输入框获得焦点
表单对象.submit();//让表单提交
$(function (){ //1.获取name对象,绑定click事件 $("#name").click(function (){ alert("我被点击了") }) }) //多个绑定事件,简化操作,链式编程 $("#name").mouseover(function (){ alert("鼠标来了") }).mouseout(function (){ alert("鼠标走了") }) //jq独有方法 $("#name").focus();//让文本输入框获得焦点
-
on 用于绑定事件
off 解绑绑定事件
jq对象.on("事件名称",回调函数)
jq对象.off("事件名称")
如果off内不传递任何参数,则将组件上的所有事件全部解绑
//使用on给按钮绑定单击事件 $("#name").on("click",function (){ alert("我被点击了") }) //使用off给按钮解除单击事件 $("#name2").on("click",function (){ //接除name单击事件 $("#name").off("click"); })
5.2 事件切换
jq对象.toggle(fn1,fn2,...)
:在jq1.9版本之后被移除了,但可以使用JQuery Migrate(迁移)插件
可以恢复使用
当单击jq对象对应的组件后,会执行fn1,再次点击执行fn2,…,之后会执行fn1,…
$(function (){
$("#click").toggle(function (){
//改变box背景色
$("#box").css("backgroundColor","blue")
},function (){
$("#box").css("backgroundColor","yellow")
},function (){
$("#box").css("backgroundColor","pink")
})
})
5.3 插件
**插件:**增强JQuery的功能
- 实现方式:
jQuery.fn.extend(Object)
:增强通过Jquery获取的对象的功能,$("#id")
jQuery.exttend(Object)
:增强JQuery对象自身的功能,$/jQuery
$fn.extend({
//定义了一个check()方法,所有的jq对象都可以调用该方法
check:function(){
//...
},
uncheck:function(){
//...
}
})
//调用
$("#btn-check").click(function(){
//获取复选框对象
$("#input[type='checked']").check();
})
$.extend({
max:function(a,b){
return a>=b?a:b;
}
min:function(a,b){
return a<=b?a:b;
}
})
//调用全局方法
var max=$.max(2,3);
alert(max)