HttpServletResponse与HttpServletRequest
HttpServletResponse与HttpServletRequest
1.HttpServletResponse
1.概述
补充:response,request对象销毁之前,服务器拿到响应数据
2.HttpServletResponse对象方法的探索
1.响应头方法
更正一下:开发中常用的方法是setHeader();
2.响应正文
3.应用--服务器解码与客户端编码
1.客户端编码设置方式1
2.客户端编码方式设置2
3.服务器解码与客户端编码方式设置
图示:
补充:setCharacterEncoding
代码参考:
package com.xu.httpservletresponse;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @auther xu
* @date 2022/4/7 - 15:36
*/
public class HttpServletResponseDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//服务器中默认编码为ISO-8859-1,她不支持中文(Tomcat)
//告诉服务器使用UTF-8解析文本
// resp.setCharacterEncoding("UTF-8");
//方式1:告诉客户端使用UTF-8编码
// resp.setHeader("content-type","text/html;charset=UTF-8");
//方式3:告诉服务器使用UTF-8解析文本,告诉客户端使用UTF-8编码(该方法将上面两个方法封装)
resp.setContentType("text/html;charset=UTF-8");
//得到一个字符输出流
PrintWriter out = resp.getWriter();
// out.write(" <html><head></head><body><meta charset=\"UTF-8\"/>你好呀!</body></html>");//方式2
out.write("使用封装的编码与解码方法");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
4.响应编码字节输出流
500错误:
以上错误是getBytes()方法中的参数传错了
乱码错误:
解决:告诉浏览器使用UTF-8编码
3.文件下载
1.505报错:
代码:
package com.xu.httpservletresponse;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @auther xu
* @date 2022/4/7 - 20:03
*/
public class DownLoadFile extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//需求:客户端访问服务器端(Tomcat服务器)的图片,并将其下载到面
//1.首先:获取文件路径
String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/美女.jpg");
//2.获取字节流对象
FileInputStream fis = new FileInputStream(realPath);
//3.创建字节输出流
ServletOutputStream sos = resp.getOutputStream();
//创建缓冲区
int len;//记录读入字节的个数
byte[] buffer = new byte[1024];
while ((len = fis.read(buffer)) != -1) {
sos.write(buffer,0,len);
}
//管理操作:
sos.close();
fis.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
2.以上解决了客户端得到想要访问的图片数据,但是并未实现在客户端实现图片的下载的功能
1.用于下载图片时,文件名的编码
2.获取字符串的子串
package com.xu.httpservletresponse;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
/**
* @auther xu
* @date 2022/4/7 - 20:03
*/
public class DownLoadFile extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//需求:客户端访问服务器端(Tomcat服务器)的图片,并将其下载到面
//1.首先:获取文件路径
String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/美女.jpg");
//2.获取字节流对象
FileInputStream fis = new FileInputStream(realPath);
//3.创建字节输出流
ServletOutputStream sos = resp.getOutputStream();
//4.得到待下载的文件名
String imageName = realPath.substring(realPath.lastIndexOf("\\")+1);
//5.设置文件名的编码
imageName = URLEncoder.encode(imageName,"UTF-8");
//6.在响应头中,告诉客户端下载文件
resp.setHeader("content-disposition","attachment;fileName="+imageName);
resp.setHeader("content-type","image/jpeg");
//创建缓冲区
int len;//记录读入字节的个数
byte[] buffer = new byte[1024];
while ((len = fis.read(buffer)) != -1) {
sos.write(buffer,0,len);
}
//管理操作:
sos.close();
fis.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
4.验证码--涉及知识没有学(不理解)
5.告诉浏览器不缓存
6.页面刷新
package com.xu.httpservletresponse;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Random;
/**
* @auther xu
* @date 2022/4/8 - 7:09
*/
public class RefreshDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//实现页面的刷新
resp.setHeader("refresh","1");//1s刷新一次
Random random = new Random();
resp.getWriter().write(random.nextInt()+"");//为字符流,将数字转变为字符串(防止出现数字97输出为a)
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
1.实现页面跳转到主页面
报404错误:
2.跳转成功:
代码参考:
package com.xu.httpservletresponse;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Random;
/**
* @auther xu
* @date 2022/4/8 - 7:09
*/
public class RefreshDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//实现页面的刷新
// resp.setHeader("refresh","1");//1s刷新一次
// Random random = new Random();
// resp.getWriter().write(random.nextInt()+"");
//实现3秒钟跳到主页
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("注册成功,3秒钟跳到主页");
resp.setHeader("refresh","3;url=http://localhost:8080/secondServlet/servlet/mainP");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
7.上午总结:
更正:URLEncoder.encode(文件名,"UTF-8");
7.重定向
1.程序验证:重定向之后访问下一个Servlet8与之前Servlet7没有一点关系
注意:
代码参考:
package com.xu.httpservletresponse;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @auther xu
* @date 2022/4/8 - 11:11
*/
public class ServletForward1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("客户端:我要借钱");
System.out.println("ServletForword1:我没钱,我知道ServletForward2有钱");
//设置响应行状态
resp.setStatus(302);
//设置头部信息,告诉服务器待重定向的地址
resp.setHeader("location","/secondServlet/servletforward2");
System.out.println("此输出语句验证是先输出本句话,还是ServletForward2中的输出语句");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
package com.xu.httpservletresponse;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @auther xu
* @date 2022/4/8 - 11:11
*/
public class ServletForward2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Servlet2:我有钱,我借给你");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
8总结:
2.HttpServletRequest
因为涉及到操作访问客户端的报文,肯定是一个实现类而不是HttpServletRequest()接口
1.请求消息行相关方法
package com.xu.httpservletrequest;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @auther xu
* @date 2022/4/8 - 21:06
*/
public class RequestHeadMethodDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//查看HttpServletRequest接口的实现类
// System.out.println(req.getClass().getName());
// System.out.println(resp);
//request方法的探索
//1.获取请求方式
System.out.println(req.getMethod());
//2.返回客户端发送请求时完整的URL
System.out.println(req.getRequestURL());
//3.返回请求行中的资源名称
System.out.println(req.getRequestURI());
//4.当前应用的虚拟目录(也就是8080后面开始那一个路径)----/secondServlet
System.out.println(req.getContextPath());
//5.返回请求行中的参数部分
System.out.println(req.getQueryString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
客户端访问路径:
服务器输出:
给参数部分一个名称输出:
2.获取请求消息头的相关信息
1.应用--获取请求头部信息---req.getHeader("User-Agent");
/**
* 利用请求头部信息判断所发送的请求报文来自哪一个浏览器
* @param req
*/
public void showClientType(HttpServletRequest req) {
//获取请求信息的头部信息
String headerInfo = req.getHeader("User-Agent");
//写一个判断语句,判断客户端浏览器类型
if (headerInfo.toLowerCase().contains("chrome")) {
System.out.println("该请求报文从google浏览器发送过来");
} else if (headerInfo.toLowerCase().contains("edge")) {
System.out.println("该请求报文从微软浏览器发送过来");
} else {
System.out.println("请求数据报文从其他浏览器发送过来");
}
}
输出结果:
2.获取所有消息请求头的名字---req.getHeaderNames()
/**
* 获取所有消息请求头的名字,以及对应名字所包含的内容
* @param req
*/
public void getAllName(HttpServletRequest req) {
Enumeration<String> headerNames = req.getHeaderNames();//获取所有请求消息的名字
while (headerNames.hasMoreElements()) {
String element = headerNames.nextElement();
System.out.println(element+":"+req.getHeader(element));
}
}
输出结果:
host:localhost:8080
connection:keep-alive
cache-control:max-age=0
sec-ch-ua:" Not A;Brand";v="99", "Chromium";v="99", "Google Chrome";v="99"
sec-ch-ua-mobile:?0
sec-ch-ua-platform:"Windows"
upgrade-insecure-requests:1
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
sec-fetch-site:none
sec-fetch-mode:navigate
sec-fetch-user:?1
sec-fetch-dest:document
accept-encoding:gzip, deflate, br
accept-language:zh-CN,zh;q=0.9
cookie:JSESSIONID=B26F20D8B7EE7B9B6270E39F91E7861F
3.获得相同类型的消息头---req.getHeaders("accept-encoding")
3.请求正文-获取表单数据相关的方法
1.ISO-8859-1导致的乱码问题
编码器操作出站数据,而解码器处理入站数据。编码器是将消息转换为适合于传输的格式,而对应的解码器则是将网络字节流转换回应用程序的消息格式。
2.解决ISO-8859-1导致的服务器解析乱码的问题:告诉服务器使用UTF-8解析由UTF-8编码的文件
代码参考:
/**
* 根据表单中name属性的名,获取value属性值的方法
* @param req
*/
public void getFormDate1(HttpServletRequest req) {
String userName = req.getParameter("userName");
String password = req.getParameter("pwd");
String sex = req.getParameter("sex");//性别只能选一个
String[] hobbies = req.getParameterValues("hobby");
String city = req.getParameter("city");
System.out.println(userName);
System.out.println(password);
System.out.println(sex);
for (int i = 0; hobbies != null && i < hobbies.length; i++) {
System.out.println(hobbies[i]+"\t");
}
System.out.println(city);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<form action="/secondServlet/form" method="post">
用户名:<input type="text" name="userName"/><br/>
密码:<input type="password" name="pwd"/><br/>
性别:<input type="radio" name="sex" value="男" checked="checked"/>男
<input type="radio" name="sex" value="女" />女<br/>
爱好:
<input type="checkbox" name="hobby" value="篮球">篮球
<input type="checkbox" name="hobby" value="唱歌">唱歌
<input type="checkbox" name="hobby" value="编码">编码
<br/>
所在城市:
<select name="city">
<option>-----请选择----</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
</select>
<br/>
<input type="submit" value="登录"/>
</form>
</body>
</html>
3.改进版1
/**
* 得到表单数据改进版
* @param req
*/
public void getFormDate2(HttpServletRequest req) {
Enumeration<String> parameterNames = req.getParameterNames();//得到表单中所有的name属性名的枚举
while (parameterNames.hasMoreElements()) {
String name = parameterNames.nextElement();//得到其中一个名字
String[] parameterValues = req.getParameterValues(name);//将名字所对应的值都封装为String数组,即使只有一个值
for (int i = 0; parameterNames != null && i < parameterValues.length; i++) {
System.out.println(parameterValues[i]);
}
}
}
4.改进版2:为了将数据存入到数据库,需要将登入的数据映射到实体类,然后再存入到数据库中
/**
* 为了将数据存入到数据库,需要将登入的数据映射到实体类,然后再存入到数据库中
* @param req
*/
public void formDateToEntry(HttpServletRequest req) {
try {
req.setCharacterEncoding("UTF-8");
//根据表单中name属性的名,获取value属性值的方法
// getFormDate1(req);
// getFormDate2(req);
User user = new User();
System.out.println("数据封装前User状态:"+user);
//获取表单数据
Map<String, String[]> parameterMap = req.getParameterMap();
for (Map.Entry<String,String[]> m:parameterMap.entrySet()){
String key = m.getKey();
String[] value = m.getValue();
//使用反射知识完成对数据的封装
PropertyDescriptor pd = new PropertyDescriptor(key,User.class);//该对象封装了每一个名字对应的get和ser方法
//相当与获取对应名称的set方法
Method setter = pd.getWriteMethod();
//判断value是一个值还是多个值,然后进行数据填充
if (value.length == 1) {
setter.invoke(user,value[0]);//对应名称只有一个值的封装
} else {
setter.invoke(user,(Object) value);//给复选框变量封装赋值
}
}
System.out.println("数据封装后User状态:"+user);
} catch (Exception e) {
e.printStackTrace();
}
}
输出:
5.改进版本3
使用框架实现:
package com.xu.httpservletrequest;
import org.apache.commons.beanutils.BeanUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Map;
/**
* @auther xu
* @date 2022/4/9 - 11:12
*/
public class GetFormDate extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// formDateToEntry(req);
try {
req.setCharacterEncoding("UTF-8");//指定服务器的解码方式
User user = new User();
System.out.println(user);
BeanUtils.populate(user,req.getParameterMap());
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 为了将数据存入到数据库,需要将登入的数据映射到实体类,然后再存入到数据库中
* @param req
*/
public void formDateToEntry(HttpServletRequest req) {
try {
req.setCharacterEncoding("UTF-8");
//根据表单中name属性的名,获取value属性值的方法
// getFormDate1(req);
// getFormDate2(req);
User user = new User();
System.out.println("数据封装前User状态:"+user);
//获取表单数据
Map<String, String[]> parameterMap = req.getParameterMap();
for (Map.Entry<String,String[]> m:parameterMap.entrySet()){
String key = m.getKey();
String[] value = m.getValue();
//使用反射知识完成对数据的封装
PropertyDescriptor pd = new PropertyDescriptor(key,User.class);//该对象封装了每一个名字对应的get和ser方法
//相当与获取对应名称的set方法
Method setter = pd.getWriteMethod();
//判断value是一个值还是多个值,然后进行数据填充
if (value.length == 1) {
setter.invoke(user,value[0]);//对应名称只有一个值的封装
} else {
setter.invoke(user,(Object) value);//给复选框变量封装赋值
}
}
System.out.println("数据封装后User状态:"+user);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 得到表单数据改进版
* @param req
*/
public void getFormDate2(HttpServletRequest req) {
Enumeration<String> parameterNames = req.getParameterNames();//得到表单中所有的name属性名的枚举
while (parameterNames.hasMoreElements()) {
String name = parameterNames.nextElement();//得到其中一个名字
String[] parameterValues = req.getParameterValues(name);//将名字所对应的值都封装为String数组,即使只有一个值
for (int i = 0; parameterNames != null && i < parameterValues.length; i++) {
System.out.println(parameterValues[i]);
}
}
}
/**
* 根据表单中name属性的名,获取value属性值的方法
* @param req
*/
public void getFormDate1(HttpServletRequest req) {
String userName = req.getParameter("userName");
String password = req.getParameter("pwd");
String sex = req.getParameter("sex");//性别只能选一个
String[] hobbies = req.getParameterValues("hobby");
String city = req.getParameter("city");
System.out.println(userName);
System.out.println(password);
System.out.println(sex);
for (int i = 0; hobbies != null && i < hobbies.length; i++) {
System.out.println(hobbies[i]+"\t");
}
System.out.println(city);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
4.获取表单字节流方式(乱码问题没有解决)
package com.xu.httpservletrequest;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @auther xu
* @date 2022/4/9 - 22:38
*/
public class ServletInputStreamDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
//一般应用于操作照片等数据
ServletInputStream inputStream = req.getInputStream();
int len;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
//将字节转变为字符串输出
String s = new String(buffer, "UTF-8");
System.out.println(s);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
控制台输出:
5.操作非表单数据的方法---请求转发
1.request维护一个Map集合,转发过程中,可以将当前页面得到的数据传递给下一个页面
RequestAndForwardDemo1页面:
package com.xu.httpservletrequest;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @auther xu
* @date 2022/4/9 - 22:58
*/
public class RequestAndForwardDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
//定义字符串,模拟该页面所得数据,保存req中,转发给下一个页面(request维护了一个Map集合)
String str= "aaaaaaaaa";
req.setAttribute("s",str);//s相当于键,str相当于所存储的值str
//探索转发过程
System.out.println("client:我想办事");
System.out.println("RequestAndForwardDemo1:我办不了,但是我可以找别人帮你办");
req.getRequestDispatcher("/requestAndForward2").forward(req,resp);
System.out.println("RequestAndForwardDemo1:事情办完了");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
RequestAndForwardDemo2页面:
package com.xu.httpservletrequest;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @auther xu
* @date 2022/4/9 - 23:05
*/
public class RequestAndForwardDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
System.out.println("RequestAndForwardDemo2:我帮你办");
//得到上一个页面的数据
String str = (String)req.getAttribute("s");
System.out.println(str);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req,resp);
}
}
输出:
2.removeAttribute()方法
6.重定向与转发的对比:
1.请求转发不改变当前页面的地址栏(从别的页面反馈过来的数据经过当前页面响应给客户端),而重定向会改变地址栏实现跳转