后端工程化 | SpringBoot 知识点

news2024/11/24 5:06:21

文章目录

    • [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 {
    @Override
    public List<Emp> listEmp() {
        //1. 加载并解析emp.xml
        String 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();

    @Override
    public List<Emp> listEmp() {
        //1. 调用dao, 获取数据
        List<Emp> empList = empDao.listEmp();

        //2. 对数据进行转换处理 - gender, job
        empList.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是按照名称注入

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

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

相关文章

10 特征向量与特征值

特征向量与特征值 什么是特征向量三维空间的旋转矩阵和线性变换特征向量二维线性变换不一定有特征向量一个特征值可能不止一个特征向量特征基 这是关于3Blue1Brown "线性代数的本质"的学习笔记。 图1 预备知识 什么是特征向量 图1 特征向量 线性变换过程中&#xff…

测试常见异常总结

为了更好地保障测试质量&#xff0c;除了测试正向场景&#xff0c;也需要验证软件在异常情况下的行为和反应。本文分享一些测试过程中常见的异常。 通过模拟和触发各种异常情况&#xff0c;测试人员可以验证软件对异常的处理是否符合预期&#xff0c;是否能够正确地处理和恢复。…

Microsoft Dynamics 365 CE 扩展定制 - 7. 安全

在本章中,我们将介绍以下内容: 构建累积安全角色配置业务单元层次结构基于分层位置配置访问配置和分配字段级安全组建团队并共享设置访问团队对静止数据进行加密以满足FIPS 140-2标准管理Dynamics 365在线SQLTDE加密密钥简介 Dynamics 365是一个强大的平台,具有超过10年的良…

电脑风扇控制软件 Macs Fan Control Pro mac中文版功能介绍

Macs Fan Control mac是一款专门为 Mac 用户设计的软件&#xff0c;它可以帮助用户控制和监控 Mac 设备的风扇速度和温度。这款软件允许用户手动调整风扇速度&#xff0c;以提高设备的散热效果&#xff0c;减少过热造成的风险。 Macs Fan Control 可以在菜单栏上显示当前系统温…

LT498. 对角线遍历

498. 对角线遍历 问题描述 给你一个大小为 m x n 的矩阵 mat &#xff0c;请以对角线遍历的顺序&#xff0c;用一个数组返回这个矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;mat [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,4,7,5,3,6,8,9]示例 2&#xf…

机器学习实战:基于sklearn的工业蒸汽量预测

文章目录 写在前面工业蒸汽量预测1.基础代码2.模型训练3.模型正则化4.模型交叉验证5.模型超参空间及调参6.学习曲线和验证曲线 写在后面 写在前面 本期内容&#xff1a;基于机器学习的工业蒸汽量预测 实验环境&#xff1a; anaconda python sklearn 注&#xff1a;本专栏内所有…

uniapp小程序才到第五层就报错navigateto:fail webview count limit exceed

错误截图 原因 小程序官方描述是说可以跳转10层&#xff0c;但是使用uniapp开发的程序在小程序中才运行到第五层就报错了&#xff0c;原因是因为没有设置appId。如果设置了就正常了。

基于APM(PIX)飞控和missionplanner制作遥控无人车-从零搭建自主pix无人车无人坦克

前面的步骤和无人机调试一样&#xff0c;可以参考无人机相关专栏。这里不再赘述。 1.安装完rover的固件后&#xff0c;链接gps并进行校准。旋转小车不同方向&#xff0c;完成校准&#xff0c;弹出成功窗口。 2.校准遥控器。 一定要确保遥控器模式准确&#xff0c;尤其是使用没…

按键精灵中的UI界面操作

1. 按键精灵中UI界面常用的控件 1. 文字框 界面1: {标签页1:{文字框:{名称:"文字框1",显示内容:"显示内容",文字大小:0,高度:0,宽度:0,注释:"文字大小、高度、宽度是可选属性&#xff0c;如需使用默认值&#xff0c;可保持值为0或直接删除此属性&qu…

easyHttp -- 轻量级的 HTTP 客户端工具包

easyHttp gitte地址:easy-http 介绍 easyHttp 是一个轻量级的 HTTP 客户端工具包&#xff0c;专为 Java 设计&#xff0c;使得基本的 HTTP 请求变得异常简单。该库主要针对常见的 HTTP 请求提供了简洁的 API&#xff0c;使得开发者无需面对复杂的设置。当前版本已支持基本的请…

游戏服务器频繁遭到攻击是什么原因?

这可能是来自竞争对手的恶意攻击&#xff0c;使您的服务器无法正常运行。如果游戏被卡住或攻击&#xff0c;所有服务器都将瘫痪。玩家的游戏体验不好&#xff0c;自然会选择别家的游戏。当然&#xff0c;也不排除游戏中的一些玩家对游戏中或游戏公司中的一些人不满&#xff0c;…

自动驾驶算法(七):基于遗传算法的路径规划(下)

目录 1 遗传选择 2 遗传交叉 3 遗传变异 4 结语 1 遗传选择 我们书接上回&#xff0c;我们完成了种群的初始化&#xff0c;将所有的种群放入了new_pop1中&#xff0c;这个new_pop1是一个&#xff08;种群大小 * 路径&#xff09;的一个矩阵&#xff0c;我们来看如何进行遗传…

软件外包开发需要注意的问题

软件外包开发是一种常见的商业实践&#xff0c;可以帮助企业降低成本、提高效率和获得专业技能。然而&#xff0c;要确保成功的外包开发项目&#xff0c;需要注意以下一些关键问题&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司…

数组的存储结构、特殊矩阵和稀疏矩阵的压缩存储

数组的存储结构、特殊矩阵和稀疏矩阵的压缩存储 1.数组的存储结构、特殊矩阵、稀疏矩阵的压缩存储1.1 数组的存储结构1.1.1 一维数组的存储结构关系式1.1.2 多维数组的存储结构关系式 1.2 特殊矩阵的压缩存储1.2.1 对称矩阵1.2.2 下三角矩阵1.2.3 上三角矩阵1.2.4 三对角矩阵 1…

Cesium:WFS请求两种方式

以本地发布的上海市浦东区行政区划WMS地图服务为例,讲述Cesium中WFS请求的两种方式及其优缺点。 服务加载地址及其参数如下, 服务加载地址:http://localhost:8089/geoserver/pudong/wms 加载参数:layerName:pudong:distractservice: "WMS",request: "GetMa…

基于材料生成算法的无人机航迹规划-附代码

基于材料生成算法的无人机航迹规划 文章目录 基于材料生成算法的无人机航迹规划1.材料生成搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用材料生成算法来优化无人机航迹规划。 …

以华为为例:GTM岗位主要是做什么的?如何做好GTM工作?

如何让产品上市以后卖得更好&#xff1f;这是一个系统工程。 许多公司在学习华为&#xff08;尤其是做消费者业务&#xff0c;通俗地说就是2C业务的公司或产品&#xff09;&#xff0c;设立GTM相关的岗位。我们来看一下&#xff0c;GTM岗位主要做些什么&#xff0c;如何才能胜…

宠物领养系统jsp+servlet+mysql

设计不同用户的操作权限、注册和登录方法。 管理员可以在管理员管理、用户管理、宠物管理、评论管理、团队活动管理、志愿者的申请等等模块中进行查询、添加、删除、修改。 管理员可以在领养管理中通过领养时间查询所有宠物被领养的信息&#xff0c;修改是否同意领养宠物&#…

色彩大师:纽约公寓的大胆装修之旅

这对夫妇刚从西海岸搬到了纽约&#xff0c;最初尝试自己布置家居。但在设计中心寻找面料和家具时&#xff0c;他们感到有些不知所措。 在海外期间&#xff0c;他们深受英国乡村别墅装饰的魅力所吸引&#xff0c;希望将类似的风格带到他们的纽约公寓。我们喜欢英国乡村别墅的随…

nn.embedding函数详解(pytorch)

提示&#xff1a;文章附有源码&#xff01;&#xff01;&#xff01; 文章目录 前言一、nn.embedding函数解释二、nn.embedding函数使用方法四、模型训练与预测的权重变化探讨 前言 最近发现prompt工程(如sam模型)&#xff0c;也有transform的detr模型等都使用了nn.Embedding函…