servlet 总结
(1), servlet 基础
1), 什么是 servlet
sun 公司制定的一种扩展 web 服务器的组件规范.
2), 如何开发 servlet
1> 写一个 java 类,继承 HttpServlet 类或者实现 servler 接口
2> 定义 service() 方法,有两个参数HttpServletRequest 的request,
HttpServletResponse 的 response.
3> 在 service()方法中实现具体的逻辑.
3), 什么是 servlet 容器
符合规范的,提供运行组件运行环境的程序.
4), http 协议()
1> 什么是 http
http 超文本传输协议,由 W3C 制定的一种网络应用层协议,它规定了浏览器和
web 服务器之间是怎么通信的,以及通信过程中的格式.
2> 如何通信
a, 浏览器将请求打包并发送,
b, 服务器响应数据包,并转发给浏览器,
一次请求,一次响应
2> 请求/响应数据包的结构
请求数据包 :
a, 请求行:请求方式 请求资源路径 协议类型和版本号(http)
b, 若干消息头
一般是由 W3C 定义的一些键值对,浏览器与服务器之间可以通过发送
这些消息头来传递一些特定的信息.
如: 浏览器可以发送 "user-agent" 消息头,告诉web服务器用户的
浏览器版本.
c, 实体内容
只有当浏览器发送 post 请求时,才会有请求数据(参数)
响应数据包 :
a, 状态行:协议类型和版本 状态码 状态描述
状态码 : 是一个三位的数字,由 W3C 定义,表示 web 服务器处理请求
的一种方式
200 : 正确
500 : 系统错误
404 : 依据请求地址找不到对应的资源
405 : service() 方法的签名是否正确.
b, 若干消息头
服务器也可发送消息头给浏览器, 如: "content-type" 消息头,告诉
浏览器服务器返回的数据类型
c, 实体内容
程序处理的结果(一般是 html 文档)
3> 两种请求方式,
1). get
> 直接输入地址,会发送 get 请求
> 点击连接后的请求是 get 请求
> 表单的 method 属性设置为 get
特点:
1. 会将请求参数添加在请求资源路径后面,只能提交少量的数据(请求行只能存放
2k 的数据)
2. 不安全(路由器会截获请求地址)
2). post
> 表单的 method 属性设置为 post
特点:
1. 会将请求参数添加到实体内容后面,可以提交大量数据
2. 相对安全一些(不管是什么请求,都不会对请求参数进行加密,
一般使用 https 协议)
4> 状态码,消息头
(2), servlet 核心
1), 如何获得请求参数值
String request.getParameter(String parameName);
String[] request.getParameterValues(String parameName);
2). 表单中有中文,如何处理
1> 要保证表单所在的页面按照指定的字符集打开
request.setCharacterEncoding("utf-8");
2> 服务器按照对应的字符集去解码
response.setContext("text/html;charset=utf-8");
3), servlet 如何输出中文
response.setContentType("text/html;charset=utf-8");
注: 指定支持中文的字符集
4), servlet 容器如何处理请求资源路径
String request.getRequestURI(String url);
5), 如何让一个servlet 处理多个请求
获取请求路径资源,通过分析请求路径资源,判断去调用那个 servlet 相关的逻辑.
uri.subString(uri.lastIndexOf("/") + 1, uri.lastIndexOf("."));
if("login".equase(uri)) {
...
} else if ("logout".equase(uri)) {
...
}
...
6), 重定向与转发
重定向:
reseponse.sendRedirect(String url);
转发:
request.setAttribute(String name, Object obj);
request.getRequestDispatcher(String url).forword(request, response);
区别:
1). 转发所涉及的 web 组件可以共享同一个请求对象,重定向不可以.
2). 重定向之后,浏览器地址栏中的地址会发生变化,而转发不变
3). 重定向地址是任意的,而转发地址必须是同一个应用
4). 转发是一件事未完成,而重定向是一件事已经完成,
7), servlet 生命周期
1> 实例化(创建)
a, 什么是实例化
容器创建 servlet 对象,
b, 什么时候实例化?
1. 容器收到请求之后,才会创建
注: 容器在默认情况下,对某个 servlet 只会创建一个
2. 容器启动之后立即创建
<load-on-startup>大于等于0的整数</load-on-startup>
优先级:值越小容器越先创建
2> 初始化
a, 什么是初始化
容器在创建好 servlet 对象之后,立即调用该队型的 init() 方法
b, 如何创建自己的初始化处理逻辑
Genericervlet 提供了 init 方法的基本实现; 将容器传递的
Servletconfig 对象保存下来,并且提供了一个 getServletConfig
来获得该对象.
只要重写 init() 方法即可
c, 访问 servlet 的初始化参数
配置: web.xml 的初始化参数
<init-param>
<param-name>company</param-name>
<param-value>tarena</param-value>
</init-param>
获取参数值
String company = config.getInitParameter("company");
init 方法只执行一次
3> 就绪
容器收到请求之后,会调用 servlet 对象的 service() 方法.
HttpServlet 的 service 方法事项过程
依据请求方式调用相应的 doXXX() 方法(若是 get 请求,调用doGet()
方法),这些 doXXX() 方法并没有完全实现,需要开发人员实现该方法
4> 销毁
容器将 servlet 对象从容器中删除,容器在删除 servlet 对象之前
会调用该对象的 destory () 方法.
destory() 方法用于释放资源,只会调用一次.
7), Servlet 接口
servlet 接口定义了三个方法,init(),destory(), service(),
GenericServlet 类实现了该接口,扩展了该接口,不过该实现类只提供了
与协议无关的方法,目地是为以后出现新的协议也可以继承它,所以
HttpServlet 类继承了该类,实现了 http 协议的方法,
8), ServletContext
ServletContext 称为 serclet 上下文,容器在启动之后会给每一个
应用创建唯一的一个符合 ServletContext 接口要求的对象,
该对象会一直存在,直到应用被卸载或容器关闭后才销毁,
1> 获取 servlet 上下文
GenericServlet,ServletConfig, FilterConfig,HttpSession
都提供了 getServletContext() 方法
2> servlet 上下文的作用
a, 绑定数据据
setAttribute(),getAttribute(),removeAttribute()
注: request,session,servletContext,都提供了绑定数据的
方法,区别如下;
1.绑定数据的生存时间不一样, request < session < ServletContext
优先使用生命周期短的对象,节省内存空间
2.访问的范围不一样,request 绑定的数据只有同一个请求所涉及的
组件(转发), session 绑定的数据只有同一个会话所涉及的组件可以访问
ServletContext 绑定的数据整个应用都可以访问.
b, 访问全局的初始化参数
指的是,该参数可以被 web.xml 文件中配置的所有组件访问
配置:
<context-param>
<param-name>add</param-name>
<param-value>BeiJing</param-value>
</context-param>
使用:
ServletContext.getInitParameter(String parameterName);
9), servlet 线程安全问题
1. servlet 容器收到请求之后,会启动一个线程来处理
2. 在默认情况下,servlet 容器只会创建一个 servlet 实例.
3. 当有多个线程同时访问某个 servlet 时,就会有可能发生线程安全
问题, 如: 同时修改 servlert 的属性时.
4. 解决 使用 synchronized 加锁
5. 也可以让 servlet 实现 SingleThreadModel(其中没有任何方法) 接口
容器会为实现了该接口的 servlet 创建多个实例. (不建议使用,因为创建
过多的实例会占用内存空间).
注: 像 Serializable 接口, 使可以序列化
(3), 状态管理
1, 什么是状态管理
将浏览器与 web 服务器之间多次交互当作一个整体来看待,并且将多次交互
所涉及的数据(即状态)保存下来.
状态管理解决两个问题:
a, 身份的识别
b, 状态的保存和维护
2, 如何进行状态管理
1), 客户端的状态管理
即将状态保存在客户端(浏览器),如 cookie
2). 服务器端的状态管理
即将状态保存在 web 服务器端, 如 session
3, cookie
1). cookie 是什么?
服务器临时保存在浏览器端的少量数据,
2). cookie 的工作原理
当浏览器访问服务器时 ,服务器会将少量数据以 set-cookie 消息头的
方式发送给浏览器,浏览器会将这些数据临时保存下来,当浏览器再次访问服务器
时会将之前保存的数据以 cookie 消息头的方式发送给服务器,
3). 如何添加 cookie
//创建 cookie 对象
Cookie c = new Cookie(String name, String value);
response.addCookie(c);
4). 查看cookie
Cookie[] cookies = request.getCookies();
注: 有可能返回 null
if(cookies.length != 0) {
for (...){
cookie.getName();
cookie.getValue();
}
}
5). cookoe 的编码问题
cookie 只能保存合法的 ascii 字符,若需要保存中文,必须把中文
转换成响应的 ascii 字符的表示形式,
String URLEncoder.encode(String str, String charset) 编码
String URLDecoder.decode(String str, String charset) 解码
建议: 在任何时候保存 cookie 时,都要用以上方法进行编码
6). cookie 的生存周期
如果添加 cooke 时没有设置 cookie 的生存周期时,则浏览器会将 cookie
保存在内存里,只要浏览器不关闭,若浏览器关闭, 则 cookie 会被删除,
设置 cookie 的生存周期
cookie.setMaxAge(int seconds);
注: 单位为秒,而非毫秒
seconds 的值
大于 0 :浏览器会将 cookie 保存在硬盘,关闭浏览器也存在,当超过指定的时间
浏览器会删除 cookie
等于 0 :删除 cookie
例: 删除一个叫 "uid" 的 cookie
Cookie c = new Cookie("uid","...");
c.setMaxAge(0);
response.add(c);
小于 0 :缺省值
7). cookie 的路径问题
浏览器向服务器上的某个地址发送和请求时,会比较要访问的地址是否与
cookie 的地址(即路径)匹配,只有匹配的 cookie 才会发送.
1> cookie 的默认路径]
添加该 cookie 的组件的路径
例: "web06/abc/" 下的 addcookie.jsp 添加了一个 cookie ,则
cookie 的默认路径为 "/web06/abc/"
2> 匹配规则
要访问的路径必须是 cookie 的路径或者是 cookie 的子路经,cookie
才会被发送.
3> 设置 cookie 的路径
cookie.setPath(String path);
例: cookie.setPath("/web06");
注: 在添加 cookie 时
Cookie c = new Cookie(String name, String value);
value需要编码
c.setMaxAge(); //设置生存周期
c.setPath(); //设置 cookie 路径
response.addCookie(c);
8). cookie 的限制
> 不安全,如果有敏感数据必须进行加密,
> 可以被用户禁止.
> cookie 只能保存少量的数据(4k)
> 能够保存 cookie 的数量有限制(300个左右)
> 只能保存字符串
9). cookie 相关的 API
//创建 cookie
Cookie c = new Cookie(String name, String value);
//处理 cookie 的编码问题
URLEncoder.encode()--编码
URLDecoder,decode()--解码
//设置 cookie 的生存周期
c.setMaxAge(int second);
//设置 cookie 的路径
c.setPath(String url);
//添加 cookie
response.addCookie(c);
//获取 cookie 的名称
cookie.getName();
// 获取 cookie 的值
cookie.getValue();
4, session
1). session 是什么?
服务器为客户端创建的一个用来维护状态的对象.
2). session 的工作原理
浏览器访问服务器时 ,服务器创建一个 session 对象,该对象有一个唯一的
id (sessionId)号,服务器会将 sessionId 以 cookie 的方式发送给浏览器
当浏览器再次访问服务器时,会将 seesionId 发送给服务器,服务器可以根据
sessionID 找到之前创建的 seesion 对象.
3). 如何获得 session 对象
1> HttpSession hs = request.getSession(boolean flag);
当 flag = true
查看请求当中是否有 sessionId , 如果没有,则创建 session 对象.
如果有,则根据 sessionId 查找 session 对象,(有可能找不到, session
超时,服务器内存不够会删除长时间不用的 session 对象),若找不到会重新创建
session 对象
当 flag = false
查看请求中是否有 sessionId ,如果没有,则返回 null; 如果有,则
根据 sessionId 查找 session 对象,如果找不到,则返回 null;
不会创建新的 session 对象
2> HttpSession hs = request.getSession();
等价于 request.getSession(true);
4). 绑定数据相关的几个方法
// 绑定数据到 session 对象上
setAttribute(String name, Object value);
// 根据绑定数据的名字,获取绑定数据的值
Object getAttribute(String name);
// 解除绑定
removeAttribute(String name); // 解除绑定
5). session 超时
服务器将空闲时间过长的 session 对象删除掉,原因节省资源,通常服务器的
缺省超时限制为 30 分钟.
1> 修改服务器缺省的超时限制
可以修改 tomcat 的配置文件
conf/web.xml
<session-config>
<session-timeout>30</session-timeout>
</session-config>
注: 该配置对所有部署在 tomcat 服务器上的应用有效.
也可以将该配置添加在某个应用的 web.xml 文件中,只针对于该应用有效.
2> session.setMaxInactiveInterval(35);
3> 删除 session
session.invalidate();
5), Session 相关的 API
//创建 session
HttpSession session = request.getSession(boolean flag);
HttpSession session = request.getSession();
//绑定数据到 session 上
setAttribute(String name, Object obj),
// 获取绑定在 session 上的数据
getAttribute(String name),
// 移除绑定在 session 上的数据
removeAttribute(),
// 设置 session 的生命周期时间 (通常为 30 分钟)
session.setMaxInactiveInterval(int second);
// 销毁 session
session.incvalidate()
// URl 重写(主要使用在用户禁止客户端的 cookie 时)
response.encodeURL() //用于连接地址和表单提交地址
response.encodeRedirectURL() //用于重定向地址
(4), 数据库访问
使用 JDBC 连接数据库,常用 dbcp 或 c3p0 连接池技术,在此不做详细使用步骤.
(5), 过滤器和监听器
1, Filter (过滤器)
1), 什么是过滤器?
Servlet 规范中定义的一种特殊的组件,用来拦截容器的调用过程,
并做出响应的处理.
2), 如何写一个拦截器
1> 新建一个 java 类,让其实现 Filter 接口,
2> 重写 Filter 接口的放法, 在 doFilter() 方法处理拦截器的
具体逻辑.
3> 在 web.xml 文件中配置器
3), Filter 的工作原理及生命周期
1> 在容器启动时,容器会自动调用 Filter 的 init() 方法,初始化
Filter.只调用一次.
2> 容器会按照 wen.xml 文件中的配置,调用 doFilter() 方法处理
具体的拦截逻辑,若通过该拦截器,容器调用下一个拦截器的 doFilter()
方法,若不能通过拦截器,则会按照逻辑提示用户.直到将所有的拦截器
执行通过后,容器才会去调用 servlet 的 service() 方法.
3> 当容器关闭时,容器会调用 Filter 的 destory() 方法,销毁拦截器
到此,拦截器生命结束.
4> init() 方法,有一个 FilterConfig 的参数,可以用来读取初始化参数
我们可以给 Filter 增加一个属性 FilterConfig 类型的 config,
在容器调用 init() 方法时给其赋值,然后就可以用它来获取在 web.xml
文件中配置的初始化参数了.具体代码如下:
配置:
<!-- 配置初始化参数 -->
<init-param>
<param-name>size</param-name>
<param-value>5</param-value>
</init-param>
使用:
String FilterConfig.getInitParameter(String paramName);
5> doFilter() 方法,定义了三个参数,分别是 ServletRequest 的 request
ServletResponse 的 response 和,FilterChain 的 chain.
在使用时需要注意的是,ServletRequest 和 ServletResponse 接口 是
无关协议的,所以必须进行一次强转,
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
FilterChain 是一个 Fliter 链,它调用 doFilter() 方法,其实是调用
下一个 Filter 的 doFilter() 方法,调用的顺序是按照在 web.xml 文件
中 <filter-mapping> 的配置顺序依次调用的,直到通过了所有的拦截器,才去
调用 servlet.
2, Listener(监听器)
1). 什么是监听器?
servlet 规范中制定的另一种特殊的组件,用来监听 servlet 容器中发生的
事件处理.
监听的事件主要有两大类:
1, 生命周期相关的事件,request,session,ServletContext,的创建和
销毁的事件.
2, 绑定数据相关的事件,request,session,ServletContext,绑定数据时
的 setAttribute() 和 getAttribute() 方法.
2). 如何写一个监听器
1> 新建一个 java 类,根据要监听事件的类型,实现响应的接口,比如: 要监听
session 的创建与销毁,就实现 HttpSessionListener 接口.
2> 重写接口的方法,并处理响应的监听逻辑
3> 在 web.xml 文件中配置监听器.
3), 统计在线人数(利用监听器实现)
(6), 典型案例