# 什么是Servlet?
sun公司制定的一种用来扩展web服务器功能的组件规范。
# 扩展web服务器功能
web服务器只能够处理静态资源的请求(需要事先将html文件写好),不
能够处理动态资源的请求(需要计算生成html),所以,需要扩展。
可以使用Servlet来扩展web服务器功能,当web服务器收到请求之后,
如果需要计算,则交给Servlet来处理。
注:
常见的web服务器有apache、iis、nginx等。
# 组件规范
什么是组件?
符合规范,实现部分功能,并且需要部署到相应的容器里面才能运行的 软件模块。 Servlet就是一个符合servlet规范的组件,需要部署到Servlet容器里面才能运行。 servlet只需要关注业务逻辑,servlet容器会提供运行环境(包括网络相关的服务)。
什么是容器?
符合规范,提供组件的运行环境的程序。 Tomcat(雄猫)就是一个Servlet容器,为Servlet提供运行环境(提供网络 相关的服务)。
# 如何写一个servlet?
step1. 写一个Java类,实现Servlet接口或者继承HttpServlet类。
注:
HttpServlet类实现了Servlet接口中的部分方法。
step2.编译。
注:
使用Java命令来将.java文件编译成.class文件。
step3.打包。
注:
建立一个具有如下结构的文件夹
appname(应用名)
WEB-INF
classes(放.class文件)
lib(放.jar文件,该文件夹可选)
web.xml(部署描述文件)
stpe4.部署
将step3创建好的整个文件夹拷贝到servlet容器制定的位置
注:
可以将整个文件夹使用jar命令压缩成".war"为后缀的文件,然后拷贝。
step5.启动容器,访问servlet。
http://ip:port/appname/url-pattern
注:
url-pattern是一个字符串,在web.xml中设置
# 安装并且配置Tomcat。
# servlet是如何运行的?
比如,在浏览器输入http://ip:prot/day01/hello step1.浏览器依据IP和port建立连接。
step2.浏览器将相关数据添加到请求数据包里面,然后发送给服务器。
step3.服务器会解析请求数据包中的数据,并且将这些数据添加到request对象里面,同时,还会创建一个response对象。
注:
开发人员可以通过request对象获得请求数据包中的数据,比如获得请求参数值。可以将
处理结果写到response对象里面,容器会从response对象中获取处理结果,然后创建响应
数据包并发送给浏览器。
step4.服务器创建servlet对象(实例化),然后调用该对象的service方法。
注:容器会将request对象和response对象作为参数传递给service方法。
step5.服务器将从response对象中获取处理结果,然后创建响应数据包并发送给浏览器。
step6.浏览器解析响应数据包,依据解析到的数据生成相应的页面。
# 5.常见错误
# (1)404
a.含义:404是一个状态码,表示服务器依据请求路径找不到对应的资源。 b.原因:
b1.请求路径写错。
应该按照http://ip:port/appname/url-pattern来写。
b2.应用没有部署或者部署失败
# (2)500
a.含义:500是一个状态码,表示服务器运行出错。 b.原因:
b1.代码没有严格遵守serlvet规范。
比如,没有实现servlet接口或者继承HttpServlet类。
又比如web.xml中将srevlet-class写错或者servlet-name不一致。
b2.代码不严谨
比如,对请求参数没有做检查就做类型转换。
# (3)405
a.含义:服务器找不到处理方法 b.原因:
service方法没有按照正确的格式来写,即没有正确override HttpServlet的service方法。
# 练习
写一个DateServlet,输出当前的系统日期
比如在浏览器栏输入http://ip:port/day01-exec/date, 返回 2018-09-20
# 提示:
step1.创建一个maven工程,注意要选war包。
step2.添加web.xml文件。 step3.指定服务器(在工程上点击鼠标右键,点击properties, 然后如下图进行选择)。 step4.添加DateServlet。 参考代码如下:
public class HelloServlet extends HttpServlet{
public HelloServlet() {
System.out.println("HeeloServlet's constructor...");
}
@Override
/**
* servlet容器在收到请求后,会调用servlet的service方法来处理请求
*
* 注:
* 容器会将request对象和response对象事先创建好,
* 然后作为参数传递给service方法。
* 容器会将请求数据包中的数据解析出来,然后存放到requset对象上,
* 开发人员只需要调用request对象提供的方法就可以获得请求数据包中
* 的所有数据(比如获得请求参数值)。
* 另外开发人员只需要将处理结果存放到response对象上即可,
* 容器会从response对象上获取处理结果,然后创建响应数据包并发送
* 给浏览器。
*
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("HelloServlet's service...");
/*
* 通过request对象提供的方法来获得请求参数值
* 注意:
* 如果请求参数名与实际传递过来的请求参数名不一样,会获得null值。
*/
String name = request.getParameter("name");
System.out.println("name:"+name);
//Integer.parseInt("123 ");
/*
* 设置响应类型。
* 注:
* 通过设计响应类型,可以告诉浏览器,服务器返回的数据类型,
* 浏览器会采取相应的方式来解析服务器返回的数据。
* content-type
*/
response.setContentType("text/html");
PrintWriter out = response.getWriter();
/*
* out.println方法只是将数据存放到了response对象里面
*/
out.println("<h1>Hello "+ name +"</h1>");
/*
* 关闭流。
* 注:
* 不调用close方法也可以,容器会自动关闭流
*/
out.close();
}
}
step5.在部署描述文件(web.xml)中添加Servlet配置信息。 参数配置如下:
<servlet>
<servlet-name>helloSrevlet</servlet-name>
<!--
需要填写servlet完整的类名。
注:
servlet容器会利用Java反射机制来加载servlet,并且将其
实例化。
-->
<servlet-class>web.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloSrevlet</servlet-name>
<!--
url-pattern用来告诉容器,该servlet处理哪些请求
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
step6.在工程上点击鼠标右键,在弹出菜单中选Run As --> Run on Server。 注: eclipse会在容器上指定的位置创建符合servlet规范的文件 夹(默认以工程名作为应用名),并且会将.java文件编译成.class 文件并放到classes文件夹下。也就是说eclipse会简化编译、 打包、部署、运行的过程。
step7.在浏览器地址栏输入请求地址,访问该Servlet。
# http协议(了解)
# 什么是http协议?
是一种网络应用层协议,规定了浏览器与web服务器之间如何通信以及相应的数据包的格式。
注(了解):
tcp/ip 网络层和传输层协议,负责将数据可靠的从一台机器传递到另外一台机器
http 属于应用层协议,将数据打包之后,会将数据包交给tcp/ip来传递这些数据包。
# 浏览器与web服务器是如何通信的
如果浏览器要发送新的请求,需要重新建立新的连接,即“一次请求,一次连接”。这样做的好处是服务器可以利用有限的连接为尽可能多的请求服务。
# 数据包的结构
请求数据包
请求行(请求方式 请求资源路径 协议和版本)
若干消息头
注:
消息头是一些键值对,使用": "分隔。通信的双方可以利用一些消息头来传递一些特定的
消息。比如浏览器可以通过发送user-agent消息头来告诉服务器,浏览器的类型和版本。
实体内容(消息正文)
注:
只有请求方式为post时,实体内容才会又数据。如果请求方式为get,实体内容为空
响应数据包
状态行(协议和版本 状态码 状态描述)
注:
状态码是一个三位数字,表示服务器处理请求的一种状态,
常见的状态码:
200 正常
500 系统出错
404 找不到对应的请求
若干消息头
注:
服务器也可以发送一些消息头给浏览器,比如,发送content-type消息头,告诉浏览器,
服务器返回的数据类型和编码
实体内容
注:
程序处理的结果,浏览器会解析出来,生成相应的页面。
# 两种请求方式
# get请求
a.哪些情况下,浏览器会发送get请求?
a1.在浏览器地址输入某个地址。
a2.表单默认的提交方式。
a3.点击连接。
b.特点?
b1.会将请求参数显示在浏览器地址栏,不安全
注:
有一些网络设备,比如路由器,会记录请求地址。
b2.会将请求参数添加到请求资源路径的后面,只能提交少量的数据给服务器。
注:
请求行大约只能存放2k左右的数据。
# post请求
a.哪些情况下,浏览器会发送post请求?
a1.将表单的method属性设置为post.
b.特点:
b1.不会将请求参数显示在地址栏,相对安全一些。
注:
http协议并不会对数据包中的数据进行加密,所以,对于敏感数据,一定要加密。
b2.会将请求参数添加到实体内容里面,可以提交大量的数据给服务器。
# servlet输出中文,如何处理乱码问题?
# 为什么会产生乱码?
out.println方法默认会使用iso-8859-1来编码。
# 如何处理?
/*
* 1.设置content-type消息头的值。
* 2.out.println方法会使用制定的字符集来编码。
* MIMI类型
*/
response.setContentType("text/html;charset=utf-8");
# 读取请求参数值
# String request.getParameter(String paramName);
注:
如果请求参数名与实际传递过来的与实际传递过来的请求参数名不一致,会获得null值。
# String[] request.getParameterValues(String paramName);
注:
有多个请求参数名相同时,使用次方法。
对于多选框,如果没有选择任何选项,会获得null值。
# 表单包含有中文参数值,如何处理乱码问题?
# 为什么会乱码?
表单提交时,浏览器会对中文参数值进行编码。(比如,使用utf-8来编码),服务器端默认会使用iso8859-1来解码,所以,会产生乱码。
注:
浏览器会使用打开该表单所在页面时的字符集来进行编码。
# 如何解决?
# post请求
/*
* 设置请求参数值的解码方式
* 注:
* a.该方法一定要添加到所有的getParameter方法的前面。
* b.该方法只针对post请求有效。
*/
request.setCharacterEncoding(String charset);
# get请求
修改server.xml,<Connector URIEncoding="utf-8"/>
注:
如果tomcat8.0及以上版本,可以不用加。
# 练习2 添加用户
# 访问数据库
step1.建表
create database jsd1808db default character set utf8;
use jsd1808db;
create table t_user(
id int primary key auto_increment, username varchar(50),
password varchar(20), email varchar(30)
);
step2.导包
从jdbc02maven中拷贝pom.xml的maven依赖
step3.添加jdbc.properties配置文件
step4.添加DBUtils类并测试。
step5.使用jdbc API访问数据库。
# DAO(扩展)
# 什么是DAO(Data Access Object)?
封装了数据访问逻辑的一个对象。
# 怎么写一个DAO
step1.写一个Java类,一般称之为值对象。
注:
该类用于存放从数据库中查询出来的数据。
比如,要查询t_user表中的数据,就可以设计一个User类,该类的结构要与表的结构一致,
也就是说,表有哪些字段,类就会有对应的属性,属性类型要匹配。
因为数据库是面向关系的,而tava是面向对象的,所以创建User类
step2.写DAO类,提供一些访问数据库的方法。
# DAO的优点
a.方便测试。
将数据访问逻辑写在DAO类里面,可以直接测试,如果将数据访问逻辑写在servlet里面,
需要部署整个应用才能测试。
b.方便代码的维护。
DAO封装了数据的访问逻辑,调用者不用关心底层数据库相关的代码,比如,
数据库访问逻辑发生了改变(从jdbc换成了mybatis),对调用者没有任何影响。
# 重定向
# 什么是重定向?
服务器通知浏览器向某个地址发送请求。
注:
服务器可以通过发送302状态码及location消息头(该消息头的值是一个地址,一般称之为重定向地址)给浏览器,浏览器收到后,会立即向重定向地址发送请求。
# 如何重定向?
response.sendRedirect(String url);
注:
url就是重定向地址。
重定向之前,服务器会清空response对象上存放的所有数据。
# 重定向的特点
a.重定向的地址是任意的。 b.重定向之后,浏览器地址栏的地址会发生变化
# 转发
# 什么是转发?
一个web组件将未完成的处理交给另外一个web组件继续做。
注:
web组件指的是servlet和jsp的统称。
常见的情况是一个servlet获得数据之后,转发给一个jsp来展现这些数据。
# 如何转发?
step1.绑定数据到request对象上。
request.setAttribute(String name,Object obj);
注:
name称之为绑定名,obj称之为绑定值。
内部的实现,实际上是将数据放到了一个map对象里面map.put(key,obj)
step2.获得转发器。
RequestDispatcher rd = request.getRequestDispatcher(String uri);
注:
a. requestDispatcher是一个接口,该方法会返回一个实现了该接口的对象(即转发器)。
b. uri是转发的目的地,通常是一个jsp地址。
c. RequestDispatcher可以理解为是一个媒介,web组件可以通过转发器
RequestDispatcher来通知容器去调用另外一个web组件。
d. 转发的本质是一个web组件通知容器去调用另外一个web组件。
step3.转发
rd.forward(request, response);
# 转发的特点
a.转发之后,浏览器地址栏的址不变 b.转发的目的地有限制,要求属于同一个web应用。
# 比较转发与重定向
a.浏览器地址栏的地址有无变化?
重定向之后,浏览器地址栏的地址会发生变化;
转发之后,浏览器地址栏的地址不变。
b.目的地有无限制?
重定向地址没有任何限制,转发有限制(要求属于同一个web应用)。
c.能否共享request对象?
转发所涉及的各个web组件可以共享同一个request对象,重定向不行。
注:
c1 .容器收到请求之后,会立即创建request对象和response对象,一旦响应发送完毕,
容器会立即删除这两个对象。
即request对象和response对象的生存时间很短暂(在一次请求与响应期间存在)。
c2.重定向是两次请求,上次请求创建的request对象和
response对象已经被删除。
d.转发是一件事没有做完,让另外一个web组件继续做;而重定向是一件事 已将完成,去做另外一件独立的事。
# include指令
<%@ include file="" %>
注:
file属性用于指定被包含的文件名。
该指令用来告诉容器,在将jsp转换成servlet时,将file属性指定的文件的内容插入到该指令
所在的位置。
被包含的文件可以是任何文件,包括html,如果是jsp, 该jsp并没有被执行!
# 练习
用户登录
# 状态管理
# 什么是状态管理?
将浏览器与web服务器之间多次交互当作一个整体来处理,并且将多次交互所涉及的数据(即状态)保存下来。
# 如何进行状态管理?
方式一:将状态保存在浏览器端(使用cookie)。 方式二:将状态保存在服务器端(使用session)。
# Cookie(小甜点)
# 什么是cookie?
服务器临时存放在浏览器端的少量数据,用于存放用户的状态。
注:
当浏览器第一次访问服务器时,服务器去会将少量数据以set-cookie消息头的形式
发送给浏览器,浏览器会将这些数据保存下来。
当浏览器再次访问服务器时,会将这些数据以cookie消息头的形式发送非服务器。
# 如何添加Cookie?
Cookie c = new Cookie(String name,String value);
response.addCookie(c);
注:
cookie只能存放字符串。
cookie都有一个名字,值是一个字符串。
# 如何读取Cookie?
Cookie[] request.getCookies();
注:
该方法有可能返回值为null。
String cookie.getName();
String cookie.getValue();
# Cookie的生存时间
默认情况下,浏览器会将Cookie存放到内存里面,浏览器关闭,则Cookie会被删除。
cookie.setMaxAge(int seconds);
注:
单位是秒。
比如保存一个月 30 * 24 * 60 * 60
seconds > 0时:
浏览器会将cookie保存在硬盘上(一般是一个小的文件),超过指定时间,
浏览器会将cookie删除。
second < 0时:
缺省值(浏览器会将Cookie存放到内存里面)。
second = 0时:
浏览器会删除cookie。
比如:要删除一个名称为username的cookie:
Cookie c = new Cookie("username","");
c.setMaxAge(0);
response.addCookie(c);
# Cookie的编码问题
Cookie只能存放合法的ascii字符,如果要存放中文,需要将中文转换成对应的ascii字符的形式(即编码)。
String URLEncoder.encode(String str, String charset);
建议,在添加Cookie时,统一编码处理。ascii编码不支持空格,转码之后在浏览器查看是用➕号连接在一起。利用编码读取以后,还是空格形式。
# Cookie的路径问题?
a.什么是Cookie的路径问题?
浏览器在向服务器发请求时,会比较请求地址是否符合Cookie的路径,只有符合
条件的cookie才会发送给服务器。
b.Cookie的默认路径
等于添加该Cookie的web组件的路径。比如,/day06/biz01/addCookie.jsp,
则该jsp添加的cookie,则该cookie的路径就是“/day06/biz01"。
c.匹配规则
请求地址要么等于cookie的路径,要么是其子路径,符合该要求的cookie会被发送。
比如,cookie的路径是"/day06/biz01",则
“/day06/findCookie1.jsp" no
"/day06/biz01/findCookie2.jsp" yes 自身路径
"/day06/biz01/sub/findCookie2.jsp" yes 子路径
d.修改Cookie的路径
cookie.setpath
# Cookie的限制
a.Cookie可以被用户禁止。
b.Cookie不安全。
cookie是一种客户端的状态管理技术,数据都保存在浏览器端,所以,对于敏感
数据,一定要加密处理。
c.Cookie只能保存少量数据。
大约是4k左右。
d.Cookie的数量也有限制。
大约是几百个。
e.Cookie只能存放字符串。
# 练习
写一个servlet,该servlet先查看有没有一个名称为"cart"的cookie, 如果有,则输出该cookie的值; 如果没有,则添加。
# 练习
统计用户是第几次访问某个Servlet。
# Session(会话)
# 什么是Session?
服务器端为了保存用户的状态,而创建的一个特殊的对象。
注:
当浏览器第一次访问服务器时,服务器创建一个特殊的对象(该对象一般称之为
session对象,session对象有一个唯一的id,一般称之为sessionId)。服务器会将
sessionId以cookie的方式发送给浏览器。
当浏览器再次访问服务器时,会将sessionId发送过来,服务器可以依据sessionId
找到对应的session对象。
# 如何获得Session对象?
# 方式一
HttpSession session = request.getSession(boolean flag)
注:
HttpSession是一个接口。
当flag为true时:
会先查看请求当中是否有sessionId,如果没有,则创建一个session对象。
如果有,则根据sessionId查找对应的session对象,找到了则返回该对象
找不到,则创建一个新的session对象。
当flag为false时:
先查看请求当中是否有sessionId,如果没有,返回null。
如果有sessionId,则依据sessionId查找对应的session对象,找到了则返回
该对象,找不到,返回null。
# 方式二
HttpSession session = request.getSession();
注:
等价于request.getSession(true);
# 常用的方法
//绑定数据
session.setAttribute(String name,Object obj);
//依据绑定名,获得绑定值,如果绑定值不存在,返回null
Object session.getAttribute(String name);
//删除绑订
session.removeAttribute(string name);
# session超时
什么是session超时? 服务器会将空闲时间过长的session对象删除掉。 目的是为了节省空间。 注: 大部分服务器默认的超时时间限制是30分钟。
如何修改超时时间?
方式一 修改服务器的配置文件(web.xml)
方式二 session.setMaxInactiveInterval(int seconds);
用于设置两次请求之间的最大间隔,如果超过这个时间,session对象会被销毁。
# 删除session
session.invalidate()
# session验证
step1.登录成功以后,在session对象上绑定一些数据。比如:
session.setAttribute("user",user);
step2.当用户访问需要保护的资源时(即只有登录之后的用户才能访问的资源),进行session验证。
Object obj = session.getAttribute("user);
if(obj == null){
//没有登录
response.sendRedirect("login.jsp");
}
# Session中存储哪些数据
- 用户的唯一标识,例如用户的ID
- 使用频率非常高的数据,例如用户的用户名,昵称,头像等;
- 其他不便于使用其他技术存储的数据......
# 比较session与cookie
session支持更丰富的数据类型(cookie只能存放字符串)、更安全、可以存放更多的数据(ccokie只能存放少量的数据)。 但是,session是将状态保存在服务器端,有可能会占用过多的内存。
# 路径问题
# 什么是相对路径?
不以“/“开头的路径。
# 什么是绝对路径?
以“/”开头的路径。
# 如何写绝对路径?
连接、表单提交、重定向从应用名开始写; 转发从应用名之后开始写。
注:
不要将用户名直接写在路径里面,而应该使用request.getContextPath()来获得
实际部署时的应用名。
# 建议使用绝对路径,容易写,而且利于维护
# 练习
显示用户上一次访问的时间,如果是第一次访问,显示“你是第一次访问"。
# Servlet的生命周期
# 什么是servlet的生命周期?
容器如何去创建servlet对象,如何对该对象进行初始化,如何调用该对象处理请求,以及如何销毁该对象的整个过程。 即Servlet容器是如何管理Servlet的。
# 生命周期分成那几个阶段?
# 实例化
a.什么是实例化
容器调用servlet的构造器,创建servlet对象。
b.什么时候实例化?
情形1:默认情况下,容器收到请求之后,才会创建。
注:
容器只会创建一个实例。
情形2:容器启动后,立即创建。
注:
需要在web.xml配置load-on-startup参数。
# 初始化
a.什么是初始化?
容器在创建servlet实例之后,会调用该实例的init方法。
注:
init方法只执行一次!
b. GenericServlet已经提供了init方法的实现。
该方法会将容器传递过来的ServletConfig对象保存下来,并且提供了一个方法
(getServletConfig)来获得该对象。
c.如何实现自己的初始化逻辑。
只需要override GenericServlet的init()方法。
d.初始化参数
ServletConfig config = getServletConfig();
/*
* 通过ServletConfig对象提供的方法来读取初始化参数。
*/
String company = config.getInitParameter("company");
# 就绪
a.什么是就绪?
容器收到请求之后,调用servlet对象的service方法来处理请求。
b.HttpServlet已经提供了service方法的实现。
该方法是这样实现的:
依据请求类型调用对应的doXXX方法,比如,get请求会调用doGet方法,
post请求会调用doPost方法。
doGet、doPost方法只是抛除了一个异常
开发人员可以override HttpServlet的doXXX方法来实现业务逻辑的处理。也可以
override HttpServlet的service方法。
# 销毁
a.什么是销毁?
容器在删除servlet对象之前,会调用该对象的destroy方法。
注:
该方法只会执行一次!
b.GenericServlet已经提供了destroy方法的实现。
注:
该方法的实现实际上什么都没有做。
开发人员可以override GenericServlet提供的destroy方法,来实现自己的
销毁处理逻辑。
# 相关的接口与类(了解)。
a.Servlet接口
注:该接口主要声明了三个方法
init(ServletConfig config);
service(ServletRequest req,ServletResponse res);
destroy();
b.GenericServlet抽象类
注:实现了Servlet接口中的部分方法(init,destroy)。
c.HttpServlet抽象类
注:继承了GenericServlet,实现了service方法。
# 容器如何处理请求资源路径?
比如,在浏览器地址栏输入http://ip:port/day08-2/abc.html 浏览器会将"/day08-2/abc.html"作为请求资源路径发送给容器。
step1.容器默认认为访问的是一个servlet,容器会从web.xml中去查找对应的servlet。
会将请求资源路径中的应用名除掉,然后去跟<url-pattern>的值去做匹配
(比如这儿,请求资源路径除掉应用名之后是"/abc.html",url-pattern的值正好也
是“/abc.html",这样就匹配了)。
url-pattern有三种写法:
精确匹配:
即请求资源路径除掉应用名之后的值必须等于url-pattern的值。
统配符匹配:
使用“*”匹配任意的零个或者多个字符。
比如:
<url-pattern>/*</url-pattern>
后缀匹配:
使用“*.“开头,然后接一个后缀(后缀就是一个字符串)。
比如:
<url-pattern>*.do</url-pattern>
以上配置,会匹配所有以.do结尾的请求。
<url-pattern>*.action</url-pattern>
step2.如果没有匹配的servlet,容器会从对应的位置去查找文件,如果找不到,返回404。
# 如何让一个servlet处理多种请求?
step1.使用后缀匹配,比如:
<servlet-mapping>
<servlet-name>ActionServlet2</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
step2.分析请求资源路径,依据请求路径进行相应的处理。
# 过滤器
# 什么是过滤器?
servlet规范当中定义的一种特殊的组件,用于拦截servlet容器的调用过程。
注:
Servlet容器收到请求之后,会先调过滤器,再调用后续的Servlet的。
# 如何写一个过滤器?
step1.写一个Java类,实现Filter接口。
注:
a.过滤器的声明周期类似于servlet的生命周期,也分成四个阶段。区别是,容器
在启动之后,会立即过滤实例,而servlet默认情况下是容器收到请求之后才会创建。
b.Filter接口定义了三个方法,分别用于初始化(init)、就绪(doFilter)和销毁
(destroy)。
step2.在doFilter方法当中,实现拦截处理逻辑。
step3.配置过滤器。(web.xml)
# 过滤器的优先级
当有多个过滤器都满足拦截要求,则容器依据<filter-mapping>
配置的先后顺序来执行。
# 初始化参数
step1.配置初始化参数
<init-param>
<param-name>illegal</param-name>
<param-value>猫</param-value>
</init-param>
step2.读取初始化参数
String illegal = config.getInitParameter("illegal");
注:
config是从init中获取
# 过滤器的优点
a.可以在不修改原有代码的基础上,为应用添加一些简单的功能。 b.可以将多个组件相同的功能集中卸载过滤器里面,方便代码的维护。
# 监听器
# 什么是监听器?
servlet规范当中定义的一种特殊的组件,用于监听servlet容器产生的时间并进行相应的处理。
注:
servlet容器产生两大类事件:
a.生命周期相关的事件:
当容器创建了或者销毁了request,session,servlet上下文时产生的事件。
b.绑定数据相关的事件:
当调用了request,session, servlet上下文的setAttribute,removeAttribute时
产生的事件。
# Servlet上下文
# 什么是Servlet上下文?
容器启动之后,会为每一个web应用创建唯一的一个符合ServletContext接口要求的对象,该对象我们一般称之为Servlet上下文。
该对象有两个特点:
a.唯一性:一个web应用对应一个servlet上下文。
b.持久性:只要容器不关闭(应用没有被卸载),则servlet上下文会一直存在。
# 如何获得servlet上下文?
可以通过ServletConfig,FilterConfig,GenericServlet, HttpSession提供的方法(getServletContext)来获得。
# 作用
a.绑定数据
setAttribute(String name,Object);
Object getAttribute(string name);
removeAttribute(String name);
注:
request,session,servlet上下文都提供了绑定数据相关的方法,如别如下:
区别1:绑定的数据,生存的时间是不一样的,从小到大依次是
request<session<servlet上下文。在满足使用条件的情况下,优先使用
生命周期短的。
区别2:
b.读取全局的初始化参数
配置全局的初始化参数
<context-param>
<param-name>company</param-name>
<param-value>IBM</param-value>
</context-param>
//读取全局的初始化参数
String company = sctx.getInitParameter("company");
# 如何写一个监听器?
step1.写一个Java类,实现相应的监听器接口。
注;
要依据监听的事件类型来选择实现对应的接口,比如,要监听session对象的创建
和销毁,需要实现HttpSessionListener接口。
step2.在监听器接口方法当中,实现监听处理逻辑。
step3.配置监听器(web.xml)
<listener>
<listener-class>web.CountListener</listener-class>
</listener>
# 练习
写一个过滤器,检查评论的子数,如果超过10个字,则提示用户“评论字数过多”。
统计在线人数。
# Servlet的线程安全问题
# 为什么说Servlet会有线程安全问题?
a. 容器只会创建一个实例。 b. 容器收到一个请求,就会启动一个线程,由该线程来进行相应的处理。这样就有可能有多个线程同时去调用同一个servlet对象的service方法,就有可能产生线程安全问题。比如说,这些线程同时去修改该servlet的某个属性。
# 如何解决?
/*
* 对有可能产生线程安全问题的代码块加锁。
*/
synchronized(this) {
count ++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(
Thread.currentThread().getName()+":"+count);
}
# Servlet总结
# Servlet基础
1).什么是Servlet?
2).如何写一个Servlet?
3).Servlet是如何运行的?
4).Http协议(了解)
a. http协议是什么?
b. 特点?
c. 数据包的结构(消息头、状态码、)
d. 两种请求方式 get post
# Servlet核心
1). 如何获得请求参数值?
2). Servlet输出中文,如何处理?
3). 表单包含有中文参数,如何处理?
4). Servlet容器如何处理请求资源路径?
5). 如何让一个Servlet处理多种请求?
6). Servlet的线程安全问题
7). 转发与重定向
a. 什么是重定向?
b. 如何重定向?
c. 重定向的特点
d. 什么是转发?
e. 如何转发?
f. 转发的特点
g. 比较转发与重定向
8). Servlet的生命周期
a. 什么是Servlet的生命周期?
b. 生命周期分成哪几个阶段?
c. 容器在什么时候创建Servlet对象?
d. 容器会创建几个Servlet实例。
e. 初始化方法会执行几次?
g.如何配置初始化参数?
h. 如何实现自己的初始化处理逻辑?
i. doGet,doPost方法的作用?
j. Servlet接口,GenericServlet,HttpServlet的关系。
h. ServletConfig的作用?
9). 路径问题
a. 什么是相对路径?
b. 什么是绝对路径?
c. 如何写绝对路径?request.getContextPath();
10)Servlet上下文
a. 什么是Servlet上下文?(唯一性,持久性)
b. 如何获得Servlet上下文?
c. 主要作用(绑定数据时与request,sessioon的区别)
d. 全局的初始化参数。
# 状态管理
1). 什么是状态管理? 2). 如何进行状态管理? 3). Cookie
a. 什么是Cookie?
b. 如何添加Cookie?
c. 添加Cookie时需要考虑的三个问题(编码问题、生存事件、路径问题)。
d. 如何读取Cookie?
e. Cookie的限制
4). Session
a. 什么是Session?
b. 如何获得Session对象?
c. 常用方法。
d. Session超时。
e. 删除Session对象
f. 比较Cookie与Session
# 过滤器与监听器
1). 什么是过滤器?
2). 如何写一个过滤器?
3). 过滤器的优先级
4). 初始化参数
5). 过滤器的优点
6). 什么是监听器?
7). 如何写一个监听器?
# 数据访问
1). 什么是DAO?
2). 如何写一个DAO?
3). DAO的优点?
# 典型案例
用户管理
登录(session验证)