Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是做为来自 Web 浏览器或其余 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet,能够收集来自网页表单的用户输入,呈现来自数据库或者其余源的记录,还能够动态建立网页。
Servlet是sun公司提供的一门用于开发动态web资源的技术。
Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),须要完成如下2个步骤:
一、编写一个Java类,实现servlet接口。
二、把开发好的Java类部署到web服务器中。
按照一种约定俗成的称呼习惯,一般咱们也把实现了servlet接口的java程序,称之为Servlet。html
Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:
①Web服务器首先检查是否已经装载并建立了该Servlet的实例对象。若是是,则直接执行第④步,不然,执行第②步。
②装载并建立该Servlet的一个实例对象。
③调用Servlet实例对象的init()方法。
④建立一个用于封装HTTP请求消息的HttpServletRequest对象和一个表明HTTP响应消息的HttpServletResponse对象,而后调用Servlet的service()方法并将请求和响应对象做为参数传递进去。
⑤WEB应用程序被中止或从新启动以前,Servlet引擎将卸载Servlet,并在卸载以前调用Servlet的destroy()方法。java
Servlet 生命周期可被定义为从建立直到毁灭的整个过程。如下是 Servlet 遵循的过程:web
Servlet 执行如下主要任务:数据库
@WebServlet(name = "MyServlet", urlPatterns = {"/MyServlet", "/myServlet"}) public class MyServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { System.out.println("----------doPost-----------"); doGet(request, response); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { System.out.println("----------doGet-----------"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>"); out.println(" <BODY>"); out.print(" This is "); out.print(this.getClass()); out.println(", using the GET method"); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); } }
<servlet> <servlet-name>MyServlet</servlet-name> <servlet-class>org.silence.servlet.MyServlet</servlet-class> <init-param> <param-name>name</param-name> <param-value>zhangsan</param-value> </init-param> <display-name>MyServlet</display-name> </servlet> <servlet-mapping> <servlet-name>MyServlet</servlet-name> <url-pattern>/servlet</url-pattern> </servlet-mapping>
注意:Servlet3.0的项目服务器须要Tomcat7.0开始的版本才支持!!浏览器
@WebServlet(name = "ParamServlet", urlPatterns = "/param", initParams = {@WebInitParam(name = "name", value = "zhangsan"), @WebInitParam(name = "abc", value = "abc")}) public class ParamServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext servletContext = getServletContext(); ServletConfig config = getServletConfig(); String name = config.getInitParameter("name"); response.getWriter().println(name); Enumeration<String> parameterNames = config.getInitParameterNames(); while (parameterNames.hasMoreElements()) { String element = parameterNames.nextElement(); String parameter = config.getInitParameter(element); response.getWriter().println(element + " = " + parameter); } } }
在默认的状况下Servlet容器(web服务器)对声明的Servlet,只建立一个Servlet实例,当多个客户端并发访问同一个Servlet时,Servlet容器会为每个客户端的访问请求建立一个线程,并在这个线程上调用Servlet的service方法,所以service方法内若是访问了同一个资源的话,就有可能引起线程安全问题。
例以下面的代码:缓存
@WebServlet(name = "SynServlet", urlPatterns = "/syn") public class SynServlet extends HttpServlet { int i = 1; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // synchronized (this) { i++; try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } response.getWriter().write("i: " + i); // } } }
解决办法之一是给共享资源加锁。安全
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { synchronized (this) { i++; try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } response.getWriter().write("i: " + i); } }
javax.servlet.SingleThreadModel API及其翻译服务器
Ensures that servlets handle only one request at a time. This interface has no methods.cookie
确保servlet每次只处理一项请求。接口不含方法。session
If a servlet implements this interface, you are guaranteed that no two threads will execute concurrently in the servlet's service
method. The servlet container can make this guarantee by synchronizing access to a single instance of the servlet, or by maintaining a pool of servlet instances and dispatching each new request to a free servlet.
*若是servlet实现了该接口,会确保不会有两个线程同时执行servlet的service方法。 servlet容器经过同步化访问servlet的单实例来保证,也能够经过维持servlet的实例池,对于新的请求会分配给一个空闲的servlet。*
Note that SingleThreadModel does not solve all thread safety issues. For example, session attributes and static variables can still be accessed by multiple requests on multiple threads at the same time, even when SingleThreadModel servlets are used. It is recommended that a developer take other means to resolve those issues instead of implementing this interface, such as avoiding the usage of an instance variable or synchronizing the block of the code accessing those resources. This interface is deprecated in Servlet API version 2.4.
*注意:SingleThreadModel不会解决全部的线程安全隐患。*例如,会话属性和静态变量仍然能够被多线程的多请求同时访问,即使使用了SingleThreadModel servlet。
使用synchronized或提供的锁来同步共享资源。