Spring MVC 响应处理:页面、数据与状态配置详解

Spring MVC 响应处理:页面、数据与状态配置详解

个人主页♡喜欢做梦

欢迎  👍点赞  ➕关注  ❤️收藏  💬评论


目录

🍋响应

🍊定义

🍊返回静态页面

🍋返回数据:@ResponseBody

🍓 @ResponseBody和@RestController的区别

🍋返回JSON

🍋状态码

🍍状态码的定义

🍍设置状态码

🍋设置header

🍋综合性练习

🍉加法计算器

🍉用户登入


🍋响应

🍊定义

响应(Response)是接收方(服务器、服务或设备)针对发送方(客户端)发起的“请求”所返回的反馈信息。

🍊返回静态页面

html代码:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>我是index页面</h1> </body> </html>

代码:

@RestController @RequestMapping("response") public class ResponseController { @RequestMapping("/1") public String method1(){ return "/index.html"; } }

结果:咦?这结果怎么不是我们想要的页面?为什么会这样?那要怎么修改?

这个代码的问题在于@RestController会将返回值直接作为响应体。这里我们需要用到@Controller。

为什么呢?

@Controller:@Controller是承接http请求,完成视图解析,方法返回的字符串会被视图解析器处理,找到对应的页面文件,响应给前端。

@RestController:是@ResponseBody+@Controller的组合注解,核心是直接返回数据,而不是视图,不会做视图解析流程。

那这样就可以了吗

正确代码如下:

@Controller @RequestMapping("response") public class ResponseController { @RequestMapping("/1") public String method1(){ return "/index.html"; } }

🍋返回数据:@ResponseBody

@ResponseBody:他主要用于将方法的返回值直接写入http响应体中,而不是将其解析为视图名称去进行视图跳转。简单来说,就是把你要返回的东西直接原样发给前端,不会当成路径页面瞎找。

 @RequestMapping("/2") @ResponseBody public String method2(){ return "返回数据"; }

如果没有加@ResponseBody,结果如下,有人可能会疑问,那为什么我返回静态页面第一个错误的代码,也可以返回数据。因为第一个错误代码里面使用的是@RestController注解,核心是直接返回数据。

那@ResponseBody和@RestController又有什么区别?

🍓 @ResponseBody和@RestController的区别

对比@RestController@ResponseBody
作用范围只能用在类上只能用在方法上
功能本质相当于@ResponseBody+@Controller的组合,标记一个类,表明该类是一个控制器单独的注解,仅控制方法返回作为响应
使用场景整个类都需要返回数据,一次注解,全类方法生效类用@Controller时,个别方法需要返回数据,逐个方法标记
视图解析不会走视图解析,直接返回数据不会走视图解析,直接返回数据

@RestController就像老师在班群里面通知消息,而@ResponseBody相当于老师个别针对几个同学私信通知消息。

返回HTML片段代码

 @RequestMapping("/4") @ResponseBody public String method4(){ return "<h1>我是一级标题<h1>"; }

看一下结果

不是说好的,@ResponseBody是原样返回字符串吗,为什么这次不是!!!

这里解释一下:是因为浏览器会自动解析html,造成一种“不是原样”返回的错觉。

浏览器收到响应后,发现响应头里的Content-type是text/html(Spring自动推断的),就会按照html的规则进行渲染。

如果想让浏览器不解析,直接显示原样,应该怎么写?

这里需要设置Content-type

可以强制让响应方法变为纯文本,给方法加produces=“text/plain”

代码:

 @RequestMapping(value = "/5",produces = "text/plain") @ResponseBody public String method5(){ return "<h1>我是一级标题<h1>"; }

结果:

🍋返回JSON

UserInfo

public class UserInfo { private String name; private int age; public UserInfo(){ } public UserInfo(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "UserInfo{" + "name='" + name + '\'' + ", age=" + age + '}'; } }

返回json对象代码:

 @RequestMapping("/6") @ResponseBody public UserInfo method6(){ UserInfo userInfo=new UserInfo("lisi",13); return userInfo; }

结果:

🍋状态码

🍍状态码的定义

状态码是http协议中,服务器响应请求时返回的三位数数字,用来快速告知客服端“请求处理结果”,就是请求结果的快捷反馈

分类:

  • 1xx:服务器已收到请求,需继续处理(如100Continue让客户端继续发数据)
  • 2xx:请求成功(200 OK表示请求完成,201 Created表示资源创建成功)
  • 3xx:需客户端进一步操作(301永久重定向,302临时重定向)
  • 4xx:客户端请求有误(400请求语法错误、401需登入、403没权限、404资源找不到)
  • 5xx:服务器处理出错(500服务器内部故障、503服务器忙/维护中)

🍍设置状态码

代码:

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

结果:

🍋设置header

代码:

@RequestMapping("/8") @ResponseBody public String method8(HttpServletResponse response){ response.setHeader("headerkey","headervalue"); return "设置header成功"; }

结果

🍋综合性练习

练习1:

🍉加法计算器

前端代码:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="calc/sum" method="post"> <h1>计算器</h1> 数字1:<input name="num1" type="text"><br> 数字2:<input name="num2" type="text"><br> <input type="submit" value=" 点击相加 "> </form> </body> </html>

前后端交互接口

服务器代码:

@RestController @RequestMapping("/calc") public class CalcController { @RequestMapping("/sum") public String method8(Integer num1,Integer num2){ //如果有其中一个没有参数,直接返回 if(num1 == null || num2 ==null){ return "参数不合法"; } Integer sum=num1+num2; return "<h1>计算机结果:" + sum + "<h1>"; } } 

练习2:

🍉用户登入

我们需要一个前端的输入信息登入界面,然后向后端发送请求进行校验,查询当前账号是否正确。随后在有一个登入状态,展示当前登入的用户名。

1.前端登入页

功能:提供输入框页面,以及通过点击按钮像后端发送请求,进行前后端的交互

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录页面</title> </head> <body> <!--页面--> <h1>用户登录</h1> 用户名:<input name="userName" type="text"><br> 密码:<input name="password" type="password"><br> <input type="button" value="登录" onclick="login()"> <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.7.1.min.js"></script> <script> <!--前后端进行交互--> function login(){ //获取前端数据发送给后端,到时候后端进行校验 //1.请求方式 //2.后端地址 //3.前端数据 //使用jQuery的ajax方法发送请求 $.ajax({ //请求类型 type: "post", //请求后端接口地址 url: "/user/login", //要发送到后端的数据 data: { //获取输入框的值 userName: $("#userName").val(), password: $("#password").val() }, //返回后端校验后的结果 //成功跳转页面 //失败,进行错误提示 //http请求成功的回调函数 //success:是ajax专门为成功响应设计的回调,会自动接收后端返回的正常结果 success: function(result){ //判断后端返回的结果 if(result){ //如果登入成功,跳转页面 location.href="index2.html"; }else{ //否则,返回错误提示 alert("密码错误"); } } }) } </script> </body> </html>

2.后端控制器

功能:提供两个接口,进行接口的校验,查询当前的登入状态。

import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/user") @RestController public class UserController { @RequestMapping("/login") //校验,记录登入状态 public Boolean login(String userName, String password, HttpSession session){ //参数校验:校验用户名和密码是否为空或者不是空字符串 //写法一: // if(userName == null || userName == "" || password == null || password == "" ){ // return false; // } //写法二: //StringUtils.hasLength():校验用户名和密码是否为空或者不是空字符串 if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){ return false; } //校验用户名和密码是否正确 //这里是硬编码,固定用户名为admin和密码为123456,实际数据要从数据库中查询验证 if("admin".equals(userName) && "123456".equals(password)){ //如果校验成功,将用户名存储到会话中 session.setAttribute("userName",userName); return true; } return false; } //查询当前登入状态 @RequestMapping("/getLoginUser") public String getLoginUser(HttpSession session){ //获取会话中存储的值 //如果用户未登入,返回null //如果用户已登入,返回用户名 String userName=(String) session.getAttribute("userName"); return userName; } }

前端首页

功能:查询登入状态,展示用户的登入名

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>用户登录首页</title> </head> <body> 登录人: <span></span> <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.7.1.min.js"></script> <script> $.ajax({ url: "/user/getLoginUser", type: "get", //请求成功后的回调函数 success: function(userName){ //将结果填充到页面 $("#loginUser").text(userName); } }); </script> </body> </html>

Read more

爬虫工程师必备:用Selenium+Python自动获取登录态Cookie的3种实战方案

爬虫工程师的“钥匙串”:三种高可用Selenium Cookie获取方案深度实战 做爬虫,尤其是需要处理用户登录态的爬虫,最让人头疼的往往不是解析页面,而是如何稳定、优雅地拿到那把“钥匙”——身份认证凭证。无论是传统的Cookie,还是现代应用偏爱的Token、Session,获取它们的过程,常常是项目从“玩具级”迈向“生产级”的第一道坎。很多开发者止步于简单的driver.get_cookies(),却在面对复杂登录流程、动态令牌或反爬策略时束手无策。今天,我们不谈那些手动复制粘贴的“玩具”方法,而是聚焦于如何用Selenium构建一套健壮的、可自动化的身份凭证获取体系。这不仅仅是调用一个API,更是一场关于浏览器自动化、网络协议理解与工程化思维的实战。 1. 基础与进阶:超越 get_cookies() 的API获取方案 绝大多数Selenium教程都会告诉你,获取Cookie只需一行代码:cookies = driver.get_cookies()。这没错,但如果你只停留在这一步,可能会错过一半的风景,并踩进无数的坑。

By Ne0inhk
【SpringBoot】一篇文章讲清楚拦截器所有知识

【SpringBoot】一篇文章讲清楚拦截器所有知识

🎬 那我掉的头发算什么:个人主页 🔥 个人专栏: 《javaSE》《数据结构》《数据库》《javaEE》 ⛺️待到苦尽甘来日 文章目录 * 拦截器 * 快速入门 * 定义拦截器 * 注册配置拦截器 * 拦截器详解 * 拦截路径 * 拦截器执行流程 * 登录校验 * 定义注册拦截器 * DispatcherServlet 源码分析 * 适配器模式 拦截器 快速入门 拦截器是 Spring 框架提供的核心功能之一,主要用来拦截用户的请求,在指定方法执行的前后,根据业务需要执行预先设定的代码。 也就是说,拦截器允许开发人员提前定义一些通用逻辑,在用户的请求被处理前、响应返回后执行;也可以在用户请求处理前直接阻止其执行。 在拦截器中,开发人员可以实现应用程序中的一些通用性操作。比如通过拦截器拦截前端发来的所有请求,判断 Session 中是否存在登录用户的信息:如果存在则放行请求,继续处理业务;如果不存在则拦截请求,拒绝后续处理。 就好比上学时进校门出校门需要带出入证,保安就

By Ne0inhk

ROS 2从入门到精通系列(一):什么是ROS2 - 核心概念和架构

ROS 2从入门到精通系列(一):什么是ROS2 - 核心概念和架构 本文是ROS2系列的第一篇,帮助你快速理解ROS2的核心概念和系统架构。 引言 如果你即将学习ROS2或者对机器人开发感兴趣,首先需要理解:什么是ROS2? ROS(Robot Operating System)是一个灵活的框架,用于编写机器人软件。ROS2是其第二代版本,相比ROS1有重大改进。本文将从零开始,帮你建立起对ROS2的全面认识。 一、什么是ROS2? 1.1 ROS2的定义 ROS2 是一个分布式计算框架,专门为机器人应用设计。它提供了: * 硬件抽象 - 屏蔽各类传感器和执行器的底层差异 * 中间件 - 实现进程间通信(IPC)和跨机器通信 * 工具链 - 调试、可视化、模拟等开发工具 * 库和算法 - 常用机器人算法的参考实现 1.2 为什么是ROS2而不是ROS1?

By Ne0inhk
Flutter 组件 ansi_text 适配鸿蒙 HarmonyOS 实战:终端色彩渲染,构建高性能 ANSI 日志高亮与命令行交互架构

Flutter 组件 ansi_text 适配鸿蒙 HarmonyOS 实战:终端色彩渲染,构建高性能 ANSI 日志高亮与命令行交互架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 ansi_text 适配鸿蒙 HarmonyOS 实战:终端色彩渲染,构建高性能 ANSI 日志高亮与命令行交互架构 前言 在鸿蒙(OpenHarmony)生态迈向工业级运维、涉及大量后台守护进程(Daemon)、系统日志审计及开发者工具链(CLI)开发的背景下,如何为枯燥的纯文本终端注入具备视觉层级的色彩与样式,已成为提升调试效率与故障定位速度的“视觉助推器”。在鸿蒙设备这类强调 AOT 极致性能与低级别 shell 交互的环境下,如果应用依然依赖基础的单色字符串输出日志,由于由于信息流极其庞大且缺乏重点,极易由于由于“视觉疲劳”导致关键系统警告或业务异常被淹没在海量数据中。 我们需要一种能够支持 ANSI 转义序列、具备富文本样式(加粗/背景色)且兼容多种终端模拟器的文本渲染方案。 ansi_text 为 Flutter 开发者引入了基于标准

By Ne0inhk