Http 头信息

HTTP 头(Header)是一种附加内容,独立于请求内容和响应内容。

HTTP 协议中的大量特性都通过Header信息交互来实现,比如内容编解码、缓存、连接保活等等。

request是代表HTTP请求信息的对象,response是代表HTTP响应信息的对象。

当浏览器发请求访问服务器中的某一个Servlet时,服务器将会调用Servlet中的service方法来处理请求。在调用service方法之前会创建出request和response对象。

其中request对象中封装了浏览器发送给服务器的请求信息(请求行、请求头、请求实体等),response对象中将会封装服务器要发送给浏览器的响应信息(状态行、响应头、响应实体),在service方法执行完后,服务器再将response中的数据取出,按照HTTP协议的格式发送给浏览器。

每次浏览器访问服务器,服务器在调用service方法处理请求之前都会创建request和response对象。(即,服务器每次处理请求都会创建request和response对象)

在请求处理完,响应结束时,服务器会销毁request和response对象。

如下面的一个请求响应:

Request

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Host: www.cnblogs.com
If-Modified-Since: Wed, 18 Jul 2023 13:47:45 GMT
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36

Response

Cache-Control: private, max-age=10
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Wed, 18 Jul 2023 13:47:51 GMT
Expires: Wed, 18 Jul 2023 13:48:01 GMT
Last-Modified: Wed, 18 Jul 2023 13:47:51 GMT
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Frame-Options: SAMEORIGIN
X-UA-Compatible: IE=10

SpringBoot 处理头信息

获取指定请求头

通过@RequestHeader注解方式将请求头信息映射到参数,如下:

@GetMapping("/header")
@ResponseBody
public String getHeader(@RequestHeader(value = "Host") String host,
@RequestHeader(value = "User-Agent") String userAgent,
@RequestHeader(value = "Cache-Control", required = false) String cacheControl,
HttpServletResponse response) { logger.info("host:{}", host);
logger.info("User-Agent:{}", userAgent);
logger.info("Cache-Control:{}", cacheControl); // 设置响应头
response.setHeader("Cache-Control", "no-cache,no-store,must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0); return "OK";
}

而响应头呢,可以通过声明一个HttpServletResponse参数后,通过该对象进行设置。

获取全部请求头

如果希望获得全部的请求头,可以使用HttpHeaders对象:

@GetMapping("/all")
public ResponseEntity<Map<String, List<String>>> allHeaders(@RequestHeader HttpHeaders headers) {
Map<String, List<String>> valueMap = new HashMap<String, List<String>>();
for (String header : headers.keySet()) {
valueMap.put(header, headers.get(header));
logger.info("header[{}]={}", header, headers.get(header));
}
// 通过ResponseEntity设置响应头
ResponseEntity<Map<String, List<String>>> entity = ResponseEntity.status(HttpStatus.OK)
.header("new header", UUID.randomUUID().toString()).body(valueMap);
return entity;
}

上面的一段代码中,可以将所有请求头信息全部打印出来。

此外还须注意到,返回响应使用了ResponseEntity对象,这是一个用于直接表示响应信息头、内容的对象,利用ResponseEntity可以很方便的设置响应头信息。

Cookie处理

Cookie一开始服务器用于辨别用户信息而记录在浏览器上的信息。到目前为止Cookie作为客户端的存储有了非常多的应用场景。

获取指定参数

SpringBoot 提供了 @CookieValue 以支持参数方式注入,如下:

@GetMapping("/cookie")
@ResponseBody
public String getCookie(@CookieValue(value = "counter", defaultValue = "0") int counter,HttpServletResponse response) {
logger.info("counter:{}", counter);
counter += 1;
String newValue = counter + "";
// 设置Cookie
response.addCookie(new Cookie("counter", newValue));
return newValue;
}

上述代码中,访问/cookie 可以获得一个counter的cookie值,且每访问一次则自增一次,这是一个简单的访问计数器功能。

获取全部参数

如果希望获取全部的Cookie,可以参考以下代码:

@GetMapping("/all")
public ResponseEntity<Map<String, String>>allCookies(HttpServletRequest request, HttpServletResponse response) {
Map<String, String> valueMap = new HashMap<String, String>();
for (Cookie cookie : request.getCookies()) {
valueMap.put(cookie.getName(), cookie.getValue());
logger.info("cookie[{}]={}", cookie.getName(), cookie.getValue());
}
// 设置Cookie
response.addCookie(new Cookie("key", UUID.randomUUID().toString()));
return new ResponseEntity<Map<String, String>>(valueMap, HttpStatus.OK);
}

清理全部Cookie

@GetMapping("/clear")
public ResponseEntity<Map<String, String>> clearCookies(HttpServletRequest request, HttpServletResponse response) {
Map<String, String> valueMap = new HashMap<String, String>();
for (Cookie cookie : request.getCookies()) {
valueMap.put(cookie.getName(), cookie.getValue());
logger.info("cookie[{}]={}", cookie.getName(), cookie.getValue());
// 清除
cookie.setMaxAge(0);
response.addCookie(cookie);
}
return new ResponseEntity<Map<String, String>>(valueMap, HttpStatus.OK);
}

Cookie机制存在一定的缺陷,尽可能在考虑一些风险后使用。

1、安全性无法保证,除非使用HTTPS;

2、浏览器端只有4KB大小的存储上限;

Session处理

Session 指的是会话,是建立于Cookie机制上的一种身份识别方式。

由于Cookie自身的安全性和容量限制,大多数应用中是在Cookie中存放一个唯一凭证;

服务侧通过凭证再进行身份信息的存取,这就是会话的由来。

不同的语言、框架采用的实现方式有些差异,比如JavaEE采用JSESSION_ID,而PHP则是PHPSESSID。

Session的交互原理可以参考下面一个图:



Springboot 内嵌了Servlet容器,则是沿用的JSESSION_ID。因此在浏览一些JavaWeb站点时会发现该Cookie。

使用@SessionAttribute可以将会话中的属性映射到方法参数;

如果希望对Session属性进行操作,可以在Controller上声明 @SessionAttributes 注解以指定想要变更的属性;

之后,通过Model参数进行写入即可(由框架自动检测并修改Session)

获取单个会话

@SessionAttributes("seed")
public class SessionController {
private static final Logger logger = LoggerFactory.getLogger(SessionController.class); @GetMapping("/session")
@ResponseBody
public String getSession(@SessionAttribute(value = "seed", required = false) Integer seed, Model model) {
logger.info("seed:{}", seed);
if (seed == null) {
seed = (int) (Math.random() * 10000);
} else {
seed += 1;
}
model.addAttribute("seed", seed);
return seed + "";
}
}

上面的例子与Cookie实现访问计数器的功能是一样的!

获取全部会话

如果希望获取全部会话,可以使用HttpSession

@GetMapping("/all")
public ResponseEntity<Map<String, Object>> allSessions(HttpSession session) {
Map<String, Object> valueMap = new HashMap<String, Object>();
Enumeration<String> iSession = session.getAttributeNames();
while (iSession.hasMoreElements()) {
String sessionName = iSession.nextElement();
Object sessionValue = session.getAttribute(sessionName);
valueMap.put(sessionName, sessionValue);
logger.info("sessoin[{}]={}", sessionName, sessionValue);
}
// 写入session
session.setAttribute("timestmap", new Date());
return new ResponseEntity<Map<String, Object>>(valueMap, HttpStatus.OK);
}

清除会话

@GetMapping("/clear")
public ResponseEntity<Map<String, Object>> clearSessions(HttpSession session) {
Map<String, Object> valueMap = new HashMap<String, Object>();
Enumeration<String> iSession = session.getAttributeNames();
while (iSession.hasMoreElements()) {
String sessionName = iSession.nextElement();
Object sessionValue = session.getAttribute(sessionName);
valueMap.put(sessionName, sessionValue);
logger.info("sessoin[{}]={}", sessionName, sessionValue);
session.removeAttribute(sessionName);
}
return new ResponseEntity<Map<String, Object>>(valueMap, HttpStatus.OK);
}

Flash参数传递

Flash的意思是一瞬间,一闪而过的,因此很好理解,这是一类仅用来消费一次的参数,有些类似阅后即焚。

试想这样的场景,你确认完购物车,完成订单支付后进入订单管理界面,而此时界面上提示你"下单成功,请等待发货"。

这便可以通过Flash传参来实现。

Flash的意义是用作请求之间的瞬时参数传递,仅消费一次后便不再用。

以下是一个示例:

/**
* 执行跳转,并设置传值
*
* @param counter
* @param response
* @return
*/
@GetMapping("/first")
public String first(final RedirectAttributes redirectAttrs) {
logger.info("redirect start:{}");
redirectAttrs.addFlashAttribute("flash", UUID.randomUUID().toString());
return "redirect:/flash/second";
} /**
* 获取传值
*
* @param session
* @param response
* @return
*/
@GetMapping("/second")
@ResponseBody
public String second(@ModelAttribute("flash") String flash) {
logger.info("redirect receive {}", flash);
return flash;
}

交互原理



Sprintboot中Flash机制也是利用Session实现的,其中FlashMapManager接口实现了Flash参数的管理。

默认的实现是SessionFlashMapManager,可以通过RequestContextUtils获得上下文中的FlashMapManager对象。

RequestContextUtils通过Request Scope(请求上下文)存取对象。

这也是一个本文未提及的scope域,Request上下文是利用线程变量实现的,通常用于线程内业务处理的数据交互。

SpringBoot获取请求头信息的更多相关文章

  1. jsp获取请求头信息

    <%@ page language="java" import="java.util.*" contentType="text/html; ch ...

  2. springmvc 获取请求头信息

    @PostMapping("/test/post") public void post(@RequestBody String params, @RequestHeader(req ...

  3. JAVA Serverlet 请求头信息和响应头信息

    <1>获取请求头信息 //获取请求头信息的全部名称 Enumeration<String> header = request.getHeaderNames(); while(h ...

  4. RequestFacade对象获取请求头时忽略大小写

    也许在Controller层 在RequestFacde文件中getHeader函数逻辑实现如下所示: public String getHeader(String name) { if(this.r ...

  5. js获取HTTP的请求头信息

    以下为js获取HTTP的全部请求头信息: var req = new XMLHttpRequest(); req.open('GET', document.location, false); req. ...

  6. PHP获取客户端请求头信息

    获取HTTP请求头信息 Apache 如果web服务器用的是apache,可以直接用php的库函数getallheaders() Nginx 如果web服务器用的是nginx,则无法直接使用getal ...

  7. 0057 Spring MVC如何获取HTTP请求头信息--URL中的动态参数--@RequestHeader--@CookieValue--@PathVariable

    获取HTTP请求头信息 一个HTTP请求除了有参数和实体内容外还有HTTP请求头信息,Spring MVC也可以获取这部分信息 @RequestHeader解可以将请求头信息映射到处理方法的形参上 @ ...

  8. post请求后获取不到请求头信息的原因

    在前台获取数据时,因为没有条件,所以不用传数据,用的post请求.再添加token验证时想着前端在请求时直接添加一个请求头信息就ok 没想到后台却获取不到请求头信息,打印了下日志发现是null,这是怎 ...

  9. PHP获取http头信息和CI中获取HTTP头信息的方法

    CI中获取HTTP头信息的方法: $this->input->request_headers() 在不支持apache_request_headers()的非Apache环境非常有用.返回 ...

  10. js获取response头信息

    当我们使用ajax发起请求时,经常需要获取请求返回的头信息.默认情况下,js货可以获取如下头信息: Cache-Control Content-Language Content-Type Expirs ...

随机推荐

  1. 密码学—重合指数法Python程序

    重合指数(Ic) 计算重合指数就是用来验证在Kasiski测试法中猜测出来的各种密钥长度哪一个才是最接近真实密钥长度的. 计算重合指数步骤 按照Kasiski测试法猜测的密钥长度分组 ↓ 分好组之后将 ...

  2. JDK源码阅读-------自学笔记(十九)(容器概念初探和泛型概念)

    简介 数组存在的优势和劣质 优势 数组是线性序列,从效率和类型检查的角度讲,数组是最好的 劣势 不灵活,数组的大小是预先定义好的,不会随意改变 引入容器 容器这个概念就是装东西的介质,可以理解为能装东 ...

  3. JDBC连接MySQL 8时报错:MySQLNonTransientConnectionException: Public Key Retrieval is not allowed

    需要设置属性 IDEA DBerver

  4. OpenNESS NTS 的前世今生

    目录 文章目录 目录 NEV SDK NEV SDK 的软件架构 NEV SDK 的持续演进 OpenNESS NTS NTS 在 VM 场景中的应用 NTS 在 Container 场景中的应用 N ...

  5. avue-crud字段之间的动态交互效果以及接口数据的获取赋值

    一.form表单下拉表单类型字段数据获取 1.通过配置系统字典接口获取数据并渲染 { label: "经纪人", prop: "broker", type: & ...

  6. 用STM32F4的DMA实现高速、实时的同步并行通信——以读取高速ADC为例[原创www.cnblogs.com/helesheng]

    大概6-7年前,在网上看到过一篇用STM32F1的DMA控制GPIO输出高速数字波形的帖子.觉得很有意思,就自己试了试:控制GPIO输出波形翻转的速度最高只能达到3-4MHz,且容易受到STM32F1 ...

  7. redis 的下载与安装

    下载地址:https://github.com/MicrosoftArchive/redis/releases 选择免安装包: 解压到路径  D:\Redis-x64-3.0.504 用管理员权限打开 ...

  8. 二进制安装Kubernetes(k8s)v1.30.1

    二进制安装Kubernetes(k8s)v1.30.1 https://github.com/cby-chen/Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 kubernetes(k ...

  9. vue-cli 单文件组件 工具安装

    https://cli.vuejs.org/zh/ 在很多 Vue 项目中,我们使用 Vue.component 来定义全局组件,紧接着用 new Vue({ el: '#container '}) ...

  10. kettle从入门到精通 第三十六课 kettle carte 集群

    1.carte服务可以单体运行也可以集群方式运行,今天我们一起来学习下carte的集群模式部署和使用.本次示例用一个master和两个slave从节点演示. carte-config-master-8 ...