HTTP总结

Http基础:

1、客户端请求消息
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:

(1)请求行(request line): 用来说明请求类型,要访问的资源以及所使用的HTTP版本。
(2)请求头部(header): 用来说明服务器要使用的附加信息。
(3)空行: 请求头部后面的空行是必须的,即使第四部分的请求数据为空,也必须有空行。(4)请求数据: 请求数据也叫主体,可以添加任意的其他数据。

2、服务器响应消息
HTTP响应也由四个部分组成,分别是:

(1)状态行:由HTTP协议版本号, 状态码(200), 状态消息(OK) 三部分组成。
(2)消息报头: 用来说明客户端要使用的一些附加信息。
(3)空行: 消息报头后面的空行是必须的
(4)响应正文: 服务器返回给客户端的文本信息。

3、HTTP请求方法
HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。

(1)GET:请求指定的页面信息,并返回实体主体。
(2)HEAD:类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
(3)POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
(4)PUT:从客户端向服务器传送的数据取代指定的文档的内容。
(5)DELETE:请求服务器删除指定的页面。
(6)CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
(7)OPTIONS:允许客户端查看服务器的性能。
(8)TRACE:回显服务器收到的请求,主要用于测试或诊断。

4、HTTP状态码(HTTP Status Code)
常见的HTTP状态码:

200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误

5、HTTP状态码分类
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:

(1)1** 信息,服务器收到请求,需要请求者继续执行操作
(2)2** 成功,操作被成功接收并处理
(3)3** 重定向,需要进一步的操作以完成请求
(4)4** 客户端错误,请求包含语法错误或无法完成请求
(5)5** 服务器错误,服务器在处理请求的过程中发生了错误

6、HTTP状态码列表
100 Continue 继续。客户端应继续其请求
101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议

200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
202 Accepted 已接受。已经接受请求,但未处理完成
203 Non-Authoritative Information 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205 Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 Partial Content 部分内容。服务器成功处理了部分GET请求

300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303 See Other 查看其它地址。与301类似。使用GET和POST请求查看
304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy 使用代理。所请求的资源必须通过代理访问
306 Unused 已经被废弃的HTTP状态码
307 Temporary Redirect 临时重定向。与302类似。使用GET请求重定向

400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
402 Payment Required 保留,将来使用
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405 Method Not Allowed 客户端请求中的方法被禁止
406 Not Acceptable 服务器无法根据客户端请求的内容特性完成请求
407 Proxy Authentication Required 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
408 Request Time-out 服务器等待客户端发送的请求时间过长,超时
409 Conflict 服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突
410 Gone 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411 Length Required 服务器无法处理客户端发送的不带Content-Length的请求信息
412 Precondition Failed 客户端请求信息的先决条件错误
413 Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414 Request-URI Too Large 请求的URI过长(URI通常为网址),服务器无法处理
415 Unsupported Media Type 服务器无法处理请求附带的媒体格式
416 Requested range not satisfiable 客户端请求的范围无效
417 Expectation Failed 服务器无法满足Expect的请求头信息

500 Internal Server Error 服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
505 HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理

7、URI和URL
URI:uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。

Web上可用的每种资源如HTML文档、图像、视频片段、程序等都是一个来URI来定位,URI一般由三部组成:
①访问资源的命名机制
②存放资源的主机名
③资源自身的名称,由路径表示,着重强调于资源。

URL:uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。

URL是Internet上用来描述信息资源的字符串,主要用在各种WWW客户程序和服务器程序上,特别是著名的Mosaic。采用URL可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等。URL一般由三部组成:
①协议(或称为服务方式)
②存有该资源的主机IP地址(有时也包括端口号)
③主机资源的具体地址。如目录和文件名等

URN:uniform resource name,统一资源命名,是通过名字来标识资源,比如mailto:java-net@java.sun.com。

URI是以一种抽象的,高层次概念定义统一资源标识,而URL和URN则是具体的资源标识的方式。URL和URN都是一种URI。笼统地说,每个 URL 都是 URI,但不一定每个 URI 都是 URL。这是因为 URI 还包括一个子类,即统一资源名称 (URN),它命名资源但不指定如何定位资源。上面的 mailto、news 和 isbn URI 都是 URN 的示例。

在Java的URI中,一个URI实例可以代表绝对的,也可以是相对的,只要它符合URI的语法规则。而URL类则不仅符合语义,还包含了定位该资源的信息,因此它不能是相对的。

在Java类库中,URI类不包含任何访问资源的方法,它唯一的作用就是解析。相反的是,URL类可以打开一个到达资源的流。

8、Session和cookie
(1)web会话: 用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,程序要想办法为每个用户保存这些数据。

(2)test Session和cookie

cookie由服务器生成,发送给浏览器,浏览器把cookie以 K-V 形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。

Cookie的格式Set-Cookie: NAME=VALUE;Expires=DATE;Path=PATH;Domain=DOMAIN_N AME;
NAME=VALUE是每一个Cookie均必须有的部分。NAME是该Cookie的名称,VALUE是该Cookie的值。在字符串“NAME=VALUE”中,不含分号、逗号和空格等字符。 VALUE可以是基本类型也可以是复杂数据类型(对象)。在服务端一次只可以返回给客户端一个cookie。即一个name和value。

在控制层,所有http进行的通信,参数都可以有HttpServletRequest request和HttpServletResponse response或者其他参数。

浏览过的网页,就会产生COOKIE,以便于你下次进入同一个页面的时候,浏览器直接从cookie中读出信息,这样访问速度就会很快。在浏览器中清除cookie等,并没有清除session哦! 清除了cookie之后,服务端request.getCookies()得到的cookies为空。

Session从字面上讲,就是会话。这个就类似于你和一个人交谈,你怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征(长相等)表明他就是张三。

session 也是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户端分配不同的“身份标识”,然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,可以有很多种方式,对于浏览器客户端,大家都默认采用 cookie 的方式。

服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对cookie来说更安全,可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。

获取session里的信息是通过存放在会话cookie里的session_id获取的。而session是存放在服务器的内存中里,所以session里的数据不断增加会造成服务器的负担,所以会把很重要的信息存储在session中,而把一些次要东西存储在客户端的cookie里。

服务端生成这个全局的唯一标识,传递给客户端用于唯一标记这次请求,也就是cookie中标示的session_id;而服务器创建的那个map结构就是session。所以,**cookies中session_Id由服务端生成,用于标记客户端的唯一标识,**无特定含义,在每次网络请求中,都会被传送。服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁 (session销毁机制是服务器端决定的)。

如果要用到session,浏览器第一次访问服务器会在服务器端生成一个session。得到sessionId之后通过设置其Attribute。

Demo测试:
用session和cookie实现用户的登录和登出时。
功能:在用户登录之前判断服务端的session中的isLogin属性值,如果该属性值为yes,则表示用户已经登录过了,不用再次登录,否则提示该用户要登录。
通过测试可知,只要浏览器端不清除cookies的值,request请求的sessionId都是一样的,不会发生变化。当在浏览器中清除cookies值之后,request请求的sessionId值会发生变化,所以服务端会要求其再次进行登录。如果执行logout操作,logout会把isLogin的值设置成no,再次登录时,和发现在服务端的sessionId值还是和之前一样的,只是该session对应的attribute值变了导致需要重新登录,其实sessionId的值是没有改变的。

当清除浏览器cookie后,sessionID的值该变了 请求头中携带的cookie中为空,因此服务端会再次给客户端生成新的sessionId。sessionId是和浏览器的请求挂钩的,当请求刷新了,对应的请求的sessionId也会改变,所以在清除浏览器记录时,浏览器会提示“执行当前操作会导致您从大多数网页退出”。

Session是保存在服务器内存中的,当服务重启之后,客户端再次请求时的sessionId也会发生变化。因此当服务重启之后,用户需要重新登录。 <如果session丢失,那么客户端需要重新登录。但是其实如果服务器将session做到这种地步,那用户的体验感会非常查,其实可以将session存入redis服务器中,这样就算服务端重启,再次连接redis库即可,session信息不会丢失>

Http实践:

1、spring中的http实现
在Control方法中,参数都是有HttpServletRequest和HttpServletResponse的,通过HttpServletRequest可以得到请求的很多数据。

Interface HttpServletRequest implements ServletRequest;

2、HttpClient
实现了所有HTTP的方法(GET,POST,PUT,HEAD 等);支持自动转向;支持 HTTPS 协议;支持代理服务器等。

背景:

一般的情况下我们都是使用浏览器来访问一个WEB服务器,用来浏览页面查看信息或者提交一些数据等等。当在某些时候需要通过程序来访问这样的一些页面,比如从别人的网页中拿一些数据;利用某些站点提供的页面来完成某种功能,例如说我们想知道某个手机号码的归属地而我们自己又没有这样的数据,因此只好借助其他公司已有的网站来完成这个功能,这个时候我们需要向网页提交手机号码并从返回的页面中解析出我们想要的数据来。

Commons-httpclient项目就是专门设计来简化HTTP客户端与服务器进行各种通讯编程。通过它可以让原来很头疼的事情现在轻松的解决,例如你不再管是HTTP或者HTTPS的通讯方式,告诉它你想使用HTTPS方式,剩下的事情交给httpclient替你完成。

3、RestTemplate
spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。

在Spring应用程序中访问第三方REST服务与使用Spring RestTemplate类有关。RestTemplate类的设计原则与许多其他Spring *模板类(例如JdbcTemplate、JmsTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。

RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。

考虑到RestTemplate类是为调用REST服务而设计的,因此它的主要方法与REST的基础紧密相连就不足为奇了,后者是HTTP协议的方法:HEAD、GET、POST、PUT、DELETE和OPTIONS。例如,RestTemplate类具有headForHeaders()、getForObject()、postForObject()、put()和delete()等方法。

RestTemplate包含以下几个部分:

HttpMessageConverter 对象转换器

ClientHttpRequestFactory 默认是JDK的HttpURLConnection

ResponseErrorHandler 异常处理

ClientHttpRequestInterceptor 请求拦截器

restTemplate在调用远程服务的时候如何提交多个数据,比如一个基本数据类型和一个对象??<早上弄了好久,以后弄不出来的东西就暂且放一放,等之后再弄呀>

可以用json来解决这个问题,将对象转换成json字符串格式,然后进行传输。

Spring 中借助 RestTemplate使用Rest资源

模版方法将过程中与特定实现相关的部分委托给接口,而这个接口的不同实现定义了接口的不同行为。

RestTemplate定义了36个与REST资源交互的方法,其中的大多数都对应于HTTP的方法。 其实,这里面只有11个独立的方法,其中有十个有三种重载形式,而第十一个则重载了六次,这样一共形成了36个方法。

delete() 在特定的URL上对资源执行HTTP DELETE操作。

exchange() 在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中 映射得到的。

execute() 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象。

getForEntity() 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象。

getForObject() 发送一个HTTP GET请求,返回的请求体将映射为一个对象。

postForEntity() POST 数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的。

postForObject() POST 数据到一个URL,返回根据响应体匹配形成的对象。

headForHeaders() 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头。

optionsForAllow() 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息。

postForLocation() POST 数据到一个URL,返回新创建资源的URL。

put()PUT 资源到特定的URL实际上,由于Post 操作的非幂等性,它几乎可以代替其他的CRUD操作。

4、SpringSession
https://www.cnblogs.com/lxyit/p/9672097.html

要打开本地redis服务(redis-server),在启动springboot项目时,会自动进行redis的连接,由于本机安装的redis没有密码,所以直接不用在application.properties文件中设置密码,设置了反而会错误。

当关闭redis-server时,出现错误,并会开始重新连接:
当再次启动redis时,连接成功。

5、redis
StringRedisTemplate操作redis数据https://www.cnblogs.com/slowcity/p/9002660.html

以<key,value>的形式进行存储

Session指的是某一个站点对应的请求,只有当请求发生变化时才会有改变,比如在另外的浏览器中浏览(更换请求方式:浏览/postman)

登录判断:根据输入的用户名来得到对应的session,判断该session是否可用,该session有对应的属性,若之前登录成功,则会设置相应的属性值,这个时候判断相应的属性值就可以了。(与自定义的登录逻辑有关,不必过于纠结)

在Spring中使用redis

1、添加maven依赖

<!--spring session 与redis应用基本环境配置 -->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

<!--spring boot 与redis应用基本环境配置 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、在项目的启动配置中加入配置项

#在配置redis时需要确保redis安装正确,并且配置notify-keyspace-events Egx,spring.redis.timeout设置为大于0,我当时这里配置为0时springboot时启不起来。
spring.redis.host=127.0.0.1
spring.redis.port=6379
#spring.redis.password=123456
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
#超时一定要大于0
spring.redis.timeout=3000
spring.session.store-type=redis

3、开启redis-server

4、启动项目,会自动连接redis数据库。使用spring封装的StringRedisTemplate进行编程即可

RedisTemplate中定义了5种数据结构操作

redisTemplate.opsForValue(Key,Value);  //操作字符串
redisTemplate.opsForHash();   //操作hash
redisTemplate.opsForList();   //操作list
redisTemplate.opsForSet();    //操作set
redisTemplate.opsForZSet();   //操作有序set
stringRedisTemplate.opsForValue().set("test", "100",60*10,TimeUnit.SECONDS);//向redis里存入数据和设置缓存时间 

常见操作:

stringRedisTemplate.boundValueOps("test").increment(-1);//val做-1操作

stringRedisTemplate.opsForValue().get("test")//根据key获取缓存中的val

stringRedisTemplate.boundValueOps("test").increment(1);//val +1

stringRedisTemplate.getExpire("test")//根据key获取过期时间

stringRedisTemplate.getExpire("test",TimeUnit.SECONDS)//根据key获取过期时间并换算成指定单位

stringRedisTemplate.delete("test");//根据key删除缓存

stringRedisTemplate.hasKey("546545");//检查key是否存在,返回boolean值

stringRedisTemplate.opsForSet().add("red_123", "1","2","3");//向指定key中存放set集合

stringRedisTemplate.expire("red_123",1000 , TimeUnit.MILLISECONDS);//设置过期时间

stringRedisTemplate.opsForSet().isMember("red_123", "1")//根据key查看集合中是否存在指定数据

stringRedisTemplate.opsForSet().members("red_123");//根据key获取set集合

在基于Spring获取properties文件属性值的时候,一般使用@Value的方式注入配置文件属性值,但是总是需要引入这些多余的变量。基于Spring解析@Value的方式,使用EmbeddedValueResolverAware解析配置文件,实现起来也很简单,工具类如下:

public class MyEmbeddedValueResolverAware implements EmbeddedValueResolverAware {
    private StringValueResolver stringValueResolver;
    @Override
    public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
        this.stringValueResolver = stringValueResolver;
    }
    /**
     * 获取属性,直接传入属性名称即可
     */
    public String getPropertiesValue(String key) {
        StringBuilder name = new StringBuilder("${").append(key).append("}");
        return stringValueResolver.resolveStringValue(name.toString());
    }
//   使用方法
//    @Autowired
//    private MyEmbeddedValueResolverAware myEmbeddedValueResolverAware;
//    String s = myEmbeddedValueResolverAware.getPropertiesValue("test.hello");
}

在RedisSession中,虽然有几个自定义的redisSession类里面的方法很多,而且很难懂,但是实际上redisSession只在登录成功之后将session写入到了redis存储器中,1、根据sessionId在redis集群中查询session——findById;2、在redis集群中保存新建的session——save;3、登出的时候删除session——deleteById。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值