Servlet学习笔记4——HTTP协议请求方式与HttpServletRequest对象详解

文章目录

适配器

当前项目中的程序没有使用适配器模式代码丑陋

A、B、C类直接实现接口,其中m1,m2,m3方法是需要使用的,其它方法都给默认空实现,代码丑陋不够优雅!

1、抽取Servlet适配器类型,以后所有的Servlet类不再直接实现Servlet接口了,因为这样代码很丑陋。
可以让以后所有的Servlet继承“Servlet适配器类型”,这样代码会很优雅。

2、Servlet适配器类型除了完成优雅的效果,尽量在该类中提供更多的更方便的方法,供程序员使用。

3、我们这个适配器类起名:GenericServlet【通用的Servlet】

4、测试GenericServlet适配器是否可用


abstract public class Adapter implements CommIn{

	@Override
	abstract public void m1() ;

	@Override
	abstract public void m2() ;

	@Override
	abstract public void m3() ;

	@Override
	public void m4() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void m5() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void m6() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void m7() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void m8() {
		// TODO Auto-generated method stub
		
	}

}

HTTP请求的两种方式

HTTP请求的两种方式,GET和POST请求的表面形式上的区别:

  1. GET请求通过URL(请求行)提交数据,在URL中可以看到所传参数。POST通过“请求体”传递数据,参数不会在url中显示 。
  2. GET请求提交的数据有长度限制(1024或2048),POST请求没有限制(或限制80KB)。
  3. GET请求返回的内容可以被浏览器缓存起来。而每次提交的POST,浏览器在你按下F5的时候会跳出确认框,浏览器不会缓存POST请求返回的内容。

以上描述都是GET,POST两者区别表现形式,是浏览器对这两种请求的处理方式。作为Web开发人员,更应该看清的是它们的本质区别是什么HTTP协议是这样解释GET和POST的:GET请求不应该做读取数据之外的事情(原文:Requests using GET SHOULD NOT have the significance of taking an action other than retrieval)。而如果一个请求,修改了服务器资源或者使用了服务器资源(如发邮件,使用打印机等),那么应当使用POST。所以,GET和POST的本质区别是使用场景的区别,简单的说,GET是只读,POST是写。浏览器对两种请求的不同处理方式也是基于这两个不同的场景:

  1. GET:查询往往需要的上传的数据量比较小,查询参数也往往不需要保密,所以放在url里比较高效。HTTP协议要求同一URL的多个请求应该返回同样的结果,所以浏览器可以把返回结果缓存起来,以提高性能。至于参数长度的限制,这个是和浏览器url的长度限制相关的,1024也好,2048也好,其实没有太大的意义,参数超长往往是错误使用GET方法的结果。
  2. POST:修改数据需要支持大数据量表单的提交,数据也常常包含用户的私人信息,所以数据放在请求的消息体中传递。相同的POST请求可能会对服务器端产生不同的影响,比如两次POST可能创建两条不同的数据,所以对POST返回结果的缓存是没有意义的。

用GET,还是用POST?
如果回答“因为POST的参数长度不受限制,所以我用POST”,就有点本末倒置了。两者之间如何选择,首先要看是不是修改或者使用了服
务器资源,其次要看请求或者响应中的数据是不是包含了敏感信息,如果是,那么应该选择POST,同时处于安全性的考虑,服务器端应该
只接受POST,拒绝GET。比如数据的增加和修改,认证信息的提交,是一定要用POST的。如果只是简单查询,用GET就可以了。

POST请求是不是比GET请求更安全?
有人说“POST比GET安全,因为GET的参数都明文写在url上了”,从个人信息安全的角度上说,这句话是对的,但这种安全机制是“防君
子不防小人”的,有各种工具能够获取POST请求的数据。如前面所说,两者有截然不同的使用场景,如果是该用POST的地方用了GET,
又说GET不安全,那GET也太冤枉了。其实,HTTP协议中提到GET是安全的方法(safe method),其意思是说GET方法不会改变服务器
端数据,所以不会产生副作用。这是建立在Web开发人员正确使用GET方法的基础上的,如果修改数据的请求却使用了GET方法,显然
是非常危险的。

GET与POST的误用有什么危害?
应该使用GET的地方用了POST:性能受损,浏览器不会缓存。
应该使用POST的地方用了GET:每一个这样的地方都是一个漏洞,有可能被黑客利用。如果是一个对安全要求很高的网站,一定不要忽视。
不仅仅是在前端要正确的使用GET和POST,同时还需要后端代码的支持,比如后端应当在需要POST请求的时候拒绝GET请求,从而切
断黑客利用GET请求攻击的途径,更高级别的,还需要对POST请求进行过滤,以确保所有的POST请求都来自可信任的地址。

如何判断当前请求是GET请求还是POST请求?
在浏览器地址栏上直接编写URL提交的请求一定是GET请求。
使用热链接向服务器发送的请求一定是GET请求。
使用form表单提交数据的时候,如果method属性没有编写,或者method属性值被指定是GET,这样发送的请求属于GET请求。
使用form表单提交数据的时候,如果method属性值被手动指定为POST,那么该请求属于POST请求。

思考:我们在做javaweb开发的时候所有的Servlet都要继承HttpServlet类,并且负责重写doGet和doPost方法,假设当前请求是POST请求,而没有重写doPost方法为什么会出现以下异常?

底层是doPost方法表明希望客户端发送的请求是POST请求,如果此时发送的请求是GET请求,则会执行HtttpServlet类中的doGet方法,这样这个方法会报错(上面就是错误)。

该用POST的时候,java的Servlet服务器端代码进行了控制,客户端只能发送POST请求,不嫩发送GET,你只要发GET就报错。

记住:不要随意的编写doPost和doGet,是POST就编写doPost方法,是GET就编写doGet方法。在重写doGet方法和doPost方法的时候一定记住不要再调用super.doGet或者super.doPost等方法。

Http协议详解与GET请求和POST请求的区别

​ 1、HTTP协议是什么?

  • HTTP协议是一种超文本传输协议
  • W3C制定的浏览器和服务器之间提前制定好的一种数据传送格式

2、HTTP协议包括:请求协议和响应协议

  • 请求协议:浏览器向服务器发送数据的时候,数据传送格式
  • 响应协议:服务器向浏览器发送数据的时候,数据传送格式

3、安装httpwatch[IE浏览器的插件]/httplook工具,监测并深度剖析HTTP协议的详细内容。
【javaweb程序员必须精通HTTP协议,只有精通了HTTP协议,才知道在网络中传送的到底是哪些数据】

4、请求协议包括以下四部分:

  • 请求行
  • 消息报头
  • 空白行
  • 请求体

5、请求协议:基于get方式

	GET /prj-servlet-08/user/login?username=admin&password=123 HTTP/1.1					请求行
	Accept: text/html, application/xhtml+xml, */*										消息报头
	Referer: http://localhost:8080/prj-servlet-08/										消息报头
	Accept-Language: zh-CN																消息报头
	User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)			消息报头
	Accept-Encoding: gzip, deflate														消息报头
	Host: localhost:8080																消息报头
	Connection: Keep-Alive																消息报头
																						空白行
																						请求体

​ 注:
​ 第一:请求行由三部分组成:请求方式、URI、协议版本号
​ 第二:若请求是GET请求,在请求行中发送数据,格式:uri?name=value&name=value…
​ 第三:GET请求最终浏览器地址栏上会将提交的数据显示出来

6、请求协议:基于POST方式

POST /prj-servlet-08/user/login HTTP/1.1											请求行
	Accept: text/html, application/xhtml+xml, */*									消息报头
	Referer: http://localhost:8080/prj-servlet-08/
	Accept-Language: zh-CN
	User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
	Content-Type: application/x-www-form-urlencoded
	Accept-Encoding: gzip, deflate
	Host: localhost:8080
	Content-Length: 27
	Connection: Keep-Alive
	Cache-Control: no-cache
																					空白行
	username=admin&password=123														请求体
	
	注:
		第一:请求行由三部分组成:请求方式、URI、协议版本号
		第二:若请求是POST请求,在请求体中发送数据,格式:name=value&name=value.....
		第三:POST请求最终浏览器地址栏上不会将提交的数据显示出来,因为不是在请求行上发送的数据

7、什么时候请求方式是基于POST?

  • 只有一种方式是POST请求,使用form表单提交数据,并且同时form标签的method属性设置为method=“POST”
  • 剩下任何一种请求,一律都是GET方式

8、响应协议包括以下四部分:

  • 状态行
  • 消息报头
  • 空白行
  • 响应体[响应正文]

9、GET和POST只和请求有关系,和响应无关。无论发送的请求是GET请求还是POST请求,响应协议只有一种格式:

	HTTP/1.1 200 OK																	状态行
	Server: Apache-Coyote/1.1														消息报头
	Content-Type: text/html;charset=UTF-8
	Content-Length: 129
	Date: Sat, 30 Jan 2016 03:28:29 GMT
																					空白行
	<html><head><title>login result</title></head><body><h1 align='center'>			响应体
	<font color='red'>login success!</font></h1></body></html>

注:
第一:状态行由三部分组成:协议版本号、响应状态号、状态描述信息

响应状态号:【HTTP协议规定的】

404 资源找不到

500 服务器内部错误

200 请求响应完整成功结束

第二:消息报头包括

响应的服务器版本

响应的内容类型以及字符编码方式

响应长度,字节为单位

响应时间

第三:空白行
分离消息报头和响应体的关建行

第四:响应体会显示到网页中。浏览器解释执行HTML代码

10、GET请求和POST请求有什么区别?怎么选用?

​ GET请求和POST请求在表面上的区别:

GET请求最终提交的数据会显示到浏览器地址栏上,在请求行上提交数据

POST请求在请求体中提交数据,不会显示到浏览器地址栏上

GET请求只能提交普通字符串,因为GET请求在请求行上提交数据

POST请求不但可以提交普通字符串,而且还可以提交图片等文件

GET请求提交的字符串长度有限制,只能提交少量数据,这也是因为GET请求在请求行上提交数据

POST请求提交数据理论上无长度限制,可以提交大数据,这也是因为POST请求在请求体中提交数据

GET请求最终的请求结果,会存放到浏览器缓存中。【支持Cache】

POST请求最终的请求结果,不会被放到浏览器缓存中。【不支持Cache:no cache】
注:缓存是一种优化策略,减少IO,提高程序执行效率的重要手段,浏览器也不例外,为了降低服务器的压力,浏览器也是支持缓存机制的。

GET请求和POST请求怎么选择呢?

大多数都是使用GET请求

提交的数据中有敏感信息,必须使用POST

提交的数据不是普通字符串,例如文件上传,必须使用POST

提交的数据长度过长,必须使用POST

若请求是读取服务器端的资源,一般都是使用GET请求。读取的资源不会频繁的发生变化,所以这种请求有必要缓存起来。以提高访问效率

若请求是修改服务器端的资源,一般都是使用POST请求。因为每一次修改之后的结果大部分都是不一样的,没有必要缓存。

HTTP协议详解

Servlet学习笔记4——HTTP协议请求方式与HttpServletRequest对象详解

1、 请求行:
a) GET(描述该请求采用了什么请求方法),HTTP协议中包含8种请求方法:
GET 请求获取Request-URI 所标识的资源
POST 在Request-URI 所标识的资源后附加新的数据
HEAD 请求获取由Request-URI 所标识的资源的响应消息报头
PUT 请求服务器存储一个资源,并用Request-URI 作为其标识
DELETE 请求服务器删除Request-URI 所标识的资源
TRACE 请求服务器回送收到的请求信息,主要用于测试或诊断
CONNECT 保留将来使用
OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求
b) URI(请求WEB服务器的资源名称)
(一) URI:统一资源标识符(代表这个资源的名称),如:上图中的 /PrjTheHttpProtocol/test?username=admin&userpassword=123
说明:HTTP协议规定GET请求发送数据在URI中发送,格式:uri?name=value&name=value&name=value……
(二) URL:统一资源定位符(不但代表这个资源的名称,而且通过它还可以找到该资源),如:http://ip:port/URI
c) HTTP1.1(当前使用的HTTP协议版本)
2、 请求报头
a) 告诉web服务器浏览器接收的语言版本
b) 请求web服务器的IP地址和端口号
c) Cookies等信息。
3、 空白行(分割请求报头和请求体的专用行)
4、 请求体(由于当前使用的请求方式是GET请求方式,所以请求体中不传送任何数据)

Servlet学习笔记4——HTTP协议请求方式与HttpServletRequest对象详解

1、 请求行:
a) 上图采用POST方式发送请求。
b) 上图URI后边没有任何数据,这是因为采用POST方式提交的缘故。
c) HTTP1.1(当前使用的HTTP协议版本)
2、 请求报头(由于请求是POST请求,所以报头中显示:Cache-Control:no-cache)
3、 空白行(分割请求报头和请求体的专用行)
4、 请求体(由于当前使用的请求方式是POST请求方式,所以数据在请求体中发送,并且格式是:name=value&name=value&name=value……)

1、从此之后不再继承javax.servlet.GenericServlet,直接继承javax.servlet.http.HttpServlet
POST请求,请重写doPost方法
GET请求,请重写doGet方法

2、405错误:表示前端发送的请求方式和后台要求的请求方式不同。请求方式错误

关于模板方法设计模式

​ 在模板类中定义模板方法,在模板方法中规定程序的执行流程,规定核心算法骨架,
​ 具体的实现步骤延迟到子类中完成,在不改变任何算法的前提之下,却可以重新
​ 定义步骤的具体的实现。

​ 这种设计模式使用了java中最简单的继承即可完成。
​ 虽然很简单的设计模式,但是使用广泛。

​ 使用模板方法设计模式,核心算法得到了复用。
​ 核心算法受到保护。

​ HttpServlet是一个模板类,其中service方法是一个模板方法
​ service{
​ doPost();
​ doGet();
​ doPut();
​ …
​ }
​ HttpServlet是一个典型的模板方法设计模式的代表。

​ 注意:模板方法设计模式一般都和doXXX有关.

回顾以前:
1、什么是设计模式?
设计模式是可以重复利用的解决方案
设计模式是一种固定的模型,遇到特定的问题,直接套用模式,解决问题。

2、你听说过的设计模式有哪些?

Gof95设计模式

JavaEE设计模式

3、Gof95设计模式?

1995年Gof四人组共同提出23种设计模式

4、设计模式的分类:

创建型:解决对象的创建问题

行为型:和算法、行为、方法有关系的设计模式

结构型:更多的类、更多的对象组合成更大的结构解决某个特定的问题

5、创建型设计模式:单例模式、工厂模式…

6、行为型设计模式:迭代模式【集合】、策略模式【集合】、模板方法设计模式…

7、结构型设计模式:适配器模式、装饰器模式【IO流】…

HttpServletRequest对象详解

​ javax.servlet.http.HttpServletRequest是SUN制定的Servlet规范,是一个接口。表示请求,“HTTP请求协议”的完整内容都被封装到request对象中,HttpServletRequest接口的父接口是javax.servlet.ServletRequest。
​ Apache软件基金会开发的“Tomcat容器”对javax.servlet.http.HttpServletRequest接口的实现类完整类名是org.apache.catalina.connector.RequestFacade,但是我们javaweb程序员不需要关心具体的请求对象类型,不需要关心是哪个容器,我们只需要面向HttpServletRequest接口调用方法即可。
​ 一次请求对应一个请求对象,请求开始,请求对象被创建,请求结束,请求对象被回收,下一次请求的时候是一个新的请求对象。如何理解一次请求:从用户发送请求开始,到网页最终停下来,这是一次完整的请求(除重定向之外)
​ HttpServletRequest接口中常用的方法
​ 获取参数Map
​ Map<String,String[]> parameterMap = request.getParameterMap();
​ 获取参数Map的所有key,获取所有参数的name
​ Enumeration parameterNames = request.getParameterNames();
​ 通过参数Map集合的key获取参数Map集合的value(value是一个字符串类型的一维数组)用于获取复选框提交的数据
​ String[] parameterValues = request.getParameterValues(String name);
​ 通过用户提交的参数name获取参数value(最常用的方法)
​ String value = request.getParameter(String name);
​ 向HttpServletRequest对象中存储数据(绑定)
​ request.setAttribute(String name,Object obj);
​ 从HttpServletRequest对象中获取数据(读取数据)
​ Object obj = request.getAttribute(String name);
​ 移除HttpServletRequest对象中的数据
​ request.removeAttribute(String name);
​ 使用request对象完成转发(转发是一次请求,一次请求跨越多个Servlet)
​ request.getRequestDispatcher(“资源路径”).forward(request,response);
​ 转发的代码下边不能再编写转发的程序。
​ 转发的下一个资源可能是:JSP、Servlet、HTML等。
​ 获取客户端的IP地址
​ String clientIP = request.getRemoteAddr();
​ 获取URI
​ String uri = request.getRequestURI();
​ 获取URL
​ StringBuffer url = request.getRequestURL();
​ 获取Servlet Path
​ String servletPath = request.getServletPath();
​ 获取应用程序的根路径,获取应用上下文路径
​ String contextPath = request.getContextPath();
​ 解决请求体中的乱码问题(在从request对象中获取任何数据之前设置有效)
​ request.setCharacterEncoding(“GB18030”);
​ 在服务器端获取用户发送的请求中的所有Cookie
​ Cookie[] cookies = request.getCookies();
​ 获取会话对象session
​ HttpSession sessoin = request.getSessoin(); 获取session对象,如果获取不到则开启新session
​ HttpSession sessoin = request.getSession(true); 获取session对象,如果获取不到则开启新session
​ HttpSession sessoin = request.getSession(false); 获取session对象,如果获取不到则返回null

​ HttpServletRequest对象是一个请求级别的对象,一次请求一个对象,所以request对象只能完整在同一次请求中进行数据的传递,可以跨越多个Servlet进行数据的传递,但是必须使用转发机制。如果request对象和ServletContext对象都可以完成此功能,我们优先选择request范围。(到此为止我们已经讲过两个范围对象:ServletContext、HttpServletRequest)。request不能完成跨用户传递数据。只能完成在一次请求中传递数据。
​ 路径总结:
a) 向web服务器发送请求时:Hello Servlet(第一个“/”代表Tomcat服务器根)
b) web.xml文件中:/servlet/hello
c) 通过ServletContext获取文件绝对路径:String realPath = application.getRealPath(“/index.html”);(保证webapp根下有index.html文件)
d) 转发涉及到的路径:request.getRequestDispatcher(“/servlet/hello”).forward(request,response);
总结:目前我们涉及到的所有路径都是以“/”开始,只有在向web服务器发送请求的时候才需要添加“项目名”,其他的路径都是不需要添加项目名。

研究:javax.servlet.http.HttpServletRequest接口

​ 1、javax.servlet.http.HttpServletRequest是一个接口,代表了请求
​ 它的父接口:javax.servlet.ServletRequest

​ 2、javax.servlet.http.HttpServletRequest接口的实现类是:org.apache.catalina.connector.RequestFacade
​ 在Tomcat服务器中:
​ public org.apache.catalina.connector.RequestFacade implements javax.servlet.http.HttpServletRequest{}

​ 3、HttpServletRequest是一个请求对象,该对象中包装了HTTP请求协议的全部信息。
​ 表单提交的数据都在request对象中,面向request可以获取表单中的数据。

​ 4、一次请求对应一个request对象。10次请求对应10个不同的request对象。
​ 什么是一次请求?
​ “目前为止”,在浏览器上点击超链接,到最终浏览器网页停止下来,可以视为一次完整的请求。

​ 5、javax.servlet.http.HttpServletRequest接口中有哪些常用的方法?

String getParameter(String name)

String[] getParameterValues(String name)

Map getParameterMap()

Enumeration getParameterNames()

Object getAttribute(String name)

void setAttribute(String name, Object o)

void removeAttribute(String name)

RequestDispatcher getRequestDispatcher(String path)

String getRemoteAddr()

String getContextPath()

String getMethod()

String getRequestURI()

StringBuffer getRequestURL()

String getServletPath()

javax.servlet.http.HttpServletRequest接口

Object getAttribute(String name)

void setAttribute(String name, Object o)

void removeAttribute(String name)

RequestDispatcher getRequestDispatcher(String path)

注:
request对象:
只要用户发送一个请求,底层就会对应一个request对象。
发送100个请求,底层则对应有100个不同的request对象。

request对象只能完成在同一次请求中数据的共享
无法完成跨请求传递数据/共享数据

request是一个请求范围的对象

javax.servlet.RequestDispatcher接口

void forward(ServletRequest request,ServletResponse response);

回顾:javax.servlet.ServletContext接口 (ServletContext application = config.getServletContext()

上一篇:Day_19 【Java基础】集合Collection(List、Set)


下一篇:重磅 | 物联网数据分析利器 阿里云发布时序数据库InfluxDB版