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 ...
随机推荐
- C# Linq 笛卡尔积
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 006.SQLServer AlwaysOn可用性组高可用部署
一 数据库镜像部署准备 1.1 数据库镜像支持 有关对 SQL Server 2012 中的数据库镜像的支持的信息,请参考:https://docs.microsoft.com/zh-cn/previ ...
- java接口自动化(一) - 接口自动化测试整体认知 - 开山篇(超详解)
简介 了解什么是接口和为什么要做接口测试.并且知道接口自动化测试应该学习哪些技术以及接口自动化测试的落地过程.其实这些基本上在python接口自动化的文章中已经详细的介绍过了,不清楚的可以过去看看.了 ...
- 《ElasticSearch6.x实战教程》之父-子关系文档
第七章-父-子关系文档 打虎亲兄弟,上阵父子兵. 本章作为复杂搜索的铺垫,介绍父子文档是为了更好的介绍复杂场景下的ES操作. 在非关系型数据库数据库中,我们常常会有表与表的关联查询.例如学生表和成绩表 ...
- Java EE.JSP.指令
JSP的指令是从JSP向Web容器发送消息,它用来设置页面的全局属性,如输出内容类型等. JSP的指令的格式为:<%@ 指令名 属性="属性值"%> 1.page指令 ...
- 《VR入门系列教程》之12---转换矩阵
转换矩阵 模型网格的三维空间位置都是由它们的顶点坐标决定的,如果每次想要移动一下模型位置都要依次改变每个网格的顶点坐标,这将一件非常头疼的事,要是遇上需要显示动画效果那就更糟了.为了解决这个问 ...
- FTP文件传输服务器原理
FTP服务器,全称File Transfer Protocol Server,是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务.FTP,文件传输协议(File Transfer ...
- [NLP-ASR] 语音识别项目整理(一) 语音预处理
简介 之前参与过114对话系统的项目,中间搁置很久,现在把之前做过的内容整理一下,一是为自己回顾,二是也希望分享自己看的内容,中间也遇到一些问题,如果您可以提一些建议将不胜感激. 114查询主要分 ...
- thinkphp项目阿里云ECS服务器部署
[日记]thinkphp项目阿里云ECS服务器部署 项目本地开发告一段落.准备上传到服务器上测试 技术组成 thinkphp+mysql+阿里ECS 代码管理方式git 一.阿里ECS服务器配置 ...
- python下载报错:Could not install packages due to an EnvironmentError: [WinError 5] 拒绝访问
更新pip模块的版本:python -m pip install --upgrade pip 但是遇到报错提示: Could not install packages due to an Enviro ...