HttpServletRequest与HttpServletResponse
web服务器接收到客户端的http请求后,针对这个请求,分别创建一个代表请求的HttpServletRequest对象和一个代表响应的HttpServletResponse对象。
- 获取客户端请求过来的参数:HttpServletRequest
- 给客户端响应一些数据:HttpServletResponse
1、HttpServletRequest
HttpServletRequest代表客户端的请求,用户通过HTTP协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest对象中,通过HttpServletRequest的方法,可以获得客户端的所有信息。
1.1、获取前端传递的参数与请求转发
1.1.1、获取前端的参数
- getParameter():获取前端的数据,根据name获取到value,返回一个String类型的数据。
- getParameterValues():获取前端的数据,根据name获取到value,返回的是一个String[]数组,即获取的值有多个。
1.1.2、请求转发
- getRequestDispatcher():括号内参数传入转发的路径,“/”:解析为当前项目,即:http://localhost:8080/servletStudy。
- forward(request,response):调用此方法,达到转发的目的。
示例:获取前端登录页面传来的数据,进行简单的验证,根据结果进行转发
servlet:
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置请求与响应的编码
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// 获取前端传递来的参数
String username = request.getParameter("username");
String password = request.getParameter("password");
String[] skills = request.getParameterValues("skills");
// 验证输入的username和password
if (username.equals("admin") && password.equals("123456")){
System.out.println("登陆成功!");
request.getRequestDispatcher("/success.jsp").forward(request,response);
}else {
System.out.println("登录失败!");
request.getRequestDispatcher("/failure.jsp").forward(request,response);
}
System.out.println(username);
System.out.println(password);
for (String str : skills) {
System.out.print(str + "\t");
}
System.out.println("admin" == username);
System.out.println("123456" == password);
}
}
登录页面:
- ${pageContext.request.contextPath}是JSP取得绝对路径的方法,即取出当前项目的名称
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<div>
<form method="get" action="${pageContext.request.contextPath}/login">
账号:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
技能:<input type="checkbox" name="skills" value="java" checked>Java
<input type="checkbox" name="skills" value="python">Python
<input type="checkbox" name="skills" value="c++">C++
<input type="checkbox" name="skills" value="php">PHP<br/>
<input type="submit" value="好兄弟,填好点我">
</form>
</div>
</body>
</html>
根据输入的账户密码是否正确跳转到success.jsp与failure.jsp
2、HttpServletResponse
HttpServletResponse获取两个输出流:getPOutputStream()和getWiter()。获取的两个输出流不能同时使用,会报错。
HttpServletResponse应用:
2.1、浏览器下载文件
- 步骤:
- 获取文件的路径(相对路径与绝对路径都可)
- 获取文件名(把整个文件路径当作String的一个实例,调用substring方法,截取文件名,多多细品,我是刚学的这个方法,越品越有味儿)
- 告诉浏览器,我们要下载东西,即让浏览器支持我们下载文件(这一步向切要!!)
- 创建文件输入流读取下载的文件
- 创建响应输出流,在浏览器中响应并写出(下载)文件
- 关闭流资源
/**
* 使用HttpServletResponse实现下载文件
*
* @Author:xiezr
* @Creat:2021-07-29 15:12
*/
public class HttpServletResponseTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, UnsupportedEncodingException {
// 1.
String filePath = "G:\\SummerWeb\\servletStudy\\src\\main\\webapp\\images\\beautifulGirl.jpg";
// 2.使用substring截取文件名
String fileName = filePath.substring(filePath.lastIndexOf("\\") + 1);
// 3.设置浏览器支持下载文件,设置文件名编码格式为UTF-8,防止下载的时候文件名显示错误乱码
resp.setHeader("Content-disposition","attachment;filename"+ URLEncoder.encode(fileName, "UTF-8"));
// 4.使用缓冲流,提高效率
BufferedInputStream fis = null;
BufferedOutputStream bos = null;
try {
fis = new BufferedInputStream(new FileInputStream(filePath));
// 5.创建响应输出流,ServletOutputStream继承与OutputStream,属于节点流
ServletOutputStream sos = resp.getOutputStream();
bos = new BufferedOutputStream(sos);
// 读取文件,写出文件到浏览器,即下载
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1){
bos.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 6.关闭资源就不显示了
}
}
}
运行结果:
2.2、图片验证码
- 步骤:要有验证码和图片,把验证码写进图片里面
- 定义一个方法,生成随机数
- 让浏览器刷新(也可不用,自己手动刷新更改验证码)
- 在内存中创建图片,使用BufferedImage类(此时的图片只有宽,高)
- 获得图片并对图片进行修改
- 给图片写入验证码
- 告诉浏览器请求打开的方式,即setContextType()
- 把图片写给浏览器
public class CheckCodeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.
response.setHeader("refresh","3");
// 2.
BufferedImage image = new BufferedImage(100, 30, BufferedImage.TYPE_INT_RGB);
// 3.获取“画笔”工具
Graphics2D graphics = (Graphics2D) image.getGraphics();
// 修改背景颜色,填充颜色
graphics.setColor(Color.white);
graphics.fillRect(0,0,100,30);
// 4.给图片写数据
graphics.setColor(Color.MAGENTA);
// 设置字体类型与字体大小
graphics.setFont(new Font(null,Font.BOLD,30));
// 将随机数写入图片
graphics.drawString(productCode(),0,30);
// 5.
response.setContentType("image/jpg");
// 设置浏览器不要缓存
response.setDateHeader("expires",-1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
// 6.图片IO流写出到浏览器上
ImageIO.write(image,"jpg",response.getOutputStream());
}
// 生成随机数
public String productCode(){
Random random = new Random();
// 把生成的随机数转换为String类型
String str = String.valueOf(random.nextInt(666666));
// 如果随机数生成的位数少于6为,使用0补齐
StringBuffer sbuffer = new StringBuffer();
for (int i = 0; i < 6 - str.length(); i++) {
sbuffer.append("0");
}
return sbuffer + str;
}
}
运行结果:
2.3、HttpServletResponse实现重定向
- sendRedirect():设置重定向到哪里。(常用)
或者设置响应头: - setStatus(302):设置响应状态码
- setHeader(“Location”,"/项目名/资源路径"):设置新的访问地址
一个web资源收到客户端的请求后,他会通知客户端去访问另一个web资源,这个过程叫做重定向(地址栏的url地址会改变)。
public class RedirectTest extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendRedirect("/servletStudy/hello");
}
}
看一下浏览器:
3、请求转发与请求重定向的区别
- 相同点:都会实现页面的跳转
- 不同点:
- 请求转发的时候,url地址栏不会发生变化,响应状态码为307。请求重定向的时候,url地址栏会发生变化,响应状态码为302。
- 请求转发是一次请求,请求重定向是两次请求。
- 请求转发可以共享Request域中的数据,请求重定向不共享Request域中的数据,因为是两次请求,Tomcat每次请求都把数据封装到一个HttpServletRequest对象中。
- 请求转发可以访问WEB-INF目录下的资源,请求重定向无法访问WEB-INF目录下的资源。(/WEB-INF在浏览器地址栏中是受保护,访问不到的)
- 请求转发无法访问工程以外的资源,请求重定向可以访问工程外的资源
浏览器地址栏 | 请求次数 | 是否共享Request域的数据 | 能否访问WEB-INF目录下的资源 | 能否访问工程外的资源 | |
---|---|---|---|---|---|
请求转发 | 没有改变 | 一次 | 是 | 是 | 否 |
请求重定向 | 发生改变 | 两次 | 否 | 否 | 是 |