javaweb-day05-5&6&7(Servlet - ServletConfig对象 和 ServletContext对象)

ServletConfig对象

  • 在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数。
  • 当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。
  • 阅读ServletConfig API,并举例说明该对象的作用:
    • 获得字符集编码
    • 获得数据库连接信息
    • 获得配置文件,查看struts案例的web.xml文件

package cn.mengmei.servlet;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletConfigDemo1 extends HttpServlet {

	private ServletConfig config;
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		/*
		//获取指定的初始化参数
		String value = config.getInitParameter("xxx");
		response.getOutputStream().write((value+"<br/>").getBytes());
		
		//获取全部初始化参数
		Enumeration e = config.getInitParameterNames();
		while(e.hasMoreElements()){
			String name = (String)e.nextElement();
			String value1 = config.getInitParameter(name);
			response.getOutputStream().write((name+"="+value1+"<br/>").getBytes());
		}
		
		//获得字符集编码,用于向浏览器输出中文
		String charset = config.getInitParameter("charset");
		response.setHeader("Content-Type", "text/html;charset="+charset);
		response.getWriter().write("中国");
		*/
		
		//获得数据库连接信息
		String url = config.getInitParameter("url");
		String username = config.getInitParameter("username");
		String password = config.getInitParameter("password");
	}

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

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

web.xml配置文件:

  <servlet>
    <servlet-name>ServletConfigDemo1</servlet-name>
    <servlet-class>cn.mengmei.servlet.ServletConfigDemo1</servlet-class>
    <init-param>
    	<param-name>xxx</param-name>
    	<param-value>yyy</param-value>
    </init-param>
    <init-param>
    	<param-name>charset</param-name>
    	<param-value>UTF-8</param-value>
    </init-param>
    <init-param>
    	<param-name>url</param-name>
    	<param-value>jdbc:mysql://localhost:3306/test</param-value>
    </init-param>
    <init-param>
    	<param-name>username</param-name>
    	<param-value>root</param-value>
    </init-param>
    <init-param>
    	<param-name>password</param-name>
    	<param-value>root</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>ServletConfigDemo1</servlet-name>
    <url-pattern>/servlet/ServletConfigDemo1</url-pattern>
  </servlet-mapping>


在开发中,这样获取ServletConfig对象:

package cn.mengmei.servlet;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletConfigDemo2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//GenericServlet的方法,直接获取ServletConfig对象:
		ServletConfig config = this.getServletConfig();
		response.getWriter().write(config.getInitParameter("aa"));
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
web.xml配置文件:
  <servlet>
    <servlet-name>ServletConfigDemo2</servlet-name>
    <servlet-class>cn.mengmei.servlet.ServletConfigDemo2</servlet-class>
    
    <init-param>
    	<param-name>aa</param-name>
    	<param-value>bb</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>ServletConfigDemo2</servlet-name>
    <url-pattern>/servlet/ServletConfigDemo2</url-pattern>
  </servlet-mapping>


ServletContext

  • WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
  • ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。
  • 由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context对象。
  • 查看ServletContextAPI文档,了解ServletContext对象的功能。


ServletContext应用

  • 多个Servlet通过ServletContext对象实现数据共享。
  • 获取WEB应用的初始化参数。
  • 实现Servlet的转发。
  • 利用ServletContext对象读取资源文件。
    • 得到文件路径
    • 读取资源文件的三种方式
    • .properties文件(属性文件)
1. 多个Servlet通过ServletContext对象实现数据共享:

package cn.mengmei.servlet;

import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletContextDemo1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//产生了数据
		String data = "abcdefg";
		//得到代表整个应用的ServletContext对象。
		ServletContext context = this.getServletContext();
		//将数据存到context对象的属性里
		context.setAttribute("data", data);
		//转给ServletContextDemo2来处理
		context.getNamedDispatcher("ServletContextDemo2").forward(request, response);
	}

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

		doGet(request, response);
	}

}

package cn.mengmei.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletContextDemo2 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//从ServletContext对象的属性里获取到数据
		String data = (String)this.getServletContext().getAttribute("data");
		//把数据输出给浏览器
		response.getWriter().write(data);
	}

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

		doGet(request, response);
	}

}
只需访问ServletContextDemo1就会得到ServletContextDemo2的运行结果。


2. 获取WEB应用的初始化参数。

package cn.mengmei.servlet;

import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletContextDemo3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		ServletContext context = this.getServletContext();
		
		String url = context.getInitParameter("url");
		String username = context.getInitParameter("username");
		String password = context.getInitParameter("password");
	}

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

		doGet(request, response);
	}

}
web.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>myday05</display-name>

	<context-param>
		<param-name>url</param-name>
		<param-value>jdbc:mysql://localhost:3306/test</param-value>
	</context-param>
	
	<context-param>
		<param-name>username</param-name>
		<param-value>root</param-value>
	</context-param>
	
	<context-param>
		<param-name>password</param-name>
		<param-value>root</param-value>
	</context-param>

  <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>ServletContextDemo3</servlet-name>
    <servlet-class>cn.mengmei.servlet.ServletContextDemo3</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>ServletContextDemo3</servlet-name>
    <url-pattern>/servlet/ServletContextDemo3</url-pattern>
  </servlet-mapping>

</web-app>

3. 实现Servlet的转发。

package cn.mengmei.servlet;

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletContextDemo4 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		response.getOutputStream().write("1111111".getBytes());  //不会输出,请求转发时会清空response。
		
		/*
		OutputStream out = response.getOutputStream();
		out.write("关掉流,此数据会强制刷给浏览器,但是后面的转发会抛异常:Cannot forward after response has been committed".getBytes());
		out.close();
		*/
		
		ServletContext context = this.getServletContext();
		RequestDispatcher rd = context.getRequestDispatcher("/servlet/ServletContextDemo5");  //
		rd.forward(request, response);
		
		System.out.println("haha");  //会执行
		response.getOutputStream().write("4444444444".getBytes());  //不会输出。
	}

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

		doGet(request, response);
	}

}
package cn.mengmei.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletContextDemo5 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.getOutputStream().write("ServletContextDemo5".getBytes());
	}

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

		doGet(request, response);
	}

}
请求ServletContextDemo4会显示ServletContextDemo5的运行结果。


4. 利用ServletContext对象读取资源文件。

资源放在类目录下时:

package cn.mengmei.servlet;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletContextDemo6 extends HttpServlet {

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

	//读取web工程中资源文件的模板代码
	public void test1() throws IOException {
		//此代码在web工程中行不通,因为web工程发布以后就没有src目录。
		//FileInputStream in = new FileInputStream("src/db.properties"); //相对路径,代码由谁运行它就相对于谁
		/*这个web应用由服务器来运行,所以这个java类由服务器调用。
		 * 服务器运行时靠bin目录下的二进制文件。
		 * tomcat的bin目录和webapps目录下的web应用的classes目录没有相对关系。
		 * ServletContext对象代表web应用,所以需要用ServletContext对象来读取。*/
		
		InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); //用ServletContext读,第一个“/”代表web工程。
		
		Properties prop = new Properties();
		prop.load(in);
		String driver = prop.getProperty("driver");
		String url = prop.getProperty("url");
		String username = prop.getProperty("username");
		String password = prop.getProperty("password");
		
		System.out.println(driver);
	}
	
	public void test2() throws IOException {
		//这个代码是获取web工程资源在硬盘的绝对路径。
		String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties");
		
		System.out.println(realPath);
		
		//有了web资源在硬盘的绝对路径,就可以使用普通流来读取了:
		FileInputStream in = new FileInputStream(realPath);
		
		Properties prop = new Properties();
		prop.load(in);
		String driver = prop.getProperty("driver");
		String url = prop.getProperty("url");
		String username = prop.getProperty("username");
		String password = prop.getProperty("password");
		
		System.out.println(driver);
	}

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

		doGet(request, response);
	}

}

资源放在WebRoot目录下时:

package cn.mengmei.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletContextDemo7 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		InputStream in = this.getServletContext().getResourceAsStream("/db1.properties"); //此“/”代表此web工程
		
		Properties prop = new Properties();
		prop.load(in);
		String driver = prop.getProperty("driver");
		String url = prop.getProperty("url");
		String username = prop.getProperty("username");
		String password = prop.getProperty("password");
	
		System.out.println(driver);
	}

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

		doGet(request, response);
	}

}


5. 资源文件放在类目录下时,更专业的方式是:用类加载器来读取。

package cn.mengmei.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletContextDemo8 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		test2();
	}
	
	//用类装载器 获取src目录下的资源文件
	public void test1() throws IOException {
		//获取当前类的类装载器:
		ClassLoader loader = ServletContextDemo8.class.getClassLoader();
		InputStream in = loader.getResourceAsStream("db.properties");  //类装载器就是用来装载classes目录下面所有类的,db.properties正好也在classes目录下。
		
		Properties prop = new Properties();
		prop.load(in);
		String driver = prop.getProperty("driver");
		
		System.out.println(driver);
	}

	
	//用类装载器获取src下的某个包下的资源文件
	public void test2() throws IOException {
		//获取当前类的类装载器:
		ClassLoader loader = ServletContextDemo8.class.getClassLoader();
		InputStream in = loader.getResourceAsStream("cn/mengmei/servlet/db2.properties");  //类装载器就是用来装载classes目录下面所有类的,db.properties正好也在classes目录下。
		
		Properties prop = new Properties();
		prop.load(in);
		String driver = prop.getProperty("driver");
		
		System.out.println(driver);
	}


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

		doGet(request, response);
	}

}
类装载器用装载类的方式装载资源文件,有一个隐患需要注意:

  • 它会把整个资源文件都装载到内存中来,并且一直滞留在内存中。如果这个资源文件特别大,java虚拟机会内存溢出。
  • 用类装载的方式装载,不适合装载大文件。

6. 用ServletContext对象将src目录下的大文件拷贝到硬盘中:

package cn.mengmei.servlet;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletContextDemo9 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//用来截取文件名
		String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/haha.mp4");
		//System.out.println(realPath);  //C:\javaweb\apache-tomcat-7.0.42\webapps\myday05\WEB-INF\classes\haha.mp4
		String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
		
		//用ServletContext对象将src目录下的大文件拷贝到硬盘中
		InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/haha.mp4");
		byte[] buffer = new byte[1024];
		int len = 0;
		
		FileOutputStream out = new FileOutputStream("C:/javaweb/"+fileName);
		while((len=in.read(buffer))>0){
			out.write(buffer, 0, len);
		}
		out.close();
		in.close();
	}
	

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

		doGet(request, response);
	}

}


7.在实际开发中,可能根本就不会用Servlet去读取文件,而是用另外一个类:Dao

package cn.mengmei.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.mengmei.dao.Dao;

public class ServletContextDemo10 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		Dao dao = new Dao();
		dao.run();
	}

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

		doGet(request, response);
	}

}

package cn.mengmei.dao;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;

public class Dao {
	
	public void run() throws IOException {
		//通过类装载器,只是为了获取资源的绝对路径。
		URL url = Dao.class.getClassLoader().getResource("db.properties");
		String realPath = url.getPath();
		
		//通过传统流来读取,避免了类装载器只装载一次 导致 新写进去的内容读不到的弊端。
		FileInputStream in = new FileInputStream(realPath);
		
		Properties prop = new Properties();
		//加载
		prop.load(in);
		
		System.out.println(prop.getProperty("driver"));
		System.out.println(prop.getProperty("url"));
		System.out.println(prop.getProperty("username"));
		System.out.println(prop.getProperty("password"));
		System.out.println(prop.getProperty("name"));
		
		//这条如果写在加载前,会导致整个properties文件被清空。
		FileOutputStream out = new FileOutputStream(realPath);
		
		//写入一条数据。
		prop.setProperty("name", "mm");
		//更新到硬盘。
		prop.store(out, "注释不写也行");
	}
	
}

//注意:src下的properties文件只有在文件里修改后,重新发布到服务器才会被重新加载。

src下的db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=root

浏览器,第二次运行:http://localhost:8080/myday05/servlet/ServletContextDemo10 ,会看到更新后的数据。




在客户端缓存Servlet的输出

  • 对于不经常变化的数据,在servlet中可以为其设置合理的缓存时间值,以避免浏览器频繁向服务器发送请求,提升服务器的性能。
package cn.mengmei.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletDemo4 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		String data = "abcdefg";
		response.setDateHeader("Expires", System.currentTimeMillis()+24*3600*1000); //从现在开始缓存一天。
		response.getOutputStream().write(data.getBytes());
	}

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

		doGet(request, response);
	}

}

用 HttpWatch 抓取的 http 响应:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Expires: Tue, 20 Jan 2015 15:49:43 GMT
Content-Length: 7
Date: Mon, 19 Jan 2015 15:49:43 GMT


abcdefg







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值