当前位置: 首页 > news >正文

后端工程化 | SpringBoot 知识点

文章目录

    • [SpringBoot] 后端工程化
      • 1 需求
      • 2 开发流程
      • 3 RequestController 类(操作类)
        • 3.1 简单参数(形参名和请求参数名一致)
        • 3.2 简单参数(形参名和请求参数名不一致)
        • 3.3 复杂实体参数
        • 3.4 数组参数
        • 3.5 集合参数
        • 3.6 时间参数
        • 3.7 json参数
        • 3.8 单个路径参数
        • 3.9 多个路径参数
      • 4 RequestController 类(查询类)
        • 4.1 @ResponseBody
        • 4.2 统一响应结果
      • 5 分层解耦
        • 5.1 三层架构
        • 5.2 分层目录及代码
          • 5.2.1 数据访问层
          • 5.2.2 业务逻辑层
          • 5.2.3 控制层
        • 5.3 分层解耦
          • 5.3.1 耦合问题
          • 5.3.2 解耦思路
        • 5.4 IOC & DI
          • 5.4.1 Bean的声明(IOC)
          • 5.4.2 组件扫描(IOC)
          • 5.4.3 DI


[SpringBoot] 后端工程化

1 需求

  • 需求:基于SpringBoot的方式开发一个web应用,浏览器发起请求“/hello”后,给浏览器返回字符串 “Hello World ”。

SpringBoot通信流程-2023-10-2917:12:43.png

2 开发流程

  • 创建SpringBoot工程项目

第一步:用 IDEA 基于Spring官方骨架,创建SpringBoot工程。

SpringBoot工程骨架-2023-10-2917:15:16.png

第二步:选择 SpringBoot 框架版本,勾选web开发相关依赖。

SpringBoot 框架版本-2023-10-2917:17:41.png

  • 定义RequestController类,添加方法hello,并添加注解

在主包名下,创建 controller 包 + pojo 包

SpringBoot项目的架构-2023-10-2917:23:43.png

package com.itheima.controller;
import org.springframework.web.bind.annotation.*;@RestController
public class RequestController {@RequestMapping("/hello")public String hello(){System.out.println("Hello World ~");return "Hello World !";} 
} 
  • 测试运行

运行 SprintBootWebObjectApplication

3 RequestController 类(操作类)

  • 作用:接收前端的表单数据
3.1 简单参数(形参名和请求参数名一致)
  • 前端
- 请求方式:GET
- URL: http://localhost:8080/simpleParam?name=lisi&age=45
  • 后端
@RestController
public class RequestController {// 第1个请求参数: name=Tom   参数名:name,参数值:Tom// 第2个请求参数: age=10     参数名:age , 参数值:10//springboot方式@RequestMapping("/simpleParam")public String simpleParam(String name , Integer age ){//形参名和请求参数名保持一致System.out.println(name+"  :  "+age);return "OK"; //返回数据}
}
3.2 简单参数(形参名和请求参数名不一致)
  • 前端
- 请求方式:GET
- URL: http://localhost:8080/simpleParam?name=lisi&age=45
  • 后端
@RestController
public class RequestController {// 第1个请求参数: name=Tom   参数名:name,参数值:Tom// 第2个请求参数: age=10     参数名:age , 参数值:10//springboot方式@RequestMapping("/simpleParam")public String simpleParam(@RequestParam(name = "name", required = false) String username , Integer age ){// name:请求参数名,required:参数是否必须System.out.println(username+"  :  "+age);return "OK"; //返回数据}
}
3.3 复杂实体参数
  • 前端
- 请求方式:GET
- URL: http://localhost:8080/complexPojo?username=李四&age=10&address.province=背景&address.city=上海
  • 后端
@RestController
public class RequestController {  //springboot方式@RequestMapping("/complexPojo")public String complexPojo(User user) {System.out.println(user);return "ok";}User{private String username;private int age;private Address address;GetSet 方法;ToString 方法;}Address{private String province;private String city;GetSet 方法;ToString 方法;}
}
3.4 数组参数
  • 前端
- 请求方式:GET
- URL: http://localhost:8080/arrayParam?hobby=string&hobby=java&hobby=python
  • 后端
@RestController
public class RequestController {//springboot方式@RequestMapping("/arrayParam")public String arrayParam(String[] hobby) {System.out.println(Arrays.toString(hobby));return "ok,arrayParam";}
}
3.5 集合参数
  • 前端
- 请求方式:GET
- URL: http://localhost:8080/listParam?hobby=string&hobby=java&hobby=python
  • 后端
@RestController
public class RequestController {//springboot方式@RequestMapping("/listParam")public String listParam(@RequestParam List<String> hobby) {System.out.println(hobby);return "ok,listParam";}
}
3.6 时间参数
  • 前端
- 请求方式:GET
- URL: http://localhost:8080/dateParam?date=2023-02-09 12:08:09
  • 后端
@RestController
public class RequestController {//springboot方式@RequestMapping("/dateParam")public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime date) {System.out.println(date);return "ok,dateParam";}
}
3.7 json参数
  • 前端
- 请求方式:POST
- URL: http://localhost:8080/jsonParam
- 请求体:
{"username": "lisi","age": 23,"address": {"province": "beijing","city": "上海"}
}
  • 后端
@RestController
public class RequestController {// 第1个请求参数: name=Tom   参数名:name,参数值:Tom// 第2个请求参数: age=10     参数名:age , 参数值:10//springboot方式@RequestMapping("/jsonParam")public String jsonParam(@RequestBody User user) {System.out.println(user);return "ok,jsonParam";}
}
3.8 单个路径参数
  • 前端
- 请求方式:GET
- URL: http://localhost:8080/path/1000
  • 后端
@RestController
public class RequestController {//springboot方式@RequestMapping("/path/{id}")public String pathParam(@PathVariable Integer id) {System.out.println(id);return "ok,pathParam";}
}
3.9 多个路径参数
  • 前端
- 请求方式:GET
- URL: http://localhost:8080/path/1000/Lisi
  • 后端
@RestController
public class RequestController {//springboot方式@RequestMapping("/path/{id}/{name}")public String pathParam(@PathVariable Integer id, @PathVariable String name) {System.out.println(id);System.out.println(name);return "ok,pathParam";}
}

4 RequestController 类(查询类)

4.1 @ResponseBody
  • 由于 @RestController = @Controller + @ResponseBody ,所以不用重复添加。
4.2 统一响应结果
  • 定义在一个实体类 Result 来包含以上信息。代码如下:
public class Result {private Integer code;//响应码,1 代表成功; 0 代表失败private String msg;  //响应码 描述字符串private Object data; //返回的数据public 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(){return new Result(1,"success",null);}//查询 成功响应(把查询结果做为返回数据响应给前端)public static Result success(Object data){return new Result(1,"success",data);}//失败响应public static Result error(String msg){return new Result(0,msg,null);}
}

5 分层解耦

5.1 三层架构
  • 请求处理、响应数据(Controller):控制层。负责接收页面的请求,给页面响应数据。
  • 逻辑处理(Service):业务逻辑层。负责业务逻辑处理的代码。
  • 数据访问(Dao):数据访问层(Data Access Object),也称为持久层。负责业务数据的维护操作,包括增、删、改、查等操作。

在这里插入图片描述

5.2 分层目录及代码

1698590017953-2023-10-2922:33:38.png

5.2.1 数据访问层
  • 负责数据的访问操作,包含数据的增、删、改、查

  • 数据访问接口

//数据访问层接口(制定标准)
public interface EmpDao {//获取员工列表数据public List<Emp> listEmp();
}
  • 数据访问实现类
//数据访问实现类
public class EmpDaoA implements EmpDao {@Overridepublic List<Emp> listEmp() {//1. 加载并解析emp.xmlString file = this.getClass().getClassLoader().getResource("emp.xml").getFile();System.out.println(file);List<Emp> empList = XmlParserUtils.parse(file, Emp.class);return empList;}
}
5.2.2 业务逻辑层
  • 处理具体的业务逻辑

  • 业务接口

//业务逻辑接口(制定业务标准)
public interface EmpService {//获取员工列表public List<Emp> listEmp();
}
  • 业务实现类
//业务逻辑实现类(按照业务标准实现)
public class EmpServiceA implements EmpService {//dao层对象private EmpDao empDao = new EmpDaoA();@Overridepublic List<Emp> listEmp() {//1. 调用dao, 获取数据List<Emp> empList = empDao.listEmp();//2. 对数据进行转换处理 - gender, jobempList.stream().forEach(emp -> {//处理 gender 1: 男, 2: 女String gender = emp.getGender();if("1".equals(gender)){emp.setGender("男");}else if("2".equals(gender)){emp.setGender("女");}//处理job - 1: 讲师, 2: 班主任 , 3: 就业指导String job = emp.getJob();if("1".equals(job)){emp.setJob("讲师");}else if("2".equals(job)){emp.setJob("班主任");}else if("3".equals(job)){emp.setJob("就业指导");}});return empList;}
}
5.2.3 控制层
  • 接收前端发送的请求,对请求进行处理,并响应数据
@RestController
public class EmpController {//业务层对象private EmpService empService = new EmpServiceA();@RequestMapping("/listEmp")public Result list(){//1. 调用service层, 获取数据List<Emp> empList = empService.listEmp();//3. 响应数据return Result.success(empList);}
}
5.3 分层解耦
5.3.1 耦合问题
  • 内聚:软件中各个功能模块内部的功能联系。

  • 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。

软件设计原则:高内聚低耦合。

高内聚:一个模块中的代码,各个代码块之间关系越紧密,则内聚性越高。

低耦合:软件中各个层、模块之间的依赖(相互关联)性越低,则耦合度越低。

高内聚、低耦合-2023-11-621:24:47.png

5.3.2 解耦思路
  • 解决思路

    1. 提供一个容器,容器中存储一些对象(例:EmpService对象)
    2. controller程序从容器中获取EmpService类型的对象
  • 解耦操作

    • 控制反转:[ Inversion Of Control ],简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。

      对象的创建权由程序员主动创建转移到容器(由容器创建、管理对象)。这个容器称为:IOC容器或Spring容器

    • 依赖注入:[ Dependency Injection ],简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。

      程序运行时需要某个资源,此时容器就为其提供这个资源。

      例:EmpController程序运行时需要EmpService对象,Spring容器就为其提供并注入EmpService对象

5.4 IOC & DI
5.4.1 Bean的声明(IOC)
  • ICO 容器管理:IOC控制反转,就是将对象的控制权交给Spring的IOC容器,由IOC容器创建及管理对象。IOC容器创建的对象称为bean对象。

把某个对象交给IOC容器管理,需要在类上添加一个注解:@Component

注解说明位置
@Component声明bean的基础注解全部类通用注解(除控制类)
@Controller@Component的衍生注解标注在控制器类上
@Service@Component的衍生注解标注在业务逻辑类上
@Repository@Component的衍生注解标注在数据访问类上(由于与mybatis整合,用的少)

  • @RestController = @Controller + @ResponseBody
  • 声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为类名首字母小写。
  • 使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能用@Controller。
5.4.2 组件扫描(IOC)
  • Bean 想要生效,还需要被组件扫描。
// 使用四大注解声明的 Bean,要想生效,还需要被组件扫描注解 @ComponentScan 扫描
@ComponentScan("dao", "com.Jiacheng")
@SpringBootApplication
public class SprintBootWebObjectApplication {public static void main(String[] args) {SpringApplication.run(SprintBootWebObjectApplication.class, args);}
}

:不推荐组件扫描,按照 SprintBoot 项目结构创建目录即可

5.4.3 DI
  • 依赖注入:IOC容器要为应用程序去提供运行时所依赖的资源,而资源指的就是对象。
// 依赖注入:@Autowired注解,按照类型进行自动装配。
@Autowired
private EmpService empService;
  • 依赖冲突:在 IOC 容器中,存在多个相同类型的 Bean 对象,程序运行会报错。
注解说明位置
@Autowired按照类型自动装配 Bean 对象类内
@Primary让当前类的 Bean 生效类上
@Qualifier(“serviceA”)指定注入的 Bean 对象(搭配@Autowired)类内
@Resource(name = “serviceB”)按照 Bean的名称进行注入类内
// 1.@Autowired 注入
@Autowired
private EmpService empService;// 2.@Primary 注入
@Primary
public class EmpServiceA implements EmpService {}// 3.@Qualifier() 注入,指定当前要注入的bean对象
@Autowired
@Qualifier("empServiceA")
private EmpService empService;// 4.@Resource() 注入
@Resource(name = "empServiceB")
private EmpService empService;
  • 面试题 : @Autowird 与 @Resource的区别?
  1. @Autowired 是spring框架提供的注解,而@Resource是JDK提供的注
  2. @Autowired 默认是按照类型注入,而@Resource是按照名称注入

相关文章:

后端工程化 | SpringBoot 知识点

文章目录 [SpringBoot] 后端工程化1 需求2 开发流程3 RequestController 类&#xff08;操作类&#xff09;3.1 简单参数&#xff08;形参名和请求参数名一致&#xff09;3.2 简单参数&#xff08;形参名和请求参数名不一致&#xff09;3.3 复杂实体参数3.4 数组参数3.5 集合参…...

Oracle(15)Managing Users

目录 一、基础知识 1、Users and Security 用户和安全 2、Database Schema 3、Checklist for Creating Users创建用户步骤 二、基础操作 1、创建一个用户 2、OS Authentication 操作系统身份验证 3、Dropping a User 删除用户 4、Getting User Information 获取用户信…...

自动化测试(Java+eclipse)教程

webdriver环境配置 1.下载chromedriver到本地&#xff08;一定要选择和自己浏览器相对应的版本chromedriver下载地址&#xff09; 2.加入到环境变量path中 webdriver工作原理 创建web自动化测试脚本 1.Maven项目创建 File->New->project->(搜索maven)选择maven pr…...

ThreadFactory 实例创建方式

匿名内部类 private final Executor executor;{ThreadFactory threadFactory new ThreadFactory() {Overridepublic Thread newThread(Runnable r) {Thread t new Thread(r);t.setDaemon(true);return t;}};executor Executors.newFixedThreadPool(shops.size(), threadFac…...

【自动化测试】Pytest框架 —— 跳过测试和失败重试

1、Pytest跳过测试用例 自动化测试执行过程中&#xff0c;我们常常出现这种情况&#xff1a;因为功能阻塞&#xff0c;未实现或者环境有问题等等原因&#xff0c;一些用例执行不了&#xff0c; 如果我们注释掉或删除掉这些测试用例&#xff0c;后面可能还要进行恢复操作&#…...

python 时间加法 输出t分钟后的时间

题目&#xff1a; 现在时间是a点b分&#xff0c;请问t分钟后&#xff0c;是几点几分&#xff1f; 输入&#xff1a; 第一行包含一个整数a 第二行包含一个整数b 第三行包含一个整数t 其中&#xff0c;0≤a≤23&#xff0c;0≤b≤59&#xff0c;0≤t&#xff0c;t分钟后还…...

51单片机-串口通信

文章目录 前言1.基础介绍2.串口实战3.4. 前言 1.基础介绍 常见1&#xff0c;2&#xff0c;3,电源 常用方式1 fosc外部晶振 2.串口实战 3. 4....

JAVA微信端医院3D智能导诊系统源码

医院智能导诊系统利用高科技的信息化手段&#xff0c;优化就医流程。让广大患者有序、轻松就医&#xff0c;提升医疗服务水平。 随着人工智能技术的快速发展&#xff0c;语音识别与自然语言理解技术的成熟应用&#xff0c;基于人工智能的智能导诊导医逐渐出现在患者的生活视角中…...

考研408-计算机网络 第二章-物理层学习笔记及习题

第二章 物理层 一 通信基础 1.1 物理层基本概念 1.1.1 认识物理层 物理层目的&#xff1a;解决如何在连接各种计算机的传输媒体上传输数据比特流&#xff0c;而不是具体的传输媒体。 物理层主要任务&#xff1a;确认与传输媒体接口有关的一些特性&#xff0c;需要进行定义标…...

鸿蒙开发工具的汉化

1、下载汉化包 汉化插件下载地址&#xff1a;Chinese (Simplified) Language Pack / 中文语言包 - IntelliJ IDEs Plugin | Marketplace 百度网盘下载地址&#xff1a;链接&#xff1a;百度网盘 请输入提取码 DevEco Studio是基于IDEA223版本&#xff0c;下载汉化包时请注意…...

14:00面试,14:06就出来了,问的问题有点变态。。。。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到5月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…...

如何使用 NFTScan NFT API 在 zkSync 网络上开发 Web3 应用

zkSync 是由 Matter Labs 创建的&#xff0c;是一个以用户为中心的 zk rollup 平台&#xff0c;它是以太坊的第 2 层扩展解决方案&#xff0c;使用 zk-rollups 作为扩展技术&#xff0c;与 optimistic rollups 一样&#xff0c;zk-rollups 将会汇总以太坊主网上的交易并将交易证…...

rust从0开始写项目-读取配置文件

一个项目初始化&#xff0c;总是有几个元素是必不可少的、框架、日志、配置文件等等基本元素。 今天我们主要介绍下怎么获取配置并在全局使用 更多好文。vx. golang技术实验室 专注分享 golang、rust等多语言、中间件及大数据相关内容 Part1一、读取cargo.toml文件内容 Cargo.t…...

Docker的安装以及使用

每次安装Docker都会报一堆错&#xff0c;痛定思痛干脆自己总结一篇&#xff01;&#xff01;&#xff01; Docker的安装 卸载系统自带的旧版本 sudo apt-get remove docker docker-engine docker.io containerd runc 获取软件最新源 sudo apt-get update 安装apt依赖包 s…...

计算机网络学习笔记(五):运输层(待更新)

目录 5.1 概述 5.1.1 TCP协议的应用场景 5.1.2 UDP协议的应用场景 5.2 三大关系 5.2.1 传输层协议和应用层协议之间的关系 5.3 用户数据报协议UDP(User Datagram Protocol) 5.3.1 UDP的特点 5.3.2 UDP的首部 5.4 传输控制协议TCP(Transmission Control Protocol) 5.…...

阿里云99元服务器40G ESSD Entry云盘、2核2G3M带宽配置

阿里云99元服务器新老用户均可以买&#xff0c;你没看错&#xff0c;老用户可以买&#xff0c;活动页面 aliyunfuwuqi.com/go/aliyun 配置为云服务器ECS经济型e实例、2核2G、3M固定带宽、40G ESSD Entry云盘&#xff0c;并且续费不涨价&#xff0c;原价99元即可续费&#xff0c…...

6个机器学习可解释性框架

1、SHAP SHapley Additive explanation (SHAP)是一种解释任何机器学习模型输出的博弈论方法。它利用博弈论中的经典Shapley值及其相关扩展将最优信贷分配与局部解释联系起来. 举例&#xff1a;基于随机森林模型的心脏病患者预测分类 数据集中每个特征对模型预测的贡献由Shap…...

数据结构——B树

文章目录 B树1. 概念2. B树插入分析3.插入过程4. B树插入实现5.B树验证6. B树性能分析7.B树&B*树8. 小结9. B树的运用MyISAMInnoDB 10. 总结 B树 可以用于查询的数据结构非常的多&#xff0c;比如说二插搜索树、平衡树、哈希表、位图、布隆过滤器&#xff0c;但如果需要存…...

java--String

1.String创建对象封装字符串数据的方式 ①方式一&#xff1a;java程序中的所有字符串文字(例如"abc")都为此类的对象 ②方式二&#xff1a;调用String类的构造器初始化字符串对象。 2.String提供的操作字符串数据的常用方法...

ls命令区别

ls -lh:显示详细信息&#xff0c;其中其中文件大小是显示Kb或Mb。 ls -l:也会显示文件大小&#xff0c;只是显示的是字节。...

宠物车载安全座椅市场报告:解读行业趋势与投资前景

一、什么是宠物车载安全座椅&#xff1f; 宠物车载安全座椅是一种专为宠物设计的车内固定装置&#xff0c;旨在保障宠物在乘车过程中的安全性与舒适性。它通常由高强度材料制成&#xff0c;具备良好的缓冲性能&#xff0c;并可通过安全带或ISOFIX接口固定于车内。 近年来&…...

ABB馈线保护 REJ601 BD446NN1XG

配电网基本量程数字继电器 REJ601是一种专用馈线保护继电器&#xff0c;用于保护一次和二次配电网络中的公用事业和工业电力系统。该继电器在一个单元中提供了保护和监控功能的优化组合&#xff0c;具有同类产品中最佳的性能和可用性。 REJ601是一种专用馈线保护继电器&#xf…...

【动态规划】B4336 [中山市赛 2023] 永别|普及+

B4336 [中山市赛 2023] 永别 题目描述 你做了一个梦&#xff0c;梦里有一个字符串&#xff0c;这个字符串无论正着读还是倒着读都是一样的&#xff0c;例如&#xff1a; a b c b a \tt abcba abcba 就符合这个条件。 但是你醒来时不记得梦中的字符串是什么&#xff0c;只记得…...

Vue.js教学第二十一章:vue实战项目二,个人博客搭建

基于 Vue 的个人博客网站搭建 摘要: 随着前端技术的不断发展,Vue 作为一种轻量级、高效的前端框架,为个人博客网站的搭建提供了极大的便利。本文详细介绍了基于 Vue 搭建个人博客网站的全过程,包括项目背景、技术选型、项目架构设计、功能模块实现、性能优化与测试等方面。…...

React与原生事件:核心差异与性能对比解析

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

STM32CubeMX-H7-19-ESP8266通信(中)--单片机控制ESP8266实现TCP地址通信

前言 上篇文章我们已经能够使用串口助手实现esp8266的几种通信&#xff0c;接下来我们使用单片机控制实现。这篇文章会附带教程&#xff0c;增加.c和,.h&#xff0c;把串口和定时器放到对应的编号&#xff0c;然后调用初始化就可以使用了。 先讲解&#xff0c;然后末尾再放源码…...

docker 部署redis集群 配置

docker的网络模式 网桥模式每次重启容器都有可能导致容器ip地址变化&#xff0c;需要固定ip的自己自定义网络&#xff0c;这里介绍的是默认网络模式 docker创建容器 docker run --name redis6379 -p 6379:6379 -p 16379:16379 -v /etc/redis/redis6379:/etc/redis -d --r…...

【bat win系统自动运行脚本-双击启动docker及其它】

win系统自动化运行脚本 创建一个 startup.bat右键编辑&#xff0c;输入以下示例 echo off start "" "C:\Program Files\Docker\Docker\Docker Desktop.exe"timeout /t 5docker start your_container_namestart cmd /k "conda activate your_conda_e…...

时间序列预测的机器学习方法:从基础到实战

时间序列预测是机器学习中一个重要且实用的领域&#xff0c;广泛应用于金融、气象、销售预测、资源规划等多个行业。本文将全面介绍时间序列预测的基本概念、常用方法&#xff0c;并通过Python代码示例展示如何构建和评估时间序列预测模型。 1. 时间序列预测概述 时间序列是按…...

部署DNS从服务器

部署DNS从服务器的目的 DNS域名解析服务中&#xff0c;从服务器可以从主服务器上获得指定的区域数据文件&#xff0c;从而起到备份解析记录与负载均衡的作用&#xff0c;因此通过部署从服务器可以减轻主服务器的负载压力&#xff0c;还可以提升用户的查询效率。 注意&#xf…...