文章目录
1. response
response对象的功能分为以下四种:
- 设置响应头信息;
- 发送状态码;
- 设置响应正文;
- 重定向;
1.1 设置响应头信息
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; URL=http://www.itcast.cn")
// 5秒后自动跳转到传智主页
1.2 发送状态码及其他方法
response.setContentType("text/html;charset=utf-8"):等同与调用response.setHeader(“content-type”, “text/html;charset=utf-8”);
response.setCharacterEncoding(“utf-8”):设置字符响应流的字符编码为utf-8;
response.setStatus(200):设置状态码;
response.sendError(404, “您要查找的资源不存在”):当发送错误状态码时,Tomcat会跳转到固定的错误页面去,但可以显示错误信息。
1.3 设置响应正文
response是响应对象,向客户端输出响应正文(响应体)可以使用response的响应流,repsonse一共提供了两个响应流对象:
PrintWriter out = response.getWriter():获取字符流对象;
ServletOutputStream out = response.getOutputStream():获取字节流对象;
response.getWriter()是PrintWriter类型,所以它有缓冲区,缓冲区的默认大小为8KB。
如果希望响应数据马上发送给客户端,需要调用response.flushBuffer()
方法来手动刷新缓冲区;
1.4 重定向
- 重定向是两次请求;
- 重定向的URL可以是其他应用,不局限于当前应用;
- 重定向的响应头为302,并且必须要有Location响应头;
- 重定向就不要再使用response.getWriter()或response.getOutputStream()输出数据,不然可能会出现异常;
2. request
request的功能:
- 封装了请求头数据;
- 封装了请求正文数据,如果是GET请求,那么就没有正文;
- request是一个域对象,可以把它当成Map来添加获取数据;
- request提供了请求转发和请求包含功能。
2.1 请求头
String getHeader(String name):获取指定名称的请求头;
Enumeration getHeaderNames():获取所有请求头名称;
int getIntHeader(String name):获取值为int类型的请求头。
2.2 请求参数
String getParameter(String name):通过指定名称获取参数值;
String[] getParameterValues(String name):当多个参数名称相同时,可以使用方法来获取;
Enumeration getParameterNames():获取所有参数的名字;
Map getParameterMap():获取所有参数封装到Map中,其中key为参数名,value为参数。
2.3 域对象
request是域对象!一个请求只会创建一个request对象。
Servlet中三大域对象:request、session、application。
void setAttribute(String name, Object value)
Object getAttribute(String name)
void removeAttribute(String name)
Enumeration getAttributeNames()
2.4 请求转发和请求包含
(1)一个请求跨多个Servlet,需要使用转发和包含。
RequestDispatcher rd = request.getRequestDispatcher("/MyServlet"); 使用request获取RequestDispatcher对象,方法的参数是被转发或包含的Servlet的Servlet路径
请求转发:rd.forward(request,response);
请求包含:rd.include(request,response);
- 请求转发:由下一个Servlet完成响应体!当前Servlet可以设置响应头!(留头不留体)
- 请求包含:由两个Servlet共同完成响应体!(都留)
- 无论是请求转发还是请求包含,都在一个请求范围内!使用同一个request和response!
(2)请求转发与请求包含比较
- 转发留头不留体,包含都可以留;
- 请求包含大多是应用在JSP页面中,完成多页面的合并;
- 请求转发大多是应用在Servlet中,转发目标大多是JSP页面;
(3)请求转发与重定向比较
- 请求转发是一个请求,而
重定向是两个请求
; - 请求转发后浏览器地址栏不会有变化,而重定向会有变化,因为重定向是两个请求;
- 请求转发的目标只能是本应用中的资源,重定向的目标可以是其他应用;
- 请求转发对AServlet和BServlet的请求方法是相同的,即要么都是GET,要么都是POST,因为请求转发是一个请求;
- 重定向的第二个请求一定是GET;
- 请求转发是服务器端行为,只需给出转发的Servlet路径,而重定向需要给出requestURI,即包含项目名!
- 请求转发和重定向效率是转发高!因为是一个请求!
- 需要在下一个Servlet中获取request域中的数据,必须要使用转发!
3.编码
3.1 请求编码
-
直接在地址栏给出请求
不同浏览器使用不同的编码,所以这是不确定的!IE和FireFox:使用GB2312;而Chrome:使用UTF-8; -
在页面发出请求
页面是服务器发送到客户端浏览器的,所以这个页面本身的编码由服务器决定。
<head>
<title>index.html</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
- get请求解读编码
request.getParameter()获取的数据是被服务器误认为ISO-8859-1编码的,所以需要使用ISO-8859-1解码再编码成需要的格式。
String name = request.getParameter(“name”);
name = new String(name.getBytes(“iso-8859-1”), “utf-8”);
- post请求解读编码
(1)先指定编码:request.setCharacterEncoding();再读取数据:reuqest.getParameter()
(1)但如果没有指定编码,那么默认还是使用ISO-8859-1来解读。
request.setCharacterEncoding(“utf-8”);
String name = request.getParameter(“name”);
3.2 响应编码
服务器默认的相应编码是ISO-8859-1,使用response.getWriter()发送数据之前,一定要设置response的编码:
response.setCharacterEncoding(“utf-8”);
同时需要通知浏览器使用的解码方式:
response.setContentType(“text/html;charset=utf-8”);
在静态页面中,使用<meta>
来设置content-type响应头,例如:
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
3.3 URL编码
特殊字符需要先转换成URL编码格式,再发送给服务器。
表单自动使用URL编码,只有get请求需要手动设置编码:
这里使用JS修改:
<script type="text/javascript">
function _go() {
location = "/day05_2/AServlet?name=" + encodeURIComponent("传智+播客");
}
</script>
<a href="javascript:_go();">链接</a>
4.路径问题
4.1. 客户端路径和服务器端路径
- 客户端路径需要给出应用名称,例如:/day05_1/AServlet
- 服务器端路径无需给出应用名称,例如:/AServlet
4.2. 客户端路径
1). 页面中都是客户端路径:
<a>
的href:如果不以“/”开头,那么相对当前.html页面所在路径<form>
的action<img>
的src
2). 重定向也是客户端路径:
以“/”开头:相对当前主机,例如:http://localhost:8080/
,所以需要自己手动添加项目名
response.sendRedirect("/day05_1/BServlet");
相当于:http://localhost:8080/day05_1/BServlet
4.3. 服务器端路径
(1)<url-pattern>
:也叫Servlet路径
- 要么以
“*”
开关,要么为“/”
开头
(2)请求转发和请求包含
- 以“/”开头:相对当前项目路径,例如:http://localhost:8080/项目名/
request.getRequestdispacher("/BServlet")
==>文件地址 http://localhost:8080/项目名/BServlet.java
- 不以“/”开头:相对当前Servlet路径。
- request.getRequestdispacher("/BServlet");,
假如当前Servlet是:http://localhost:8080/项目名/servlet/
AServlet,
就是http://localhost:8080/项目名/servlet/
BServlet
(3)ServletContext获取资源等
相对当前项目目录,即当然index.jsp所在目录(http://localhost:8080/项目名)
4.4 获取类路径资源
可以通过Class类的对象来获取类路径下的资源,对应JavaWeb应用的类路径就是classes目录下的资源。
类路径对一个JavaWeb项目而言,就是/WEB-INF/classes和/WEB-INF/lib/每个jar包!
常见方式:
-
Class类的getResourceAsStream(String path):
路径以“/”开头,相对classes路径;
路径不以“/”开头,相对当前.class文件所在路径,例如在cn.itcast.servlet.MyServlet中执行,那么相对/classes/cn/itcast/servlet/路径; -
ClassLoader类的getResourceAsStream(String path):
相对classes路径;
例如:
InputStream in = this.getClass().getResourceAsStream("/xxx.txt"); // 在classes文件夹内
System.out.println(IOUtils.toString(in));
InputStream in = this.getClass().getClassLoader().getResourceAsStream("xxx.txt");// 在classes文件夹
System.out.println(IOUtils.toString(in));