我们知道,如果我们自定义一个servlet继承HttpServlet,并且重写HttpServlet中的doGet或doPost方法,那么从浏览器发送过来的request请求将调用HttpServlet中的service方法,在service方法中,根据获得的method是get还是post,将调用我们自定义servlet中的doGet或doPost方法,这里用到了多态技术,因为基类HttpServlet中service方法调用的不是基类的doGet或doPost方法,而是子类的doGet或doPost方法。

我们举一个例子来说明:

1 public class HelloServlet extends HttpServlet{
2 @Override
3 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
4 System.out.println("请求已收到。。。");
5 }
6 }

这是正常情况下的程序。但是这里的多态是怎么实现的呢,我们并没有看见子类对象赋给基类的代码。这里我们不得不提java中很重要的概念:反射。反射不是这里研究的重点,所以不过多阐述。
那利用反射是怎样实现上面代码的多态呢?
我们看下面这个例子:

1 public class HelloServlet extends HttpServlet{
2 public HelloServlet(int i) {
3 }
4
5 @Override
6 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
7 System.out.println("请求已收到。。。");
8 }
9 }

这个代码只是在第一个代码的基础上加上了一个HelloServlet的带参构造器,当我们运行上述代码时,会报如下错误:

HTTP Status 500 – Internal Server Error
--------------------------------------------------------------------------------
Type Exception Report
Message Error instantiating servlet class [com.itheima.a_hello.HelloServlet]
Description The server encountered an unexpected condition that prevented it from fulfilling the request.
Exception
javax.servlet.ServletException: Error instantiating servlet class [com.itheima.a_hello.HelloServlet]
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:651)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:407)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:754)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1376)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:844)

Root Cause
java.lang.NoSuchMethodException: com.itheima.a_hello.HelloServlet.<init>()
java.base/java.lang.Class.getConstructor0(Class.java:3322)
java.base/java.lang.Class.getConstructor(Class.java:2108)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:651)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:407)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:754)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1376)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:844)

Note The full stack trace of the root cause is available in the server logs.

在Message中我们看到,原理时实例化servlet类时出错,那为什么会这样呢?
原来,我们没有看到的子类对象赋给基类的代码正式反射帮我们做的。还记得我们在创建HelloServlet时会在web.xml中需要配置HelloServlet的全限定名吗,这正是给反射用的,通过这个类名,反射技术可以得到该类的Class对象,并由Class对象的newInstance方法创建该类的实例,并把该子类对象赋给了基类,由此产生多态。
Class对象的newInstance方法需要根据无参构造器去创建实例,由于我们用带参构造器覆盖了无参构造器,所以,HelloServlet没有了无参构造器,因此不能创建实例,报出以上错误信息。

自定义servlet重写doGet或doPost方法是如何实现多态的的更多相关文章

  1. 自定义servlet重写doGet或者doPost方法时,405 method not allowed

    自定义servlet public class TestServlet extends HttpServlet { @Override protected void doGet(HttpServlet ...

  2. Servlet的doGet与doPost方法的区别与使用

    Servlet的doGet与doPost方法的区别与使用 2016年07月07日 13:05:13 阅读数:10222 一,区别 在使用表单提交数据到服务器的时候有两张方式可共选择,一个是post一个 ...

  3. Servlet的Service方法和doget 和 dopost方法的区别,常见的错误解析

    package com.sxt.in; import java.io.IOException; import javax.servlet.ServletException; import javax. ...

  4. 去除myeclipse中doget和dopost方法中的注释

    当我们使用myeclipse新建servlet时发现doget和dopost方法中有一些无用的注释,每次新建一个servlet时都要手动删除特别麻烦. 下面就教大家如何去除这些注释! 以myeclip ...

  5. service 方法和doGet、doPost方法的区别

    Service方法和doGet和doPost方法的区别service:     可以处理get/post方式的请求,如果servlet 中有service方法,会优先调用service方法进行处理do ...

  6. servlet中doGet()和doPost()的用法

    转自:https://blog.csdn.net/qq_38963960/article/details/79468182 1.servlet中doGet()和doPost()的用法 一般来说我们是用 ...

  7. 关于servlet中doGet和doPost乱码再一次理解

    今天系统的整理了在web项目下,出现的编码问题,下面就做一些总结: 首先对HTTP协议中对GET和POST的定义:   GET POST 后退按钮/刷新 无害 数据会被重新提交(浏览器应该告知用户数据 ...

  8. 【Servlet】doGet()与doPost()的区别

    doGet与doPost的区别 .Servlet接口只定义了一个服务方法--service .当发出客户端请求时,调用service方法并传递一个请求和响应对象 .使用时经常在doPost()中调用d ...

  9. servlet中doGet()和doPost()的区别

    1.生成方式 get方法有四种: ①直接在URL地址栏中输入URL ②网页中的超链接 ③form中method为get ④form中method为空时,默认是get提交 post只知道有一种:form ...

随机推荐

  1. python中的API学习

    URL: url是统一资源定位符,对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址.互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该 ...

  2. 系统学习python第四天学习笔记

    1.解释 / 编译补充 编译型:代码写完后,编译器将其变成成另外一个文件,然后交给计算机执行. 解释型:写完代码交给解释器,解释器会从上到下一行行代码执行:边解释边执行. [实时翻译] 2.字符串功能 ...

  3. linux配置词典goldendict

    在mint 18下使用通过, ubuntu 类似. 方法: 通过软件中心安装goldendict,或者 sudo apt install goldendict 通过网页抓取程序, 见附录 下载朗道词典 ...

  4. 17.3.12---urlparse模块的URL下载

    1---urlparse模块是一个解析与泛解析Web网址URL字符串的一个工具 urlparse模块会将一个普通的url解析为6个部分,返回的数据类型都是元祖,同时,他还可以将已经分解后的url在组合 ...

  5. 12 Spring Data JPA:springDataJpa的运行原理以及基本操作(下)

    spring data jpaday1:orm思想和hibernate以及jpa的概述和jpa的基本操作 day2:springdatajpa的运行原理 day2:springdatajpa的基本操作 ...

  6. 专业程序设计part1

    7 专业程序设计 (有多少人在大学里学到了自己真正喜欢的专业??并在此专业上获得了升华??)i== 软件图标下载网址:easyicon 01thu 4邻域 8邻域 D邻域 是啥 像素间的连通性,是转为 ...

  7. JavaScript学习笔记 - 入门篇(3)- DOM操作

    认识DOM 文档对象模型DOM(Document Object Model)定义访问和处理HTML文档的标准方法.DOM 将HTML文档呈现为带有元素.属性和文本的树结构(节点树). 先来看看下面代码 ...

  8. mac 编程环境

    新mac (EI Capitan),需要在python中使用xgboost,通过pip安装未成功. 配置pip cat $HOME/Library/Application\ Support/pip/p ...

  9. vi几个常用的命令

    1.同时打开多个文件:vi 1.txt 2.txt 3.txt 在多个文件中来回切换,命令行模式输入“:next"表示下一个,输入":previous"代表进入上一个,” ...

  10. Opencv笔记(十二)——形态学转换

    学习目标: 学习不同的形态学操作,例如腐蚀,膨胀,开运算,闭运算等 我们要学习的函数有: cv2.erode(), cv2.dilate(), cv2.morphologyEx()等 原理简介: 形态 ...