Servlet学习之ServletContext

一、ServletContext概述:

  • ServletContext即Servlet上下文对象,该对象表示当前的web应用环境信息,一个Web应用只会创建一个ServletContext对象。

  • web容器在启动时,他会为每个web应用程序创建一个对应的ServletContext对象,它代表当前的web应用。

  • 由于一个Web应用中的所有Servlet共享一个ServletContext对象,所以多个Servlet通过ServletContext对象实现数据共享。

  • ServletConfig对象中维护了ServletContext对象的引用,在开发编写servlet时,可以通过ServletConfig.getServletContext()方法获得ServletContext对象

  • ServletContext对象通常称为Context域对象。

ServletContext对象的三种获取方法:

1、ServletContext context1 = config.getServletContext();
通过继承GenericServlet类或HttpServlet类,调用GenericServlet类或HttpServlet类的getServletContext()方法获取。

2、ServletContext context2 = this.getServletContext();
通过ServletConfig对象的this.getServletContext()方法获取。

3、ServletContext context3 = request.getSession().getServletContext();
采用request.getSession().getServletContext()方法获取。

二、ServletContext的作用:

1、获取web应用的初始化全局配置参数

涉及的方法:

方法作用
ServletContext context = this.getServletContext();获得ServletContext域对象
public String getInitParameter(String name)返回包含指定上下文范围初始化参数值的 String,如果参数不存在,则返回 null。
public java.util.Enumeration getInitParameterNames()以 String 对象的 Enumeration 的形式返回上下文初始化参数的名称,如果该上下文没有初始化参数,则返回一个空的 Enumeration。

web.xml中配置全局信息信息:
web.xml配置的信息
获取web.xml中配置的信息测试代码:

public class ContextTest01 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 1、获得ServletContext对象
		ServletContext context = this.getServletContext();
		// 2、获得单个数据,并逐一打印
		String username = context.getInitParameter("username");
		String password = context.getInitParameter("password");

		System.out.println(username);
		System.out.println(password);
		// 3、获得多个数据并进行遍历打印
		Enumeration<String> names = context.getInitParameterNames();
		while (names.hasMoreElements()) {
			String name = names.nextElement();
			String value = context.getInitParameter(name);
			System.out.println(name + ":" + value);
		}
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		doGet(request, response);
	}

2、实现数据共享

域对象(多个Servlet共享数据) 网站计数器:统计网站的访问量,每次用户进行访问(MyVisitContext类),网站计数器count就会进行加一操作。最后将访问量展示出来(MyShowContext类)!

  • 涉及到的方法:
方法作用
public void setAttribute(String name, Object object)往域对象里面添加数据,添加时以key-value形式添加
public Object getAttribute(String name)根据指定的key读取域对象里面的数据
public void removeAttribute(String name)根据指定的key从域对象里面删除数据

MyVisitContext.java

public class MyVisitContext extends HttpServlet {
	// ServletContext context = null;

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ServletContext context = getServletContext();
		Integer count = (Integer) context.getAttribute("count");
		if (count == null) {
			count = 1;
		} else {
			count += 1;
		}
		context.setAttribute("count", count);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

MyShowContext.java

public class MyShowContext extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {		
		ServletContext context = getServletContext();
		//获取访问的次数
		int conut = (int) context.getAttribute("count");
		//设置响应的编码类型
		response.setContentType("text/html;charset=utf-8");
		//得到输出对象
		PrintWriter out = response.getWriter();
		out.println("<H1>共访问MyVisitContext"+conut+"次</H1>");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

运行结果展示:
数据共享展示

3、实现Servlet的请求转发

方法作用
public RequestDispatcher getRequestDispatcher(String path)返回一个 RequestDispatcher 对象,它充当位于给定路径上的资源的包装器。可以使用 RequestDispatcher 对象将请求转发到资源,或者在响应中包含资源。资源可以是动态的,也可以是静态的。

HTTP的协议

* 请求
* referer 记住当前网页的来源
* user-agent 浏览器版本信息
* if-modefied-since

* 响应
* 响应头
* location 和302一起来完成重定向的操作
* refresh 页面的定时刷新
* last-modefied和 if-modefied-since和304状态码一起来控制缓存。

区别两个重要的概念:
请求转发:服务器内不进行资源流转 (一次请求一次响应,来实现资源流转)
1、地址栏不会改变

2、只能跳转到项目内的资源,不能跳转项目外的资源。

3、浏览器向服务器发出一次请求,那么可以使用请求作为域对象共享数据。

重定向(重新定位方向):302+Location(两次请求两次响应):

1、地址栏会改变,变成重定向到的地址

2、可以转跳到项目内资源,也可以转跳到项目外资源

3、浏览器向服务器发送两次请求,不可以使用请求来作为域对象来共享数据
举例说明

  • 重定向:你找我借钱,我没有,我告诉你谁有,你自己去找他借钱
  • 请求转发:你找我借钱,我没有,我去给你借钱,但是你不需要考虑钱是哪里来的(我自己内部的事情)。反正你找我借钱我借给你了

ContextTest03.java

public class ContextTest03 extends HttpServlet {
/**
 * 实现请求转发
 */
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		//实现请求转发的关键代码
		RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher("/ContextTest04");
		//执行完这一行将转跳到ContextTest04的servlet类中
		dispatcher.forward(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

ContextTest04.java

public class ContextTest04 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		PrintWriter out = response.getWriter();
		out.println("我是ContextTest03请求转发得到的");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

运行结果:
请求转发

4、读取web项目的资源文件

常用方法介绍:

方法作用
public String getContextPath()返回 Web 应用程序的上下文路径。(工程名字)
public String getRealPath(String path)getRealPath()获得的是绝对路径
public java.net.URL getResource(String path)getResource()获得的是相对路径
public java.util.Set getResourcePaths(String path)返回指向 Web 应用程序中资源的所有路径的类似目录的清单,这些路径中最长的子路径与提供的 path 参数匹配。
public java.io.InputStream getResourceAsStream(String path)以 InputStream 对象的形式返回位于指定路径上的资源。 如果指定路径上没有资源,则此方法返回 null。

涉及到的知识点:

  • getRealPath()和getResource()区别:

      1、getRealPath()获得的是绝对路径,getResource()获得的是相对路径;
      2、对于 开发人员来说都是使用相对路径,因为使用的是绝对路径一旦你换了服务器或者系统,那便会出现路径或者类加载的错误。
      3、典型的:如果你在windows下可能有C,D盘之分,但是在linux系统下便没有盘符之分了,所以建议使用getResource()。
      4、如果你使用的是getResource()你在用myeclipse或者eclipse时把项目压
      缩成war包后对你的部署工作不会存在影响,但是如果是用的绝对路径,一定会有影响!
    
  • URL中的getFile()和getPath()方法的区别:

       获取此URL的文件名。
       返回的文件部分将与getPath()相同,加上getQuery()的值的串联(如果有)。
       如果没有查询部分,则此方法和getPath()将返回相同的结果
    

分别创建txt文件1,2,3,4:
1.txt在WebRoot 外 — > 不会发布到tomcat服务器,无法在服务器端读取
2.txt 位于WEB-INF下 — > getServletContext().getResource("/WEB-INF/2.txt").getPath();
3.txt 位于WebRoot下 — > getServletContext().getResource("/3.txt").getPath();
4.txt 位于src下,复制到WEB-INF/classes下 —> getServletContext().getResource("/WEB-INF/classes/4.txt").getPath();

测试代码:

public class ContextTest extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 获得ServletContext
		ServletContext context = this.getServletContext();
		// getContextPath()方法
		String path1 = context.getContextPath();
		// getRealPath()方法
		String path2 = context.getRealPath("/");
		String path3 = context.getRealPath("");
		// getResource()方法,getPath()和getPath();
		String path4 = context.getResource("/").getPath();
		String path5 = context.getResource("").getPath();

		System.out.println(path1);
		System.out.println(path2);
		System.out.println(path3);
		System.out.println(path4);
		System.out.println(path5);
		// System.out.println("-------------------------------读取文件1.txt---------------------------------");
		// 读取文件1.txt,因为在WebRoot外面不会发布到tomcat服务器上,无法在服务器端读取
		// String filename1 = "";
		// readfile(filename1);Q
		System.out.println("-------------------------------读取文件2.txt---------------------------------");
		// 读取文件2.txt。
		String filename2 = context.getResource("/WEB-INF/2.txt").getPath();
		readfile(filename2);
		// D:/tomcat8/apache-tomcat-8.0.53-windows-x64/apache-tomcat-8.0.53/webapps/day03_2/WEB-INF/2.txt
		// 2222222222222222222222

		System.out.println("-------------------------------读取文件3.txt---------------------------------");
		// 读取文件3.txt
		String filename3 = context.getResource("/3.txt").getPath();
		readfile(filename3);
		// D:/tomcat8/apache-tomcat-8.0.53-windows-x64/apache-tomcat-8.0.53/webapps/day03_2/3.txt
		// 33333333333333333333333333333333
		// D:\tomcat8\apache-tomcat-8.0.53-windows-x64\apache-tomcat-8.0.53\webapps\day03_1\3.txt
		// 3333333333333333333333333

		System.out.println("-------------------------------读取文件4.txt---------------------------------");
		// 读取文件4.txt
		String filename4 = context.getResource("/WEB-INF/classes/4.txt").getPath();
		readfile(filename4);
		// D:/tomcat8/apache-tomcat-8.0.53-windows-x64/apache-tomcat-8.0.53/webapps/day03_2/WEB-INF/classes/4.txt
		// 444444444444444444444

		System.out.println("-------------------------------读取文件4.txt(类加载器)---------------------------------");
		// getResource
		// public URL getResource(String name)查找带有给定名称的资源。
		// 查找与给定类相关的资源的规则是通过定义类的 class loader 实现的。
		// 此方法委托给此对象的类加载器。如果此对象通过引导类加载器加载,
		// 则此方法将委托给 ClassLoader.getSystemResource(java.lang.String)。

		// 使用类加载器进行4.txt的读取
		URL url = ContextTest.class.getResource("/4.txt");
		// 将上面的url转化为字符串
		String file1 = ContextTest.class.getResource("/4.txt").getFile();
		String file2 = ContextTest.class.getResource("/4.txt").getPath();
		System.out.println(url);
		System.out.println(file1);
		System.out.println(file2);
		readfile(file2);
		// file:/D:/tomcat8/apache-tomcat-8.0.53-windows-x64/apache-tomcat-8.0.53/webapps/day03_2/WEB-INF/classes/4.txt
		// /D:/tomcat8/apache-tomcat-8.0.53-windows-x64/apache-tomcat-8.0.53/webapps/day03_2/WEB-INF/classes/4.txt
		// /D:/tomcat8/apache-tomcat-8.0.53-windows-x64/apache-tomcat-8.0.53/webapps/day03_2/WEB-INF/classes/4.txt
		// /D:/tomcat8/apache-tomcat-8.0.53-windows-x64/apache-tomcat-8.0.53/webapps/day03_2/WEB-INF/classes/4.txt
		// 444444444444444444444
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

	public void readfile(String filename) throws IOException {
		System.out.println(filename);
		BufferedReader bufferedReader = new BufferedReader(new FileReader(filename));
		String line;
		while ((line = bufferedReader.readLine()) != null) {
			System.out.println(line);
		}
		bufferedReader.close();
	}
}

getResourceAsStream方法读取配置文件:

  • 在WEB-INF下面创建db1.properties文件

  • 在src.com.syj.getResourceAsStream下面创建db2.properties文件
    配置信息如下:

      //db1.properties文件
      id=001
      username=tom
      password=123456
    
      //db2.properties文件
      id=002
      username=xiaoming
      password=654321
    
public class test extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Test("/WEB-INF/classes/com/syj/getResourceAsStream/db2.properties");
		Test("/WEB-INF/db1.properties");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

	public void Test(String filename) throws IOException {
		InputStream is = getServletContext().getResourceAsStream(filename);
		Properties properties = new Properties();
		properties.load(is);
		
		String id = properties.getProperty("id");
		String username = properties.getProperty("username");
		String password = properties.getProperty("possword");
		
		System.out.println(id);
		System.out.println(username);
		System.out.println(password);
	}
}

结果:
getResourceAsStream

三、ServletContext的总结:

  • WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
  • 由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。
  • 创建:该web应用被加载(服务器启动或发布web应用(前提,服务器启动状态))
  • 销毁:web应用被卸载(服务器关闭,移除该web应用)

四、扩展:

  • 如果写硬盘的路径D:\tomcat8\apache-tomcat-8.0.53-windows-x64\apache-tomcat-8.0.53\webapps\项目名\资源,可以找到资源,但是只要一换发布环境,这个硬盘路径很可能是错误的,同样不行。
    为了解决这样的问题,ServletContext提供了getRealPath方法,在这个方法中传入一个路径,这个方法的底层会在传入的路径的前面拼接当前web应用的硬盘路径,从而得到当前资源的硬盘路径(即当前项目的路径),这种方式即使换了发布环境,方法的底层也能得到正确的web应用的路径从而永远都是正确的资源的路径。
  • 1、getRealPath()获得的是绝对路径,getResource()获得的是相对路径;
    2、对于 开发人员来说都是使用相对路径,因为使用的是绝对路径一旦你换了服务器或者系统,那便会出现路径或者类加载的错误。
    3、典型的:如果你在windows下可能有C,D盘之分,但是在linux系统下便没有盘符之分了,所以建议使用getResource()。
    4、如果你使用的是getResource()你在用myeclipse或者eclipse时把项目压
    缩成war包后对你的部署工作不会存在影响,但是如果是用的绝对路径,一定会有影响!
  • 类路径classpath(src下)
    * 通过字节码对象读取Class
    getResource("/info.txt").getFile()
    * 获取字节码对象Class
    类名.class ——静态方法获取
    对象.getClass() —— 实例方法
  • 使用基本的FileInputStream 读取相对路径时 是相对于Tomcat安装程序的bin目录,而要想相对路径在Tomcat的webapps的当前应用的根路径,就需要使用 getResourceAsStream()方法。
  • 1、使用带有main函数java程序普通的java应用(Java Application)读取文件,可以使用相对路径和绝对路径、这个是属于在本地读取。
    2、在Servlet中读取资源文件,必须使用磁盘绝对路径 (服务器读取)

平时的小知识积累,在此以笔记的形式记录下来,如有错误欢迎指正
不积跬步,无以至千里;不积小流,无以成江海

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值