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类

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时,后台输出:


问题一:在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错误,这表明服务器内部运行出现错误

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

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

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

问题二:这是为什么呢?


我们先来梳理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对象中的属性

13.ServletContext

13.1为什么需要ServletContext

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

方案一:使用DB

方案二:使用ServletContext

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对象通常也被称为域对象。

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_:

后台输出:

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

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

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

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:

day15-Servlet04的更多相关文章

  1. python_way day15 HTML-DAY2 HTML-DAY2、JS

    python_way day15 HTML-DAY2 html-css回顾 javascript 一.html-css回顾 1.input与+,-号的写法 <!DOCTYPE html> ...

  2. Spark Streaming揭秘 Day15 No Receivers方式思考

    Spark Streaming揭秘 Day15 No Receivers方式思考 在前面也有比较多的篇幅介绍了Receiver在SparkStreaming中的应用,但是我们也会发现,传统的Recei ...

  3. Python之路,Day15 - Django适当进阶篇

    Python之路,Day15 - Django适当进阶篇   本节内容 学员管理系统练习 Django ORM操作进阶 用户认证 Django练习小项目:学员管理系统设计开发 带着项目需求学习是最有趣 ...

  4. ##DAY15——UICollectionView

    DAY15——UICollectionView 创建UICollectionView //创建一个布局对象,采用系统布局类UICollectionViewFlowLayout UICollection ...

  5. 【JAVA零基础入门系列】Day15 对象的比较

    最近一直有事,博客也停笔了一段时间,十分抱歉. 这一篇主要讲讲对象的比较,什么是对象的比较,我们知道两个数值类型只需要用"=="符号即可进行相等判断,但如果是两个Goods对象呢? ...

  6. day15.Python内置函数

    作用域相关 locals() -- 获取执行本方法所在命名空间的局部变量的字典 globals() --  获取全局变量的字典 print(locals()) print(globals()) {'_ ...

  7. 11.2 正睿停课训练 Day15

    目录 2018.11.2 正睿停课训练 Day15 A 郁闷的小G(二分) B 小G的树(树形DP) C 数的距离(思路) 考试代码 B C 2018.11.2 正睿停课训练 Day15 时间:3.5 ...

  8. python开发学习-day15(前端部分知识、web框架、Django创建项目)

    s12-20160430-day15 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...

  9. Day15模块(导入,使用)

    Day15模块 什么是模块: 一系列功能的集合体 一个py文件就是一个模块 aaa.py就是aaa模块 模块四种形式: 内置的模块 py文件 第三方的 包 模块三种来源:内置的,第三方,自定义 为什么 ...

  10. 学习日常笔记<day15>mysql基础

    1.数据库入门 1.1数据库软件 数据库:俗称数据的仓库,方便管理数据的软件(或程序) 1.2市面上数据库软件 Oracle,甲骨文公司的产品. 当前最流行应用最广泛的数据库软件.和java语言兼容非 ...

随机推荐

  1. Linux安装Jenkins及配置svn使用

    目录 1. 下载 2. 创建文件夹 3. 安装 4. 修改端口,不用这步 5. 安装插件提速 6. 启动 7. 页面访问 8. 新建用户 9. 安装Subversion插件 10. 安装maven插件 ...

  2. Tablesaw——Java统计、机器学习库

    资源 java二维数组处理可可视化库 https://github.com/jtablesaw/tablesaw plotly JS库的Java封装 https://github.com/jtable ...

  3. Can't pickle local object '_createenviron.<locals>.encodekey'报错解决

    关于selenium传参报错问题,用下面是报错信息: Traceback (most recent call last): File "D:/code/read_book/main.py&q ...

  4. 教大家怎么看monaco-editor的官方文档

    最近业务中有用到浏览器在线编辑器,用的是monaco-editor,官网文档只在首页介绍了npm安装方式. 但其实还有另外一种<script>的引入方式,但是这种方式体现在API文档中,由 ...

  5. Cluster table 与性能

    用户数据行存储在文件系统中的堆文件中,而这些行以不确定的顺序存储.如果表最初以插入/复制的顺序加载,那么以后的插入.更新和删除将导致在堆文件中以不可预测的顺序添加行.创建索引创建一个指向堆行的辅助文件 ...

  6. ubuntu下vscode安装go插件失败解决办法

    go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.io,direct go env -w GOSUMDB=gosum.io+ce6e ...

  7. Windows 2012 R2上搭建IIS管理用户的隔离模式FTP

    Windows 2012 R2上搭建IIS管理用户的隔离模式FTP Windows自带的FTP现在可以提供基于非OS用户的管理,这提高了安全性.即使FTP用户名和密码泄露,也不会对操作系统造成进一步的 ...

  8. 微信小程序-云函数、云存储

    云函数是运行在服务器端的 创建一个目录cloud project.config.json配置云函数目录 cloud目录有个云朵.代表云函数 初始化成功了 新建一个云函数 cloud目录右击 新建一个N ...

  9. ProxySQL(10):读写分离方法论

    文章转载自:https://www.cnblogs.com/f-ck-need-u/p/9318558.html 不同类型的读写分离 数据库中间件最基本的功能就是实现读写分离,ProxySQL当然也支 ...

  10. ProxySQL Cluster 高可用集群 + MySQL MGR环境部署 (多写模式) 部署记录

    文章转载自:https://blog.51cto.com/u_6215974/4937192 ProxySQL 在早期版本若需要做高可用,需要搭建两个实例,进行冗余.但两个ProxySQL实例之间的数 ...