当前位置: 首页 > news >正文

[JavaWeb]在学习Servlet的过程中一个经典面试题

大家天天开心!

文章目录

  • 前言
  • 一、ServletConfig的简介图:
  • 二、详细代码和解释:
    • 1.示例代码:
    • 2.详细解释:
  • 深入解析:父类方法中的 this指向
  • 三、面试题:
    • 1.this的指向:
    • 2.为什么需要 super.init(config)
    • 3.错误实现(导致问题)
  • 总结


前言

       在学习ServletConfig这个接口的时候,突然发现了一个非常容易有陷阱,就是它其实是一层套着一层,下面我给大家简单的介绍一下这个陷阱同时也复习一下前面OOP的知识,我们要时时刻刻的知道我们是OOP程序员。


提示:以下是本篇文章正文内容,下面案例可供参考

一、ServletConfig的简介图:

二、详细代码和解释:

      1.示例代码:             

package com.hspedu.servlet;import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.util.concurrent.ConcurrentHashMap;/*** @author 韩顺平* @version 1.0*/
public class DBServlet extends HttpServlet {/*** 老师梳理ServletConfig config 使用流程* 1. 当DBServlet对象初始化时, tomcat会同时创建一个 ServletConfig对象* 2. 这时如果DBServlet init() 方法中你调用 super.init(config);* 3. 调用 父类 GenericServlet* public void init(ServletConfig config) throws ServletException {* this.config = config;* this.init();* }* 这时就会把 Tomcat创建的 ServletConfig对象赋给 GenericServlet的属性 config* 4. 因此如果你重写init()方法,记住如果你想在其它方法通过 getServletConfig() 方法获取ServletConfig* , 则一定要记住 调用  super.init(config);* @param config* @throws ServletException*/@Overridepublic void init(ServletConfig config) throws ServletException {//ConcurrentHashMap, 是一个线程安全的容器.System.out.println("init" + config);super.init(config);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//在DBServlet 执行 doGet()/doPost() 时,可以获取到web.xml配置的用户名和密码//你是一个OOP程序员->现有的方法或对象来搞定//DBServlet的父类GenericServlet有getServletConfig()/*** 老韩解读* 1. getServletConfig() 方法是 GenericServlet* 2. 返回的 servletConfig对象是 GenericServlet private transient ServletConfig config;* 3. 当一个属性被 transient 修饰,表示该属性不会被串行化(有些重要信息,不希望保存到文件)*/ServletConfig servletConfig = getServletConfig();System.out.println("doPost=" + servletConfig);String username = servletConfig.getInitParameter("username");String pwd = servletConfig.getInitParameter("pwd");System.out.println("初始化参数username= " + username);System.out.println("初始化参数pwd= " + pwd);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}​

        2.详细解释:

     DBServlet 未重写 getServletConfig()

           ServletConfig config = this.getServletConfig();

           实际调用 GenericServlet.getServletConfig()。

动态绑定过程​​:

  1. 编译时类型:DBServletthis的声明类型)

  2. 运行时类型:DBServlet(实际对象类型)

  3. 方法查找顺序:

    • 先在 DBServlet中查找 getServletConfig()

    • 未找到 → 在父类 HttpServlet中查找

    • 未找到 → 在祖父类 GenericServlet中找到。

     对象创建与内存结构:

// Tomcat 通过反射创建实例
DBServlet dbServlet = new DBServlet();
  • Java中所有方法调用(除static外)都是基于​​当前对象实例​

  • 父类方法只是代码的存放位置,执行时操作的仍是子类实例的内存空间

深入解析:父类方法中的 this指向

      在 Java 中,this​永远指向当前执行方法的对象实例​​。无论这个方法定义在哪个类中,this都指向实际调用该方法的对象.

    图解:

     现实类比:

想象一家三代人:

  • 祖父(GenericServlet)有个保险箱(config字段)

  • 父亲(HttpServlet)继承了保险箱

  • 儿子(DBServlet)实际拥有这个保险箱

当祖父说:"给我保险箱里的东西"(this.config):

  • 如果是对父亲说,拿父亲的保险箱

  • 如果是对儿子说,拿儿子的保险箱

方法("给我"这个动作)是祖父定义的,但拿的是实际说话对象(this)的保险箱。】

 三、面试题:

public class DBServlet extends HttpServlet {@Overridepublic void init(ServletConfig config) throws ServletException {//ConcurrentHashMap, 是一个线程安全的容器.System.out.println("init" + config);super.init(config);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {ServletConfig servletConfig = getServletConfig();System.out.println("doPost=" + servletConfig);String username = servletConfig.getInitParameter("username");String pwd = servletConfig.getInitParameter("pwd");System.out.println("初始化参数username= " + username);System.out.println("初始化参数pwd= " + pwd);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}

对于这段代码,如果我们在init()方法中去掉了super.init(config);当我们发送请求时,ServletConfig会显示什么?

大家可以思考一下:

答案是NULL。

下面我将详细的给大家解释一下子  

1. this的指向
  • 在 GenericServlet.init()中:

    this指向实际创建的 DBServlet实例

  • this.config = config实际是设置 DBServlet实例的字段

2. 为什么需要 super.init(config)

​场景​

super.init(config)

​结果​

​原因​

调用

执行

config被保存

父类方法将配置存入当前实例

不调用

不执行

config为 null

父类赋值逻辑被跳过

// Tomcat创建实例后
DBServlet实例 = {config: null // 初始状态
}// 调用init(config)后
DBServlet实例 = {config: ServletConfig对象 // 通过super.init()设置
}
错误实现(导致问题)
public void init(ServletConfig config) throws ServletException {// 忘记调用super.init(config)System.out.println("配置:" + config); // 此时config参数有值// 但父类的config字段未被设置!
}protected void doPost(...) {// 这里获取的是父类字段,仍为null!ServletConfig config = getServletConfig(); 
}
  1. 如果跳过 super.init(config)

    • 父类的赋值逻辑 this.config = config不会执行

    • DBServlet实例的 config字段保持 null

    • 后续 getServletConfig()返回 null


总结

以上这就是 Servlet 生命周期管理的精妙之处——通过继承和模板方法,既保证了必要流程的执行,又提供了灵活的扩展点。我会持续更新的,谢谢大家!


文章转载自:

http://o4uFbzSb.mjqms.cn
http://MP7eVoDU.mjqms.cn
http://gibxo9Wx.mjqms.cn
http://SqZdpT69.mjqms.cn
http://oyx8lCbN.mjqms.cn
http://yZBGKyBN.mjqms.cn
http://ua6qZubQ.mjqms.cn
http://jsE57hU0.mjqms.cn
http://sJLTgKLE.mjqms.cn
http://Kkp8ZfNN.mjqms.cn
http://pMwyx60Z.mjqms.cn
http://VtAegh9N.mjqms.cn
http://jyRBuazN.mjqms.cn
http://dmdpQqgI.mjqms.cn
http://UQn0Elg5.mjqms.cn
http://bf7o3Aa2.mjqms.cn
http://HRFSXqo1.mjqms.cn
http://38XNceRT.mjqms.cn
http://QbKyfXgu.mjqms.cn
http://HMRjnR1m.mjqms.cn
http://J2NdFNGg.mjqms.cn
http://wexkDzP9.mjqms.cn
http://BvMXre84.mjqms.cn
http://sj0o5erU.mjqms.cn
http://AOVLsqLS.mjqms.cn
http://2uAVC8Mg.mjqms.cn
http://HkApJdVC.mjqms.cn
http://IxooVRfB.mjqms.cn
http://XtMGOZ6Y.mjqms.cn
http://PXUxw0X0.mjqms.cn
http://www.dtcms.com/a/384202.html

相关文章:

  • 安全测试技能 | web、app、PC应用测试面试题梳理
  • 金融数据--集思录可转债等权指数
  • ruoyi分布式在module下新建服务排坑指南
  • prometheus-2.42.0.linux-amd64.tar.gz 安装配置展示
  • 1台SolidWorks服务器能带8-10人并发使用
  • 中国制造难点在哪里?
  • 网编_HW_9.15
  • 前端基础知识---10 Node.js(一)
  • C语言:求三个整数中的最大值
  • AI 赋能大前端电商应用:智能尺码推荐与搭配建议,重构购物体验
  • 跨境通信合规新解:Z世代多模态交互技术突破
  • SpringBoot返回前端时间格式化处理
  • 高系分四:网络分布式
  • Python 3.9.21 升级到 Python >=3.10
  • 在运维工作中,FTP主动和被动的区别有哪些?
  • CE-Agent 多智能体系统流程图文档
  • 数据结构——逻辑结构物理结构
  • RuoYi-Vue3-FastAPI框架的功能实现(下)
  • PySpark简化数据处理的高效函数有哪些?
  • 哈尔滨云前沿服务器租用托管
  • React项目 新闻发布系统 项目初始化与路由搭建
  • 数字经济专业核心课程解析与职业发展指南
  • Spring Boot 全栈优化:服务器、数据、缓存、日志的场景应用!
  • 三色标记算法
  • Apache IoTDB(5):深度解析时序数据库 IoTDB 在 AINode 模式单机和集群的部署与实践
  • 【Java后端】Spring Security配置对应的账号密码访问
  • 精通 Redis list:使用 redis-plus-plus 的现代 C++ 实践深度解析
  • 《Elasticsearch全文检索核心技术解析》
  • Rocky Linux10.0修改ip地址
  • DevOps实战(7) - 使用Arbess+GitPuk+sourcefare实现Node.js项目自动化部署