【JavaWeb】Servlet

50 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

Servlet

Servlet的继承关系

  1. 继承关系

    • javax.servlet.Servlet接口
      • javax.servlet.GenericServlet抽象类
        • javax.servlet.http.HttpServlet抽象子类
  2. 相关方法 - 重点查看服务方法。

    • javax.servlet.Servlet接口:

        void init(config) - 初始化方法
             //客户端发送请求,service方法自动执行。
           void service(requst,response) - 服务方法
           void destory() - 销毁方法
      
    • javax.servlet.GenericServlet抽象类: void service(requst,response) - 仍然是抽象方法

    • javax.servlet.http.HttpServlet抽象类: void service(requst,response) - 不是抽象方法

      service方法执行流程:

      1. String method = req.getMethod(); 获取请求的方式。
      2. 判断,根据请求方式不同,决定调用不同do方法。 java if (method.equals("GET")) { this.doGet(req, resp); } else if (method.equals("HEAD")) { this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } doPost方法: protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String msg = lStrings.getString("http.method_post_not_supported"); this.sendMethodNotAllowed(req, resp, msg); } sendMethodNotAllowed方法: private void sendMethodNotAllowed(HttpServletRequest req, HttpServletResponse resp, String msg) throws IOException { String protocol = req.getProtocol(); if (protocol.length() != 0 && !protocol.endsWith("0.9") && !protocol.endsWith("1.0")) { resp.sendError(405, msg); } else { resp.sendError(400, msg); }

小结: 1)继承关系:HttpServlet-> GenericServlet-> Servlet 2)Servlet中核心方法:init() 、service()、destory() 3)服务方法:当有请求过来时,service方法会自动响应(其实是tomcat容器调用的) 在HttpServlet中的service方法会分析发送请求的方式:到底是get、post还是...然后再决定调用哪个do方法。 在HttpServlet中这些do方法都是405的实现风格,所以要我们子类去实现对应的方法,否则默认会报405。 4)因此,在新建Servlet时,会考虑请求方法,从而决定重写哪个do方法。

Servlet生命周期

JavaWeb_02——DemoServlet02

  1. 生命周期:从出生到死亡的过程就是生命周期。对应Servlet中的三个方法:init()、service()、destroy()
  2. 默认情况下,第一次接收请求:Servlet实例化(调用构造方法)、初始化(调用init)、服务(调用service)。 从第二次请求开始:每一次都是服务。 当容器关闭:销毁服务。
  3. Servlet实例tomcat只会创建一个,所有的请求都通过这个实例去响应。 好处:提高系统的启动速度。 缺点:第一次请求时耗时较长。 如果需要提高第一次请求的响应速度,应该设置Servlet初始化时机。
  4. Servlet的初始化时机: 可以通过<load-on-startup>来设置servlet的启动先后顺序,数字越小,启动越靠前。
  5. Servlet在容器中是单例的(只有一个servlet实例去响应线程)、线程不安全的。 所以:不要在servlet中定义成员变量。如果不得不定义成员变量的值,不要去修改值或做逻辑判断。

HTTP协议

  1. HTTP称为超文本传输协议。

  2. Http是无状态的。

  3. Http请求响应包含两个部分:请求 request 和 响应 response。

    • 请求:
    1. 请求行:包含请求方式、访问地址url、HTTP协议的版本。

    2. 请求(消息)头:包含很多客户端需要告诉服务器的信息,比如:浏览器型号,版本,可以接收内容的类型。

    3. 请求主体: get方式:没有请求体,但是有一个queryString。 post方式:有请求体,form data。 json格式:有请求体,request payload

    • 响应:
    1. 响应行:包含协议、响应状态码(200)、响应状态(ok)
    2. 响应头:包含服务器的信息。
    3. 响应体:响应的实际内容(比如等)

常见Http响应状态码: 404:找不到对应的资源。 405:当前请求的方法不支持。 500:没有找到数据库驱动/driver、url错误。为数据库内部错误。 200:正常访问。 302:客户端重定向

session会话

JavaWeb_02——DemoServlet03

因为Http协议是无状态的,服务器无法判断两次请求是否都由同一客户端发出。 所以通过会话跟踪技术来解决无状态问题。

  • 会话跟踪技术

    客户端第一次发请求给服务器,服务器获取session,获取不到,则创建新的sessionID。响应给客户端。下次客户端发送请求时,会把session带给服务器,那么服务器就可以判断是哪台客户端。

  • 常用API

    //获取当前会话,如果没有创建一个新的会话。
    request.getSession();
    request.getSession(true);
    //获取当前会话,如果没有返回null。
    request.getSession(false);
    //获取会话ID
    session.getId();
    //判断当前session是否是新的
    session.isNew();
    //获取/设置session的最大非激活间隔时长,默认1800秒
    session.getMaxInactiveInterval();
    session.setMaxInactiveInterval(16000);
    //强制让会话失效
    session.invalidate();
    
    //向session的保存作用域中保存数据
    session.setAttribute(key,value);
    //读取session保存作用域中key对应的value。
    session.getAttribute(key);
    
  • session保存作用域 JavaWeb_02——DemoServlet04/05

    session保存作用域是和具体的某一个sessionID对应的。

    比如下图:浏览器通过demo04向服务器发送请求,获得了一个sessionID并且通过session.setAttribute(key,value);在保存作用域保存了数据。

    那么只要sessionID一致,都可以通过session.getAttribute(key);直接获取保存作用域的数据。 在这里插入图片描述

服务器内部转发及客户端重定向

JavaWeb_02——DemoServlet06/07

  • 服务器内部转发: API:req.getRequestDispatcher("demo07").forward(req,resp); 是一次请求响应的过程,对于客户端而言,内部经过了多少次转发,客户端不知道。 在这里插入图片描述
  • 客户端重定向: API:resp.sendRedirect("demo07"); 两次请求响应的过程,客户端知道请求的url有变化。 在这里插入图片描述