《JavaEE进阶》----5.<SpringMVC②剩余基本操作(CookieSessionHeader响应)>

news2024/9/21 14:31:44

Cookie和Session简介。
Spring MVC的

2.请求
Cookie的设置和两种获取方式
Session的设置和三种获取方式。

3.响应

1.返回静态页面

2.返回数据

3.返回HTML片段

4.返回JSON

5.设置状态码

6.设置header

三、(接上文)SpringMVC剩余基本操作

3.2postman请求

3.2.10 获取Cookie和Session

1.理解Cookie

我们知道HTTP协议自身是“无状态”协议。

"无状态" 的含义指的是:

默认情况下 HTTP 协议的客⼾端和服务器之间的这次通信和下次通信之间没有直接的联系.

实际开发中,我们很多时候需要知道请求之间的关联关系。

例如登陆网站成功后,第二次访问的时候服务器就能知道该请求是否是已经登陆过了.

当用户输入用户名和密码点击登录后,服务器响应,这时候登陆成功后,服务器会给用户一个“令牌”,这样下次用户再访问,就会带上“令牌”。服务器就知道这个用户已经登陆过了。

"令牌" 通常就存储在 Cookie 字段中.

此时在服务器这边就需要记录"令牌"信息,以及令牌对应的用户信息,这个就是 Session 机制所做的工作.

2.理解Session

此时在服务器这边就需要记录"令牌"信息,以及令牌对应的用户信息,这个就是 Session 机制所做的工作.

Session就是会话的意思,比如10个浏览器请求同一个服务器(同样的进程)。那么就会产生10个会话。这10个会话,服务器会通过Session来分辨出会话是哪个浏览器请求的。

服务器同⼀时刻收到的请求是很多的.服务器需要清楚的区分每个请求是从属于哪个用户,也就是属于哪个会话,就需要在服务器这边记录每个会话以及与用户的信息的对应关系. Session是服务器为了保存用户信息而创建的⼀个特殊的对象.

 Session的本质就是⼀个 "哈希表",存储了⼀些键值对结构.Key就是SessionID,Value就是用户信息(用户信息可以根据需求灵活设计)。

SessionID就是由服务器生成的,“唯一性”字符。从Session机制角度看来,这个唯一性字符就是SessionID。如果站在登录流程中看待,也可以把这个唯一性字符称作“token”。

3.Cookie 和 Session之间的关系。(举例)


举一个生活中的例子,新生入学,学校会收录学生信息存储在教务系统,并为每一个学生设定学号

存储学生信息示例如下:

001        张三        18        计科1班

002        李四        19        计科1班

003        王五        18        计科1班

这里的信息就相当于Session


而学校存储信息之后,会给学生发学生证。

出入校园,使用学生证来证明学生身份。

这里的学生证就相当于Cookie

注意:

学生证(Cookie):是可以造假。

教务系统信息(Session):一定是真的

4.Cookie和session的区别

5.获取Cookie (两种方式)

①传统写法(可获取所有Cookie)
@RestController
@RequestMapping("/request")
public class RequestController {
    /**
     * 传统方法获取Cookie
     * 每个方法都内置了HttpServletRequest request/HttpServletResponse response对象
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/getCookie")
    public String getCookie(HttpServletRequest request, HttpServletResponse response){
        Cookie[] cookies = request.getCookies();//通过这种方式可以获取Cookie

        //我们使用lambda表达式的方式来打印Cookie。这种写法可以先了解一下。
//        Arrays.stream(cookies).forEach(x->{
//            System.out.println(x.getName() + ":" + x.getValue());
//        });
        //等价于使用foreach循环来打印Cookie
        for (Cookie c: cookies){
            System.out.println(c.getName()+":"+c.getValue());
        }
        return "获取Cookie成功!!!";
    }
}

 

注意,如果Cookie为空,会报异常。因此写法如下。 

    @RequestMapping("/getCookie")
    public String getCookie(HttpServletRequest request, HttpServletResponse response){
        Cookie[] cookies = request.getCookies();//通过这种方式可以获取Cookie
//使用foreach循环来打印Cookie
        if(cookies != null){
            for (Cookie c: cookies){
                System.out.println(c.getName()+":"+c.getValue());
            }
            return "获取Cookie成功!!!";
        }
        return "Cookie为空!";
    }

运行结果 

当我们添加Cookie之后,刷新一下

 

Cookie也被打印在控制台上。从这里也可以看出,Cookie是可以造假,除了通过浏览器造假,通过Postman也是可以造假的。 

②Spring Boot写法(@CookieValue注解获取指定Cookie)

我们使用postman添加几个Cookie,当我们使用传统方式打印Cookie

 

我们得到了所有的Cookie。但是当我们用SpringBoot方式打印。我们只能通过注解 

@CookieValue来或者指定key值的cookie。

    @RequestMapping("getCookie2")
    public String getCookie2(@CookieValue("yang")String yang){
        return "yang:"+yang;
    }

 

 因此使用这两种方法取决于你想要获取

全部Cookie还是

只获得某些Cookie

6.获取Session

①传统写法
    @RequestMapping("setSession")
    public String setSession(HttpServletRequest request){
        HttpSession session = request.getSession();
        session.setAttribute("student","zzx");
        return "设置Session成功!";
    }

    @RequestMapping("getSession")
    public String getSession(HttpServletRequest request){
        HttpSession session = request.getSession();
//默认值为ture,如果Session为null,就创建一个空的Session
        String student = (String) session.getAttribute("student");
        return "登录用户:"+student;
    }

 http://127.0.0.1:1208/request/setSession

http://127.0.0.1:1208/request/getSession

②SpringBoot写法()
I.直接使用内置对象HttpSession session获取Session。
    @RequestMapping("getSession2")
    public String getSession(HttpSession session){
        String student = (String) session.getAttribute("student");
        return "登录用户:"+student;
    }

II.使用注解 (@SessionAttribute)
    @RequestMapping("getSession3")
    public String getSession(@SessionAttribute("student")String student){
        return "登录用户:"+student;
    }

虽然这样写如下代码非常的简短,但是也有一个问题就是如果直接getSession。会报错 

 

没有找到student这个类型。这是因为加了注解之后,这个参数就变成了必传参数,因此不能为空。

如何修改呢,如下: @SessionAttribute(value = "student",required = false)

    @RequestMapping("getSession3")
    public String getSession(@SessionAttribute(value = "student",required = false)String student){
        return "登录用户:"+student;
    }

 

此时就不报错了。 

3.2.11 获取Header

我们请求打印Header。中的 User-Agent 的信息。

它表示用的哪个客户端去请求的。

①传统方式

    @RequestMapping("/getHeader")
    public String getHeader(HttpServletRequest request){
        String userAgent = request.getHeader("User-Agent");
        return "userAgent:"+userAgent;
    }

②SpringBoot方式(@RequestHeader注解) 

    @RequestMapping("/getHeader2")
    public String getHeader2(@RequestHeader("User-Agent")String userAgent){
        return "userAgent:"+userAgent;
    }

 

上图:当我们使用Postman请求。 

 

上图:当我们使用浏览器请求。  

我们只想获取Header信息中的其中的一个,使用SpringBoot方式很方便。

当我们想要获取多个内容,使用SpringBoot方式就需要写很多参数。

因此我们可以使用传统方式更加方便的获取。

 请求完结。

3. 3响应:

在响应中,我们有以下操作:

1.返回静态页面

2.返回数据

3.返回HTML片段

4.返回JSON

5.设置响应头(状态码,编码或者其他header)

我们可以

使用Fiddler来查看请求和响应的数据

执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤⼾,也就是响应.

1.返回静态页面(页面)

首先要有一个静态页面,

创建前端页面index.html(注意路径)。

如果要访问的目录在静态目录static下面,还有其他目录,那么路径url中需要带上这个目录

@Controller
@RequestMapping("/return")
public class ReturnController {
    @RequestMapping("/r1")
    public String r1(){
        return "/index.html";
    }
}

 

 注意: 

1.在SpringBoot中。@RequestMapping中的/是可以被省略的。而return中的/不能省略。

2.当我们想要访问静态页面时,我们需要把原先

@RestController注解改为@Controller

@RestController注解与@Controller的区别和联系

想要返回数据使用:@RestController

想要返回页面使用:@Controller

@RestController = @ResponseBody + @Controller

@Controller:告诉Spring帮我们管理哪些程序,默认返回的是页面

@ResponseBody:表示返回数据

 我们看看注解@RestController的源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

注解解释 

@Target:表示注解的使用范围如上:ElementType.TYPE 表示注解只能修饰类

@Retention:表示注解的生命周期

我们看看注解@Controller的源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

2.返回数据 @ResponseBody注解

源码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {
}

表示返回数据。响应正文里面的内容。

这里区别@RequestBody:是请求正文里面的内容。接收JSON的时候我们经常用到。

它既可以修饰类,也可以修饰方法。

修饰类:表示该类所有的方法,返回的都是数据

修饰方法:表示该方法的返回都是数据。

示例:

    @ResponseBody
    @RequestMapping("/r2")
    public String r2(){
        return "hello ,SpringMVC,我是返回的数据";
    }


 

ps:关于路径中是否有项目名&一个项目部署多个服务/部署多个项目

 

 

3.返回HTML片段(数据)

    @ResponseBody
    @RequestMapping("/r3")
    public String r3(){
        return "<h1>hello ,SpringMVC,我是HTML片段</h1>";
    }

 

 

注意这里文本类型是html。

content-Type:text/html

无论返回的是页面,还是数据。content-Type类型都是html

如果让它返回JSON呢?请往下看。

ps:get和post的区别

get可以被缓存,get是幂等的。不管什么时候请求,得到响应是一样的。

post不可以被缓存。

4.返回JSON(对象,哈希表等键值对格式)

JSON通常也是表示对象,我们返回一个对象试试。

    @ResponseBody
    @RequestMapping("/r4")
    public UserInfo r4(){
        UserInfo userInfo = new UserInfo();
        userInfo.setName("zzx");
        userInfo.setId(9);
        userInfo.setAge(18);
        return userInfo;
    }

 

 

如上如,我们返回对象成功返回了JSON类型的文本。 

content-Type:application/json 

    @ResponseBody
    @RequestMapping("/r5")
    public Map<String,String> r5(){
        HashMap map = new HashMap<>();
        map.put("k1","v1");
        map.put("k2","v3");
        map.put("k3","v3");
        return map;
    }

 

content-Type:application/json 

如上如,使用Map也成功返回了JSON类型的文本。 

    @RequestMapping("/r6")
    public String r6(){
        return "/a.js";
    }

 

 content-Type:application/javascript

成功返回了页面a.js

    @RequestMapping("/r7")
    public String r7(){
        return "/b.css";
    }

 

 content-Type:text/css

成功返回了页面b.css

总结:

在SpringBoot中, content-Type  不需要我们自己设置。

会自动根据我们的返回的结果自行设置。

5.设置状态码(HttpServletResponse)

状态码的设置不影响页面的展示。

错误显示可以自定义的图。也有很多公共的页面格式。

    @ResponseBody
    @RequestMapping("/r8")
    public String r8(HttpServletResponse response){
        response.setStatus(401);
        return "设置状态成功!";
    }

 

6.设置Header(了解)

Http响应报头也会向客户端传递⼀些附加信息,

比如服务程序的名称,请求的资源已移动到新地址等

如:Content-Type、Local等.

这些信息通过@RequestMapping注解的属性来实现

先来看@RequestMapping的源码:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";

    @AliasFor("path")
    String[] value() default {};

    @AliasFor("value")
    String[] path() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};

    String[] consumes() default {};

    String[] produces() default {};
}

简单了解一下它的属性:(了解就好,不用记)

1.value:指定映射的URL

下面这些属性更多的是对请求的限制

2.method:指定请求的method类型,如GET,POST等

3.consumes:指定处理请求(request)的提交内容类型(Content-Type),例如application/json、text/html;

4.produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回

5.Params:指定request中必须包含某些参数值时,才让该方法处理

6.headers:指定request中必须包含某些指定的header值,才能让该方法处理请求

我们前面了解到,在Spring中,content-Type:的类型不需要我们自己设置,不过在工作中可能有时候还需要我们设置。

而且有些 Header 是自定义的。

什么都没写的时候,我们发现只有

这样的如

Content-Type:

Content-Length:

Data:

Keep-Alive:

Connection:

但是我们访问其他网站,就会发现会有许多。有些就是他们自定义的。

设置Content-Type(produce属性):

SpringBoot给我们默认的是 text/html 类型。要想我们自定义,我们就要用到

@RequestMapping的produce属性。下面是我们给它设置成json的代码:

    @ResponseBody
    @RequestMapping(value = "/r9",produces = "application/json")
    public String r9(){
        return "自定义Header中的Content-Type成功!";
    }

那么我们返回的本身就不是json,如果不自定义,那么就是text/html

什么时候会使用这种情况呢?

比如当我们返回{"ok":1}这串数据,是json格式,但是Spring这里默认还是html。这样就可以会对前端造成一定的影响。不过现在前端框架也更新了,可以自动识别为json

通过这样我们也可以在后面写

@RequestMapping(value = "/r9",produces = "application/json;charset = utf-8")

因此也可以同步的设置编码。

自定义Header(HttpServletResponse) 
    @ResponseBody
    @RequestMapping(value = "/r10")
    public String r10(HttpServletResponse response){
        response.setHeader("myHeader","myHeaderValue");
        return "自定义Header成功!";
    }

这就多了一个

myHeader:myHeaderValue


对于SpringMVC来说,掌握了以上3个功能(建立链接+请求+响应)就相当于掌握了SpringMVC. 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2096545.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSAPP Data Lab

CSAPP 的第一个 Lab&#xff0c;对应知识点为书中的第 2 章&#xff08;信息的表示与处理&#xff09;&#xff0c;要求使用受限制的运算符和表达式实现一些位操作。主要分为两个部分&#xff1a;整数部分和浮点数部分。其中整数部分限制较多&#xff0c;比较偏重技巧性&#x…

Red Hat Enterprise Linux 9—Red Hat 9.4Linux系统 Mac电脑虚拟机安装【保姆级教程】

Mac分享吧 文章目录 效果一、下载软件二、安装软件与配置1、安装2、配置 三、查看基本信息安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件 地址&#xff1a;www.macfxb.cn 二、安装软件与配置 1、安装 2、配置 三、查看基本信息 安装完成&#xf…

【国考】特值法

特值法 题干中存在乘除关系&#xff0c;且对应量未知。 例3&#xff1a;甲、乙、丙三个工程队的效率比为6&#xff1a;5&#xff1a;4,现将A、B两项工作量相同的工程交给这三个工程队,甲队负责A工程,乙队负责B工程,丙队参与A工程若干天后转而参与B工程.两项工程同时开工,耗时16…

【PyQt6 应用程序】视频百叶窗效果一键生成模块

在现代的多媒体创作中,音频和视频的结合是提升作品感染力的关键因素之一。尤其是短视频的制作,往往需要根据音频的节奏进行精细的剪辑和特效添加。PyQt6 作为一个功能强大的 Python GUI 库,为我们提供了极大的便利,使得我们可以轻松地创建功能丰富的应用程序。 本教程将一…

J.U.C并发工具集实战及原理分析

​在J.U.C里提供了很多的并发控制工具类&#xff0c;这些工具类可以使得线程按照业务的某种约束来执行。本节包含CountDownLatch、Semaphore、CyclicBarrier等工具类。目的是了解他们基本使用、原理及实际应用。 1. CountDownLatch主题 1.1 CountDownLatch简介 CountDownLat…

ShardingSphere-JDBC实现数据加解密

一、什么是ShardingSphere&#xff1f; ShardingSphere定位为轻量级 Java 框架&#xff0c;在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库&#xff0c;以 jar 包形式提供服务&#xff0c;无需额外部署和依赖&#xff0c;可理解为增强版的 JDBC 驱动&#xff0c;完…

最优化理论(一)

什么是最优化问题 最优化问题是决策问题&#xff0c;选择一下可以执行的策略来使得目标最优。 一个最优化问题包括&#xff1a; 决策变量一个或多个目标函数一个由科兴策略组成的集合&#xff0c;可由等式或者不等式刻画 最优化问题的基本形式&#xff1a; 最优化问题的分类…

upload-labs通关攻略

Pass-1 这里上传php文件说不允许上传 然后咱们开启抓包将png文件改为php文件 放包回去成功上传 Pass-2 进来查看提示说对mime进行检查 抓包把这里改为image/jpg; 放包回去就上传成功了 Pass-3 这里上传php文件它说不允许上传这些后缀的文件 那咱们就可以改它的后缀名来绕过…

Guitar Pro 8.2.1 Build 32+Soundbanks Win/Mac音色库 开心激活版 音乐软件Guitar Pro 8中文破解版

音乐软件Guitar Pro 8中文破解版是一个受吉他手喜爱的吉他和弦、六线谱、BASS 四线谱绘制、打印、查看、试听软件&#xff0c;它也是一款优秀的 MIDI 音序器&#xff0c;MIDI 制作辅助工具&#xff0c;可以输出标准格式的 MIDI。GP 的过人之处就在于它可以直接用鼠标和键盘按标…

过滤器 与 拦截器

文章目录 过滤器 与 拦截器一、过滤器&#xff08;Filter&#xff09;1、特点2、生命周期3、实现4、过滤器链1&#xff09;配置 order2&#xff09;执行顺序 二、拦截器 Inteceptor1、特点2、生命周期3、实现4、拦截器链1&#xff09;配置 order2&#xff09;执行顺序&#xff…

【Linux】保姆级 Linux 常见命令使用

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. Linux 是什么1.1 Linux 是什么1.2 关于 Linux 我们需要学什么 2. 需提前准备的东西2.1 环境 —— 如何获取…

关于PowerDesigner的使用

1.PowerDesigner概述&#xff1a; 1.PowerDesigner是一款开发人员常用的数据库建模工具&#xff0c;用户利用该软件可以方便地制作 数据流程图、概念数据模型 、 物理数据模型 &#xff0c;它几乎包括了数据库模型设计的全过程&#xff0c;是Sybase公司为企业建模和设计提供的…

蓝色炫酷碎粒子HTML5导航源码

源码介绍 蓝色炫酷碎粒子HTML5导航源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 效果预览 源码获取 蓝色炫酷碎粒…

火焰传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 三、程序设计 main.c文件 IR.h文件 IR.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 火焰传感器是一种常用于检测火焰或特定波长&#xff08;760nm-1100nm&#xff09;红外光的传感器。探测角度60左右&am…

MQTT学习:MQTT vs AMQP,mosquitto安装,调试工具mqttfx mqttx

前言 物联网vs互联网? 数据量/数据源:物联网的数据多是设备的自动采集,其数量远远超过互联网,互联网的数据更多是人工生成的 MQTT 协议(Message Queuing Telemetry Transport)vs AMQP 协议(Advanced Message Queuing Protocol)是两种在物联网中广泛使用的协议。 物联网…

推荐一款灵活,可靠和快速的开源分布式任务调度平台

今天给大家推荐一款灵活&#xff0c;可靠和快速的开源分布式任务调度平台——SnailJob。 前言 什么是任务调度&#xff1f; 任务调度&#xff0c;是指在多任务的环境下&#xff0c;合理地分配系统资源&#xff0c;调度各个任务在什么时候&#xff0c;由哪一个处理器处理&…

【简单】 猿人学web第一届 第15题 备周则意怠,常见则不疑

数据接口分析 数据接口 https://match.yuanrenxue.cn/api/match/15 请求时需要携带 page 页码&#xff0c;m为加密参数 cookie中没有加密信息&#xff0c;携带 SessionId请求即可 加密参数还原 查看数据接口对应的 requests 栈 m参数 是通过 window.m() 方法执行后得到的 打上…

分布式系统中的Dapper与Twitter Zipkin:链路追踪技术的实现与应用

目录 一、什么是链路追踪&#xff1f; 二、核心思想Dapper &#xff08;一&#xff09;Dapper链路追踪基本概念概要 &#xff08;二&#xff09;Trace、Span、Annotations Trace Span Annotation 案例说明 &#xff08;三&#xff09;带内数据与带外数据 带外数据 带…

『 C++ 』多线程相关

文章目录 极短临界区互斥锁的短板原子操作类 atomicatomic 原子操作原理 CASCAS 操作解决多线程创建链表的节点丢失问题多线程下的 shared_ptr 智能指针最简单的单例模式 极短临界区互斥锁的短板 如果两个线程同时对一个共享资源变量x进行自增操作将会出现线程安全问题,这个线程…

官方宣布Navicat免费使用!

官方宣布Navicat免费使用&#xff01; 对于开发者和数据库管理员来说&#xff0c;Navicat一直是不可或缺的工具之一。官方宣布Navicat可以免费使用&#xff0c;这无疑是个令人振奋的消息&#xff01;虽然是精简版&#xff0c;但足够日常使用。文末有下载链接。 无论你是管理M…