1. request对象和response对象的原理
- request和response对象是由服务器创建的。我们来使用它们
- request对象是来获取请求消息,response对象是来设置响应消息
2. request对象继承体系结构
ServletRequest -- 接口
| 继承
HttpServletRequest -- 接口
| 实现
org.apache.catalina.connector.RequestFacade 类(tomcat)
最终的request对象的类型是RequestFacade
3. request功能:
根据request提供的对应的api就可以获取整个http请求协议里面的内容。
3.1 获取请求消息数据
3.1.1 获取请求行数据
请求行数据 : GET /day14/myServlet?name=zhangsan HTTP/1.1
方法:
-
获取请求方式 :GET
String getMethod()System.out.println(request.getMethod()); //GET
-
(*)获取虚拟目录:/day14
String getContextPath()System.out.println(request.getContextPath()); // /day14
-
获取Servlet路径: /myServlet
String getServletPath()System.out.println(request.getServletPath()); // /myServlet
-
获取get方式请求参数:name=zhangsan
String getQueryString()System.out.println(request.getQueryString()); //name=zhangsan
-
获取请求URI:/day14/myServlet -->虚拟目录+资源名称(servlet)
String getRequestURI(): /day14/myServlet
StringBuffer getRequestURL() :http://localhost/day14/myServletURL: 统一资源定位符
URI:统一资源标识符System.out.println(request.getRequestURI()); // http://localhost/day14/myServlet System.out.println(request.getRequestURL()); // /day14/myServlet
-
获取协议及版本:HTTP/1.1
String getProtocol()System.out.println(request.getProtocol()); // HTTP/1.1
-
获取客户机的IP地址:
String getRemoteAddr()
System.out.println(request.getRemoteAddr()); //0:0:0:0:0:0:0:1
System.out.println(request.getServerName()); //这个是主机名字:localhost
3.1.2 获取请求头数据
方法:
-
String getHeader(String name):通过请求头的名称获取请求头的值
System.out.println(request.getHeader("User-Agent")); // 获取客户端的信息包括浏览器和操作系统的版本 //Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
-
Enumeration
<String>
getHeaderNames():获取所有的请求头名称
//Enumeration 理解成是集合 带迭器Enumeration<String> headerNames = request.getHeaderNames(); while(headerNames.hasMoreElements()){//判断是否还有元素 next() String head = headerNames.nextElement();//把元素返回 String value = request.getHeader(head); System.out.println(head+":"+value); }
3.1.3 获取请求体数据:
请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
步骤:
-
获取流对象
BufferedReader getReader():获取字符输入流,只能操作字符数据BufferedReader reader = request.getReader(); String s = reader.readLine(); System.out.println(s);
ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
ServletInputStream inputStream = request.getInputStream(); int data; while((data=inputStream.read())!=-1){ System.out.print((char)data); }
-
再从流对象中拿数据
3.2 其他功能:
3.2.1 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
-
String getParameter(String name):根据参数名称获取参数值 username=zs&password=123
String username = request.getParameter("username"); // zs String password = request.getParameter("password"); // 123 System.out.println(username+":"+password);
-
String[] getParameterValues(String name):根据参数名称获取参数值的数组hobby=xx&hobby=game
String[] hobbies = request.getParameterValues("hobby"); System.out.println(Arrays.toString(hobbies)); // [xx,game]
-
Enumeration
<String>
getParameterNames():获取所有请求的参数名称Enumeration<String> parameterNames = request.getParameterNames(); while(parameterNames.hasMoreElements()){ String name = parameterNames.nextElement(); System.out.println(name); String[] parameterValues = request.getParameterValues(name); // 不一定只有一个参数值 System.out.println(name+":"+Arrays.toString(parameterValues)); }
-
Map<String,String[]> getParameterMap():获取所有参数的map集合
把所有的参数及参数值封装到map中去了key:参数名称
values:数组Map<String, String[]> map = request.getParameterMap(); Set<String> names = map.keySet(); Iterator<String> iterator = names.iterator(); while(iterator.hasNext()){ String name = iterator.next(); String[] values = map.get(name); System.out.println(name+":"+Arrays.toString(values)); }
3.2.2 中文参数乱码问题:
-
get方式:tomcat 8 已经将get方式乱码问题解决了
-
post方式:会乱码
- 解决:在获取参数前,设置request的编码request.setCharacterEncoding(“utf-8”);
只有中文由乱码,英文不会乱码
是post请求,请求的数据会按照iso-8859-1编码request.setCharacterEncoding("utf-8");//设置请求体的编码 String username = request.getParameter("username"); System.out.println(username);
3.3 request请求转发:一种在服务器内部的资源跳转方式
步骤:
- 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
//请求转发
RequestDispatcher dispatcher = request.getRequestDispatcher("myServlet7");//调度器
//进行调度
dispatcher.forward(request,response);
特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中。
- 转发是一次请求
3.4 共享数据:
- 域(范围)对象:一个有作用范围的对象,可以在范围内共享数据
servlet中有四个域()对象(pageContext,request,session,ServletContext) - request域:代表一次请求的范围(生命周期就是在一次请求响应中),一般用于请求转发的多个资源中共享数据
- ServletContext : 应用(项目)上下文的意思, ServletContext的作用域在整个项目中都有效。ServletContext的生命周期与tomcat同存。
一个项目有一个ServletContext,当项目在tomcat中运行起来的时候,这个对象就被tomcat创建,
方法:(所有的域对象都有这三个方法)
-
void setAttribute(String name,Object obj):存储数据
request.setAttribute("name","袁林");
-
Object getAttitude(String name):通过键获取值
String name = (String) request.getAttribute("name");
-
void removeAttribute(String name):通过键移除键值对
request.removeAttribute("name"); name = (String) request.getAttribute("name"); // null
request对象获取ServletContext
ServletContext getServletContext()
//获取servletContext对象
ServletContext ctx = request.getServletContext();
//往ctx域存东西
ctx.setAttribute("text","段小雷");
4. Response对象
4.1 功能:设置响应消息
-
设置响应行
设置状态码:setStatus(int sc) -
设置响应头:setHeader(String name, String value)
-
设置响应体(用流的形式设置。流从哪里来,从Response对象获取响应流):
- 获取输出流
* 字符输出流:PrintWriter getWriter()
* 字节输出流:ServletOutputStream getOutputStream() - 使用输出流,将数据输出到客户端浏览器
- 获取输出流
4.2 完成重定向
重定向:资源跳转的方式
代码实现:
//1. 设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location","/WEB02/responseDemo2");
//简单的重定向方法
response.sendRedirect("/WEB02/responseDemo2");
重定向的特点:redirect(重定向)
- 地址栏发生变化
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求。不能使用request对象来共享数据
对比:
转发的特点:forward(转发)
- 转发地址栏路径不变
- 转发只能访问当前服务器下的资源
- 转发是一次请求,可以使用request对象来共享数据
4.3 服务器输出字符、字节数据到浏览器
步骤:
-
字符输出流 PrintWriter getWriter()
response.setHeader("content-type","text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.write("你好!同学们");
-
字节输出流:ServletOutputStream getOutputStream()
String data = "hello"; byte[] bytes = data.getBytes(); ServletOutputStream os = response.getOutputStream();//OutputStream os.write(bytes)
乱码问题
PrintWriter pw = response.getWriter();获取的流的默认编码是ISO-8859-1
方法:
- 设置该流的默认编码
得到响应流之前设置响应流的编码response.setCharacterEncoding("utf-8");//响应流的编码是utf-8
- 告诉浏览器响应体使用的编码
首先是把响应体设置为utf-8编码,其次要求浏览器用utf-8进行解码,浏览器默认编码的是gbkresponse.setContentType("text/html;charset=utf-8"); //会设置响应头content-type //采用setHeade设置响应头content-type ,两种方法相同 response.setHeader("content-type","text/html;charset=utf-8");