java笔记2-servlet-处理请求与响应

目标

  • 怎么处理请求与响应
    • web容器到底是怎么实现请求与响应的
    • HttpServletRequest处理请求
      • http请求头信息有哪些
      • get/post获取参数
      • get/post编码
      • 上传图片怎么解决?(http协议body数据怎么获取?)
      • 容器内部如何共享数据?
      • 两个servlet程序之间如何调用?
      • 内部转发到底是什么逻辑?
    • HttpServletResponse处理响应
      • http响应头信息有哪些
      • 输出内容也是需要编码的!
      • 二进制响应
      • 重定向
      • 直接输出错误状态(404)

1. web容器到底是怎么实现请求与响应的?

java笔记2-servlet-处理请求与响应_第1张图片
Paste_Image.png
  1. web容器接收到HTTP服务器转发的请求内容
  2. 初始化HttpServletRequest对象,然后用相关参数进行赋值
  3. 初始化HttpServletResponse对象
  4. 初始化HttpServlet的实现类,调用它的service函数,并把HttpServletRequest和HttpServletResponse两个对象传递过去
  5. service调用doXXX函数,在该函数中,使用request的getParamter()函数获取参数
  6. 处理相应的业务逻辑
  7. 设置response的setContentType输出文件类型和编码
  8. 调用HttpServletResponse的getWriter()函数获得输出用的PrintWriter对象,然后通过函数println()打印输出html

需注意的是:

  1. 一次请求和响应是一个生命周期,在该周期呢,HttpServletRequest和HttpServletResponse由容器负责创建和销毁,它们不能跨越生命周期
  2. web容器在一个生命周期内处理的流程已经很清晰了,试想,如果没有web容器,这些工作都要由程序员每次编码实现,很复杂!因此容器将系统自身业务逻辑和软件需求业务逻辑进行分离,开发人员只需要编写软件需求业务逻辑即可!

servlet原来设计是处理各种网络协议的,因此提供的请求和响应对象类型是ServletRequest和ServletResponse,HttpServlet将这两个对象转化为HttpServletRequest和HttpServletResponse,请看具体代码:

java笔记2-servlet-处理请求与响应_第2张图片
Paste_Image.png

然后在service里面调用实际的doXXX相关函数:

java笔记2-servlet-处理请求与响应_第3张图片
Paste_Image.png

2. HttpServletRequest处理请求

  • http请求头信息有哪些?

标示字段 含义
Accept 客户端支持的数据类型
Accept-Charset 客户端支持的编码
Acctpt-Encoding 客户端支持哪种数据压缩格式
Acctpt-Language 客户端采用的是那种开发语言
Host 客户端想访问的服务器主机
if-Modified-Since 数据在客户端缓存的时间
Referer 客户端从哪个页面来的
User-Agent 客户端的操作系统和浏览器信息
Cookie cookie数据
Connection 持否需要持久链接
Content_length 表示请求消息正文的长度

这是ljlj的请求头信息截图:

java笔记2-servlet-处理请求与响应_第4张图片
Paste_Image.png
  • GET/POST获取参数及标头

取得web应用程序环境路径:getContextPath()

获取参数

函数 功能描述
getParameter(参数名称) 获取指定参数名称的值
getParameterValues() 同一个请求参数会有多个值,返回的是一个数组,返回类型为Enumeration对象
getParameterNames() 返回所有参数的名称
getParameterMap 以key/value的方式返回参数与值

获取标头

函数 功能描述
getHeader(参数名称) 获取指定参数名称的标头
getHeaders() 类似于getParameterValues函数,返回的也是Enumeration对象
getHeaderNames() 返回所有标头参数名称
  • GET/POST编码

编码问题主要是针对非ASCII码字符

-------------------------------post请求-------------------------------

浏览器端
Content-Type标头中会设置字符编码

Context-Type:text/html;charset=UTF-8

相当于是做了如下操作:

String text = java.net.URLEncoding.encode("林","UTF-8")

容器端
容器端默认的编码是:ISO-8859-1,所以如果要取得正确的中文字符,就需要:

req.setCharacterEncoding("UTF-8");
-------------------------------get请求-------------------------------

get请求的浏览器端和post一样,不再赘述!

HTTP服务器端
这里为什么和post不一样,post是容器端,而这里是HTTP服务器端?
因为处理URL的是http服务器,而不是web容器,因此get参数不能使用HttpServletRequest对象!!
get获取参数只能是获得参数后,在进行编码转换,它会使用到String对象的getBytes()函数,具体方式如下:

String name = req.getParameter("name");
String name = new String(name.getBytes("ISO-8859-1","UTF-8"));
  • 上传图片怎么解决?(http协议body数据怎么获取?)

先来确认一下http协议body数据是什么?http协议一般是由请求行、请求头部、空行和请求数据四部分组成的:

java笔记2-servlet-处理请求与响应_第5张图片
Paste_Image.png

GET请求没有body

GET /hello/index.html HTTP/1.1 
#【↑】request line
#【↓】request headers
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
Host: localhost:8000
#发送完关闭连接 or 等待
Connection: Keep-Alive
Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6

post请求的表单数据就是body

#url的部分仍然是urlencoded
POST /hello/checkUser.html?opt=xxx HTTP/1.1
Referer: http://localhost:8000/hello/index.html
Accept: */*
Accept-Language: zh-cn
#纯文本的编码:不编码
Content-Type: text/plain
Accept-Encoding: gzip, deflate
Host: localhost:8000
Content-Length: 20
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6

#【↑】/r/n
#【↓】request body
hl=zh-CN&source=hp&q=domety  

搞清楚body的原理后,把取body数据分为两种,一种是简单的字符串表单,里面的都是文字,另一种就是文件上传了。

---------字符串------------
HttpServletRequest定义了getReader()方法,可以获得BufferReadere对象,通过该对象,就可以访问body中的数据

java笔记2-servlet-处理请求与响应_第6张图片
Paste_Image.png

---------文件(图片)上传------------
有两种方式,一种是用HttpServletRequest的getInputStream()函数获取ServletInputStream对象,是一种串流对象,来处理上传文件。另一种就是servlet3.0中使用的Part进行操作。前一种有点落伍,就不赘述了!

使用Part处理上传图片,必须加上@WebServlet("/upload.do")

java笔记2-servlet-处理请求与响应_第7张图片
Paste_Image.png
  • 容器内部如何共享数据?

req.setAttrbute()
req.getAttrbute()
req.getAttrbuteNames()
req.removeAttrbute()

在一个请求的生命周期内,php共享数据靠session,java可以设置HttpServletRequest的属性,来在整个生命周期内,不论转发了多少个servlet,这些属性都存在。
有些保留的属性名称就不要设置了:

java笔记2-servlet-处理请求与响应_第8张图片
Paste_Image.png
  • 两个servlet程序之间如何调用?

request.getRequestDispatcher("some.do").include(request,response)
request.getRequestDispatcher("some.do?data=xxx").include(request,response)
  • 内部转发到底是什么逻辑?

在调用forward函数前,当前servlet不能对请求进行响应(例如打印字符串),如果有响应但未确认(缓冲区未满或未调用任何清除方法),则响应设置会被忽略。如果有效应且已确认,然后在调用forward()方法,则会抛出IllegalStateException异常

request.getRequestDispatcher("some.do").forward(request.response);

3. HttpServletResponse处理响应

  • http响应头信息有哪些?

头标示 头标示解释
Location 表示客户端应该到哪里去提取文档
Content-Encoding 文档的编码方式
Content-Length 表示内容长度
Content-Type 表示后面的文档属于哪种MIME类型
Last-Modified 文档的最后修改时间
Expires 文档什么时候过期
Refresh 表示浏览器因该在多少时间之后刷新文档
Server 服务器名字
Set-Cookie 设置和页面关联的cookie
java笔记2-servlet-处理请求与响应_第9张图片
Paste_Image.png

---------------常规的设置标头的函数---------------

  • setHeader() 设置标头名称和值
  • addHeader() 给同一标头名称上附加值
  • setIntHeader() 如果标头的值是整数
  • addIntHeader() 同理
  • setDateHeader() 如果标头的值是日期时间
  • addDateHeader() 同理

所有的标头设置必须在响应输出确认之前,如果在之后,所有的设置会被忽略

---------------响应输出有缓冲区---------------
只有在缓冲区满或者强制刷新缓冲区的情况下,才会真正的输出内容到客户端浏览器。

  • getBufferSize()
  • setBufferSize()
  • isCommited() 查看缓冲区的内容是否已经确认
  • reset()
  • resetBuffer()
  • flushBuffer()

在调用HttpServletResponse的getWrite()或getOutputStream()方法之后调用setBufferSize(),会抛出IllegalStateException。(也就是在调用输出函数之前就得设置好缓冲区)
在响应输出确认之后,调用reset(),resetBuffer()会抛出IllegalStateException异常。(确认的输出不能随意重置)

  • 输出内容也是需要编码的!

HttpServletResponse对象的setCharacterEncoding()和setContextType()都能设置编码,建议使用后者,连同文件内容类型一起设置

response.setContextType("text/html","UTF-8")
  • 二进制响应

在大部分情况下,会从HttpServletResponse取得PrintWriter实例,使用println()对浏览器进行字符输出。但是有时候,需要直接对浏览器进行字节输出,这时候可以使用HttpServletResponse的getOutputStream()方法取得ServletOutputStream实例,他是OutputStream的子类。

区分字符流输出和字节流输出,前者主要用来处理文字,包括多国语言的识别。而字节流主要用来处理文字意外的数据,例如二进制文件,图片,PDF文件

java笔记2-servlet-处理请求与响应_第10张图片
Paste_Image.png

这段代码就展示了如果向浏览器输出一个PDF文件,如果浏览器有第三方插件可以在线打开这个字节流pdf文件,那就直接显示,否则提示下载。

  • 重定向

java笔记2-servlet-处理请求与响应_第11张图片
Paste_Image.png
response.sendRedirect("http://xxxxxx.com");

重定向其实也是利用了HTTP状态吗和标头,因此重定向前,不能有响应输出确认,否则会抛出异常

  • 直接输出错误状态(404)

    response.sendError(HttpServletResponse.SC_NOT_FOUND)

你可能感兴趣的:(java笔记2-servlet-处理请求与响应)