Servlet是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态web内容。通常我们也把实现了Servlet接口的java程序,称之为Servlet。
客户端发送HTTP请求到服务器,服务器启动并创建一个Servlet,Servlet根据请求的类型,调用service()的doGet()、doPost()等方法,将处理后的数据传递到服务端再处理由服务器端发送的数据发送到客户端,流程如下:
浏览器向服务器请求时,服务器不会直接执行我们的类,而是到web.xml里寻找路径名 ①:第一步,浏览器输入访问路径后,携带了请求行,头,体 ②:第二步,根据访问路径找到已注册的servlet名称,既图中的demo ③:第三步,根据映射找到对应的servlet名 ③:第四步,根据根据servlet名找到我们全限定类名(盗了一张大神的图)
每个servlet标签对应一个servlet-mapping或者多个servlet-mapping标签,servlet标签中的servlet-name与servlet-mapping标签中servlet-name相同,且具有唯一性。servlet-class的值,指的是包名(servlet)+类名(firstServlet)。
<servlet> <servlet-name>firstServlet</servlet-name> <servlet-class>servlet.firstServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>firstServlet</servlet-name> <url-pattern>/firstServlet</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>firstServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
当配置<url-pattern>/*</url-pattern>时,*为通配符映射,即所有的链接都可以匹配。当存在多个映射的时候,根据访问请求的链接有优先匹配更‘像’的映射。如当请求URL为/firstServlet会优先匹配<url-pattern>/firstServlet</url-pattern>。 <load-on-startup>1</load-on-startup>为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据。
当多个客户端并发访问同一个Servlet的时候,Web服务器会给每个客户端的请求创建一个线程,通过调用Servlet的service(),当多个客户端同时访问的时候就会出现线程安全的问题。 当参数i是局部变量的时候即定义在doGet()方法里的时候,由于每个线程都有局部变量i,所以不存在线程安全的问题。 但是当i变成了全局变量的时候,每个线程的访问都会改变i的值。
public class secondServlet extends HttpServlet { private static final long serialVersionUID = 1L; int i = 1; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("SECOND SERVLET DOGET"); //int i = 1; i++; response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } out.println(i); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
解决方案:1.使用SingleThreadModel接口,但是现在已经过时了。
synchronized (this) { i++; response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } out.println(i); }
参考文章:https://www.cnblogs.com/xdp-gacl/p/3760336.html
https://blog.csdn.net/u010452388/article/details/80395679
https://baike.baidu.com/item/servlet/477555?fr=aladdin
原文:https://www.cnblogs.com/dujingxin/p/10384103.html