request到response的流程(三石说-Request与Response)(1)

在前面Http请求的文章中我们看到一个http请求包含请求头,请求体,响应头和响应体,那么对于这些请求方面和响应方面我们与浏览器交互标准是有了,我们后端是不是需要一个关于请求和响应的API,我们为了方便描述一个http请求出现了Request和Response概念。

request到response的流程(三石说-Request与Response)(2)

Request

request这个对象不用事先声明,就可以在JSP网页中使用,在编译为Servlet之后,它会转换为javax.servlet.http.HttpServletRequest形态的对象,HttpServletRequest对象是有关于客户端所发出的请求的对象,只要是有关于客户端请求的信息,都可以由它来取得,例如请求标头、请求方法、请求参数、客户端IP,客户端浏览器等等信息

ServletRequest -- 通用request,提供一个request应该具有的最基本的方法.HttpSerletRequest是Rquest的子类针对http协议进行了进一步的增强

Request的操作获取客户机信息

getRequestURL() 方法返回客户端发出请求完整URLgetRequestURI() 方法返回请求行中的资源名部分getQueryString() 方法返回请求行中的参数部分getRemoteAddr() 方法返回发出请求的客户机的IP地址getMethod() 得到客户机请求方式getContextPath() 获得当前web应用虚拟目录名称

protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ //TODOAuto-generatedmethodstub //1.获取客户端请求的完整的url Stringurl=request.getRequestURL().toString(); System.out.println(url); //2.获取客户端请求的资源的部分名称 Stringuri=request.getRequestURI(); System.out.println(uri); //3.获取请求行中的参数部分 Stringpram=request.getQueryString(); System.out.println(pram); //4.返回客户端的ip地址(*) Stringip=request.getRemoteAddr(); System.out.println(ip); //5.获取客户机的请求方式 Stringmethod=request.getMethod(); System.out.println(method); //6.获取当前web的应用的名称 Stringname=request.getContextPath(); System.out.println(name); //请求转发时以后有这个方法 response.sendRedirect(request.getContextPath() "/index.jsp"); }

获取请求头信息

获得客户机请求头getHeader(name)方法 --- String getHeaders(String name)方法 --- Enumeration枚举变量getHeaderNames方法 --- Enumeration获得具体类型客户机请求头getIntHeader(name)方法 --- intgetDateHeader(name)方法 --- long(日期对应毫秒)

protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ //TODOAuto-generatedmethodstub //获取客户机的请求头 //Stringvalue=request.getHeader("Host"); //System.out.println(value); //遍历所有的请求头 Enumeration<String>enument=request.getHeaderNames(); while(enument.hasMoreElements()){ Stringname=enument.nextElement(); Stringvalues=request.getHeader(name); System.out.println(name ":" values); } }

获取请求参数

request.getParameter()

浏览器以什么编码来发送请求参数? 浏览器以什么编码打开的表单页面,就用什么编码发送这个页面提交的数据。服务器以什么编码来打开呢?如果不指定,则使用ISO8859-1,这样如果请求参数中有中文必然就乱码了

对于POST提交,可以设置request.setCharacterEncoding("utf-8");明确的通知服务器以浏览器发送过来的编码来打开数据就可以解决乱码但是上面的方法只对请求中实体内容部分起作用,所以GET提交的乱码并不能解决. 对于GET提交的乱码,只能手动的进行编解码从而解决乱码问题:String username = request.getParameter("username");username = new String(username.getBytes("iso8859-1"),"utf-8");

protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ //TODOAuto-generatedmethodstub /* *post提交乱码解决 */ //此处也要进行对服务器编码进行设置(通知服务器以什么编码解码http请求中的实体内容) request.setCharacterEncoding("utf-8"); //获取请求参数的值但是传中文字符是会转义到其他的 Stringname=request.getParameter("username"); //System.out.println(name); /* *get提交乱码解决方式(同样也适合post提交方式) *现对提交的参数按照iso8859-1进行编码,然后在解码到其他码表转回 * */ Stringusername=newString(name.getBytes("iso8859-1"),"utf-8"); ///// //获取到用一个枚举变量的类型; Enumeration<String>enumeration=request.getParameterNames(); while(enumeration.hasMoreElements()){ Stringnames=enumeration.nextElement(); Stringvalues=request.getParameter(names); System.out.println(names ":" values); } }

利用请求域传递对象

作用范围:整个请求链上 生命周期:当服务器收到一个请求,创建出代表请求的request对象,request开始.当请求结束,服务器销毁代表请求的request对象,request域结束. 作用:在整个请求链范围内共享数据,通常我们在Servlet中处理好的数据会存入request域后请求转发到jsp页面来进行展示

protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ //TODOAuto-generatedmethodstub //request作用域全局域 getRequestDispater()返回一个作为位于给定路径的资源资源的封装器的 RequestDispatcher 对象。 request.setAttribute("banana","color:yellow"); this.getServletContext().getRequestDispatcher("/Demo2").forward(request,response); //转发到xxxjsp中 //先要获取其中的数据ru Stringresult="xxxx"; request.setAttribute("xxx",result); request.getRequestDispatcher("xxx.jsp"); }

实现请求转发和请求包含

(1)请求转发(.forward()):this.getServletContext().getRequestDispatcher("").forward(request,response);request.getRequestDispatcher("").forward(request,response);

请求转发是希望将请求交给另外一个资源执行,所以应该保证只有最后真正要执行的资源才能够输出数据,所以: 请求转发时,如果已经有数据被写入到了response的缓冲区,但是这些数据还没有被发送到客户端,则请求转发时,这些数据将会被清空.但是清空的只是响应中的实体内容部分,头信息并不会被清空. 而请求转发时已经有数据被打给了浏览器,那么再进行请求转发,不能成功,会抛出异常,原因是响应已经结束了,再转发交给其他人没意义了 在最终输出数据的Servlet执行完成后,response实体内容中的数据将会被设置为已提交的状态,再往里写数据也不会起作用

(2)请求包含(.include()):将两个资源的输出进行合并后输出多个资源同时输出this.getServletContext().getRequestDispatcher("").include(request,response);request.getRequestDispatcher("").include(request,response);

被包含的Servlet程序不能改变响应消息的状态码和响应头,如果它里面存在这样的语句,这些语句的执行结果将被忽略常被用来进行页面布局

(3)三种资源处理方式的区别请求重定向response.sendRedirect();请求转发request.getRequestDispatcher().forward();请求包含request.getRequestDispatcher().include();

请求重定向和请求转发的区别:

请求重定向地址栏会发生变化.请求转发地址栏不发生变化. 请求重定向两次请求两次响应.请求转发一次请求一次响应. 如果需要在资源跳转时利用request域传递域属性则必须使用请求转发request.getRequestDispatcher().forward(); 如果希望资源跳转后修改用户的地址栏则使用请求重定向response.sendRedirect(); 如果使用请求转发也可以重定向也可以,则优先使用请求转发,减少浏览器对服务器的访问次数减轻服务器的压力.

Response

response是Servlet.service方法的一个参数,类型为javax.servlet.http.HttpServletResponse。在客户端发出每个请求时,服务器都会创建一个response对象,并传入给Servlet.service()方法。response对象是用来对客户端进行响应的,这说明在service()方法中使用response对象可以完成对客户端的响应工作。

Response操作设置编码方式

response.setHeader("Content-Type", "text/html;charset=utf-8");response.setCharacterEncoding("utf-8");response.getWriter().write("中国");

publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ //TODOAuto-generatedmethodstub //这里是一个编码过程,用的是操作系统的编码GBK; //浏览器打开时也是GBK的打开方式所以没有乱码 //response.getOutputStream().write("Englishverysoeasy".getBytes()); //这是会出现乱码,需要让浏览器也使用Utf-8编码打开才不会乱码或则用下面的方法 //response.setHeader("Content-Type","text/html;charset=utf-8"); //response.getOutputStream().write("中国".getBytes("utf-8")); /*这时用中文又会乱码这时是只能是服务器把汉字转换为010101然后去查iso8859-1码表 这个码表中没有中文,如果在iso8859-1找不到的话会被转换为?,然而浏览器又会用GBK打开这个编码所以会显示?? 这时要指定服务器查的码表 */ //指定服务器查的码表 response.setCharacterEncoding("gbk"); response.getWriter().write("beijiang"); response.getWriter().write("中国"); //或者这样; response.setHeader("Content-Type","text/html;charset=utf-8"); response.setCharacterEncoding("utf-8"); response.getWriter().write("中国"); //或者这样;setContentType可以直接指定浏览器和服务器的编码方式 response.setContentType("text/html,charset=utf-8"); response.getWriter().write("中国"); //或者这样SetCharacterEnconding指定服务器的编码 //setContentType指定浏览器的编码 response.setCharacterEncoding("utf-8"); response.setContentType("text/html,charset=utf-8"); response.getWriter().write("中国"); }

设置是否缓存(缓存时间)

不进行缓存的设置形式response.setIntHeader("Expires", -1);response.setHeader("Cache-control","no-cache");response.setHeader("Pragma","no-cache");设置缓冲并设置缓存的时间response.setDateHeader("Expires", System.currentTimeMillis() 1000L360024*30);

protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ //设置缓冲的时间 response.setDateHeader("Expires",System.currentTimeMillis() 1000L*3600*24*30); //这样只是读取到这样的文件但是并没有实现下载功能 InputStreamin=newFileInputStream(this.getServletContext().getRealPath("1.jpg")); OutputStreamout=response.getOutputStream(); byte[]bs=newbyte[1024]; inti=0; i=in.read(bs); while(i!=-1){ out.write(bs,0,i); i=in.read(bs); } in.close(); ///下载的形式应该用这个方式 } publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ //TODOAuto-generatedmethodstub //设置响应头信息在浏览器中不进行缓存 response.setIntHeader("Expires",-1); response.setHeader("Cache-control","no-cache"); response.setHeader("Pragma","no-cache"); //同时设置服务器和浏览器的编码方式 response.setContentType("text/html;charset=utf-8"); response.getWriter().write("当前时间是:" newDate().toLocaleString()); }

设置资源下载

文件名中包含中文,则文件名要进行URL编码,URLEncoding.encode('啊啊.jpg','utf-8');如果不进行编码则文件名显示错误并且不可下载

///下载的形式应该用这个方式 翻译:Disposition:配置

response.setHeader("Content-Disposition", "attachment;filename=1.jpg");

//这样只是读取到这样的文件但是并没有实现下载功能InputStream in=new FileInputStream(this.getServletContext().getRealPath("1.jpg"));

OutputStream out=response.getOutputStream();

protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ //TODOAuto-generatedmethodstub ///下载的形式应该用这个方式(Y) //setHeader头信息不支持中文格式所以命名不能用中文命名这样可以指定下载是所显示的名字 //response.setHeader("Content-Disposition","attachment;filename=美女.jpg"); //方式一:狭隘 //response.setHeader("Content-Disposition","attachment;filename=butiful.jpg"); //解决方式二:url编码可以用ascII码中的转换为url编码然后再转换为指定的编码 response.setHeader("Content-Disposition","attachment;filename=" URLEncoder.encode("美女.jpg","utf-8")); //这样只是读取到这样的文件但是并没有实现下载功能(N) InputStreamin=newFileInputStream(this.getServletContext().getRealPath("1.jpg")); OutputStreamout=response.getOutputStream(); byte[]bs=newbyte[1024]; inti=0; i=in.read(bs); while(i!=-1){ out.write(bs,0,i); i=in.read(bs); } in.close(); }

请求重定向

response.sendRedirect("/Test/index.jsp");

设置刷新跳转

response.setHeader("refresh", "3;url=/Test/index.jsp");转发//request.getRequestDispatcher("/index.jsp").forward(request, response);包含/request.getRequestDispatcher("/index.jsp").include(request, response);重定向response.sendRedirect("/Test/index.jsp");

protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{ //TODOAuto-generatedmethodstub //隔几秒刷新页面 //response.getWriter().write(newDate().toString()); //response.setHeader("Refresh","1"); //隔几秒会到主页 //response.setCharacterEncoding("utf-8"); //response.setHeader("Content-Type","text/html;charset=utf-8"); response.setContentType("text/html;charset=utf-8"); response.getWriter().write("恭喜你注册成功3秒后跳转页面...."); response.setHeader("refresh","3;url=/Test/index.jsp"); //但是一般不会这样写会把写出的话放到html页面中 //向newFilehtml那样进行操作可以在html中用<metahttp-equiv=""content="">来模拟响应头信息 }

以上就是分享的请求和响应的技术,但是随着前后端的分离,我们现在大多数都采用response进行直接写数据到那个位置,而往往是大多数的框架帮我帮我们做了一些事情,但是我们也应该去真正的明白其中的内涵.喜欢的关注一下,同时也希望你提出宝贵的建议。

,