Servlet深入学习(一)——生命周期、service方法、ServletConfig、ServletContext、request、response对象

Servlet生命周期

服务器启动时(web.xml中配置load-on-startup=1,默认为0)或者第一次请求该servlet时,就会初始化一个Servlet对象,也就是会执行初始化方法init(ServletConfig conf),将其加载进内存并在内存中驻留,该servlet对象去处理所有客户端请求,在service(ServletRequest req,ServletResponse res)方法中执行。最后服务器关闭时,才会销毁这个servlet对象,执行destroy()方法。

整个生命周期如下图所示

demo: 

package com.company;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "HttpServlet",urlPatterns = {"/My"})
public class MyServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
    
    @Override
    public void init() throws ServletException {
        System.out.println("servlet初始化完成");
    }
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Hello Servlet");
    }

    @Override
    public void destroy() {
        System.out.println("servlet被销毁了");
    }

}

Servlet生命周期总结:

  •  1.从第一次调用到服务器关闭
  • 2.如果Servlet在web.xml中配置了load-on-startup方法(注解同理),生命周期为从服务器启动到服务器关闭
@WebServlet(name = "HttpServlet",urlPatterns = {"/My"},loadOnStartup = 1) 
//1表示第一个被加载

注意:

  • load-on-startup用途:  为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据
  • init方法是对Servlet进行初始化的一个方法,会在Servlet第一次加载进内存时调用
  • destroy方法是在Servlet被销毁时调用

service方法和doGet、doPost

参考这篇文章3.3,讲解的很全面

简单的说,由下图继承关系可以看到GenericServlet大概实现了Servlet接口,并且通过实现ServletConfig接口可以让我们直接获取servlet信息和ServletContext对象(而不是先获得servletconfig对象,再获得servletcontex对象),从而就能获取大部分我们需要的信息,比如获取servlet的路径,等方法。

对于init方法,通过在初始化config时通过添加init的空方法,可以使得原有的config信息不被覆盖,还可以通过init方法进行用户自定义初始化。

另外,对于service方法,service(HttpServletRequest req, HttpServletResponse resp)方法和service(ServletRequest req, ServletResponse res)方法。

service(ServletRequest req, ServletResponse res)方法

                        

该方法中就是将ServletRequest和ServletResponse这两个对象强转为HttpServletRequest和HttpServletResponse对象。

   

     

通过图可以得知,req的继承结构:RequestFacade、httpServletRequest、ServletRequest,我们知道本身req是ServletRequest,那么从继承结构上看,它也可以看成HttpServletRequest,也可以看成ServletRequest,所以强转为HttpServletRequest是可以的,如果不明白,我举个例子,ArrayList、List、Object 这个,Object obj = new ArrayList();  List list = new ArrayList();  一个ArrayList对象可以看成List对象, 也可以看成一个Object对象,现在obj是不是可以堪称List对象呢?答案是可以的,因为obj就是ArrayList对象,既然是ArrayList对象,那么就可以看成是List对象。一样的道理,RequestFacade 对应 ArrayList、httpServleRequest对应 List、 ServletRequest 对应 Object。

转换为httpServletRequest和HttpServletResponse对象之后,再调用service(HttpServletRequest req, HttpServletResponse resp)方法。service(HttpServletRequest req, HttpServletResponse resp)

这个方法就是判断浏览器过来的请求方式是哪种,每种的处理方式不一样,我们常用的就是get,post,并且,我们处理的方式可能有很多的内容,所以,在该方法内会将get,post等其他5种请求方式提取出来,变成单个的方法,然后我们需要编写servlet时,就可以直接重写doGet或者doPost方法就行了,而不是重写service方法,更加有针对性。所以这里就回到了我们上面编写servlet时的情况,继承httpServlet,而只要重写两个方法,一个doGet,一个doPost,其实就是service方法会调用这两个方法中的一个(看请求方式)。

几个重要对象ServletConfig、ServletContext,request、response

ServletConfig

直接拷贝的https://www.cnblogs.com/whgk/p/6399262.html

获取途径:getServletConfig(); 

功能:上面大概提及了一下,能得到四个东西,

              

getServletName();  //获取servlet的名称,也就是我们在web.xml中配置的servlet-name

getServletContext(); //获取ServletContext对象,该对象的作用看下面讲解

getInitParameter(String); //获取在servlet中初始化参数的值。这里注意与全局初始化参数的区分。这个获取的只是在该servlet下的初始化参数

                

 getInitParameterNames(); //获取在Servlet中所有初始化参数的名字,也就是key值,可以通过key值,来找到各个初始化参数的value值。注意返回的是枚举类型

             

                

                

注意:在上面我们所分析的源码过程中,我们就知道,其实可以不用先获得ServletConfig,然后在获取其各种参数,可以直接使用其方法,比如上面我们用的ServletConfig().getServletName();可以直接写成getServletName();而不用在先获取ServletConfig();了,原因就是在GenericServlet中,已经帮我们获取了这些数据,我们只需要直接拿就行。

ServletContext

获取途径:getServletContext(); 、getServletConfig().getServletContext();  //这两种获取方式的区别就跟上面的解释一样,第一种是直接拿,在GenericServlet中已经帮我们用getServletConfig().getServletContext();拿到了ServletContext。我们只需要直接获取就行了,第二种就相当于我们自己在获取一遍,两种读是一样的。

功能:tomcat为每个web项目都创建一个ServletContext实例,tomcat在启动时创建,服务器关闭时销毁,在一个web项目中共享数据,管理web项目资源,为整个web配置公共信息等,通俗点讲,就是一个web项目,就存在一个ServletContext实例,每个Servlet读可以访问到它。

1、web项目中共享数据,getAttribute(String name)、setAttribute(String name, Object obj)、removeAttribute(String name)

setAttribute(String name, Object obj) 在web项目范围内存放内容,以便让在web项目中所有的servlet读能访问到

getAttribute(String name) 通过指定名称获得内容

removeAttribute(String name) 通过指定名称移除内容   

                   

                     

                    

2、整个web项目初始化参数 //这个就是全局初始化参数,每个Servlet中都能获取到该初始化值

getInitPatameter(String name)  //通过指定名称获取初始化值

getInitParameterNames()  //获得枚举类型

web.xml 配置 整个web项目的初始化

                      

                      

                      

3、获取web项目资源

3.1获取web项目下指定资源的路径:getServletContext().getRealPath("/WEB-INF/web.xml")

                    

                    

3.2获取web项目下指定资源的内容,返回的是字节输入流。InputStream getResourceAsStream(java.lang.String path)

前提知识:需要了解流。不知道的可以去看看IO流总结的文章

                    

                    输出内容截图一部分

                    

4、getResourcePaths(java.lang.String path)  指定路径下的所有内容。

                    

                    

                    

5还有很多别的方法,暂时用到的就这几个了,以后需要在用的,就查看源码,看API。

request

request就是将请求文本封装而成的对象,所以通过request能获得请求文本中的所有内容:请求行、请求头、请求体 。

获得请求行信息:

package com.company;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

@WebServlet(name = "HttpServlet",urlPatterns = {"/My"})
public class MyServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求头数据
            //获得请求方式
            String method = request.getMethod();
            System.out.println(method);  //GET
            //获得请求URL(统一资源定位符)
            StringBuffer url = request.getRequestURL();
            System.out.println(url);  //http://localhost:8888/JavaWeb/My
            //获得请求URI(统一资源标记符)
            String uri = request.getRequestURI();
            System.out.println(uri);  ///JavaWeb/My
            //获取协议
            String scheme = request.getScheme();
            System.out.println(scheme);  //http
    }
}

获得请求头信息:

//获得请求头数据
            //获得所有请求行键的枚举
            Enumeration e = request.getHeaderNames();
            while (e.hasMoreElements()){
                String key = (String) e.nextElement();
                String values = request.getHeader(key);
                System.out.println(key+":"+values);
            }
            //获取指定的请求行信息
            String value = request.getHeader("host");
            System.out.println(value);

 

 获得请求体(用户数据):

get请求参数:http://localhost:8080/test01/MyServlet?uname=jack&password=1234

post请求参数: <form method="post"><input type="text" name="username">

String request.getParameter(String) 获得指定名称,一个请求参数值。

String[] request.getParameterValues(String) 获得指定名称,所有请求参数值。例如:checkbox、select等

Map<String , String[]> request.getParameterMap() 获得所有的请求参数

Enumeration request.getParameterNames()  //返回用户所有请求数据的枚举集合

因为需要用到jsp的知识,所以先知道如何获取请求体,之后会介绍jsp

response

用来响应数据到浏览器的一个对象

package com.company;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "HttpServlet",urlPatterns = {"/My"})
public class MyServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置响应编码格式
        response.setContentType("text/html;charset=utf-8");  //告诉浏览器如何解析响应结果
        //设置响应行
            //设置响应头
            response.setHeader("key","value");
            //添加响应头
            response.addHeader("key1","value1");
            response.addHeader("key1","value2");  //键可以重复
            //设置响应状态码
            /*response.sendError(404,"sorry");*/  //自定义响应状态码
        //设置响应实体
            PrintWriter pw = response.getWriter();
            pw.println("<h3>今天适合学习</h3>");
    }

}


请求处理代码流程总结

  • 1.设置响应编码格式
  • 2.获取请求数据
  • 3.处理请求数据
  • 4.响应处理结果

猜你喜欢

转载自blog.csdn.net/weixin_39722922/article/details/88944688