zoukankan      html  css  js  c++  java
  • Java-Servlet请求方式doXXX、service 具体分析

    说起Servlet的接收处理请求的方式,想必各位都并不陌生,如doGet、doPost、service...

    那么他们的背后是如何执行?服务器怎么选择知道的?我们就此来探讨一下

    本节案例的代码奉上:

    web.xml部分

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <servlet>
            <servlet-name>one</servlet-name>
            <servlet-class>cn.arebirth.servlet.MyServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>one</servlet-name>
            <url-pattern>/one</url-pattern>
        </servlet-mapping>
    </web-app>

    JSP部分

    <%--
      Created by IntelliJ IDEA.
      User: Arebirth
      Date: 2019/8/17
      Time: 15:00
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
          <form action="http://localhost:8080/ServletDemo_war_exploded/one" method="get">  <%--请求方式会改动--%>
            <label>Usercode:</label>
            <input type="text" name="name">
            <br/>
            <label>Password:</label>
            <input type="password" name="password">
            <br/>
            <input type="submit" value="Submit">
          </form>
      </body>
    </html>

    Servlet部分后续分析在具体展露。

    下面我们来简单的写下具体用法,在做具体分析

    doGet     相比不用说大家也都能见名知意,根据get的方式请求服务器

    前端method:get请求

    package
    cn.arebirth.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("MyServlet.doGet"); } }

    结果
      MyServlet:doGet

    doPost 方式同上doGet,请求方式改变了

    前端method:post请求

    package
    cn.arebirth.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class MyServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("MyServlet.doPost"); } }

    结果:
      MyServlet.doPost

    service  接收请求

    前端method:get or post方式皆可

    package
    cn.arebirth.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class MyServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("MyServlet.service"); } }

    结果:
      MyServlet.service

    正题来了前方高能!

    分析1:当我们以GET请求方式进行请求的时候,servlet中只有doPost会怎么样?

    package cn.arebirth.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class MyServlet extends HttpServlet {
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyServlet.doPost");
        }
    }

    Result:

      会报 HTTP Status 405-Method Not Allowed    405错误状态码  服务器不允许以此请求方式访问

    分析2:当我们以POST请求方式进行请求的时候,servlet中只有doGET会怎么样? 

    Result:

      同上,只是互换了一下还是会报405错误!

    分析3:当我们以GET or POST请求方式进行请求的时候,servlet中只有doPost or doGet 和 service方法 那么它会执行谁?

    //前端我们以get方式请求
    
    
    package cn.arebirth.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class MyServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyServlet.doGet");
        }
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyServlet.service");
        }
    }

    Result:

    结果是输出
    MyServlet.service

    明明我们是以get方式进行请求的,而且servlet中含有doGet方法,为什么走的确实service??这是一个初学者的坑,让我们来探究下吧!

    底层实现:我们的服务器在接受到请求的时候,servlet首先会查找是否service方法,因为servlet只认识service,原因看下图:

    我们底层的servlet接口里面只有service接口!所以当我们的服务器接收到请求的时候首先会查找是否有service方法,如果没有的话则会去父类中调用,

    分析4:我们就上面分析3中可以得知,如果没有servlet中没有重写service方法的话,那么它会调用父类的service方法,我们就此来分析

    前端以get方式进行请求
    
    package cn.arebirth.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class MyServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyServlet.doGet");
        }
        
    }

    Result:  

    结果输出的是:
      MyServlet.doGet

    我们来分析下执行原理:

      首先请求达到这个servlet的时候,会查找本方法中是否有重写了的service方法,没有的话,将执行父类HttpServlet中的service方法首先会调用HttpServlet中一个重载的service方法,用于接收request和response,然后把request和response传递给另一个注的service重载的执行方法

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
            HttpServletRequest 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);   //这里吧request请求参数和response响应参数传递给另一个重载的方法并调用
        }
    
    
    另一个重载的执行方法
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod();//首先获取请求方式 long lastModified;
      //接着判断请求方式,
    if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { this.doGet(req, resp); //如果是GET请求方式就会通过多态的方式调用者个doGet方式, } 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")) {//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); } }

    通过上面的底层代码我们可以得知,它的底层实际上是不会直接调用我们servlet中写的doGet或doPost方法,而是间接的通过service方法判断请求方式,然后在通过多态的方式调用具体的请求,还是那句话因为它只认识service方法!!!!

    分析4:当doGet or doPost和service方式同时存在,并且service方式中调用了父类的service方法,那么,它会得到什么结果??

    前端以get方式进行请求
    
    
    package cn.arebirth.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    public class MyServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyServlet.doGet");
        }
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("MyServlet.service");
            super.service(req, resp);
        }
    }

    Result:

    结果输出的是:
        MyServlet.service
        MyServlet.doGet

    这时有人就会说了,按照上面的例子来讲,如果有service方法存在的话,那么不就不会调用doGet or doPost了吗????

    朋友,别忘了service方法里面还有   super.service(req,reps)  这句代码!! 

    通过上面的底层分析,我们可以得知,它首先会执行我们重写的service方法里面的代码,然后遇见了super.service(req,reps)  ,这句代码是不是在调用父类HttpServlet的service方法??对吧。

    所以他会根据响应的请求的方式,然后通过多态的方式调用了我们servlet中重写的doGet or doPost方法,所以这样就会一并执行啦!!

    总结:

      servlet执行的时候值认识service方法,如过我们自己写的方法中没有service方法的话,那么它就会逐级往上面找直到找到service方法然后去执行,如:我们继承的HttpServlet抽象类,在它的里面找到了service方法之后,就会开始调用它的service方法,并根据响应的请求然后通过多态的方式调用相应的代码!

  • 相关阅读:
    js语法中一些容易被忽略,但会造成严重后果的细节
    第三方技术方案大集合,收集一些好用、有意思的方法、网站
    jQuery的Promise 这里介绍的很详细
    获取当月|目标月最后一天
    bootstrap ui样例
    正则校验数字格式,并只能保留两个小数
    新建指定长度的数组,填入内容,内容都为固定值
    mobx 学习笔记
    (二)Android 基本控件
    (一)初识Android
  • 原文地址:https://www.cnblogs.com/arebirth/p/javaservletreq.html
Copyright © 2011-2022 走看看