Java HttpServletRequest中getAttribute()方法和getParameter()区别
一、ServletRequest接口
HttpServletRequest接口继承了ServletRequest接口,实现类通常代表一个实际的Http Request。
Servlet容器负责创建一个HttpServletRequest对象(在Web服务器接收到浏览器的一个请求后),然后Servlet容器把这个HttpServletRequest传递给相关Servlet的service方法。(其实同时创建和传递的还有HttpServletResponse对象,这也是我们在编写相关Servlet时,无须关注request是如何被接收,也无须关注response最终如何被返回,这些都是Servlet容器和Web服务器的职责)
ServletRequest接口,定义了一个能代表实际request的对象,它包含了这个request的各项信息。
一个ServletRequest对象提供的数据包括了parameter name and value,attributes,以及input stream。HttpServletRequest对象还能提供额外的http协议相关的信息(他是唯一的子接口)。
当然接口只是定义了行为规范,Java为其提供了两个基础的实现,以供开发人员扩展:
HttpServletRequestWrapper, ServletRequestWrapper。
二、Request中的parameter 和 attributes
2.1 首先来个大体的区分
Request parameter是客户端提交过来的参数,以“name=value”的字符串形式存储在Request对象中,所以对于parameter,只有getParameter方法。
例如,我们登录时提交账户信息,假如是GET方法提交(实际上不会用GET提交),那么在提交的信息会以"?username=root&password=123456"这种形式附加在表单指向的url后面,这种形式称之为Query String。而POST方式则会把信息放在Request Body当中,这种形式称之为POST Body。
一个有意思的点是,Query string data is presented(显示) BEFORE post body data.
例如,如果使用Query String提交“a=hello”和POST Body提交“a=goodbye“和”a=world”,则结果参数集将被排序为a=(hello, goodbye, world)。
更新:发现我以前讲得不够清楚。可以参考下列网址:
How are parameters sent in an HTTP POST request?
HTTP中application/x-www-form-urlencoded字符说明
在将post表单数据填充到参数集(parameter set)之前,必须满足以下条件:
- The request is an HTTP or HTTPS request.
- The HTTP method is POST.
- The content type is application/x-www-form-urlencoded.
- The servlet has made an initial call of any of the 'getParameter' family of methods on the request object.
如果不满足条件,且post表单数据不包含在参数集中,post数据仍然可以通过request object的输入流提供给servlet。
如果满足这些条件,post表单数据将不再可以直接从请求对象的输入流中读取。
Request attributes则与客户端无关,服务器端接收后产生的一个Request对象,可能在各个不同的Servlet间传递而进行必要的处理,这时我们可以在Servlet A中通过setAttribute(String name,Object)方法存储一些信息,然后在Servlet B中通过getAttribute(String name)方法,取出相关的Object对象,进行一些处理。
API中提到了一点,Attributes are reset between requests,我有点疑惑为什么要特意提这样一句,直观上来说,在不同的Request对象上存储东西,二者当然不会共享吧?所以对Attributes的存储机制开始好奇了。
An attribute is a server variable that exists within a specified scope i.e.:
- application, available for the life of the entire application
- session, available for the life of the session
- request, only available for the life of the request
- page (JSP only), available for the current JSP page only
可以确定的一点是,当代码中出现了setAttribute()方法时,那么这个Request对象必定会与一个RequestDispatcher对象一起工作了,因为你在此处添加了一些有用的数据,肯定要在别处取出来用吧?
2.2 RequestDispatcher接口
先总结,RequestDispatcher接口类用于request的转发。
RequestDispatcher也是一个接口,它定义一个这样的对象:接收来自客户端的request,然后把他们送到服务器的其他资源上去(如servlet,html文件,JSP文件)。所以,通常是Servlet容器创建RequestDispatcher对象,用于包装一个有特定路径或者名称的服务器端资源。
这个接口用于包装servlet,但是servlet容器可以创建RequestDispatcher对象来包装任何类型的资源。
在JDK中,这个接口没有任何子接口和实现类。但是在ServletContext接口(Defines a set of methods that a servlet uses to communicate with its servlet container)中有几个get方法来获得RequestDispatcher对象。
RequestDispatcher接口,也仅有两个方法:
void forward(ServletRequest request, ServletResponse response),把一个request从一个Servlet中转发到服务端的另一处资源(servlet, JSP file, or HTML file)。
该方法允许一个servlet对请求进行初步处理,并允许另一个资源生成响应。
对于通过getRequestDispatcher()获得的RequestDispatcher, ServletRequest对象调整了其路径元素和参数,以匹配目标资源的路径。
forward()方法,应该在将response提交给客户机之前(在response body output被刷新之前)调用。如果response已经被提交了,调用forward()会抛出IllegalStateException。 response缓冲区中未提交的输出,在forward()调用前,会自动被清除。(Uncommitted output in the response buffer is automatically cleared before the forward.)
传递给forward的两个对象,要和servlet中service方法中获得的对象是相同的。即针对的是同一次请求过程。
void include(ServletRequest request, ServletResponse response),这个方法用于向response中添加一些资源(servlet, JSP page, HTML file)。
这里就涉及到ServletResponse对象了,它代表着一个要被返回的Response。ServletResponse对象也由Servlet容器创建,(在这样的一个转发过程中)它的路径元素和参数与调用者的保持不变(The ServletResponse object has its path elements and parameters remain unchanged from the caller's. )而且进行include操作的servlet,无法改变response的状态码,也无法设置header信息,这样的操作会被无视掉。(why?)
这里 include方法的ServletRequest request和ServletResponse response必须与传递给调用该include方法的servlet的service方法的两个ServletRequest request和ServletResponse response是同一对(反正一般也不会自己创建了),或者是包装前面这两个对象的ServletRequestWrapper或ServletResponseWrapper类的子类。
三、ServletResponse接口
3.1
HttpServletResponse接口的父接口,定义一个对象来帮助servlet向客户端发送response。
Servlet容器会创建一个 ServletResponse对象,然后与ServletRequest一起传递给servlet的service方法。
如果要在MIME body response中发送二进制数据,请使用getOutputStream()返回的ServletOutputStream。(什么是MIME)
要发送字符数据,使用getWriter()返回的PrintWriter对象。
要混合二进制和文本数据,例如,创建一个multipart响应,请使用ServletOutputStream并手动管理字符部分。
MIME主体响应的字符集可以使用以下任何一种技术显式指定:
per request, per web-app (using ServletContext.setRequestCharacterEncoding(java.lang.String), deployment descriptor(即web.xml)), and per container (for all web applications deployed in that container, using vendor specific configuration(更改web容器的配置)).
如果使用了前面提到的多种技术,那么优先级就是所列的顺序。
对于每个请求,可以使用本接口中的setCharacterEncoding(java.lang.String)和setContentType(java.lang.String)方法显式地指定响应的字符集,或者隐式地使用setLocale(java.util.Locale)方法 。
显式规范优先于隐式规范。如果没有明确指定字符集,将使用ISO-8859-1。
setCharacterEncoding、setContentType或setLocale方法的调用必须在getWriter之前,并在提交要使用的字符编码的响应之前
3.2 方法
ServletResponse接口定义的方法并不复杂,都和设置response的相关的格式有关,其中的一些会设置reponse header。
四、再谈谈ServletContext接口
前面已经提到过了,ServletContext中定义了一系列方法让servlet与servlet容器打交道,例如获取文件的MIME类型、分派request或写入日志文件。
每个Java虚拟机中的每个“web应用程序”,都有一个上下文(context)。
而一个“Web Application”的定义:
A "web application" is a collection of servlets and content installed under a specific subset of the server's URL namespace, such as /catalog and possibly installed via a .war file.)
对于在部署描述符中标记为“distributed”的web应用程序,每个虚拟机都有一个上下文实例。在这种情况下,上下文不能用作共享全局信息的位置(因为信息不是真正的全局的)。使用外部资源,比如数据库。
ServletContext对象包含在ServletConfig对象中,这个对象用于Web服务器在初始化servlet时提供给servlet。API链接
ServletContext提供的方法,与我们在web.xml中常进行的一些配置相似。如添加Filter、Listener、Servlet等。
Java HttpServletRequest中getAttribute()方法和getParameter()区别的更多相关文章
- 原生js中slice()方法和splice()区别
slice()方法和splice()方法都是原生js中对数组操作的方法. slice(),返回一个新的数组,该方法可从已有的数组中返回选定的元素.例如:arrObject(start,end),sta ...
- Java基础之equals方法和"= ="的区别
==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符. 如果一个变量指向的数据是对象类型的 ...
- 线程中sleep方法和wait方法有什么区别?(转)
本文转自https://www.cnblogs.com/linkstar/p/6043846.html 线程中sleep方法和wait方法有什么区别? 如果你没有接触过java的多线程,那么多对于 ...
- Classloader中loadClass()方法和Class.forName()区别
Classloader中loadClass()方法和Class.forName()都能得到一个class对象,那这两者得到的class对象有什么区别呢 1.java类装载的过程 Java类装载有三个步 ...
- ThinkPHP 中M方法和D方法的具体区别(转)
M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...
- ThinkPHP 中M方法和D方法的具体区别
M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...
- Java提高篇——equals()方法和“==”运算符
equals() 超类Object中有这个equals()方法,该方法主要用于比较两个对象是否相等.该方法的源码如下: public boolean equals(Object obj) { retu ...
- ThinkPHP 中M方法和D方法详解----转载
转载的地址,http://blog.163.com/litianyichuanqi@126/blog/static/115979441201223043452383/ 自己学到这里的时候,不能清除的分 ...
- Java基础系列-equals方法和hashCode方法
原创文章,转载请标注出处:<Java基础系列-equals方法和hashCode方法> 概述 equals方法和hashCode方法都是有Object类定义的. publi ...
随机推荐
- Vue图片浏览组件v-viewer,支持旋转、缩放、翻转等操作
v-viewer 用于图片浏览的Vue组件,支持旋转.缩放.翻转等操作,基于viewer.js. 从0.x迁移 你需要做的唯一改动就是手动引入样式文件: 1 import 'viewerjs/dist ...
- websocket原理、为何能实现持久连接?
WebSocket 是 HTML5 一种新的协议.它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是 ...
- opencv_traincascade级联训练人脸数据
正负样本格式: 正样本 灰度化 24*24 2000张 负样本 灰度化 50*50 1000张 训练过程 第一步:dir /b >pos.txt 以及dir /b >neg.txt ...
- C++ STL Heap算法
#include <iostream>#include <algorithm>#include <vector> using namespace std; int ...
- 5G 与 MEC 边缘计算
目录 文章目录 目录 前言 参考文献 通信网络 核心网演进之路 早古时期 2G 网络架构 3G 网络架构 4G 网络架构 5G 5G 网络的需求 5G 网络架构的设计原则 5G 网络的逻辑架构 5G ...
- PAT 甲级 1021 Deepest Root (25 分)(bfs求树高,又可能存在part数part>2的情况)
1021 Deepest Root (25 分) A graph which is connected and acyclic can be considered a tree. The heig ...
- 免费申请https
https://blog.csdn.net/MariaOzawa/article/details/81877756 实测有效
- 【计算机视觉】MTCNN的windows-cpu配置
前言 MTCNN是级联卷积网络,原理基本上比较清晰,只是还缺少实战,看到一个CSDN上windows的实现过程,就拿来试试. 操作过程 参考here,某些步骤会添加博主遇到的问题的解释. 第一部分:c ...
- flask的jinja2过滤器使用:遍历索引指定标签class属性,实现样式变化
在flask项目中实现上图效果,采用使用自定义过滤器的形式对 span 标签的 class 指定. 1.定义过滤器 # common.py def do_index_class(index): &qu ...
- 通用 spring cloud 微服务模板
说明文档 功能 1. 基于映射数据库一键生成 spring cloud 微服务 2. 通用 Controller ,无需编写代码即可完成基于数据库的服务 3. 动态多条件 CRUD + 分页 使用说明 ...