httpservletrequest和httpservletresponse的理解

来源:互联网 发布:sql书写规范 编辑:程序博客网 时间:2024/06/06 14:07

有这样一段代码

@ResponseBody
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ApiOperation(value = "会员登录", response = ApiResult.class, notes = "会员登录接口", position = 2)
@ResponseStatus(value = HttpStatus.OK)

public ResponseEntity<?> login(

@ApiParam(required = true, name = "mobile", value = "手机") @RequestParam(value = "mobile", required = true) String mobile,
@ApiParam(required = true, name = "password", value = "密码") @RequestParam(value = "password", required = true) String password,

HttpServletRequest request, HttpServletResponse response)

发现每个接口中都有httpservletrequest和httpservletresponse这两个参数,一直疑惑这两个对象是哪里来的。今天就来解一解惑。

首先,这个两个对象是servlet容器创建的,我们还记得一个完整的http请求的过程吗?

Servlet作为补充Web服务器功能的组件,需要依赖于Servlet容器才能运行,它的运行原理如下图所示。

在浏览器中输入请求地址后,浏览器会依据IP地址及端口号找到对应的Web服务器,如果请求的是静态资源,Web服务器直接提供响应;如果请求的是动态资源,Web服务器的通信模块会将该请求传递给Servlet容器的通信模块,Servlet容器负责创建Servlet实例,并将请求中的数据解析出来传递给Servlet。在Servlet处理完数据之后,响应结果也是由容器的通信模块负责返回给Web服务器。后续的Servlet的销毁及管理都由容器来负责。

能够充当Servlet容器这个角色的有很多软件,如Tomcat、Weblogic、JBoss等。而这些Servlet容器不仅仅具备了管理Servlet组件的功能,也具备了Web服务器的一些功能,所以很多时候只要安装一个Tomcat软件就同时具备了Web服务器及Servlet容器的双重功能。

我想说的就是,一个http请求到了web服务器,然后甩给了servlet容器(比如tomcat)然后容器会生成servlet实例,实例中就包含了httpservletrequest和httpservleresponse这两个变量,可以想一下直接用servlet写的java程序,实现业务的类是继承httpservlet的,复写的方法dopost包含httpservletrequest和httpservletresponse这两个变量。

protectedvoiddoPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { }



然后我们讨论一下,从httpservletrequest和httpservletresponse 我们能做些什么。

首先我们要知道httpservletrequest和httpservletresponse都是对象,它们包含了请求和返回的所有数据。

想知道它们有哪些方法最好当然是去查servlet的API了,在这里稍微讲几个。API地址:http://tomcat.apache.org/tomcat-7.0-doc/servletapi/


HttpServletRequest 

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


常用方法

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()方法读取


HttpServletResponse

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

常用方法

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对象进行输出。   


其实最好还是去看下servlet的api,以前一直疑惑在请求中到底存放着哪些内容,现在的理解是这样的:请求是一个对象,这个对象是servlet容器创建servlet实例后产生的。那么我们通过request对象能做什么呢(也就是我以前疑惑的请求中有写什么东西)

通过request这个对象我们可以获得parameter.attribute.session.浏览器的一些信息等等,从api就可以知道。