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方法,并根据响应的请求然后通过多态的方式调用相应的代码!
Java-Servlet请求方式doXXX、service 具体分析的更多相关文章
- 航信电子发票开发(servlet请求方式)
在系统用户交费后,需要打印发票,可以选择普票或者机打票(票据信息在系统中自定义设置的),也可以打印电子发票,这里对接的是航信的电子发票,请求方式非web服务,而是使用servlet通过HTTP请求的方 ...
- Java Servlet(四):Servlet接口service工作(ServletRequest,ServletResponse对象)(jdk7+tomcat7+eclipse)
本篇将会记录,Servlet接收客户端传递来的参数信息,并返回信息使用的对象,及这些对象的函数相关用法. 还是在java ee工程中进行操作,在WebContent目录下创建一个login.jsp文件 ...
- Java项目打包方式分析
[TOC] 概述 在项目实践过程中,有个需求需要做一个引擎能执行指定jar包的指定main方法. 起初我们以一个简单的spring-boot项目进行测试,使用spring-boot-maven-plu ...
- Java Servlet (1) —— Filter过滤请求与响应
Java Servlet (1) -- Filter过滤请求与响应 版本: Java EE 6 参考来源: Oracle:The Java EE 6 Tutorial: Filtering Reque ...
- [1.6W字] 浏览器跨域请求限制的详细原理分析&寻找一种最简单的方式实现XHR跨域(9种方法, 附大招可以纯前端实现跨域!)
Title/ 浏览器跨域(CrossOrigin)请求的原理, 以及解决方案详细指南 #flight.Archives011 序: 最近看到又有一波新的创作活动了, 官方给出的话题中有一个" ...
- Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 [ 转载 ]
Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 @author Trinea 原文链接:http://www.trinea.cn/android/arrayl ...
- Servlet请求参数的方式
今天整理了以下几种常用的Servlet请求参数的方式,下面简单地介绍 1)getParameter(String key)返回一个字符串,获得name和key 一样的表单控件的数据,如果有重复的nam ...
- Java Servlet完全教程
Servlet 是一些遵从Java Servlet API的Java类,这些Java类可以响应请求.尽管Servlet可以响应任意类型的请求,但是它们使用最广泛的是响应web方面的请求. Servle ...
- Java Servlet(六):HttpServlet实现原理(jdk7+tomcat7+eclipse)
本篇记录了HttpServlet的实现过程,主要讲述了如何依赖Servlet,GenericServlet实现的原理. HttpServlet实现过程:1.是一个Servlet,继承自GenericS ...
随机推荐
- Pygame安装问题
1.首先使用如下命令: conda install -c https://conda.anaconda.org/quasiben pygame 测试报错: >>> import py ...
- CentOS6.5安装Oracle 12c
CentOS6.5 安装 ORACLE 12c步骤 Oracle官网下载oracle12c安装包,解压软件:unzip linuxx64_12201_database.zip 一.创建用户和组#gro ...
- Oracle将两张表的数据插入第三张表且第三张表中不存在
1.由于是先查再插所以不能使用insert into table1() values(), 要使用insert into table1() select * table2,不能使用values. 2. ...
- Linux 下载文件命令(wget)
wget是Linux最常用的下载命令, 一般的使用方法是: wget + 空格 + 要下载文件的url路径 例如: # wget http://www.linuxsense.org/xxxx/xxx. ...
- 开源分布式事务中间件Seata使用指南
介绍 Seata 是阿里巴巴开源的分布式事务中间件,一种分布式事务解决方案,具有高性能和易于使用的微服务架构. 初衷 对业务无侵入:即减少技术架构上的微服务化所带来的分布式事务问题对业务的侵入 高性能 ...
- JNDI资源(一)
JNDI:Java命名与目录接口 是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录的通用.统一的服务. 使用JNDA的步骤: 1.配置资源. //Tomcat跟目录/conf/co ...
- (技能篇)双机热备之Oracle切换故障处理
背景: 以前做的的一个项目中使用了某国产双机热备产品,但是在数据库做双机热备时出现了一些问题,没办法.不得不研究一番了!经过两天的研究终于问题得以解决.将问题处理步骤记录下来以备后用,也希望能帮助到需 ...
- Mybatis连接查询返回类型问题
一对一映射 public class Card { private Integer id; private String num; private Student student; //重要 publ ...
- TCP加速机制是如何加速的?
一.什么是TCP加速? TCP加速就是在高时延链路提高吞吐量的一系列解决方案. 二.为什么需要对TCP进行加速? 1.传统的TCP拥塞控制算法并不适用于高时延.高误码的链路. 2.随着we ...
- ASP.NET Core - 实现自定义WebApi模型验证
Framework时代 在Framework时代,我们一般进行参数验证的时候,以下代码是非常常见的 [HttpPost] public async Task<JsonResult> Sav ...