SpringBoot(二)--- SpringBoot基础(http协议、分层解耦)

目录

前言

一、SpringBoot入门

1.入门程序

2.解析

二、HTTP协议

1.HTTP概述

2.HTTP请求协议

2.1 GET方式的请求协议

2.2 POST方式的请求协议

2.3 两者的区别

2.4 获取请求数据

3.HTTP响应协议

三、分层解耦

1.三层架构

2.IOC&DI

2.1 入门

2.2 IOC详解

2.3 DI详解

2.4 注意事项


前言

我们可以通过HTML、CSS、JS这三项技术进行前端页面的开发,最终,这些前端页面,我们就可以部署在服务器上,然后打开浏览器就可以直接访问服务器上部署的前端页面了。而像这HTML、CSS、JS 以及图片、音频、视频等这些资源,我们都称为静态资源。 所谓静态资源,就是指在服务器上存储的不会改变的数据,通常不会根据用户的请求而变化。

与静态资源相对的就是动态资源,即在服务器端进行存储,会根据用户请求和其他数据动态生成,内容可能会在每次请求时都发生变化。我们可以基于Spring框架来构建动态资源

对于java程序开发的动态资源来说,我们通常会将这些动态资源部署在Tomcat(Tomcat服务器),这样的Web服务器中运行。 而浏览器与服务器在通信的时候,基本都是基于HTTP协议的。


一、SpringBoot入门

1.入门程序

在com.example.demo这个包下创建HelloController类

类中的代码如下:

package com.example.demo;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController// 表明是个请求处理类
public class HelloController {@RequestMapping("/hello") // 标识请求路径public String hello(String name) {System.out.println("HelloController...hello:" + name);return "Hello" + name;}
}

上面的hello方法中参数是前端给服务器提交的参数,return表示服务器给前端返回的数据。

运行SpringBoot自动生成的引导类 (标识有@SpringBootApplication注解的类)

打开浏览器,输入http://localhost:8080/hello?name=xiaoming

可以发现,前端页面在网址栏向服务器传递了xiaoming这个参数,然后服务器将这个参数重新相应给了前端页面。

2.解析

我们发现运行SpringBoot自动生成的引导类就可以启动整个服务,这是为什么呢?

因为我们在创建springboot项目的时候,选择了web开发的起步依赖 spring-boot-starter-web。而spring-boot-starter-web依赖,又依赖了spring-boot-starter-tomcat,由于maven的依赖传递特性,那么在我们创建的springboot项目中也就已经有了tomcat的依赖,这个其实就springboot中内嵌的tomcat。

而运行引导类中的main方法,其实启动的就是springboot中内嵌的Tomcat服务器。 而我们所开发的项目,也会自动的部署在该tomcat服务器中,并占用8080端口号 。

二、HTTP协议

1.HTTP概述

HTTP:Hyper Text Transfer Protocol(超文本传输协议),规定了浏览器与服务器之间数据传输的规则。

  • http是互联网上应用最为广泛的一种网络协议

  • http协议要求:浏览器在向服务器发送请求数据时,或是服务器在向浏览器发送响应数据时,都必须按照固定的格式进行数据传递

HTTP协议

  • 基于TCP协议: 面向连接,安全。

  • 基于请求-响应模型: 一次请求对应一次响应(先请求后响应)。

  • HTTP协议是无状态协议: 对于数据没有记忆能力。每次请求-响应都是独立的

        无状态指的是客户端发送HTTP请求给服务端之后,服务端根据请求响应数据,响应完后,不会记录任何信息。

2.HTTP请求协议

浏览器将数据以请求格式发送到服务器。包括:请求行、请求头 、请求体。

2.1 GET方式的请求协议

  • 请求行(以上图中红色部分) :HTTP请求中的第一行数据。由:请求方式资源路径协议/版本组成(之间使用空格分隔)

    • 请求方式:GET

    • 资源路径:/brand/findAll?name=OPPO&status=1

      • 请求路径:/brand/findAll

      • 请求参数:name=OPPO&status=1

        • 请求参数是以key=value形式出现

        • 多个请求参数之间使用&连接

      • 请求路径和请求参数之间使用?连接

    • 协议/版本:HTTP/1.1

  • 请求头(以上图中黄色部分) :第二行开始,上图黄色部分内容就是请求头。格式为key: value形式

    • http是个无状态的协议,所以在请求头设置浏览器的一些自身信息和想要响应的形式。这样服务器在收到信息后,就可以知道是谁,想干什么了

服务端可以根据请求头中的内容来获取客户端的相关信息,有了这些信息服务端就可以处理不同的业务需求。

2.2 POST方式的请求协议

  • 请求行(以上图中红色部分):包含请求方式、资源路径、协议/版本

    • 请求方式:POST

    • 资源路径:/brand

    • 协议/版本:HTTP/1.1

  • 请求头(以上图中黄色部分)

  • 请求体(以上图中绿色部分) :存储请求参数

    • 请求体和请求头之间是有一个空行隔开(作用:用于标记请求头结束)

2.3 两者的区别

2.4 获取请求数据

web服务器对HTTP请求进行解析,并将其数据封装到了HttpServletRequest类里面,并在调用Controller方法的时候传递给了该方法。

用HttpServletRequest类型 声明一个形参(例如request),用request的方法操作具体数据。

@RestController
public class RequestController {/*** 请求路径 http://localhost:8080/request?name=Tom&age=18* @param request* @return*/@RequestMapping("/request")public String request(HttpServletRequest request){//1.获取请求参数 name, ageString name = request.getParameter("name"); // 请求数据以键值对形式存在String age = request.getParameter("age");System.out.println("name = " + name + ", age = " + age);//2.获取请求路径String uri = request.getRequestURI();String url = request.getRequestURL().toString();System.out.println("uri = " + uri);System.out.println("url = " + url);//3.获取请求方式String method = request.getMethod();System.out.println("method = " + method);//4.获取请求头String header = request.getHeader("User-Agent");System.out.println("header = " + header);return "request success";}}

3.HTTP响应协议

服务器将数据以响应格式返回给浏览器。包括:响应行 、响应头 、响应体

  • 响应行(以上图中红色部分):响应数据的第一行。响应行由协议及版本响应状态码状态码描述组成

    • 协议/版本:HTTP/1.1

    • 响应状态码:200

    • 状态码描述:OK

  • 响应头(以上图中黄色部分):响应数据的第二行开始。格式为key:value形式

    • http是个无状态的协议,所以可以在请求头和响应头中设置一些信息和想要执行的动作,这样,对方在收到信息后,就可以知道你是谁,你想干什么

  • 响应体(以上图中绿色部分): 响应数据的最后一部分。存储响应的数据

    • 响应体和响应头之间有一个空行隔开(作用:用于标记响应头结束)

关于响应状态码,我们主要有以下三个状态码:

  • 200 ok 客户端请求成功

  • 404 Not Found 请求资源不存在

  • 500 Internal Server Error 服务端发生不可预期的错误

三、分层解耦

1.三层架构

我们进行程序设计以及程序开发时,尽可能让每一个接口、类、方法的职责更单一些(单一职责原则)。尽量满足高内聚、低耦合的要求。

我们在项目开发中,可以把代码分为三层,如图所示:

  • Controller:控制层。接收前端发送的请求,对请求进行处理,并响应数据。

  • Service:业务逻辑层。处理具体的业务逻辑。

  • Dao:数据访问层(Data Access Object),也称为持久层。负责数据访问操作,包括数据的增、删、改、查。这一层主要是进行数据库的处理。

基于三层架构执行流程如图所示:

  • 前端发起的请求,由Controller层接收(Controller响应数据给前端)

  • Controller层调用Service层来进行逻辑处理(Service层处理完后,把处理结果返回给Controller层)

  • Serivce层调用Dao层(逻辑处理过程中需要用到的一些数据要从Dao层获取)

  • Dao层操作文件中的数据(Dao拿到的数据会返回给Service层)

2.IOC&DI

  • 控制反转: Inversion Of Control,简称IOC对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。对象的创建权由程序员主动创建转移到容器(由容器创建、管理对象)。这个容器称为:IOC容器或Spring容器。

  • 依赖注入: Dependency Injection,简称DI容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。程序运行时需要某个资源,此时容器就为其提供这个资源。

      • bean对象:IOC容器中创建、管理的对象,称之为:bean对象。

       

      2.1 入门

      在实现类加上 @Component 注解,就代表把当前类产生的对象交给IOC容器管理。

      来看下面的代码:

      A. UserDaoImpl

      @Component
      public class UserDaoImpl implements UserDao {@Overridepublic List<String> findAll() {InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());return lines;}
      }

      B. UserServiceImpl

      @Component
      public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;@Overridepublic List<User> findAll() {List<String> lines = userDao.findAll();List<User> userList = lines.stream().map(line -> {String[] parts = line.split(",");Integer id = Integer.parseInt(parts[0]);String username = parts[1];String password = parts[2];String name = parts[3];Integer age = Integer.parseInt(parts[4]);LocalDateTime updateTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));return new User(id, username, password, name, age, updateTime);}).collect(Collectors.toList());return userList;}
      }

      发现UserServiceImpl这个类中声明了接口UserDao,但是它并没有创建接口的实现类对象,就是因为实现类UserDaoImpl加了@Component 注解,把当前类产生的对象交给了IOC容器管理。而在UserServiceImpl这个类中声明的接口UserDao上有@Autowired注解,它可以自动从IOC容器中取出实现类的相关对象。

      2.2 IOC详解

      IOC控制反转,就是将对象的控制权交给Spring的IOC容器,由IOC容器创建及管理对象。IOC容器创建的对象称为bean对象。

      而Spring框架为了更好的标识web应用程序开发当中,bean对象到底归属于哪一层,又提供了@Component的衍生注解:

      注意1:声明bean的时候,可以通过注解的value属性指定bean的名字,如果没有指定,默认为类名首字母小写。

      注意2:使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能用@Controller。

      2.3 DI详解

      依赖注入,是指IOC容器要为应用程序去提供运行时所依赖的资源,而资源指的就是对象。

      在入门代码中,我们使用了@Autowired这个注解,完成了依赖注入的操作,而这个Autowired翻译过来叫:自动装配。@Autowired注解,默认是按照类型进行自动装配的(去IOC容器中找某个类型的对象,然后完成注入操作)

      @Autowired 进行依赖注入,常见的方式,有如下三种:

      a) 属性注入

      @RestController
      public class UserController {//方式一: 属性注入@Autowiredprivate UserService userService;}

      b). 构造函数注入

      @RestController
      public class UserController {//方式二: 构造器注入private final UserService userService;@Autowired //如果当前类中只存在一个构造函数, @Autowired可以省略public UserController(UserService userService) {this.userService = userService;}}   

      3). setter注入

      /*** 用户信息Controller*/
      @RestController
      public class UserController {//方式三: setter注入private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}}    

      第一种是最常用的,因为代码最为简洁。

      2.4 注意事项

      那如果在IOC容器中,存在多个相同类型的bean对象,会出现什么情况呢?

      在下面的例子中,准备了两个UserService的实现类,并且都交给了IOC容器管理。 代码如下:

      启动项目之后,控制台报错了

      出现错误的原因是因为在Spring的容器中,UserService这个类型的bean存在两个,框架不知道具体要注入哪个bean使用,所以就报错了。

      对于上述问题,有以下解决方案:

      方案一:使用@Primary注解

      当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现。

      @Primary
      @Service
      public class UserServiceImpl implements UserService {
      }

      方案二:使用@Qualifier注解

      指定当前要注入的bean对象。 在@Qualifier的value属性中,指定注入的bean的名称。 @Qualifier注解不能单独使用,必须配合@Autowired使用。

      @RestController
      public class UserController {@Qualifier("userServiceImpl")@Autowiredprivate UserService userService;
      }

      方案三:使用@Resource注解

      @RestController
      public class UserController {@Resource(name = "userServiceImpl")private UserService userService;
      }

      @Autowird 与 @Resource有什么区别?

      • @Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解

      • @Autowired 默认是按照类型注入,而@Resource是按照名称注入

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

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

      相关文章

      Please install it with pip install onnxruntime

      无论怎么安装都是 Please install it with pip install onnxruntime 我python 版本是3.11 &#xff0c;我换成3.10 解决了

      【数据结构入门训练DAY-35】棋盘问题

      本次训练聚焦于使用深度优先搜索&#xff08;DFS&#xff09;算法解决棋盘上的棋子摆放问题。题目要求在一个可能不规则的nn棋盘上摆放k个棋子&#xff0c;且任意两个棋子不能位于同一行或同一列。输入包括棋盘大小n和棋子数k&#xff0c;以及棋盘的形状&#xff08;用#表示可放…

      【日常笔记】wps如何将值转换成东西南北等风向汉字

      在WPS表格中&#xff0c;若要将数值&#xff08;如角度值&#xff09;转换成“东、南、西、北”等风向汉字&#xff0c;可通过以下步骤结合自定义函数或条件判断实现&#xff1a; 一、wps如何将值转换 方法一&#xff1a;使用LOOKUP函数&#xff08;简化公式&#xff09;&…

      Web性能优化的未来:边缘计算、AI与新型渲染架构

      一、边缘计算与性能优化深度整合 1.1 边缘节点计算卸载策略 • 智能任务分割:将非关键路径计算卸载到边缘节点 // 客户端代码 const edgeTask = new EdgeTask(image-processing); edgeTask.postMessage(imageData, {transfer

      spring中的EnvironmentPostProcessor接口详解

      前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 EnvironmentPostProcessor 是 Spring Boot 提供的一个关键扩展接口&#xff0c;允许开发者在 Spring 应用环境初始化后、应用上下文创建前&…

      Vue3知识点梳理

      注&#xff1a;纯手打&#xff0c;如有错误欢迎评论区交流&#xff01; 转载请注明出处&#xff1a;https://blog.csdn.net/testleaf/article/details/148056625 编写此文是为了更好地学习前端知识&#xff0c;如果损害了有关人的利益&#xff0c;请联系删除&#xff01; 本文章…

      C++23 新增的查找算法详解:ranges::find_last 系列函数

      文章目录 引言C Ranges 库简介ranges::find_last、ranges::find_last_if 和 ranges::find_last_if_not 概述ranges::find_last示例代码代码解释 ranges::find_last_if函数签名参数解释示例代码代码解释 ranges::find_last_if_not示例代码代码解释 使用场景总结 引言 在 C 的发…

      DW_DMAC简介

      基本概念&#xff1a; DMA&#xff1a;全称direct memory access&#xff0c;即直接存储器访问。dma可以在中央处理器CPU不参与的情况下&#xff0c;实现外设和内存之间的数据直接传输&#xff0c;从而提高数据传输效率 外设与计算机内存之间的数据传输&#xff0c;一般可通过…

      信号量基础入门:并发控制的核心概念

      问题的复杂性产生的根本原因在于&#xff0c;如 2.2 节所述&#xff0c;共享变量的访问始终是“单向信息流”。也就是说&#xff0c;一个进程可以分配新值或检查当前值&#xff0c;但这种检查不会为其他进程留下任何痕迹。结果是&#xff0c;当一个进程想要对共享变量的当前值作…

      (十九)Java集合框架深度解析:从基础到高级应用

      一、集合框架概述 1.1 什么是集合框架 Java集合框架(Java Collections Framework, JCF)是Java语言中用于表示和操作集合的一套标准化体系结构。它提供了一组接口、实现类和算法&#xff0c;用于存储和操作对象组&#xff0c;解决了数组在存储对象时的诸多限制。 集合框架的主…

      Blender cycles烘焙贴图笔记

      下载了一些枪模型&#xff0c;一个模型有七八个材质&#xff0c;一个扳机、准星还有单独的材质&#xff0c;用的贴图只有一小部分有内容&#xff0c;对Draw Call非常不友好。不得不学一下怎么用Blender减材质。 找到了这个视频如何在Blender中将多种材料多张贴图烘焙成一张贴图…

      mysql的高可用

      1. 环境准备 2台MySQL服务器&#xff08;node1: 192.168.1.101&#xff0c;node2: 192.168.1.102&#xff09;2台HAProxy Keepalived服务器&#xff08;haproxy1: 192.168.1.103&#xff0c;haproxy2: 192.168.1.104&#xff09;虚拟IP&#xff08;VIP: 192.168.1.100&#x…

      鸿蒙 系统-安全-程序访问控制-应用权限管控

      Ability Kit 提供了一种允许应用访问系统资源&#xff08;如&#xff1a;通讯录等&#xff09;和系统能力&#xff08;如&#xff1a;访问摄像头、麦克风等&#xff09;的通用权限访问方式&#xff0c;来保护系统数据&#xff08;包括用户个人数据&#xff09;或功能&#xff0…

      算法-数对的使用

      1、数对可用于数组排序中&#xff0c;并且可记忆化排序前的元素下标 #include<iostream> #include<string> #include<bits/stdc.h> using namespace std; typedef long long ll; const int N 2e5 10; pair<int, int> a[N]; void solve() {ll n;cin …

      Linux基础第四天

      系统之间文件共享 想要实现两个不同的系统之间实现文件共享&#xff0c;最简单的一种方案就是设置VMware软件的共享文件夹&#xff0c;利用共享文件夹可以实现linux系统和windows系统之间的文件共享&#xff0c;这样就可以实现在windows系统上编辑程序&#xff0c;然后在linux系…

      Docker 核心原理详解:Namespaces 与 Cgroups 如何实现资源隔离与限制

      #Docker疑难杂症解决指南# Docker 作为容器化技术的代名词,彻底改变了软件的开发、部署和管理方式。它凭借其轻量、快速、一致性强的特性,成为了现代云原生架构的基石。然而,Docker 容器的神奇之处并非“无中生有”,其背后是 Linux 内核的两大核心技术——Namespaces(命名…

      GitHub 趋势日报 (2025年05月14日)

      本日报由 TrendForge 系统生成 https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日整体趋势 Top 10 排名项目名称项目描述今日获星总星数语言1xming521/WeClone&#x1f680;从聊天记录创造数字分身的一站式解决方案&…

      【Go】从0开始学习Go

      文章目录 从0开始学习Go0 与C对比1 代码框架1.1 helloworld式代码示例1.2 主体代码元素&#xff08;核心三部分&#xff09;1.3 其他 2 与C/C区别3 有用的小工具4 注意事项 从0开始学习Go 0 与C对比 特性CGo编译型语言需要编译为机器码直接编译为二进制可执行文件静态类型类型…

      简单说一下 Webpack分包

      最近在看有关webpack分包的知识&#xff0c;搜索了很多资料&#xff0c;感觉这一块很是迷惑&#xff0c;网上的资料讲的也迷迷糊糊&#xff0c;这里简单总结分享一下&#xff0c;也当个笔记。 如有错误请指出。 为什么需要分包 我们知道&#xff0c;webpack的作用&#xff0c…

      使用Python和FastAPI构建网站爬虫:Oncolo医疗文章抓取实战

      使用Python和FastAPI构建网站爬虫&#xff1a;Oncolo医疗文章抓取实战 前言项目概述技术栈代码分析1. 导入必要的库2. 初始化FastAPI应用3. 定义请求模型4. 核心爬虫功能4.1 URL验证和准备4.2 设置HTTP请求4.3 发送请求和解析HTML4.4 提取文章内容4.5 保存结果和返回数据 5. AP…