http协议以及Servlet

http协议以及Servlet

1.1 http协议

协议:是指双方按照一定的规则进行某种行为

http协议:(超文本传输协议)定义了浏览器域服务器之间的相互通信的规则

请求协议:浏览器端发送给服务器端

响应协议:服务器端发送给浏览器端


1.1.1 http之请求协议

请求格式如下,如果浏览器不按照这个格式服务器将无法识别

 

请求格式:

请求首行;

请求头信息;

空行;

请求体;


GET /javaWEB1/index.jsp HTTP/1.1 //请求方式为GET请求,路径是javaWEB1/index.jsp 协议版本1.1

Accept: text/html, application/xhtml+xml, */* //接受参数类型*/*表示所有

Accept-Language: zh-CN  //接受语言是中文

User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)  //浏览器版本,操作系统类型

Accept-Encoding: gzip, deflate  //接受编码,压缩以及解压缩

Host: localhost:8888   //主机名称 

Connection: Keep-Alive //连接状态  存活

Cookie: JSESSIONID=03A34AAB1E01103D443520A7F0B88DC5 //后面再讲

//空格

 

1、GET/javaWEB1/index.jsp HTTP/1.1 //请求方式为GET请求,路径是javaWEB1/index.jsp 协议版本1.1

2、Host:localhost:8888   请求主机名为localhost,端口号为8888

3、User-Agent  发送一些关于浏览器的信息给服务器,例如浏览器版本,操作系统的版本等。



1.1.2 http之响应协议

响应协议格式如下:

响应首行;

响应头信息;

空行;

    响应体。

 

在刚才的JavaWEB中服务器响给浏览器的内容如下

HTTP/1.1 200 OK  //协议版本  状态码  状态码的解释

Server: Apache-Coyote/1.1  //服务器名称

Content-Type: text/html;charset=UTF-8 //文本类型以及编码

Content-Length: 619  //文本大小

Date: Thu, 08 Jun 2017 02:58:18 GMT  //时间

//空格

 

 

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">//响应体

<html>

 ............响应具体内容........

</html>

1、HTTP/1.1 200OK:表示协议版本号为1.1版本,状态码为200,表示请求成功,OK是对状态码的解释

2、Server:Apache-Coyote/1.1:服务器的名称

3、Content-Type:text/html;charset=UTF-8:响应文本类型以及编码格式

响应协议状态码所表示的含义:

200:表示请求成功

404:表示资源路径没有找到

405:请求的方式有问题(get、post等)

500:表示服务器的错误

302:表示重定向(服务器没有资源,提供一个url地址给浏览器访问)

 

 

1.2 Servlet组件

Servlet是我们JavaWeb三大组件之一,(Servlet和filter、listener),Servlet属于动态资源,服务器将浏览器发出的请求交给servlet来处理。接收请求数据,处理请求信息,完成响应。




一句话总结:servlet处理浏览器的请求,并且处理请求然后完成对浏览器的响应

注意:

一个功能的Servlet只能被Tomcat创建一次,很多次访问都是访问同一个Servlet(线程不安全)

 

实现Servlet的三种方式:

1.实现Servlet接口

2.继承GenericServlet类

3.继承HttpServlet类(重点掌握,常用)



1.2.1 Servlet接口

1.2.1.1 Servlet的实现方法

我们在新建类时实现Servlet接口,将会在servlet中实现如下方法

 

@Override

   public void destroy() {

   }

 

   @Override

   public ServletConfig getServletConfig() {

      return null;

   }

 

   @Override

   public String getServletInfo() {

      return null;

   }

 

   @Override

   public void init(ServletConfig arg0) throws ServletException {

   }

 

   @Override

   public void service(ServletRequest arg0, ServletResponse arg1)

          throws ServletException, IOException {

   }

 

注意:

在servlet大部分的方法都是由服务器,即tomcat来调用,并且方法中的类类型参数,也就是对象也是由服务器来创建,服务器已经将固化代码写入,我们只需写其中的逻辑实现,直接使用即可。


1.2.1.1.1 Servlet中的生命周期

Method Summary

 void

destroy()  ---销毁,服务器关闭时调用此方法
          由servlet容器调用,以指示servlet被停用的servlet。

 ServletConfig

getServletConfig()
          返回一个ServletConfig对象,该对象包含该servlet的初始化和启动参数。

String

getServletInfo()
          返回有关servlet的信息,如作者、版本和版权。

 void

init(ServletConfig config)  ---初始化,浏览器第一次访问servlet时调用
          由servlet容器调用,以指示servlet被放置到服务中的servlet。

 void

service(ServletRequest req,ServletResponse res)
          由servlet容器调用,以允许servlet响应请求。

 

void init(ServletConfig config) 在Servlet被创建后,服务器会马上调用Servlet的void init(ServletConfig)方法。 Servlet出生后马上就会调用init()方法,而且一个Servlet的一生。这个方法只会被调用一次。(该方法里面会放一些初始化的参数)

服务器会在servlet第一次被调用时来创建servlet对象,并且一个servlet只被创建一个对象

 

 

void service(ServletRequest req,ServletResponse res) 用于处理浏览器请求的,服务器接受一次请求就会调用一次service();--每次访问都会调用一次

 

void destroy() :在服务器关闭时Servlet才会离去!在服务器被关闭时,服务器会去销毁Servlet,在销毁Servlet之前服务器会先去调用Servlet的destroy()方法。(释放一些非内存资源,比如IO流的关闭,但是通常不会将其放在这个方法中)



1.2.1.1.2 Servlet中的参数

1、ServletConfig一个ServletConfig对应一段web.xml文件中的<servlet>元素每个servlet都有自己的ServletConfig

ServletConfig对象对应web.xml文件中的<servlet>元素。例如你想获取当前Servlet在web.xml文件中的配置名,那么可以使用servletConfig.getServletName()方法获取!

ServletConfig本身来讲是一个接口,具体的实现类是由tomcat来完成的,这并不是我们所关心的问题

ServletConfig中提供方法有

Method Summary

String

getInitParameter(java.lang.String name)
          获取带有给定名称的初始化参数的值。

Enumeration<java.lang.String>

getInitParameterNames()
         返回servlet初始化参数的名称作为字符串对象的枚举,或者如果servlet没有初始化参数,则返回空的枚举。

 ServletContext

getServletContext()
          返回调用者正在执行的ServletContext的引用。

String

getServletName()
          返回该servlet实例的名称。

 

1.getInitParameter( String name) 可以获取初始化参数值

2.getInitParameterNames() 获得一个存有所有param-name值的枚举集合

3.getServletContext() 获取上下文

4.getServletName() 获取servlet名称(不用)



web.xml文件配置:

  <servlet>

    <servlet-name>BServlet</servlet-name> //表示给该servlet一个名字用于标识

    <servlet-class>com.edu118.servlet.BServlet</servlet-class> //servlet所在的路径

    <init-param>

      <param-name>p1</param-name>

      <param-value>v1</param-value>

    </init-param>

    <init-param>

      <param-name>p2</param-name>

      <param-value>v2</param-value>

    </init-param>

  </servlet>

  <servlet-mapping>

    <servlet-name>BServlet</servlet-name>

    <url-pattern>/BServlet</url-pattern> //映射一个URL地址让浏览器访问,必须以“/”开始对命名规范没有要求

 

  </servlet-mapping>

 

<!--浏览器访问地址:http://localhost:8080/day02/BServlet -->

 

public void init(ServletConfig config)throws ServletException {

      String parameter = config.getInitParameter("p1");

      System.out.println(parameter);

      System.out.println("---------------");

     

      Enumeration<String> parameterNames =config.getInitParameterNames();

      //迭代器遍历

      while(parameterNames.hasMoreElements()){

         System.out.println(config.getInitParameter(parameterNames.nextElement()));

      }

   }

结果:

v1

---------------

v1

v2

 

2、ServletRequestServletResponse是Servlet#service() 方法的两个参数,一个是请求对象,一个是响应对象,可以从ServletRequest对象中获取请求数据,可以使用ServletResponse对象完成响应。你以后会发现,这两个对象就像是一对恩爱的夫妻,永远不分离,总是成对出现

 

Request

a)       String s = httprquest.getLocalAddr();  --获取浏览器访问服务器的ip地址

b)      String name = httprquest.getMethod(); --获取访问的方式(get或post等)

 

Response

a)    getWriter():获取字符响应流,使用该流可以向客户端输出响应信息。例如response.getWriter().print(“<h1>HelloJavaWeb!</h1>”);

b)    void setCharacterEncoding(String encoding):用来设置字符响应流的编码


1.2.2 GenericServlet类

源码

 

public abstract class GenericServlet implements Servlet, ServletConfig,

        java.io.Serializable {

 

    private static final long serialVersionUID = 1L;

 

private transient ServletConfig config;

 

    public GenericServlet() {

        // NOOP

    }

    @Override

    public void destroy() {

        // NOOP by default

    }

    @Override

    public String getInitParameter(Stringname) {

        return getServletConfig().getInitParameter(name);

}

 

    @Override

    public Enumeration<String> getInitParameterNames() {

        return getServletConfig().getInitParameterNames();

    }

    @Override

    public ServletConfig getServletConfig() {

        returnconfig;

    }

    @Override

    public ServletContext getServletContext() {

        return getServletConfig().getServletContext();

    }

 

 

 

    @Override

    public String getServletInfo() {

        return"";

}

 

    @Override

    public void init(ServletConfig config)throws ServletException {

        this.config =config;

        this.init();

    }

 

    public void init() throws ServletException {

        // NOOP by default

    }

 

 

    public void log(String msg) {

        getServletContext().log(getServletName() + ": " + msg);

    }

    public void log(String message, Throwablet) {

        getServletContext().log(getServletName() + ": " + message, t);

    }

 

 

    @Override

    public abstract void service(ServletRequestreq, ServletResponse res)

            throws ServletException, IOException;

 

    @Override

    public String getServletName() {

        returnconfig.getServletName();

    }

}

 

模拟GenericServlet类

public class EServlet implements Servlet {

   //定义一个全局变量,使继承EServlet的类都可以使用

   private ServletConfigconfig;

   //初始化

   public void init(ServletConfig config)throws ServletException {

      this.config =config;

      /*

       * init初始化进行补充,让继承EServlet的类可以再次实现对servlet的初始化

       * 并且不影响config这个变量

       */

      init();

   }

  

   public void init() {

 

   }

   //重写ServletConfig接口中的方法

   //对接口中的方法进行实现

   public Enumeration<String> getInitParameterNames() {

      return getServletConfig().getInitParameterNames();

     

   }

  

   public String getInitParametername(Stringname){

      return getServletConfig().getInitParameter(name);

   }

  

   public ServletContext getServletContext(){

      return getServletConfig().getServletContext();

     

   }

  

   public String getServletName(){

      return getServletConfig().getServletName();

   }

   public ServletConfig getServletConfig() {

      // TODO Auto-generated method stub

      return null;

   }

 

   public void service(ServletRequest req, ServletResponseres) throws ServletException, IOException {

      // TODO Auto-generated method stub

     

   }

 

   public String getServletInfo() {

      // TODO Auto-generated method stub

      return null;

   }

 

   public void destroy() {

      // TODO Auto-generated method stub

     

   }

  

}


1.2.3 HttpServlet类

HttpServlet是对GenericServlet的一个继承,它除了有GenericServlet的service(ServletRequest,ServletResponse)方法之外,还有自身的service(HttpServletRequest,HttpServletResponse)来对Http协议的支持。

 

protected  void

service(HttpServletRequest req,HttpServletResponse resp)
          Receives standard HTTP requests from the public service method and dispatches them to thedoXXX methods defined in this class.

 void

service(ServletRequest req,ServletResponse res)
          Dispatches client requests to the protected service method.

 

 

Httpservlet的工作流程如下:

1.浏览器发出请求,服务器首先会运行生命周期方法service

2.然后将service(ServletRequest,ServletResponse)强转为支持http的servlet

3.获取请求方法,根据请求方式来调用doGet还是doPost方法(这两个方法是由我们自己来覆盖的,需要注意的是当请求方式在servlet没有对应的方法复写会出现405错误)



1.3 ServletContext域

ServletContext是JavaWeb四大域之一,每一个项目都有且只有一个ServletContext,作用范围是整个web项目用于不同的servlet之间进行通信的。可以在不同的servlet中来获取这个ServletContext从而到达共享数据的目的,在服务器启动的时候被创建,在服务器关闭的时候被销毁。




1.3.1 ServletContext域对象的获取

因为我们新建的servlet类都是继承自HttpServlet类,而HttpServlet类继承自GnericServlet类,GenericServlet类中有getServletContext()的方法来获取ServletContext对象。所以可以直接使用this.getServletContext()获取


1.3.2 ServletContext的域功能

四个功能方法:

 

1、voidsetAttribute(String name,Object value):

void setAttribute(String name,Object value):存储数据

设置域属性以及域属性的值。域属性的名称为name,域属性的值为value。如果多次调用该方法设置相同的name域属性名称,那么会覆盖上一次设置的值。

 

2、ObjectgetAttribute(String name):

Object getAttribute(String name):获取数据

    通过域属性的名称name获取对应的域属性值value,如果域对象中没有该域属性,会自动帮你创建该域属性。-->String value =(String)ServletContext.getAttribute(name);

 

3、voidremoveAttribute(String name):

void removeAttribute(String name):用来移除ServletContext对象中的域属性

 

4、Enumeration<String>getAttributeNames():

Enumeration<String> getAttributeNames():获取所有域属性的名称。

    返回的是一个枚举集合,通过迭代器进行迭代。使用方法与Vector的迭代方式一样。




1.3.3 ServletContext获取资源的相关路径

1.3.3.1 获取真实路径

String getRealPath(): 获取与给定的虚拟路径相对应的真实路径。

 

获取a.txt的真实路径:

String realPath= servletContext.getRealPath(“/a.txt”);

(realPath的值为a.txt文件的绝对路径:F:\tomcat6\webapps\hello\a.txt;)



1.3.3.2 获取资源流

获取a.txt资源流:

InputStream in =servletContext.getResourceAsStream(“/a.txt”);

 

获取b.txt资源流:

InputStream in =servletContext.getResourceAsStream(“/WEB-INF/b.txt”);

 

获取指定目录下所有资源路径:

Set set =context.getResourcePaths("/WEB-INF");

       System.out.println(set);

 

注意本方法必须以“/”开头!!!

 

访问网站统计访问量的小案例:

@Override

   protected void doGet(HttpServletRequest req, HttpServletResponseresp) throws ServletException, IOException {

      // 获得ServletContext域对象

      ServletContext context =this.getServletContext();

      // 获得一个属性,如果这个属性没有就自动帮你创建

      Integer countNum = (Integer)context.getAttribute("count");

      // 判断是否是第一次访问网站

      if (countNum ==null) {

          //设置属性值

          context.setAttribute("count", 1);

//        count = (Integer)context.getAttribute("count");

      } else {

          context.setAttribute("count",countNum++);

      }

      //更新了属性值然后重新赋值

      countNum = (Integer)context.getAttribute("count");

      // 输出一下

      System.out.println(countNum);

      PrintWriter writer = resp.getWriter();

      writer.println("<h1>" +countNum + "</h1>");

   }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章