Servlet
初识Servlet
概述
- Servlet 是 JavaEE 规范之一。 规范就是接口
- Servlet 就 JavaWeb 三大组件之一。 三大组件分别是: Servlet 程序、 Filter 过滤器、 Listener 监听
- Servlet 是运行在服务器上的一个 java 小程序, 它可以接收客户端发送过来的请求, 并响应数据给客户端。
Servlet规范
- 作用:
- 在Servlet规范中,指定【动态资源文件】开发步骤。
- 在Servlet规范中,指定Http服务器调用动态资源文件规则。
- 在Servlet规范中,指定Http服务器管理动态资源文件实例对象规则。
Servlet基本使用
Servlet接口实现类
Tomcat服务器下lib文件下有一个servlet-api.jar存放的Servlet接口(javax.servlet.Servlet接口)
Servlet规范中任务,Http服务器能调用的【动态资源文件】必须是一个Servlet接口实现类
例:
public class Student { // 不是动态文件,Tomcat无权调用 } class Tearcher implements Servlet { // 合法动态文件,Tomcat可以调用 }
将Servlet接口实现类信息【注册】到Tomcat服务器
【网站】–>【web】–>【WEB-INF】—>web.xml
<!--将servlet接口实现类类路径地址交给Tomcat--> <servlet> <servlet-name>ServletTest01</servlet-name> <servlet-class>lesson01.ServletTest01</servlet-class> </servlet> <!--为servlet接口实现类提供一个简短的别名--> <servlet-mapping> <servlet-name>ServletTest01</servlet-name> <url-pattern>/Test01</url-pattern> </servlet-mapping>
在浏览器向Tomcat索要ServletTest01时的地址:
Servlet生命周期
网站中所有的Servlet接口实现类的实例对象,只能由Http服务器负责创建,开发人员不能手动创建Servlet接口实现类的实例对象。
在默认的情况下,Http服务器接收到对于当前Servlet接口实现类第一次请求时自动创建这个Servlet接口实现类的实例对象,在手动配置情况下,要求Http服务器在启动时自动创建某个Servlet接口实现类的实例对象。
<servlet> <servlet-name>ServletTest03</servlet-name> <!--声明一个变量存储servlet接口实现类类路径--> <servlet-class>lesson01.ServletTest03</servlet-class> <load-on-startup>3<load-on-startup> <!--以上填写一个大于0的整数即可--> </servlet>
在Http服务器运行期间,一个Servlet接口实现类只能被创建出一个实例对象
在Http服务器关闭时刻,自动将网站中所有的Servlet对象进行销毁
HttpServletResponse接口(响应对象)
概述
- HttpServletResponse接口来自于Servlet规范中,在Tomcat中存在servlet-api.jar。
- HttpServletResponse接口实现类由Http服务器负责提供。
- HttpServletResponse接口负责将doGet/doPost方法执行结果写入到【响应体】交给浏览器。
- 开发人员习惯于将HttpServletResponse接口修饰的对象称为【响应对象】。
主要功能
- 将执行结果以二进制形式写入到【响应体】
- 设置响应头中[content-type]属性值,从而控制浏览器使用对应编译器将响应体二进制数据编译为【文字,图片,视频,命令】。
- 设置响应头中【location】属性,将一个请求地址赋值给location,从而控制浏览器向指定服务器发送请求。
常用方法
- getWriter(); 获取Tomcat服务器输出流对象(返回PrintWriter对象)
- sendRedirect():在响应体中添加请求地址
- setContentType():在响应体中针对相应输出数据指定浏览器采用正确格式输出,及编码格式
- write()方法:通过Tomcat服务器输出流对象为响应体输出二进制数据
注意:一般返回【字符】、【字符串】、【ASCII码】 - print()方法:通过Tomcat服务器输出流对象为响应体输出二进制数据
注意:print方法可以输出任何数据且不会转变成ASCII码,所以大多数使用print方法
HttpServletRequest接口(请求对象)
概述
- HttpServletRequest接口来自于Servlet规范中,在Tomcat中存在servlet-api.jar。
- HttpServletRequest接口实现类由Http服务器负责提供。
- HttpServletRequest接口负责在doGet/doPost方法运行时读取Http请求协议包中信息。
- HttpServletRequest接口实现了service方法,此方法可以处理get/post请求。
- 开发人员习惯于将HttpServletRequest接口修饰的对象称为【请求对象】。
主要功能
- 可以读取Http请求协议包中【请求行】信息
- 可以读取保存在Http请求协议包中【请求头】或则【请求体】中请求参数信息
- 可以代替浏览器向Http服务器申请资源文件调用
常用方法
- getRequestURL():获取【请求行】中【url】信息
- getMethod():获取【请求行】中【method】(请求方式)信息
- getRequestURI():获取【请求行】中uri信息
- setCharacterEncoding:修改请求字符集编码格式
URI:
- 资源文件精准定位地址,在请求行中并没有URI这个属性
- 实际上是截取的URL中的字符串,这个字符串格式:“/网站名/资源文件名”
- URI用于HTTP服务器对访问的资源文件进行定位
getParameterNames():获取请求参数名称
getParameter():获取请求参数值
请求对象与响应对象的生命周期
1.在Http服务器接收到浏览器发送的【Http请求协议包】之后,自动为当前的【Http请求协议包】生成一个【请求对象】和一个【响应对象】。
2.在Http服务器调用doGet/doPost方法时,负责将【请求对象】和【响应对象】作为实参传递到方法,确保doGet/doPost正确执行。
3.在Http服务器准备推送Http响应协议包之前,负责将本次请求关联的【请求对象】和【响应对象】销毁。
【请求对象】和【响应对象】生命周期贯穿一次请求的处理过程中【请求对象】和【响应对象】相当于用户在服务端的代言人。
欢迎资源文件
引例:
用户发送了一个针对某个网站的【默认请求】时,此时由Http服务器自动从当前网站返回的资源文件。
例:正常请求(网址):https://www.baidu.com:80/index.html
常用请求(网址):https://www.baidu.com/
Tomcat对于默认欢迎资源文件规则:
规则位置:Tomcat安装位置/conf/web.xml
规则命令:
<welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list>
设置当前网站的默认欢迎资源文件规则
规则位置:网站/web/WEB-INF/web.xml
规则命令:
<welcome-file-list> <welcome-file>login.html</welcome-file> </welcome-file-list>
注意:网站设置自定义默认文件定位规则,此时Tomcat自带定位规则将失效.
欢迎资源文件运行步骤:
- Tomcat服务器自上而下查找第一行的资源文件是否存在,如存在则返回。
- 如不存在则查找第二个文件,如果第二个不存在则查找下条,直到将配置的资源文件查找完毕。
- 如查找完毕都找不到,则Tomcat返回404。
Http状态码
概述
- 由100—599三位数字组成的一个一串数字为状态码。
- Http服务器在推送响应包之前,根据本次请求处理情况,将Http状态码写入到响应包中【状态行】上。
- 如果Http服务器针对本次请求,返回了对应的资源文件,通过Http状态码通知浏览器应该如何处理这个结果。
- 如果Http服务器针对本次请求,无法返回对应的资源文件,通过Http状态码向浏览器解释不能提供服务的原因。
分类(以下为常见状态码)
1XX:
100:通知浏览器本次返回的资源文件,并不是一个独立的资源文件,需要浏览器在接收响应包之后,继续向Http服务器所要依赖的其他资源文件。
2XX:
200:通知浏览器本次返回的资源文件是一个完整独立资源文件,浏览器在接收到之后不需要所要其他关联文件。
3XX:
302:通知浏览器本次返回的不是一个资源文件内容而是一个资源文件地址,需要浏览器根据这个地址自动发起请求来索要这个资源文件。
例:response.sendRedirect(“资源文件地址”)写入到响应头中
以上行为会让Tomcat服务器将302状态码写入到状态行。
4XX:
404:通知浏览器,由于在服务端没有定位到被访问的资源文件,因此无法提供帮助。
405:通知浏览器,在服务端已经定位到被访问的资源文件(Servlet),但是这个Servlet对于浏览器采用的请求方式不能处理。
例如:浏览器是以get方式请求的,而服务器端只写了一个post方式接受请求,就会返回405。
5XX:
500:通知浏览器,在服务端已经定位到被访问的资源文件(Servlet),这个Servlet可以接收浏览器采用请求方式,但是Servlet在处理请求期间,由于Java异常导致处理失败。
Servlet之间调用
问题
某些来自于浏览器发送请求,往往需要服务端中多个Servlet协同处理。但是浏览器一次只能访问一个Servlet,导致用户需要手动通过浏览器发起多次请求才能得到服务。这样增加用户获得服务难度,导致用户放弃访问当前网站。
解决
无论本次请求涉及到多少个Servlet,用户只需要【手动】通知浏览器发起一次请求即可。
重定向解决方案
工作原理:
服务器端:
用户第一次通过【手动方式】通知浏览器访问第一个Servlet动态文件。当第一个Servlet工作完毕后,将第二个Servlet地址写入到响应头location属性中,导致Tomcat将302状态码写入到状态行。
浏览器端:
在浏览器接收到响应包之后,会读取到302状态。此时浏览器自动根据响应头中location属性地址发起第二次请求,访问第二个Servlet去完成请求中剩余任务。
实现命令:
- 以上命令是将地址写入到响应包中响应头中location属性中。
response.sendRedirect("请求地址")
特征:
请求地址
既可以把当前网站内部的资源文件地址发送给浏览器 (/网站名/资源文件名)也可以把其他网站资源文件地址发送给浏览器(http://ip地址:端口号/网站名/资源文件名)。
请求次数
浏览器至少发送两次请求,但是只有第一次请求是用户手动发送。后续请求都是浏览器自动发送的。
请求方式
重定向解决方案中,通过地址栏通知浏览器发起下一次请求,因此 通过重定向解决方案调用的资源文件接收的请求方式一定是【GET】。
缺点:
重定向解决方案需要在浏览器与服务器之间进行多次往返,大量时间消耗在往返次数上,增加用户等待服务时间。
请求方式:
因为第二次的Servlet是通过第一个Servlet的响应头location属性发送到浏览器中的,所以当浏览器发送第二次Servlet时候是以网址发送,网址发送都是以Get方式发送请求。
请求转发解决方案
工作原理:
用户第一次通过手动方式要求浏览器访问第一个Servlet。当抵押给Servlet工作完毕后,通过当前的请求对象代替浏览器向Tomcat发送请求,申请调用第二个Servlet。Tomcat在接收到这个请求之后,自动调用第二个Servlet来完成剩余任务。
实现命令:
- 请求对象代替浏览器向Tomcat发送请求
//1.通过当前请求对象生成资源文件申请报告对象
RequestDispatcher report = request.getRequestDispatcher("/资源文件名");一定要以"/"为开头
//2.将报告对象发送给Tomcat
report.forward(当前请求对象,当前响应对象)
特征:
请求地址:
只能向Tomcat服务器申请调用当前网站下资源文件地址。
请求次数:
在请求转发过程中,浏览器只发送一次请求。
优点:
无论本次请求涉及到多少个Servlet,用户只需要手动通过浏览器发送一次请求。
Servlet之间调用发生在服务端计算机上,节省服务端与浏览器之间往返次数增加处理服务速度。
请求方式:
在请求转发过程中,浏览器只发送一个了个Http请求协议包。参与本次请求的所有Servlet共享同一个请求协议包,因此这些Servlet接收的请求方式与浏览器发送的请求方式保持一致。
Servlet数据共享
概述
当第一个Servlet工作完毕后,将产生的数据交给第二个Servlet来使用。这两者之间的数据传递称之为”数据共享。
数据共享的方案:
ServletContext接口
概述
来自于Servlet规范中一个接口。在Tomcat中存在servlet-api.jar,Tomcat服务器负责提供这个接口实现类。
如果两个Servlet来自于同一个网站。彼此之间通过网站的ServletContext实例对象实现数据共享。
开发人员习惯于将ServletContext对象称为【全局作用域对象】。
工作原理:
每一个网站都存在一个全局作用域对象。 这个全局作用域对象【相当于】一个Map集合,在这个网站中第一个Servlet可以将一个数据存入到全局作用域对象,当前网站中其他Servlet此时都可以从全局作用域对象得到这个数据进行使用。
生命周期:
- 在Http服务器启动过程中,自动为当前网站在内存中创建一个全局作用域对象。
- 在Http服务器运行期间时,一个网站有且只有一个全局作用域对象。
- 在Http服务器运行期间,全局作用域对象一直处于存活状态。
- 在Http服务器准备关闭时,负责将当前网站中全局作用域对象进行销毁处理。
总结:全局作用域对象生命周期贯穿网站整个运行期间。
命令实现:
OneServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
//1.通过【请求对象】向Tomcat索要当前网站中【全局作用域对象】
ServletContext application = request.getServletContext();
// 注意:一般全局作用域对象名为:application
//2.将数据添加到全局作用域对象作为【共享数据】
application.setAttribute("key1",数据);
}
}
TwoServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
//1.通过【请求对象】向Tomcat索要当前网站中【全局作用域对象】
ServletContext application = request.getServletContext();
//2.从全局作用域对象得到指定关键字对应数据
Object 数据 = application.getAttribute("key1");
}
}
Cookie类
概述
- Cookie来自于Servlet规范中一个工具类,存在于Tomcat提供servlet-api.jar中。
- 如果两个Servlet来自于同一个网站,并且为同一个浏览器/用户提供服务,此时借助于Cookie对象进行数据共享。
- Cookie存放当前用户的私人数据,在共享数据过程中提高对用户的服务质量。
- 在现实生活场景中,Cookie相当于用户在服务端得到【会员卡】
特点
- cookie相当于一个map集合,但是这个键值对的key与value只能是String。
- 键值对中key不能是中文。
工作原理
用户通过浏览器第一次向这个网站发送请求申请Servlet。 Servlet在运行期间创建一个Cookie存储与当前用户相关数据,Servlet工作完毕后,【将Cookie写入到响应头】交还给当前浏览器,浏览器收到响应响应包之后,将cookie存储在浏览器的缓存。
一段时间之后,用户通过【同一个浏览器】再次向【myWeb网站】发送请求申请TwoServlet时。【浏览器需要无条件的将myWeb网站之前推送过来的Cookie,写入到请求头】发送过去,此时第二个Servlet在运行时,就可以通过读取请求头中cookie中信息,得到第一个Servlet提供的共享数据。
生命周期
在默认情况下,Cookie对象存放在浏览器的缓存中。因此只要浏览器关闭,Cookie对象就被销毁掉
在手动设置情况下,可以要求浏览器将接收的Cookie存放在客户端计算机上硬盘上,同时需要指定Cookie
在硬盘上存活时间。在存活时间范围内,关闭浏览器关闭客户端计算机,关闭服务器,都不会导致Cookie被销毁。在存活时间到达时,Cookie自动从硬盘上被删除。cookie.setMaxAge(minute); //cookie在硬盘上存活time分钟
命令实现
例:同一个网站 OneServlet 与 TwoServlet 借助于Cookie实现数据共享
// 第一个Servlet
OneServlet{
public void doGet(HttpServletRequest request,HttpServletResponse resp){
//1.创建一个cookie对象,保存共享数据(当前用户数据)
Cookie card = new Cookie("key1","abc");
Cookie card1= new Cookie("key2","efg");
//2.【发卡】将cookie写入到响应头,交给浏览器
resp.addCookie(card1);
resp.addCookie(card2)
}
}
/*浏览器/用户 <--- 响应包,状态码:【200】
【cookie: key1=abc; key2=eft】
浏览器向网站发送请求访问TwoServlet ---> 请求包 【url:/myWeb/two method:get】
请求参数:xxxx
Cookie key1=abc;key2=efg
*/
// 第二个Servlet
TwoServlet{
public void doGet(HttpServletRequest request,HttpServletResponse resp){
//1.调用请求对象从请求头得到浏览器返回的Cookie
Cookie cookieArray[] = request.getCookies();
//2.循环遍历数据得到每一个cookie的key 与 value
for(Cookie card:cookieArray){
String key = card.getName(); 读取key "key1"
String value = card.getValue();读取value "abc"
}
}
}
HttpSession接口
概述
- HttpSession接口来自于Servlet规范下一个接口。存在于Tomcat中servlet-api.jar,其实现类由Http服务器提供,Tomcat提供实现类存在于servlet-api.jar。
- 如果两个Servlet来自于同一个网站,并且为同一个浏览器/用户提供服务,此时 借助于HttpSession对象进行数据共享。
- 开发人员习惯于将HttpSession接口修饰对象称为【会话作用域对象】
HttpSession 与 Cookie 区别:【面试题】
- 存储位置:
- Cookie:存放在客户端计算机(浏览器内存/硬盘)。
- HttpSession:存放在服务端计算机内存。
- 数据类型:
- Cookie对象存储共享数据类型只能是String。
- HttpSession对象可以存储任意类型的共享数据Object。
- 数据数量:
- 一个Cookie对象只能存储一个共享数据。
- HttpSession使用map集合存储共享数据,所以可以存储任意数量共享数据。
- 参照物:
- Cookie相当于客户在服务端【会员卡】
- HttpSession相当于客户在服务端【私人保险柜】
生命周期
用户与HttpSession关联时使用的Cookie只能存放在浏览器缓存中,在浏览器关闭时,意味着用户与他的HttpSession关系被切断。
由于Tomcat无法检测浏览器何时关闭,因此在浏览器关闭时并不会导致Tomcat将浏览器关联的HttpSession进行销毁。
为了解决这个问题,Tomcat为每一个HttpSession对象设置【空闲时间】这个空闲时间默认30分钟,如果当前HttpSession对象空闲时间达到30分钟,此时Tomcat认为用户已经放弃了自己的HttpSession,此时Tomcat就会销毁掉这个HttpSession。HttpSession空闲时间手动设置
<!--当前网站/web/WEB-INF/web.xml--> <session-config> <session-timeout>minute</session-timeout> <!--当前网站中每一个session最大空闲时间minute分钟--> </session-config>
实现原理
命令实现
例:同一个网站 OneServlet 与 TwoServlet 借助于Cookie实现数据共享
OneServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
//1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜
HttpSession session = request.getSession();
//2.将数据添加到用户私人储物柜
session.setAttribute("key1",共享数据)
}
}
// 浏览器访问/myWeb中TwoServlet
TwoServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
//1.调用请求对象向Tomcat索要当前用户在服务端的私人储物柜
HttpSession session = request.getSession();
//2.从会话作用域对象得到OneServlet提供的共享数据
Object 共享数据 = session.getAttribute("key1");
}
}
Http服务器将用户与HttpSession关联起来
getSession()
如果当前用户在服务端已经拥有了自己的私人储物柜,要求tomcat将这个私人储物柜进行返回,如果当前用户在服务端尚未拥有自己的私人储物柜要求Tocmat为当前用户创建一个全新的私人储物柜。getSession(false)
如果当前用户在服务端已经拥有了自己的私人储物柜,要求tomcat将这个私人储物柜进行返回
如果当前用户在服务端尚未拥有自己的私人储物柜,此时Tomcat将返回null。
总结:以上两种方法第一种更适合登陆成功使用,第二个则用户未登录成功使用。
HttpServletRequest接口
概述
在同一个网站中,如果两个Servlet之间通过【请求转发】方式进行调用,彼此之间共享同一个请求协议包。而一个请求协议包只对应一个请求对象,因此servlet之间共享同一个请求对象,此时可以利用这个请求对象在两个Servlet之间实现数据共享。
在请求对象实现Servlet之间数据共享功能时,开发人员将请求对象称为【请求作用域对象】
命令实现
// OneServlet通过请求转发申请调用TwoServlet时,需要给TwoServlet提供共享数据
OneServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
//1.将数据添加到【请求作用域对象】中attribute属性
request.setAttribute("key1",数据); //数据类型可以任意类型Object
//2.向Tomcat申请使用请求转发方式调用TwoServlet
request.getRequestDispatcher("/two").forward(req,response)
}
}
TwoServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response){
//从当前请求对象得到OneServlet写入到共享数据
Object 数据 = request.getAttribute("key1");
}
}
注意:
- 当请求转发时,只有请求对象有请求作用域对象,而响应对象是没有作用域对象的。
- 在多个请求转发时,一般只有最后一个Servletv才会将最后的结果发送给浏览器。
监听器接口
概述
- 一组来自于Servlet规范下接口,共有8个接口。在Tomcat存在servlet-api.jar包。
- 监听器接口需要由开发人员亲自实现,Http服务器提供jar包并没有对应的实现类。
- 监听器接口用于监控【作用域对象生命周期变化时刻】以及【作用域对象共享数据变化时刻】。
作用域对象
在Servlet规范中,认为在服务端内存中可以在某些条件下为两个Servlet之间提供数据共享方案的对象,被称为【作用域对象】。
Servlet规范下作用域对象:
- ServletContext:全局作用域对象
- HttpSession:会话作用域对象
- HttpServletRequest:请求作用域对象
监听器接口实现类开发规范
- 根据监听的实际情况,选择对应监听器接口进行实现。
- 重写监听器接口声明【监听事件处理方法】。
- 在web.xml文件将监听器接口实现类注册到Http服务器。
监听器接口(全局作用域接口)
ServletContextListener接口
作用:
- 通过这个接口合法的检测全局作用域对象被初始化时刻以及被销毁时刻。
监听事件处理方法
public void contextInitialized() // 在全局作用域对象被Http服务器初始化被调用
public void contextDestroyed() // 在全局作用域对象被Http服务器销毁时候触发调用
ServletContextAttributeListener接口
作用
- 通过这个接口合法的检测全局作用域对象共享数据变化时刻。
监听事件处理方法
public void attributeAdded() // 在全局作用域对象添加共享数据
public void attributeReplaced() // 在全局作用域对象更新共享数据
public void attributeRemoved() // 在全局作用域对象删除共享数据
全局作用域对象共享数据变化时刻
ServletContext application = request.getServletContext(); // 获取全局作用域对象
application.setAttribute("key1",100); //新增共享数据
application.setAttribute("key1",200); //更新共享数据
application.removeAttribute("key1"); //删除共享数据
过滤器接口(Filter)
概述
- 来自于Servlet规范下接口,在Tomcat中存在于servlet-api.jar包。
- Filter接口实现类由开发人员负责提供,Http服务器不负责提供。
- Filter接口在Http服务器调用资源文件之前,对Http服务器进行拦截。
作用
- 拦截Http服务器,帮助Http服务器检测当前请求合法性。
- 拦截Http服务器,对当前请求进行增强操作。
Filter接口实现类开发步骤
- 创建一个Java类实现Filter接口。
- 重写Filter接口中doFilter方法。
- web.xml将过滤器接口实现类注册到Http服务器。
Filter拦截地址格式
命令格式:
<!--1.将过滤器移交给Tomcat-->
<filter>
<filter-name>filterName</filter-name>
<filter-class>filter类文件地址</filter-class>
</filter>
<!--2.调用何种资源文件时,需要被当前过滤器拦截-->
<filter-mapping>
<filter-name>filterName</filter-name>
<!--调用这个资源文件时,过滤器进行拦截-->
<url-pattern>将要拦截的资源文件</url-pattern>
</filter-mapping>
拦截的资源文件格式
- 在调用何种资源文件之前需要调用Filter过滤器进行拦截。
<!--要求Tomcat在调用某一个具体文件之前,来调用Filter拦截-->
<url-pattern>/imgs/photo.jpg</url-pattern>
<!--要求Tomcat在调用某一个文件夹下所有的资源文件之前,来调用Filter拦截-->
<url-pattern>/img/*</url-pattern>
<!--要求Tomcat在调用任意文件夹下某种类型文件之前,来调用Filter拦截-->
<url-pattern>*.jpg</url-pattern>
<!--要求Tomcat在调用网站中任意文件时,来调用Filter拦截-->
<url-pattern>/*</url-pattern>