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 ...
随机推荐
- 软件测试必须掌握的linux命令大全
测试工程师的四大基础技能:数据库.linux.网络协议.测试工具,不管是刚入门还是已经工作多年,这几个方向都是要掌握的.今天我们再讲一下测试工程师必须要掌握的linux命令. 测试工程师需要掌握lin ...
- 个人永久性免费-Excel催化剂功能第57波-一键生成完全组合的笛卡尔积结果表
在数据库的多表查询中,通常会有各种连接关系,同样地在Excel环境中,也有很大的场景需要用到类似数据库的多表查询,如经典的VLOOKUP就是其中一种类似LEFT JOIN查询的查询效果.在很多时候需要 ...
- Jmeter(1):使用TCP取样器与socket接口进行简单通信
一个小任务:服务器与客户端连接,每次发送50个随机生成的字符,两秒发送一次 失败过太多次,然后昨晚终于跑通了,心情激动,于是清均第一篇博客就诞生了. 之前不了解jmeter,想过单纯用java编写服务 ...
- AndroidStudio使用genymotion模拟器
安装Genymotion之前首先要安装好virtualbox这个软件 virtual官方网站:https://www.virtualbox.org/ genymotion的官方网站: https:// ...
- c语言进阶14-线性表之链表
一. 线性表的链式存储结构 1. 顺序存储结构不足的解决办法 前面我们讲的线性表的顺序存储结构.它是有缺点的,最大的缺点就是插入和删除时需要移动大量元素,这显然就需要耗费时间.能不能想 ...
- 客户端内嵌Vue页面
目前很多应用都存在网页端和客户端形式,例如常用的:钉钉.微信等.按传统的开发形式,需要为客户端开发一套界面.基于当前Web应用可以利用三大前端框架和UI框架快速开发出各种酷炫的界面,于是出现了客户端嵌 ...
- sql server中format函数的yyyyMMddHHmmssffff时间格式兼容旧版sql写法
问题:博主看到项目脚本,有些地方使用了format函数来把当前日期转换成yyyyMMddHHmmssffff的格式,但在测试环境数据库是sql 2008 r2,是不支持format这个函数的.脚本会报 ...
- 《 C#语言学习笔记》——自动属性
属性是访问对象状态的首选方式,因为它们禁止外部代码实现对象内部的数据存储机制.属性还对内部数据的访问方式有了更多控制.一般以非常标准的方式定义属性,即通过一个公共属性直接访问一个私有成员. 利用自动属 ...
- Intellij IDEA 打开文件tab数量限制的调整
最近在阅读一个开源项目,发现IDEA对同时打开的文件TAB有限制,最多只能打开10个文件Tab,再多开就会把原来的Tab关闭了. 找了半天,在菜单中找到了调整方法,以Mac为例,调整路径为 “Inte ...
- 一文搞懂List 、List<Object>、List<?>的区别以及<? extends T>与<? super T>的区别
前段时间看<Java编程思想>泛型时对 <? extends T>与<? super T>很懵逼,接着看到泛型与集合的更蒙蔽,随后又翻开<码出高效>时, ...