Request和Response

一、简介:

  • web服务器收到客户端的http请求后,会针对每一次请求分别创建代表请求的request对象和代表响应的response对象。
  • request对象和response对象既然代表请求和响应,那我们要想获得客户端请求提交过来的数据只需要找request对象;要想向客户机输出数据,只需要找到response对象就行。
  • request和response对象都是有服务器端创建的。

体系结构:

Request和Response

二、Request:

1、获取客户机信息常用方法:

方法 作用
public String getMethod() 返回用于发出此请求的 HTTP 方法的名称,例如 GET、POST 或 PUT。
public StringBuffer getRequestURL() 重新构造客户端用于发出请求的 URL(http://localhost/day/hello)
public String getRequestURI() 返回此请求的 URL 的一部分,从协议名称一直到 HTTP 请求的第一行中的查询字符串。POST /some/path.html HTTP/1.1—>/some/path.html
public String getQueryString() 返回包含在请求 URL 中路径后面的查询字符串
public String getContextPath() 返回请求 URI 指示请求上下文的那一部分(/day)
public String getRemoteAddr() 返回发送请求的客户端或最后一个代理的 Internet Protocol (IP) 地址。(ServletRequest类)

2、获取请求头信息常用方法:

方法 作用
public String getHeader(String name) 以 String 的形式返回指定请求头的值
public java.util.Enumeration getHeaders(String name) 以 String 对象的 Enumeration 的形式返回指定请求头的所有值。
public java.util.Enumeration getHeaderNames() 返回此请求包含的所有头名称的枚举。如果该请求没有头,则此方法返回一个空枚举。

3、获取请求参数常用方法:

方法 作用
public String getParameter(String name) 以 String 形式返回请求参数的值,如果该参数不存在,则返回 null
public String[] getParameterValues(String name) 返回包含给定请求参数拥有的所有值的 String 对象数组,如果该参数不存在,则返回 null。
public java.util.Enumeration getParameterNames() 返回包含此请求中所包含参数的名称的 String 对象的 Enumeration。如果该请求没有参数,则此方法返回一个空的 Enumeration

| public java.util.Map<K, V> getParameterMap() |返回此请求的参数的 java.util.Map |
4、域对象的常用方法:

方法 作用
public void setAttribute(String name, Object o) 存储此请求中的属性。在请求之间重置属性。此方法常常与 RequestDispatcher 一起使用。
存储此请求中的属性。在请求之间重置属性。此方法常常与 RequestDispatcher 一起使用。 以 Object 形式返回指定属性的值,如果不存在给定名称的属性,则返回 null。
public void removeAttribute(String name) 从此请求中移除属性。此方法不是普遍需要的,因为属性只在处理请求期间保留。

5、请求转发的常用方法:

方法 作用
public RequestDispatcher getRequestDispatcher(String path) 返回一个 RequestDispatcher 对象,它充当位于给定路径上的资源的包装器。
public void forward(ServletRequest request, ServletResponse response) 将请求从一个 servlet 转发到服务器上的另一个资源(servlet、JSP 文件或 HTML 文件)。此方法允许一个 servlet 对请求进行初步处理,并使另一个资源生成响应。

思考:
如何获取当前项目的资源路径:getRequestURI()-getContextPath()=hello

实例:

1、获取客户机信息

  • request1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/day05/request1">
<input type="text" name="username" value=""/><br>
<input type="password" name="username" value=""/><br>
<input type="submit" value="OK"/>
</form>
</body>
</html>
  • RequestServlet1.java
public class RequestServlet1 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 1、获取请求方式
		System.out.println("请求方式" + request.getMethod());

		// 2、获取请求路径:
		System.out.println("URL:" + request.getRequestURL());
		System.out.println("URI:" + request.getRequestURI());
		System.out.println("虚拟目录映射:" + request.getContextPath());

		// 3、获取请求参数:
		System.out.println(request.getQueryString());
		System.out.println(request.getRemoteAddr());
		// 4、获得请求资源
		// 4.1得到请求URI
		String uri = request.getRequestURI();
		// 4.2得到请求的虚拟目录
		String path = request.getContextPath();
		// 4.3得到资源
		System.out.println(uri.substring(path.length()));
		System.out.println();
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

获得结果:
Request和Response

2、获取请求头参数

防盗链:
request2.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="/day05/request2">是否防盗链</a>
</body>
</html>

RequestServlet2.java

public class RequestServlet2 extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String referer = request.getHeader("referer");
		if("http://localhost/day05/request/request2.html".equalsIgnoreCase(referer)){
			System.out.println("没有防盗链");
		}else{
			System.out.println("盗链来的");
		}
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

3、获取请求参数

向服务器发出请求,带参数传递:
request3.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

	function onchange(){
		window.location.href="/day05/request3?username='tom'&password='123'";
	}

</script>
</head>
<body>
<!-- 1、超链接  -->
<a href="/day05/request3?username='tom'&password='123'">点击跳转</a>
<!-- 2、form表单  -->
<form action="/day05/request3">
<input type="text" name="username"   /><br>
<input type="text" name="password"   /><br>

<input type="checkbox" name="interesting" value="打篮球" />打篮球
<input type="checkbox" name="interesting" value="踢足球" />踢足球
<input type="checkbox" name="interesting" value="打羽毛球" />打羽毛球<br>

<input type="radio" name="gender" value="男"/>男
<input type="radio" name="gender" value="女"/>女<br>

<select name="city">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="深圳">深圳</option>

</select><br>

<input type="submit"  value="OK" />
</form>

<!-- 3、直接在地址栏输入 -->

<!-- javaScript -->
<input type="button" value="发送消息" onclick="onchange()" />

</body>
</html>

RequestServlet3.java:

public class RequestServlet3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		response.setCharacterEncoding("utf-8");
		// 获取姓名密码
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		// 获取兴趣(多选框)
		String[] interestings = request.getParameterValues("interesting");
		// 获取性别
		String gender = request.getParameter("gender");
		// 获取城市
		String city = request.getParameter("city");
		response.getWriter().write(username + "::" + password+"<br>");

		response.getWriter().write(Arrays.toString(interestings)+"<br>");
		response.getWriter().write(gender+"<br>");
		response.getWriter().write(city+"<br>");
		
		
		//得到参数名集合
		Enumeration<String> enums = request.getParameterNames();
		while(enums.hasMoreElements()){
			response.getWriter().write(enums.nextElement()+"<br>"+"<br>");
		}
		
		//以Map的形式获取参数名和参数值
		Map<String, String[]> map = request.getParameterMap();
		Set<String> keys = map.keySet();
		
		for (String key : keys) {
			String[] values = map.get(key);
			response.getWriter().write("KEY:"+key+"VALUE:"+Arrays.toString(values)+"<br>");
		}
		
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

4、获取请求域传递对象

  • 设置属性
    void setAttribute(String name, Object o)

  • 获取属性
    Object getAttribute(String name)

  • 移除属性
    void removeAttribute(String name)

5、请求转发

FirstServlet.java:

public class FirstServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setAttribute("name", "Tom");
		request.getRequestDispatcher("/second").forward(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

SecondServlet.java

public class SecondServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		String attribute = (String) request.getAttribute("name");
		response.getWriter().write(attribute + "<br>");
		response.getWriter().write("我是请求转发来的");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

三、response:

常用方法:
1、设置响应状态码:

方法 作用
public void setStatus(int sc) 设置此响应的状态代码

2、设置响应头:

方法 作用
public void setDateHeader(String name, long date) 用给定名称和日期值设置响应头
public void setHeader(String name, String value) 用给定名称和值设置响应头
public void setIntHeader(String name, int value) 用给定名称和整数值设置响应头
public void sendRedirect(String location) 使用指定重定向位置 URL 将临时重定向响应发送到客户端。

3、设置响应正文:(比较特殊)
需要先获取输出流对象,然后根据流对象输出信息

方法(HttpServlet中的方法) 作用
public ServletOutputStream getOutputStream() 返回适用于在响应中编写二进制数据的 ServletOutputStream,servlet 容器不会编码二进制数据
public java.io.PrintWriter getWriter() 返回可将字符文本发送到客户端的 PrintWriter 对象

4、响应编码问题
**setCharacterEncoding(“UTF-8”)(不建议):**只能设置响应正文的编码,不要通知浏览器以什么样的编码方式去解析。
**setContentType(“text/html;charset=UTF-8”)(建议):**不仅能设置编码,还可以通知浏览器以什么样的方式去解析。

方法 作用
public void setCharacterEncoding(String charset) 设置将发送到客户端的响应的字符编码 (MIME charset),
public void setContentType(String type) 设置将发送到客户端的响应的内容类型,如果该响应尚未提交。

实例:

1、重定向

关键代码(底层实现)

		// 1、设置响应头
		// response.setStatus(302);
		// 2、设置locationֵ的值(跳转的路径)---再次发出请求是从浏览器发出的请求(必须加上工程名)
		// response.setHeader("location", "/day05/redirect.jsp");

		//相当于以上两行
		response.sendRedirect(request.getContextPath()+"/redirect.jsp");

RedirectServlet.java代码:

//response实现重定向
public class RedirectServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		// 1、设置响应头
		// response.setStatus(302);
		// 2、设置locationֵ的值(跳转的路径)---再次发出请求是从浏览器发出的请求(必须加上工程名)
		// response.setHeader("location", "/day05/redirect.jsp");
		// ----------------------------------------------------------------
		// response.sendRedirect("/day05/redirect.jsp");
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		
		if("root".equals(username) && "123456".equals(password)){
			response.getWriter().write("欢迎"+username+"登录成功");
		}else{
			response.sendRedirect(request.getContextPath()+"/redirect.jsp");
			response.getWriter().write("");
		}
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

2、页面定时刷新

关键代码:

response.setHeader("refresh", "5;url=" + request.getContextPath()+"/refresh.html");

5秒钟之后转跳到refresh.html页面:
RefreshServlet.ava:

public class RefreshServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		// response.getWriter().write("页面将在5秒钟之后穿跳到refersh.jsp页面");
		response.setHeader("refresh", "5;url=" + request.getContextPath() + "/");
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

实现数字的倒数5,4,3,2,1JavaScript:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!--实现页面的5秒钟后刷新  -->
<meta http-equiv="refresh" content="5;url=/day05/index.jsp">
<title>Insert title here</title>

<script type="text/javascript">
	//定义一个变量,用于倒数秒数
	var x = 5;
	function fun() {
		var s = document.getElementById("s");
		s.innerHTML = x;
		x--;
		window.setTimeout("fun()", 1000);
	}
</script>
</head>
<body onload="fun();">
	<span id="s"> </span>秒之后跳转到index.jsp页面
</body>
</html>

3、禁用浏览器缓存

  • 安全性比较高的(网银系统)
response.setHeader("Cache-Control", "no-cache");
		response.setHeader("Pragma", "no-cache");
		response.setHeader("Expires", "-1");
//禁用缓存
public class CacheServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setHeader("Cache-Control", "no-cache");
		response.setHeader("Pragma", "no-cache");
		response.setHeader("Expires", "-1");
	}
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

4、生成响应信息(编码问题)

1、使用字节流向页面输出中文,可能会出现中文问题
解决方案:
①告知浏览器使用utf-8编码解析
②字节流使用utf-8编码

2、使用字符流向页面输出中文,一定会出现乱码,因为响应流的缓冲区是ISO-8859-1编码,不是UTF-8编码。
解决方案:
①将响应对象的字符流缓冲区的编码设置为UTF-8
②告知浏览器使用UTF-8编码解析  
Request和Response
Request和Response

public class WriterMsgServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=utf-8");
		// response.setCharacterEncoding("utf-8");
		// 1、得到字节输出流对象
		// 其真正的返回正类型是:ServletOutputStream但是ServletOutputStream继承自OutputStream
		// OutputStream outputStream = response.getOutputStream();

		// 2.得到字符输出流
		PrintWriter out = response.getWriter();
		// out.print(97);// write(String.valueOf(i));
		// out.write(97);// 直接输出

		out.println("<form action='index.jsp'  method='post'>");
		out.println("<input type='submit'  value='index.jsp'/>");
		out.print("</form>");
		out.println(" <hr/>");
		out.print("<H1>欢迎登陆</H1>");
		out.flush();
		out.close();
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

总结:

  • Web应用程序接收一次请求,就创建一个Request对象和Response对象。

  • 通过Request对象可以在服务器端获取客户端发送的请求数据内容。

  • 通过Response对象可以生成服务器端向客户端响应的数据内容。

  • Request对象和Response对象并不是Web应用程序所创建的,而是由Tomcat服务器创建(JavaEE并没有Request与Response的实现类)。

  • JavaEE提供了javax.servlet.http包中提供了HttpServletRequest和HttpServletResponse接口,这两个接口是继承于javax.servlet包中的ServletRequest和ServletResponse接口。

  • javax.servlet包中的ServletRequest和ServletResponse接口是与协议无关的,而javax.servlet.http包中的HttpServletRequest和HttpServletResponse接口是与Http协议有关的。

;