Servlet运行在Servlet容器中,其生命周期由容器来管理。Servlet的生命周期通过javax.servlet.Servlet接口中的init()、service()和destroy()方法来表示
Servlet的生命周期包含了下面4个阶段:
1.加载和实例化
2.初始化
3.请求处理
4.服务终止
Web服务器在与客户端交互时Servlet的工作过程是:
1. 在客户端对web服务器发出请求
2. web服务器接收到请求后将其发送给Servlet
3. Servlet容器为此产生一个实例对象并调用ServletAPI中相应的方法来对客户端HTTP请求进行处理,然后将处理的响应结果返回给WEB服务器.
4. web服务器将从Servlet实例对象中收到的响应结构发送回客户端.
servlet的生命周期:
1.加载和实例化
Servlet容器负责加载和实例化Servlet。当Servlet容器启动时,或者在容器检测到需要这个Servlet来响应第一个请求时,创建Servlet实例。当Servlet容器
启动后,它必须要知道所需的Servlet类在什么位置,Servlet容器可以从本地文件系统、远程文件系统或者其他的网络服务中通过类加载器加载Servlet类,
成功加载后,容器创建Servlet的实例。因为容器是通过Java的反射API来创建Servlet实例,调用的是Servlet的默认构造方法(即不带参数的构造方法),所
以我们在编写Servlet类的时候,不应该提供带参数的构造方法。
2.初始化
在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象。初始化的目的是为了让Servlet对象在处理客户端请求前完成一些初始化的工作,
如建立数据库的连接,获取配置信息等。对于每一个Servlet实例,init()方法只被调用一次。在初始化期间,Servlet实例可以使用容器为它准备的
ServletConfig对象从Web应用程序的配置信息(在web.xml中配置)中获取初始化的参数信息。在初始化期间,如果发生错误,Servlet实例可以抛出
ServletException异常或者UnavailableException异常来通知容器。ServletException异常用于指明一般的初始化失败,例如没有找到初始化参数;而
UnavailableException异常用于通知容器该Servlet实例不可用。例如,数据库服务器没有启动,数据库连接无法建立,Servlet就可以抛出
UnavailableException异常向容器指出它暂时或永久不可用。
I.如何配置Servlet的初始化参数?
在web.xml中该Servlet的定义标记中,比如:
配置了两个初始化参数user和blog它们的值分别为username和http://。。。, 这样以后要修改用户名和博客的地址不需要修改Servlet代码,只需修改配置文件即可。
II.如何读取Servlet的初始化参数?
ServletConfig中定义了如下的方法用来读取初始化参数的信息:
public String getInitParameter(String name)
参数:初始化参数的名称。
返回:初始化参数的值,如果没有配置,返回null。
III.init(ServletConfig)方法执行次数
在Servlet的生命周期中,该方法执行一次。
IV.init(ServletConfig)方法与线程
该方法执行在单线程的环境下,因此开发者不用考虑线程安全的问题。
V.init(ServletConfig)方法与异常
该方法在执行过程中可以抛出ServletException来通知Web服务器Servlet实例初始化失败。一旦ServletException抛出,Web服务器不会将客户端请求交给该Servlet实例来处理,而是报告初始化失败异常信息给客户端,该Servlet实例将被从内存中销毁。如果在来新的请求,Web服务器会创建新的Servlet实例,并执行新实例的初始化操作
3.请求处理
Servlet容器调用Servlet的service()方法对请求进行处理。要注意的是,在service()方法调用之前,init()方法必须成功执行。在service()方法中,
Servlet实例通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息。在service
()方法执行期间,如果发生错误,Servlet实例可以抛出ServletException异常或者UnavailableException异常。如果UnavailableException异常指示了该实
例永久不可用,Servlet容器将调用实例的destroy()方法,释放该实例。此后对该实例的任何请求,都将收到容器发送的HTTP 404(请求的资源不可用)响应
。如果UnavailableException异常指示了该实例暂时不可用,那么在暂时不可用的时间段内,对该实例的任何请求,都将收到容器发送的HTTP 503(服务器暂
时忙,不能处理请求)响应。
I. service()方法的职责
service()方法为Servlet的核心方法,客户端的业务逻辑应该在该方法内执行,典型的服务方法的开发流程为:
解析客户端请求-〉执行业务逻辑-〉输出响应页面到客户端
II.service()方法与线程
为了提高效率,Servlet规范要求一个Servlet实例必须能够同时服务于多个客户端请求,即service()方法运行在多线程的环境下,Servlet开发者必须保证该方法的线程安全性。
III.service()方法与异常
service()方法在执行的过程中可以抛出ServletException和IOException。其中ServletException可以在处理客户端请求的过程中抛出,比如请求的资源不可用、数据库不可用等。一旦该异常抛出,容器必须回收请求对象,并报告客户端该异常信息。IOException表示输入输出的错误,编程者不必关心该异常,直接由容器报告给客户端即可。
编程注意事项说明:
1) 当Server Thread线程执行Servlet实例的init()方法时,所有的Client Service Thread线程都不能执行该实例的service()方法,更没有线程能够执行该实例的destroy()方法,因此Servlet的init()方法是工作在单线程的环境下,开发者不必考虑任何线程安全的问题。
2) 当服务器接收到来自客户端的多个请求时,服务器会在单独的Client Service Thread线程中执行Servlet实例的service()方法服务于每个客户端。此时会有多个线程同时执行同一个Servlet实例的service()方法,因此必须考虑线程安全的问题。
3) 请大家注意,虽然service()方法运行在多线程的环境下,并不一定要同步该方法。而是要看这个方法在执行过程中访问的资源类型及对资源的访问方式。分析如下:
i. 如果service()方法没有访问Servlet的成员变量也没有访问全局的资源比如静态变量、文件、数据库连接等,而是只使用了当前线程自己的资源,比如非指向全局资源的临时变量、request和response对象等。该方法本身就是线程安全的,不必进行任何的同步控制。
ii. 如果service()方法访问了Servlet的成员变量,但是对该变量的操作是只读操作,该方法本身就是线程安全的,不必进行任何的同步控制。
iii. 如果service()方法访问了Servlet的成员变量,并且对该变量的操作既有读又有写,通常需要加上同步控制语句。
iv. 如果service()方法访问了全局的静态变量,如果同一时刻系统中也可能有其它线程访问该静态变量,如果既有读也有写的操作,通常需要加上同步控制语句。
v. 如果service()方法访问了全局的资源,比如文件、数据库连接等,通常需要加上同步控制语句。
4.服务终止
当容器检测到一个Servlet实例应该从服务中被移除的时候,容器就会调用实例的destroy()方法,以便让该实例可以释放它所使用的资源,保存数据到持久存
储设备中。当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例
随后会被Java的垃圾收集器所回收。如果再次需要这个Servlet处理请求,Servlet容器会创建一个新的Servlet实例。
在整个Servlet的生命周期过程中,创建Servlet实例、调用实例的init()和destroy()方法都只进行一次,当初始化完成后,Servlet容器会将该实例保存在内存中,通过调用它的service()方法,为接收到的请求服务。
5.异步Servlet
再Servlet3.0中开始支持异步处理方式。
Servlet 3.0 之前,一个普通 Servlet 的主要工作流程大致如下:
(1)首先,Servlet 接收到请求之后,可能需要对请求携带的数据进行一些预处理;
(2)接着,调用业务接口的某些方法,以完成业务处理;
(3)最后,根据处理的结果提交响应,Servlet 线程结束。
其中第二步的业务处理通常是最耗时的,这主要体现在数据库操作,以及其它的跨网络调用等,在此过程中,Servlet 线程一直处于阻塞状态,直到业务方法执行完毕。
在处理业务的过程中,Servlet 资源一直被占用而得不到释放,对于并发较大的应用,这有可能造成性能的瓶颈。对此,在以前通常是采用私有解决方案来提前结束 Servlet 线程,并及时释放资源。
Servlet 3.0 针对这个问题做了开创性的工作,现在通过使用 Servlet 3.0 的异步处理支持,之前的 Servlet 处理流程可以调整为如下的过程:
首先,Servlet 接收到请求之后,可能首先需要对请求携带的数据进行一些预处理;
接着,Servlet 线程将请求转交给一个异步线程来执行业务处理,线程本身返回至容器,此时 Servlet 还没有生成响应数据,异步线程处理完业务以后,可以直接生成响应数据(异步线程拥有 ServletRequest 和 ServletResponse 对象的引用),或者将请求继续转发给其它 Servlet。
如此一来, Servlet 线程不再是一直处于阻塞状态以等待业务逻辑的处理,而是启动异步线程之后可以立即返回。
开启功能:
异步处理特性可以应用于 Servlet 和过滤器两种组件,由于异步处理的工作模式和普通工作模式在实现上有着本质的区别,因此默认情况下,Servlet 和过滤器并没有开启异步处理特性,如果希望使用该特性,则必须按照如下的方式启用:
1、对于使用传统的部署描述文件 (web.xml) 配置 Servlet 和过滤器的情况,Servlet 3.0 为 和 标签增加了 子标签,该标签的默认取值为 false,要启用异步处理支持,则将其设为 true 即可。以 Servlet 为例,其配置方式如下所示:
1. <servlet>
2. <servlet-name>DemoServlet</servlet-name>
3. <servlet-class>footmark.servlet.Demo Servlet</servlet-class>
4. <async-supported>true</async-supported>
5. </servlet>
2、对于使用 Servlet 3.0 提供的 @WebServlet 和 @WebFilter 进行 Servlet 或过滤器配置的情况,这两个注解都提供了 asyncSupported 属性,默认该属性的取值为 false,要启用异步处理支持,只需将该属性设置为 true 即可。以 @WebFilter 为例,其配置方式如下所示:
1. @WebFilter(urlPatterns = "/demo",asyncSupported = true)
2. public class DemoFilter implements Filter{...}
一个简单的模拟异步处理的 Servlet 示例如下:
1. @WebServlet(urlPatterns = "/demo", asyncSupported = true)
2. public class AsyncDemoServlet extends HttpServlet {
3. @Override
4. public void doGet(HttpServletRequest req, HttpServletResponse resp)
5. throws IOException, ServletException {
6. resp.setContentType("text/html;charset=UTF-8");
7. PrintWriter out = resp.getWriter();
8. out.println("进入Servlet的时间:" + new Date() + ".");
9. out.flush();
10.
11. //在子线程中执行业务调用,并由其负责输出响应,主线程退出
12. AsyncContext ctx = req.startAsync();
13. new Thread(new Executor(ctx)).start();
14.
15. out.println("结束Servlet的时间:" + new Date() + ".");
16. out.flush();
17. }
18. }
19.
20. public class Executor implements Runnable {
21. private AsyncContext ctx = null;
22. public Executor(AsyncContext ctx){
23. this.ctx = ctx;
24. }
25.
26. public void run(){
27. try {
28. //等待十秒钟,以模拟业务方法的执行
29. Thread.sleep(10000);
30. PrintWriter out = ctx.getResponse().getWriter();
31. out.println("业务处理完毕的时间:" + new Date() + ".");
32. out.flush();
33. ctx.complete();
34. } catch (Exception e) {
35. e.printStackTrace();
36. }
37. }
38. }
Servlet 3.0 还为异步处理提供了一个监听器,使用
AsyncListener 接口表示。它可以监控如下四种事件:
1. 异步线程开始时,调用 AsyncListener 的 onStartAsync(AsyncEvent event) 方法;
2. 异步线程出错时,调用 AsyncListener 的 onError(AsyncEvent event) 方法;
3. 异步线程执行超时,则调用 AsyncListener 的 onTimeout(AsyncEvent event) 方法;
4. 异步执行完毕时,调用 AsyncListener 的 onComplete(AsyncEvent event) 方法;
要注册一个AsyncListener,只需将准备好的 AsyncListener 对象传递给 AsyncContext 对象的 addListener() 方法即可,如下所示:
1. AsyncContext ctx = req.startAsync();
2. ctx.addListener(new AsyncListener() {
3. public void onComplete(AsyncEvent asyncEvent) throws IOException {
4. // 做一些清理工作或者其他
5. }
6. ...
7. });
1 .首先,什么是Servlet?
Servlet是一个Java编写的程序,此程序是在服务器端运行的,是按照Servlet规范编写的一个Java类。 2.Servlet是做什么的? Servlet是处理客户端的请求并将其发送到客户端。 3.Servlet API
1>Servlet框架的组成 Servlet框架是由2个Java包组成:(1)javax.servlet和(2)javax.servlet.http
(1)javax.servlet包中定义了所有Servlet类都必须实现的接口和类。 javax.servlet包的接口为: ServletConfig接口 —— 在初始化过程中由Servlet容器使用 ServletContext接口 —— 定义Servlet用于获取容器信息的方法 ServletRequest接口 —— 向服务器请求信息 ServletResponse接口 —— 响应客户端请求 Servlet接口 —— 定义所有Servlet必须实现的方法 javax.servlet包中的类为: ServletInputStream类 —— 用于从客户端读取二进制数据 ServletOutputStream类 —— 用于将二进制数据发送到客户端 GenericServlet类 —— 抽象类,定义一个通用的,独立于地层协议的Servlet。
(2)javax.servlet.http包中定义了采用HTTP通信的HttpServlet类。 javax.servlet.http包的接口为: HttpServletRequest接口 —— 提供http请求 HttpServletResponse接口 —— 提供http响应 HttpSession接口 —— 用于标识客户端并存储有关客户信息 HttpSessionAttributeListener接口 ——实现这个侦听接口用户获取会话的属性列表的改变的通知 javax.servlet.http包中的类: HttpServlet类 —— 扩展了 GenericServlet的抽象类,用于扩展创建Http Servlet
Cookie类 —— 创建一个Cookie,用于存储Servlet发送给客户端的信息
2>Servlet框架的核心 Servlet框架的核心是:javax.servlet.Servlet接口,所有的Servlet都必须实现这一接口。 4.Http Servlet
HttpServlet是一个抽象类,用来创建用户自己的 HTTP Servlet。HttpServlet类的子类必须至少重写一下方法中的一个:doGet()和doPost()。
HttpServlet类提供doGet()方法来处理GET请求 public void doGet(HttpServletRequest req,HttpServletResponse res)
提供doPost()方法处理POST请求
public void doPost(HttpServletRequest req,HttpServletResponse res)
其中有2个参数:HttpServletRequset和HttpServlerResponse
这2个类实现了ServlerRequset接口和ServletResponse接口 ServletRequest接口中封装了客户请求信息<客户请求方式,参数名,参数值等>
ServletResponse接口 为 Servlet提供了返回相应结果的方法。 5.Servlet体系结构 Servlet—>GenericServlet—>HttpServlet—>用户自定义的Servlet
6.Servlet的生命周期 Servlet的生命周期由Servlet容器控制,该容器创建Servlet的实例。 Servlet生命周期就是指创建Servlet实例后响应客户请求直至销毁的全过程。 1>Serlvet生命周期的三个方法:init()—>service()—>destroy()
2>生命周期的各个阶段: 实例化:Servlet容器创建Servlet类的实例对象 初始化:Servlet容器调用Servlet的init()方法 服务:如果请求Servlet,则容器调用service()方法 销毁:销毁实例之前调用destroy()方法 不可用:销毁实例并标记为垃圾处理
Servlet的生命周期
Servlet的生命周期由Servlet容器控制,该容器创建Servlet的实例。Servlet的生命周期就是指Servlet实例在创建之后响应客户请趟直到至销毁的全过程。Servlet实例的创建取决于Servlet的首次调用。Servlet接口定义了Servlet生命周期的3个方法。
1 init():创建Servlet的实例后对其进行初始化。实现ServletConfig接口的对象作为参数进行传递。init方法在浏览器请求servlet或web server启动时加载运行。
public void init()throws servletexception{
}
public void init(servletconfig conf)throws servletexception{
super.init(conf);//init方法带servletconfig参数时必须有此句代码
//此处写一些初始化操作。如连接数据库等。
}
2 service():响应客户端发出的请求。Service()方法接受ServletRequest接口和ServletResponse接口的对象来处理请求和发送响应。经常的用法是:不用service()方法,用dopost,doget方法来处理请求。其他的方法还有dotrace(),dooptions().dohead()方法,因trace,options.head信息已经在dopost,doget方法中包括,不必使用,doput(),dodelete()方法在web app不经常使用
Service()方法的语法为:
public void service(ServletRequest request, ServletResponse response) throws ServletException,IOException
其中,request是作为参数传递以存储客户端请求的ServletRequest接口的对象;ServletResponse接口的对象,它包含Servlet作出的响应。
3 destroy():如果不需要处理的请求,则释放Servlet 实例。Destroy()方法的语法为:
public void destroy(){
}
public void destroy(){
super.dedtroy(conf);
}
注意:Servlet关闭时才销毁。
Servlet层次结构
在写Servlet程序时,一开始必须导入(import) javax.servlet.*、javax.servlet.http.*。
其中:
javax.servlet.*:存放与Http协议无关的一般性servlet类;
javax.servlet.http.*:除了继承javax.servlet.*之外,并且还增加了与HTTP协议有关的功能。
所有Servlet都必需实现javax.servlet.Servlet接口(Interface),但是通常我们都会从javax.sevler.GenericServlet或javax.servlet.http.HttpServlet择一来实现。
javax.servlet.* 里的ServletRequest和ServletResponse接口提供存取一般的请求和响应;
javax.servlet.http.* 里的HttpServletRequest 和HttpServletResponse接口,则提供HTTP请求及响应的存取服务。
声明servlet类MyServlet
public class MyServletextends httpservlet{}
javax.servlet包主要的接口和类:
1 ServletInputStream类:用于从客户端读取二进制据数。
ServletInputStream类是从java.io.InputStream类扩展而来的抽象类。它只实现
一个readLine()方法。
Public int readLine(byte b[],int offset,int length) throws IOException
b是用于存储读取的数据的字节数组;
offset指定开始读取字符串的位置;
length指定要读取的最大字节数
返回实际读到的字节数。到达流的结尾时返回-1.
2 ServletOutputStream类:向客户端发送二进制数据。
ServletOutputStream类是从java.io.OutputStream类扩展而来的抽象类。主要方法:
public void print(String s) throws IOException
public ovid println(String s) throws IOException
s是要发送到客户端的字符串。
3 GenericServlet类:抽象类,定义一个通用的、独立于底层协议的Servlet。
4 ServletRequest接口:定义一个对象,封装客户向Servlet的请求信息。
使用ServletRequest接口创建的对象,用于使客户端请求信息对Servlet可用。创建的对象作为参数传递至Servlet的Service()方法。
5 ServletResponse接口:定义一个对象辅助Servlet将请求的响应信息发送给客户端。
6 ServletContext接口:Servlet上下文。定义Servlet使用的方法以获取其容器的信息。
7 ServletConfig接口:定义了在Servlet初始化的过程中由Servlet容器传递给Servlet的配置信息对象。保存Servlet的配置信息。
8 Servlet接口:定义所有Servlet必须实现的方法。
javax.servlet.http包主要的接口和类:
1 HttpServletRequest接口:扩展ServletRequest接口,为Http Servlet提供Http请求信息。
getrealpath,getinputstream,getcontenttype,getcontentlengh…
得到服务器的根目录
string path=request.getrealpath(“.”);
取得输入流
datainputstream din=new datainputstream(request.getinputstream());
2 HttpServletResponse接口:扩展ServletResponse接口,提供Http特定的发送响应的功能。常用的方法:
sendredirect,getwriter,setcontenttype,getoutputstream.
设置文件类型
private static final string content_type=”text/html;charset=gb2312”;
response.setcontenttype(content_type);
输出html文件头部信息:
printwriter out=response.getwriter();
out.close();
3 HttpSession接口:用于创建客户端与服务器端之间的会话。
Public HttpSession getSession()
返回与请求关联的当前会话。如果请求没有与其关联的话,则getSession()会创建一个新会话。
Public HttpSession getSession(boolean value)
返回与请求关联的当前session的对象。
boolean value为true时等同于Public HttpSession getSession()
boolean value为false时,则返回null。
4 HttpSessionAttributeListener接口:实现这个侦听接口用于获取会话的属性列表的改变的通知。
5 HttpServlet类:扩展了GenericServlet的抽象类,用于扩展创建Http Servlet。
6 Cookie类:创建一个Cookie,用于存储Servlet发送给客户端的信息。
会话跟踪
会话跟踪允许服务器确定访问站点的用户、用户访问站点的次数和用停留站点的时间
段。会话跟踪技术包括隐藏表单域、URL重写、Cookie、Session。
1 隐藏表单域:是实现会话跟踪最简单的方式。将字段添加到HTML表单中,但并不在
客户端浏览器中显示。
示例代码:
2 URL重写
URL(Uniform Resource Locator,统一资源定位符)是Web上特定页面的地址。URL重
写技术在URL结尾添加一些附加数据以标识该会话。
3 Cookie
Cookie是Web服务器发送给客户端的一小段信息,客户端请求时,可以读取信息发送到服务器端。
Servlet API为使用Cookie而提供javax.servlet.http.Cookie。
Cookie类常用的方法如下:
(1) setMaxAge():设置Cookie的最大保存时间(以秒表示)
public void setMaxAge(int age)
(2) getMaxAge():返回Cookie的最大保存时间
public int getMaxAge()
4 Session
Servlet通信方法
Servlet运行一个称为ServletContext的环境,此环境描述了与Servlet关联的各种参数,一个Servlet只属于一个ServletContext。
1 Servlet与jsp页面通信
下面是UserServlet1中的doGet()方法中的部分代码:
String uid=request.getParameter(“txtuserid”);
ServletContext context=this.getServletContext();
context.setAttribute(“userid”, uid);
RequestDispatcher dispatcher=request.getRequestDispatcher(“../x.jsp”);
x.jsp部分代码:
<%
ServletContext context=this.getServletContext();
String userid=context.getAttribute(“userid”).toString();
%>
用户ID:${userid}
2 Servlet与Servlet通信
属于同一个应用程序的Servlet可以使用javax.servlet.RequestDispatcher接口的forward和include方法来共享数据。
forward()方法将HTTP请求从一个Servlet发送到其它Servlet。该请求包含传递到目标Servlet的URL和请求参数。
include方法可以接收Servlet以包括Servlet响应中的其他Servlet响应数据。接收客户端可以接收的对象,并将数据写入到response对象。
(1)forward():用于将请求从一个Servlet转发到同一个服务器上的另一个Servlet。语法为:
public void forward(ServletRequest request,ServletResponse response) throws ServletException,IOException
基中,request是客户端向Servlet发出的请求,response是Servlet对客户端作出的响应。
(2)include():用于包括另一个Servlet的内容。语法为:
public void include(ServletRequest request,ServletResponse response) throws IOException
其中,request是包含客户端请求的对象,response是包含Servlet响应的对象。
下面是UserServlet1中的doGet()方法中的部分代码:
String uid=request.getParameter(“txtuserid”);
ServletContext context=this.getServletContext();
context.setAttribute(“userid”, uid);
RequestDispatcher dispatcher=request.getRequestDispatcher(“/servlet/UserServlet2”);
Servlet上下文
Servlet上下文提供对应用程序中所有Servlet所共有的各种资源和功能的访问。Servlet上下文API用于设置应用程序中所有Servlet共有的信息。
Javax.servlet.ServletContext接口中用于处理上下文属性的方法如下:
1 getAttribute():返回Servlet上下文中对应属性名称的对象。若没有则返回null。
public Object getAttribute(String name)
其中,name是Servlet的属性名称。
2 setAttribute():将对象绑定到Servlet上下文中提供的属性名称。
public void setAttribute(String name,Object object);
其中,name指定属性名称,object表示要绑定的对象。
_
一、什么是Servlet
简单的说Servlet使用Java语言实现的程序,运行于支持Java语言的Web服务器或者应用服务器中。Servlet先于JSP出现,提供和客户端动态交互的功能。Servlet可以处理来自客户端的HTTP请求,并生成响应返回给客户端。
二、使用Servlet的基本流程如下:
客户端通过HTTP提出请求。
Web服务器接受改请求并将其发给servlet。如果这个servlet尚未被加载,Web服务器将把它加载到Java虚拟机并且执行它。
Servlet将接收该HTT请求执行某种处理。
Servlet将向Web服务器返回应答。
Web服务器将从servlet收到的应答发送给客户端。
三、创建一个MyServlet继承HttpServlet,重写doGet和doPost方法,也就是看请求的方法是get还是post,然后不同的处理方式来处理请求
在Web.xml中配置MyServlet,为什么需要配置?让浏览器发出的请求知道到达哪个servlet,也就是让tomcat将封装好的request找到对应的servlet让其使用
四、get提交和post提交有何区别
(1)get一般用于从服务器上获取数据,post一般用于向服务器传送数据
(2)请求的时候参数的位置有区别,get的参数是拼接在url后面,用户在浏览器地址栏可以看到。post是放在http包的包体中。
比如说用户注册,你不能把用户提交的注册信息用get的方式吧,那不是说把用户的注册信息都显示在Url上了吗,是不安全的。
(3)能提交的数据有区别,get方式能提交的数据只能是文本,且大小不超过1024个字节,而post不仅可以提交文本还有二进制文件。
(4)servlet在处理请求的时候分别对应使用doGet和doPost方式进行处理请求
五、doGet与doPost方法的两个参数是什么
HttpServletRequest:封装了与请求相关的信息
HttpServletResponse:封装了与响应相关的信息
5、request.getAttribute()和request.getParameter
(1)有setAttribute,没有setParameter方法
(2)getParameter获取到的值只能是字符串,不可以是对象,而getAttribute获取到的值是Object类型的。
(3)通过form表单或者url来向另一个页面或者servlet传递参数的时候需要用getParameter获取值;getAttribute只能获取setAttribute的值
(4)setAttribute是应用服务器把这个对象放到该页面所对应的一块内存当中,当你的页面服务器重定向到另一个页面的时候,应用服务器
会把这块内存拷贝到另一个页面对应的内存当中。通过getAttribute可以取得你存下的值,当然这种方法可以用来传对象。
用session也是一样的道理,这是说request和session的生命周期不一样而已。
Servlet由来
做过BS项目的人都知道,浏览器能够根据HTML静态标记语言来显示各式各样的网页。但是如果我们需要在网页上完成一些业务逻辑:比如登陆验证。或者说网页显示的内容在服务器的数据库中。如果是这样,除了负责显示的HTML标记之外,必须还要有完成这些业务功能的代码存在。这种网页我们就叫做动态网页。
对于静态网页而言,服务器上存在的是一个个纯HTML文件。当客户端浏览器发出HTTP请求时,服务器可以根据请求的URL找到对应的HTML文件,并将HTML代码返回给客户端浏览器。
但是对于动态网页,服务器上除了找到需要显示的HTML标记外,还必须执行所需要的业务逻辑,然后将业务逻辑运算后的结果和需要显示的HTML标记一起生成新的HTML代码。最后将新的带有业务逻辑运算结果的HTML代码返回给客户端。
为了实现动态网页的目标,JavaServlet技术因应而生,它能够以一种可移植的方法来提供动态的、面向用户的内容。
简单来说:
servlet是在服务器上运行的小程序。Servlet的主要功能在于交互式地浏览和修改数据,生成动态Web内容,是为web开发服务的。
CGI与Servlet对比
开始的时候,公共网关接口(CommonGateway Interface,CGI)脚本是生成动态内容的主要技术。虽然使用得非常广泛,但CGI脚本技术有很多的缺陷,这包括平台相关性和缺乏可扩展性。为了避免这些局限性,JavaServlet技术因应而生,它能够以一种可移植的方法来提供动态的、面向用户的内容。处理用户请求。
对比一:当用户浏览器发出一个Http/CGI的请求,或者说调用一个CGI程序的时候,服务器端就要新启用一个进程(而且是每次都要调用),调用CGI程序越多(特别是访问量高的时候),就要消耗系统越多的处理时间,只剩下越来越少的系统资源,对于用户来说,只能是漫长的等待服务器端的返回页面了,这对于电子商务激烈发展的今天来说,不能不说是一种技术上的遗憾。
而Servlet充分发挥了服务器端的资源并高效的利用。每次调用Servlet时并不是新启用一个进程,而是在一个Web服务器的进程中共享和分离线程,而线程最大的好处在于可以共享一个数据源,使系统资源被有效利用。故servlet不是线程安全的,单实例多线程的
_
对比二:传统的CGI程序,不具备平台无关性特征,系统环境发生变化,CGI程序就要瘫痪,而Servlet具备Java的平台无关性,在系统开发过程中保持了系统的可扩展性、高效性。
对比三:传统技术中,一般大都为二层的系统架构,即Web服务器+数据库服务器,导致网站访问量大的时候,无法克服CGI程序与数据库建立连接时速度慢的瓶颈,从而死机、数据库死锁现象频繁发生。而我们的Servlet有连接池的概念,它可以利用多线程的优点,在系统缓存中事先建立好若干与数据库的连接,到时候若想和数据库打交道可以随时跟系统”要”一个连接即可,反应速度可想而知。
Servlet的运行过程
⒈ 客户端发送请求至服务器端;
⒉服务器端根据web.xml文件中的Servlet相关配置信息,将客户端请求转发到相应的Servlet
⒊ Servlet引擎调用Service()方法,根据request对象中封装的用户请求与数据库进行交互,返回数据之后,Servlet会将返回的数据封装到response对象中;
⒋ Servlet生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求
⒌ 服务器将响应返回给客户端
Servlet生命周期
<br />_ _<br />1) 加载和实例化;在第一次请求Servlet时,Servlet容器将会创建Servlet实例;<br />2) 初始化;Servlet容器加载完成Servlet之后,必须进行初始化,此时,init方法将被调用;<br />_3) Servlet初始化之后,就处于响应请求的就绪状态,此时如有客户端请求发送,就会调用Servlet实例的service()方法,并且根据用户的请求方式,调用doPost或者doGet方法;_<br />4) 最后,Servlet容器负责将Servlet实例进行销毁,调用destroy方法实现;<br /> 对于更多的客户端请求,Server创建新的请求和响应对象,仍然激活此Servlet的service()方法,将这两个对象作为参数传递给它。如此重复以上的循环,但无需再次调用init()方法。<br />_ 一般Servlet只初始化一次(只有一个对象),当Server不再需要Servlet时(一般当Server关闭时),Server调用Servlet的Destroy()方法。_
实例解析:

html代码—客户端浏览器
1. <span style="font-family:KaiTi_GB2312;"><html>
2. <head>
3. <title>学生管理</title>
4. </head>
5. <body>
6. <h1>根据出生日期段查询</h1>
7. <form action="queryStudentServlet">
8. 出生日期 :<input type="text" name="beginDate">至<input type="text" name="endDate">
9. <input type="submit" value="查询学生">
10. </form>
11. </body>
12. </html>
13. </span>
配置文件
1. <span style="font-family:KaiTi_GB2312;"><servlet>
2. <servlet-name>StudentMgrServlet</servlet-name>
3. <servlet-class>StudentServlet</servlet-class>
4. </servlet>
5. <servlet-mapping>
6. <servlet-name>StudentMgrServlet</servlet-name>
7. <url-pattern>/queryStudentServlet</url-pattern>
8. </servlet-mapping>
9. </span>
servlet处理过程
1. <span style="font-family:KaiTi_GB2312;"> import java.text.*;
2. import java.util.*;
3. import java.io.*;
4. import javax.servlet.http.*;
5. import javax.servlet.*;
6.
7. import com.bjpowernode.exam.model.*;
8. import com.bjpowernode.exam.manager.*;
9.
10. public class StudentServlet extends HttpServlet {
11.
12. public void doGet(HttpServletRequest request, HttpServletResponse response)
13. throws ServletException, IOException {
14. doPost(request, response);
15. }
16.
17. public void doPost(HttpServletRequest request, HttpServletResponse response)
18. throws ServletException, IOException {
19.
20. String sBeginDate = request.getParameter("beginDate");
21. String sEndDate = request.getParameter("endDate");
22.
23. Date beginDate = new Date();
24. Date endDate = new Date();
25. try {
26. beginDate = new SimpleDateFormat("yyyy-MM-dd").parse(sBeginDate);
27. endDate = new SimpleDateFormat("yyyy-MM-dd").parse(sEndDate);
28. }catch(Exception e) {
29. e.printStackTrace();
30. }
31.
32.
33. StudentManager studentManager = new StudentManagerImpl();
34. List<Student> studentList = studentManager.findStudentList(beginDate, endDate);
35. //表格省略…
36. }
37. }
38. </span>
Servlet如何同时处理多个请求?
Servlet采用多线程来处理多个请求的同时访问。Servlet容器通过线程池来管理维护服务请求。所谓线程池,相当于数据库连接池,实际上是等待执行代码的一组线程,叫做工作者线程。Servlet容器通过一个调度线程来管理工作者线程。<br />· 当容器收到一个Servlet的访问请求,调度者线程就从线程池中选出一个工作者线程,将用户请求传递给该线程,然后由该线程处理Servlet的service()方法;<br />· 当这个线程在执行的时候,容器收到一个新的请求,调度者线程再次从线程池中选出一个新的工作者线程;<br />· 当容器同时收到对同一个Servlet的多个请求时,那么Servlet的service方法将在多线程中并发执行。
注:
1.Servlet容器默认采用单实例多线程的方式来处理请求。这样减少了产生Servlet实例的开销,提升了对请求的响应时间;
2.对于Tomcat容器来讲,可以在其server.xml中通过
如何开发线程安全的Servlet?
Servlet容器采用多线程来处理请求,提高性能的同时也造成了线程安全问题。要开发线程安全的Servlet应该从一下几个方面进行:<br />1. 变量的线程安全; 多线程并不共享局部变量,所以我们要尽可能的在Servlet中使用局部变量;<br />2. 代码块的线程安全; 使用同步块Synchronized,防止可能调用的代码块;但是要注意的是,要尽可能得缩小同步代码的方范围,不要在service方法和响应方法上直接使用同步,这会严重影响性能。<br />3. 属性的线程安全; ServletContext,HttpSession,ServletRequest对象中属性;<br />4. 使用同步集合; 使用Vector代替ArrayList,使用HashTable代替HashMap;<br />5. 不要在Servlet中创建自己的线程来完成某个功能; Servlet本身就是多线程的,如果再创建新的线程,将会导致线程执行复杂化,出现线程安全问题;<br />6. 在多个Servlet中,对外部对象,比如:文件;进行修改操作一定要加锁,做到互斥访问;
总结:
一个servlet就是Java编程语言中的一个类,它被用来扩展服务器的性能,服务器上驻留着可以通过“请求-响应”编程模型来访问的应用程序。Servlet通过解析http请求,取得客户端的参数来进行下一步操作。其实简单来说,servlet就是一个控制器,取参数,调用业务逻辑.
而在.net 中HttpHandler是一个HTTP请求的真正处理中心,也正是在这个HttpHandler容器中,ASP.NET Framework才真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。