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), 典型案例