Request和Response都是Servlet的service方法的参数,Request负责获取请求数据,而Response负责设置相应数据~
一.Request
1.继承体系
Tomcat负责解析数据,因此由Tomcat来提供实现类~
2.获取请求数据
- 请求行
- 请求头
- 请求体
需要注意的是只有Post方法才有请求体。因此请求体的方法应该写到Servlet的doPost方法中~
3.通用方式获取请求参数
尝试一下,先写一个用户表单:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="//Servlet_F1_war/demo2" ><input type="text" name="username"><br/><input type="password" name="password"><br/><input type="checkbox" name="gender" value="男">男<br/><input type="checkbox" name="gender" value="女">女<br/><input type="submit" ><br/></form>
</body>
</html>
注意, 第一个斜杠后面是项目的访问路径(也就是名称),第二个是自愿路径(这里是一个Servlet的注解!)
Servlet的代码如下(只演示第一个方法:)
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("此时调用的是get方法~");Map<String,String[]> map = req.getParameterMap();//键入:iter 快速遍历for (String key : map.keySet()) {System.out.print(key+" ");String[] values = map.get(key);for(String value : values){System.out.print(value + ",");}System.out.println();}}
Get方法将参数提交到Url里面:
打印成功:
然后将表单的提交方式改为post,doGet方法修改如下:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String m =req.getMethod();System.out.println("此时调用的是"+m+"方法~");Map<String,String[]> map = req.getParameterMap();//键入:iter 快速遍历for (String key : map.keySet()) {System.out.print(key+" ");String[] values = map.get(key);for(String value : values){System.out.print(value + ",");}System.out.println();}}
然后doPost直接调用doGet:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req,resp);}
post方法将参数隐藏在请求体中:
请求成功(中文有些乱码,暂时忽略):
完整的代码如下,经供参考:
package Myweb;
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.io.IOException;
import java.util.Map;@WebServlet("/demo2")
public class ServletDemo2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String m =req.getMethod();System.out.println("此时调用的是"+m+"方法~");Map<String,String[]> map = req.getParameterMap();//键入:iter 快速遍历for (String key : map.keySet()) {System.out.print(key+" ");String[] values = map.get(key);for(String value : values){System.out.print(value + ",");}System.out.println();}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doGet(req,resp);}
}
4.解决乱码
post的解决非常简单,只需要如下代码设置字符流的输入编码,即可完美解决:
req.setCharacterEncoding("UTF-8");
搞定~
对于汉字类型的数据,在get方式中会通过Url编码变为16进制数据。乱码的原因是Tomcat在解码时默认使用ISO-8859-1。这里给出一个通用的方式,假设中文数据的名称为username:
username = new String(username.getBytes(StandardCharsets.ISO_8859_1),StandardCharsets.UTF_8);
也可以解决post方式。
不过,Tomcat8版本之后已经默认解决了GET方式乱码的问题,大家不需要操心~
5.请求转发
一种在服务器内部的资源跳转方式。
新建Servlet3号和4号如下:
package Myweb;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.io.IOException;@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("使用的是Servlet3号~");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}
package Myweb;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.io.IOException;@WebServlet("/demo4")
public class ServletDemo4 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("使用的是Servlet4号~");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}
在Servlet3中书写请求转发到Servlet4的代码:
req.getRequestDispatcher("/demo4").forward(req,resp);
访问Servlet3成功后,Servlet4也会一起成功:
请求转发的特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器的内部资源
- 一次请求可以在转发的资源间使用request共享数据
二.Response
1.设置响应数据
2.完成重定向
重定向是一种资源跳转方式。状态码是:302。位置的格式是:响应头Location:xxx
定义两个Servlet:
package Myweb.Response;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.io.IOException;@WebServlet("/respd1")
public class RespDemo1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("访问的是Response1~");resp.setStatus(302);resp.setHeader("Location","/Servlet_F1_war/respd2");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}
package Myweb.Response;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.io.IOException;@WebServlet("/respd2")
public class RespDemo2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("重定向的Resp2也被访问了~");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}
}
虚拟路径一定要写对,这是易错点。
如上,访问1号2号也会被重定向~
resp.sendRedirect("/Servlet_F1_war/respd2");
如上是一种简化写法。
重定向的特点:
- 浏览器地址栏路径发生变化
- 可以重定向到任意位置的资源(服务器内部、外部均可)
- 两次请求,不能在多个资源使用request共享数据
重定向与请求转发的特点完全相反~
针对于虚拟路径:
- 浏览器使用:需要加虚拟目录(项目访问路径)
- 服务端使用:不需要加虚拟目录
String contextPath = request.getContextPath(); response.sendRedirect(contextPath+"/resp2");
如上是动态配置虚拟目录的方式~
3.响应字符数据
PrintWriter writer=resp.getWriter();
//获取字符输出流writer.write("啦啦啦~");writer.write("<h1>HELLO</h1>");
通过Response对象获取字符输出流,并写出数据~
存在乱码现象,且按照普通文本的读取方式~
resp.setContentType("text/html;charset=UTF-8");
设置头的解析方式,并设置流的编码为UTF-8。
成功。
(流不需要关闭,Response对象销毁后服务器会将其自动关闭~)
4.响应字节数据
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency>
引入工具类坐标。
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1、读取文件FileInputStream fis=new FileInputStream("E:\\照片//德拜.jpg");//2、获取字节输出流ServletOutputStream os = resp.getOutputStream();//3、完成流的复制IOUtils.copy(fis,os);}
如上。
即可成功读取图片~