Servlet学习总结
1、Servlet是一种独立于平台和协议的服务器端的Java应用程序,能够生成动态的Java Web页面。Web浏览器或HTTP客户程序请求和HTTP服务器上的数据库或应用程序之间的中间层,Servlet是由Web服务器加载的,Web服务器必须包含支持Servlet的Java虚拟机。运行于使用Java技术的WebServer中,采用“请求-响应”模式。
Applet与Servlet都不是独立的应用程序,没有main()方法,有另外一个应用程序(容器)调用,有一个生命周期
(创建Servlet实例
Web容器调用Servlet的init()方法、初始化
Servlet存在容器中、响应客户端请求、get-doGet()方法、post-doPost()方法、统一使用service()方法
销毁Servlet
先调用destroy()方法、在关闭Web应用时销毁Servlet)
包含init() destroy()。
JSP的本质就是Servlet,Servlet是一个服务器端小程序,处理并响应客户端的请求,Servlet是一个特殊的Java类,Java类必须继承HttpServlet。doGet() doPost() doPut() doDelete(),客户端的请求:get post。
JavaEE 容器:实现了所有JavaEE规范的容器;
WEB容器:只实现了Servlet、JSP
Servlet = Server + Applet
Servlet:Client-known URL name/Deployer-known secret internal name/Actual file name
the Folder of the Web Server:
Web Xml
<servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>com.cp.servlet.Hello</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>hello.do</url-pattern>
</servlet-mapping>
cmd tomcat6\bin\startup shutdown//启动和关闭tomcat
javac –classpath .;C:\tomcat6\lib\servlet-api.jar Hello.java
javac –classpath .;C:\tomcat6\lib\servlet-api.jar Hello.java –d .生成class文件
2、Servlet 架构
Servlet 任务
Servlet 执行以下主要任务:
读取客户端(浏览器)发送的显式的数据。这包括网页上的HTML表单,或者也可以是来自 applet 或自定义的 HTTP 客户端程序的表单。
读取客户端(浏览器)发送的隐式的 HTTP 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
处理数据并生成结果。这个过程可能需要访问数据库,执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置cookies和缓存参数,以及其他类似的任务。
Servlet 生命周期
Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:
Servlet通过调用 init () 方法进行初始化。
Servlet调用 service() 方法来处理客户端的请求。
Servlet通过调用 destroy() 方法终止(结束)。
最后,Servlet是由JVM的垃圾回收器进行垃圾回收的。
init()方法
init方法被设计成只调用一次。它在第一次创建Servlet时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像Applet的init 方法一样。
Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但也可以指定 Servlet 在服务器第一次启动时被加载。
当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。
service() 方法
service()方法是执行实际任务的主要方法。Servlet容器(即 Web 服务器)调用service()方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service()方法检查HTTP请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。
doGet() 方法
GET 请求来自于一个URL的正常请求,或者来自于一个未指定METHOD的 HTML表单,它由doGet()方法处理。
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
doPost()方法
POST 请求来自于一个特别指定了METHOD为POST的HTML表单,它由 doPost() 方法处理。
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
destroy() 方法
}destroy()方法只会被调用一次,在Servlet生命周期结束时被调用。destroy()方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。
在调用destroy()方法之后,servlet对象被标记为垃圾回收。destroy方法定义如下所示:
public void destroy() {
// 终止化代码...
架构图
第一个到达服务器的 HTTP 请求被委派到 Servlet容器。
Servlet容器在调用 service()方法之前加载 Servlet。
然后 Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的Servlet实例的 service()方法。
3、Servlet 表单数据
GET方法
GET方法向页面请求发送已编码的用户信息。页面和已编码的信息中间用 ? 字符分隔,如下所示:
GET方法是默认的从浏览器向 Web 服务器传递信息的方法,它会产生一个很长的字符串,出现在浏览器的地址栏中。如果您要向服务器传递的是密码或其他的敏感信息,请不要使用 GET方法。GET方法有大小限制:请求字符串中最多只能有 1024 个字符。
这些信息使用 QUERY_STRING 头传递,并可以通过 QUERY_STRING 环境变量访问,Servlet 使用 doGet() 方法处理这种类型的请求。
POST方法
另一个向后台程序传递信息的比较可靠的方法是 POST方法。
POST 方法打包信息的方式与GET方法基本相同,但是 POST方法不是把信息作为 URL 中 ? 字符后的文本字符串进行发送,而是把这些信息作为一个单独的消息。消息以标准输出的形式传到后台程序,您可以解析和使用这些标准输出。
Servlet使用doPost()方法处理这种类型的请求。
4、使用Servlet读取表单数据
Servlet 处理表单数据,这些数据会根据不同的情况使用不同的方法自动解析:
getParameter():可以调用 request.getParameter() 方法来获取表单参数的值。
getParameterValues():如果参数出现一次以上,则调用该方法,并返回多个值,例如复选框。
getParameterNames():如果您想要得到当前请求中的所有参数的完整列表,则调用该方法。
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="utf-8"/>
//解决Post提交方式中的中文乱码request.setCharacterEncoding("utf-8");
从客户端获取信息(数据):
String username = request.getParmeter(“username”);
//参数要与form表单中的name属性值保持一致
String password = request.getParmeter(“password”);
String [] likes = request.getParameterValues(“like”);//集合
5、容器环境的搭建,Servlet的编写,Servlet生命周期
class ServletInfo{//抽取类、封装,记录Servlet有关信息
private String servletName;
private String className;
private String urlPattern;
}
class ServletContext {//存储Servlet有关信息、数据结构、Map结构xml解析
private Map<String,ServletInfo> m = new HashMap...;
public void parse(){
for(){
ServletInfo sf = new ServletInfo();
m.put(urlPattern,sf);//urlPattern唯一标识,不同
}
}
}
class MyServer {//服务器端
main(){
ServeltContext sc = new ServletC...;
sc.parse(); //存储ServletInfo
ServerSocket ss = new ServerSocket(8080);//监听端口
while(true){
Socket skt = ss.accept();
new A(skt,sc).start();//启动线程
}
}
}
class A extends Thread {
private Socket skt;
private ServletContext sc;
public A(Socket skt,ServletContext sc){
this.skt=skt;
this.sc = sc;
}
public void run(){
try{
InputStream is = skt.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//GET hello.do HTTP/1.1
String str = br.readLine().split(" ")[0];
if(str.endWith(".html") || str.endsWith(".js") || str.endsWith(".css") || ...){
// IO
} else {
// 动态资源
ServletInfo sf = sc.getMap().get(str);
if(sf = = null){
// 404
} else {
// com.softeem.web.servlet.Hello
String s = sf.getClassName;
HttpServlet o = (HttpServlet)Class.forName(s).newInstance();
ServltRequest request = new ServletRequest(skt.getInputStream());
ServletResponse response = new ServletResponse(skt.getOutptutStream());
o.service(request,response);
}
}
}catch(e){
}
}
}
创建类的方法:
new:Hello hello = new Hello();
三步:
1、加载类到内存
2、静态资源初始化
3、堆区构建对象、栈区创建引用
Class.forName("oracle.jdbc.OracleDriver").newInstance();
public inferface Servlet {//接口,规范、标准,定义基本方法
public void init();
public void service(ServletRequest requser,ServletRespone response);
public void destroy();
}
--------------------------------------------------------
//容器厂商实现接口
public abstract class GenericServlet implements Servlet {//抽象类
public void init();
public void service(ServletRequest requser,ServletRespone response);
public void destroy();
}
public abstract class HttpServlet extends GenericServlet {//抽象类
public void init(){
}
public void service(ServletRequest requser,ServletRespone response){
//GET
doGet();
//post
doPost();
}
public void destroy(){
}
public void doGet(......){
// 405
}
public void doPost(......)[
//405
}
}
-----------------------------------------------------------
开发人员编程,继承HttpServlet类
public class A extends HttpServlet {
doGet(HttpServletRequest req,HttpServletResponse resp){
}
doPost(){
}
}
6、得到头部信息
Enumeration<String> names = request.getHeaderNames();
request.getHeader("key");
String method = request.getMethod();
String uri = request.getRequestURI();
String prot = request.getProtocol();
get Data from Request:
request.getParameter("key")
request.getParameterValues("key")
request.getQueryString()
request.getParameterMap()
Response Type:
Character Type Byte Stream Type
Get Stream:
response.getWriter()字符流
response.getOutputStream()字节流 文件下载
mime类型:tomact\conf\web.xml中查询
ServletContext:(初始化成功后、项目才能正常进行、启动Web容器时就要构建)
lobal container全局容器、上下文对象/Change relative path to the absolute path/Reading init parameter(what difference between ServletConfig and ServletContext's reading init parameter)/Read the container's information
context.setAttribute("key","value");//存放信息、生命周期
context.getAttribute("key");//得到信息
<load-on-startup>1<load-on-startup> 整型值越小、Servlet就越优先实例化。
7、Redirect跳转
转发(服务器内部资源的跳转、一次请求、一次响应、可以转发对象、地址栏不发生改变)
重定向(两次请求、两次响应、地址栏发生改变)
不能同时出现response.sendRedirect("..."),否则出现IllegalStateException 状态非法异常,其他情况也可能出现
重定向请求到另一个网页的最简单的方式是使用 response 对象的 sendRedirect() 方法。下面是该方法的定义: 将请求重定向到另一页的最简单的方法是,用方法的sendRedirect()的响应对象。
以下是这种方法的定义:
public void HttpServletResponse.sendRedirect(String location)throws IOException
状态码:
200-299:服务器成功响应,而且客户端看到结果
300-399:服务器上的资源位置有变化
400-499:服务器上的资源不存在
500-599:服务器上的程序有问题
Servlet HTTP状态码
HTTP请求和HTTP响应消息的格式是类似的,结构如下:
初始状态行 + 回车换行符(回车+换行)
零个或多个标题行+回车换行符
一个空白行,即回车换行符
一个可选的消息主体,比如文件、查询数据或查询输出
状态行包括 HTTP 版本、一个状态码和一个对应于状态码的短消息
二叉树的深度优先遍历与广度优先遍历
二叉树的遍历:D:访问根节点,L:遍历根节点的左子树,R:遍历根节点的右子树。给定一棵二叉树的前序遍历序列和中序遍历序列可以唯一确定一棵二叉树。
二叉树的深度优先遍历的非递归的通用做法是采用栈、广度优先遍历的非递归的通用做法是采用队列。
Servlet会话跟踪技术
Web中会话是指在客户端和HTTP之间通过接口HttpSession实现关联,可以维持指定的时间,也可以跨越多个连接或用户界面请求。一个Session只负责与一个用户通信,并存储有关信息。
HTTP:单向性 无状态
Cookie存储客户端的信息、少量信息、上网、登陆邮箱网站、微博等产生的cookie
Session存储服务器端的信息、购物车中用到了session、有生命周期、(tomcat)默认30分钟
<session-config><time-out>30</time-out></session-config>
一个客户端浏览器使用同一个session对象。
HttpSession session = request.getSession(true=不填|false);//两者的区别
session.setAttribute("key",Object);//值可以为对象
session.getAttribute("key");
class Cookie {
private String name;
private String value;
public Cookie (String name,String value){
this.name = name;
this.value=value;
}
getName();
getValue();
}
class HttpSessionImple implements HttpSession {
Map<String,Object> map = new HashMap()...;//put() get()方法
public void setArrtibute(String key,Object obj){
map.put(key,obj);
}
public Object getAttribute(String key){
return map.get(key);
}
}
class HttpServletRequestImpl implements HttpServletRequest {
public Cookie[] getCookies(){
}
public HttpSession getSession(){
Cookie[] cs = this.getCookies();//得到一个数组
Cookie cc = null;
for(Cookie c : cs){
if("sessionId".equals(c.getName())){
cc = c;
break;
}
}
}
if(cc!= null){
String value = cc.getValue();
return ServeltContext.getAtrritbute(value);//得到一个ServletSessin对象
} else {
String sessionId = generateSessionId();// uuid
HttpSession s = new HttpSessionImpl();
ServletContext.setAtrribute(sessionId,s);
Cookis cookie = new Cookie("sessionId",sessionId);
response.addCookies(cookie);//添加Cookie对象
return s;
}
}
http://blog.****.net/hejingyuan6/article/details/30273879
http://blog.****.net/cike110120/article/details/8266959
Servlet实例
编写Hello.java文件(就是一个servlet程序),放在D:\Program Files (x86)\Java\tomcat7\webapps\ROOT下(<Tomcat-installation-directory>),进行编译,生成Hello.class文件。
把Hello.class放在D:\Program Files (x86)\Java\tomcat7\webapps\ROOT\WEB-INF\classes目录下,
并在D:\Program Files (x86)\Java\tomcat7\webapps\ROOT\WEB-INF\web.xml中进行设置
<servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>Hello</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/Hello</url-pattern>
</servlet-mapping>
Servlet 编写过滤器启动tomcat,然后再浏览器地址栏输入http://localhost:8080/Hello,就可以访问了,效果如下:
Servlet过滤器是可用于Servlet编程的Java类,有以下目的:
在客户端的请求访问后端资源之前,拦截这些请求。
在服务器的响应发送回客户端之前,处理这些响应。
根据规范建议的各种类型的过滤器:
身份验证过滤器(Authentication Filters)。
数据压缩过滤器(Data compression Filters)。
加密过滤器(Encryption Filters)。
触发资源访问事件过滤器。
图像转换过滤器(Image Conversion Filters)。
日志记录和审核过滤器(Logging and Auditing Filters)。
MIME-TYPE 链过滤器(MIME-TYPE Chain Filters)。
标记化过滤器(Tokenizing Filters)。
XSL/T 过滤器(XSL/T Filters),转换 XML 内容。
过滤器被部署在部署描述符文件 web.xml 中,然后映射到您的应用程序的部署描述符中的Servlet名称或URL模式
Servlet 异常处理
当一个 Servlet 抛出一个异常时,Web 容器在使用了 exception-type 元素的 web.xml 中搜索与抛出异常类型相匹配的配置。必须在 web.xml 中使用 error-page 元素来指定对特定异常 或 HTTP 状态码 作出相应的 Servlet 调用。
Servlet Cookies处理
Cookies是存储在客户端计算机上的文本文件,并保留了各种跟踪信息。Java Servlet 显然支持 HTTP Cookies。
识别返回用户包括三个步骤:
服务器脚本向浏览器发送一组 Cookies。例如:姓名、年龄或识别号码等。
浏览器将这些信息存储在本地计算机上,以备将来使用。
当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookies 信息发送到服务器,服务器将使用这些信息来识别用户。
通过 Servlet 设置 Cookies
通过 Servlet 设置 Cookies 包括三个步骤:
通过 Servlet 删除 Cookies
(1)创建一个 Cookie 对象:您可以调用带有 cookie 名称和 cookie 值的 Cookie 构造函数,cookie 名称和 cookie 值都是字符串。
Cookie cookie = new Cookie("key","value");
请记住,无论是名字还是值,都不应该包含空格或以下任何字符:
[ ] ( ) = , " / ? @ : ;
(2)设置最大生存周期:您可以使用 setMaxAge 方法来指定 cookie 能够保持有效的时间(以秒为单位)。下面将设置一个最长有效期为 24 小时的 cookie。
cookie.setMaxAge(60*60*24);
(3)发送 Cookie 到 HTTP 响应头:您可以使用 response.addCookie 来添加 HTTP 响应头中的 Cookies,如下所示:
response.addCookie(cookie);
删除 Cookies 是非常简单的。如果您想删除一个 cookie,那么您只需要按照以下三个步骤进行:
读取一个现有的 cookie,并把它存储在 Cookie 对象中。
使用 setMaxAge() 方法设置 cookie 的年龄为零,来删除现有的 cookie。
把这个 cookie 添加到响应头。
Servlet Session 跟踪
HTTP 是一种"无状态"协议,这意味着每次客户端检索网页时,客户端打开一个单独的连接到 Web 服务器,服务器会自动不保留之前客户端请求的任何记录。
删除 Session 会话数据
当完成了一个用户的 session 会话数据,您有以下几种选择:
移除一个特定的属性:您可以调用 public void removeAttribute(String name) 方法来删除与特定的键相关联的值。 to delete the value associated with a particular key.
删除整个 session 会话:您可以调用 public void invalidate() 方法来丢弃整个 session 会话。
设置session 会话过期时间:您可以调用 public void setMaxInactiveInterval(int interval) 方法来单独设置 session 会话超时。
注销用户:如果使用的是支持 servlet 2.4 的服务器,您可以调用 logout 来注销 Web 服务器的客户端,并把属于所有用户的所有 session 会话设置为无效。
web.xml 配置:如果您使用的是 Tomcat,除了上述方法,您还可以在 web.xml 文件中配置 session 会话超时
Servlet 国际化
国际化(i18n):这意味着一个网站提供了不同版本的翻译成访问者的语言或国籍的内容。
本地化(l10n):这意味着向网站添加资源,以使其适应特定的地理或文化区域,例如网站翻译成印地文(Hindi)。
区域设置(locale):这是一个特殊的文化或地理区域。它通常指语言符号后跟一个下划线和一个国家符号。例如 "en_US" 表示针对 US 的英语区域设置。
// 获取客户端的区域设置
Locale locale = request.getLocale();
String language = locale.getLanguage();
String country = locale.getCountry();