Part01:ServletContext
1、ServletContext的作用
- 获取全局初始化参数
- 资源共享(Servlet通信)
- 获取资源文件
2、ServletContext的生命周期
- 创建:服务器启动的时候会为每个项目创建一个ServletContext上下文对象,ServletContext是项目的一个引用
- 销毁:在服务器关闭或者项目被移除的时候ServletContext销毁
3、ServletContext的获取方式
- getServletConfig( ).getServletContext( )
- getServletContext( )
4、ServletContext的常用方法
- String getInitParameter(String name);//获取指定的项目的全局初始化参数
- Enumeration getInitParameterNames( );//获取项目所有初始化参数名称
- String getRealPath(String filepath);//获取一个资源在本地服务器上的路径
- InputStream getResourceAsStream(String filepath);//以流的方式返回一个文件
- String getMimeType(String 文件名);//获取一个文件的mime类型 如:text/html image/gif
5、一个小bug
- 不小心把ServletContext的获取(ServletContext servletContext = getServletContext();)直接写在Servlet类中,出现500Error instantiating servlet class Servlet.MyServlet异常,刷新后又变成404异常,后来把获取方式写在doGet方法中就正常了

6、ServletContext的常用方法的使用
- 在web.xml文件的标签中配置全局初始化参数

//获取servletContext
ServletContext servletContext = getServletContext();
//获取全局初始化参数
String dbValue = servletContext.getInitParameter("db");
System.out.println(dbValue);
//获取全部全局初始化参数名称
Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
//遍历
while (initParameterNames.hasMoreElements()){
String string = (String) initParameterNames.nextElement();
System.out.println(string+":"+servletContext.getInitParameter(string));
}
//获取一个资源在本地服务器上的路径
String path = servletContext.getRealPath("/h.html");
System.out.println(path);
//以流的形式返回一个文件
InputStream is = servletContext.getResourceAsStream("/h.html");
//读取这个文件并打印
byte[] bytes = new byte[1024];
int b =0;
while ((b=is.read(bytes)) != -1){
System.out.println(new String(bytes,0,b));
}
//获取一个文件的mime类型
String mime = servletContext.getMimeType("/h.html");
System.out.println(mime);

7、资源共享的实现
- 方法
- setAttribute(String name,Object value);//设置
- getAttribute(String name);//获取指定的属性值
- removeAttribute(String name);//移除指定的属性
- 需求
- Servlet2获取到Servlet1中添加的数据
- Servlet3删除Servlet1中添加的数据
//Servlet1:
@WebServlet(name = "Servlet1",urlPatterns = {"/Servlet/Servlet1"})
public class Servlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext对象
ServletContext servletContext = this.getServletContext();
//往上下文对象中放数据
servletContext.setAttribute("FF","HH");
}
}
//Servlet2:
@WebServlet(name = "Servlet2",urlPatterns = {"/Servlet/Servlet2"})
public class Servlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext对象
ServletContext servletContext = this.getServletContext();
//从ServletContext对象中获取Servlet1中的数据
Object obj = servletContext.getAttribute("FF");
System.out.println(obj);
}
}
//Servlet3:
@WebServlet(name = "Servlet3",urlPatterns = {"/Servlet/Servlet3"})
public class Servlet3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取ServletContext对象
ServletContext servletContext = this.getServletContext();
//删除ServletContext对象的值
servletContext.removeAttribute("FF");
}
}
Part02:记录访问次数案例
1、需求:
- 有一个页面提供两个超链接,第一个超链接记录访问次数,每访问一次,访问次数增加一次,第二个超链接查看另一个记录访问次数的结果。
//记录访问次数的Servlet
@WebServlet(name = "CountServlet",urlPatterns = {"/Servlet2/CountServlet"})
public class CountServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建ServletContext对象
ServletContext servletContext = getServletContext();
//从ServletContext中获取访问次数
Integer count =(Integer) servletContext.getAttribute("count");
//判断是否是第一次访问
if(count==null){
//若是第一次访问:给当前访问次数设置为1;
count=1;
}else {
//若不是,访问次数加1
count++;
}
//把当前访问次数存入ServletContext对象中
servletContext.setAttribute("count",count);
//System.out.println(count);
}
}
//查看访问次数的Servlet
@WebServlet(name = "ShowServlet",urlPatterns = {"/Servlet2/ShowServlet"})
public class ShowServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置response编码格式为utf-8,这样给前台写中文信息不会出现乱码
response.setHeader("content-type","text/html;charset=utf-8");
//创建ServletContext对象
ServletContext servletContext = getServletContext();
//获取访问次数
Integer count = (Integer) servletContext.getAttribute("count");
//输出访问次数到屏幕上
response.getWriter( ).print("访问次数为:"+(count==null?0:count));
}
}

Part03:response响应
1、响应行:
- 格式:协议/版本 状态码 状态码说明
- 状态码分类:
- 1XX:已发送请求
- 2XX:响应完成
- 3XX:还需浏览器进一步操作
- 302重定向 配合响应头location使用
- 304读缓冲
- 4XX:用户操作错误
- 5XX:服务器错误
- 常用方法:
- setStatus(int code);//针对1 2 3 状态码,code为状态码
- setError(int code);//针对4 5状态码
2、响应头:
- 格式:key:value(value可以为多值)
- 常用方法:
- setHeader(String name,String value);//设置一个字符串形式的响应头
- addHeader(String name,String value);//追加一个字符串形式的响应头,若无设置则设置,若已设置则追加
- 常见的响应头:
- location:重定向
- 第一种方式
- response.setStatus(302);//设置重定向的状态码302
- response.setHeader(“location",”跳转路径如:/Servlet/MyServlet“);//设置重定向的响应头
- 第二种方式:
- response.sendRedirect(”跳转路径如:/Servlet/MyServlet“);
- refresh:定时刷新
- Java中使用:
- response.setHeader(“refresh”,”秒数;url=跳转的路径“)
- HTML中使用:
<meta http-equiv="refresh" content=“秒数;url=跳转的路径">
- content-type:
- 设置文件到mime类型
- 设置响应流到编码
- 通知浏览器用什么编码打开
3、响应体:
- 常用方法:
- PrintWriter getWriter( );//以字符流形式往前台写东西
- response.getWriter( ).print(“”);
- ServletOutputStream getOutputStream( );//以字节流形式往前台写东西
- 注意⚠️:字符流和字节流不能同时出现
- 响应中文乱码问题解决方式:
- response.setHeader(“content-type”,"text/html;charset=utf-8”);
- response.setContentType("text/html;charset=utf-8”);
4、浏览器查看当前页面状态码:
- 打开开发者工具,选择Nextwork->All,刷新后就能看见

5、实现3秒后跳转到新页面,并在当前页面更新秒数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--实现3秒后跳转到2.html页面-->
<meta http-equiv="refresh" content="3;url=/2.html">
<title>Title</title>
<script type="text/javascript" src="js/jquery-1.11.0.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
<link type="text/css" href="css/bootstrap.css"/>
<script type="text/javascript">
var x=2;
$(function () {
//设置一个定时器,每秒执行show函数
var id = setInterval(show,1000);
});
function show() {
//把span标签中的元素设置为x
$("#span1").html(x);
//每一秒后x--
x--;
//当x为0时关闭计时器
if (x == 0){
clearInterval(id)
}
}
</script>
</head>
<body>
<span id="span1">3</span>秒后跳转
</body>
</html>

Part04:下载功能的实现
1、需求:
- HTML、图片、文本、压缩文件等文件都能以附件的形式下载到本地
2、实现方式
- 超链接方式:浏览器能解析的类型直接打开,不能解析的类型才会下载

- 第二种方式:所有类型的文件都能下载
- 设置文件的mime类型:response.setContentType(String 文件的mime类型);
- 设置文件的下载头:response.setHeader(“content-disposition”,"attachment;filename=“+文件名);//attachment表示以附件的形式下载


- //HTML主要代码
<!--通过?拼接文件名把文件名称传过去,通过文件名获取到文件的mime类型-->
<a href="/download?filename=1.html">HTML文件下载</a>
<a href="/download?filename=tubiao.png">png图片下载</a>
<a href="/download?filename=1.zip">zip压缩文件下载</a>
<a href="/download?filename=1.txt">txt文件下载</a>
- //工具类代码,解决浏览器下载文件中文名出现乱码问题
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import sun.misc.BASE64Encoder;
public class DownLoadUtils {
public static String getName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其他浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
@WebServlet(name = "DownLoadServlet",urlPatterns = {"/download"})
public class DownLoadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取浏览器的版本内核
String agent = request.getHeader("user-agent");
//创建ServletContext对象
ServletContext servletContext = getServletContext();
//获取文件名
String filename = request.getParameter("filename");
//通过ServletContext对象的getMimeType方法获取文件的Mime类型
String mimeType = servletContext.getMimeType("/" + filename);
//设置文件的mime类型头
response.setHeader("content-type",mimeType);
//设置文件下载头
response.setHeader("content-disposition","attachment;filename="+DownLoadUtils.getName(agent,filename));
//设置流
//获取输入流
InputStream is = servletContext.getResourceAsStream("/" + filename);
//获取输出流
ServletOutputStream os = response.getOutputStream();
//把输入流数据拷到输出流
byte[] bytes = new byte[1024];
int b=0;
while ((b=is.read(bytes))!=-1){
os.write(bytes,0,b);
}
os.close();
is.close();
}
}
Part05:验证码切换案例
1、随机产生验证码,点击验证码就会切换新的验证码


package Servlet5;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(name = "CodeServlet",urlPatterns = {"/code"})
public class CodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 使用java图形界面技术绘制一张图片
int charNum = 4;
int width = 20 * 4;
int height = 28;
// 1. 创建一张内存图片
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 2.获得绘图对象
Graphics graphics = bufferedImage.getGraphics();
// 3、绘制背景颜色
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, width, height);
// 4、绘制图片边框
graphics.setColor(Color.GRAY);
graphics.drawRect(0, 0, width - 1, height - 1);
// 5、输出验证码内容
graphics.setColor(Color.RED);
graphics.setFont(new Font("宋体", Font.BOLD, 22));
// 随机输出4个字符
String s = "ABCDEFGHGKLMNPQRSTUVWXYZ23456789";
Random random = new Random();
// session中要用到
String msg = "";
int x = 5;
for (int i = 0; i < charNum; i++) {
int index = random.nextInt(32);
String content = String.valueOf(s.charAt(index));
msg += content;
graphics.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
graphics.drawString(content, x, 22);
x += 20;
}
// 6、绘制干扰线
graphics.setColor(Color.GRAY);
for (int i = 0; i < 5; i++) {
int x1 = random.nextInt(width);
int x2 = random.nextInt(width);
int y1 = random.nextInt(height);
int y2 = random.nextInt(height);
graphics.drawLine(x1, y1, x2, y2);
}
// 释放资源
graphics.dispose();
// 图片输出 ImageIO
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="js/jquery-1.11.0.js"></script>
<script type="text/javascript" src="js/bootstrap.js"></script>
<link type="text/css" href="css/bootstrap.css"/>
<script type="text/javascript">
$(function () {
//绑定图片的点击事件
$("#img").click(function () {
//一点击,重新发送请求,更换验证码
$("#img").attr("src","code?data="+new Date);
})
})
</script>
</head>
<body>
<h2>验证码案例</h2>
<img src="code" id="img"/>
</body>
</html>