码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-03-31 22:34:46      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:javaweb

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

发现有以下反应:

技术分享


资料下载

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

标签:javaweb

原文地址:http://blog.csdn.net/faith_yee/article/details/44782745

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!