• JavaWeb-Servlet(一)


     一 Servlet(Server Applet)是Java Servlet的简称,是服务器小应用程序
      1)用来完成B/S架构下,客户端请求的响应处理
     
      2)平台独立,性能优良,能以线程方式运行
      3)Servlet API为Servlet提供了通用的编程接口
      4)Servlet一般在容器中运行,对外统一接口,由容器来调用。
        常见的Servlet容器:Tomcat
           
     二  TomcatServlet的关系
      上面说过,Servlet需要对外统一接口,那么谁来统一这些接口呢?这个时候就需要容器来调用。
      Tomcat是一个Web应用轻量级服务器,同时也是一个ServletJSP容器。其作为Servlet容器,有三种工作模式:独立的Servlet容器、进程内的Servlet容器和进程外的Servlet容器。

        web服务器收到客户端的Servlet访问请求后,若是服务器装载并创建了Servlet的实列对象

      1) Tomcat将http请求文本进行解析,然后封装称为HttpServletRequest类型的Requset对象

      2) Tomcat将要响应的信息封装为HttpServletResponse类型的response对象进行返回

     
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
         request;
        HttpServletResponse response;
        try {
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)res;
        } catch (ClassCastException var6) {
            throw new ServletException("non-HTTP request or response");
        }
    
        this.service(request, response);
    }

     三  创建一个Servlet

      3.1 Servlet的执行流程

        首先,如果浏览器由这样一个输入:http://localhost:8080/demo/MyServlet

      http:http协议 

          统一资源定位符URL。

            格式:<协议>://<主机>:<端口>/<路径>

      localhost:域名

      8080:Tomcat端口号

                

      demo:   web应用的名称,在webapps下找是否存在demo的目录。

      MyServlet:web资源,在demoweb的应用的应用下查找是否存在此资源。

        /MyServlet资源就是我们的一个Servlet 

            ->   得到/MyServlet字符串

            ->   使用/MyServlet到web.xml文件中查找每一个<servlet-mapping>下的<url-pattern>标签里的内容,然后得到sevlet-name

            ->   使用sevlet-name去servlet标签中找到对应的相同名称的servlet配置。

            ->   得到servlet配置中的servlet-class内容。     

    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

       3.2 DIEA开发Servlet

        1 新建JAVA EE Web Appication工程。

        2 新建一个Servlet类。

        3 导入需要依赖的tomcat目录下的servlet-api.jar包

              

      4  编写FirstServlet的代码.

      

    package javademo;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    public class FirstrServlet extends javax.servlet.http.HttpServlet {
        protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
    
        }
    
        protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
            response.setContentType("text/html");
            PrintWriter pw = response.getWriter();
            pw.write("<h1> hello first servlet!</h1>");
        }
    }
       

        5 编写web,xml配置文件 dom4j才能正确解析

    <servlet>
        <servlet-name>FirstrServlet</servlet-name>
        <servlet-class>javademo.FirstrServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FirstrServlet</servlet-name>
        <!-- 响应所有请求-->
        <url-pattern>/FirstrServlet</url-pattern>
    </servlet-mapping>
    
    
    

      3.3 详解Servlet实现原理

        3.3.1  servlet的生命周期是什么?

         服务器启动时(web.xml中配置load-on-startup=1,默认为0)或者第一次请求该servlet时,就会初始化一个Servlet对象,也就是会执行初始化方法init(ServletConfig conf)

              该servlet对象去处理所有客户端请求,在service(ServletRequest req,ServletResponse res)方法中执行

              最后服务器关闭时,才会销毁这个servlet对象,执行destroy()方法。

                

          

       3.3.2 为什么创建的servlet是继承自httpServlet,而不是直接实现Servlet接口?

      Servlet是一个接口,如果实现了这个接口,那么就必须实现接口里面定义的所有方法。

      我们来看HttpServlet源码:

       继承了HttpServlet实际上也就实现了Servlet接口,没有必要再去实现Servlet中的方法。HttpServlet在实现servlet接口时,已经实现了Servlet里面的所有方法,所以不用再去覆写对应的生命周期等方法。

          

       Servlet接口:

    public interface Servlet {
            
        //由Servlet容器调用,以指示将servlet放入服务器的servlet
        void init(ServletConfig var1) throws ServletException;
        //返回一个servlet对象,其中包含这个servlet初始化和启动参数。
        ServletConfig getServletConfig();
        //由servive调用,以允许servlet对请求做出响应
        void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
        //返回有关servlet的信息,如作者,版本和版权
        String getServletInfo();
        //由servlet容器调用,以只是servlet将排除在服务器之外
        void destroy();
    }

      ServletConfig接口:

     interface ServletConfig {
        String getServletName();
    
        ServletContext getServletContext();
    
        String getInitParameter(String var1);
    
        Enumeration<String> getInitParameterNames();
    }

      其中servletContext接口是Servlet中最大的一个接口,呈现了web应用的Servlet视图。获得ServletContext对象也就能得到我们需要的大部分信息。

      GenericServlet中有两个Init函数,一个有参数一个无参 。这样做是为什么呢?

      

      博主 一杯凉茶解释的很好:通过这几个方法一起来讲解,首先看init(ServletConfig config)方法,因为只有init(ServletConfig config)中带有ServletConfig对象,为了方便能够在其他地方也能直接使用ServletConfig对象,而不仅仅局限在init(ServletConfig config)方法中,所以创建一个私有的成员变量config,在init(ServletConfig config)方法中就将其赋值给config,然后通过getServletConfig()方法就能够获取ServletConfig对象了,这个可以理解,但是在init(ServletConfig config)中,158行,还调用了一个init()方法,并且这个init()方法是空的,什么读没有,这是为什么呢?这个原因是为了防止一件事情,当我们需要在init方法中做一点别的事情,我们想到的方法就是继承GenericServlet并且重写了init(ServletConfig config)方法,这样依赖,就破坏了原本在GenericServlet类中init(ServletConfig config)写的代码了,也就是在GenericServlet类中的成员变量config会一直是null,无法得到赋值,因为被重写了,就不会在执行GenericServlet中init(ServletConfig config)方法中的代码。要想赋值,就必须在重写的init(ServletConfig config)方法中调用父类的init(ServletConfig config)方法,也就是super.init(ServletConfig config),这样一来,就很不方便,怕有时候会忘了写这句代码,所以在GenericServlet类中增加一个init()方法,以后需要在init方法中需要初始化别的数据,只需要重写init()这个方法,而不需要去覆盖init(ServletConfig config)这个方法,这样设计,就好很多,不用在管    init(ServletConfig config)这个其中的内容了。也不用出现其他的问题。

      四  关于ServletConfig对象,ServletContext对象、request对象,response对象的学习。

       ServletConfig对象

          1)通过getServletConfig()获得。

          2)通过继承父类(GenericServlet)的方法得到一个ServletConfig对象

          

        功能:获取servletname context parameter initparameternames

    public interface ServletConfig {
        //获取web.xml中配置的Servlet-name
        String getServletName();
        //获取ServletContext对象 其中内容非常多
        ServletContext getServletContext();
        //获取在servlet中初始化参数的值。
        String getInitParameter(String var1);
        //返回类型是枚举型,获取在Servlet中所有初始化参数的名字。相当于有多个<init-param>
        Enumeration<String> getInitParameterNames();
    }
        

     

      Web.xml配置如下:

     运行结果如下:

     

      ServletContext对象

        获取:

          1)getServletContext()

          2)getServletConfig().getServletContext();

        功能:tomcat为每个web项目都创建一个ServletContext实列,主要是为了方便数据共享,让每个Servlet都可以访问到它。

       4.1 web项目中共享数据

      在一定范围内(当前应用),使多个Servlet共享数据

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

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

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

        实例如下:

        

     getServletContext().setAttribute("name1","value1");

      4.2 获取全局配置信息

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

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

        getInitParameterNames()  //获得枚举类型 上面说过的,多个servlet-name

      4.3 获取web项目资源

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

            String  getRealPath(String path);//根据资源名称得到资源的绝对路径

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

      

     public  void  test()throws IOException{
            InputStream in  = getServletContext().getResourceAsStream("/WEB-INF/web.xml");
            //统一编码才能正确进行输出
            InputStreamReader is = new InputStreamReader(in,"UTF-8");
            BufferedReader br = new BufferedReader(is);
            String s = null;
            while ((s = br.readLine())!=null)
            {
                System.out.println(s);
            }
    
        }

        结果如下,正是web.xml里面的配置内容

        4.3.4 实现Servlet的转发

        

    ServletContext sc = this.getServletContext();
    RequestDispacher rd = sc.getRequestDispacher("/转发页面");
    rd.forward(request,response);

      4.4 Request、Response

        4.4.1 request和response是什么?

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

        response是服务器根据请求进行的响应

          request

           包含:请求头,请求行,请求体。

        下面是一个实际的请求报文:

    ①是请求方法,HTTP/1.1 定义的请求方法有8种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE,最常的两种GET和POST,如果是RESTful接口(需要在WEB.XML中进行filter配置)的话一般会用到GET、POST、DELETE、PUT。
    ②为请求对应的URL地址,它和报文头的Host属性组成完整的请求URL
    ③是协议名称及版本号。
    ④是HTTP的报文头,报文头包含若干个属性,格式为“属性名:属性值”,服务端据此获取客户端的信息。
    ⑤是报文体,它将一个页面表单中的组件值通过param1=value1&param2=value2的键值对形式编码成一个格式化串,它承载多个请求参数的数据。不但报文体可以传递请求参数,请求URL也可以通过类似于“/chapter15/user.html? param1=value1&param2=value2”的方式传递请求参数。
      请求报文具有固定的结构格式:
      Request Headers
      设置::response.setHeader(java.lang.String name, java.lang.String value) 设置指定的头

      Accept:告诉服务器,客户机支持的数据类型

      Accept-Encoding:告诉服务器,客户机支持的数据压缩格式

      Cache-Control:缓存控制,服务器通过控制浏览器要不要缓存数据

      Connection:处理完这次请求,是断开连接还是保持连接

      Cookie:客户机通过这个可以向服务器带数据

      Host:访问的主机名

      Upgrade-Insecure-Requests:参考http://www.cnblogs.com/hustskyking/p/upgrade-insecure-requests.html

      User-Agent:告诉服务器,客户机的软件环境


      response也有与之对应的响应报文

       

     Response Headers响应头

      Connection:处理完这次请求后,是断开连接还是继续保持连接

        Content-Encoding:服务器通过这个头告诉浏览器数据的压缩格式

        Content-Length:服务器通过这个头告诉浏览器回送数据的长度

        Content-Type:服务器通过这个头告诉浏览器回送数据的类型

        Date:当前时间值

        Server:服务器通过这个头告诉浏览器服务器的类型

        Vary:Accept-Encoding ——明确告知缓存服务器按照 Accept-Encoding 字段的内容,分别缓存不同的版本;参考:https://imququ.com/post/vary-header-in-http.html

        X-Powered-By:服务器告知客户机网站是用何种语言或框架编写的。

         总结:搞懂基础性的东西才能让未来的路走的更远!

  • 相关阅读:
    robot 如何定义用户关键字、变量
    appium 启动参数配置
    mock模拟接口返回数据
    jenkins 中邮件发送
    python中正则表达式
    python中操作数据库
    pytest和unittest中参数化如何做
    learnku社区分享
    FOR ALL ENTRIES IN的使用
    BAPI_DELIVERYPROCESSING_EXEC
  • 原文地址:https://www.cnblogs.com/zqoceean/p/9343491.html
Copyright © 2020-2023  润新知