转载自博客园:https://www.cnblogs.com/whgk/p/6399262.html
以及菜鸟教程:https://www.runoob.com/servlet/servlet-life-cycle.html
一、什么是servlet?
处理请求和发送响应的过程是由一种叫做Servlet的程序来完成的,并且Servlet是为了解决实现动态页面而衍生的东西。理解这个的前提是了解一些http协议的东西,并且知道B/S模式(浏览器/服务器)。
B/S:浏览器/服务器。 浏览器通过网址来访问服务器,比如访问百度,在浏览器中输入 www.baidu.com,这个时候浏览器就会显示百度的首页,那么这个具体的过程,步骤是怎样的呢?这个就了解一下http请求和响应了。
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
使用 Servlet,可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
下图显示了 Servlet 在 Web 应用程序中的位置
二、tomcat和servlet的关系
Tomcat 是Web应用服务器,是一个Servlet/JSP容器. Tomcat 作为Servlet容器,负责处理客户请求,把请求传送给Servlet,并将Servlet的响应传送回给客户.而Servlet是一种运行在支持Java语言的服务器上的组件. Servlet最常见的用途是扩展Java Web服务器功能,提供非常安全的,可移植的,易于使用的CGI替代品.
从http协议中的请求和响应可以得知,浏览器发出的请求是一个请求文本,而浏览器接收到的也应该是一个响应文本。但是在上面这个图中,并不知道是如何转变的,只知道浏览器发送过来的请求也就是request,我们响应回去的就用response。忽略了其中的细节,现在就来探究一下。
①:Tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型的request对象,所有的HTTP头数据读可以通过request对象调用对应的方法查询到。
②:Tomcat同时会把要响应的信息封装为HttpServletResponse类型的response对象,通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给tomcat,tomcat就会将其变成响应文本的格式返回给浏览器。
Java Servlet API 是Servlet容器(tomcat)和servlet之间的接口,它定义了serlvet的各种方法,还定义了Servlet容器传送给Servlet的对象类,其中最重要的就是ServletRequest和ServletResponse。所以说我们在编写servlet时,需要实现Servlet接口,按照其规范进行操作。
三、编写Servlet
1、创建一个HelloWorld 继承HttpServlet,重写doGet或者doPost方法,也就是看请求的方式是get还是post,然后用不同的处理方式来处理请求,
// 导入必需的 java 库
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
// 扩展 HttpServlet 类
public class HelloWorld extends HttpServlet {
private String message;
public void init() throws ServletException
{
// 执行必需的初始化
message = "Hello World";
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 设置响应内容类型
response.setContentType("text/html");
// 实际的逻辑是在这里
PrintWriter out = response.getWriter();
out.println("<h1>" + message + "</h1>");
}
public void destroy()
{
// 什么也不做
}
}
2、在web.xml中配置HelloWorld,为什么需要配置?让浏览器发出的请求知道到达哪个servlet,也就是让tomcat将封装好的request找到对应的servlet让其使用。
<web-app>
<servlet>
<servlet-name>HelloWorld</servlet-name> //servlet的名字
<servlet-class>HelloWorld</servlet-class> // servlet的全限定名(包名+类名)
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name> //servlet的名字
<url-pattern>/HelloWorld</url-pattern> // 浏览器通过 "/HelloWorld"找到该servlet
</servlet-mapping>
</web-app>
3、编译和部署Servlet
(1)先将servlet文件编译成能够直接使用的.class文件
javac HelloWorld.java
(2)再将生成的.class文件部署到web服务器相关目录下(这里使用tomcat)
默认情况下,Servlet 应用程序 位于路径
< Tomcat-installation-directory >/webapps/ROOT 下,且 类文件 放在
< Tomcat-installation-directory>/webapps/ROOT/WEB-INF/classes 中。
如果您有一个全限定名为 com.myorg.MyServlet 类,那么这个 Servlet 类必须位于 WEB-INF/classes/com/myorg/MyServlet.class 中。也就是说 类文件的目录必须和类的全限定名吻合。
4、运行servlet
在浏览器中输入:http://localhost:8080/HelloWorld,
即可显示下列文字:
四、Servlet的原理
1、servlet的生命周期是什么?
服务器启动时(web.xml中配置load-on-startup=1,默认为0)或者第一次请求该servlet时,就会初始化一个Servlet对象,也就是会执行初始化方法init(ServletConfig conf)
该servlet对象去处理 所有客户端请求,在service(ServletRequest req,ServletResponse res)方法中执行。
每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用与之对应的 doGet、doPost、doPut,doDelete 等方法。
最后服务器关闭时,才会销毁这个servlet对象,执行destroy()方法。
五、Servlet其他细节
转自:https://blog.youkuaiyun.com/qq_28483283/article/details/51220749
不要在Servlet中创建成员!创建局部变量即可!
可以创建无状态成员!
可以创建有状态的成员,但状态必须为只读的!
1.Servlet与线程安全
因为一个类型的Servlet只有一个实例对象,那么就有可能会现一个Servlet同时处理多个请求,那么Servlet是否为线程安全的呢?答案是:“不是线程安全的”。这说明Servlet的工作效率很高,但也存在线程安全问题!
所以我们 不应该在Servlet中创建成员变量,因为可能会存在一个线程对这个成员变量进行写操作,另一个线程对这个成员变量进行读操作。
2.让服务器在启动时就创建Servlet
默认情况下,服务器会在某个Servlet第一次收到请求时创建它。也可以在web.xml中对Servlet进行配置,使服务器启动时就创建Servlet。
<servlet>
<servlet-name>hello1</servlet-name>
<servlet-class>cn.itcast.servlet.Hello1Servlet</servlet-class>
<load-on-startup>0</load-on-startup>[在<servlet>中配置<load-on-startup>,其中给出一个非负整数!]
</servlet>
<servlet-mapping>
<servlet-name>hello1</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>hello2</servlet-name>
<servlet-class>cn.itcast.servlet.Hello2Servlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>hello3</servlet-name>
<servlet-class>cn.itcast.servlet.Hello3Servlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello3</servlet-name>
<url-pattern>/hello3</url-pattern>
</servlet-mapping>
在元素中配置元素可以让服务器在启动时就创建该Servlet,其中元素的值必须是大于等于的整数,它的使用是服务器启动时创建Servlet的顺序。上例中,根据的值可以得知服务器创建Servlet的顺序为Hello1Servlet、Hello2Servlet、Hello3Servlet。