一、HttpServletRequest类
HttpServletRequest 类作用
每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到 Request 对象中。然后传递到 service方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息.
1.1 HttpServletRequest类的常用方法
常用方法 | 方法介绍 |
---|---|
String getParameter(String name) | 返回name指定参数的参数值 |
String[] getParameterValues(String name) | 返回包含参数name的所有值的数组 |
void setAttribute(String,Object) | 存储此请求中的属性 |
Object getAttribute(String name) | 返回指定属性的属性值 |
String getContentType() | 得到请求体的MIME类型 |
String getProtocol() | 返回请求用的协议类型及版本号 |
String getServerName() | 返回接受请求的服务器主机名 |
int getServerPort() | 返回服务器接受此请求所用的端口号 |
String getCharacterEncoding() | 返回字符编码方式 |
void setCharacterEncoding() | 设置请求的字符编码方式 |
int getContentLength() | 返回请求体的长度(以字节数) |
String getRemoteAddr() | 返回发送此请求的客户端IP地址 |
String getRealPath(String path) | 返回一虚拟路径的真实路径 |
String request.getContextPath() | 获取当前工程路径 |
getRequestDispatcher() | 获取请求转发对象 |
getRequestURI() | 获取请求的资源路径 |
getRequestURL() | 获取请求的统一资源定位符(绝对路径) |
getHeader(String name) | 得HTTP协议定义的文件头信息 |
getMethod() | 获取请求的方式 GET 或 POST |
-
常用方法实例
public class RequestAPIServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws javax.servlet.ServletException, IOException { // getRequestURI() 获取请求的资源路径 System.out.println("URI="+req.getRequestURI());//"/07_servlet/RequestAPIServlet" // getRequestURL() 获取请求的统一资源定位符(绝对路径) System.out.println("URL="+req.getRequestURL());//"http://localhost:8080/07_servlet/RequestAPIServlet" // getRemoteHost() 获取客户端的ip地址 /** * 在IDEA中,使用localhost访问时,得到的客户端 ip 地址是 ===>>> 127.0.0.1<br/> * 在IDEA中,使用127.0.0.1访问时,得到的客户端 ip 地址是 ===>>> 127.0.0.1<br/> * 在IDEA中,使用 真实ip 访问时,得到的客户端 ip 地址是 ===>>> 真实的客户端 ip 地址<br/> */ System.out.println("客户端ip地址:"+req.getRemoteHost()); // iv.getHeader() 获取请求头 System.out.println("请求头User-Agent ==>> "+req.getHeader("User-Agent")); // vii.getMethod() 获取请求的方式GET或POST System.out.println("请求的方式 ==>> " + req.getMethod()); //getContextPath()返回获取当前工程路径 System.out.println("获取当前工程路径:"+req.getContextPath());// “/07_servlet” } }
-
获取请求参数
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("-----get------"); // 获取请求参数 String username = req.getParameter("username"); String password = req.getParameter("password"); String[] hobby = req.getParameterValues("hobby"); System.out.println("用户名:" + username); System.out.println("密码:" + password); System.out.println("兴趣爱好:" + Arrays.asList(hobby)); }
1.2 解决doGet 和 doPost 请求中文乱码
- doGet解决请求乱码问题
// 获取请求参数
String username = req.getParameter("username");
//1 先以 iso8859-1 进行编码
//2 再以 utf-8 进行解码
username = new String(username.getBytes("iso-8859-1"), "UTF-8");
- doPost解决请求乱码问题
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置请求体的字符集为 UTF-8 ,从而解决 post 请求的中文乱码问题
req.setCharacterEncoding("utf-8");
// 获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("用户名:" + username);
System.out.println("密码:" + password);
System.out.println("兴趣爱好:" + Arrays.asList(hobby));
}
1.3 请求转发
服务器收到请求后,从一次资源跳转到另一个资源的操作叫请求转发。
请求转发的特点:
1.浏览器地址栏没有变化
2.他们是一次请求
3.他们共享request域中的数据
4.可以转发到WEB-INF目录
5.不可以访问工程以外的资源
Servlet1代码:
public class Servlet1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取form表单中的数据
String username = request.getParameter("username");
// 将数据存储到request对象中
request.setAttribute("key","servlet1中的数据");
//返回封装了某条路径所指定资源的 RequestDispatcher 对象。其中,参数 path 必须以“/”开头
//请求转发必须要以斜杠打头,/ 斜杠表示地址为:http://ip:port/工程名/ , 映射到IDEA代码的web目录
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet2");
//将请求从一个 Servlet 传递给另一个 Web 资源
requestDispatcher.forward(request,response);
}
}
Servlet2代码:
public class Servlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取servlet1中设置的数据
System.out.println(request.getAttribute("key"));//servlet1中的数据
}
}
1.4 base标签的作用
- 相对路径在工作时候都会参照当前浏览器地址栏中的地址来进行跳转。
- base标签可以设置当前页面中所有相对路径工作时,参照哪个路径来进行跳转
没有设置base标签:(此时页面中的超链接需要根据浏览器地址栏动态的改变)
设置base标签之后:
1.5 Web中的相对路径和绝对路径
在 javaWeb 中,路径分为相对路径和绝对路径两种:
-
相对路径是:
. 表示当前目录 .. 表示上一级目录 资源名 表示当前目录/资源名(和资源名前加./是等价的)
-
绝对路径:
http://ip:port/工程路径/资源路径
在实际开发中,路径都使用绝对路径,而不简单的使用相对路径。
1、绝对路径
2、base+相对
1.6 web中 /斜杠 的不同意义
-
在web中/斜杠是一种绝对路径。
浏览器解析: / 斜杠如果被浏览器解析,得到的地址是:http://ip:port/ <a href="/">斜杠</a> 服务器解析: / 斜杠 如果被服务器解析,得到的地址是:http://ip:port/工程路径 1、<url-pattern>/servlet1</url-pattern> 2、servletContext.getRealPath("/"); 3、request.getRequestDispatcher("/"); 特殊情况: response.sendRediect("/"); 把斜杠发送给浏览器解析。得到 http://ip:port/
二、HttpServletResponse类
-
HttpServletResponse 类和 HttpServletRequest 类一样。每次请求进来,Tomcat 服务器都会创建一个Response对象传递给 Servlet 程序去使用HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息,
-
我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 对象来进行设置
2.1 HttpServletResponse类的常用方法
- 设置响应头信息
方法 | 介绍 |
---|---|
setHeader(String name,String value) | 设置具有给定名称和值的响应标头,但是同键会被覆盖 |
addHeader(String name, String value) | 添加具有给定名称和值的响应标头,但不会覆盖 |
public class ServletMethod extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置响应头
resp.setHeader("name","key1");
resp.setHeader("name","key2");//将key1覆盖
resp.addHeader("name2","key1");
resp.addHeader("name2","key2");
resp.setHeader("content-type", "text/html;charset=utf-8");//设置响应编码格式
}
}
- 设置响应状态
方法 | 介绍 |
---|---|
resp.sendError(int) | 向客户端发送一个代表特定错误的HTTP响应状态码 |
resp.sendError(int,String) | 向客户端发送一个代表特定错误的HTTP响应状态码,并且发送具体的错误信息 |
response.setContentType(“text/html;charset=utf-8”) | 设置响应编码等同与调用response.setHeader(“content-type”, “text/html;charset=utf-8”) |
- 设置响应正文
方法 | 介绍 |
---|---|
getOutputStream() | 返回一个ServletOutputStream对象,Servlet用它来输出二进制的正文数据。 |
getWriter() | 返回一个PrintWriter对象,Servlet用它来输出字符串形式的正文数据。 |
2.2 如何往客户端回传数据
字节流 getOutputStream(); 常用于下载(传递二进制数据)
字符流 getWriter(); 常用于回传字符串(常用)
注意:在一个请求中,不能同时使用这两个流!也就是说,要么你使用repsonse.getWriter(),要么使用response.getOutputStream(),但不能同时使用这两个流。不然会抛出illegalStateException异常。
-
缓冲区:
response.getWriter()是PrintWriter类型,所以它有缓冲区,缓冲区的默认大小为8KB。也就是说,在响应数据没有输出8KB之前,数据都是存放在缓冲区中,而不会立刻发送到客户端。当Servlet执行结束后,服务器才会去刷新流,使缓冲区中的数据发送到客户端。
如果希望响应数据马上发送给客户端:
使用out.flush()表示强制将缓冲区中的数据发送出去 -
writer() 和 print()的区别:
write():仅支持输出字符类型数据,字符、字符数组、字符串等
print():可以将各种类型(包括Object)的数据通过默认编码转换成bytes字节形式,这些字节都通过write(int c)方法被输出
public class ResponseIOServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
//要求:往客户端回传字符串数据
PrintWriter out = response.getWriter();
out.write("response's content");
out.write("国哥很帅");
}
}
2.3 响应的乱码解决
解决响应中文乱码方案一(不推荐使用):
// 设置服务器字符集为 UTF-8
resp.setCharacterEncoding("UTF-8");
// 通过响应头,设置浏览器也使用 UTF-8 字符集
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
解决响应中文乱码方案二(推荐):
// 它会同时设置服务器和客户端都使用 UTF-8 字符集,还设置了响应头
// 此方法一定要在获取流对象之前调用才有效
resp.setContentType("text/html; charset=UTF-8");
2.4 请求重定向
特点:
1.浏览器地址栏会发生变化
2.两次请求
3.不共享request域中数据
4.不能访问WEB-INF下得资源
5.可以访问工程外的资源
方法一:
public class Response1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("我是Response1");
//设置响应状态码302,表示重定向
response.setStatus(302);
//设置响应头,说明新的地址在哪里
response.setHeader("location","http://localhost:8080/07_servlet/response2");//请求重定向到response2
}
}
public class Response2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("我是response2");
}
}
方法二:(推荐)
public class Response1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("我是Response1");
//把"/"斜杠发送给浏览器解析。得到 http://ip:port/
response.sendRedirect("http://localhost:8080/07_servlet/response2");//请求重定向到response2
}
}
public class Response2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("我是response2");
}
}
三、请求转发和重定向的区别
- 请求转发是一个请求一次响应,而重定向是两次请求两次响应。
- 请求转发地址不变化,而重定向会显示后一个请求的地址。这是因为请求转发是服务器的行为,是由容器控制的转向,整个过程处于同一个请求中,因此客户端浏览器不会显示转向后的地址;但重定向是客户端的行为,重新发送了请求,整个过程不在同一个请求中,因此客户端浏览器会显示跳转后的地址。
- 请求转发只能转发到本项目其它Servlet,而重定向不只能重定向到本项目的其它Servlet,还能定向到其它项目。
- 请求转发是服务端行为,只需给出转发的Servlet路径,而重定向需要给出requestURI,既包含项目名。
请求转发:
请求重定向:
重定向和转发页面的后续代码是否执行
重定向和转发页面的后续代码是否执行:https://blog.youkuaiyun.com/dear_syl/article/details/82116394
sendRedirect()之后的代码是否会继续执行:https://blog.youkuaiyun.com/learningforfun/article/details/67835627
总结:
重定向:会在当前页面代码执行完毕后,跳转到指定的页面执行其他代码。
转 发:在本页面代码执行到转发语句后,即跳转到指定的页面执行其他代码,执行完毕后返回接着执行转发语句后的代码