Java 中的 request 和response 理解
request和response(请求和响应) 1.当Web容器收到客户端的发送过来http请求,会针对每一次请求,分别创建一个用于代表此次请求的HttpServletRequest对象(request)对象、和代表响应的HTTPServletResponse对象(response)。 request负责获取客户机提交过来的数据。
response负责向客户机输出数据。
2.HttpServletRequest请求 GET /Servlet/servlet/Servlet_03 HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, */*
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: localhost:8080
Connection: Keep-Alive getRequestURL方法返回客户端发出请求时的完整URL。 getRequestURI方法返回请求行中的资源名部分。 getQueryString 方法返回请求行中的参数部分。 getRemoteAddr方法返回发出请求的客户机的IP地址 getRemoteHost方法返回发出请求的客户机的完整主机名 getRemotePort方法返回客户机所使用的网络端口号 getLocalAddr方法返回WEB服务器的IP地址。 getLocalName方法返回WEB服务器的主机名 在request中可以获取一些请求头,这些请求头的案例有:
1.可以用来防盗链(Referer头) 防盗链:
有些下载系统的下载地址会有一个下载跳转,用户在下载页面上看到的下载地址可能是 http://www.abc.com/down.asp?id=xxxx
有人直接将这个地址复制到其他地方,即可盗链,直接利用下载的地址就可以实现下载,而不是通过我自己的网站去下载,这时我们就需要判断下是否是通过我自己的网站点击下载的。 所以我们需要在 down.asp 这个页面做下简单的来源判断。如果不是来自本站的连接,则直接拒绝访问。 String referer = request.getHeader("referer");//获取请求头 //判断这个头是否为空,或这个头的首地址是否为http://localhost,如果不是则重定向 2.获取表单中的信息:
String value = req.getParameter("name");
在表单提交过来时的中文乱码的问题: *浏览器怎样进行URL编码:
(1)浏览器对FORM表单中输入的中文字符都会进行URL编码后再传送给WEB服务器。
(2)对于页面中的FORM表单中输入的内容,浏览器将按照当前显示页面时所采用的字符集编码来进行URL编码。
getParameter方法的中文问题:
(1)getParameter等方法在读取的参数信息时,需要进行URL解码。
(2)对于HTTP请求消息的请求行中的URL地址后的参数,getParameter等方法进行URL解码时所采用的字符集编码在Servlet规范中没有明确规定Tomcat中的ServletReq uest对象的getParameter等方法默认采用ISO8859-1字符集编码进行URL解码,因此无法返回正确的中文参数信息 。
(3)对于POST方式下的“application/x-www-form-urlencoded”编码格式的实体内容,getParameter等方法以ServletRequest对象的getCharacterEncoding()方法返 回的字符集编码对其进行URL解码。
(4)getCharacterEncoding()方法的返回值通常为null,对于这种情况,ServletRequest对象的getParameter等方法将使用默认的ISO8859-1字符集编码对实体内容中 的参数进行URL解码,因此也将无法返回正确的中文参数信息。
(5)ServletRequest接口中定义了一个setCharacterEncoding方法来设置请求消息中的实体内容的字符集编码名称,getParameter方法将以该方法设置的字符集编码 对实体内容进行URL解码。
(6)setCharacterEncoding方法设置的是请求消息中的实体内容的字符集编码名称,它只影响getParameter方法对POST方式下的“application/x-www-form-urlencod ed”编码格式的实体内容进行URL解码的结果,而不能影响getParameter方法对HTTP请求消息的请求行中的URL地址后的参数进行URL解码的结果。
解决方案:
1.post方式
对于POST方式,表单中的参数值对是通过request包发送给服务器,此时浏览器会根据网页的ContentType("text/html; charset=GBK")中指定的编码进行对表单中的数据进行编码,然后发给服务器。
在服务器中根据:request.setCharacterEncoding(""),只要编码跟浏览器一直的就可以。
2.get方式
对于GET方式,我们知道它的提交是将请求数据附加到URL后面作为参数,这样依赖乱码就会很容易出现,因为数据name和value很有可能就是传递的为非ASCII码。 当URL拼接后,浏览器对其进行encode,然后发送到服务器。具体规则见URL编码规则。 这里详细说一下encode的过程中容易出现的问题,在这个过程中我们要明白需要URL encode的字符一般都是非ASCII码字符,所以我们就能知道出现乱码主要是URL中附加了中文或特殊字符做成的,另一个要知道URL encode到底是以什么样的编码方式对字符进行编码的,其实这个编码方式是由浏览器决定的,不同的浏览器和同一浏览器的不同设置影响了URL的编码,所以为了避免我们不需要的编码,我们可以通过java代码或javaspcript代码统一进行控制。 完成了URL encode之后URL就成了ASCII范围内的字符了,然后就以iso-8859-1的编码方式转换为二进制随着请求头一起发送出去。 到了服务器之后,首先服务器会先用iso-8859-1进行解码,服务器获取的数据都是ASCII范围内的请求头字符,其中请求URL里面带有参数数据,如果是中卫或特殊字符,那么encode后的%XY(编码规则中的十六进制数)通过request.setCharacterEncoding()是不管用的。这时候我们就能发现出现乱码的根本原因就是客户端一般是通过用UTF-8或GBK等对数据进行encode的,到了服务器却用iso-8859-1方式decoder显然不行。
String value = new String(req.getParameter("name").getBytes("iso-8859-1"),"GBK");
3.request对象实现请求转发:
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/index.jsp");
requestDispatcher.forward(req, resp);
请求重定向和请求转发:是Servlet处理完数据后进行页面跳转的两种主要方式
请求转发:
请求转发是指将请求再转发到另一资源(一般为JSP或Servlet)。此过程依然在同一个请求范围内,转发后浏览器地址栏内
容不变
请求转发使用RequestDispatcher接口中的forward()方法来实现,该方法可以把请求转发到另外一个资源,并让该资源对浏
览器的请求进行响应
请求重定向:
重定向是指页面重新定位到某个新地址,之前的请求失效,进入一个新的请求,且跳转后浏览器地址栏内容将变为新的指定
地址
重定向是通过HttpServletResponse对象的sendRedirect()来实现,该方法相当于浏览器重新发送一个请求
//1.请求转发
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/index.jsp");
requestDispatcher.forward(req, resp); //2.请求重定向:
resp.sendRedirect("http://localhost:8080/Servlet/servlet/Servlet_03");
区别:
1.使用请求重定向,浏览器会向服务器发送两次请求,而请求转发则为一次请求
2.地址栏显示不一样请求转发地址栏没有变化,而请求重定向地址栏会显示新的请求地址 HttpServletResponse.sendRedirect方法和RequestDispatcher.forward方法的区别:
尽管HttpServletResponse.sendRedirect方法和RequestDispatcher.forward方法都可以让浏览器获得另外一个URL所指向的资源,但
两者的内部运行机制有着很大的区别。下面是HttpServletResponse.sendRedirect方法实现的请求重定向与 RequestDispatcher.forward方法实现的请求转发的总结比较:
(1)RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect 方法不仅
可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其
他站点的资源。如果传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;如
果创建RequestDispatcher对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。
(2)调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL
地址变成重定向的目标URL;而调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变
。
(3)HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL
的 访问请求,这个过程好比有个绰号叫“浏览器”的人写信找张三借钱,张三回信说没有钱,让“浏览器”去找李四借,并将李四
现在的通信地址告诉给了“浏览器”。于是,“浏览器”又按张三提供通信地址给李四写信借钱,李四收到信后就把钱汇给了“浏览
器”。可见,“浏览器”一共发出了两封信和收到了两次回复, “浏览器”也知道他借到的钱出自李四之手。
RequestDispatcher.forward方 法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知
道在服务器程序内部发生了转发行为。这个过程好比绰号叫“浏览器”的人写信找张三借钱,张三没有钱,于是张三找李四借了一些
钱,甚至还可以加上自己的一些钱,然后再将这些钱汇给了“浏览器”。可见,“浏览器”只发 出了一封信和收到了一次回复,他
只知道从张三那里借到了钱,并不知道有一部分钱出自李四之手。
(4)RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求
和响应过程;而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个
独立的访问请求和响应过程。对于同一个WEB应用程序的内部资源之间的跳转,特别是跳转之前要对请求进行一些前期预处理,并要
使用HttpServletRequest.setAttribute方法传递预处理结果,那就应该使用RequestDispatcher.forward方法。不同WEB应用程序之
间的重定向,特别是要重定向到另外一个WEB站点上的资源的情况,都应该使用HttpServletResponse.sendRedirect方法。
(5)无论是RequestDispatcher.forward方法,还是HttpServletResponse.sendRedirect方法,在调用它们之前,都不能有内容已经
被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中清除。
场景应用:
请求转发:
用于不同应用场景
一般来讲,在MVC设计模式下,一个servlet将数据交给jsp来做显示就使用请求转发,因为没必要让用户 知道内部实现原理,同时对jsp页面也可以做保护
重定向:
用户登录成功跳转到首页面是用请求重定向,因为此时需要让用户明确知道自己登录成功并跳转到了首页 include和forward的区别:
forward会转发到相应的资源中。
而include会将包含的资源处理下,之后在处理自己的页面。
例子:
- package com.enterise.always.servlet;
- import java.io.IOException;
- import javax.servlet.RequestDispatcher;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- public class Servlet_05 extends HttpServlet{
- private static final long serialVersionUID = 1L;
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- this.doPost(req, resp);
- }
- protected void doPost(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- //1.请求转发
- // RequestDispatcher requestDispatcher = req.getRequestDispatcher("/index.jsp");
- // requestDispatcher.forward(req, resp);
- // requestDispatcher.include(req, resp);
- //2.请求重定向:
- // resp.sendRedirect("http://localhost:8080/Servlet/servlet/Servlet_03");
- //3.include和forward的区别
- RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet/Servlet_03");
- requestDispatcher.forward(req, resp);
- // requestDispatcher.include(req, resp);
- resp.getOutputStream().write("Servlet_05".getBytes());
- }
- }
include的结果为:servlet_03Servlet_05
forward的结果为:servlet_03
2.HttpServletResponse
HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Tue, 03 Sep 2013 03:52:13 GMT 1.getOutputStream和getWriter方法分别用于得到输出二进制数据、输出文本数据的ServletOuputStream、Printwriter对象。
但是两则不能结合在一起使用,原因是:
两个对象的流不一样:
getOutputStream:方法用于返回Servlet引擎创建的字节输出流对象
getWriter:返回Servlet引擎创建的字符输出流对象
这两个方法互斥,调用了其中的一个方法之后,就不能在调用另外一个。 Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法, 如果没有,Servlet引擎将调用close方法关闭该输出流对象。 response的其他功能:
通过setStats方法可以设置响应头的状态码
通过setHead方法可以设置响应头
常见应用 发送REFRESH头,控制浏览器定时刷新网页
发送Expires头,控制浏览器禁止缓存当前文档内容 发送content-type头通知浏览器打开文件的方式
response.setCharacterEncoding("GBK");
//设置浏览器定时刷新
response.setHeader("refresh", "3");
response.getWriter().write("定时刷新中"); //设置浏览器禁止缓存
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Prama", "no-cache"); //实现文件的下载
//对于中文文件名,如果想正常,一定要经过url编码
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
- package com.enterise.always.servlet;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.net.URLEncoder;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class Servlet_06 extends HttpServlet{
- private static final long serialVersionUID = 1L;
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- this.doPost(req, resp);
- }
- protected void doPost(HttpServletRequest req, HttpServletResponse response)
- throws ServletException, IOException {
- //获取到下载资源的绝对路径getRealPath("e://aa/aa.jpg");
- String path = "e://aa/aa.jpg";
- String filename = path.substring(path.lastIndexOf("\\")+1);
- //对于中文文件名,如果想正常,一定要经过url编码
- response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
- FileInputStream in = new FileInputStream(path);
- OutputStream out = response.getOutputStream();
- try {
- int len = 0;
- byte buffer[] = new byte[1024];
- while ((len = in.read(buffer)) > 0) {
- out.write(buffer, 0, len);
- }
- } finally {
- if (in != null)
- try {
- in.close();
- } catch (Exception e) {
- }
- ;
- if (out != null)
- try {
- out.close();
- } catch (Exception e) {
- }
- ;
- }
- }
- }
302状态码和location头即可实现重定向 response.setStatus(302);
response.setHeader("location","/Servlet/index.jsp");
Java 中的 request 和response 理解的更多相关文章
- Java 中的 request 和response 区别
1.response 属于重定向请求: 其地址栏的URL会改变: 会向服务器发送两次请求: 2. request 属于请求转发: 其地址栏的URL不会改变: 向服务器发送一次请求: 举一个区分它们的简 ...
- java中获取request与response对象的方法
Java 获取Request,Response对象方法 第一种.参数 @RequestMapping("/test") @ResponseBody public void sa ...
- LoadRunner中取Request、Response
LoadRunner中取Request.Response LoadRunner两个“内置变量”: 1.REQUEST,用于提取完整的请求头信息. 2.RESPONSE,用于提取完整的响应头信息. 响应 ...
- struts2中获取request、response,与android客户端进行交互(文件传递给客户端)
用struts2作为服务器框架,与android客户端进行交互需要得到request.response对象. struts2中获取request.response有两种方法. 第一种:利用Servle ...
- Django中的Request和Response
接触Django这么久了,从来没有好好学习关于Django中的Request和Response对象.借着文件上传下载的相关工作,现在总结一下也不错. 当一个页面请求过来,Django会自动创建一个Re ...
- SpringMvc4中获取request、response对象的方法
springMVC4中获取request和response对象有以下两种简单易用的方法: 1.在control层获取 在control层中获取HttpServletRequest和HttpServle ...
- java中容器的学习与理解
以前一直对于java中容器的概念不理解,虽然学习过,但始终没有认真理解过,这几天老师提出了这样一个问题,你怎么理解java中的容器.瞬间就蒙了.于是各种搜资料学习了一下,下面是我学习后整理出来的的一些 ...
- spring MVC中获取request和response:
spring MVC中获取request和response: HttpServletRequest request = ((ServletRequestAttributes) RequestConte ...
- DRF (Django REST framework) 中的Request 与 Response
DRF中的Request 与 Response 1. Request - REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST f ...
随机推荐
- 求文件的m至n行
#!/usr/bin/env python def read_file(file_name,start,stop): start_line = 0 try: with open(file_name) ...
- Adding Swagger to Web API project
Adding Swagger to Web API project. All source code for this series can be found here. When you creat ...
- R&&rstudio
R sudo apt-get install R-base Rstudio()下载Rstudio桌面版失败 sudo apt-get install gdebi-core 如果提示少了什么东西,运行下 ...
- [原创]如何设计Lighthoused定位接收电路
本文使用最新出来的专用芯片TS3633 1)电路设计说明 1.电源电路 利用LM317低线性稳压芯片将5V或者12V的电源电压稳压到3.3V为TS3633提供工作电压.其中,磁珠L1主要用于抑制电源线 ...
- cat常用参数详解
cat常用参数详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 最近,我的一个朋友对linux特别感兴趣,于是我觉得每天交给他一个命令的使用,这样一个月下来也会使用30个命令,基 ...
- 自定义view imageviw
新建一个类继承imageview package com.exaple.myselfview; import android.content.Context; import android.graph ...
- 如何用jquery获取页面下HiddenField的值··
怎么用jquery获取页面上HiddenField的值·· 怎么用jquery获取页面上HiddenField的值··?HiddenField的值是从后台赋值的··· 先赋值给Hiddenfield ...
- CSS图片列表
1.效果图: 2.Example Source Code <h3><a href="http://www.52css.com/">我爱CSS画廊</a ...
- Ajax实现原理详解
Ajax:Asynchronous javascript and xml,实现了客户端与服务器进行数据交流过程.使用技术的好处是:不用页面刷新,并且在等待页面传输数据的同时可以进行其他操作. 这就是异 ...
- Android SQLite数据库使用
在Android开发中SQLite起着很重要的作用,网上SQLite的教程有很多很多,不过那些教程大多数都讲得不是很全面.本人总结了一些SQLite的常用的方法,借着论坛的大赛,跟大家分享分享的.一. ...