Servlet是一种运行于服务器端的Java应用程序,可以生成动态的Web页面,它是属于客户与服务器响应的中间层。实际上,JSP在底层就是一个Servlet,两者可以实现同样的页面效果,不过两者相比来说编写JSP的成本低的多。
创建Servlet
- 创建一个类并让这个类继承
HttpServlet
package servlets;
public class WelcomeServlet extends HttpServlet {
......
}
- 重写doGet()用于处理GET请求、doPost()方法用于处理POST请求
package servlets;
public class WelcomeServlet extends HttpServlet {
@Override
public void init() throws ServletException {
super.init();
}
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
super.service(req, res);
}
@Override
public void destroy() {
super.destroy();
}
}
- 配置Servlet:编写完Servlet后,还不能直接访问,必须要配置Servlet,才能通过URL映射到与它对应的Servlet中来,用户才能对它进行访问。在
web.xml
中加入以下配置:
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>WelcomeServlet</servlet-name>
<servlet-class>servlets.WelcomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WelcomeServlet</servlet-name>
<url-pattern>/servlets/WelcomeServlet</url-pattern>
</servlet-mapping>
</web-app>
以上配置表示给servlets.WelcomeServlet起名为WelcomeServlet,在访问时,以:http://服务器IP:端口/项目虚拟目录名/servlets/WelcomeServlet
为访问的URL,如http://localhost:8080/Proj00/servlet/WelcomeServlet
<servlet-name>
可以自己命名,不一定要与源文件名字一样,但是两个servlet-name名字必须相同。
<url-pattern>
表示访问路径,可以不配置为Servlet的类路径。
- 在浏览器输入在
web.xml
配置的URL路径来访问Servlet。
如:http://localhost:8080/Proj00/servlet/WelcomeServlet
Servlet运行机制
Servlet采用的是多线程机制
,当浏览器发送给服务器一个Servlet的请求时,如果这个Servlet是第一次被调用,那么服务器将会自动创建一个Servlet实例,并调用doGet()或doPost()方法处理请求;而如果这个Servlet已经被实例化,那么服务器只是会新启动一个线程来运行doGet()或doPost()方法。
扩展:servlet在多线程下其本身并不是线程安全的。
如果在类中定义成员变量,而在service中根据不同的线程对该成员变量进行更改,那么在并发的时候就会引起错误。最好是在方法中,定义局部变量,而不是类变量或者对象的成员变量。由于方法中的局部变量是在栈中,彼此各自都拥有独立的运行空间而不会互相干扰,因此才做到线程安全。
Servlet生命周期
-
init()方法
对Servlet做一些初始化工作,这个方法只会被调用一次,不会对每次连接都调用,可以将一些初始化代码放在该函数中。 -
service()、doGet()、doPost()方法
doGet()方法是在以GET方式请求Servlet时运行。doGet是在javax.servlet.http.HttpServlet
中实现的
doPost()方法是在以POST方式请求Servlet时运行。doPost 是在javax.servlet.http.HttpServlet
中实现的
当客户端发送一个请求过来时,服务器端会开启一个线程,该线程会调用service()
方法,service()方法会根据收到的客户端的请求类型来决定是调用doGet()方法还是doPost()方法。(一般情况下不用重写service()方法)service()是在javax.servlet.Servlet
接口中定义的 -
destory()方法
destroy()方法在Servlet实例消亡时自动调用。
总结:当客户端向Web服务器端发出第一次请求时,Web服务器会实例化一个Servlet并且调用init()方法;如果Web服务器中已经存在了一个当前Servlet实例,将直接使用此实例;然后调用service()方法,service()方法将根据客户端的请求方式来决定调用对应的doGet()或doPost()方法;当Servlet从Web服务器中消亡时,Web服务器将会调用Servlet的destroy()方法。