【JavaWeb-Spring boot】学习笔记
目录
- <<回到导览
- Spring boot
- 1. http协议
- 1.1.请求协议
- 1.2.响应协议
- 2.Tomcat
- 2.1.请求
- 2.1.1.apifox
- 2.1.2.简单参数
- 2.1.3.实体参数
- 2.1.4.数组集合参数
- 2.1.5.日期参数
- 2.1.6.(重点)JSON参数
- 2.1.7.路径参数
- 2.2.响应
- 2.3.综合练习
- 3.三层架构
- 3.1.三层拆分
- 3.2.分层解耦
- 3.3.补充
<<回到导览
Spring boot
Spring boot官网
简介:Spring Boot 基于Spring,简化了配置,降低的入门难度,可以帮助我们非常快速的构建应用程序、简化开发、提高效率
需求:使用 SpringBoot 开发一个web应用,浏览器发起请求 /hello后,给浏览器返回字符串 “Hello World ~”
-
创建spring boot项目(保证网络间接正常)


-
删除一些暂时不用的文件

-
在包下创建文件

-
编写这个文件
// 请求处理类 @RestController public class HelloController {// 表名这个请求处理类,处理的是“/hello”@RequestMapping("/hello")public String Hello() {System.out.println("Hello World");return "Hello World!!!";} }运行启动类(SpringDemoApplication)

-
访问服务
访问
http://localhost:8080/hello或者http://127.0.0.1:8080/hello
每访问一次这个服务,控制台还会打印一次Hello World
1. http协议
概念:Hyper Text Transfer Protocol, 超文本传输协议,规定了浏览器和服务器之间数据传输的规则。
特点:
- 基于TCP协议:面向连接,安全
- 基于请求-响应模型的:一次请求对应一次响应
- HTTP协议是无状态的协议:对于事务处理没有记忆能力。每次请求-响应都是独立的。
- 缺点:多次请求间不能共享数据。
- 优点:速度快
1.1.请求协议
| 请求方式 | 请求参数位置 | 请求大小 |
|---|---|---|
| GET | 在请求行(没有请求体) | 有大小限制 |
| POST | 在请求体 | 没有大小限制 |
-
GET请求

-
POST请求

1.2.响应协议
响应协议和POST请求有些相似,分为响应行、响应头、响应体,响应数据放在响应体里面

| 状态码 | 说明 |
|---|---|
| 1xx | 临时状态码,表示请求已经接收,应该继续请求或者如果它已经完成则忽略它。 |
| 2xx | 成功接收,处理已完成。 |
| 3xx | 重定向到其他地方;让客户端再发起一次请求以完成整个处理。 |
| 4xx | 客户端错误,责任在客户端。(如:请求了不存在的资源、客户端未被授权、禁止访问等。) |
| 5xx | 服务器错误,责任在服务端。(如:程序抛出异常等)。 |
| 常用状态码 | 解释 |
|---|---|
| 200 | 处理成功 |
| 302/304 | location重定向/隐式重定向 |
| 400 | 客户端语法错误 |
| 403 | 服务器拒绝提供服务(没有权限) |
| 404 | 请求资源不存在(url错误) |
| 405 | 请求方式有误 |
| 500 | 服务器发生不可预期的错误 |
| 503 | 服务器尚未准备好处理请求 |
2.Tomcat
Web服务器是一个软件程序,对HTTP协议的操作进行封装,简化web服务器开发
作用:部署web项目,对外提供网上信息浏览服务
Tomcat:一个轻量级的web服务器,支持servlet、jsp等少量avaEE规范。也被称为web容器、servlet容器。
起步依赖:利用maven中依赖传递的特性,把开发某一个功能常见的依赖整合在一起(如web)

在spring boot web开发环境中,已经集成了Tomcat

2.1.请求
2.1.1.apifox
apifox官网:https://app.apifox.com/
apifox使用教程:https://www.bilibili.com/video/BV1Jc41147xC
在使用apifox之前要安装插件Apifox Browser Extension:

尝试用apifox测试接口

2.1.2.简单参数
简单参数:参数名和变量名相同,定义形参即可接收参数
@RestController
public class RequestController {@RequestMapping("/simpleParam")public String simpleParam(String name, int age) {System.out.println(name + ":" + age);return "OK";}
}

如果方法形参名称与请求参数名称不匹配,不能接收值,但是不会报错
这时,可以使用@RequestParam完成映射,但是该注解的required属性默认是true,代表请求参数必须传递
@RestController
public class RequestController {@RequestMapping("/simpleParam")public String simpleParam(@RequestParam(name = "name") String username, int age) {System.out.println(username + ":" + age);return "OK";}
}
2.1.3.实体参数
实体参数:多个参数名和形参变量名相同,定义POJO接收即可
@RestController
public class RequestController {@RequestMapping("/simplePojo")public String simpleParam(User user) {System.out.println(user);return "OK";}
}
public class User{private String name;private int age;// Getter、Setter、toString
}

-
示例
为上面用户添加地址信息(包含省份和城市)
@RestController public class RequestController {@RequestMapping("/complexPojo")public String complexPojo(User user) {System.out.println(user);return "OK";} }public class User{private String name;private int age;private Address address;// Getter、Setter、toString }public class Address {private String province;private String city;// Getter、Setter、toString }
2.1.4.数组集合参数
-
数组参数:请求参数名与形参数组名称相同,定义数组类型形参即可接收参数
@RestController public class RequestController {@RequestMapping("/arrayParam")public String arrayParam(String[] hobby) {System.out.println(Arrays.toString(hobby));return "OK";} }
-
集合参数:请求参数名与形参集合名称相同,通过
@RequestParam绑定参数关系@RestController public class RequestController {@RequestMapping("/listParam")public String listParam(@RequestParam List<String> hobby) {System.out.println(hobby);return "OK";} }
2.1.5.日期参数
日期参数:使用@DateTimeFormat注解完成日期参数格式的转换
@RestController
public class RequestController {@RequestMapping("/dateParam")public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")LocalDateTime updateTime) {System.out.println(updateTime);return "OK";}
}

2.1.6.(重点)JSON参数
JSON参数:JSON数据键名和形参属性名相同,定义POJO类型形参即可接收参数,需要使用@RequestBody标识
在上面的请求中,都是用的GET请求方式,请求参数在请求行,但利用json字符串传参要用POST请求方式,请求参数在请求体
-
例如:
{"name":"Tom","age":18,"address":{"province":"四川","city":"成都"} } -
json参数传递
@RestController public class RequestController {@RequestMapping("/jsonParam")public String jsonParam(@RequestBody User user) {System.out.println(user);return "OK";} }
2.1.7.路径参数
路径参数:通过URL直接传递参数,使用{}来标识该路径参数,需要使用@RequestMapping获取路径参数
@RestController
public class RequestController {@RequestMapping("/pathParam/{id}")public String pathParam(@PathVariable Integer id) {System.out.println(id);return "OK";}
}

-
传递多个路径参数
@RestController public class RequestController {@RequestMapping("/pathParam/{id}/{uid}")public String pathParam(@PathVariable Integer id, @PathVariable Integer uid) {System.out.println(id + "," + uid);return "OK";} }
2.2.响应
@RestController注解包含了@ResponseBody注解@Controller注解
-
统一响应结果:
- 响应码
- 提示信息
- 返回的数据
// Result public class Result {private Integer code ;//1 成功 , 0 失败private String msg; //提示信息private Object data; //数据 datapublic Result() {}public Result(Integer code, String msg, Object data) {this.code = code;this.msg = msg;this.data = data;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}public static Result success(Object data){return new Result(1, "success", data);}public static Result success(){return new Result(1, "success", null);}public static Result error(String msg){return new Result(0, msg, null);}@Overridepublic String toString() {return "Result{" +"code=" + code +", msg='" + msg + '\'' +", data=" + data +'}';} } -
改写请求
@RequestMapping("/simpleParam") public Result simpleParam(String name, int age) {System.out.println(name + ":" + age);return Result.success("Hello World"); }
2.3.综合练习
获取员工数据,返回统一响应结果,在页面中渲染(相关资料可以在黑马官方公众号下载)
-
在pom.xml文件中引入dom4j的依赖,用于解析XML文件
<!-- 解析xml --> <dependency><groupId>org.dom4j</groupId><artifactId>dom4j</artifactId><version>2.1.3</version> </dependency> -
引入资料中提供的解析XML的工具类XMLParserUtils、对应的实体类Emp、XML文件 emp.xml
-
引入资料中提供的静态页面文件,放在resources下的static目录下

-
编写Controller程序,处理请求,响应数据
@RestController public class EmpController {@RequestMapping("/listEmp")public Result list() {// 1. 加载解析xmlString file = "D:\\桌面\\Java\\Java(下)\\spring_demo\\src\\main\\resources\\emp.xml";List<Emp> empList = XmlParserUtils.parse(file, Emp.class);// 2. 对数据进行转换处理empList.forEach(emp -> {String gender = emp.getGender();if("1".equals(gender)) {emp.setGender("男");}else if("2".equals(gender)) {emp.setGender("女");}String job = emp.getJob();if("1".equals(job)) {emp.setJob("教师");}else if("2".equals(job)) {emp.setGender("学生");}});// 3. 响应数据return Result.success(empList);} }
-
尝试发送请求

-
通过浏览器访问前端页面

3.三层架构
在上一节的综合练习中,代码的不同的业务逻辑写在了一起,导致代码复用性差,难以维护

为此设计了三层架构来优化
| 功能分类 | 对应层 | 说明 |
|---|---|---|
| 数据访问 | controller(控制层) | 接收前端发送的请求,对请求进行处理,并响应数据 |
| 逻辑处理 | service(业务逻辑层) | 处理具体的业务逻辑 |
| 接收请求、响应数据 | dao(数据访问层,Data Access Object) | 数据访问操作(包括增、删、改、查) |
controller => service => dao (=>表示调用关系)
3.1.三层拆分
我们将上面三部分的代码分别写到对应层,每个对应层有一个接口(要做的事情),每个接口可以有若干个实现方案(实现类)

-
数据访问层(dao)
// 接口 public interface Empdao {// 获取员工列表public List<Emp> empList(); }// 实现类 public class EmpDaoA implements Empdao {@Overridepublic List<Emp> empList() {// 1. 加载解析xmlString file = "D:\\桌面\\Java\\Java(下)\\spring_demo\\src\\main\\resources\\emp.xml";List<Emp> empList = XmlParserUtils.parse(file, Emp.class);return empList;} } -
业务逻辑层(service)
// 接口 public interface EmpService {public List<Emp> empList(); }// 实现类 public class EmpServiceA implements EmpService {private Empdao empdao = new EmpDaoA();@Overridepublic List<Emp> empList() {// 调用dao层接口List<Emp> empList = empdao.empList();// 2. 对数据进行转换处理empList.forEach(emp -> {String gender = emp.getGender();if("1".equals(gender)) {emp.setGender("男");}else if("2".equals(gender)) {emp.setGender("女");}String job = emp.getJob();if("1".equals(job)) {emp.setJob("教师");}else if("2".equals(job)) {emp.setGender("学生");}});return empList;} } -
控制层(controller)
@RestController public class EmpController {private EmpService empService = new EmpServiceA();@RequestMapping("/listEmp")public Result list() {// 3. 响应数据return Result.success(empService.empList());} }
3.2.分层解耦
- 内聚:软件中各个功能模块内部的功能联系。
- 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
- 软件设计原则:高内聚低耦合
在上节的三层拆分中,三个层级耦合性比较高,我们要降低耦合性
控制反转(IOC):对象的创建控制器由程序自身转移到外部(容器),通过
@Component注解实现
依赖注入(DI):容器为应用程序提供运行时所依赖的资源,通过
@Autowired注解实现
-
Service层、Dao层的实现类,交给IOC容器管理(控制反转)
// Service层 @Component public class EmpServiceA implements EmpService {private Empdao empdao;// ... }// Dao层 @Component public class EmpDaoA implements Empdao {// ... } -
为Controller层、Service层注入运行时依赖的对象(依赖注入)
@RestController public class EmpController {@Autowiredprivate EmpService empService;// ... }// Service层 @Component public class EmpServiceA implements EmpService {@Autowired // 程序在运行时,IOC容器会提供该类型的bean对象,并赋值给该变量private Empdao empdao;// ... }
3.3.补充
| 注解 | 声明 | 位置 |
|---|---|---|
| @Component | bean的基础注解 | 不属于以下三类时,用此注解(eg:工具类) |
| @Controller | @Component的衍生注解 | 标注在控制器类上(@RestController注解已包括,一般不写) |
| @Service | @Component的衍生注解 | 标注在业务逻辑类上 |
| @Repository | @Component的衍生注解 | 标注在数据访问类上(由于与mybatis整合,用的少) |
了解:
- 声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为类名首字母小写。
- 前面声明bean的四大注解,要想生效,还需要被组件扫描注解@ComponentScan扫描。
- @ComponentScan注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解 @SpringBootApplication 中,默认扫描的范围是启动类所在包及其子包。
相关文章:
【JavaWeb-Spring boot】学习笔记
目录 <<回到导览Spring boot1. http协议1.1.请求协议1.2.响应协议 2.Tomcat2.1.请求2.1.1.apifox2.1.2.简单参数2.1.3.实体参数2.1.4.数组集合参数2.1.5.日期参数2.1.6.(重点)JSON参数2.1.7.路径参数 2.2.响应2.3.综合练习 3.三层架构3.1.三层拆分3.2.分层解耦3.3.补充 &…...
SQLmap工具使用
1. sqlmap介绍 sqlmap是一款自动化的SQL注入工具,用于检测和利用web应用程序中的SQL注入漏洞。不需要我们进行手注,当我们输入url地址后,会自动进行注入指令并将payload返回显示。 在kali中自带。在本机中需要下载,在相应的路径…...
OpenCV 实现对形似宝马标的黄黑四象限标定位
文章目录 功能背景代码效果 功能 实现对形似宝马标的黄黑四象限光学识别标定位 背景 大学同学遇到了这个场景,琢磨了下,以备不时之需。 代码 所用opencv版本:4.12 numpy2.2.4 scikit_learn1.6.1import time import cv2 import numpy as…...
2025 年 4 月补丁星期二预测:微软将推出更多 AI 安全功能
微软正在继续构建其 AI 网络安全战略,并于本月宣布在 Microsoft Security Copilot 中引入新代理。 他们引入了用于网络钓鱼分类的代理、用于数据丢失预防和内部风险管理的警报分类、条件访问优化、漏洞修复和威胁情报简报。 这些代理的目标是不断从这些不同学科中…...
从吉卜力漫画到艺术创造:GPT-4o多种风格绘图Prompt大全
在3月底,GPT-4o掀起了一阵吉卜力绘图浪潮,大家纷纷输入一张图片,让4o模型进行风格化迁移,其中吉卜力风格的漫画在社交媒体上最为火热。在大家争议4o的训练数据是否侵权和4o背后的技术原理的时候,我们先来玩一玩&#x…...
resttemplate设置params
如何使用RestTemplate设置请求参数 RestTemplate设置请求参数的方式根据请求类型(GET/POST)和参数形式(路径参数、查询参数、JSON请求体)有所不同,以下是具体实现方法: 一、GET请求参数设置 路径参数 使用…...
16.1Linux自带的LED灯驱动实验(知识)_csdn
前面我们都是自己编写 LED 灯驱动,其实像 LED 灯这样非常基础的设备驱动, Linux 内核已经集成了。 Linux 内核的 LED 灯驱动采用 platform 框架,因此我们只需要按照要求在设备树文件中添加相应的 LED 节点即可,本章我们就来学习如…...
【vLLM】使用 vLLM 对自定义实现模型进行高速推理
推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 介绍什么是 vLLM?处理 vLLM 中的多模态模型实现独特的视频生成模型转换为 vLLM 模型的策略准备输入标记序列如何添加多个多模式输入如…...
SQL Server 数据库实验报告
1.1 实验题目:索引和数据完整性的使用 1.2 实验目的: (1)掌握SQL Server的资源管理器界面应用; (2)掌握索引的使用; (3)掌握数据完整性的…...
在响应式网页的开发中使用固定布局、流式布局、弹性布局哪种更好
一、首先看下固定布局与流体布局的区别 (一)固定布局 固定布局的网页有一个固定宽度的容器,内部组件宽度可以是固定像素值或百分比。其容器元素不会移动,无论访客屏幕分辨率如何,看到的网页宽度都相同。现代网页设计…...
代码随想录算法训练营第三十八天 | 322.零钱兑换 279.完全平方数 139.单词拆分
322. 零钱兑换 题目链接:322. 零钱兑换 - 力扣(LeetCode) 文章讲解:代码随想录 视频讲解:动态规划之完全背包,装满背包最少的物品件数是多少?| LeetCode:322.零钱兑换_哔哩哔哩_b…...
linux提取 Suid提权入门 Sudo提权入门
前言 suid基本使用 Suid 是什么命令? suid 是管理员用户(root)可以对命令文件进行赋权 让其在低权限用户下下也可以保持root权限的执行能力 我现在是管理员我 使用网站用户查找信息的时候总是被阻拦没权限 查找的内容不完整 这个使用我…...
Talib库安装教程
1. 打开 https://github.com/cgohlke/talib-build 2. 点击 Releases 3. 选择对应版本下载(本人电脑win-amd64,python版本3.12) 4. 安装该库(进入该文件路径) pip install ta_lib-0.6.3-cp312-cp312-win_amd64.whl 5…...
TDengine 3.3.6.0 版本中非常实用的 Cols 函数
简介 在刚刚发布的 TDengine 3.3.6.0 版本 中,新增了一个非常实用的 函数COLS ,此函数用于获取选择函数所在行列信息,主要应用在生成报表数据,每行需要出现多个选择函数结果,如统计每天最大及最小电压,并报…...
LeetCode 249 解法揭秘:如何把“abc”和“bcd”分到一组?
文章目录 摘要描述痛点分析 & 实际应用场景Swift 题解答案可运行 Demo 代码题解代码分析差值是怎么来的?为什么加 26 再 %26? 示例测试及结果时间复杂度分析空间复杂度分析总结 摘要 你有没有遇到过这种情况:有一堆字符串,看…...
Python数据可视化-第4章-图表样式的美化
环境 开发工具 VSCode库的版本 numpy1.26.4 matplotlib3.10.1 ipympl0.9.7教材 本书为《Python数据可视化》一书的配套内容,本章为第4章 图表样式的美化 本章主要介绍了图表样式的美化,包括图表样式概述、使用颜色、选择线型、添加数据标记、设置字体…...
ROS Master多设备连接
Bash Shell Shell是位于用户与操作系统内核之间的桥梁,当用户在终端敲入命令后,这些输入首先会进入内核中的tty子系统,TTY子系统负责捕获并处理终端的输入输出流,确保数据正确无误的在终端和系统内核之中。Shell在此过程不仅仅是…...
系统思考:思考的快与慢
在做重大决策之前,什么原因一定要补充碳水化合物?人类的大脑其实有两套运作模式:系统1:自动驾驶模式,依赖直觉,反应快但易出错;系统2:手动驾驶模式,理性严谨,…...
音视频入门基础:RTP专题(21)——使用Wireshark分析海康网络摄像机RTSP的RTP流
一、引言 使用vlc等播放器可以播放海康网络摄像机的RTSP流: 网络摄像机的RTSP流中,RTSP主要用于控制媒体流的传输,如播放、暂停、停止等操作。RTSP本身并不用于转送媒体流数据,而是会通过PLAY方法使用RTP来传输实际的音视频数据。…...
浅谈StarRocks 常见问题解析
StarRocks数据库作为高性能分布式分析数据库,其常见问题及解决方案涵盖环境部署、数据操作、系统稳定性、安全管控及生态集成五大核心领域,需确保Linux系统环境、依赖库及环境变量配置严格符合官方要求以避免节点启动失败,数据导入需遵循格式…...
ASP.NET Core Web API 参数传递方式
文章目录 前言一、参数传递方式路由参数(Route Parameters)查询字符串参数(Query String Parameters)请求体参数(Request Body)表单数据(Form Data)请求头参数(Header Pa…...
04.游戏开发-unity编辑器详细-工具栏、菜单栏、工作识图详解
04.游戏开发,unity编辑器详细-工具栏、菜单栏、工作识图详解 提示:帮帮志会陆续更新非常多的IT技术知识,希望分享的内容对您有用。本章分享的是Python基础语法。前后每一小节的内容是存在的有:学习and理解的关联性,希…...
基于STM32与应变片的协作机械臂力反馈控制系统设计与实现----2.2 机械臂控制系统硬件架构设计
2.2 机械臂控制系统硬件架构设计 一、总体架构拓扑 1.1 典型三级硬件架构 #mermaid-svg-MWmxD3zX6bu4iFCv {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-MWmxD3zX6bu4iFCv .error-icon{fill:#552222;}#mermaid-s…...
【java】在 Java 中,获取一个类的`Class`对象有多种方式
在 Java 中,获取一个类的Class对象有多种方式。Class对象代表了 Java 中的一个类或接口的运行时类信息,可以用于反射操作。以下是获取Class对象的几种常见方法: 1.使用.class属性 每个类都有一个.class属性,可以直接获取该类的Cl…...
QGIS中第三方POI坐标偏移的快速校正-百度POI
1.百度POI: name,lng,lat,address 龙记黄焖鸡米饭(共享区店),121.908315,30.886636,南汇新城镇沪城环路699弄117号(A1区110室) 好福记黄焖鸡(御桥路店),121.571409,31.162292,沪南路2419弄26号1层B间 御品黄焖鸡米饭(安亭店),121.160322,31.305977,安亭镇新源路792号…...
将电脑控制手机编写为MCP server
文章目录 电脑控制手机后,截屏代码复习MCP server构建修改MCP的config文件测试效果困惑电脑控制手机后,截屏代码复习 def capture_window(hwnd: int, filename: str = None) -> dict:""&...
Pycharm 启动时候一直扫描索引/更新索引 Update index/Scanning files to index
多个项目共用一个虚拟环境,有助于加快PyCharm 启动吗 chatgpt 4o认为很有帮助,gemini 2.5pro认为没鸟用,我更认可gemini的观点。不知道他们谁在一本正经胡说八道。 -------- 打开pycharm的时候,下方的进度条一直显示在扫描文件…...
Vanna:用检索增强生成(RAG)技术革新自然语言转SQL
引言:为什么我们需要更智能的SQL生成? 在数据驱动的业务环境中,SQL 仍然是数据分析的核心工具。然而,编写正确的 SQL 查询需要专业知识,而大型语言模型(LLM)直接生成的 SQL 往往存在**幻觉&…...
Unity:标签(tags)
为什么需要Tags? 在游戏开发中,游戏对象(GameObject)数量可能非常多,比如玩家、敌人、子弹等。开发者需要一种简单的方法来区分这些对象,并根据它们的类型执行不同的逻辑。 核心需求: 分类和管…...
如何创建一个自行设计的nginx的Docker Image
目录 前奏问题描述问题解决第一步:设置构建环境第二步:构建BoringSSL第三步:下载并构建Nginx第四步:创建最终镜像 整体的Dockerfile 前奏 你是否曾经想过,亲手打造一个属于自己的Nginx Docker镜像呢? 今天…...
