萤火小屋

优律的知识库

  • 首页
  • 归档
  • 分类
  • 标签
  • 留言
  • 关于

  • 搜索
消息队列 RabbitMQ Redis 双指针 力扣 动态代理 Git YAML SpringBoot SpringMVC 回溯算法 分治算法 归并排序 快排 手撕 事务 MySQL索引 MySQL 小技巧 Spring Framework Spring 动态规划 Linux Android 贪心算法 操作系统 进程调度模拟 IPv6 数据库 计算机组成原理 计算机基础 栈 Java 静态路由 路由器 交换机 数字通信 网络工程 计算机网络 Web http 大学学习技巧 程序设计 算法

JavaWeb-请求和响应

发表于 2019-08-11 | 分类于 Java企业级开发学习日记 | 0 | 阅读次数 724
Response基础
HttpServletResponse对象

  • 是一个给客户端做出相应的对象。客户端每请求一次,就会创建一个HttpServletResponse对象(响应)。

  • HttpServletResponse接口信息

  1. 接口名:HttpServletResponse(Response是简写)
  2. 包名:javax.servlet.http
  3. 父接口:ServletResponse
  4. 已知实现类:HttpServletResponseWrapper

  • 功能(作用)
  1. 设置响应头信息
  2. 设置响应状态码
  3. 实现重定向
  4. 设置响应正文

  • 功能详解
  1. 设置响应头信息

    方法:setHeader(String name, String value); name:value,这个值是固定的。 发送个客户端浏览器,浏览器能够识别头信息。

  2. 设置响应状态码

    方法:setStatus();
    2*  OK:200
    3*  重定向相关:304 重定向到本地的缓存 302 重定向到其他的资源
    4*  客户端问题:404 找不到资源 405 没有相应的处理方法
    5*  服务器端错误:500 服务器端异常
    详情见《关于Http状态码》

  3. 实现重定向

    发送一个302的状态码,并且发送一个浏览器重新请求的地址

    重定向的方式:
    1. 使用方法:
    response.setStatus(302);
    response.setHeader("Location","URL");
    2. 重定向的便捷方法:
    response.sendRedirect("URL");

    重定向的特点:
    1. 两次请求,两次响应。
    2. 地址栏会发生变化。
    3. 重定向能够访问到除了当前web以外的其他的资源。

  4. 设置响应正文

    响应的内容:

    1. 可以是普通的字符。
    2. 设置的内容可以是HTML标签,浏览器能够直接解析。

    • 使用字节流:response.getOutputStream();
    • 使用字符流:response.getWriter();
    • 注意:字节流和字符流在使用的时候只能选择其中一个。 否则将抛出异常:IllegalStateException

  • response乱码问题

    造成乱码的原因,在Servlet当中,服务器使用ISO-8859-1对汉字进行了编码。 (不支持中文)
    将编号后的结果发送给了浏览器,浏览器默认情况下,按照gbk进行解码。 所以出现了乱码。
    解决:告知服务器使用UTF-8进行编码:response.setCharacterEcoding("utf-8");
    发送给浏览器一个响应头,告知浏览器使用utf-8解码:response.setHeader("Content-Type","text/html;charset=utf-8"); response.setContentType("text/html;charset=utf-8");



response响应正文

  • response是响应对象,向客户端输出响应正文(响应体)可以使用response的响应流,repsonse一共提供了两个响应流对象:

    1. PrintWriter out = response.getWriter():获取字符流;
    2. ServletOutputStream out = response.getOutputStream():获取字节流

    当然,如果响应正文内容为字符,那么使用response.getWriter(),如果响应内容是字节,例如下载时,那么可以使用response.getOutputStream() 注意,在一个请求中,不能同时使用这两个流!也就是说,要么你使用repsonse.getWriter(),要么使用response.getOutputStream(),但不能同时使用这两个流。不然会抛出IllegalStateException异常。


  • 字符响应流

    1. 字符编码
      在使用response.getWriter()时需要注意默认字符编码为ISO-8859-1,如果希望设置字符流的字符编码为utf-8,可以使用response.setCharaceterEncoding(“utf-8”)来设置。这样可以保证输出给客户端的字符都是使用UTF-8编码的。 但客户端浏览器并不知道响应数据是什么编码的。如果希望通知客户端使用UTF-8来解读响应数据,那么还是使用response.setContentType("text/html;charset=utf-8")方法比较好,因为这个方法不只会调用response.setCharaceterEncoding(“utf-8”),还会设置content-type响应头,客户端浏览器会使用content-type头来解读响应数据。

    2. 缓冲区
      response.getWriter()是PrintWriter类型,所以它有缓冲区,缓冲区的默认大小为8KB。也就是说,在响应数据没有输出8KB之前,数据都是存放在缓冲区中,而不会立刻发送到客户端。当Servlet执行结束后,服务器才会去刷新流,使缓冲区中的数据发送到客户端。 如果希望响应数据马上发送给客户端:

      • 向流中写入大于8KB的数据
      • 调用response.flushBuffer()方法来手动刷新缓冲区

设置响应头信息

可以使用response对象的setHeader()方法来设置响应头。使用该方法设置的响应头最终会发送给客户端浏览器!

  • response.setHeader(“content-type”, “text/html;charset=utf-8”);:设置content-type响应头,该头的作用是告诉浏览器响应内容为html类型,编码为utf-8。而且同时会设置response的字符流编码为utf-8,即response.setCharaceterEncoding(“utf-8”);
  • response.setHeader("Refresh","5;http://blog.fireflyhut.cc");:5秒后自动跳转到萤虫屋主页。



设置状态码及其他方法

  • response.setStatus(200);:设置状态码
  • response.sendError(404, “您要查找的资源不存在”);:当发送错误状态码时,服务器会跳转到固定的错误页面去,但可以显示错误信息

重定向
什么是重定向

当你访问http://www.sun.com/时,你会发现浏览器地址栏中的URL会变成http://www.oracle.com/sun/(不信你试试),这就是重定向了。重定向是服务器通知浏览器去访问另一个地址,即再发出另一个请求。

完成重定向

响应码为200表示响应成功,而响应码为302表示重定向。所以完成重定向的第一步就是设置响应码为302。
因为重定向是通知浏览器再第二个请求,所以浏览器需要知道第二个请求的URL,所以完成重定向的第二步是设置Location头,指定第二个请求的URL地址。

public class TestServlet extends HttpServlet {
	public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		response.setStatus(302);
		response.setHeader("Location", "http://blog.fireflyhut.cc");
	}
}

上面代码的作用是:当访问TestServlet后,会通知浏览器重定向到萤虫屋主页。客户端浏览器解析到响应码为302后,就知道服务器让它重定向,所以它会马上获取响应头Location,然发出第二个请求。

便捷的重定向方式

public class TestServlet extends HttpServlet {
	public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		response.sendRedirect("http://blog.fireflyhut.cc");
	}
}

response.sendRedirect()方法会设置响应头为302,以设置Location响应头。 如果要重定向的URL是在同一个服务器内,那么可以使用相对路径,例如:

public class TestServlet extends HttpServlet {
	public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		response.sendRedirect("/gh/AnotherServlet");
	}
}

重定向的URL地址为:http://localhost:8080/gh/AnotherServlet

重定向总结

  1. 重定向是两次请求
  2. 重定向的URL可以是其他应用,不局限于当前应用
  3. 重定向的响应头为302,并且必须要有Location响应头
  4. 重定向就不要再使用response.getWriter()或response.getOutputStream()输出数据,不然可能会出现异常

request基础
request概述

request是Servlet.service()方法的一个参数,类型为javax.servlet.http.HttpServletRequest。在客户端发出每个请求时,服务器都会创建一个request对象,并把请求数据封装到request中,然后在调用Servlet.service()方法时传递给service()方法,这说明在service()方法中可以通过request对象来获取请求数据。

RequestStructure-img

HttpServletRequest接口信息

包:javax.servlet.http
父接口:ServletRequest
已知实现类:HttpServletRequestWrapper

request对象的功能

封装了请求头数据
封装了请求正文数据,如果是GET请求,那么就没有正文
request是一个域对象,可以把它当成Map来添加获取数据
request提供了请求转发和请求包含功能

获取请求头数据

request与请求头相关的方法有:

  • String getHeader(String name):获取指定名称的请求头
  • Enumeration getHeaderNames():获取所有请求头名称
  • int getIntHeader(String name):获取值为int类型的请求头
request获取请求相关的其它方法

返回值类型方法名参数类型参数值描述
intgetContentLengthvoid获取请求体的字节数,GET请求没有请求体,没有请求体返回-1
StringgetContentTypevoid获取请求类型,如果请求是GET,那么这个方法返回null;如果是POST请求,那么默认为application/x-www-form-urlencoded,表示请求体内容使用了URL编码
StringgetMethodvoid返回请求方法,例如:GET
java.util.LocalegetLocalevoid返回当前客户端浏览器的Locale。java.util.Locale表示国家和言语,这个东西在国际化中很有用(此方法是父接口方法)
StringgetCharacterEncodingvoid获取请求编码,如果没有setCharacterEncoding(),那么返回null,表示使用ISO-8859-1编码
voidsetCharacterEncodingStringcode设置请求编码,只对请求体有效。注意,对于GET而言,没有请求体。所以此方法只能对POST请求中的参数有效。
StringgetContextPathvoid返回上下文路径,获取的是项目名称。例如:/hello
StringgetQueryStringvoid返回请求URL中的参数,例如:name=zhangSan
StringgetRequestURIvoid返回请求URI路径,例如:/hello/oneServlet
java.lang.StringBuffergetRequestURLvoid返回请求URL路径,例如:http://localhost/hello/oneServlet,即返回除了参数以外的路径信息
StringgetServletPathvoid返回Servlet路径,例如:/oneServlet
StringgetRemoteAddrvoid返回当前客户端的IP地址
StringgetRemoteHostvoid返回当前客户端的主机名,但这个方法的实现还是获取IP地址
StringgetSchemevoid返回请求协议,例如:http
StringgetServerNamevoid返回主机名,例如:localhost
intgetServerPortvoid返回服务器端口号,例如:8080

RequestURLStructureMethod-img



request获取从客户端传递过来的请求参数

最为常见的客户端传递参数方式有两种:

  1. 浏览器地址栏直接输入:一定是GET请求
  2. 超链接:一定是GET请求
  3. 表单:可以是GET,也可以是POST,这取决与<form>的method属性值

GET请求和POST请求的区别:
GET请求:

  1. 请求参数会在浏览器的地址栏中显示,所以不安全
  2. 请求参数长度限制长度在1K之内
  3. GET请求没有请求体,无法通过request.setCharacterEncoding()来设置参数的编码

POST请求:

  1. 请求参数不会显示浏览器的地址栏,相对安全
  2. 请求参数长度没有限制


  • 获得GET请求参数-浏览器地址栏传参
    编写代码:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestHttpServletRequest extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req,resp);
	}
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		
		String name = request.getParameter("name");
		String pass = request.getParameter("pass");	
		System.out.println("get请求的请求参数"+name+":"+pass);
	}
}

启动服务器后访问http://localhost:8080/Test?name=lalala&pass=123456在浏览器中可以查看到想服务端传递的参数 GetTransferParameters-img

并在控制台可以看到打印信息

GetTransferParametersConsole-img



  • 获得GET请求参数-form表单

    编写html表单

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>Test</title>
	</head>
	<body>
		<form action="/Tech/Test" method="get">
		
			user:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="text" name="name" /><br/>
			password:&nbsp;<input type="password" name="pass"><br/>
			<input type="submit" value="提交">
		
		</form>
	</body>
</html>

访问http://localhost:8080/Tech/FormTest.html并输入用户和密码

GetFormTransferParametersTypingValueInHTMLPage-img

提交后查看浏览器地址栏和控制台

GetFormTransferParametersTypingValueInHTMLPage-res-img

GetFormTransferParametersTypingValueInHTMLPage-res2-img

可以看到用form表单提交并且提交后执行访问TestServlet也可以将参数通过get方法传到服务端

  • 获得post请求参数-form表单

    更改html代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>Test</title>
	</head>
	<body>
		<form action="/Tech/Test" method="post"><!--这里把method的值改成post-->
		
			user:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="text" name="name" /><br/>
			password:&nbsp;<input type="password" name="pass"><br/>
			<input type="submit" value="提交">
		
		</form>
	</body>
</html>

PostFormTransferParametersTypingValueInHTMLPage-res-img

PostFormTransferParametersTypingValueInHTMLPage-res2-img

可以看到post提交并不会在浏览器地址栏显示提交内容,且信息依然也可以传到服务端,由于没有更改服务端打印信息所以打印的还是“get请求的请求参数”。另外,超链接传参是get方法,通过url连接一个或者多个参数,这里不再展示

ps:如果获取不到该名称的参数值,会返回服务端会打印null,且不会报错。如果想要获取多个同名参数的值需要用String values[] getParameterValues(String name)方法来返回一个字符串数组(下面我们将介绍)

将获得的参数封装到Map集合中

  • ServletRequest接口中的方法

java.util.Map<java.lang.String,java.lang.String[]> getParameterMap()

  • 测试代码
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class TestHttpServletRequest extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req,resp);	
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {	
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		
		Map<String,String[]> map = request.getParameterMap();
		
		for(String key: map.keySet()) {
			String[] value = map.get(key);
			System.out.println(key+":"+Arrays.toString(value));
		}
	}
}

浏览器地址栏随便输入多个参数,且其中有同名但值不同的参数 getParameterMap-Method-Exp-res-img 服务端控制台可以看到打印信息 getParameterMap-Method-Exp-console-res-img

java.util.Map<java.lang.String,java.lang.String[]> getParameterMap()方法将所有客户端传递的参数全部用Map以键值对的形式接收到了集合中(传参方法可以是get也可以是post,本例为get)

域对象
域方法

  • void setAttribute(String name, Object value):用来存储一个对象,也可以称之为存储一个域属性,例如:servletContext.setAttribute(“xxx”, “XXX”),在request中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。请注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同;
  • Object getAttribute(String name):用来获取request中的数据,当前在获取之前需要先去存储才行,例如:String value = (String)request.getAttribute(“xxx”);,获取名为xxx的域属性;
  • void removeAttribute(String name):用来移除request中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做;
  • Enumeration getAttributeNames():获取所有域属性的名称;



请求转发和请求包含
请求转发

无论是请求转发还是请求包含,都表示由多个Servlet共同来处理一个请求。例如Servlet1来处理请求,然后Servlet1又转发给Servlet2来继续处理这个请求。

  • 请求转发:在AServlet中,把请求转发到BServlet
//AServlet
public class AServlet extends HttpServlet {
	public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		System.out.println("AServlet");
		RequestDispatcher rd = request.getRequestDispatcher("/BServlet");
		rd.forward(request, response);
	}
}
//BServlet
public class BServlet extends HttpServlet {
	public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		System.out.println("BServlet");
	}
}



请求包含

在AServlet中,把请求包含到BServlet:

//AServlet
public class AServlet extends HttpServlet {
	public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		System.out.println("AServlet");
		RequestDispatcher rd = request.getRequestDispatcher("/BServlet");
		rd.include(request, response);
	}
}
//BServlet
public class BServlet extends HttpServlet {
	public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		System.out.println("BServlet");
	}
}



请求转发与重定向的区别

  • 请求转发是一个请求,而重定向是两个请求
  • 请求转发后浏览器地址栏不会有变化,而重定向会有变化,因为重定向是两个请求
  • 请求转发的目标只能是本应用中的资源,重定向的目标可以是其他应用
  • 请求转发对AServlet和BServlet的请求方法是相同的,即要么都是GET,要么都是POST,因为请求转发是一个请求
  • 重定向的第二个请求一定是GET


请求转发和请求包含的区别

  • 请求转发:

方法: response.getRequestDispather("ServletURL").forword(request,response);负责转发的Servlet设置的请求头生效,设置的请求体不生效(留头不留体)。

  • 请求包含:

方法: response.getRequestDispather("ServletURL").include(request,response);负责转发的Servlet和被包含的Servlet共同完成。 (留头又留体)





# http # Web # Java
JavaWeb-Servlet
数学方法实现堆栈
  • 文章目录
  • 站点概览
优律

优律

优律的知识库

83 日志
20 分类
44 标签
E-mail Twitter Instagram
Links
  • CZLisyx - 浮生志
  • Vedfolnir
0%
© 2019 — 2023 萤火小屋——优律的博客网站
网站已勉强运行 
Halo博客系统技术支持