JavaWeb-07(tomcat与web程序结构与Http协议与Servlet基础)

JavaWeb-07

JavaWeb-tomcat与web程序结构与Http协议与Servlet基础

HTTP协议(记住)

1、http协议:规定了客户端和服务端交流时的数据格式

a. WEB浏览器与WEB服务器之间的一问一答的交互过程必须遵循一定的规则,这个规则就是HTTP协议。
b. HTTP是HyperText Transfer Protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程及数据本身的格式。
c. HTTP协议的版本:HTTP/1.0、HTTP/1.1
d. HTTP协议是学习JavaWEB开发的基石,不深入了解HTTP协议,就不能说掌握了WEB开发,更无法管理和维护一些复杂的WEB站点。

2、HTTP1.0的基本运行方式

基于HTTP协议的客户/服务器模式的信息交换过程,如图所示,

它分四个过程:

建立连接、发送请求信息、发送响应信息、关闭连接。

浏览器与WEB服务器的连接过程是短暂的,每次连接只处理一个请求和响应。对每一个页面的访问,浏览器与WEB服务器都要建立一次单独的连接。

浏览器到WEB服务器之间的所有通讯都是完全独立分开的请求和响应。

无状态

3、HTTP1.0特点:

客户端连上服务器后,向服务器请求某个web资源,称之为客户端向服务器发送了一个HTTP请求。

一个完整的HTTP请求包括如下内容:

    一个请求行、若干消息头、以及请求正文,其中的一些消息头和正文都是可选的,消息头和正文内容之间要用空行隔开。

1、请求和响应都由三部分组成:

请求信息(3部分组成):    

    1)请求行 (由3部分组成)
        a) 请求的方式
        b) 请求的资源地址
        c) 请求协议
    2)请求头信息(2部分组成)
        a) 头名称
        b) 头值
    3)请求正文 (只有请求的类型是post才会有)

响应信息:(3部分组成)

    1)响应行(由3部分组成)
        a)响应协议
        b)状态码
        c)状态信息
    2) 响应头信息(2部分):
          a): 响应头
          b): 头值
    3) 响应正文.

2、get和post方式区别:

GET方式:如请求方式为GET方式,则可以在请求的URL地址后以?的形式带上交给服务器的数据,多个数据之间以&进行分隔,例如:
    GET /mail/1.html?name=abc&password=xyz HTTP/1.1
    GET方式的特点:在URL地址后附带的参数是有限制的,其数据容量通常不能超过1K。    

POST方式:如请求方式为POST方式,则可以在请求的正文内容中向服务器发送数据,Post方式的特点:传送的数据量无限制。

get方式对提交的数据大小有限制(1k),post方式对数据大小没有限制.

3、响应的状态码:

200(正常)
    表示一切正常,返回的是正常请求结果
302/307(临时重定向)
    指出被请求的文档已被临时移动到别处,此文档的新的URL在Location响应头中给出。
304(未修改)
    表示客户机缓存的版本是最新的,客户机可以继续使用它,无需到服务器请求。
404(找不到)
    服务器上不存在客户机所请求的资源。
500(服务器内部错误)
    服务器端的程序发生错误

4、请求头信息:

* Accept: 浏览器告诉服务端, 浏览器可接受的MIME类型

* MIME类型: 相当于操作系统下的文件类型。
是由大类型和小类型组成: text/html;
对应的关系在conf/web.xml中查询

* Accept-Charset: 浏览器告诉服务端, 浏览器支持哪种字符集

* Accept-Encoding: 浏览器告诉服务端, 浏览器能够进行解码的数据编码方式,比如gzip
* Accept-Language: 浏览器告诉服务端,浏览器支持的语言种类

* Host: 浏览器告诉服务端,浏览器所在的主机

* Referer: 浏览器告诉服务端,当前页面从哪里来的。
*
    用处:
    1. 用来记录广告的信息
    2. 防盗链

* Content-Type: 浏览器告诉服务端 ,内容类型 If-Modified-Since: 浏览器告诉服务端修改的时间

* Content-Length: 浏览器告诉服务端 请求正文内容长度

* Connection: 浏览器告诉服务端,连接的状态

* Cookie: 浏览器告诉服务端 ,浏览器携带的Cookie

* Date: 浏览器告诉服务端,发送请求的时间

5、响应头信息

*Location : 服务端用来告诉浏览器,请求需要重定向.(必须结合状态码302使用)

*Server : 服务端用来告诉浏览器,服务器的类型

*Content-Encoding: 服务端用来告诉浏览器,服务器对数据采用的编码

*Content-Length:  服务端用来告诉浏览器,响应正文的长度

*Content-Language: 服务端用来告诉浏览器,zh-cn服务发送的文本的语言

*Content-Type: 服务端用来告诉浏览器,你要用哪个码表来解析二进制数据

*Last-Modified : 服务端用来告诉浏览器,访问资源的最后修改时间

*Refresh:服务端用来告诉浏览器,多长时间刷新一次

*Content-Disposition: 服务端用来告诉浏览器,以下载文件的方式打开文件

*Expires: -1 : 服务端用来告诉浏览器,不要缓存 Cache-Control: no-cache (1.1)    Pragma: no-cache   (1.0)  

*Set-Cookie: 服务端用来告诉浏览器,要存储的内容

以下我们使用httpwatch插件安装到IE浏览器去抓取客户端浏览器与tomcat服务器互访的数据包信息:

安装后

在MyEclipse下新建工程:

然后自定义配置工程的服务器。我们的实验使用的是tomcat服务器:

在此我们使用的是Tomcat6.x版本的,因为该版本可以兼容1.6版本以下的JDK: 在打开配置对话框后选择用户Tomcat存储的地址,然后点击apply再确定:

然后点击Tomcat6.x下的JDK选择用户JDK存储的目录:

确定完步骤之后,点击项目部署按钮:

进入部署界面,把新建的servlet项目绑定到自定义的服务器上,点击完redepoly之后下面对话框会显示成功,点击确定:

部署成功。

ServletResponse1.java

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//演示location响应头
public class ServletResponse1 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setStatus(302) ;
        response.setHeader("Location", "/day07_01_httpresponse/servlet/ServletResponse2") ;
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

ServletResponse2.java

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletResponse2 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.getWriter().write("hello world!!!") ;
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

在装了httpwatch插件的IE里输入:http://localhost:8080/day0701httpresponse/servlet/ServletResponse1之后IE会自动跳转到了http://localhost:8080/day0701httpresponse/servlet/ServletResponse2

ServletResponse3.java

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//演示content-Encoding响应头
public class ServletResponse3 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ;

        byte[] bs = s.getBytes() ;
        System.out.println("压缩前的长度: " + bs.length);

        ByteArrayOutputStream baos = new ByteArrayOutputStream() ;

        //用压缩流将数据压缩到一个输出流中
        GZIPOutputStream out = new GZIPOutputStream(baos) ;
        //将数据压缩到baos中
        out.write(bs) ;
        out.close() ;

        //从输出流中拿取数据
        bs = baos.toByteArray() ;  // 拿取到了压缩后的数据
        System.out.println("压缩后长度:" + bs.length);

        //通知浏览器服务端采用的数据格式
        response.setHeader("Content-Encoding", "gzip") ;

        response.getOutputStream().write(bs) ;
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

在装了httpwatch插件的IE里输入:http://localhost:8080/day0701httpresponse/servlet
/ServletResponse3

ServletResponse4

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//演示Content-Type响应头
public class ServletResponse4 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //通知浏览器用哪个码表解析二进制数据
        response.setHeader("Content-Type", "text/html;charset=gbk") ;
        System.out.println(response.getCharacterEncoding()) ;
        response.getWriter().write("冠希哥爱上了阿娇") ;
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

在装了httpwatch插件的IE里输入:http://localhost:8080/day0701httpresponse/servlet
/ServletResponse4

ServletResponse6.java

import java.io.IOException;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//演示refresh响应头
public class ServletResponse6 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //定期刷新自己
//      response.setHeader("Refresh", "2") ;
//      response.getWriter().write("aaaaaa" + new Random().nextInt()) ;

        //刷新到其他页面
        response.setHeader("Refresh", "2;url=/day07_01_httpresponse/servlet/ServletResponse5") ;
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

在装了httpwatch插件的IE里输入:http://localhost:8080/day0701httpresponse/servlet
/ServletResponse6

点击打开后:

ServletResponse5.java

import java.io.FileInputStream;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//演示Content-Disposition响应头
public class ServletResponse5 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //获取图片的路径
        String path = getServletContext().getRealPath("/WEB-INF/classes/1.gif") ;
        System.out.println(path);
        //创建一个输入流
        FileInputStream in = new FileInputStream(path) ;
        //创建输出流
        ServletOutputStream os = response.getOutputStream() ;

        //通知浏览器以下载文件的方式来打开数据
        response.setHeader("Content-Disposition", "attachment;filename=1.gif") ;

        //读取数据发送数据
        byte[] bs = new byte[1024] ;
        int b = 0 ;
        while((b = in.read(bs)) != -1){
            os.write(bs,0,b) ;
        }

        in.close() ;
        os.close() ;

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

在装了httpwatch插件的IE里输入:http://localhost:8080/day0701httpresponse/servlet
/ServletResponse5

ServletResponse7.java

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//演示不要缓存
public class ServletResponse7 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.getWriter().write("hello ,ajiao") ;

        response.setHeader("Expires", "-1") ;
        response.setHeader("Cache-Control", "no-cache") ;
        response.setHeader("Pragma", "no-cache") ;
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

在装了httpwatch插件的IE里输入:http://localhost:8080/day0701httpresponse/servlet
/ServletResponse7

Servlet

一、Servlet简介

Servlet是sun公司提供的一门用于开发动态web资源的技术。

Sun公司在其API中提供了一个servlet接口,用户若想开发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:

编写一个Java类,实现servlet接口。
把开发好的Java类部署到web服务器中。
  • 快速入门,用servlet向浏览器输出“hello servlet”

    阅读Servlet API,解决两个问题:

    输出hello servlet的java代码应该写在servlet的哪个方法内?
    如何向IE浏览器输出数据?
    

    首先新建一个Java程序

    把servlet的包拉到该路径下

    在dos下进入到新建Java程序的文件夹内

    设定classpath

    设定好classpath之后编译java程序

    得到类文件

    配置新建工程下的web.xml文档

    xml内容如下

    工程环境配置好之后在客户端浏览器输入该路径,测试成功。

二、执行过程图解

Tomcat在加载Web应用时,就会把相应的web.xml文件中的数据读入到内存中。因此当Tomcat需要参考web.xml文件时,实际上只需要从内存中读取相关数据就可以了,无需再到文件系统中读取web.xml。

三、在Eclipse中开发Servlet

四、Servlet接口实现类

1、Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。

2、HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。

3、HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。

4、阅读HttpServlet API文档,看一下servlet-api.jar

五、Servlet的一些细节

1、由于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用servlet标签和servlet-mapping标签完成。

2、servlet标签用于注册Servlet,它包含有两个主要的子元素:servlet-name标签和servlet-class标签,分别用于设置Servlet的注册名称和Servlet的完整类名。

一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name>和<url-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。例如:

    <web-app>
        <servlet>
            <servlet-name>AnyName</servlet-name>
            <servlet-class>HelloServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>AnyName</servlet-name>
            <url-pattern>/demo/hello.html</url-pattern>
        </servlet-mapping>
    </web-app>

3、同一个Servlet可以被映射到多个URL上,即多个servlet-mapping标签的servlet-name标签子元素的设置值可以是同一个Servlet的注册名。

4、在Servlet映射到的URL中也可以使用通配符,但是只能有两种固定的格式:一种格式是“.扩展名”,另一种格式是以正斜杠(/)开头并以“/*”结尾。

    <servlet-mapping>
        <servlet-name>
            AnyName
        </servlet-name>
        <url-pattern>
            *.do
        </url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>
            AnyName
        </servlet-name>
        <url-pattern>
            /action/*
        </url-pattern>
    </servlet-mapping>

5、如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。

6、凡是在web.xml文件中找不到匹配的servlet-mapping标签的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。

7、在tomcat的安装目录标签\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。

8、当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet。

六、Servlet的生命周期

1、 a. Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。

b. 针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。

c. 在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。

2、如果在servlet标签中配置了一个load-on-startup标签,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。

举例:
<servlet>
    <servlet-name>invoker</servlet-name>
    <servlet-class>
        org.apache.catalina.servlets.InvokerServlet
    </servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>

*用途:为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据。

注意:从提高Servlet容器运行性能的角度出发,Servlet规范为Servlet规定了不同的初始化情形。如果有些Servlet专门负责在 web应用启动阶段为web应用完成一些初始化操作,则可以让它们在web应用启动时就被初始化。对于大多数Servlet,只需当客户端首次请求访问时 才被初始化。假设所有的Servlet都在web应用启动时被初始化,那么会大大增加Servlet容器启动web应用的负担,而且Servlet容器有 可能加载一些永远不会被客户访问的Servlet,白白浪费容器的资源。

  • 实验:

首先配置工程环境如下:

该工程下的web.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name>
  <!-- com.heima.servlet.Servlet1 Servlet1  = new com.heima.servlet.Servlet1()-->
  <servlet>
    <servlet-name>Servlet1</servlet-name>
    <servlet-class>com.heima.servlet.Servlet1</servlet-class>
    <load-on-startup>2</load-on-startup>
  </servlet>
  <servlet>
    <servlet-name>Servlet2</servlet-name>
    <servlet-class>com.heima.servlet.Servlet2</servlet-class>
    <load-on-startup>6</load-on-startup>
  </servlet>
  <servlet>
    <servlet-name>Servlet3</servlet-name>
    <servlet-class>com.heima.servlet.Servlet3</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>Servlet4</servlet-name>
    <servlet-class>com.heima.servlet.Servlet4</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>Servlet5</servlet-name>
    <servlet-class>com.heima.servlet.Servlet5</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>Servlet1</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--
         url的配置:
              1. 配置的时候是以/开头,不允许/*.do 此种情况
              2. 配置的时候是*开头,后面必须加后缀名
   -->
  <servlet-mapping>
    <servlet-name>Servlet2</servlet-name>
    <url-pattern>*.abcde</url-pattern>
  </servlet-mapping>    

  <servlet-mapping>
    <servlet-name>Servlet2</servlet-name>
    <url-pattern>/aaa/bbb</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Servlet3</servlet-name>
    <url-pattern>/servlet/Servlet3</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Servlet4</servlet-name>
    <url-pattern>/servlet/Servlet4</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Servlet5</servlet-name>
    <url-pattern>/servlet/Servlet5</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

Servlet1.java

import java.io.IOException;

import javax.servlet.GenericServlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class Servlet1 extends GenericServlet {

    public Servlet1() {
        System.out.println("servlet1");
    }

    @Override
    public void init() throws ServletException {
        System.out.println("aaaaaaaaaaaaa");
    }

//  @Override
//  public void init(ServletConfig config) throws ServletException {
//      System.out.println("init方法");
//  }

    @Override
    public void service(ServletRequest arg0, ServletResponse arg1)
            throws ServletException, IOException {
        System.out.println("service");
    }

    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

Servlet2.java

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

public class Servlet2 extends HttpServlet {

    public Servlet2() {
        System.out.println("bbbbbbbbbbbbbbbbb");
    }

    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        System.out.println("servletdemo2");
    }
}

在服务器初始化时,输出以下代码,可以发现在xml文档里配置的

<servlet-name>Servlet1</servlet-name>
<servlet-class>com.heima.servlet.Servlet1</servlet-class>
<load-on-startup>2</load-on-startup>

起效了,效果图如下:

在配置完tomcat后打开浏览器输入http://localhost:8080/day0702servlet/servlet/Servlet1

得到如下结果:

service

七、线程安全

1、当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。

2、如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。

3、SingleThreadModel接口中没有定义任何方法,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。

4、对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。

5、实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为Deprecated(过时的)。

结论:serlvet的线程安全(明白)

明确: Servlet的设计是一个单实例多线程。
线程安全要求将变量创建成一个局部变量,而不要创建成实例变量.

Servlet3.java

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.SingleThreadModel;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//演示线程安全问题
//单实例多线程
public class Servlet3 extends HttpServlet implements SingleThreadModel {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        int a = 0;
        a++;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(a);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doGet(req, resp);
    }
}

不断在浏览器内输入http://localhost:8080/day0702servlet/servlet/Servlet3

发现有以下反应:

资料下载

时间: 2024-10-25 12:45:07

JavaWeb-07(tomcat与web程序结构与Http协议与Servlet基础)的相关文章

题库 tomcat与web程序结构与Http协议与HttpUrlConnection

1.下面关于tomcat服务器描述正确的是() (难度A) A. tomcat是一个开源的免费的web服务器,它支持javaEE规范 B. tomcat不是一个开源的免费的web服务器,它支持servlet规范 C. tomcat是一个开源的免费的web服务器,它支持servlet规范 D. 以上说法都不对 答案:C 2.tomc安装成功后默认的端口是() (难度A) A. 80 B. 8888 C. 8080 D. 以上都不对 答案:C 3.访问tomcat部署的应用,出现404错误,原因是(

JavaWeb-06(Dom4j技术及Schema 约束、Tomcat与Web程序结构)

JavaWeb-06 JavaWeb-Dom4j技术及Schema 约束.Tomcat与Web程序结构 DOM4J及Schema 一.Dom4j解析(掌握) DOM4J解析XML文档 a. Dom4j是一个简单.灵活的开放源代码的库.Dom4j是由早期开发JDOM的人分离出来而后独立开发的.与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性. b. Dom4j是一个非常优秀的Java XML API,具有性能优异.功能强大和极

java web 程序---jsp连接mysql数据库的实例基础+表格显示

<%@ page language="java" import="java.util.*,java.sql.*" pageEncoding="gb2312"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <body> <center>JSP连接mysql数据库</

javaweb回顾第二篇tomcat和web程序部署

前言这篇主要说下关于tomcat中一些属性和web程序的简单部署,可能在实际开发有更好的部署方式,但是这也是一个基础. 1:tomcat 关于tomcat估计只要接触java的人都听过这个名字,那我们都知道Servlet运行的话需要一个运行环境,也就是我们常说的Servlet容器,那么tomcat就是一个免费开源的Servlet容器.做过.net开发的应该知道IIS,其实tomcat和IIS一样都是具有处理HTMl页面的能力,当然也能处理Servlet和jsp. 下面是一个tomcat服务器接收

基础知识回顾第二篇tomcat和web程序部署

前言这篇主要说下关于tomcat中一些属性和web程序的简单部署,可能在实际开发有更好的部署方式,但是这也是一个基础. 1:tomcat 关于tomcat估计只要接触java的人都听过这个名字,那我们都知道Servlet运行的话需要一个运行环境,也就是我们常说的Servlet容器,那么tomcat就是一个免费开源的Servlet容器.做过.net开发的应该知道IIS,其实tomcat和IIS一样都是具有处理HTMl页面的能力,当然也能处理Servlet和jsp. 下面是一个tomcat服务器接收

修改Tomcat默认web程序路径遇到的问题

线上前端是nginx反向到后边的两个tomcat的架构,在搭建tomcat的时候,由于自定义了tomcat的默认web数据存储路径,导致后来更新代码的时候出现了问题. 今天上线之后,由于程序有点儿问题,更改了一下,还没等重启tomcat服务,尼玛网站就打不开了,网站首页显示一个502的页面,手机立马收到了报警短信. 1).首先检查日志,查看这段儿时间的tomcat日志,报错如下: Sep 15, 2015 12:31:06 PM org.apache.catalina.loader.Webapp

tomcat部署web程序

* 如何部署WEB程序(三种)    * 项目复制到webapps目录下.         * 通过配置虚拟路径的方式.     * 直接修改配置文件      * 写到tomcat/conf/server.xml      * 找到<Host>标签,配置到Host标签的中间      * 目的:通过配置,配置访问路径,准确找到c:\bb的文件       * <Context docBase="文件夹的真实目录" path="虚拟路径(访问路径)"

Web 程序结构

一个 web 应用程序是由一组 Servlet,HTML 页面,类,以及其它的资源组成的运行在 web 服务器上的完整的应用程序,以一种结构化的有层次的目录形式存在 组成 web 应用程序的这些文件要部署在相应的目录层次中,根目录代表整个 web 应用程序的”根” 通常将 web 应用程序的目录放在 webapps 目录下,在 webapps 目录下的每一个子目录都是一个独立的 web 应用程序,子目录的名字就是 web 应用程序的名字,也就是 web 应用程序的“根”.用户通过 web 应用程

Tomcat配置Web程序几种方式

原文来自搬砖工,如需转载请注明出处 我们常用的是java的JDBC,因此这里就以JDBC为例总结一下java数据库操作常用的一些内容 一.数据库驱动加载 首先,我们知道JDBC是以java数据库驱动为主要实现机制进行数据库操作的,每个类型的数据库都有不同的数据库驱动.常用的数据库驱动加载如下:(驱动可到官网下载) 1.Oracle8/8i/9iO数据库(thin模式) Class.forName("Oracle.jdbc.driver.OracleDriver").newInstanc