• day15-Servlet04


    Servlet04

    12.ServletConfig

    12.1ServletConfig基本介绍

    1. ServletConfig类是为Servlet程序配置信息的类
    2. Servlet对象和ServletConfig对象都是由Tomcat负责创建
    3. Servlet对象默认是第一次访问的时候创建,ServletConfig在Servlet对象创建的时候,就创建一个对应的ServletConfig对象

    12.2ServletConfig作用

    1. 获取Servlet程序的servlet-name的值
    2. 获取初始化参数init-param
    3. 获取ServletContext对象(上下文对象)

    12.3ServletConfig应用实例

    例子

    需求:编写DBServlet.java,完成如下功能

    1. 在web.xml配置连接mysql的用户名和密码

    2. 在DBServlet执行doGet()或者doPost()时,可以获取到web.xml配置的用户名和密码

    3. 思路分析:

      浏览器发送请求,Tomcat去创建DBServlet,DBServlet去web.xml文件中去获取配置的参数,获取的方法有两种:一是使用dom4j,二是使用ServletConfig类

      image-20221110231130553

    web.xml配置Servlet:

    <servlet>
    <servlet-name>DBServletservlet-name>
    <servlet-class>servlet.DBServletservlet-class>
    <init-param>
    <param-name>usernameparam-name>
    <param-value>jackparam-value>
    init-param>
    <init-param>
    <param-name>pwdparam-name>
    <param-value>123456param-value>
    init-param>
    servlet>
    <servlet-mapping>
    <servlet-name>DBServletservlet-name>
    <url-pattern>/dburl-pattern>
    servlet-mapping>

    DBServlet:

    package servlet;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.io.IOException;
    public class DBServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //在DBServlet执行doGet()或者doPost()时,可以获取到web.xml配置的用户名和密码
    //DBServlet的父类GenericServlet有方法getServletConfig()
    /**
    * 1.getServletConfig()是父类GenericServlet的
    * 2.返回的ServletConfig对象是GenericServlet的private transient ServletConfig config
    * 3.当一个属性被transient修饰,表示该属性不会被串行化(有些重要信息不希望保存到文件中)
    */
    ServletConfig servletConfig = getServletConfig();
    String username = servletConfig.getInitParameter("username");
    String pwd = servletConfig.getInitParameter("pwd");
    System.out.println("初始化参数username=" + username);
    System.out.println("初始化参数pwd=" + pwd);
    }
    }

    浏览器访问DBServlet时,后台输出:

    image-20221111163640834

    问题一:在doPost方法中可以得到servletConfig,在doGet方法也可以得到servletConfig,那么这两个servletConfig是同一个servletConfig吗?

    答:是同一个servletConfig。

    先来看一个例子

    在上述的DBServlet中重写init方法,并且分别在init和doPost方法中输出ServletConfig对象

    package servlet;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.io.IOException;
    public class DBServlet extends HttpServlet {
    @Override
    public void init(ServletConfig config) throws ServletException {
    System.out.println("init()=" + config);
    }
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doPost(request, response);
    }
    @Override
    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);
    }
    }

    redeployTomcat,在浏览器重新访问DBServlet,会发现出现了500错误,这表明服务器内部运行出现错误

    image-20221111165414131

    查看控制台输出,发现doPost方法竟然输出了null

    image-20221111165456889

    在DBServlet中的init方法加上语句super.init(config);

    image-20221111165825143

    redeployTomcat,重新访问浏览器,会发现访问DBServlet成功,后台输出变正常了

    image-20221111165845773

    问题二:这是为什么呢?


    我们先来梳理ServletConfig config的使用流程

    1. 当DBServlet对象初始化时,Tomcat会同时创建一个ServletConfig对象

    2. 如果DBServlet init()方法中调用了super.init(config);

    3. 就会调用父类GenericServlet的init方法:

      public void init(ServletConfig config) throws ServletException {
      this.config = config;
      this.init();
      }

      这时就会把Tomcat创建的ServletConfig对象赋给GenericServlet的属性config

    4. 因此如果要重写init()方法,记住如果你想在其他方法通过getServletConfig()获取ServletConfig,则一定要记住调用super.init(config);


    回到问题二:

    如果没有把tomcat创建的ServletConfig,赋值给GenericServlet的属性config。那么GenericServlet的属性config的值就为null,而doPost或者doGet方法通过getServletConfig()拿到的就是GenericServlet的属性config,因此就会输出null。

    侧面证实了方法中获取的servletConfig是同一个对象(问题一)

    因此上面的例子中,浏览器访问DBServlet,发现出现了500错误的原因是,doPost方法中获取了为null的ServletConfig对象中的属性

    image-20221111172545657

    13.ServletContext

    13.1为什么需要ServletContext

    先来看一个需求:如果我们希望统计某个web应用的所有Servlet被访问的次数,怎么办?

    方案一:使用DB

    image-20221111180455985

    方案二:使用ServletContext

    image-20221111180517874

    13.2ServletContext基本介绍

    1. ServletContext是一个接口,它表示Servlet上下文对象

    2. 一个web工程中,只有一个ServletContext对象实例

    3. ServletContext对象是在web工程启动的时候创建的,在web工程停止的时候销毁

    4. 可以通过ServletConfig.getServletContext方法获得对ServletContext对象的应用,也可以通过this.getServletContext()来获得其对象的引用

    5. 由于一个web应用中的所有Servlet共享一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现多个Servlet间的通信。ServletContext对象通常也被称为域对象。

      image-20221111182439732

    13.3ServletContext可以做什么

    1. 获取web.xml文件中配置的上下文参数context-param [信息和整个web应用相关,而不是属于某个Servlet]

    2. 获取当前的工程路径,格式:/工程路径

    3. 获取工程部署后在服务器硬盘上的绝对路径

      比如 D:\IDEA-workspace\servlet\out\artifacts\servlet_war_exploded

    4. 向Map一样存取数据,多个Servlet共享数据

    13.4应用实例

    13.4.1应用实例1-获取工程相关信息

    需求如下:

    1. 获取web.xml中配置的上下文参数context-param
    2. 获取当前的工程路径,格式:/工程路径
    3. 获取工程部署后在服务器硬盘上的绝对路径

    配置ServletContext_: 在web.xml文件增加相关配置

    <servlet>
    <servlet-name>ServletContext_servlet-name>
    <servlet-class>com.li.servlet.servletcontext.ServletContext_servlet-class>
    servlet>
    <servlet-mapping>
    <servlet-name>ServletContext_servlet-name>
    <url-pattern>/servletContext_url-pattern>
    servlet-mapping>
    <context-param>
    <param-name>websiteparam-name>
    <param-value>http://www.lili.netparam-value>
    context-param>
    <context-param>
    <param-name>companyparam-name>
    <param-value>lili有限公司param-value>
    context-param>

    ServletContext_:

    package com.li.servlet.servletcontext;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.io.IOException;
    public class ServletContext_ extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //获取web.xml的context-parameter
    //1.获取到ServletContext对象
    ServletContext servletContext = getServletContext();
    //2.获取website
    String website = servletContext.getInitParameter("website");
    String company = servletContext.getInitParameter("company");
    System.out.println("website= " + website);
    System.out.println("company= " + company);
    //3.获取项目的工程路径
    String contextPath = servletContext.getContextPath();
    System.out.println("项目路径= " + contextPath);// /servlet_demo
    //4.得到项目发布后真正的工作路径
    //这里的斜杠/表示我们的项目发布后的根路径 D:\IDEA-workspace\servlet_demo\out\artifacts\servlet_demo_war_exploded
    String realPath = servletContext.getRealPath("/");
    System.out.println("项目发布后的绝对路径= " + realPath);
    }
    }

    浏览器访问ServletContext_:

    image-20221111190127615

    后台输出:

    image-20221111190940108

    13.4.2应用实例2-简单的网站访问次数统计器

    需求:完成一个简单的网站访问次数统计器

    不管使用什么浏览器,每访问一次Servlet,就增加1访问次数,在后台输出,并将结果返回给浏览器显示

    image-20221111191533055

    WebUtils.java:

    package com.li.servlet.servletcontext;
    import javax.servlet.ServletContext;
    public class WebUtils {
    //该方法对访问网站的次数累加,同时返回次数
    public static Integer visitCount(ServletContext servletContext) {
    //从servletContext获取 visit_count 属性 k-v
    Object visit_count = servletContext.getAttribute("visit_count");
    //判断visit_count是否为空
    if (visit_count == null) {//说明是第1次访问网站
    servletContext.setAttribute("visit_count", 1);
    visit_count = 1;
    } else {//说明是第二次或之后访问
    //visit_count+1
    visit_count = Integer.parseInt(visit_count + "") + 1;
    //再将其放回servletContext
    servletContext.setAttribute("visit_count", visit_count);
    }
    return Integer.parseInt(visit_count + "");
    }
    }

    Servlet01.java:

    package com.li.servlet.servletcontext;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    import java.io.PrintWriter;
    @WebServlet(urlPatterns = {"/Servlet01"})
    public class Servlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //获取到ServletContext对象
    ServletContext servletContext = getServletContext();
    Integer visit_count = WebUtils.visitCount(servletContext);
    //输出显示
    response.setContentType("text/html;charset=utf-8");
    PrintWriter writer = response.getWriter();
    writer.print("

    该网站被访问的次数是" + visit_count + "

    "
    );
    writer.flush();
    writer.close();
    }
    }

    Servlet02.java:

    package com.li.servlet.servletcontext;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.annotation.*;
    import java.io.IOException;
    import java.io.PrintWriter;
    @WebServlet(urlPatterns = {"/Servlet02"})
    public class Servlet02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //获取到ServletContext对象
    ServletContext servletContext = getServletContext();
    Integer visit_count = WebUtils.visitCount(servletContext);
    //输出显示
    response.setContentType("text/html;charset=utf-8");
    PrintWriter writer = response.getWriter();
    writer.print("

    该网站被访问的次数是" + visit_count + "

    "
    );
    writer.flush();
    writer.close();
    }
    }

    redeployTomcat,在不同的浏览器分别访问Servlet01和Servlet02:

  • 相关阅读:
    群狼调研(长沙医院满意度调查)|医院患者满意度提升方案
    【数据结构与算法】顺序表的基本操作实现
    DQL命令查询数据(一)
    Jmeter之断言
    Python求解线性规划——PuLP使用教程
    如何让ChatGPT生成图片?
    spring boot社区居民健康档案管理系统毕业设计源码220940
    C现代方法(第8章)笔记——数组
    python3-- Pillow10 ‘FreeTypeFont‘ object has no attribute ‘getsize‘报错解决
    面试官:设计模式之简单工厂模式
  • 原文地址:https://www.cnblogs.com/liyuelian/p/16881635.html