Request和Response
一、Request
常用API
Request
1.通过request获得请求行
获得客户端的请求方式:String getMethod()
获得请求的资源:
String getRequestURI()
StringBuffer getRequestURL()
String getContextPath() ---web应用的名称
String getQueryString() ---- get提交url地址后的参数字符串
username=zhangsan&password=123
注意:request获得客户机(客户端)的一些信息
request.getRemoteAddr() --- 获得访问的客户端IP地址
2.通过request获得请求头
long getDateHeader(String name)
String getHeader(String name)
Enumeration getHeaderNames()
Enumeration getHeaders(String name)
int getIntHeader(String name)
referer头的作用:执行该此访问的的来源
做防盗链
3.通过request获得请求体
请求体中的内容是通过post提交的请求参数,格式是:
username=zhangsan&password=123&hobby=football&hobby=basketball
key ---------------------- value
username [zhangsan]
password [123]
hobby [football,basketball]
以上面参数为例,通过一下方法获得请求参数:
String getParameter(String name)
String[] getParameterValues(String name)
Enumeration getParameterNames()
Map<String,String[]> getParameterMap()
4. 注意:get请求方式的请求参数 上述的方法一样可以获得
解决post提交方式的乱码:request.setCharacterEncoding("UTF-8");
解决get提交的方式的乱码:
parameter = new String(parameter.getbytes("iso8859-1"),"utf-8");
5.request的其他功能
(1)request是一个域对象
request对象也是一个存储数据的区域对象,所以也具有如下方法:
setAttribute(String name, Object o)
getAttribute(String name)
removeAttribute(String name)
注意:request域的作用范围:一次请求中
(2)request完成请求转发
获得请求转发器----path是转发的地址
RequestDispatcher getRequestDispatcher(String path)
通过转发器对象转发
requestDispathcer.forward(ServletRequest request, ServletResponse response)
6. 注意:ServletContext域与Request域的生命周期比较?
ServletContext:
创建:服务器启动
销毁:服务器关闭
域的作用范围:整个web应用
request:
创建:访问时创建request
销毁:响应结束request销毁
域的作用范围:一次请求中
注意:转发与重定向的区别?
1)重定向两次请求,转发一次请求
2)重定向地址栏的地址变化,转发地址不变
3)重新定向可以访问外部网站 转发只能访问内部资源
4)转发的性能要优于重定向
注意:客户端地址与服务器端地址的写法?
客户端地址:
是客户端去访问服务器的地址,服务器外部的地址,特点:写上web应用名称
直接输入地址:
重定向
服务器端地址:
服务器内部资源的跳转的地址,特点:不需要写web应用的名称
转发
总结:
request获得行的内容
request.getMethod()
request.getRequestURI()
request.getRequestURL()
request.getContextPath()
request.getRemoteAddr()
request获得头的内容
request.getHeader(name)
request获得体(请求参数)
String request.getParameter(name)
Map<String,String[]> request.getParameterMap();
String[] request.getParameterValues(name);
注意:客户端发送的参数 到服务器端都是字符串
获得中文乱码的解决:
post:request.setCharacterEncoding(“UTF-8”);
get:
parameter = new String(parameter.getBytes(“iso8859-1”),”UTF-8”);
request转发和域
request.getRequestDispatcher(转发的地址).forward(req,resp);
request.setAttribute(name,value)
request.getAttribute(name)
Response
1.通过response设置响应行
设置响应行的状态码
setStatus(int sc)
2.通过response设置响应头
addHeader(String name, String value)
addIntHeader(String name, int value)
addDateHeader(String name, long date)
setHeader(String name, String value)
setDateHeader(String name, long date)
setIntHeader(String name, int value)
其中,add表示添加,而set表示设置
1.解决响应中文乱码:response.setContentType("text/html;charset=utf-8");
2.在页面打印结果:
response.getWriter().write("用户名或者密码不能为空!!!(╯﹏╰)");
3.页面跳转的另一种方式:
response.sendRedirect("/UManager/list.html");//路径需要写虚拟目录
3.通过response设置响应体
(1)响应体设置文本
PrintWriter getWriter()
获得字符流,通过字符流的write(String s)方法可以将字符串设置到response 缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端。
关于设置中文的乱码问题
原因:response缓冲区的默认编码是iso8859-1,此码表中没有中文,可以通过 response的setCharacterEncoding(String charset) 设置response的编码
但我们发现客户端还是不能正常显示文字
原因:我们将response缓冲区的编码设置成UTF-8,但浏览器的默认编码是本地系 统的编码,因为我们都是中文系统,所以客户端浏览器的默认编码是GBK,我们可以手动修改浏览器的编码是UTF-8。
我们还可以在代码中指定浏览器解析页面的编码方式,
通过response的setContentType(String type)方法指定页面解析时的编码是UTF-8
response.setContentType("text/html;charset=UTF-8");
上面的代码不仅可以指定浏览器解析页面时的编码,同时也内含 setCharacterEncoding的功能,所以在实际开发中只要编写 response.setContentType("text/html;charset=UTF-8");就可以解决页面输出中文乱码问题。
(2)响应头设置字节
ServletOutputStream getOutputStream()
获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字 节,在由Tomcat服务器将字节内容组成Http响应返回给浏览器。
4.
1)告知浏览器文件的类型:response.setContentType(文件的MIME类型);
2)告示浏览器文件的打开方式是下载:
response.setHeader("Content-Disposition","attachment;filename=文件名称");
5.(2)获得web应用中任何资源的绝对路径(重要 重要 重要)
方法:String path = context.getRealPath(相对于该web应用的相对地址);
(3)ServletContext是一个域对象(重要 重要 重要)
什么是域对象?什么是域?
存储数据的区域就是域对象
ServletContext域对象的作用范围:整个web应(所有的web资源都可以随意向 servletcontext域中存取数据,数据可以共享)
域对象的通用的方法:
setAtrribute(String name,Object obj);
getAttribute(String name);
removeAttribute(String name);
1.request对象和response对象的原理
1. request和response对象是由服务器创建的。我们来使用它们
2. request对象是来获取请求消息,response对象是来设置响应消息
2.获取请求消息数据
1.获取请求行数据
* GET /day14/demo1?name=zhangsan HTTP/1.1
* 方法:
1. 获取请求方式 :GET
* String getMethod()
2. (*)获取虚拟目录:/day14
* String getContextPath()
3. 获取Servlet路径: /demo1
* String getServletPath()
4. 获取get方式请求参数:name=zhangsan
* String getQueryString()
5. (*)获取请求URI:/day14/demo1
* String getRequestURI(): /day14/demo1
* StringBuffer getRequestURL() :http://localhost/day14/demo1
* URL:统一资源定位符 : http://localhost/day14/demo1 中华人民共和国
* URI:统一资源标识符 : /day14/demo1 共和国
6. 获取协议及版本:HTTP/1.1
* String getProtocol()
7. 获取客户机的IP地址:
* String getRemoteAddr()
2.获取请求头数据
* 方法:
* (*)String getHeader(String name):通过请求头的名称获取请求头的值
* Enumeration<String> getHeaderNames():获取所有的请求头名称
3.获取请求体数据
* 请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
* 步骤:
1. 获取流对象
* BufferedReader getReader():获取字符输入流,只能操作字符数据
* ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
3.其他获取请求参数
1. 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
1. String getParameter(String name):根据参数名称获取参数值 username=zs&password=123
2. String[] getParameterValues(String name):根据参数名称获取参数值的数组 hobby=xx&hobby=game
3. Enumeration<String> getParameterNames():获取所有请求的参数名称
4. Map<String,String[]> getParameterMap():获取所有参数的map集合
4.中文乱码问题
* get方式:tomcat 8 已经将get方式乱码问题解决了
* post方式:会乱码
* 解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");
5.请求转发
一种在服务器内部的资源跳转方式
1. 步骤:
1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
2. 特点:
1. 浏览器地址栏路径不发生变化
2. 只能转发到当前服务器内部资源中。
3. 转发是一次请求
6.共享数据
* 域对象:一个有作用范围的对象,可以在范围内共享数据
* request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
* 方法:
1. void setAttribute(String name,Object obj):存储数据
2. Object getAttitude(String name):通过键获取值
3. void removeAttribute(String name):通过键移除键值对
7.用户登录
1.案例分析![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9180f61c3f904b96f968313a3928a39c.png)
2.导入的jar包、建立数据库、配置文件![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/5cd47f277c1c575be884d0d76ce29b3d.png)
3.创建User
public class User {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
4.JDBCUtils
/*
JDBC工具类 使用Durid连接池
*/
public class JDBCUtils {
private static DataSource ds;
static {
try {
//1.加载配置文件
Properties pro = new Properties();
//2.使用ClassLoader加载配置文件,获取字节输入流
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//3.初始化连接池
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
获取连接池对象
*/
public static DataSource getDataSource(){
return ds;
}
}
5.UserDao
public class UserDao {
//声明JDBCTemplate对象共用
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
/**
* 登录方法
*/
public User login(User loginUser){
try {
//1.编写sql
String sql = "select * from user where username = ? and password = ?";
//调用query方法
User user = template.queryForObject(sql,
new BeanPropertyRowMapper<User>(User.class),
loginUser.getUsername(), loginUser.getPassword());
return user;
} catch (DataAccessException e) {
e.printStackTrace();//打印日志
return null;
}
}
}
6.LoginServlet
@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.设置编码
req.getRequestDispatcher("utf-8");
//2.获取请求参数
/* String username = req.getParameter("username");
String password = req.getParameter("password");
//3.封装对象
User loginuser = new User();
loginuser.setUsername(username);
loginuser.setPassword(password);*/
Map<String, String[]> map = req.getParameterMap();
//创建User对象
User loginuser = new User();
//使用BeanUtils封装
try {
BeanUtils.populate(loginuser,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//4.调用UserDao的login方法
UserDao dao = new UserDao();
User user = dao.login(loginuser);
//5.判断user
if(user == null){
//登录失败
req.getRequestDispatcher("/failServlet").forward(req,resp);
}else {
//登录成功
req.setAttribute("user",user);
//转发
req.getRequestDispatcher("/successServlet").forward(req,resp);
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
7.FailServlet和SuccessServlet
@WebServlet("/failServlet")
public class failServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("Text/html;charset=utf-8");
response.getWriter().write("登录失败!!!");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
@WebServlet("/successServlet")
public class successServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
User user = (User)request.getAttribute("user");
if (user != null) {
response.setContentType("Text/html;charset=utf-8");
response.getWriter().write("登录成功,欢迎"+user.getUsername()+"回来!");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
8.login.html
<body>
<form action="/request&response/loginServlet" method="post">
用户名:<input type="text" name="username"> <br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
8.BeanUtils工具类
populate(Object obj , Map map):将map集合的键值对信息,封装到对应的JavaBean对象中
Map<String, String[]> map = req.getParameterMap();
//创建User对象
User loginuser = new User();
//使用BeanUtils封装
try {
BeanUtils.populate(loginuser,map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
二、Response
1.功能
1. 设置响应行
1. 格式:HTTP/1.1 200 ok
2. 设置状态码:setStatus(int sc)
2. 设置响应头:setHeader(String name, String value)
3. 设置响应体:
* 使用步骤:
1. 获取输出流
* 字符输出流:PrintWriter getWriter()
* 字节输出流:ServletOutputStream getOutputStream()
2. 使用输出流,将数据输出到客户端浏览器
2.重定向
* 重定向:资源跳转的方式
* 代码实现:
//1. 设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location","/day15/responseDemo2");
//简单的重定向方法
response.sendRedirect("/day15/responseDemo2");
* 重定向的特点:redirect
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
3. 重定向是两次请求。不能使用request对象来共享数据
* 转发的特点:forward
1. 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求,可以使用request对象来共享数据
request.getRequestDispatcher("/aaaa").forward(request,response);
* forward 和 redirect 区别
* 路径写法:
1. 路径分类
1. 相对路径:通过相对路径不可以确定唯一资源
* 如:./index.html
* 不以/开头,以.开头路
* 规则:找到当前资源和目标资源之间的相对位置关系
* ./:当前目录
* ../:后退一级目录
2. 绝对路径:通过绝对路径可以确定唯一资源
* 如:http://localhost/day15/responseDemo2 /day15/responseDemo2
* 以/开头的路径
* 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
* 建议虚拟目录动态获取:request.getContextPath()
* <a> , <form> 重定向...
* 给服务器使用:不需要加虚拟目录
* 转发路径
3.服务器输出字符数据到浏览器
* 步骤:
1. 获取字符输出流
2. 输出数据
* 注意:
* 乱码问题:
1. PrintWriter pw = response.getWriter();获取的流的默认编码是ISO-8859-1
2. 设置该流的默认编码
3. 告诉浏览器响应体使用的编码
//简单的形式,设置编码,是在获取流之前设置
response.setContentType("text/html;charset=utf-8");
4.验证码
@WebServlet("/imageServlet")
public class ImageServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 100;
int height = 50;
//1.创建一对象
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//2.美化图片
//2.1填充画笔色
Graphics g = image.getGraphics();//画笔对象
g.setColor(Color.pink);//设置画笔颜色
g.fillRect(0,0,width,height);
//2.2花边框
g.setColor(Color.blue);
g.drawRect(0,0,width-1,height-1);
String str = "ABCDEFGHIJKLMNOPQRSTUVWSYZabcdefghijklmnopqrstuvwzyz0123456789";
//生成随机角标
Random ran = new Random();
for (int i = 1;i<=4;i++) {
int index = ran.nextInt(str.length());
//获取随机字符
char ch = str.charAt(index);
//2.3写验证码69696
g.drawString(ch+"",width/5*i,height/2);
}
//花干扰线
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());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
5.ServletContext对象
1. 概念:代表整个web应用,可以和程序的容器(服务器)来通信
2. 获取:
1. 通过request对象获取
request.getServletContext();
2. 通过HttpServlet获取
this.getServletContext();
3. 功能:
1. 获取MIME类型:
* MIME类型:在互联网通信过程中定义的一种文件数据类型
* 格式: 大类型/小类型 text/html image/jpeg
* 获取:String getMimeType(String file)
2. 域对象:共享数据
1. setAttribute(String name,Object value)
2. getAttribute(String name)
3. removeAttribute(String name)
* ServletContext对象范围:所有用户所有请求的数据
3. 获取文件的真实(服务器)路径
1. 方法:String getRealPath(String path)
String b = context.getRealPath("/b.txt");//web目录下资源访问
System.out.println(b);
String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
System.out.println(c);
String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
System.out.println(a);
6.案例
- 文件下载需求:
- 页面显示超链接
- 点击超链接后弹出下载提示框
- 完成图片文件下载
1.页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/request&response/img/1.jpg">图片1</a>
<a href="/request&response/img/1.avi">视频</a>
<hr>
<a href="/request&response/downloadServlet?filename=九尾.jpg">图片1</a>
<a href="/request&response/downloadServlet?filename=1.avi">视频</a>
</body>
</html>
2.代码
@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取请求参数,文件名称
String filename = request.getParameter("filename");
//2.使用字节输入流加载文件进内存
//2.1找到文件服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/" + filename);
//2.2用字节流关联
FileInputStream fis = new FileInputStream(realPath);
//3.设置response的响应头
//3.1设置响应头类型:content-type
String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型
response.setHeader("content-type",mimeType);
//3.2设置响应头打开方式:content-disposition
//解决中文文件名问题
//1.获取user-agent请求头、
String agent = request.getHeader("user-agent");
//2.使用工具类方法编码文件名即可
filename = DownLoadUtils.getFileName(agent, filename);
response.setHeader("content-disposition","attachment;filename="+filename);
//4.将输入流的数据写出到输出流中
ServletOutputStream sos = response.getOutputStream();
byte[] buff = new byte[1024 * 8];
int len = 0;
while((len = fis.read(buff)) != -1){
sos.write(buff,0,len);
}
fis.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
3.中文工具包
public class DownLoadUtils {
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException, UnsupportedEncodingException {
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
filename =new String(filename.getBytes(),"ISO8859-1");
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}