Request对象
功能:设置响应消息
1. 设置响应行
- 格式:协议/版本 响应状态码 状态码状态
- 设置状态码:
setStatus(int sc)
2. 设置响应头
setHeader(String name,String value)
3. 设置响应体
- 获取输出流(相对于当前程序来讲这是输出东西到客户端)
字符输出流:PrintWriter getWriter()
字节输出流:ServletOutputStream getOutputStream()
- 使用输出流,将数据输出到客户端浏览器
4. 响应重定向
//重定向到responseServlet2
/*
//1.设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location", "/responseServlet2");
*/
//鉴于上述重定向代码参数大都固定,封装有更为简单的重定向方法
response.sendRedirect("/responseServlet2");
5. redirect和forward的区别?
重定向redirect的特点
- 地址栏发生变化
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求,不能使用request域对象来共享数据(request域对象仅作用 于一次请求的范围内)
转发forward的特点
- 转发地址栏不变
- 转发只能访问当前服务器的资源
- 转发是一次请求,可以使用request域对象来共享数据
6. 相对路径与绝对路径
相对路径
- 通过相对路径不可以唯一确定资源
- 相对路径以
.
开头,如./index.html
-
./
为当前目录
-
../
为上一级目录
- 如果相对路径开头什么都没有,那么默认为当前目录
./
如index.html
=./index.html
绝对路径(常用)
- 通过绝对路径可以唯一确定资源
- 绝对路径以
/
开头,如 /responseServlet2
- 给浏览器使用的绝对路径中需要添加虚拟目录(项目的访问路径)
HTML页面中的链接是一定要加虚拟目录的
服务器端servlet中只有重定向需要加虚拟目录,因为重定向是给浏览器看的(因此有两次请求,用session来共享数据)
服务器端的请求转发不需要加虚拟目录,因为将请求转发是给服务器看的(因此只有一次请求,用request来共享数据)
-
超链接a:
<a href="/test/checkCodeServlet">超链接</a>
-
form表单:
<form action="/test/loginServlet">
-
服务器响应给浏览器的重定向
虚拟目录动态获取:request.getContextPath()
-
超链接a:
//需要动态获取虚拟目录
response.sendRedirect(request.getContextPath()+"/responseServlet2");
- 给服务器使用,绝对路径中不需要添加虚拟目录
-
服务器进行请求转发
-
服务器进行请求转发
request.getRequestDispatcher("/index.jsp").forward(request, response);
相对路径与绝对路径的区别
- 在HTML中使用相对路径,浏览器会在地址栏内容上加上相对路径
1.HTML文件中的超链接
<a href="hello">relative</a>
2.当前地址栏内容(当前虚拟目录是springmvc01)
http://localhost:8080/springmvc01/
3.点击超链接后,地址栏内容为
http://localhost:8080/springmvc01/hello
- 在HTML中使用绝对路径,浏览器会在
域名:端口
后加上绝对路径
1.HTML文件中的超链接
<a href="/hello">absolute</a>
2.当前地址栏内容(当前虚拟目录是springmvc01)
http://localhost:8080/springmvc01/
3.点击超链接后,地址栏内容为
http://localhost:8080/hello
7. 服务器输出字符流
中文数据乱码问题
-
PrintWriter pw = response.getWriter();
获取的流的默认编码是ISO-8859-1
-
response.setContentType("text/html;charset=utf-8");
输出流之前设置响应消息体的数据格式以及编码
//设置响应消息体的数据格式以及编码
//response.setHeader("content-type", "text/html;charset=utf-8");
//上述代码的简单形式
response.setContentType("text/html;charset=utf-8");
//1.获取字符输出流
PrintWriter writer = response.getWriter();
//2.输出数据
writer.write("你好啊啊啊,dominus!");
8. 服务器输出字节流
//告诉浏览器该流使用的编码
response.setContentType("text/html;charset=utf-8");
//1.获取字节输出流
ServletOutputStream sos = response.getOutputStream();
//2.输出数据
sos.write("你好 dominus!".getBytes("utf-8"));
9. 验证码
int width=100;
int height=50;
//1.创建一个对象,在内存中生成图片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//2.美化图片
//2.1填充背景色
Graphics g = image.getGraphics();//画笔对象 graphics:图像
g.setColor(Color.PINK);//设置画笔颜色
g.fillRect(0, 0, width, height);//填充矩形
//2.2画边框
g.setColor(Color.BLUE);
g.drawRect(0,0,width-1,height-1);
//2.3画验证码
String str="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random ran = new Random();
for (int i = 1; i <= 4; i++) {
int index = ran.nextInt(str.length());//返回[0,str,length)之间的随机整数
char c = str.charAt(index);//随机字符
g.drawString(String.valueOf(c), width/5*i, height/2);
}
//2.4画干扰线
g.setColor(Color.GREEN);
for (int i = 0; i < 10; i++) {
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1, y1, x2, y2);
}
//3.将图片输出到浏览器
ImageIO.write(image, "jpg", response.getOutputStream());
<script>
window.onload=function (){
//获取超链接对象和图片对象
var a=document.getElementById(`a`);
var image=document.getElementById("image");
//绑定单机事件
a.onclick=function () {
//加时间戳
var date=new Date().getTime();
//当超链接被点击时,更换img标签的src属性
//并且为了浏览器不访问上次缓存的图片,要给绝对路径加上时间戳这个参数
image.src="/checkCodeServlet?"+date;
}
}
</script>
ServletContext对象
概念
代表整个web应用,可以和程序的容器(Tomcat服务器)来通信
获取
- 通过request对象获取
request.getServletContext()
- 通过HttpServlet获取
this.getServletContext()
在同一个web应用中,以上两种方式获取的ServletContext对象为同一个
功能
1. MIME类型
- 在互联网通信过程中定义的一种文件数据类型
- 格式:大类型/小类型
text/html
image/jpeg
- 获取:
String getMimeType(String filename)
2. 域对象:共享数据
- 方法:
-
void setAttribute(String name,Object obj)
:存储数据
-
Object getAttribute(String name)
:通过键获取值
-
void removeAttribute(String name)
:通过键移除键值对
-
- ServletContext域对象范围:所有用户所有请求的数据
3. 获取文件的真实(服务器)路径
src目录下的文件都在WEB-INF的classes文件夹中
- 方法:
String getRealPath(String path)
-
context.getRealPath("/b.txt");//web目录下资源访问
-
context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
-
context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
classPath类路径
在编译打包后的项目中,根目录是META-INF
和WEB-INF
。
WEB-INF/classes
就是类路径,包含src下的所有文件
文件下载案例
//1.获取请求参数:文件名称
String filename = request.getParameter("filename");
System.out.println(filename);
//2.使用字节输入流加载文件进内存
//2.1找到文件的服务器路径
ServletContext servletContext = this.getServletContext();
String path = servletContext.getRealPath("/img/"+filename);
//2.2用字节流关联
FileInputStream fis = new FileInputStream(path);
//3.设置response的响应头
//3.1设置响应头:content-type
String mimeType = servletContext.getMimeType(filename);
response.setContentType(mimeType);
//3.2设置响应头:打开方式content-disposition
//解决中文文件名问题
//获取user-agent请求头
String ua = request.getHeader("user-agent");
//使用工具类方法编码文件名即可
filename = DownLoadUtils.getFileName(ua, filename);
response.setHeader("content-disposition", "attachment;filename="+filename);//将文件以附件的形式弹出下载框
//4.将输入流数据写到输出流
ServletOutputStream sos = response.getOutputStream();
byte[] buff = new byte[1024 * 8];
int len=0;
//fis.read(buff)从此输入流中将最多buff.length个字节的数据读入一个byte数组中,如果因为已经到达文件末尾而没有更多的数据,则返回 -1
while ((len=fis.read(buff))!=-1){
sos.write(buff, 0, len);
}
fis.close();
//HTML文件
<body>
<a href="/ggbond/downloadServlet?filename=小鸡.jpg">下载</a>
</body>
//解决中文文件名编码问题的工具类
package cn.upeveryday.util;
import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class DownLoadUtils {
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
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");
}
return filename;
}
}