自学SpringBoot笔记

news2025/1/20 5:31:37

概念

什么是SpringBoot?

Spring Boot 是基于 Spring Framework 的一款开源框架,主要用于简化 Spring 应用程序的开发。它通过提供一系列的 开箱即用的功能 和 自动配置,让开发者可以快速构建生产级别的独立应用程序,而无需手动配置大量的 XML 或注解。
Spring Boot 的目标是让开发者能够专注于业务逻辑,减少繁杂的配置工作,从而提升开发效率。

什么是 Spring MVC?

Spring MVC(Model-View-Controller)是 Spring Framework 中的一个模块,专门用于构建基于 HTTP 的 Web 应用程序,它遵循经典的 MVC 架构模式。Spring MVC 提供了一套灵活、强大的工具,用于开发动态 Web 应用或 RESTful API。

通过 Spring MVC,开发者可以轻松处理 HTTP 请求、业务逻辑和视图层的渲染,同时保持应用的模块化和可维护性。

Spring MVC 的核心概念

Spring MVC 基于 Model-View-Controller 模式,将应用分为以下三个部分:

1. Model(模型)

  • 表示应用程序的数据或业务逻辑。
  • 通常由 POJO(Plain Old Java Object)或 DTO(数据传输对象)组成。
  • 在实际开发中,Model 通常是从数据库中获取的业务实体。

2. View(视图)

  • 负责将数据(Model)渲染为用户可以看到的页面或响应数据。
  • 支持多种视图技术,例如 JSPThymeleafFreeMarker 等。
  • 对于 RESTful 应用,视图层通常是 JSON 或 XML 格式的响应。

3. Controller(控制器)

  • 负责接收用户请求,并将其分发给合适的服务或处理逻辑。
  • 控制器将数据与视图进行绑定,最终返回一个完整的响应。

Spring MVC 的工作流程

  1. 用户通过浏览器发送一个 HTTP 请求。
  2. 请求被 Spring MVC 的 DispatcherServlet 拦截。
  3. DispatcherServlet 将请求分发给合适的 Controller
  4. Controller 调用业务逻辑层或服务层,获取数据并封装为 Model。
  5. DispatcherServlet 将返回的数据传递给指定的视图(View)。
  6. 视图渲染最终的 HTML 页面或响应数据,并返回给用户。

Spring MVC 的核心组件

以下是 Spring MVC 的几个核心组件及其作用:

1. DispatcherServlet

  • 是 Spring MVC 的核心,负责拦截所有 HTTP 请求。
  • 它将请求分发给适当的处理器(Controller)并协调其他组件(如视图解析器和模型绑定器)。

2. Controller

  • 使用注解(如 @Controller@RestController)标注的类,用于处理业务逻辑。
  • 处理用户请求并返回数据或视图。

3. ModelAndView

  • 一个对象,用于封装数据(Model)和视图(View)。
  • Controller 可以返回 ModelAndView 来指定渲染的数据和视图名称。

4. ViewResolver(视图解析器)

  • 负责将逻辑视图名称转换为具体的视图。
  • 例如,将返回的视图名 home 映射到 home.jsphome.html

5. HandlerMapping

  • 负责将用户请求 URL 映射到具体的 Controller 方法。

6. Model

  • 用于在 Controller 和 View 之间传递数据。

springboot架构

首先我们先看下面这张图,待会会根据该图中的各个层进行项目创建:
在这里插入图片描述

Maven上手

这里我们使用IDEA进行Maven项目的创建,这里我们选择Maven创建:
在这里插入图片描述
这里我们选择springWebmysql

在这里插入图片描述
在这里插入图片描述

pom.xml

如果我们后续还需要添加依赖的话,可以直接在项目的pom.xml中的<dependencys>中添加依赖:
在这里插入图片描述

配置文件

application.properties中,我们可以配置数据库的连接、后端端口等内容:
在这里插入图片描述

项目结构

仿照上图的SpringBoot架构,我们创建以下文件夹来划分各个层次:
在这里插入图片描述

什么是 POJO?

POJOPlain Old Java Object 的缩写,意为“普通的旧式 Java 对象”。它是一个 纯粹的 Java 对象,不依赖于任何特定的框架或库,通常只包含 属性构造方法Getter 和 Setter 方法 以及少量的业务逻辑。

POJO 的核心思想是保持对象简单、轻量化,避免引入框架特定的依赖或复杂的特性(如继承特定的类或实现框架接口)。

POJO 的特点

  1. 轻量化

    • 没有继承任何框架特定的类(如 HttpServlet)。
    • 不实现任何框架特定的接口(如 Serializable 除外)。
  2. 纯粹性

    • 只包含简单的属性(字段)和方法(如 Getter 和 Setter)。
    • 不依赖框架代码,适用于任何 Java 环境。
  3. 无强制要求

    • POJO 不需要遵循特定规范,只要是普通的 Java 对象即可。

POJO 的常见用途

  1. 数据传输对象(DTO)

    • 用于在不同层(如 Controller 和 Service 层)之间传输数据的对象。
    • 通常只包含属性和 Getter/Setter 方法。
  2. 实体类(Entity)

    • 用于映射数据库表的类,通常用于 ORM 框架(如 Hibernate、JPA)。
    • 每个字段对应数据库表中的一列。
  3. 模型类

    • 用于封装业务逻辑中的数据模型。
  4. 配置类

    • 用于封装应用程序的配置信息。

pojo的示例——user

package com.jiaowu.backend.pojo;

import jakarta.persistence.*;

@Table(name = "tb_user")
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="user_id")
    private Integer id;
    @Column(name="user_name")
    private String name;
    @Column(name="user_password")
    private String password;
    @Column(name="user_email")
    private String email;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

注解总结

以下是代码中各注解的作用和含义:


1. @Table(name = "tb_user")

  • 作用:指定该实体类对应的数据库表名称。
  • 解释:将类 User 映射到名为 tb_user 的数据库表。如果不加该注解,默认表名会与类名一致。

2. @Entity

  • 作用:将该类标记为一个 JPA 实体类。
  • 解释User 类会被 JPA 识别为数据库中的一个表实体,JPA 会根据该类的属性与注解生成对应的数据库表操作。

3. @Id

  • 作用:指定该字段为主键。
  • 解释id 字段是数据库表 tb_user 的主键。每个实体对象都需要一个唯一标识,@Id 用来表明哪个字段是主键。

4. @GeneratedValue(strategy = GenerationType.IDENTITY)

  • 作用:定义主键的生成策略。
  • 解释
    • 使用 自增策略IDENTITY 生成方式),即数据库会自动生成主键值(如 MySQL 的自增主键)。
    • 每次插入新数据时,id 字段的值会由数据库自动递增。

5. @Column(name = "user_id")

  • 作用:将实体类的字段映射到数据库表中的列,并指定列名。
  • 解释
    • id 字段映射到数据库表 tb_user 中的 user_id 列。
    • 如果不加 @Column 注解,JPA 会默认将字段名与列名一致(如字段名为 id,则列名也为 id)。

6. @Column(name = "user_name")

  • 作用:将 name 字段映射到数据库表中的 user_name 列。

7. @Column(name = "user_password")

  • 作用:将 password 字段映射到数据库表中的 user_password 列。

8. @Column(name = "user_email")

  • 作用:将 email 字段映射到数据库表中的 user_email 列。

代码的注解功能:

  1. 类级别注解

    • @Entity:将类标记为 JPA 实体类。
    • @Table(name = "tb_user"):将类与数据库表 tb_user 进行映射。
  2. 字段级别注解

    • @Id:标识主键字段。
    • @GeneratedValue(strategy = GenerationType.IDENTITY):主键使用数据库的自增策略。
    • @Column(name = "xxx"):将字段映射到数据库表的指定列名。

通过这些注解,JPA 框架可以自动将类 User 与数据库表 tb_user 关联起来,并根据类的字段与数据库列之间的映射关系,帮助开发者进行数据库操作(如增删改查)。

备注

标记为 JPA 实体类的作用

在 Java Persistence API(JPA)中,将类标记为实体类(通过 @Entity 注解)有以下作用:


1. 将类映射为数据库表
  • @Entity 告诉 JPA 框架,这个类是一个 实体类,需要与数据库中的表进行映射。
  • 每个实体类的实例(对象)对应数据库表中的一行数据。
  • 类的字段(属性)通过注解(如 @Column)映射到数据库表的列。

示例

@Entity
@Table(name = "tb_user")
public class User {
    @Id
    private Integer id; // 对应 tb_user 表的主键列
    private String name; // 对应 tb_user 表中的 name 列
}
总结

将类标记为 JPA 实体类的作用主要体现在以下几个方面:

  • 映射类与数据库表的关系:通过注解定义类与表、字段与列的映射规则。
  • 启用 ORM 功能:实现对象与数据库记录的自动转换,简化数据操作。
  • 支持持久化操作:通过 JPA 的 API 或框架(如 Spring Data JPA)操作数据库,而无需手写 SQL。
  • 与数据库表结构集成:支持自动生成或更新表结构,便于维护。
  • 增强功能支持:如关联关系管理、懒加载、级联操作等。

controller

这里我们写好了用于各个层之间交换的数据结构后,我们就开始正式进行后端项目的功能的编写。这里我们从controller层开始写。我们在这里只需要使用对数据库的增删改查功能:

package com.jiaowu.backend.controller;

import com.jiaowu.backend.pojo.ResponseMessage;
import com.jiaowu.backend.pojo.User;
import com.jiaowu.backend.pojo.dto.UserDto;
import com.jiaowu.backend.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController //允许接口方法返回对象,转换成json文本
@RequestMapping("/user") // localhost:8080/user/**
public class UserController {
    @Autowired
    IUserService userService;
    //REST——请求方法
    //增加
    @PostMapping // localhost:8080/user method:post
    public ResponseMessage<User> addUser(@Validated @RequestBody UserDto user) {
        User userNew =  userService.add(user);
        return ResponseMessage.success(userNew);
    }
    //查询
    @GetMapping("/{userId}") // localhost:8080/user/{userId} method:get
    public ResponseMessage<User> get(@PathVariable Integer userId) {
        User userNew =  userService.getUser(userId);
        return ResponseMessage.success(userNew);
    }
    @GetMapping("/all")
    public ResponseMessage<User> getAll() {
        List<User> userNew =  userService.getAll();
        return ResponseMessage.success(userNew);
    }
    //修改
    @PutMapping
    public ResponseMessage<User> edit(@Validated @RequestBody UserDto userId) {
        User userNew =  userService.edit(userId);
        return ResponseMessage.success(userNew);
    }
    //删除
    @DeleteMapping("/{userId}")
    public ResponseMessage<User> delete(@PathVariable Integer userId) {
        userService.delete(userId);
        return ResponseMessage.success();
    }
}

代码注释总结

以下是代码中各注释的作用与含义:


类级别注解

1. @RestController
  • 作用:标识该类为一个 RESTful 控制器。
  • 功能:允许接口方法直接返回对象,Spring 会将对象自动转换为 JSON 格式的响应。
2. @RequestMapping("/user")
  • 作用:为该控制器类定义一个基础 URL 前缀。
  • 功能:所有方法的 URL 都以 /user 开头,例如:
    • localhost:8080/user

成员变量注解

3. @Autowired
  • 作用:自动注入 IUserService 接口的实现类。
  • 功能:使 userService 变量可以直接调用服务层的逻辑。

方法级别注解

增加用户
4. @PostMapping
  • 作用:映射 HTTP POST 请求。
  • 功能:处理 localhost:8080/user 的 POST 请求,用于新增用户。
5. @Validated
  • 作用:启用数据校验。
  • 功能:对请求体中的 UserDto 对象进行校验,例如检查字段的格式或必填项。
6. @RequestBody
  • 作用:将 HTTP 请求体的 JSON 数据反序列化为 Java 对象。
  • 功能:将客户端发送的用户数据解析为 UserDto 对象。

查询用户
7. @GetMapping("/{userId}")
  • 作用:映射 HTTP GET 请求。
  • 功能:处理 localhost:8080/user/{userId} 的 GET 请求,用于根据用户 ID 查询用户。
8. @PathVariable
  • 作用:将 URL 中的动态路径变量绑定到方法参数。
  • 功能:将 {userId} 解析为方法的 userId 参数。
9. @GetMapping("/all")
  • 作用:映射 HTTP GET 请求。
  • 功能:处理 localhost:8080/user/all 的 GET 请求,返回所有用户信息。

修改用户
10. @PutMapping
  • 作用:映射 HTTP PUT 请求。
  • 功能:处理 localhost:8080/user 的 PUT 请求,用于修改用户信息。

删除用户
11. @DeleteMapping("/{userId}")
  • 作用:映射 HTTP DELETE 请求。
  • 功能:处理 localhost:8080/user/{userId} 的 DELETE 请求,用于根据用户 ID 删除用户。

方法返回值说明

12. 返回值类型
  • 类型ResponseMessage<User>
  • 作用:封装接口的响应结果,通常包括:
    • success:请求是否成功。
    • data:具体返回的数据(如用户对象或用户列表)。
    • message:提示信息。

总结

代码功能
  1. 控制器类:定义了与用户相关的 RESTful 接口,包括新增、查询、修改、删除用户等操作。
  2. 注解使用:通过 Spring MVC 注解(如 @RestController@PostMapping@GetMapping 等)简化了接口开发,清晰地定义了请求的类型和 URL 路径。
  3. 数据流
    • 客户端发送 JSON 请求。
    • 通过 @RequestBody 反序列化为 Java 对象。
    • 调用服务层逻辑处理数据。
    • 最终返回 JSON 格式的响应。
RESTful 接口一览
请求方法URL描述
POST/user新增用户
GET/user/{userId}查询用户
GET/user/all查询所有用户
PUT/user修改用户
DELETE/user/{userId}删除用户

repository

这里我们实现数据访问层:

package com.jiaowu.backend.repository;

import com.jiaowu.backend.pojo.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends CrudRepository<User, Integer> {

}

代码分析与注释总结

以下是代码中注释的作用与详细解释:


1. @Repository

  • 作用:将接口标记为一个 Spring 数据访问层组件
  • 功能
    • 表示当前接口是一个 DAO(数据访问对象),负责与数据库交互。
    • Spring 会将该接口的实现类自动注册为 Bean,并纳入到 Spring 容器中管理。
    • 提供数据访问相关的异常转换功能(将底层的数据库异常转换为 Spring 的统一异常,如 DataAccessException)。

2. public interface UserRepository extends CrudRepository<User, Integer>

  • 作用:定义一个 JPA Repository,用于对 User 实体进行 CRUD(增删改查)操作。
  • 解释
    • UserRepository
      • 是一个接口,继承了 Spring Data 提供的 CrudRepository 接口。
      • 不需要手动实现,Spring 会自动生成实现类。
    • CrudRepository<User, Integer>
      • 泛型参数解析:
        • User:指定该仓库要操作的实体类类型。
        • Integer:指定主键的类型(id 的数据类型是 Integer)。

3. CrudRepository 的功能

CrudRepository 是 Spring Data JPA 提供的一个基础接口,包含了常用的 CRUD 操作方法。通过继承 CrudRepository,可以直接使用这些方法,无需额外实现。

service

编写业务逻辑层:

package com.jiaowu.backend.service;

import com.jiaowu.backend.pojo.User;
import com.jiaowu.backend.pojo.dto.UserDto;
import com.jiaowu.backend.repository.UserRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service // spring bean
public class UserService implements IUserService {
    @Autowired
    UserRepository userRepository;
    @Override
    public User add(UserDto user) {

        User userPojo = new User();

        BeanUtils.copyProperties(user, userPojo);

        return userRepository.save(userPojo);
    }

    @Override
    public User getUser(Integer userId) {
        return userRepository.findById(userId).orElseThrow(() -> {
            throw new IllegalArgumentException("用户不存在,参数异常");
        });
    }

    @Override
    public User edit(UserDto user) {
        User userPojo = new User();

        BeanUtils.copyProperties(user, userPojo);

        return userRepository.save(userPojo);
    }

    @Override
    public void delete(Integer userId) {
        userRepository.deleteById(userId);
    }

    @Override
    public List<User> getAll() {
        return (List<User>)userRepository.findAll();
    }
}

代码分析与注释总结

以下是代码中注释的作用与详细解释:


1. 类级别注解

@Service
  • 作用:将该类标记为一个 Spring 服务层组件
  • 功能
    • 表示该类是业务逻辑层的组件(Service Bean),由 Spring 容器管理。
    • 通过依赖注入(如 @Autowired),可以在控制器或其他组件中调用服务层逻辑。

2. 成员变量注解

@Autowired
  • 作用:对 UserRepository 进行自动注入。
  • 功能
    • Spring 容器会将 UserRepository 的实现类(由 Spring Data JPA 自动生成的代理类)注入到 userRepository 中。
    • 用于提供数据库操作方法(如 savefindByIddeleteById 等)。

3. 方法实现分析

add(UserDto user)
  • 作用:新增一个用户。

  • 功能

    1. 创建一个空的 User 对象(实体类)。
    2. 使用 BeanUtils.copyProperties 复制 UserDto 对象的属性值到 User 对象中。
    3. 调用 userRepository.save() 将用户数据保存到数据库。
    4. 返回保存后的 User 对象。
  • 关键点

    • BeanUtils.copyProperties(source, target)
      • Spring 提供的工具类,用于将一个对象的属性值快速复制到另一个对象中。
      • 需要确保属性名称和类型一致。
    • userRepository.save()
      • Spring Data JPA 提供的方法,用于新增或更新数据库记录。
      • 如果实体没有主键值,则新增;如果有主键值,则更新。

getUser(Integer userId)
  • 作用:根据用户 ID 查询用户。

  • 功能

    1. 调用 userRepository.findById(userId) 查询用户。
    2. 如果用户不存在,则抛出 IllegalArgumentException,提示用户不存在。
    3. 如果用户存在,返回查询到的 User 对象。
  • 关键点

    • findById(userId)
      • 返回一个 Optional 对象,避免直接返回 null
    • .orElseThrow()
      • Optional 中没有值时,抛出指定的异常。

edit(UserDto user)
  • 作用:编辑用户信息。

  • 功能

    1. 创建一个空的 User 对象。
    2. 使用 BeanUtils.copyPropertiesUserDto 的属性复制到 User 对象中。
    3. 调用 userRepository.save() 更新用户信息。
    4. 返回更新后的 User 对象。
  • 关键点

    • 编辑和新增的逻辑非常相似,区别在于:
      • 新增时,主键值为 null,会新增一条记录。
      • 编辑时,需要确保传入的对象有主键,否则会新增而不是更新。

delete(Integer userId)
  • 作用:根据用户 ID 删除用户。

  • 功能

    1. 调用 userRepository.deleteById(userId) 删除指定用户。
  • 关键点

    • deleteById(userId)
      • Spring Data JPA 提供的方法,根据主键删除对应的记录。
      • 如果记录不存在,不会抛出异常(取决于底层数据库实现)。

getAll()
  • 作用:查询所有用户。

  • 功能

    1. 调用 userRepository.findAll() 查询所有用户。
    2. 将结果转换为 List<User> 并返回。
  • 关键点

    • findAll()
      • 返回一个 Iterable,可以通过 (List<User>) 强制转换为列表。
    • 强制转换是因为 CrudRepository 默认返回 Iterable,而业务通常需要 List

4. 代码逻辑总结

方法功能一览
方法名称功能描述
add(UserDto user)新增一个用户,将 UserDto 转换为 User 并保存。
getUser(Integer userId)根据用户 ID 查询用户,不存在则抛出异常。
edit(UserDto user)编辑用户信息,将传入的 UserDto 更新到数据库中。
delete(Integer userId)根据用户 ID 删除用户。
getAll()查询所有用户,返回用户列表。

5. 注意点

  1. BeanUtils.copyProperties 的使用

    • 简化了对象之间的属性赋值,但需要注意:
      • 属性名和类型必须一致,否则会跳过不匹配的字段。
      • 可能会忽略嵌套对象的处理(例如复杂对象内的字段不会自动复制)。
  2. 异常处理

    • getUser 方法中,使用 orElseThrow 抛出异常,保证调用方法时不会出现空指针问题。
    • 可以根据业务需求,定义自定义异常类代替 IllegalArgumentException,提高可读性。
  3. 数据类型转换

    • getAll 方法中,findAll 返回的是 Iterable,需要手动转换为 List
    • 强制类型转换可能会出现问题,建议直接用 Stream 或工具类进行转换。

为什么在业务开发中 Service 层需要定义一个接口?

在业务开发中,通常会为 Service 层定义一个接口(如 IUserService),然后通过实现类(如 UserService)实现该接口。这种设计并不是强制性的,但它遵循了良好的软件设计原则,带来了许多实际的好处。


1. 遵循面向接口编程的原则
  • 面向接口编程 是软件设计中的重要原则,强调程序应依赖于抽象(接口),而不是具体的实现类。
  • 好处:
    • 服务调用者(控制器或其他服务)只需要知道接口的方法,而不需要关心具体实现。
    • 使代码更加灵活和解耦,方便后续拓展和维护。

dto

不难发现,我们在编写代码的时候,发现使用到了一个中间变量, 也就是还是用于传输的变量,以下是定义:

package com.jiaowu.backend.pojo.dto;

import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.hibernate.validator.constraints.Length;

public class UserDto {
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    private Integer id;
    @NotBlank(message = "用户名不能为空")
    private String name;
    @NotBlank(message = "密码不能为空")
    @Length(min = 6,max = 12)
    private String password;
    @Email(message = "邮箱格式不正确")
    private String email;

    @Override
    public String toString() {
        return "UserDto{" +
                "name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

1. 简介

UserDto 是一个 数据传输对象(Data Transfer Object, DTO),用于在客户端和服务端之间传递用户数据。
DTO 的主要职责是:

  • 封装用户的请求数据(如新增或编辑用户时的输入)。
  • 提供输入验证功能,确保数据的合法性。

2. 字段分析

1. private Integer id
  • 解释id 是用户的唯一标识,用于编辑或删除用户时的主键。
  • 注意:在新增用户时,通常不需要传递 id,此字段在某些场景下可能为空(如新增用户)。

2. @NotBlank(message = "用户名不能为空")
  • 作用
    • 用于验证 name 字段不能为空或全是空格。
    • 如果用户未提供 name,会抛出验证异常,返回自定义错误信息。
  • 适用场景:新增或编辑用户时,用户名为必填项。

3. @NotBlank(message = "密码不能为空")
  • 作用
    • 验证 password 字段不能为空或全是空格。
  • 额外验证@Length(min = 6, max = 12)
    • 限制密码长度,必须在 6~12 个字符之间。
  • 适用场景:新增用户或更新密码时。

4. @Email(message = "邮箱格式不正确")
  • 作用
    • 验证 email 是否符合邮箱格式。
    • 如果用户提供的邮箱格式不正确,则返回错误信息。
  • 适用场景:新增或编辑用户时。

字段验证总结
字段名验证注解描述
id主键字段,可为空(新增时)。
name@NotBlank用户名不能为空或全是空格。
password@NotBlank + @Length(6, 12)密码不能为空,长度必须在 6~12 个字符之间。
email@Email检查邮箱格式是否合法。

3. 常用方法分析

Getter 和 Setter 方法
  • 作用:提供对私有字段的访问和修改。
  • 优点
    • 提供封装,保护字段的直接访问。
    • 允许对字段的访问进行控制(如添加逻辑验证)。
  • 改进建议
    • 可使用 Lombok 简化代码,自动生成 GetterSetter 方法,减少代码冗余。
toString 方法
  • 作用
    • 重写了 toString 方法,用于输出对象的字符串表示。
    • 在调试或日志打印时,便于查看对象内容。
  • 改进建议
    • 使用 Lombok@ToString 注解,简化代码。

为什么要使用dto的变量而不是直接使用原来的user呢?

在开发中,DTO(数据传输对象,Data Transfer Object)常用于 数据传输,特别是在控制器层(Controller)和服务层(Service)之间传递数据,而不是直接使用实体类(如 User)。
这种设计是一种 分层架构的最佳实践,能够提高代码的灵活性、安全性和可维护性。以下是详细原因和优点:


1. 职责分离

实体类的职责

  • 实体类(如 User)通常是直接与数据库表映射的类(通过 JPA 或 Hibernate 等 ORM 框架)。
  • 它的主要职责是反映数据库结构(如字段)和处理持久化逻辑。

DTO 的职责

  • DTO 的职责是用来封装和传递客户端请求或响应的 数据结构
  • 它关注的是 数据传输,而不是数据库操作或业务逻辑。

好处

  • 分离了数据传输逻辑和持久化逻辑。
  • 使 数据库模型数据传输格式 之间解耦,避免直接暴露数据库模型的结构。

2. 避免暴露实体类的敏感信息

实体类中可能包含一些敏感信息或不需要暴露给客户端的数据(如密码的哈希值、数据库主键等)。
直接使用实体类会导致以下问题:

  • 无法控制哪些字段可以被客户端访问或修改。
  • 如果实体类字段较多,可能会导致不必要的数据暴露。

统一异常处理

后端处理出现了异常的时候,通常是不用将这个异常情况反馈给前端的,所以我们这里可以定义一个统一的异常处理类来进行返回统一异常信息:

package com.jiaowu.backend.exception;

import com.jiaowu.backend.pojo.ResponseMessage;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice //统一处理
public class GlobalExceptionHanderAdvice {
    // 记录日志
    Logger log = LoggerFactory.getLogger(GlobalExceptionHanderAdvice.class);

    @ExceptionHandler({Exception.class})
    public ResponseMessage handleException(Exception e, HttpServletRequest request, HttpServletResponse response) {

        log.error(e.getMessage(), e);
        return new ResponseMessage(500,"error",null);
    }
}

简介

功能

  • GlobalExceptionHanderAdvice 是一个全局异常处理类,用于捕获和处理应用程序中的异常。
  • 通过使用 @RestControllerAdvice 注解,可以拦截所有控制器方法中抛出的异常(包括运行时异常),并进行统一的处理。

为什么需要全局异常处理?

  • 提高代码的可维护性和一致性:避免在每个控制器中重复编写异常处理逻辑。
  • 提供用户友好的错误响应:统一异常格式,便于前端解析和展示。
  • 记录详细的异常信息:通过日志记录系统错误,便于后续排查问题。

2. 代码功能分析

1. @RestControllerAdvice

  • 作用:这是 Spring 提供的增强功能,结合 @ExceptionHandler 注解,可以对所有 @RestController 抛出的异常进行拦截和处理。
  • 特点
    • 默认会拦截所有 REST API 请求中的异常。
    • 返回的对象会直接转化为 JSON 响应,适合 RESTful 风格的接口。

2. @ExceptionHandler({Exception.class})

  • 作用:指定处理的异常类型,此处捕获所有异常(包括运行时异常)。
  • 逻辑
    1. 记录异常日志:通过 SLF4JLogger 记录完整的异常堆栈信息。
    2. 返回统一的错误响应:构造 ResponseMessage 对象作为标准的错误响应。

3. 日志记录

  • Logger log = LoggerFactory.getLogger(GlobalExceptionHanderAdvice.class)
    • 通过 SLF4J 记录异常日志。
    • log.error(e.getMessage(), e)
      • 输出异常的详细信息,包括错误消息和堆栈跟踪,便于排查问题。

4. 返回对象:ResponseMessage

  • ResponseMessage 是一个封装类,用于统一接口的响应格式。
  • 返回值示例:
    {
      "status": 500,
      "message": "error",
      "data": null
    }
    

小结

这里我们将SpringBoot框架的基本操作都做了一遍,不难看出,springboot开发需要用到大量的注释,省去了开发人员的编写麻烦问题。

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

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

相关文章

通过学习更多样化的生成数据进行更广泛的数据分发来改进实例分割

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 本次使用的英文整理的一些记录&#xff0c;练习一下为后续SCI发表论文打好基础 Improving Instance Segmentation by Learning Wider Data Distribution with More Diverse Generative Data Abstract In…

USB3020任意波形发生器4路16位同步模拟量输出卡1MS/s频率 阿尔泰科技

信息社会的发展&#xff0c;在很大程度上取决于信息与信号处理技术的先进性。数字信号处理技术的出现改变了信息 与信号处理技术的整个面貌&#xff0c;而数据采集作为数字信号处理的必不可少的前期工作在整个数字系统中起到关键 性、乃至决定性的作用&#xff0c;其应用已经深…

提示词的艺术----AI Prompt撰写指南(个人用)

提示词的艺术 写在前面 制定提示词就像是和朋友聊天一样&#xff0c;要求我们能够清楚地表达问题。通过这个过程&#xff0c;一方面要不断练习提高自己地表达能力&#xff0c;另一方面还要锻炼自己使用更准确精炼的语言提出问题的能力。 什么样的提示词有用&#xff1f; 有…

自定义提示确认弹窗-vue

最初可运行代码 弹窗组件代码&#xff1a; &#xff08;后来发现以下代码可运行&#xff0c;但打包 typescript 类型检查出错&#xff0c;可打包的代码在文末&#xff09; <template><div v-if"isVisible" class"dialog"><div class&quo…

【JavaEE】Spring(1)

一、什么是Spring和SpringBoot Spring是Java应用程序的开发框架&#xff0c;其目的就是为了简化Java开发&#xff1b;SpringBoot是在spring框架的基础上构建的一个快速开发框架&#xff0c;其作用是进一步简化Spring程序开发 二、SpringBoot项目 2.1 创建项目 1. 设置jdk版本…

【Rust自学】13.4. 闭包 Pt.4:使用闭包捕获环境

13.4.0. 写在正文之前 Rust语言在设计过程中收到了很多语言的启发&#xff0c;而函数式编程对Rust产生了非常显著的影响。函数式编程通常包括通过将函数作为值传递给参数、从其他函数返回它们、将它们分配给变量以供以后执行等等。 在本章中&#xff0c;我们会讨论 Rust 的一…

浅谈操作系统与初识Linux

一、Linux操作系统的出现 1.1操作系统的出现以及相关的四个要素 1.2最早出现的操作系统及其创始人 起初&#xff0c;IBM为了让计算机可以以更低技术成本进行使用&#xff0c;以此来售卖计算机&#xff1b; 为计算机搭载上了Unix操作系统&#xff0c;Unix由肯汤普森用汇编语…

K8S开启/关闭审计日志

K8S默认禁用审计 开启/关闭 k8s 审计日志 默认 Kubernetes 集群不会输出审计日志信息。通过以下配置&#xff0c;可以开启 Kubernetes 的审计日志功能。 准备审计日志的 Policy 文件配置 API 服务器&#xff0c;开启审计日志重启并验证 准备审计日志 Policy 文件 apiVersio…

深入探讨DICOM医学影像中的MPPS服务及其具体实现

深入探讨DICOM医学影像中的MPPS服务及其具体实现 1. 引言 在医疗影像的管理和传输过程中&#xff0c;DICOM&#xff08;数字影像和通信医学&#xff09;标准发挥着至关重要的作用。除了DICOM影像的存储和传输&#xff08;如影像存储SCP和影像传输SCP&#xff09;&#xff0c;…

VGG (Visual Geometry Group) :深度卷积神经网络的图像识别利器

前言 在深度学习的蓬勃发展历程中&#xff0c;卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;为图像识别领域带来了革命性的突破。而 VGG&#xff08;Visual Geometry Group&#xff09;作为其中的杰出代表&#xff0c;凭借其简洁而高效的…

【机器学习实战中阶】音乐流派分类-自动化分类不同音乐风格

音乐流派分类 – 自动化分类不同音乐风格 在本教程中,我们将开发一个深度学习项目,用于自动化地从音频文件中分类不同的音乐流派。我们将使用音频文件的频率域和时间域低级特征来分类这些音频文件。 对于这个项目,我们需要一个具有相似大小和相似频率范围的音频曲目数据集…

HTML基础与实践

目录 HTML 结构 认识 HTML 标签 HTML 文件基本结构 标签层次结构 快速生成代码框架 HTML 常见标签 注释标签 标题标签: h1-h6 段落标签: p 换行标签: br 格式化标签 图片标签: img 超链接标签: a ​编辑链接的几种形式: 表格标签 基本使用 合并单元格 …

差分(前缀和的逆运算)

作用&#xff1a; 在 [ l ,r ] 数组中&#xff0c;对全部数字c 思路 原数组a 构造差分数组b使得a[i]b1b2b3...bi; a数组是b数组的前缀和,b1b2b3...bnan b[i] a[i]-a[i-1]; 在d21,那在前缀和时&#xff0c;这些a都1 在数组中&#xff0c;要l~r这段数c 在l处c后&#xff0c…

学习记录1

[SUCTF 2019]EasyWeb 直接给了源代码&#xff0c;分析一下 <?php function get_the_flag(){// webadmin will remove your upload file every 20 min!!!! $userdir "upload/tmp_".md5($_SERVER[REMOTE_ADDR]);if(!file_exists($userdir)){mkdir($userdir);}if…

走出实验室的人形机器人,将复刻ChatGPT之路?

1月7日&#xff0c;在2025年CES电子展现场&#xff0c;黄仁勋不仅展示了他全新的皮衣和采用Blackwell架构的RTX 50系列显卡&#xff0c;更进一步展现了他对于机器人技术领域&#xff0c;特别是人形机器人和通用机器人技术的笃信。黄仁勋认为机器人即将迎来ChatGPT般的突破&…

鸿蒙动态路由实现方案

背景 随着CSDN 鸿蒙APP 业务功能的增加&#xff0c;以及为了与iOS、Android 端统一页面跳转路由&#xff0c;以及动态下发路由链接&#xff0c;路由重定向等功能。鸿蒙动态路由方案的实现迫在眉睫。 实现方案 鸿蒙版本动态路由的实现原理&#xff0c;类似于 iOS与Android的实…

左神算法基础提升--3

文章目录 Manacher 算法经典算法Manacher算法原理 单调栈或单调队列 Manacher 算法 经典算法 在每学习Manacher算法之前我们可能会使用一种比较经典暴力的算法&#xff1a;遍历str字符串&#xff0c;将字符串中的每个字符作为对称点&#xff0c;向两边扩散找到回文字段&#x…

usb通过hdc连接鸿蒙next的常用指令

参考官方 注册报名https://www.hiascend.com/developer/activities/details/44de441ef599450596131c8cb52f7f8c/signup?channelCodeS1&recommended496144 hdc-调试命令-调测调优-系统 - 华为HarmonyOS开发者https://developer.huawei.com/consumer/cn/doc/harmonyos-guid…

windows远程桌面连接限定ip

1&#xff0c;Windows防火墙->高级设置->远程桌面 - 用户模式(TCP-In)->作用域->远程IP地址 2&#xff0c;启用规则

ASP.NET Core - 配置系统之自定义配置提供程序

ASP.NET Core - 配置系统之自定义配置提供程序 4. 自定义配置提供程序IConfigurationSourceIConfigurationProvider 4. 自定义配置提供程序 在 .NET Core 配置系统中封装一个配置提供程序关键在于提供相应的 IconfigurationSource 实现和 IConfigurationProvider 接口实现&…