HttpServlet介绍以及源码分析

d一、HttpServlet 是专门为 HTTP 协议服务的,比 GenericServlet 更适合在 HTTP 协议下开发

二、HttpServlet 在 javax.servlet.http.HttpServlet 包下

三、到目前为止我们接触到了哪些接口?

  • javax.servlet.Servlet                   核心接口
  • javax.servlet.ServletConfig        Servlet配置信息接口
  • javax.servlet.ServletContext      Servlet上下文环境接口
  • javax.servlet.GenericServlet      标准通用的Servlet类【抽象类】
  • javax.servlet.ServletRequest     Servlet 请求接口
  • javax.servlet.ServletResponse   Servlet 响应接口
  • javax.servlet.ServletException   Servlet 异常【类】

四、http 包下有哪些接口和类?javax.servlet.http.*

  •      javax.servlet.HttpServletServlet
  •      javax.servlet.HttpServletRequst
  •     javax.servlet.HttpServletResponse

五、HttpServletRequest 对象中封装什么信息 ?

        HttpServletRequest 简称 Request对象

        HttpServletRequest 封装了请求协议的全部内容。

        Tomcat 服务器(WEB服务器)将 "请求协议" 中的数据全部解析出来,然后将这些数据全部封装到 request 对象当中。

        也就是说,我们只要面向 HttpServletRequest ,就可以获取请求协议中的数据。

六、HttpServletResponse 对象是专门用来响应HTTP 协议到浏览器的

HttpServlet源码分析:

public class HelloServlet extends HttpServlet {

    //用户发送第一次请求时,Tomcat服务器会通过这个无参方法构造Servlet对象,看不见的
    // public  HelloServlet(){}
    //构建完对象,通过 init 方法 初始化。HttpServlet 中没有init 方法。继续调用父类 GenericServlet 类中的 init 方法
    // 下面不带参数的init 方法可供用户重写的 init 方法。
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }

    public void init() throws ServletException {
    }


    //HttpServlet 是一个模板类。

    public abstract class HttpServlet extends GenericServlet {
        //用户发送第一次请求时,Tomcat 会调用 service 方法,处理用户的请求。HttpServlet类中有俩个service方法。
        //首先会执行这个 service 方法。
        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
            HttpServletRequest request;
            HttpServletResponse response;
            try {
                //强转成带有 Http 类型的 Request 和 Response 。
                request = (HttpServletRequest) req;
                response = (HttpServletResponse) res;
            } catch (ClassCastException var6) {
                throw new ServletException(lStrings.getString("http.non_http"));
            }
            //然后调用重载之后的service方法
            this.service(request, response);
        }


        //重载之后service 方法。
        //模板类中的核心算法。
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //getMethod 返回的是:七种请求方式中的一种。注意:返回的是大写的
            String method = req.getMethod();
            long lastModified;
            //如果是GET 就执行doGet方法,是POST 就执行 doPost方法
            if (method.equals("GET")) {
                lastModified = this.getLastModified(req);
                if (lastModified == -1L) {
                    this.doGet(req, resp);
                } else {
                    long ifModifiedSince;
                    try {
                        ifModifiedSince = req.getDateHeader("If-Modified-Since");
                    } catch (IllegalArgumentException var9) {
                        ifModifiedSince = -1L;
                    }

                    if (ifModifiedSince < lastModified / 1000L * 1000L) {
                        this.maybeSetLastModified(resp, lastModified);
                        this.doGet(req, resp);
                    } else {
                        resp.setStatus(304);
                    }
                }
            } else if (method.equals("HEAD")) {
                lastModified = this.getLastModified(req);
                this.maybeSetLastModified(resp, lastModified);
                this.doHead(req, resp);
            } else if (method.equals("POST")) {
                this.doPost(req, resp);
            } else if (method.equals("PUT")) {
                this.doPut(req, resp);
            } else if (method.equals("DELETE")) {
                this.doDelete(req, resp);
            } else if (method.equals("OPTIONS")) {
                this.doOptions(req, resp);
            } else if (method.equals("TRACE")) {
                this.doTrace(req, resp);
            } else {
                String errMsg = lStrings.getString("http.method_not_implemented");
                Object[] errArgs = new Object[]{method};
                errMsg = MessageFormat.format(errMsg, errArgs);
                resp.sendError(501, errMsg);
            }

        }
    }
}

HttpServlet 类中的service方法并不是抽象的,由此可见我们是可以重写service方法的,但是享受不到 405 的错误提示。下面举例看看什么是 405 错误?

提供一个发送请求的 html 页面:

 重写doGet 和 doPost方法:

当前端发送的是 GET 请求,但是后端重写的是 doPost方法,所以他会执行父类HttpServlet 中的doGet方法。所以它会报 405 错误。

当前端发送的是 POST 请求,但是后端重写的是 doGet方法,也会报 405 错误。

以下是 HttpServlet 类中的doGet和doPost方法:通过源码可以看出来,只要一执行HttpServlet 中的doGet 或者 doPost 就会报405 错误

 怎么避免 405 呢?

        前端发送 GET 请求,后端重写 doGet 方法

        前端发送 POST 请求,后端重写 doPost方法

有的人可能会同时重写 doGet 和 doPost 方法,但是完全没有必要。还不如直接重写 service 方法。

当继承HttpServlet类时,重写 doGet 还是重写 doPost 由程序员说了算。

        

         

        

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鲨瓜2号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值