[基于达内教育的学习,总结提炼]
概念:
request对象封装了用户一次请求的全部信息
继承关系:
ServletRequest、ServletResponse: 当浏览器发出请求时, Web容器创建一个ServletRequest对象封装请求信息, 一个ServletResponse对象封装响应信息. 两个对象作为Servlet的service()方法中的参数.
HttpServletRequest、HttpServletResponse: 丰富了SerlvetRequest、ServletResponse, 提供了http协议相关的内容.
Request作用:
http://localhost/day10/servlet/RequestDemo1 ------> 访问的地址
1. 获取客户端相关信息
getRequestURL方法 -- 返回客户端发出请求完整URL
String url=request.getRequestURL().toString();
System.out.println("url="+url); // url=http://localhost/day10/servlet/RequestDemo1
getRequestURI方法 -- 返回请求行中的资源名部分
String uri=request.getRequestURI();
System.out.println("uri="+uri); // uri=/day10/servlet/RequestDemo1
getQueryString方法 -- 返回请求行中的参数部分
String queryStr=request.getQueryString();
System.out.println("querStr="+queryStr); // querStr=null, 因为没有输入请求行中的参数
getRemoteAddr方法 -- 返回发出请求的客户机的IP地址
String ip=request.getRemoteAddr();
System.out.println("ip="+ip); // ip=127.0.0.1
getMethod -- 得到客户机请求方式
String method=request.getMethod();
System.out.println("method="+method); // method=GET
getContextPath -- 获得当前Web应用的虚拟目录名称
String contextPath=request.getContextPath();
System.out.println("contextPath="+contextPath); // contextPath=/day10
2. 获取请求头信息
http://localhost/day10/servlet/RequestDemo2 ------> 访问的地址
getHeader(name)方法 --- String
// 获取host头的值
String host=req.getHeader("host");
System.out.println("host="+host); // host=localhost
getHeaders(String name)方法 --- Enumeration<String> --- 返回指定name的请求头的所有名称
getHeaderNames方法 --- Enumeration<String> --- 返回所有请求头的名称
// 获取所有请求头的名称
Enumeration<String> names=req.getHeaderNames();
while(names.hasMoreElements()){
String name=names.nextElement();
String value=req.getHeader(name);
System.out.println("name="+name+" ,value="+value);
}//name=host ,value=localhost
//name=connection ,value=keep-alive
//name=sec-ch-ua ,value=" Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"
//name=sec-ch-ua-mobile ,value=?0
//name=sec-ch-ua-platform ,value="Windows"
//name=upgrade-insecure-requests ,value=1
//name=user-agent ,value=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36
//name=accept ,value=text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
//name=sec-fetch-site ,value=none
//name=sec-fetch-mode ,value=navigate
//name=sec-fetch-user ,value=?1
//name=sec-fetch-dest ,value=document
//name=accept-encoding ,value=gzip, deflate, br
//name=accept-language ,value=zh-CN,zh;q=0.9
getIntHeader(name)方法 --- int --- 以int 格式根据名称返回客户请求中对应的头信息
getDateHeader(name)方法 --- long(日期对应毫秒) --- 返回指定的头名称的构建 Date 对象的 long 值.
3. 获取请求参数
getParameter(String name) --- String 通过name获得值
http://localhost/day10/servlet/RequestDemo3?username=zhangsan ----> 访问地址
String username=request.getParameter("username");
System.out.println("username="+username); // username=zhangsan
注意: 如果username=张三, 最终输出的是乱码. 其原因是编码和解码所使用的码不一致造成的.
分析: 其一) 浏览器用什么码打开当前页面, 就会用什么码来发送请求参数. 所以我们可以通过浏览器所使用的码从而使浏览器发送数据的码保持一致.
其二) tomcat服务器默认使用的是ISO8859-1码, 然而这个码没有汉字, 所以使用汉字时会出现乱码的情况.
其三) request.setCharacterEncoding("uft-8"); 此方法用来指定服务器使用什么码处理数据, 但此代码必须在获取任何参数的代码之前.
其四) request.setCharacterEncoding("utf-8"); 此方法时用来通知服务器使用什么码来处理请求实体内容中的数据, POST提交的参数时在请求实体内容中,所以这个方法可以解决POST提交的乱码问题
其五) 根据乱码产生的原理,手动的编码解决乱码问题
username=new String(username.getBytes("iso8859-1"),"utf-8");
getParameterValues(String name) --- String[ ] 通过name获得多值 checkbox
http://localhost/day10/servlet/RequestDemo3?like=足球&like=篮球 ----> 访问地址
String[] likes=req.getParameterValues("like");
if(likes!=null){
for(String like:likes){
String li=new String(like.getBytes("iso8859-1"),"utf-8");
System.out.println("like="+li);
} // like=足球
} // like=篮球
getParameterMap() --- Map<String,String[ ]> key :name value: 多值
http://localhost/day10/servlet/RequestDemo3?like=篮球&username=zhangsan ----> 访问地址
Map<String, String[]> map=req.getParameterMap();
for(Entry<String, String[]> entry:map.entrySet()){
System.out.print("name="+entry.getKey());
String[] values=entry.getValue();
if(values!=null){
for(String value:values){
System.out.print(" value="+value);
}
System.out.println();
} // name=like value=篮球
} // name=username value=zhangsan
getParameterNames() --- Enumeration<String> 获得所有参数的name
http://localhost/day10/servlet/RequestDemo3?like=篮球&name=zhangsan ----> 访问地址
Enumeration<String> likes=req.getParameterNames();
while(likes.hasMoreElements()){
String value = (String)likes.nextElement();//调用nextElement方法获得元素
System.out.println(value); // like
} // name
4. 实现请求转发
请求重定向: 302+location
请求转发: 实现资源的跳转,是服务器内部的跳转, 一次请求, 一次响应, 地址栏并不发生变化
RequestDispatcher rd=request.getRequestDispatcher("/servlet/RequestDemo5").forward(request, response); // 调度器, 实现请求的转发,将请求转发给RequestDemo5
注意: 1) 在请求转发之前,如果response缓冲区写入了数据但是还没有打给浏览器,在请求转发时这些数据会被清空.
2) 在请求转发之前, 如果response缓冲区写入了数据( 即调用了 response.flushBuffer() )并且打给了浏览器, 则请求失败, 抛出异常.
3) 请求转发就像方法的调用,在转发代码之后的代码将会在转发结束后继执行
4) 如果在一个Servlet中调用了多次forward(),相当于进行了多重转发,会失败
5) 可以将一个请求在多个组件之间进行转发,但是最终只能由1个组件进行应答
5. 实现请求包含
请求包含: 允许一个Servlet将其他资源(Servlet,JSP,html)的应答内容包含进来
如果浏览器请求ServletA, 在A的内部可以通过request.getRequestDispatcher("B的虚拟路径").include(request, response);将ServletB包含进来, 这时将由A和B共同处理该请求, B处理的结果将会并入A处理的结果, 一起响应给浏览器
RequestDemo6:
resp.getWriter().write("Demo6 ");
RequestDispatcher rd=req.getRequestDispatcher("/servlet/RequestDemo7");
rd.include(req, resp);
resp.getWriter().write("from Demo7 to Demo6");
RequestDemo7:
resp.getWriter().write("Demo7 ");
最终应答内容为: Demo6 Demo7 from Demo7 to Demo6 ( RequestDemo6和RequestDemo7的结果一起响应给浏览器)
6. 作为域对象来使用
域对象: 一个对象具有可以被看见的范围, 利用这个对象身上的map就可以实现资源的共享, 像这样的对象就称之为域对象.
setAttribute(String name, Object valObj); --- 在域空间中设置数据名称和数据体
getAttribute(String name); --- 在域空间中获取指定名称的数据
removeAttribute(String name); --- 在域空间中移除指定名称的数据
getAttributeNames(); --- 返回所有属性的名称集合
生命周期: 一次请求开始,到一次请求结束
作用范围: 在整个请求链上都可以看见
主要作用: 在请求转发时将数据带到转发的地址