首页 > 其他分享 >day15-Servlet04

day15-Servlet04

时间:2022-11-11 20:24:33浏览次数:66  
标签:DBServlet servlet day15 ServletContext import ServletConfig response 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:

<!--配置DBServlet-->
<servlet>
    <servlet-name>DBServlet</servlet-name>
    <servlet-class>servlet.DBServlet</servlet-class>
    <!--为该Servlet配置初始参数-->
    <init-param>
        <!--参数名-->
        <param-name>username</param-name>
        <!--参数值-->
        <param-value>jack</param-value>
    </init-param>
    <init-param>
        <param-name>pwd</param-name>
        <param-value>123456</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>DBServlet</servlet-name>
    <url-pattern>/db</url-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文件增加相关配置

<!--配置ServletContext_-->
<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>website</param-name>
    <param-value>http://www.lili.net</param-value>
</context-param>
<context-param>
    <param-name>company</param-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("<h1>该网站被访问的次数是" + visit_count + "</h1>");
        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("<h1>该网站被访问的次数是" + visit_count + "</h1>");
        writer.flush();
        writer.close();
    }
}

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

标签:DBServlet,servlet,day15,ServletContext,import,ServletConfig,response,Servlet04
From: https://www.cnblogs.com/liyuelian/p/16881635.html

相关文章

  • day15-HTTP协议02
    HTTP协议029.HTTP练习练习一请写一篇关于HTTP协议的笔记,要求:描述清楚HTTP请求头,响应头的格式请求头:响应头:请求头和响应头中各个头字段的含义(请求头和响应头......
  • day15
    [0015.三数之和]首先哈希法我不会用就算看了思路和代码还是不会尤其是去重那块其次看到可以用双指针法那我又去想了想想自己动手写但还是写不出来然后......
  • 牛客java选择题每日打卡Day15
    牛客java选择题每日打卡Day15......
  • 代码随想录Day15
    二叉树迭代遍历:递归遍历是从后往前推,迭代遍历是从前往后推。例如前序遍历:中左右。我们用栈来实现迭代遍历的时候,由于栈是先进后出,压入栈的时候的顺序是中右左。//前序......
  • 《剑指offer》day15
    二叉树中和为某一值的路径题目描述思路DFS没有什么要注意的,就是单纯的DFS的使用代码实现/***Definitionforabinarytreenode.*publicclassTreeNode......
  • day15 Socket网络编程 & 反射
    day15socket网络编程IP地址+端口号组成socket套接字,是tcp和udp的基础websocket,前端socket原理机制1)通信两端都有socket2)网络通信其实就是socket之间的通信3)数据在......
  • Day15 词汇3个
    curb/kɜːb/​v.控制,抑制;勒住(马)n.控制,抑制;<美>路缘,马路牙子;(马的跗关节后部因扭伤韧带引起的)硬瘤​tocontrolorlimitsomethinginordertopreventitfromhaving......
  • 进入python的世界_day15_python基础——内置函数、迭代器、异常捕获
    一、一些重要内置函数、常见内置函数1..zip()​ 将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的zip对象,转成list即可查看,如果对应......
  • Python学习路程——Day15
    Python学习路程——Day15重要内置函数zip()'''zip()函数的作用 zip()函数可以将多个序列(列表、元组、字典、集合、字符串以及ranger()区间构成的列表压缩成一个zip对......
  • Day15
    Day15今日内容概要重要内置函数常见内置函数可迭代对象迭代器对象for循环内部原理异常处理今日内容详细重要内置函数1.zip()拉链zip()#接受......