ServletContext对象
服务器中的项目,名称叫做WEB应用程序,应用程序也是对象
ServletContext (上下文) 对象表示WEB应用程序
一个WEB应用程序只能存在一个ServletContext对象,唯一性
每个应用程序,对应一个ServletContext对象
ServletContext是接口,此接口的实现类是tomcat引擎提供
-
ServletContext对象获取
-
ServletConfig对象,方法 getServletContext()
-
继承HttpServlet类,继承GenericServlet类定义方法 getServletContext()
ServletContext context = getServletContext();
-
对象的作用
获取WEB应用程序的初始化参数,web.xml配置
<!-- 配置的是WEB程序的初始化参数-->
<context-param>
<param-name>heima</param-name>
<param-value>java</param-value>
</context-param>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* 获取ServletContext对象
* 父类的方法
* org.apache.catalina.core.ApplicationContextFacade实现接口ServletContext
*/
ServletContext context = getServletContext();
System.out.println(context);
//context对象,获取配置文件中的初始化参数
String value = context.getInitParameter("heima");
System.out.println(value);
}
获取WEB应用程序下任意资源的绝对路径
- 方法: String getRealPath("资源相对路径")
域对象
ServletContext对象是一个容器,可以存储数据.
对象有个作用域问题,ServletContext作用域是整个WEB应用程序
- 向域对象存储数据: setAttribute(String key, Object value)
- 取出域对象数据: Object getAttribute(String key)
- 移除域对象数据: removeAttribute(String key)
ServletContext对象的空指针异常
ServletContext对象通过父类的方法getServletContext()获取
统计访问的次数
练习域对象ServletContext的使用
第一次访问Servlet的时候,数据1存储到域对象
第二次访问,从域中取出数据++,存储回去
注解开发取代web.xml(不写配置文件)
@WebServlet,注解添加到自己定义的Servlet中的类声明上即可
注解的属性 urlPatterns,属性值就是浏览器的访问地址
@WebServlet(urlPatterns = "/test")
xml有弱点,如果配置过多,比较乱,还消耗资源。
缺点:可拓展性低。
Response对象概述
负责对浏览器进行响应的对象
ServletResponse接口,HttpServletResponse接口继承自ServletResponse
使用的是子接口HttpServletResponse,此接口对象由Tomcat引擎提供
可以实现对客户端的响应, 响应行,响应头,响应体
Response设置响应行
- 设置状态码: setStatus(int 状态码)
response.setStatus(500); // 设置响应的状态码
补充:
Response设置响应头
HTTP协议的响应头,数据格式键值对 k:v
包含指导性信息,指导客户端
- addHeader(String key,String value)
- addIntHeader(String key,int value)
- addDateHeader(String key,long l)
- setHeader(String key,String value)
- setIntHeader(String key,int value)
- setDateHeader(String key,long l)
Response设置响应体
HTTP的响应体,就是页面的正文部分
- getWriter() 返回值是打印流PrintWrite
/*
* response对象方法getWriter()
* 打印流的响应体
* write() 使用字符串数据,没有差别, 输出是整数,查询编码表
* print() 无论是什么,原样打印
*/
- 响应中的中文乱码问题
产生乱码原因: 编码和解码不一致
/*
响应数据没有写回客户端
写在response对象的缓冲区,使用的编码是iso8859-1拉丁文
设置response对象缓冲区的编码表
方法:setCharacterEncoding("编码表")
通知浏览器用utf-8解码
*/
- getOutputStream() 返回字节输出流OutputStream
返回字节流,响应非文本类型的数据
重定向
/*
* 接收浏览器的请求
* 对浏览器进行响应:
* 浏览器进行重新的定向
* 302状态码
* 重定向资源的地址: 响应头
*
* Sun: 定义个方法实现重定向
*/
注意1.sendRedirect()重定向后不要再写代码。2.getOutputStream()与getWriter()互斥(response中有缓冲区,一个字节流,一个字符流,冲突)。
文件的下载
客户端浏览器从服务器下载文件
超链接,连接的地址是服务器端文件的路径
文件: 浏览器识别文件,不是下载,直接打开运行
浏览器不识别文件,直接下载
编写服务器端代码,告诉浏览器下载,不要打开
全下载
response.setHeader()下载设置。
解决下载的文件名含中文的问题(a.jpg下载后名字为美女.jpg):
String agent = request.getHeader("User-Agent");
String filename="美女.jpg"; // 文件名为中文
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else 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");
}
response.setHeader("Content-Disposition","attachment;filename="+filename);
String aFile = getServletContext().getRealPath("download/a.jpg");
FileInputStream fis = new FileInputStream(aFile);
OutputStream out = response.getOutputStream();
int len = 0;
byte[] bytes = new byte[1024];
while ((len = fis.read(bytes))!=-1){
out.write(bytes,0,len);
}
fis.close();
验证码案例
验证码的本质是个图片,图片里面是个随机生成字符串
String str ="abcdefABCDE1234567890";
Random.nextInt( str.length() )产生整数随机数,指定长度
str.charAt(索引)
package com.itheima.code;
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;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet(urlPatterns = "/code")
public class CodeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建画布
int width = 120;
int height = 40;
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获得画笔
Graphics g = bufferedImage.getGraphics();
// 填充背景颜色
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
// 绘制边框
g.setColor(Color.red);
g.drawRect(0, 0, width - 1, height - 1);
// 生成随机字符
// 准备数据
String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
// 准备随机对象
Random r = new Random();
// 声明一个变量 保存验证码
String code = "";
// 书写4个随机字符
for (int i = 0; i < 4; i++) {
// 设置字体
g.setFont(new Font("宋体", Font.BOLD, 28));
// 设置随机颜色
g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
String str = data.charAt(r.nextInt(data.length())) + "";
g.drawString(str, 10 + i * 28, 30);
// 将新的字符 保存到验证码中
code = code + str;
}
// 绘制干扰线
for (int i = 0; i < 6; i++) {
// 设置随机颜色
g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
}
// 将验证码 打印到控制台
System.out.println(code);
// 将验证码放到session中
//request.getSession().setAttribute("code_session", code);
// 将画布显示在浏览器中
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
网页:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<!--
实现验证码效果
本质图片: img src=属性值是服务器资源CodeServlet
-->
<img src="/WEB03/code" onclick="fnChange()" id="code">
<!--点击事件-->
<script type="text/javascript">
function fnChange() {
/*
* 页面打开的时候,请求服务器资源/WEB03/code
* 点击图片js函数中,发了请求/WEB03/code
*
* 请求的资源没有变化,服务器端程序也没有变化
* 浏览器拿缓存吧
*
* 每次请求不一样就行,添加参数
*/
//点击图片,修改src的属性值
var code = document.getElementById("code");
var date = new Date().getTime();
// alert(code.src);
// 事件修改src, 需要修改一下参数,不然拿的是缓存,验证码不会改变
code.src="/WEB03/code?a="+date;
}
</script>
</body>
</html>
详细过程: