Servlet-2
HttpServletRequest 类
作用
每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中,然后传递到 service 方法(doGet 和 doPost)中,我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。
方法
- getRequestURI():获取请求的资源路径
- getRequestURL():获取请求的统一资源定位符(绝对路径)
- getRemoteHost():获取客户端的 ip 地址
- getHeader():获取请求头
- getParameter():获取请求的参数
- getParameterValues():获取请求的参数(多个值的时候使用)
- getMethod():获取请求的方式 GET 或 POST
- setAttribute(key, value):设置域数据
- getAttribute(key):获取域数据
- getRequestDispatcher():获取请求转发对象
package servlet2;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 演示HttpServletRequest类的常用方法:
* getRequestURI() 获取请求的资源路径
* getRequestURL() 获取请求的URL地址
* getRemoteHost() 获取客户端的ip地址
* getHeader() 获取请求头
* getMethod() 获取请求的方式 GET 或 POST
* getParameter() 获取请求的参数
* getParameterValues() 获取请求的参数(多个值的时候使用)
* @author MCC
*
*/
public class HttpServletRequestDemo extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public HttpServletRequestDemo() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求的资源路径
System.out.println("URI=" + request.getRequestURI());//URI=/DynamicWeb/HSRDemo
//获取请求的URL地址
System.out.println("URL=" + request.getRequestURL());//URL=http://localhost:8080/DynamicWeb/HSRDemo
//获取客户端的ip地址
/**
* 在eclipse中,使用localhost访问时,得到的客户端 ip地址是:ip=0:0:0:0:0:0:0:1
* 在eclipse中,使用127.0.0.1访问时,得到的客户端 ip 地址是:ip=127.0.0.1
* 在eclipse中,使用真实ip访问时,得到的客户端ip地址是:ip=192.168.0.155
*/
System.out.println("ip=" + request.getRemoteHost());
//获取请求头
System.out.println("请求头User-Agent=" + request.getHeader("User-Agent"));
//请求头User-Agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0
// 获取请求的方式GET或POST
System.out.println("请求方式=" + request.getMethod());//请求方式=GET
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
获取请求参数
form.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>form</title>
</head>
<body>
<form action="http://localhost:8080/DynamicWeb/GPServlet" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
兴趣:<input type="checkbox" name="hobby" value="java">java
<input type="checkbox" name="hobby" value="python">python
<input type="checkbox" name="hobby" value="C++">C++
<input type="checkbox" name="hobby" value="C">C<br>
<input type="submit">
</form>
</body>
</html>
Servlet程序:
package servlet2;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 接收来自form.html提交的数据
* @author MCC
*
*/
public class GetParameterServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public GetParameterServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* getParameter() 获取请求的参数
* getParameterValues() 获取请求的参数(多个值的时候使用)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("--------------doGet()----------------");
//getParameter() 获取请求的参数,表单中的name属性值就是要获取的参数名
String userName = request.getParameter("username");
String password = request.getParameter("password");
//属性有多个值时使用getParameterValues()
String[] hobby = request.getParameterValues("hobby");
System.out.println("姓名:"+userName+"\n密码:"+password+"\n兴趣:"+Arrays.asList(hobby));
// for(String str : hobby) {
// System.out.print(str + " ");
// }
}
}
解决请求乱码问题
设置请求体的字符集为UTF-8,解决请求的中文乱码问题,
但是要注意:request.setCharacterEncoding()方法,必须要在获取请求参数之前使用才有效,
也就是说,setCharacterEncoding()的使用必须放在getParameter()和getParameterValues()之前。
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("--------------doPost()----------------");
/*
* 设置请求体的字符集为UTF-8,解决请求的中文乱码问题,
* 但是要注意:setCharacterEncoding()方法,必须要在获取请求参数之前使用才有效,
* 也就是说,setCharacterEncoding()的使用必须放在getParameter()和getParameterValues()之前
*/
request.setCharacterEncoding("UTF-8");
//getParameter() 获取请求的参数,表单中的name属性值就是要获取的参数名
String userName = request.getParameter("username");
String password = request.getParameter("password");
//属性有多个值时使用getParameterValues()
String[] hobby = request.getParameterValues("hobby");
System.out.println("姓名:"+userName+"\n密码:"+password+"\n兴趣:"+Arrays.asList(hobby));
}
请求转发
- 什么是请求转发?
请求转发是指,服务器收到请求后,从一个资源跳转到另一个资源,叫做请求转发。 - 请求转发的特点:
(1)浏览器地址栏中的地址没有发生变化
(2)请求转发涉及到的程序是一次请求
(3)程序共享Request域中的数据(注意:ServletContext域中的数据整个工程共享)
(4)可以转发到WEB-INF目录下并访问资源(因为请求转发是服务器发起的,可以访问WEB-INF中的资源,浏览器不能直接访问WEB-INF下的资源)
(5)不可以访问工程以外的资源(例如转发到:http://www.baidu.com是不可以的)
Servelt1.java
package servlet3;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 演示Servlet的请求转发
* 步骤:
* Servlet程序1:
* (1)获取请求参数
* (2)追加标识属性
* (3)获取Servlet程序2地址(与web.xml配置文件中的访问路径相同)
* (4)转发到Servlet程序2
* Servlet程序2:
* (1)获取请求参数
* (2)检验是否有Servlet程序1的标识
* (3)事务处理
*
* 请求转发的特点:
* (1)浏览器的地址没有发生变化
* (2)请求转发涉及到的程序是一次请求
* (3)程序共享Request域中的数据(注意:ServletContext域中的数据整个工程共享)
* (4)可以转发到WEB-INF目录下并访问资源(因为请求转发是服务器发起的,可以访问WEB-INF中的资源,浏览器不能直接访问WEB-INF下的资源)
* (5)不可以访问工程以外的资源(例如转发到:http://www.baidu.com是不可以的)
* @author MCC
*
*/
public class Servlet1 extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求参数
String username = req.getParameter("username");
System.out.println("Servlet1: "+username);
//2.追加标识属性
req.setAttribute("process", "process1_ok");
/*
* 3.获取要转发到的程序的地址(与web.xml配置文件中的访问路径相同)
* 请求转发必须要以斜杠开始,/ 斜杠表示地址为:http://ip:port/工程名/ , 映射到整个工程的web目录下
*/
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
//可以转发到WEB-INF中的资源,WEB-INF中的资源是不允许直接访问的
// RequestDispatcher requestDispatcher = req.getRequestDispatcher("/WEB-INF/form.html");
//转发到上述地址
requestDispatcher.forward(req, resp);
/*
* 上行执行完毕之后,马上转去执行Servlet2的代码,Servlet2执行完毕之后,再转回执行剩余代码,因此结果为:
* Servlet1: MCC
* Servlet2: MCC
* Servlet2的事务
* Servlet1处理完毕,请求已转发到Servlet2
*/
System.out.println("Servlet1处理完毕,请求已转发到Servlet2");
}
}
Servlet2.java
package servlet3;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 接收来自Servlet1的转发请求
* @author MCC
*
*/
public class Servlet2 extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求参数
String username = req.getParameter("username");
System.out.println("Servlet2: "+username);
//检验是否有Servlert1的标识
Object flag = req.getAttribute("process");
if(flag=="process1_ok") {
//进行Servlet2的事务
System.out.println("Servlet2的事务");
}
}
}
base 标签
base标签可以设置当前页面中的所有相对路径在解析时,根据哪个路径进行跳转,资源为目录时必须以 / 结尾
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>base</title>
<!--
base标签可以设置当前页面中的所有相对路径在解析时,根据哪个路径进行跳转
b/ b后面的斜杠必须有,有斜杠时才是目录,没有斜杠会被解析为资源
-->
<base href="http://localhost:8080/DynamicWeb/HTML/a/b/">
</head>
<body>
<a href="../../../index.html">点击跳转到index.html</a>
</body>
</html>
Web中的相对路径和绝对路径
在 javaWeb 中,路径分为相对路径和绝对路径两种:
- 相对路径:
路径 | 含义 |
---|---|
•/ | 表示当前目录下,可以省略 |
••/ | 表示上一级目录下 |
资源名 | 等同于 •/ 资源名,表示当前目录 / 资源名 |
- 绝对路径:
http://ip:port/工程路径/资源路径
在实际开发中,路径一般使用下面两种形式:
- 绝对路径
- base标签 + 相对路径
web 中 / 斜杠的不同意义
被x解析 | 含义 | |
---|---|---|
/ | 浏览器 | http://ip:port/ |
/ | 服务器 | http://ip:port/工程路径 |
HttpServletResponse 类
作用
HttpServletResponse 类和 HttpServletRequest 类类似,每次有请求传入服务器,Tomcat 服务器都会创建一个 Response 对象,并传递给 Servlet 程序。HttpServletResponse 类表示所有响应的信息,可以根据需要设置返回给客户端的信息。
输出流
流 | 方法 | 用途 |
---|---|---|
字节流 | getOutputStream() | 常用于下载(传递二进制数据) |
字符流 | getWriter() | 常用于回传字符串(常用) |
注意:两个流同时只能使用其中之一。 使用了字节流,就不能再使用字符流,反之亦然,否则会报错。
package servletCharset;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletResponse1 extends HttpServlet{
private static final long serialVersionUID = 1L;
/**
* 两个输出流:
* 字节流 getOutputStream(); 常用于下载(传递二进制数据)
* 字符流 getWriter(); 常用于回传字符串(常用)
* 两个流同时只能使用一个,使用了字节流,就不能再使用字符流,反之亦然,否则就会报错。
*
* 两个流在输出基本数据类型(如int)时,print()方法可以正常输出,write()方法会转换为对应的ASCII码,
* 因此使用print()输出较好
*
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//向浏览器回传收到请求提示
//获取输出流对象
PrintWriter writer = resp.getWriter();
writer.println("Date Received");
// writer.write("Date Received");
}
}
解决响应乱码问题
方法1:分别设置服务器和浏览器的字符集(不推荐使用)
//设置服务器字符集为 UTF-8
resp.setCharacterEncoding("UTF-8");
//通过响应头,设置浏览器的字符集为 UTF-8
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
方法2:同时设置服务器和浏览器的字符集
//该方法会同时设置服务器和浏览器的字符集均为 UTF-8,并设置响应头信息。
resp.setContentType("text/html; charset=UTF-8");
注意:该方法一定要在获取流对象之前使用才会有效。
请求重定向
-
什么是请求重定向?
请求重定向,是指客户端给服务器发送请求,但请求的地址已经不存在或其他原因不能访问,此时,该请求被指派到其他地址的现象。 -
请求重定向的特点:
(1)浏览器地址栏中的地址发生变化
(2)请求重定向是两次请求
(3)程序不共享Request域中的数据
(4)不能访问WEB-INF目录下的资源(因为请求重定向是浏览器发起的,浏览器不能直接访问WEB-INF下的资源)
(5)可以访问工程以外的资源(例如重定向到:http://www.baidu.com是可以的)
实现方式1 (不推荐使用):
//设置响应状态码302 ,表示重定向
resp.setStatus(302);
//设置响应头,告知新地址
resp.setHeader("Location", "http://localhost:8080/DynamicWeb/servletRedirect2");
实现方式2:
resp.sendRedirect("http://localhost:8080/DynamicWeb/servletRedirect2");
注意:重定向的地址是要被浏览器解析的,因此不能直接写为 /servletRedirect2,这个被浏览器解析为http://localhost:8080/servletRedirect2,会报404错误(缺少工程路径)