11、Request&Response
程序员文章站
2022-07-12 14:36:02
...
一、简介
- Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象
- request和response对象即然代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向客户机输出数据,只需要找response对象就行了
二、HttpServletResponse
- HttpServletResponse对象代表服务器的响应。而HTTP协议规定一个HTTP响分为状态行、响应头、实体内容三个部分。
- 于是对象中封装了向客户端发送响应状态码、响应头、实体数据的方法。
- HttpServletResponse继承结构:ServletResponse-->HttpServletResponse
三、向浏览器输出一段数据
- 方法一:用getOutputStream() 获得一个ServletOutputStream 字节流输出数据
- --此方法按字节输出数据,如果输出的数据是表示一段字符的字节数据,则一定要指定浏览器以什么码表解码,如果指定错码表就会有乱码问题,浏览器默认用平台码表打开。
- response.setHeader("content-type", "text/html;charset=utf-8");
- 也可以在html中用<meta http-equiv="" content="">来模拟响应头信息
- 方法二:用getWriter()获得一个PrintWriter字符输出流输出数据
- response会默认以ISO8859-1将需要输出到浏览器的字符进行解码,如果输出的字符在IOS8859-1中不存在,就会导致乱码问题。可以使用setCharacterEncoding(String charset)方法设置解码用的字符集为其他字
- response.setContetnType("text/html;charset=utf-8");方法可以同时设定response所使用的字符集编码和浏览器打开所用的字符集编码。
四、response实现文件下载
- 利用response将HTTP的响应头"content-disposition"设置为"attachment;filename=xxx"即可实现文件下载功能
- 如果文件名中包含中文,则文件名要进行URL编码,URLEncoding.encode('啊啊.jpg','utf-8');如果不进行编码则文件名显示错误但是可以下载。
五、refresh控制定时刷新
- 利用Response设置响应头refresh可以实现页面的定时刷新功能。
- refresh头可以被设置为一个整数,实现定是刷新当前页面,也可以在整数后跟分号再在分好后写一个url=指定刷新到的目标URL
- response.setHeader("Refresh", "3;url='/news/index.jsp'");
- 很多网站在提示登录成功后几秒内会跳转到主页,就是由这个功能实现的。
- 使用meta实现<meta http-equiv="refresh" content="3;url=''">
六、控制是否缓存资源
- 利用response设置expires响应头为0或-1浏览器就不会缓存当前资源。(同样功能的头还有Cache-Control: no-cache、Pragma: no-cache)
- 什么都不设置,浏览器点转到或者敲回车默认会去拿缓存,这种缓存没有截至日期,只要刷新或者新开一个浏览器就会拿新的
- 如果设置了缓存时间,那么除了刷新,不管是转到回车还是新开浏览器都会拿缓存
- 如果缓存设置为不缓存的话,就不管怎样都不缓存
- expires也可以取值为一个时间,指定要缓存到的日期。
七、response实现请求重定向
- 利用response设置状态码为302,并设置响应头Location为要重定向到的地址,就可以实现请求重定向操作了
- 为了方便进行请求重定向操作,response提供了response.sendRedirec("....");实现请求重定向。
- 在大部分情况下请求重定向和转发的效果是差不多的,这时候我们推荐使用转发,以减少对服务器的访问。
- 而在某些情况下是需要使用重定向的,目的往往是为了改变浏览器地址栏里的地址(如登录成功后转到主页),和更改刷新操作(如加入商品到购物车后转到购物车页面的操作)
八、response生成响应注意事项
- getOutputStream和getWriter这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。特别注意forward后也不要违反这一规则。
- 利用Response输出数据的时候,并不是直接将数据写给浏览器,而是写到了Response的缓冲区中,等到整个service方法返回后,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端。
- Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎tomcat将调用close方法关闭该输出流对象。
九、HttpServletRequest
- HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。
- 通过Request对象进行的常用操作
- 获取客户机信息、获取请求头信息、获取请求参数、利用请求域传递对象
十、request获取客户机信息
getRequestURL 方法返回客户端发出请求完整URL getRequestURI 方法返回请求行中的资源名部分 getQueryString 方法返回请求行中的参数部分 getRemoteAddr 方法返回发出请求的客户机的IP地址 getMethod 得到客户机请求方式 getContextPath 获得当前web应用虚拟目录名称,可以用来拼路径,如果web应用名被该后,就不用更改代码中的路径 getProtocol 获得协议(HTTP/1.1)
十一、request获取请求头信息
-
获得客户机请求头
getHeader(name)方法 --- String getHeaders(String name)方法 --- Enumeration<String> getHeaderNames方法 --- Enumeration<String>
-
获得具体类型客户机请求头
getIntHeader(name)方法 --- int getDateHeader(name)方法 --- long(日期对应毫秒)
-
通过referer信息防盗链
String host = request.getHeader("referer"); if(host==null || !host.startsWith("http://localhost")){ response.sendRedirect("/Day008/home.html"); }else{ request.getRequestDispatcher("/WEB-INF/fengjie.html").forward(request, response); }
-
request获取请求参数
getParameter(name) --- String 通过name获得值 getParameterValues --- String[ ] 通过name获得多值 checkbox getParameterNames --- Enumeration<String> 获得所有name getParameterMap --- Map<String,String[ ]> key :name value: 多值
- 数据非空校验
- 处理中文乱码
post:setCharacterEncoding //放在getParameter前才有效 get:new String(str.getBytes(“ISO-8859-1”),”utf-8”) 在tomcat的server.xml中可以配置http连接器的URIEncoding可以指定服务器在获取请求参数时默认使用的编码,从而一劳永逸的解决获取请求参数时的乱码问题 也可以指定useBodyEncodingForURI参数,令request.setCharacterEncoding也对GET方式的请求起作用,但是这俩属性都不推荐使用,因为发布环境往往不允许修改此属性。 服务器解析uri是使用iso8859-1的,setCharacterEncoding只能设置其解析实体的编码,对uri不起作用,所以, new String(str.getBytes(“ISO-8859-1”),”utf-8”)这种方式是最好的解决方法
十二、 request利用请求域传递对象
- request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其它web资源处理
setAttribute方法 getAttribute方法 removeAttribute方法 getAttributeNames方法
- 生命周期:在service方法调用之前由服务器创建,传入service方法。整个请求结束,request生命结束。
- request作用域的作用范围:整个请求链
- 作用:在整个请求链*享数据,最常用的:在Servlet中处理好的数据要交给Jsp显示,此时参数就可以放置在Request域中带过去。
十三、request实现请求转发
- request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发,从而共享请求中的数据
- 如果在调用forward方法之前向servlet程序中写入的部分内容已经被真正的传送到了客户端,forward将不能进行,会抛出异常。
- 如果在调用forward之前向response缓冲区中写入了内容,只要写入到其中的内容还没有真的被输出到客户端,forward方法就可以正常执行,但原来写入到缓冲区中的数据将被清空,注意只是实体内容被清空,之前写入的响应头信息仍然存在。
- 根据HTTP协议,一次请求只能有一个响应,所以一旦数据被写出来,再想forward,晚了!
十四、请求重定向和请求转发的区别
- RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;
- 而HttpServletResponse.sendRedirect 方法还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。
- 如果传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于服务器的根目录;
- 如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。
- 调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;
- 调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
- HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求;
- RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。
- RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程
- 而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。
十五、转发和重定向常见应用场景
- 通常情况下都用请求转发,减少服务器压力
- 当需要更新地址栏时用请求重定向,如注册成功后跳转到主页。
- 当需要刷新更新操作时用请求重定向,如购物车付款的操作。
十六、RequestDispatcher进行include操作
- RequestDispatcher.include方法用于将RequestDispatcher对象封装的资源内容作为当前响应内容的一部分包含进来,从而实现可编程的服务器端包含功能
- 被包含的Servlet程序不能改变响应消息的状态码和响应头,如果它里面存在这样的语句,这些语句的执行结果将被忽略
- include在程序执行上效果类似forward,但是使用forward只有一个程序可以生成响应,include可以由多个程序一同生成响应 ----- 常用来页面布局
十七、常用地址写法
- 绝对路径(尽量使用绝对路径)
- 如果路径是给服务器用就不写web应用名,直接写资源路径。如果路径是给浏览器用的,就要从web应用名开始
- 相对路径(当绝对路径不够用时才用)
- ---需要根据当前路径名分析出真实路径名
- ---如果直接写资源替换当前路径的最后一级
- ---../开头,则会替换当前路径当前级别的上一级,可以使用多个../进行替换上一级操作。
十八、URL特殊字符转义规则
- URL编码:由于HTTP协议规定URL路径中只能存在ASCII码中的字符,所以如果URL中存在中文或特殊字符需要进行URL编码
- 编码原理:
- ----将空格转换为加号(+)
- ----对0-9,a-z,A-Z之间的字符保持不变
- ----对于所有其他的字符,用这个字符的当前字符集编码在内存中的十六进制格式表示,并在每个字节前加上一个百分号(%)。如字符“+”用%2B表示,字符“=”用%3D表示,字符“&”用%26表示,每个中文字符在内存中占两个字节,字符“中”用%D6%D0表示,字符“国”用%B9%FA表示,对于空格也可以直接使用其十六进制编码方式,即用%20表示,而不是将它转换成加号(+)
- 说明:
- 如果确信URL串的特殊字符没有引起使用上的岐义或冲突你也可以对这些字符不进行编码,而是直接传递给服务器。
- 例如,http://www.it315.org/dealregister.html?name=中国&password=123
- 如果URL串中的特殊字符可能会产生岐义或冲突,则必须对这些特殊字符进行URL编码。
- 例如,服务器会将不编码的“中+国”当作“中国”处理。还例如,当name参数值为“中&国”时,如果不对其中的“&”编码,URL字符串将有如下形式:http://www.it315.org/dealregister.html?name=中&国&password=123,应编码为:http://www.it315.org/dealregister.html?name=中%26国&password=123
- http://www.it315.org/example/index.html#section2可改写成http://www.it315.org/example%2Findex.html%23section2
-
在java中进行URL编码和解码
URLencoder.encode("xxxx","utf-8"); URLDecoder.decode(str,"utf-8");
下一篇: 9、Servlet开发
推荐阅读
-
iOS 11 使用两种方法替换(Method Swizzling)去掉导航栏返回按钮的文字
-
解读ASP.NET 5 & MVC6系列教程(11):Routing路由
-
Linux虚拟机下安装Oracle 11G教程图文解说
-
CorelDraw11如何安装?CorelDRAW11中文版安装破解详细图文教程
-
QQ旋风云播放停用说明 QQ旋风云播放功能已于2014年11月7日暂停服务
-
IE11无法打开qq空间的两种解决办法
-
淘宝双12和双11哪个便宜 2019淘宝双十二活动力度大吗
-
tar方式安装oracle11g的步骤教程
-
SQL Server误区30日谈 第11天 镜像在检测到故障后瞬间就能故障转移
-
oracle 11g dataguard 使用dgbroker管理主备切换以及快速failover方法讲解