Servlet
servlet概述
servlet是什么
- Servlet是sun公司提供的一门用于开发动态web资源的技术
- 按照这套规范写出来的Servlet可以放置到web应用中,在Servlet容器中运行
开发Servlet步骤
- 写一个类,实现
Servlet
接口,并实现其中的方法 - 在
web.xml
中为servlet
配置对外访问路径 (Idea中可直接通过注解实现)
开发servlet
-
创建一个web的project
-
更改默认浏览器、端口号和URL
-
创建一个Servlet
// 注解 // urlPatterns = "/demo01" 代表对外访问路径 @WebServlet(name = "ServletDemo1", urlPatterns = "/demo01") public class ServletDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Date date = new Date(); String datestr = date.toLocaleString(); // 将时间字符串响应给客户端 response.getWriter().write(datestr); } }
- 重启浏览器生效
Servlet的继承结构
Servlet接口
– 提供了一个Servlet应该具有的最基本的功能
|
|-- GenericServlet类
, 实现了Servlet接口,并实现了其中大部分的方法,但是 service()
没有实现,这个方法需要开发人员自己去实现
|
|-- HttpServlet类
,继承了GenericServlet类
,并实现了 service()
,在service()
中是根据不同的请求方式,调用不同的doXxx方法 (所有的请求方式实际首先由service()
处理);在开发中,只需要写一个类,继承HttpServlet类
,并覆盖doGet()
和 doPost()
方法分别来处理Get请求和POST请求即可
Servlet调用过程
调用过程
- 接收请求,通过url-pattern匹配资源
- 如果匹配上,则找到servlet-mapping的servlet-name
- 根据servlet-mapping的servlet-name,找到servlet中同名的serlet-name
- 找到对应的servlet-class,处理具体的请求
Web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<!--第三步:根据servlet-mapping的servlet-name,找到servlet中同名的serlet-name-->
<servlet-name>Servlet01</servlet-name>
<!--第四步:找到对应的servlet-class,处理具体的请求-->
<servlet-class>cn.ysu.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
<!--第二步:如果匹配上,则找到servlet-name-->
<servlet-name>Servlet01</servlet-name>
<!--第一步:接收请求,通过url-pattern匹配资源-->
<url-pattern>/demo2</url-pattern>
</servlet-mapping>
</web-app>
- 在Idea中可以通过注解
@WebServlet(name = "ServletDemo1", urlPatterns = "/demo02")
代替底层的实现
Servlet生命周期
- Servlet实例在第一次被访问时创建,创建之后服务器会立即调用
init()
进行初始化的操作,从此以后该实例会一直驻留在服务器的内存中,为后续的请求服务 - 只要有请求访问servlet,服务器就会调用
service()
来处理这个请求,直到服务器关闭或者是web应用被移出容器时为止 - 随着web应用的销毁,servlet实例也会跟着销毁,在销毁之前,服务器就调用destroy方法进行善后的处理
Request
- 代表http请求的对象
继承结构
ServletRequest
– 提供一个request对象最基本的功能
|
|-- HttpServletRequest
– 继承了ServletRequest接口
,并在其基础上添加了很多和Http协议相关的方法
request的功能
获取客户端相关的信息
getRequestURL()
– 返回客户端发出请求完整URLgetRequestURI()
– 返回请求行中的资源名部分getQueryString()
– 返回请求行中的参数部分getRemoteAddr()
– 返回发出请求的客户机的IP地址getMethod()
– 得到客户机请求方式getContextPath()
– 获得当前web应用虚拟目录名称
注意:在写路径时不要将web应用的虚拟路径的名称写死, 应该在需要写web应用的名称的地方通过getContextPath方法动态获取
@WebServlet(name = "ServletDemo2", urlPatterns = "/demo02")
public class ServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 当请求是post时,调用doGet(),这样只需要关注一个方法
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// request方法
// 1. 获取客户端信息
// 获取请求url
StringBuffer url = request.getRequestURL();
System.out.println(url); // http://localhost/demo02
// 获取请求uri (资源名)
String uri = request.getRequestURI();
System.out.println(uri); // /demo2
// 获取参数部分
// 访问 http://localhost/demo02?username=tom&passsword=123
// 打印 username=tom&passsword=123
String qs = request.getQueryString();
System.out.println(qs);
// 获取客户端的ip
String addr = request.getRemoteAddr();
System.out.println(addr);
// 0:0:0:0:0:0:0:1 ipv6格式
// 获取请求方式
String method = request.getMethod();
System.out.println(method); // GET
// 获取web命令名称
String path = request.getContextPath();
System.out.println(path); // 打印为空,因为默认访问路径为 http://localhost/
}
}
获取请求头信息
getHeader(name)
— StringgetHeaders(String name)
— Enumeration
可以通过遍历枚举遍历每一个信息getHeaderNames()
— EnumerationgetIntHeader(name)
— intgetDateHeader(name)
— long(日期对应毫秒)
获取请求参数
getParameter(String name)
— String 通过name获得值getParameterValues(String name)
— String[ ] 通过name获得多值 checkboxgetParameterMap()
— Map<String,String[ ]> key :name value: 多值getParameterNames()
— Enumeration 获得所有name
@WebServlet(name = "ServletDemo3", urlPatterns = "/demo03")
public class ServletDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 当请求是post时,调用doGet(),这样只需要关注一个方法
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 2. 获取请求头信息,参数为请求头的key
String host = request.getHeader("Host");
System.out.println(host); // localhost
// 3. 获取请求参数
// 访问http://localhost/demo03?username=lili&password=123
// String username = request.getParameter("username");
// String password = request.getParameter("password");
// System.out.println(username + "," + password); // lili,123
// 示例:提交表单
// <form method="post" action="http://localhost/demo03">
// 获取请求参数,根据请求的key获取value值
String username = request.getParameter("userName");
String password = request.getParameter("psw");
String pswConfig = request.getParameter("pswConfig");
System.out.println(username + "," + password + "," + pswConfig); // Tom,123456,123456
// 获取同一个key对应的多个值
String[] hs = request.getParameterValues("hobby");
System.out.println(Arrays.toString(hs));
// 获取请求参数组成的Map
Map<String, String[]> map = request.getParameterMap();
for (Map.Entry<String,String[]> entry : map.entrySet()){
String key = entry.getKey();
String[] value = entry.getValue();
System.out.println(key + "," + Arrays.toString(value));
}
}
}
可能出现的乱码问题
-
乱码分析: 编码时和解码时使用的码表不一致造成的
-
编码: 是在浏览器端进行的,浏览器在打开当前页面时使用的是什么码表,也会使用相同的码表来发送数据 (meta标签指定)。
-
解码: 是在服务器端进行的,可以进行指定:
request.setCharacterEncoding("utf-8");
-
通知服务器使用什么编码来接受请求实体内容中的数据,如果使用的是POST提交,POST提交的请求参数就是在请求实体内容中
-
GET提交的请求参数由于不在请求实体内容中,而是在请求行中的请求资源路径后面拼接着,所以这行代码对GET提交的参数乱码不起作用
-
Get提交的论码问题可以通过手动编码解决,如
// username为乱码,通过乱码反向编码得回二进制数组 byte[] bytes = username.getBytes("iso8859-1"); // 通过二进制数组查询正确的码表, 得出正确的数据 username = new String(bytes, "utf-8");
-
实现请求转发
请求转发和请求重定向都可以实现资源的跳转,但是区别是请求转发是服务器内部的并且是同一个WEB应用内部的资源跳转
请求转发的特点:
- 一次请求对应一次响应
- 地址栏地址不会发生变化
- 请求转发只能在同一个web应用内部资源之间进行跳转,不能是不同的web应用或者不同的主机
请求重定向: 302状态码+location响应头
@WebServlet(name = "ServletDemo4", urlPatterns = "/demo04")
public class ServletDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// demo04将请求转发到demo05
// getRequestDispatcher参数为转发的路径: http://localhost/demo05
// 此路径可以省略web应用之前的名称 /demo05
request.getRequestDispatcher("/demo05").forward(request,response);
}
}
@WebServlet(name = "ServletDemo5", urlPatterns = "/demo05")
public class ServletDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("welcome to demo05");
// response.flushBuffer();
request.getRequestDispatcher("/demo01").forward(request,response);
}
}
request开发细节:
-
在转发之前,如果response缓冲区被写入了数据但是还没有发送给浏览器,在转发时response缓冲区(数据)将会被清空
response.getWriter().write("welcome to demo05"); // response.flushBuffer(); request.getRequestDispatcher("/demo01").forward(request,response);
访问http://localhost/demo04,发现浏览器中并未得到"welcome to demo05"这段字符串的响应。
-
在转发之前, 如果response缓冲区被写入了数据并且已经打给了浏览器, 转发将会失败
response.getWriter().write("welcome to demo05"); response.flushBuffer(); request.getRequestDispatcher("/demo01").forward(request,response);
此时转发会报错,因为一次请求只能对应一次响应。
-
在同一个Servlet中转发不能进行多次 (A既转发B, 又转发给C);但是可以进行多重转发(比如A转发给B, B再转发给C)
作为域对象来使用
域对象:如果一个对象具有一个可以被看见的范围,利用该对象上的map可以在整个范围内实现资源的共享;如:request的整个请求链作为一个域
域对象提供的方法(可以操作map中的数据):
setAttribute(String name, Object value)
:用来存储一个对象,也可以称之为存储一个域属性getAttribute(String name)
: 用来获取request中的数据removeAttribute(String name)
: 用来移除request中的域属性getAttributeNames()
: 获取所有域属性的名称
生命周期:
- 一次请求开始时创建request对象,请求结束时销毁request对象
- 作用范围: 整个请求链
- 主要功能:
- 在整个范围内共享数据
- 带数据到目的地
示例:
@WebServlet(name = "ServletDemo4", urlPatterns = "/demo04")
public class ServletDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// demo04将请求转发到demo05
// 将信息添加到域中
request.setAttribute("msg01", "welcome to demo04");
request.getRequestDispatcher("/demo05").forward(request,response);
}
}
@WebServlet(name = "ServletDemo5", urlPatterns = "/demo05")
public class ServletDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// demo05将请求转发到demo06
// 将信息添加到request域中
request.setAttribute("msg02","welcome to demo05");
request.getRequestDispatcher("/demo06").forward(request,response);
}
}
@WebServlet(name = "ServletDemo6", urlPatterns = "/demo06")
public class ServletDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String msg01 = (String) request.getAttribute("msg01");
String msg02 = (String) request.getAttribute("msg02");
response.getWriter().write(msg01 + "," + msg02);
}
}
实现请求包含
请求包含是服务器内部资源合并的现象
如果浏览器访问Servlet A,但是A不能独立的处理这次请求,需要另外一个Servlet B帮忙,于是在A中可以将B包含进来
包含的代码如下:
request.getRequestDispatcher("B的路径").include(request, response);
将B包含进来后,将会由A和B共同来处理这次请求,处理的结果也会合并在一起,一起发送给浏览器!
Reponse
response概述
- 代表http响应的对象
继承结构
ServletResponse
– 通用的接口,定义了一个response对象应该具有的功能
|
|–HttpServletResponse
在ServletResponse基础上,增加很多和Http协议相关的方法
response重要方法
Http响应消息:
- 状态行:包含所遵循的协议 (如: HTTP/1.1)、状态码 (如: 200)
- 响应头:http中的响应头非常多
- 实体内容:服务器发送回的内容
设置状态码的方法
void setStatus(int sc)
设置响应头的方法
-
void setHeader(String name, String value)
-
void setDateHeader(String name, long date)
-
void setIntHeader(String name, int value)
-
void addHeader(String name, String value)
-
void addDateHeader(String name, long date)
-
void addIntHeader(String name, int value)
注:set为设置,当本来存在这个头时是修改,add只是添加。
设置响应实体内容的方法
ServletOutputStream getOutputStream()
PrintWriter getWriter()
response对象功能
向客户端发送数据
getOutputStream()
//字节流getWriter()
//字符流
a. 字节流发送数据的中文乱码问题
- 服务器端指定了用utf-8来发送数据,浏览器在接受数据时,如果不指定将使用默认的平台码GBK,编解码不一致导致乱码
解决方案:
response.setHeader("Content-Type", "text/html;charset=utf-8"); // 通知浏览器使用utf-8打开服务器发送过去的数据
// 等价于
response.setContentType("text/html;charset=utf-8");
b. 字符流发送数据的中文乱码问题
-
利用字符流发送数据,底层还是要转成字节
-
服务器会根据
getCharacterEncoding()
方法返回的编码来发送数据,如果没有指定,该方法默认返回iso8859-1
解决方案:
-
第一步:指定服务器发送数据使用utf-8
response.setCharacterEncoding("utf-8");
//通知服务器使用utf-8来发送响应实体中数据 -
第二步: 需要指定浏览器在接收数据时也使用同一个编码来打开数据
response.setHeader("Content-Type", "text/html;charset=utf-8");
等价于
response.setContentType("text/html;charset=utf-8");
-
需要注意的是:在通知浏览器使用什么编码接受服务器发送的数据时,服务器很智能,会使用相同的编码来发送数据,所以指定服务器以什么编码发送数据的代码可以省略不写
不管是字符流还是字节流,解决乱码问题,可以用一行代码搞定:
// 解决乱码问题
response.setContentType("text/html;charset=utf-8");
response开发细节
- getOutputStream()和getWriter() 这两个方法是互斥的,在一次请求当中调用了其中的一个,就不能再调用另一个
- 在调用完getOutputStream()或getWriter()方法之后,不需要手动去关闭流,服务器会自动帮我们去关闭
- 这两个方法获取到的流并不是指向客户端的流,而是指向response缓冲区的流,通过流将数据写入response缓冲区,service方法执行结束,请求回到服务器,由服务器将数据组织成响应消息发送浏览器
示例:
@WebServlet(name = "ResponseDemo1",urlPatterns = "/rsdemo1")
public class ResponseDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 解决乱码问题
response.setContentType("text/html;charset=utf-8");
// 1. 设置状态码
response.setStatus(200);
// 2. 设置响应头
response.setHeader("naem","zss");
// 3. 设置响应体
// 字节流
response.getOutputStream().write("getOutputStream\n".getBytes("utf-8"));
response.getOutputStream().write("字节流".getBytes("utf-8"));
// 字符流
// 字节流和字符流不能同时存在
// response.getWriter().write("getWriter\n");
// response.getWriter().write("字节流");
}
}
实现重定向
可以通过302状态码加上location响应头实现请求重定向
@WebServlet(name = "ResponseDemo2", urlPatterns = "/rsdemo2")
public class ResponseDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 请求重定向
// response.setStatus(302);
// response.setHeader("location","https://www.baidu.com/");
// 等价于
// 可以访问到web服务器以外的内容
response.sendRedirect("https://www.baidu.com/");
}
}
重定向的特点:
- 两次请求, 两次响应
- 地址栏地址会发生变化
- 既可以实现在同一个WEB应用内部资源之间进行跳转,也可以在不同的WEB应用或者是不同的服务器资源之间进行跳转
- 由于是两次请求,两次响应,无法通过request对象共享数据
定时刷新
与重定向类似,不同之处就是可以指定几秒之后跳转。
可以通过refresh头实现在多少秒之后跳转指定的资源.
@WebServlet(name = "ResponseDemo2", urlPatterns = "/rsdemo2")
public class ResponseDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 实现定时刷新
// 参数1:固定值,代表响应头
// 参数2:经过若干秒后跳转到指定的路径
response.setHeader("refresh","3;url = https://www.baidu.com/");
}
}
定时刷新的特点:
- 两次请求,两次响应
- 地址栏地址会发生变化
- 既可以实现在同一个WEB应用内部资源之间进行跳转,也可以在不同的WEB应用或者是不同的服务器资源之间进行跳转
控制浏览器的缓存行为
-
由于不同的浏览器的缓存行为可能是不同的, 我们可以在服务器中通过设置响应头来控制浏览器的缓存行为
-
当设置缓存后,浏览器第一次访问服务器拿到响应并将响应内存保存到浏览器中,再次访问时,直接访问缓存的内容,不再访问服务器
控制浏览器不要缓存:
setDateHeader("Expires", -1);
setHeader("Cache-control", "no-cache");
setHeader("Pragma", "no-cache");
控制浏览器缓存:
setDateHeader("Expires", System.currentTimeMillis()+1000*60*60*24);
// 设置缓存,缓存一天时间setHeader("Cache-control", "max-age=60");
//优先级更高
总结
请求转发/请求重定向/定时刷新都可以实现资源的跳转的区别
请求转发:
- 一次请求,一次响应 request对象是同一个 (可以使用request共享数据)
- 地址栏不会发生变化
- 只能用于服务器内部的资源跳转, 并且只能是同一应用中的不同资源上进行跳转,不可用在不同应用和不同服务器中的资源跳转
请求重定向:
- 两次请求,两次响应 request对象不是同一个 (不能使用request对象共享数据)
- 地址栏会发生变化
- 可以用于服务器内部的资源跳转,也可以用于不同应用和不同服务器之间的资源跳转
定时刷新:
- 两次请求,两次响应 request对象不是同一个
- 地址栏会发生变化
- 可以用于服务器内部的资源跳转,也可以用于不同应用和不同服务器之间的资源跳转
- 和重定向不同的是,定时刷新可以在刷新到新的地址之间设置一个时间,在间隔的这段时间内可以输出文本到浏览器并维系一段时间
请求转发/请求重定向/定时刷新都可以实现资源的应用场景
-
如果是同一服务器中的同一应用内部的资源跳转:
- 如果在跳转时,需要通过request对象带数据到目的地,只能用请求转发
- 如果在跳转时,希望地址栏地址不要发生变化,只能用请求转发
- 如果在跳转时,希望地址栏地址发生变化,只能使用重定向或定时刷新
- 如果没有什么具体需要,三种方式都可以,最好使用请求转发,可以减少访问服务器的次数,降低服务器的压力
-
如果是不同服务器或不同web应用内部的资源跳转,只能用重定向或者定时刷新:
- 由于重定向是立即跳转,而定时刷新是在多少秒之后再进行跳转,并且可以在跳转之前的时间里输出文本数据到浏览器并维系一段时间
- 如果跳转时,需要指定多少秒或者是需要在跳转之前发送数据到浏览器,只能使用定时刷新,否则两种方式都可以
ServletContext
概述与生命周期:
-
代表整个web应用的对象
-
当服务器启动时,服务器在启动时会依次加载web应用,每一个web应用加载完成后都会创建一个ServletContext对象唯一代表该web应用,这个对象一直存活,直到web应用移除出容器或服务器关闭时,随着应用销毁,ServletContext对象跟着销毁。
获取ServletContext对象
// 获取ServletContext
ServletContext context = this.getServletContext();
ServletContext功能
获取web应用的初始化参数
如果现有一段配置信息,不是属于某一个Servlet,而是希望在整个web应用中都可以获取到,可以将这段信息配置给整个web应用,再通过代表web应用的ServletContext对象来获取这些信息
- 在WEB-INF下的web.xml中配置初始化参数的方式:
<context-param>
<param-name>scparam1</param-name>
<param-value>scvalue1</param-value>
</context-param>
获取初始化参数的方式:
String getInitParameter(String name)
:获取当前web应用指定名称的初始化参数的值Enumeration getInitParameterNames()
:获取当前web应用所有初始化参数的名字的枚举
作为域对象来使用
- 如果一个对象具有一个可以被看见的范围,利用该对象上的map可以在整个范围内实现数据的共享
- ServletContext对象是一个域对象,利用这个对象上的map就可以在整个web应用内实现资源的共享
域对象提供的方法:
setAttribute(String name, Object obj)
: 添加或修改域属性Object getAttribute(String name)
: 通过属性名获取属性值removeAttribute(String name)
: 根据属性名删除属性Enumeration getAttributeNames()
: 获取所有域属性名字组成的枚举
域对象的特征:
- 生命周期: 随着服务器启动,web应用加载而创建,web应用销毁而销毁
- 作用范围: 整个web应用
- 主要功能: 在整个web应用范围内实现数据的共享
获取web资源文件
- 可以通过ServletContext对象提供的方法来获取web资源文件
servletContext对象提供的getRealPath()
是基于web应用的根路径去寻找配置文件,所以在getRealPath()
中还需要传入文件相对于web应用根路径的路径
方法为:servletContext.getRealPath(String path);
- 也可以通过类加载器来获取web资源文件
类加载器提供的getResource()
是基于web应用的类目录去寻找该配置文件,所以在getResource()
中还需要传入文件相对于classes目录的路径!
方法为:classLoader.getResource(String path).getPath();
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>username</param-name>
<param-value>lili</param-value>
</context-param>
<context-param>
<param-name>psw</param-name>
<param-value>root</param-value>
</context-param>
</web-app>
@WebServlet(name = "ServeltDemo1", urlPatterns = "/demo1")
public class ServeltDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取ServletContext
ServletContext context = this.getServletContext();
// 功能1: 获取web.xml中配置的参数信息
String username = context.getInitParameter("username");
String psw = context.getInitParameter("psw");
System.out.println(username + "," + psw); // lili,root
// 功能2:作为域对象
// 作用范围:整个web应用
// 生命周期:随着服务器启动,web应用加载而创建,web应用销毁而销毁
context.setAttribute("gender","女");
// 功能3:获取web资源
// WEB-INF下的东西,客户端不能随便访问
// context.getRealPath(""); 相当于进入了web目录
String path = context.getRealPath("WEB-INF/jdbcConfig.properties");
System.out.println(path);
Properties properties = new Properties();
properties.load(new FileInputStream(path));
System.out.println(properties.getProperty("user")
+", " + properties.getProperty("password"));
// 获取classes (src)下的资源
String path3 = context.getRealPath("WEB-INF/classes/mysql.properties");
System.out.println(path3);
// 通过类加载器
// 只能获取classes (src)作为根目录的资源
String path2 = ServeltDemo1.class.getClassLoader().
getResource("mysql.properties").getPath();
System.out.println(path2);
}
}
@WebServlet(name = "ServletDemo2",urlPatterns = "/demo2")
public class ServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 在这里获取gender属性
ServletContext context = this.getServletContext();
System.out.println(context.getAttribute("gender")); // 女
}
}