HttpServletrequest 与HttpServletResponse总结

  若是说DOM是javascript与HTML的桥梁,那么servlet就是前端与后端的桥梁,HttpServletRequest和HttpServletResponse就是之间的信使,好了,废话很少说!javascript

由来

  Web服务器收到一个http请求,会针对每一个请求建立一个HttpServletRequestHttpServletResponse对象,向客户端发送数据找HttpServletResponse,从客户端取数据找HttpServletRequest.html

  HTTP 协议是基于请求-响应的协议,客户端请求一个文件,服务器对该请求进行响应。HTTP 使用 TCP 协议,默认使用 80 端口。最初的 HTTP 协议版本是 HTTP/0.9,后被 HTTP/1.0 替代。目前使用的版本是 HTTP/1.1前端

HTTP 协议中,老是由主动创建链接、发送 HTTP 请求的客户端来初始化一个事务。服务器不负责链接客户端,或建立一个到客户端的回调链接(callback connection)。java

HttpServletRequest 

  公共接口类HttpServletRequest继承自ServletRequest.客户端浏览器发出的请求被封装成为一个HttpServletRequest对象。全部的信息包括请求的地址,请求的参数,提交的数据,上传的文件客户端的ip甚至客户端操做系统都包含在其内。web

一个 HTTP 请求包含如下三部分:编程

a.请求地址(URL)json

b.请求头(Request headers)后端

c.实体数据(Entity body)数组

举例以下浏览器

POST /examples/default.jsp HTTP/1.1

Accept: text/plain; text/html

Accept-Language: en-gb

Connection: Keep-Alive

Host: localhost

User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)

Content-Length: 33

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

lastName=Franks&firstName=Michael

 

  每一个 HTTP 请求都会有一个请求方法,HTTP1.1 中支持的方法包括,GETPOSTHEADOPTIONS

PUTDELETE TRACE。互联网应用中最经常使用的是 GET POST

  URI 指明了请求资源的地址,一般是从网站更目录开始计算的一个相对路径,所以它老是以斜线 “/”开头的。URL 其实是 URI 的一种类型,请求头(header)中包含了一些关于客户端环境和请求实体(entity)的有用的信息。例如,客户端浏览器所使用的语言,请求实体信息的长度等。每一个请求头使用 CRLF(回车换行符,“\r\n”)分隔。注意请求头的格式:

请求头名+英文空格+请求头值

 

经常使用方法

1.得到客户机信息

getRequestURL方法返回客户端发出请求时的完整URL

getRequestURI方法返回请求行中的资源名部分。

getQueryString 方法返回请求行中的参数部分。

getRemoteAddr方法返回发出请求的客户机的IP地址

getRemoteHost方法返回发出请求的客户机的完整主机名

getRemotePort方法返回客户机所使用的网络端口号

getLocalAddr方法返回WEB服务器的IP地址。

getLocalName方法返回WEB服务器的主机名

getMethod获得客户机请求方式

getServerPath()获取请求的文件的路径

 2.得到客户机请求头

getHeader(string name)方法 
getHeaders(String name)方法 
getHeaderNames方法 

 3. 得到客户机请求参数(客户端提交的数据)
getParameter(name)方法 获取请求中的参数,该参数是由name指定的
getParameterValuesString name)方法 获取指定名称参数的全部值数组。它适用于一个参数名对应多个值的状况。如页面表单中的复选框,多选列表提交的值。

getParameterNames方法 返回一个包含请求消息中的全部参数名的Enumeration对象。经过遍历这个Enumeration对象,就能够获取请求消息中全部的参数名。

getCharacterEncoding() 返回请求的字符编码方式

getAttributeNames()返回当前请求的全部属性的名字集合赋值:setAttribute()

getAttribute(String name) 返回name指定的属性值

getsession()返回和客户端相关的session,若是没有给客户端分配session,则返回null

getParameterMap():返回一个保存了请求消息中的全部参数名和值的Map对象。Map对象的key是字符串类型的参数名,value是这个参数所对应的Object类型的值数组

RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。方法在服务器端内部将请求转发给另一个资源,浏览器只知道发出了请求并获得了响应结果,并不知道在服务器程序内部发生了转发行为。

request.setCharacterEncoding("utf-8");

getReader() 获取请求体的数据流

getInputStream() 获取请求的输入流中的数据

经过输入输出流获取 :getInputStream() 和 getReader()

在读取的时候经过流对象.read()方法读取

Eg:

StringBuffer receiveMessage = new StringBuffer();

Scanner scanner = new Scanner(request.getInputStream(), "GBK");

    while (scanner.hasNext()) {

receiveMessage.append(scanner.next());

}

scanner.close();

String json =receiveMessage.toString()

    JSONObject obj = new JSONObject(json);

openId = obj.get("openid").toString();

出现乱码的缘由和解决

1java程序中默认的是中文字符----unicode

2. 系统会把在java程序中的unicode字符按照某种字符集编码的方式转换成字节数组,再经过浏览器输出,浏览器在输出的时候要进行解码,只有在这两种方式同样的状况下,才不会出现乱码。

:(1)某种字符编码是用reponse对象去设置的,并且必须是在out.println以前使用,要不会出现错误,会抛找不到设置的字符编码而出错。

         设置编码的两种方式:

        response.setContentType("text/html;charset=utf-8");

        request.setCharacterEncoding("utf-8");

      (2)浏览器会把字节数组转换成字符

  1. 系统默认的编码方式为ISO8859-1,若是没有指定字符编码,则输出的都是乱码,并且ISO8859-1不支持中文,因此无论浏览器在解码的时候用的是什么字符集编码,在浏览器上的都是乱码。

解决办法以下

Post方式提交出现乱码

request.setCharacterEncoding("UTF-8");

请求中之因此会产生乱码,就是由于服务器和客户端沟通的编码不一致形成的,所以解决的办法是:在客户端和服务器之间设置一个统一的编码,以后就按照此编码进行数据的传输和接收。

  因为客户端是以UTF-8字符编码将表单数据传输到服务器端的,所以服务器也须要设置以UTF-8字符编码进行接收,要想完成此操做,服务器能够直接使用从ServletRequest接口继承而来的"setCharacterEncoding(charset)"方法进行统一的编码设置。使用request.setCharacterEncoding("UTF-8");设置服务器以UTF-8的编码接收数据后,此时就不会产生中文乱码问题了

Get方式提交出现乱码

对于以get方式传输的数据,request即便设置了以指定的编码接收数据也是无效的,默认的仍是使用ISO8859-1这个字符编码来接收数据,客户端以UTF-8的编码传输数据到服务器端,而服务器端的request对象使用的是ISO8859-1这个字符编码来接收数据,服务器和客户端沟通的编码不一致所以才会产生中文乱码的。

解决办法:在接收到数据后,先获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,而后经过字节数组以指定的编码构建字符串,解决乱码问题。代码以下:

String name = request.getParameter("name");//接收数据

name =new String(name.getBytes("ISO8859-1"), "UTF-8") ;//获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,而后经过字节数组以指定的编码构建字符串,解决乱码问题

HttpServletResponse

  HttpServletResponse继承了ServletResponse接口,并提供了与Http协议有关的方法,这些方法的主要功能是设置HTTP状态码和管理CookieHttpServletResponse对象表明服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法

HttpServletResponse对象能够向客户端发送三种类型的数据:

a.响应头(Response headers)

b.状态码(ProtocolStatus codeDescription)

c.实体数据(Entity body )

举例以下:

HTTP/1.1 200 OK

Server: Microsoft-IIS/4.0

Date: Mon, 5 Jan 2004 13:13:33 GMT

Content-Type: text/html

Last-Modified: Mon, 5 Jan 2004 13:13:12 GMT

Content-Length: 112

<html><head><title>HTTP Response Example</title></head>....</html>

经常使用方法

addHeader(String name,String value)  将指定的名字和值加入到响应的头信息中

encodeURL(String url)  编码指定的URL

sendError(int sc)  使用指定状态码发送一个错误到客户端

setDateHeader(String name,long date  将给出的名字和日期设置响应的头部

setHeader(String name,String value)  将给出的名字和值设置响应的头部

setStatus(int sc)  给当前响应设置状态码

HttpServletResponse.sendRedirect 方法对浏览器的请求直接做出响应,响应的结果就是告诉浏览器去从新发出对另一个URL的访问请求;方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。

 response.setContentType("text/html;charset=utf-8");

setContentType(String ContentType)  设置响应的MIME类型 ,页面的设置文本类型,获取或设置输出流的 HTTP MIME 类型。输出流的 HTTP MIME 类型。默认值为“text/html”。

MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

使用输出流输出一张图片的时候,好比作验证码图片的时候 若是在Firefox中直接浏览验证码是乱码,放在<img>里面则不会

这时候就要事先指定Response.ContentType = "image/jpeg";//设定MIME类型

response.setHeader(Refresh,2;url=http://www.baidu.com); 页面的刷新

消息实体内容 经过输出流对象进行设置,用如下两个方法:

Response.getOutputStream()  字节输出流对象

Response.getWriter()   字符的输出流对象

 getOutputStreamgetWriter方法的比较

1getOutputStream方法用于返回Servlet引擎建立的字节输出流对象,Servlet程序能够按字节形式输出响应正文。

2getWriter方法用于返回Servlet引擎建立的字符输出流对象,Servlet程序能够按字符形式输出响应正文。

3getOutputStreamgetWriter这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另外一方法。要不会出现错误java.lang.IllegalStateException

4getOutputStream方法返回的是字节输出流对象的类型为ServletOutputStream,它能够直接输出字节数组中的二进制数据。

5getWriter方法将Servlet引擎的数据缓冲区包装成PrintWriter类型的字符输出流对象后返回,PrintWriter对象能够直接输出字符文本内容。

6Servlet程序向ServletOutputStreamPrintWriter对象中写入的数据将被Servlet引擎获取,Servlet引擎将这些数据看成响应消息的正文,而后再与响应状态行和各响应头组合后输出到客户端。

7Serlvetservice方法结束后,Servlet引擎将检查getWritergetOutputStream方法返回的输出流对象是否已经调用过close方法,若是没有,Servlet引擎将调用close方法关闭该输出流对象。

注:out.close();系统会本身释放,但通常写上

选择getOutputStreamgetWrite方法的要点

1PrintWriter对象输出字符文本内容时,它内部仍是将字符串转换成了某种字符集编码的字节数组后再进行输出,使用PrintWriter对象的好处就是不用编程人员本身来完成字符串到字节数组的转换。

2)使用ServletOutputStream对象也能输出内容全为文本字符的网页文档,可是,若是网页文档内容是在Servlet程序内部使用文本字符串动态拼凑和建立出来的,则须要先将字符文本转换成字节数组后输出。

(3)若是一个网页文档内容所有为字符文本,可是这些内容能够直接从一个字节输入流中读取出来,而后再原封不动地输出到客户端,那么就应该使用ServletOutputStream对象直接进行输出,而不要使用PrintWriter对象进行输出。   

向客户端写入中文

使用OutputStream向客户端写入中文:

String data = "中国";

OutputStream stream = response.getOutputStream();//获取一个向Response对象写入数据的流,tomcat服务器进行响应的时候,会将Response中的数据写给浏览器

stream.write(data.getBytes("UTF-8"));//此时在html页面会出现乱码,这是由于:服务器将"中国"按照UTF-8码表进行编码,获得对应的码值假设是98,99,服务器将码值发送给浏览器.浏览器默认按照GB2312进行解码,GB2312码表中对应的字符已不是"中国"

正确代码以下:

response.setHeader("Content-type","text/html;charset=UTF-8");//向浏览器发送一个响应头,设置浏览器的解码方式为UTF-8

 String data = "中国";

 OutputStream stream = response.getOutputStream();

stream.write(data.getBytes("UTF-8"));

使用PrintWriter向客户端写入中文:

PrintWriter writer = response.getWriter();

writer.write("中国");

//一样会出现乱码,这是由于咱们将"中国"写入response对象时,tomcat服务器为了将数据经过网络传输给浏览器,必须进行编码,因为没有指定编码方式,默认采用ISO8859-1,当浏览器接收到数据后,根据GBK解码必然出现乱码

 正确代码以下:

response.setCharacterEncoding("UTF_8");//设置Response的编码方式为UTF-8

response.setHeader("Content-type","text/html;charset=UTF-8");//向浏览器发送一个响应头,设置浏览器的解码方式为UTF-8,其实设置了本句,也默认设置了Response的编码方式为UTF-8,可是开发中最好两句结合起来使用 ,设置响应头,控制浏览器以指定的字符编码编码进行显示,

 //response.setContentType("text/html;charset=UTF-8");同上句代码做用同样

 PrintWriter writer = response.getWriter();

writer.write("中国");

  在获取PrintWriter输出流以前首先使用"response.setCharacterEncoding(charset)"设置字符以什么样的编码输出到浏览器,如:response.setCharacterEncoding("UTF-8");设置将字符以"UTF-8"编码输出到客户端浏览器,而后再使用response.getWriter();获取PrintWriter输出流,这两个步骤不能颠倒

使用Response实现文件下载:

 文件下载功能是web开发中常用到的功能,使用HttpServletResponse对象就能够实现文件的下载

文件下载功能的实现思路:

  1.获取要下载的文件的绝对路径

  2.获取要下载的文件名

  3.设置content-disposition响应头控制浏览器如下载的形式打开文件

  4.获取要下载的文件输入流

  5.建立数据缓冲区//缓冲区解释见下文

  6.经过response对象获取OutputStream

  7.FileInputStream流写入到buffer缓冲区

8.使用OutputStream将缓冲区的数据输出到客户端浏览器

案例1

private void downloadFileByOutputStream(HttpServletResponse response){

         //1.获取要下载的文件的绝对路径

         String realPath = this.getServletContext().getRealPath("/download/1.JPG");

         //2.获取要下载的文件名

         String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);

         //3.设置content-disposition响应头控制浏览器如下载的形式打开文件

         response.setHeader("content-disposition", "attachment;filename="+fileName);

         //4.根据文件路径获取要下载的文件输入流

        InputStream in = new FileInputStream(realPath);

         int len = 0;

         //5.建立数据缓冲区

         byte[] buffer = new byte[1024];

         //6.经过response对象获取OutputStream

         OutputStream out = response.getOutputStream();

         //7.FileInputStream流写入到buffer缓冲区         while ((len = in.read(buffer)) > 0) {

         //8.使用OutputStream将缓冲区的数据输出到客户端浏览器

             out.write(buffer,0,len);

         }

         in.close();

     }

案例2

@RequestMapping("/download")

public void download(HttpServletRequest req,HttpServletResponse res){

String fileName = "plcdmb.xls";//要下载的文件名

  //1.获取要下载的文件的绝对路径

String realPath = req.getSession().getServletContext().getRealPath("/wbms/download");

File file=new File(realPath+"/"+fileName); //设置content-disposition响应头控制浏览器如下载的形式打开文件

        res.setCharacterEncoding("utf-8");

        res.setContentType("application/octet-stream");

        res.setHeader("Content-Disposition", "attachment;fileName="+ URLEncoder.encode("批量出单模板.xls", "UTF-8"));

        InputStream inputStream=new FileInputStream(file);根据路径获取要下载的文件输入流 

        OutputStream out = res.getOutputStream();

        byte[] b=new byte[1024];  //建立数据缓冲区

            int length;  

            while((length=inputStream.read(b))>0){  把文件流写到缓冲区里

             out.write(b,0,length);  

            }  

            out.flush();

            out.close();

            inputStream.close();

 

}

在编写下载文件功能时,要使用OutputStream流,避免使用PrintWriter流,由于OutputStream流是字节流,能够处理任意类型的数据,而PrintWriter流是字符流,只能处理字符数据,若是用字符流处理字节数据,会致使数据丢失。

其余

jsp嵌套的java代码中执行js

<%

//保存登陆信息

Cookie[] cookies=request.getCookies();//request中得到cookie对象的集合  

String phone="";//电话号

String state="";//

if(cookies!=null){  

    for(int i=0;i<cookies.length;i++){  

        if(cookies[i].getName().equals("state")){  

            state=cookies[i].getValue();

               if(state.equals("cont_failed")){

               out.write("<script language='javascript'> alert('hello'); </script>;");

               }                                                           

        }  

    }                                                                 

}

 %>

getWriter()输出js代码的案例

1.res.getWriter().write("<script language=\"javascript\">location.href='"+req.getContextPath()+"/wbms/ecm//init.action';</script>");//在原页面输出

res.getWriter().flush();

2.response.getWriter().write("<script language='javascript'>alert('请上传正确格式的文件!!!');window.history.back();</script>");

3.res.getWriter().flush();

若是不使用这种形式,传值用request.setAttribute()来传值跳转用重定向或者转发页面取值能够用jstl$()取值能够在input标签的value中使用$()取值

ServletRequestServletResponse

ServletRequest

表明一个HTTP请求,请求在内存中是一个对象,这个对象是一个容器,能够存放请求参数和属性。

请求对象什么时候被建立,当经过URL访问一个JSP或者Servlet的时候,也就是当调用Servletservice()doPut()doPost()doXxx()方法时候的时候,执行Servletweb服务器就自动建立一个ServletRequestServletResponse的对象,传递给服务方法做为参数。

请求对象由Servlet容器自动产生,这个对象中自动封装了请求中getpost方式提交的参数,以及请求容器中的属性值,还有http头等等。当Servlet或者JSP获得这个请求对象的时候,就知道这个请求时从哪里发出的,请求什么资源,带什么参数等等。经过请求对象,能够得到Session对象和客户端的Cookie。请求须要指定URL,浏览器根据URL生成HTTP请求并发送给服务器.

ServletResponse

也是由容器自动建立的,表明Servlet对客户端请求的响应,响应的内容通常是HTML,而HTML仅仅是响应内容的一部分。请求中若是还包含其余资源会依次获取,如页面中含有图片,会进行第二个http请求用来得到图片内容。

相应对象有如下功能:

1、向客户端写入Cookie

2、重写URL

3、获取输出流对象,向客户端写入文本或者二进制数据

4、设置响应客户端浏览器的字符编码类型

5、设置客户端浏览器的MIME类型。

一个简单的 servlet 容器

Servlet 接口须要实现下面的 5 个方法:

public void init(ServletConfig config) throws ServletException

public void service(ServletRequest request, ServletResponse response) throws ServletException,

java.io.IOException

public void destroy()

public ServletConfig getServletConfig()

public java.lang.String getServletInfo()

在某个 servlet 类被实例化以后,init 方法由 servlet 容器调用。servlet 容器只调用该方法一次,调用后则能够执行服务方法了。在 servlet 接收任何请求以前,必须是通过正确初始化的。

当一个客户端请求到达后,servlet 容器就调用相应的 servlet service 方法,并将 Request Response对象做为参数传入。在 servlet 实例的生命周期内,service 方法会被屡次调用。

在将 servlet 实例从服务中移除前,会调用 servlet 实例的 destroy 方法。通常状况下,在服务器关闭前,会发生上述状况,servlet 容器会释放内存。只有当 servlet 实例的 service 方法中全部的线程都退出或执行超时后,才会调用 destroy 方法。当容器调用了 destroy 方法后,就不会再调用 service 方法了。

下面从 servlet 容器的角度观察 servlet 的开发。在一个全功能 servlet 容器中,对 servlet 的每一个 HTTP 请求来讲,容器要作下面几件事:

1.当第一次调用 servlet 时,要载入 servlet 类,调用 init 方法(仅此一次);

2.针对每一个 request 请求,建立一个 Request 对象和一个 Resposne 对象;

3.调用相应的 servlet service 方法,将 Request 对象和 Response 对象做为参数传入;

4.当关闭 servlet 时,调用 destroy 方法,并卸载该 servlet 类。

输出缓冲区

1.输出缓冲区的介绍

1Servlet程序输出的HTTP消息的响应正文首先被写入到Servlet引擎提供的一个输出缓冲区中,直到输出缓冲区被填满或者Servlet程序已经写入了全部的响应内容,缓冲区中的内容才会被Servlet引擎发送到客户端。

2)使用输出缓冲区后,Servlet引擎就能够将响应状态行、各响应头和响应正文严格按照HTTP消息的位置顺序进行调整后再输出到客户端。

3)若是在提交响应到客户端时,输出缓冲区中已经装入了全部的响应内容,Servlet引擎将计算响应正文部分的大小并自动设置Content-Length头字段。

4)若是在提交响应到客户端时,输出缓冲区中装入的内容只是所有响应内容的一部分,Servlet引擎将使用HTTP1.1chunked编码方式(经过设置Transfer-Encoding头字段来指定)传输响应内容。

输出缓冲区的有关方法  

      System.out.println(response.getBufferSize());    //读取缓存区的大小

      response.setBufferSize(1024);  //设置缓冲区的的大小,会小与你设置的值

      System.out.println(response.getBufferSize());

      int len=response.getBufferSize();  //填满缓冲区

      for(int i =0;i<len;i++){

         System.out.println("w");

      }

相关文章
相关标签/搜索