ServletContext 代表整个Web应用。
- Web应用中所有的Servlet 共享一个ServletContext。可以最为Servlet之间通信的桥梁。
- 获取Web应用的初始化参数
- 可以通过它来得到该Web工程所有的资源。
- 实现Servlet的转发
实现 Web工程下的 所有的Servlet 数据共享
public class ServletContextDemo1 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//将数据通过 ServletContext 传递给 其他的 Servlet
String data="基本密碼";
ServletContext servletContext=this.getServletContext() ;
servletContext.setAttribute("ServletContext的数据", data); //内部 是以 Map的形式实现的
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
另一个Servlet 得到ServletContextDemo1 所的共享的数据
public class ServletContextDemo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到 其他的Servlet 共享的数据
ServletContext servletContext=this.getServletContext();
String data=(String) servletContext.getAttribute("ServletContext的数据");
response.getOutputStream().write(data.getBytes());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
获取Web应用的初始化参数(整个web站点的参数 不止对应一个Servlet)
<context-param>
<param-name>xxx</param-name>
<param-value>yyy</param-value>
</context-param>
//获取整个站点下的 初始化参数信息
ServletContext servletContext=this.getServletContext() ;
String value=servletContext.getInitParameter("xxx");
实现Servlet的转发
当一个Servlet收到请求后,将此请求重定向给其他的Servelt去。让其他的Servlet去处理
public class ServletContextDemo1 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext s=this.getServletContext();
//收到請求后进行转发到 ServletContextDemo2中去
ServletContext s=this.getServletContext();
//次个操作无效 因为后面有转发的操作,转发操作的时候会把 response中清空 。在转发前的所有写入无效。2.在转发前不能提交,否服务器会报异常。
response.getOutputStream().write("这个是ServletContextDemo1过来的数据哦".getBytes());
RequestDispatcher requestDispatcher= s.getRequestDispatcher("/ServletContextDemo2");
requestDispatcher.forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
public class ServletContextDemo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getOutputStream().write("这个是ServletContextDemo1过来的数据哦".getBytes());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
当ServletContextDemo1 收到请求后转发给ServletContextDemo2 处理。
一般Servlet 当服务器得到请求后,要将 排版后(HTML格式)的数据交给浏览器处理,但是Servlet并不适合排版的处理,通常是转发给 JSP进行处理。
/**
* 请求的转发 给jsp
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String data="jibenmima";
this.getServletContext().setAttribute("name", data);
RequestDispatcher r =request.getRequestDispatcher("/JspDemo1.jsp");
//请求转发的第两种方式 没有区别
// RequestDispatcher r = this.getServletContext().getRequestDispatcher("/JspDemo1.jsp");
r.forward(request, response);
//当要给jsp传递数据的时候 千万不能用上面的方式 。用 ServletContext来存放数据,然后再根据ServletContext来获取。
//这样有线程安全的问题。因为所有的访问都是用的同一个 ServletContext 后面的可能会把之前的覆盖掉
//所有这个时候就要用到 request.setAttribute(name, o); 这个方法了。request 是作为一个域容器,将数据存放到域容器中,在jsp等 获取就行
String data="jibenmima";
request.setAttribute("name", data);
RequestDispatcher r =request.getRequestDispatcher("/JspDemo1.jsp");
r.forward(request, response);
System.out.println(data);
}
下面是jsp的代码 jsp自认为就是可以写java代码的html
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<%
String name=(String)this.getServletContext().getAttribute("name");
out.write(name);
//要用此方式来进行接收数据 不要用上面的
String name=(String) request.getAttribute("name");
out.write(name);
%>
</body>
</html>
可以通过它来得到该Web工程所有的资源
首先在src下面创建 db.properties 用来保持数据库的配置信息
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=root
通过流来读取此文件,注意这里有个文件的路径问题。因为我们是将程序发布到Tomcat中的webapps中去,在启动程序的时候,相当于启动了bin中的startup.bat。相当于这个文件是相对于bin文件的路径来调用的。我们把db.properties文件复制一份到bin文件中,直接调用
FileOutputStream fileOutputStream=new FileOutputStream("db.properties");
System.out.println(fileOutputStream);
没问题的。这个目录(bin)相当于java虚拟机的启动目录。但是这个方式很恶心。不建议使用。
既然这个ServletContext代表整个web资源,那么它肯定有方法来获取整个web资源的方法。
下面是代码
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//当 src下有资源的话
// getServletContext代表整个Web应用。
// 而这个 db.properties 发布后的路径是
// D:\tomcat\apache-tomcat-8.5.8\wtpwebapps\Day052\WEB-INF\classes
// 所以这个 dbpath 为下面路径
String dbPath = "/WEB-INF/classes/db.properties";
InputStream inputStream = getServletContext().getResourceAsStream(dbPath);
//读取 db.properties 中的数据
Properties properties = new Properties();
properties.load(inputStream);
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
//当然你也可以用 getRealPath 方法来获取资源的绝对路径
String path=getServletContext().getRealPath("/WEB-INF/classes/db.properties");
FileOutputStream fileOutputStream=new FileOutputStream(path);
//下面是模板代碼進行讀取 內容
//当 scr下面有资源的话 可以用类加载器进行加载资源
//但是类加载器有问题。当资源文件过大的时候,或导致虚拟机崩溃 内存溢出(不建议使用)
//因为 在目录下面生成的.class文件需要有类的加载器来调用 java类,那么也能调用 该目录下面的资源
ClassLoader servletContextLoader = ServletContextDemo2.class.getClassLoader();//得到类的加载器
InputStream inputStream2=servletContextLoader.getResourceAsStream("db.properties");
//下面是模板代碼進行讀取 內容
//当项目下有资源的话,D:\tomcat\apache-tomcat-8.5.8\wtpwebapps\Day052
InputStream inputStreamRoot = getServletContext().getResourceAsStream("/dba.properties");
}
读取 src下面的文件到 e盘下song文件夹下
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// test1();
//读取 src下面的文件 复制到 D盘中song的文件夹下
//1、 获取此文件的绝对路径以便能截取它的名字,方便后边给它赋名字
String path=this.getServletContext().getRealPath("/WEB-INF/classes/movie.avi");
System.out.println(path);//打印為:D:\tomcat\apache-tomcat-8.5.8\wtpwebapps\Day052\WEB-INF\classes\movie.avi
//根据路径来得到 文件的名字
String pathName=path.substring(path.lastIndexOf("\\")+1);
FileInputStream fileInputStream=new FileInputStream(path);
//模板代码
byte[] buffer=new byte[1024];
int len=0;
FileOutputStream fileOutputStream=new FileOutputStream("e://song//"+pathName);
while((len=fileInputStream.read(buffer))>0)
{
fileOutputStream.write(buffer,0,len);
}
fileOutputStream.close();
fileInputStream.close();
response.getWriter().write("成功");
}
当没有ServletContext时,用类加载器来加载资源。下面的代码包含了流的操作和properties的读和写
public class Dao {
// 文件的 工具类 用来读取 信息,比如 db.properties
//当读取src下面的文件的时候,必须使用 类加载器了 因为这里没有ServletContext对象的实例
public void getInfo(){
try {
//这里必须使用 Dao.class.getClassLoader().getResource()方法。
//因为 当如果用 getResourceAsStream(name)时,返回的是一个 inputStream。当类加载的时候只会加载一次。
//当你向里面重新写数据后,次 流中 的数据不变化。 所有要使用 返回 绝对路径的方法。
URL url= Dao.class.getClassLoader().getResource("db.properties");
String path=url.getPath();
FileInputStream fileInputStream=new FileInputStream(path);
Properties properties=new Properties();
properties.load(fileInputStream);
String propertiesUrl=properties.getProperty("url");
properties.setProperty("name", "value");
//注意此方法的位置。当你new FileOutputStream(path)的时候,它会默认将里面的数据清空。一定要等到
//properties.load(fileInputStream); 后再进行new 次对象
FileOutputStream outputStream=new FileOutputStream(path);
//将数据 刷新到流中
properties.store(outputStream, "");
} catch (Exception e) {
e.printStackTrace();
}
}