什么是Servlet
- sun公司制定一种扩展Web服务器功能的组件规范
扩展Web服务器功能
- web服务器只能够处理静态的资源请求(需要事先将HTML文件写好),不能够处理动态资源请求(需要计算生成HTML),所有需要扩展。可以使用Servlet来扩展web服务器功能,当web服务器收到请求之后,如果需要计算,则交给Servlet来处理。
- 注:常见的文本服务器:Apache,iis,nginx等。
组件规范
- 什么是组件:符合规范,实现部分功能,并且部署到相应的容器里面才能运行的软件模块。Servlet就是一个组件,需要部署到Servlet容器里面才能运行。
- 什么是容器:符合规范,提供组件的运行环境的程序。Tomcat就是一个Servlet容器,为Servlet提供运行环境(提供网络相关的服务)
如何写Servlet
1、写一个java类,实现Servlet接口或者继承HttpServlet类(通常继承HttpServlet)。
2、编译。
3、打包。即创建一个具有如下结构的文件夹。
appname(应用名)
WEB-INF
classes(.class)
lib(.jar)
web.xml(部署描述文件)
html文件
4、部署。将第三步创建好的文件夹拷贝到容器响应的位置。[可以将整个文件夹使用jar先压缩成.war为后缀的文件,然后在拷贝。]
5、启动容器,访问Servlet。
http://ip:port/appname/url-pattern
url-pattern在web.xml当中配置
Servlet是如何运行的
比如,在浏览器输入 http://ip:port/day01/hello
1、浏览器依据ip和port建立连接。
2、浏览器将相关数据放到请求数据包中,然后发送给服务器。
3、服务器解析请求数据包,将解析到的数据添加到request对象,同时创建一个response对象。
4、服务器创建Servlet对象,然后调用该对象的service方法。
注:服务器会将request和response对象作为参数传递过来,开发人员只需要调用这两个对象的方法就可以了,不用考虑网络相关问题。比如,要读取请求数据包中的数据,只需要调用request对象的方法就可以了。类似的,要向浏览器发送处理结果,只需要调用response对象的方法就可以了。
5、服务器从response对象中获得处理结果,然后创建响应数据包并发送给浏览器。
6、浏览器解析响应数据包,生成相应的页面。
常见的问题
- 404
1、含义:服务器依据请求路径找不到对应的资源。
2、产业原因:a、请求路径写错。b、应用没有部署或者部署失败。 - 500
1、含义:系统出错。
2、产生原因:a、没有严格按照规范些代码(包括部署描述写错)b、代码不严谨(比如请求参数不做检查,直接类型转换) - 405
1、含义:找不到处理方法
2、产生原因:service方法没有正确重写
http协议
什么是http协议
是一种网络应用层协议,规定了浏览器与web服务器之间如何通信以及相应的数据结构。
a、tcp/ip协议:属于传递层和网络层协议,保证数据可靠的传递。http协议属于应用层协议,需要依赖tcp/ip协议来传递数据包。
b、浏览器与web服务器之间如何通信:建立连接,发送请求,发送响应,关闭连接
特点:一次请求,一次连接
这样做的好处是服务器可以利用有限的连接做尽可能多的请求服务-
数据包的结构
1)请求数据包
a、请求行(请求方式,请求资源路径,协议版本)b、消息头 消息头四一些键值对(使用“: ”分隔),浏览器与web服务器之间可以通过消息头来传递一些特点的信息。比如,浏览器可以通过发送“user-age”消息头,告诉浏览器的类型和版本。 c、实体类容 只有当请求方式有post时,实体内容才会有数据,请求方式为get时,实体内容为空。
2)响应数据包
a、状态行(协议版本和状态码,状态描述)
200 :正常
500 :系统出错
404 :请求路径出错
b、消息头
服务器也可以发送一些消息头给浏览器,比如,可以发送“content-Type”消息头,告诉浏览器,服务器返回的数据类型
c、实体内容
程序处理结果,浏览器会解析出来,生成相应的页面。 两种请求方式
(1)get请求
a、哪些情况浏览器会发送get请求?
在浏览器地址栏直接输入某个地址
点击链接
表单默认的提交方式
b、特点
会将请求参数添加到请求资源路径的后面,只能提交少量的数据(2k)给服务器。
会将请求参数显示在浏览器地址栏,不安全
(2)post请求
a、哪些情况下,浏览器会发送post请求
将表单的method属性设置为post
b、特点
会将请求参数添加到实体类容中,可以提交大量的数据给服务器
不会将请求参数显示在浏览器地址栏,相对安全
(http协议并不会对数据加密,所有对于敏感数据需要进行加密)
Servlet输出中文如何处理
- 为什么吹产生乱码?
out.println()默认使用ISO-8859-1来编码(不支持中文) - 处理response.setContentType("text/html;charset=utf-8");
如何读取参数值
request.getParameter(String paramName)
- 如果请求参数名写错,获得null
- 表单提交时,不填写任何数据,会获得空字符串
String[] request.getParameterValues(String paramName)
- 当有多个请求参数名相同时,使用此方法
- 对于多选框和单选框,如果一个都不选,会获得null值
表单包含有中文参数,如何处理
- 为什么会有乱码
当提交表单时,浏览器会按照打开该表单所在的页面时的字符集来对中文参数进行编码。比如使用utf-8来编码,而服务器端默认使用ISO-8859-1来解码。所有会产生乱码 - 如何处理
-- get请求:可以修改服务器端的配置,在servers中的server.xml添加URIEncoding="utf-8"
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="utf-8" />
-- post请求:request.setCharacterEncoding(String charset);
DAO (Data Access Object )
- 什么是DAO:封装了数据访问逻辑的对象
- 如何写DAO:
1、写一个java类,用于存放从数据库中查询得到的数据。
2、写DAO类,该类封装了数据库访问逻辑。 - DAO的优点:
a、方便测试:比如,如果将数据库访问代码写在Servlet里面,需要部署应用才能测试。而将数据库访问代码写在DAO类里面,可以直接测试。
b、方便分工协作
c、方便代码的维护:比如,数据访问逻辑发送改变,不会影响到Servlet。
重定向
- 什么是重定向:服务器通知浏览器向某个地址栏发送请求。
服务器通过发送302状态码和Location消息头(该消息头的值是一个地址,一般称为重定向地址),浏览器收到之后,会立即向重定向地址发送请求。 - 如何重定向:response.sendRedirect(String url);
- 重定向的细节:重定向之前,容器会先清空response对象上存放的所有数据。(实体内容为空)
- 特点:
a、重定向的地址是任意的。
b、重定向之后,浏览器地址栏会发送变化。
jsp
- jsp是什么:jsp是sun公司制定的一种服务端的动态技术规范。
因为虽然可以使用Servlet生成动态页面,但是过于繁琐,不好维护,所以sun才制订jsp规范。jsp是一个以.jsp为后缀的文件(主要内容为HTML和少量的java代码),容器会将jsp文件转换为一个对应的Servlet然后执行。
jsp本质就是一个Servlet! - jsp文件中可以添加哪些内容
1、html(css,javascript)直接写即可。
2、java代码
方式一:java代码片段
<% java代码 %>
方式二:jsp表达式
<%= java表达式 %> - jsp是如何执行的
1、阶段1:容器先将jsp转换成一个对应的Servlet
html(css,JavaScript)------>在service方法里面,使用out.write输出。
<% %> ------->在service方法里面,照搬。
<%= %> ---------->在service方法里面,使用out.print输出
2、阶段2:容器调用该Servlet
需要将Servlet编译,然后实例化,调用对应的service方法。 - 隐含对象
a、什么是隐含对象:直接可以使用的对象。
b、为什么可以直接使用隐含对象:容器在将jsp转换成对应的Servlet时,会自动添加获得这些对象代码。
指令
- 什么是指令:通过指令,可以告诉容器在将jsp转换成Servlet时做一些额外的处理。
- 语法:<%@ 指令名 属性="值" %>
注:如果有多个属性,使用空格隔开 - page指令
import属性:指定要导入的包名
<%@ page import="java.util.,java.text." %>
contentType属性:指定response.setContentType方法的属性值
pageEncoding属性:告诉容器,在读取jsp文件的内容时,使用该属性指定的字符集编码
转发
- 什么是转发:一个web组件将未完成的处理,通过容器交给另外一个web组件继续做。
注:web组件指的是servlet或者jsp。 - 如何转发:
1、绑定数据到request对象上。
request.setAttribute(String name,Object);
注:name:绑定名 obj:绑定值
String request.getAttribute(String name);
2、获得转发器
RequestDispatcher rd = request.getRequestDispatcher(String url);
注:url是转发的地址,通常是一个jsp
3、转发
rd.forward(request,response); - 转发的特点:
1、转发的地址是有限制的,要求时同一个web应用。
2、转发之后,浏览器地址没有改变。
转发与重定向的区别
- 能否共享request对象
转发可以,重定向不可以
当请求到达容器,容器会创建request对象和response对象,当响应发送完毕,容器会销毁这两个对象。也就是说,request对象和response对象的生存时间是一次请求和响应期间存在的。 - 目的地是否有限制
转发有限制,重定向没有。
转发地址要求属于同一个web应用,重定向地址是任意的。 - 浏览器的地址栏的地址有无变化
转发没有,重定向有变化。 - 一件事是否已经做完
转发是一件事没有做完,让另外一个web组件继续做;而重定向是一件事已经做完,再做另外一件事。
状态管理
- 什么是状态管理
将浏览器与web服务器之间多次交互当做一个整体来处理,并且将多次交互所涉及的数据(即状态)保存下来。 - 如何进行状态管理
a、将状态保存在浏览器(Cookie)
b、将状态保存在服务端(Session)
Cookie
- 什么是Cookie
服务器临时存放在浏览器端的少量数据,用于跟踪用户的状态。 - 工作原理
当浏览器访问服务器时,服务器会将少量数据以set-cookie消息头的方式发生给浏览器,浏览器会将这些数据临时保存下来;当浏览器再次访问服务器时,会将这些数据以cookie消息头的方式发生给服务器。 - 添加Cookie
Cookie c = new Cookie(STring name,String value);
response.addCookie(c);
注:cookie只能存放字符串 - 读取COokie
Cookie[] request.getCookies();
String cookie.getName();
String cookie.getValue(); - cookie的生存时间
默认情况下,浏览器会将cookie保存在内存里。浏览器关闭,则cookie会被删除
cookie.setMaxAge(int seconds);
注:a、单位是秒
b、当seconds>0时,浏览器会将cookie保存在硬盘上,当超过指定时间,cookie会被删除。
c、当seconds<0时,浏览器会将cookie保存在内存里面。
d、当seconds=0时,浏览器会立即删除cookie。 - cookie编码问题
a、什么是cookie的编码问题:cookie只能存放合法的ASCII字符中文需要转换成合法的ASCII字符的形式才能存放。
b、如何处理
String URLEncoding.encoding(String str,String charset);
String uRLDecoder.decode(String str,String charset);
c、建议:不管是否为中文,最好统一编码处理。 - cookie的路径问题
a、什么是cookie的路径问题
浏览器访问服务器时,会比较请求地址是否与cookie的路径匹配,只有匹配的cookie才会被发送。
b、cookie的默认路径
cookie的默认路径等于添加该cookie的web组件的路径。
c、匹配规则:请求路径必须等于cookie的路径或者是其子路径,只有满足该条件的cookie才会被发送
d、修改cookie的路径:cookie.setPath(String path); - cookie可以被用户进制
a、cookie可以被用户进制
b、cookie不安全。对于敏感数据,尽量避免存放在cookie里,如果一定要存放,要加密之后再存放。
c、cookie只能存放少量的数据(约4k)
d、cookie个数有限制
e、cookie只能存放字符串
session(会话)
- 什么是session:服务器端为了保存用户状态而创建的一个特殊的对象
- session工作原理:当浏览器访问服务器时,服务器创建session对象(该对象有一个唯一的ID,以便称为sessionId),服务器会将sessionId以cookie的方式发生给浏览器,当浏览器再次访问服务器时,会将sessionID发生过来,服务器依据sessionID找到对应的session。
- 如何获得session对象:
方式一:HttPSession session = request.getSession(boolean flag);
注:HttpSession是一个接口,session对象是一个符合该接口的对象。
当flag为true时,先查看请求中有无sessionId,如果没有则创建一个session,有则依据该sessionId查找对应的session对象,如果找到了则返回该对象,如果找不到,则创建一个新的session对象。
当flag为false时,先查看请求中有没有sessionId,如果没有,返回null,如果有,依据sessionId查找对应的session,如果找到返回session,找不到返回null。
方式二:HttPSession session = request.getSession();
等价于request.getSession(true); - 常用方法:
setAttribute(String name,Object obj);
Object getAttribute(String name);//不存在返回null
removeAttribute(String name);
String getId(String name); - session超时
1、服务器会将空闲时间过长的session对象删掉。(一般是30分钟)
2、如何修改超时时间长度
方式一:修改web.xml
方式二:session.setMaxInactiveInterval(int seconds);
两次请求之间的最大间隔 - 删除session
session.invalidate(); - session验证
1、在登录成功之后绑定一些数据到session对象上
session.setAttribute("user",user);
2、当用户访问需要保护的资源时,进行session验证:
Object user = session.getAttribute("user");
if(user == null){
//没有登录
response.sendRedirect("login.jsp");
}
Cookie和Session比较
- session相对于cookie的优点:更安全,能存放更多的数据,支持更丰富的数据类型。但是session会占用服务端的内存空间,如果用户量很大,就需要占用大量的内存空间
路径问题
指的链接、表单提交、重定向和转发时,如何填写路径
- 相对路径
不以"/"开头的路径。 - 绝对路径
以"/"开头的路径。 - 如何写绝对路径
链接、表单提交、重定向从应用名开始写,转发从应用名之后开始写。
注:一定不要将应用名直接写在路径里,使用request.getContextPath()获得应用名
Servlet的生命周期
什么是Servlet的生命周期
Servlet容器如何创建Servlet对象,如何对该对象进行初始化处理、如何调用该对象的方法来处理请求、以及如何销毁该对象的整个过程。Servlet的生命周期分为哪几个阶段
1、实例化
a、什么是实例化:容器调用Servlet的构造器,创建Servlet对象。
b、什么时候实例化:
情形1:容器收到请求之后
情形2:容器启动之后,立即创建相应的实例(需要额外的配置)
<load-on-startup>1</load-on-startup>(值小的先创建)
2、初始化
a、什么是初始化
容器调用servlet对象的init方法(执行一次)
b、GenericServlet已经提供了init方法的实现
会将容器传递过来的ServletConfig对象保存下来,并且提供了getServletConfig来获得该对象。
如果要实现自己的初始化处理逻辑,只需要override GenericServlet的init方法
c、初始化参数
配置初始化参数
读取初始化参数
3、就绪
a、什么是就绪:容器调用Servlet的service方法来处理请求
b、HttpServlet已经提供了service方法的实现
该方法会依据请求类型(get/post)调用对应的doXXX方法。
doXXX方法只抛出一个异常。
开发人员只有两个选择:
override doXXX方法
override service方法
4、销毁
a、什么是销毁:容器在删除servlet对象之前,会调用该对象的destory方法(值执行一次)
b、GenericServlet已经提供了destory方法的实现。
该方法实际上什么都没有做,我们可以override该方法,来实现自己的销毁处理逻辑。
- 相关的接口与类
a、Servlet接口
init(ServerConfig config)
service(ServletRequest req, ServletResponse resp)
destory()
b、GenericServlet抽象类
实现了Servlet接口中的部分方法(init,destory)
c、HttpServlet抽象类
继承了GenericServlet,实现了service方法。
过滤器
- 过滤器是什么:Servlet规范当中定义的一种特殊的组件,用来拦截Servlet容器的调用过程。
注:Servlet容器收到容器请求之后,如果有过滤器,会先调用过滤器。 - 如何写过滤器:
1、写一个java类实现Filter接口。
2、在接口方法当中,实现拦截处理逻辑。
3、配置过滤器(web.xml)。 - 过滤器的优先级:当有多个过滤器拦截的要求,则容器会依据<filter-mapping>的先后顺序俩执行。
- 初始化参数:
监听器
- 什么是监听器:Servlet规范当中定义的一种特殊组件,用来监听容器产生的事件并进行相关的处理。
注:容器产生的事件主要分为两类,分别是
1)、生命周期相关的事件:容器创建或者销毁request、session、servlet上下文产生的事件
2)、绑定数据相关的事件:调用了request、session、servlet上下文的setAttribute和removeAttribute方法时产生的事件.
Servlet上下文
- 什么是Servlet上下文:容器启动之后,会为每一个web应用创建唯一的一个符合ServletContext接口要求的对象(即Servlet上下文),该对象会一直存在,除非容器关闭。
- 如何创建Servlet上下文:ServletConfig、FilterConfig、GenericServlet、HttPSession都提供了getServletContext方法。
- 作用:
1)绑定数据
setAttribute、getAttribute、removeAttribute
比较request、session、servlet上下文绑定数据的区别:
a、在满足使用条件的情况下,优先使用生命周期短的。(request<session<servlet上下文)
b、绑定到session对象的数据,只有与该session对应的用户能访问;而绑定到servlet上下文的数据,所有用户都能共享。
使用上下文读取全局的初始化参数
如何开发一个监听器
1、写一个java类,然后实现相应的监听接口
注:要依据监听的事件类型,选择实现相应的接口,比如,要监听session对象的创建和销毁,实现HttpSessionListener接口。
2、在接口方法中,实现监听处理逻辑。
3、配置监听器。
容器如何处理请求资源路径
- 容器默认访问的是一个Servlet,所以,会查看web.xml配置,看有没有匹配的servlet。
有三种<url-pattern>写法:
精确配置
通配符匹配:使用""匹配零个或多个任意字符
后缀匹配:使用"."开头,后接一个后缀 - 如果没有查到匹配的servlet,容器会查看相应位置的文件
如何让一个Servlet处理多种请求
1、 采用后缀匹配
2、 分析请求资源路径,进行相应的处理
Servlet的线程安全问题
- 为什么说Servlet会有线程安全问题
a、容器对于某个Servlet,只会创建一个实例。
b、容器收到一个请求,就会启动一个线程安全,由该线程来调用对应的Servlet实例的方法来处理请求。
这样,就有可能产生线程安全问题,比如多个线程去修改servlet的某个属性值。
- 如何解决:使用synchronize对有可能产生线程安全问题的代码块加锁。
使用synchronize加锁会影响性能。
Servlet小结
1、Servlet基础
2、Servlet核心
3、数据库访问
4、过滤器与监听器
5、典型案例