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

spring,mybatis,springboot,springmvc简单入门

一、软件架构 - 两种经典模式

  1. Client/Server(C/S)结构
    • 简单说就是 “客户端 + 服务器” 模式。比如手机上的微信 App、电脑上的 QQ,这些都属于 “客户端软件”。
    • 特点:需要专门安装客户端(像微信得下载 App),好处是能充分利用手机 / 电脑本地的硬件性能(比如让客户端处理一些数据计算),减少网络传输的压力。适合对交互性、性能要求高的场景(比如游戏、专业软件)。
  2. Browser/Server(B/S)结构
    • 也就是 “浏览器 + 服务器” 模式。现在常用的网页应用(比如在线文档、网页版邮箱)都属于这种 —— 只要电脑 / 手机装个浏览器(Chrome、Edge 等),直接通过网址访问就行。
    • 特点:不用专门装客户端,维护和更新更方便(服务器端改了,浏览器直接生效)。核心功能都在服务器上,客户端(浏览器)只负责显示和简单交互。适合大范围推广、跨设备使用的场景(比如企业办公系统、在线教育平台 )。

二、WEB 框架 - 开发效率神器

  • 可以理解为 “半成品的开发工具包”。比如盖房子时,框架就像预先搭好的 “钢筋骨架”,开发者不用从头开始设计整个结构,直接在上面填砖加瓦(写业务逻辑)。
  • 作用:提供现成的代码模板、工具(比如处理网络请求、操作数据库的通用代码),让程序员不用重复造轮子。像常见的 Spring Boot(Java)、Django(Python)都是 Web 框架,能快速搭建网站后台,处理登录、数据查询这些功能。

总结一下:

  • C/S 和 B/S 是软件的两种部署、使用模式,决定了用户怎么访问系统(装客户端 vs 用浏览器)。
  • Web 框架 是开发阶段的 “助力工具”,帮程序员更快写出 Web 应用,少写重复代码。
    本质是为了让开发更高效、维护更方便,适应不同的使用场景~

三、maven和springboot项目的创建

Maven 是 Apache 的一个顶级项目,是一个项目管理和构建自动化工具,主要用于 Java 项目,也可用于其他类型项目。

主要用于项目构建和依赖管理,右边的是Maven的依赖,可以通过搜索添加对应的依赖Maven Repository: org.springframework

Maven项目中首先需要看配置的本地仓库是否有对应的依赖,如果没有的话然后再看远程仓库是否有对应的依赖,如果还没有就去中央仓库看是否有需要的依赖项

依赖坐标

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion>
<!--  项目相关描述,公司名字路径和项目名-->公司域名<groupId>com.hualan</groupId>项目名称<artifactId>testmvn</artifactId>版本<version>1.0-SNAPSHOT</version>
<!--  项目写好之后的打包方式, 如果是web项目,就是以war包形式打包
父子项目时打包 pom包, 大多数时刻都是jar包--><packaging>jar</packaging><name>testmvn</name><url>http://maven.apache.org</url><properties>
<!--    设置项目的属性-->配置属性<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies>
<!--    项目依赖(maven管理):开发i项目时所需要的jar包都在这个结构里面
对pom文件更改后需要重新加载一下maven--><!--    下面是引入的jar包,jar包的配置,项目中添加单元测试模块包-->jar包<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version>
<!--      scope作用域:值test意思是只在test中使用,compile默认--><scope>test</scope></dependency>
<!--    mysql包:把jar的坐标写出来--><dependency>公司域名<groupId>com.mysql</groupId>项目名<artifactId>mysql-connector-j</artifactId><version>8.0.33</version>
<!--        作用域:运行时--><scope>runtime</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>RELEASE</version><scope>test</scope></dependency></dependencies>
</project>

这个和SpringBoot的依赖大致是相同的,Spring Boot是为了简化Spring开发而诞生的,使用Spring boot能快速创建Spring应用,简化开发,约定大于配置。

在创建Springboot项目时选择的镜像

Spring官方镜像: https://start.spring.io/
阿里镜像(主推):https://start.aliyun.com

四、Spring的IOC、DI、AOP

Spring 是一款目前主流的 Java EE 轻量级开源框架,是 Java 世界最为成功的框架之一。Spring 由“Spring 之父”Rod Johnson(罗宾·约翰逊) 提出并创立,其目的是用于简化 Java企业级应用的开发难度和开发周期。

Spring的核心:

  • IOC控制反转
  • AOP面向切面编程

1. IOC是控制反转

在java中普遍创建一个类再使用new来创建一个对象,代码冗余过大,现在通过一个@Component注解修饰一个实体类,将这个实体类交给IOC容器管理,在IOC容器里存放相对应的Bean对象。创建一个类用@Configuration和@ComponentScan("包路径")修饰,想要创建对象时,调用ioc容器,并获取里面相对应的bean对象,最后交给一个实例。(只能创建出一个实体类对应的对象。

  • 简而言之就是通过Spring来管理类对应的一个对象,使用时将IOC容器初始化获取里面的Bean对象即可。(单例模式,工厂模式)

  • Spring IoC 容器创建、组装、管理的 Java 对象被称为Spring Bean对象

image-20250809102918122

对象依旧保存在堆内存中

  • 方法1:

@Component + @Configuration注解创建对象的方式

@COmponent注解:将类交给Spring IOC容器管理并创建对应的Bean对象。
@Configuration注解:标注这个类是配置类。(也归IOC管理)
@ComponentScan(路径)注解:扫描路径中是否有被@Component注解修饰得类,如果有的话交给IOC容器管理并创建对应的Bean对象。

创建一个King类

//将类交给ioc容器管理,创建一个bean对象
//声明创建对象时,如果没有指定名字,会以类首字母代表对象名字
@Component(value = "aa")    //value是默认的对象名,指定的名字是aa类似于King aa = new King();
public class King {public void eat(){System.out.println("King正坐在吃东西");}
}

创建配置类

//表示是一个配置类,里面存放的都是bean对象
@Configuration
//@ComponentScan(basePackages = "com.hualan.springboot01.bean")   //扫描指定包中添加了Component注解的类,
// 让Component实现Bean对象的创建,放进ioc容器中.使用的时候直接在bean中取就可以了
@ComponentScan(value = "com.hualan.springboot01.bean")
public class MyConfig {}

测试类

@SpringBootTest
class SpringBoot01ApplicationTests {@Testpublic void testKing(){//创建一个IOC容器,通过配置类扫描配置类路径中的所有被@Component修饰的类,并创建对应的Bean对象ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);//痛过getBean方法获取到对应的bean对象King king = context.getBean("aa", King.class);//调用对象的方法king.eat();}/*
*   创建这个ioc容器会指定写入的配置类文件,然后会自动调用Scan的注解取扫描指定的包里带有Component注解的类
*   并创建相对应的bean对象,如果Component中没有设置value值的话,默认的对象名就是类名小写;有value值的话就是默认值
*   bean对象在ioc容器中管理
* */
}
  • 方法2:

使用Configuration + Bean注解创建对象

创建一个实体类

public class User {public void sayHello() {System.out.println("Hello World");}
}

创建一个配置类

//表示是一个配置类,里面存放的都是bean对象
@Configuration
//@ComponentScan(basePackages = "com.hualan.springboot01.bean")   //扫描指定包中添加了Component注解的类,
// 让Component实现Bean对象的创建,放进ioc容器中.使用的时候直接在bean中取就可以了
@ComponentScan(value = "com.hualan.springboot01.bean")
public class MyConfig {//在配置类追踪创建一个对象并标注是bean@Bean(value = "user")public User test(){return new User();}
}

创建测试类通过IOC容器获取

@SpringBootTest
class SpringBoot01ApplicationTests {@Testpublic void testKing(){//创建一个IOC容器,通过配置类扫描配置类路径中的所有被@Component修饰的类,并创建对应的Bean对象ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);//痛过getBean方法获取到对应的bean对象King king = context.getBean("aa", King.class);//调用对象的方法king.eat();User user = context.getBean("user", User.class);user.sayHello();}}

这个方法我感觉还没有上个方法好,

2. DI依赖注入

依赖注入就是实现IOC控制反转的一种方式,就是给一个类属性赋值的过程(取消手动初始化IOC容器的过程,可以直接通过Autowired自动装配在其他IOC管理的类中获取其他类的对象)。

但是通过手动初始化IOC容器的方式现在用的都不多了,因为现在不需要用代码再初始化IOC对象获取Bean了,启动类的注解已经包含了扫描的包和配置的类,会默认创建一个IOC容器,只需要对需要IOC容器管理的类加上@Component或者是他的子注解就可以了,在启动类或者是被@SpringBootTest修饰的测试类启动时,会自动扫描包创建IOC容器管理对应的类。需要调用时直接用@Autowired从IOC容器中取出对应的类的对象即可。可以直接对这个变量进行使用。

@SpringBootTest注解注意点

@SpringBootTest 本质是通过自动识别项目主配置、触发 Spring Boot 自动配置流程、整合测试框架生命周期,实现了 “零配置” 创建测试用 IOC 容器的效果。
这使得开发者无需手动编写容器初始化代码,就能在测试中直接使用与生产环境一致的 Bean,大幅简化了测试代码的编写
  • @Autowired自动装配(在IOC容器中通过类来获取对应的对象)Spring框架中的注解;
  • @Resource是默认按照名字获取对象的,如果名字不对应的话再按照类,是java中的注解。
  • 下面是ai给我的补充
需要明确的是,在现代 Spring Boot 应用中,手动初始化 IOC 容器的场景已极为罕见。这是因为:1. 应用的启动类通过`@SpringBootApplication`注解(其内部包含`@ComponentScan`等元注解)指定了需要扫描的包路径和配置类,也会初始化IOC容器;
2. 当应用启动时(包括被`@SpringBootTest`修饰的测试环境启动时),框架会自动完成 IOC 容器的初始化,并根据类上的`@Component`及其派生注解(如`@Service`、`@Controller`等)识别需要纳入容器管理的 Bean,完成这些 Bean 的创建与注册;
3. 当某个 Bean 需要使用其他 Bean 时,开发者无需手动从容器中获取,只需在依赖字段、构造方法或 setter 方法上使用`@Autowired`等注解,容器便会在初始化当前 Bean 时自动完成依赖注入,开发者可直接使用注入后的对象进行业务操作。

用的比较多的还是@Autowired注解

  • DI就是给属性赋值的一个方式;

  • 说白了依赖注入实现的一种方式就是将ioc容器里面的对象给到另一个对象的属性里面;

3. 依赖注入的方式

  1. 构造器注入

    @Service
    public class UserService {private final UserRepository userRepository;// 构造方法注入@Autowired  // Spring 4.3+ 对单构造方法可省略此注解public UserService(UserRepository userRepository) {this.userRepository = userRepository;}
    }
    
  2. Setter方法注入

    @Service
    public class OrderService {private PaymentService paymentService;// Setter方法注入@Autowiredpublic void setPaymentService(PaymentService paymentService) {this.paymentService = paymentService;}
    }
    
  3. 字段注入

    特点:代码简洁,不需要构造器和Setter方法@Controller
    public class UserController {// 字段注入@Autowiredprivate UserService userService;
    }
    
  4. 通过注解注入

    • 创建一个实体类
    @Component
    //交给IOC容器并创建对应的对象
    public class Teacher {@Value("美汁汁")private String name;@Value("19")private int age;@Value("男")private String sex;@Overridepublic String toString() {return "Teacher{" +"name='" + name + '\'' +", age=" + age +", sex='" + sex + '\'' +'}';}
    }
    
    • 创建一个测试类
    @SpringBootTest
    public class TestNote {//通过@Autowired自动装配获取Bean中的Teacher对象,使用环节@AutowiredTeacher teacher;@Testpublic void testTeacher() {//测试类将teacher对象的内容输出System.out.println(teacher);}
    }
    
  5. 在配置文件里配置(yml文件)

    • 创建一个实体类
    @Component
    @ConfigurationProperties(prefix = "teacher")
    //交给IOC容器并创建对应的对象
    public class Teacher {
    /*    @Value("美汁汁")private String name;@Value("19")private int age;@Value("男")private String sex;*/@Value("${teacher.name}")private String name;@Value("${teacher.age}")private int age;@Value("${teacher.sex}")private String sex;@Overridepublic String toString() {return "Teacher{" +"name='" + name + '\'' +", age=" + age +", sex='" + sex + '\'' +'}';}
    }
    
    • 在配置文件中写需要写进去的内容(yaml)
    teacher:name: 美滋滋age: 20sex: 男
    
    • 创建一个测试类
    @SpringBootTest
    //标识的是启动类中的@SpringBootApplication注解,启动项目,会扫描启动类所在的包下所有的包和子包(其实就是扫描整个项目的包)
    public class TestNote {//通过@Autowired自动装配获取Bean中的Teacher对象@AutowiredTeacher teacher;@Testpublic void testTeacher() {//测试类将teacher对象的内容输出System.out.println(teacher);}
    }
    

多种方法现在用的最多的还是第三种直接在字段上直接添加@Autowired注解直接注入。

说一下@Autowired和@Resource两者的区别

@Autowired:
默认按照类型(byType)进行自动装配
当容器中存在多个相同类型的 Bean 时,会抛出 NoUniqueBeanDefinitionException
可以结合 @Qualifier 注解指定要注入的 Bean 的名称(byName)
@Qualifier:
不能单独使用,必须与 @Autowired 配合
指定要注入的 Bean 的名称,解决同类型多个 Bean 的冲突问题
(如果有相同的类型的话可以用@Qualifier注解指定名)----------------------------------------------------------------
@Resource(注意是 javax.annotation.Resource,不是 Spring 的注解):
默认按照名称(byName)进行装配
如果找不到对应名称的 Bean,会再按照类型(byType)进行装配
可以通过 name 属性指定要注入的 Bean 的名称

五、Spring整合Mybatis

重点:持久层框架持久指的是什么(通过Mybatis可以将对象的数据存储到数据库里面);mybatis的概念;ORM什么;如何实现;

动态参数

1. Mybatis介绍

  • MyBatis 是一个优秀的 Java 持久层框架,用于简化jdbc开发,,半自动化ORM框架,通过 XML 或注解方式将 SQL 语句与Java 方法进行映射,简化数据库操作,提供了灵活的 SQL 管理能力,同时保留了对原生 SQL 的完全控制。MyBatis 本是 Apache 的一个开源项目 iBatis,2010年这个项目由Apache Software Foundation迁移到了Google Code,并且改名为MyBatis。
  • 本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件 + 配置几个sql映射文件,易于学习,易于使用。通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
ORM:对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与
关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映
射的元数据,将程序中的对象自动持久化到关系数据库中

通常业务上将java项目分为三层

1、controller 控制层 (响应前端)

2、service 业务层 (写逻辑代码)

3、dao 持久层(其实就是写数据的,创建对象的)

2. Mybatis的快速入门

在程序中,数据库表里面的字段名需要与实体类中字段名都相同(java中更支持用对应的包装类),sql表中的一行内容对应的是java中的一个对象,通常用对象来接收一行内容,那么多行就需要用到一个集合来接收这整个表里面对应的内容,

在idea中使用Mybatis查询数据库表

1. 需要导入一些包将Mybatis整合进Spring项目中

<!--        mysql驱动包--><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version><scope>runtime</scope></dependency>
<!--        引入mybatis包启动器--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.1</version></dependency>

2. xml文件负责连接本地数据库

jdbc:mysql://				是协议部分
localhost:3306/数据库名		  是端口号和数据库名
下面是完整的
spring:datasource:# 配置驱动类driver-class-name: com.mysql.cj.jdbc.Driver# 数据库连接 jdbc:mysql://127.0.0.1:3306/数据库名url: jdbc:mysql://127.0.0.1:3306/user# 数据库的用户名和密码username: rootpassword: 123456

3. 创建一个实体类

//实体类
@Data
//在编译时期为所有属性添加get/set方法和toString(),hashcode(),equals(),不包括无参和有参构造
@NoArgsConstructor
//提供一个无参构造器
@AllArgsConstructor
//提供一个有参构造
//需要在pom文件里面添加一个lombok依赖的jar包
public class User {private Integer id;private String name;private Short age;private Short gender;private String phone;/*public User() {}public User(Integer id, String name, Short age, Short gender, String phone) {this.id = id;this.name = name;this.age = age;this.gender = gender;this.phone = phone;}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 Short getAge() {return age;}public void setAge(Short age) {this.age = age;}public Short getGender() {return gender;}public void setGender(Short gender) {this.gender = gender;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", gender=" + gender +", phone='" + phone + '\'' +'}';}*/
}

4. 在项目包目录下创建一个mapper包,并创建UserMapper接口然后编写sql语句

@Mapper
//运行时框架会自动生成实现类对象,并且将对象交给IOC容器管理
public interface UserMapper {//查询全部用户信息@Select("select * from user")public List<User> getUser();
//接口会动态生成对应的实现类对象
}

5. 单元测试:在测试类中测试userMapper接口里面的方法

@SpringBootTest
//整合单元测试的注解,会默认创建测试的IOC容器
class HeimaMybatisApplicationTests {//自动装配@AutowiredUserMapper userMapper;@Testpublic void getUser(){//获取到的是一个集合,返回的都是对象,for (User user : userMapper.getUser()) {System.out.println(user);}}
}

3. 什么是jdbc?

sun公司提供的使用java语言操作关系型数据库的API就是jdbc, 但是还是各个厂商提供jdbc的实现(Mysql,oracle...),我们直接使用jdbc提供的接口就可以了,厂商写的实现统称为驱动,

JDBC(Java Database Connectivity)是 Java 语言操作数据库的标准 API(应用程序编程接口),它为 Java 程序提供了一套统一的方法来访问各种关系型数据库(如 MySQL、Oracle、SQL Server 等)

六、Mybatis的基本操作(增删改查CRUD)

  • 进行增删改查的基本顺序就是下面,但是基本先把配置文件写好
# 数据库驱动
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/shifangzhiyuusername: rootpassword: 123456mybatis:# 映射文件mapper-locations: classpath:mapper/*.xml# 包别名type-aliases-package: com.hualan.pojoconfiguration:# 配置日志log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# 让表字段(有下划线)与对象的属性(小驼峰)形成映射关系,否则会因为数据字段属性名不同导致映射关系失败map-underscore-to-camel-case: true# 进程死锁时候,设置sql超时时间,单位是秒(s)default-statement-timeout: 20# 分页插件
pagehelper:reasonable: true
  • 还有就是pom.xml文件里需要导入需要的jar包的坐标
        <!--mysql驱动包--><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version><scope>runtime</scope></dependency><!--mybatis启动包--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.1</version></dependency><!--lombok包--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency>

1. 开始进行mybatis的基本操作

以上是基本操作 , 下面才开始真正的增删改查操作哈哈哈,开始下手吧

  1. 先创建实体类
    • 实体类的属性与数据库表的数据类型相同
    • 属性名以大驼峰形式,数据库名有 '_' 下划线表示
  2. 再创建对应的Mapper接口文件
    • Mapper接口文件里面写方法;
    • 接口文件里面的方法写几个映射文件里就需要写几个sql语句;
  3. 然后在resource包里创建一个Mapper映射文件
    • 映射文件里面写SQL语句;
  4. 最后在测试类中测试写的方法

实体类Student写在pojo包里 , 接口文件写在mapper包里 , 两个包都在项目名下

  • 创建一个Student实体类
//实体类
@Data	//get/set/toString()/hashCode()/equals()方法
@NoArgsConstructor  //空参构造
@AllArgsConstructor //有参构造
public class Student {private Integer id;private String name;private Integer age;private String gender;private Date birthday;private String homeAddress;}
  • 再创建对应的mapper接口文件
    • @Mapper 注解是 MyBatis 框架的注解 , 其核心作用是标识该接口是 MyBatis 的映射接口,告诉 MyBatis 框架 “需要为这个接口生成动态代理实现类”,将动态代理实现类交给创建成bean对象并交给ioc容器管理
//交给ioc容器管理(可以创建接口的动态代理对象)
@Mapper
//属于mybatis里面的注解,关联到对应的xml文件之后,
// 在映射文件中必须写出与方法对应的sql语句
//增删改返回值类型都是int(影响到xx行数据)查询的结果是对应的自定义数据类型
public interface StudentMapper {//增public abstract int addStudent(Student student);//删//删除一条学生信息public abstract int deleteStudentById(Integer id);//改//修改指定学生信息public abstract int updateStudent(Student student);//查//根据姓名找到学生信息public abstract List<Student> getInfoByName(String name);//查询所有的学生信息public abstract List<Student> StudentList();//查询student对象总数public abstract Integer getStudentCount();//根据学生id获取对应的学生信息public abstract Student getInfoById(Integer id);//根据姓名模糊查询public abstract List<Student> getInfoByNameLike(String name);
}
  • 在resource包下创建一个mapper包并创建一个对应的Mapper映射文件

    • 在这个mapper映射文件里面写sql语句,而且需要将接口文件里面的所有抽象方法都实现了;

    • namespace : 命名空间,填充的是接口文件的类路径 , 让xml文件与接口文件之间产生关联 , 需要写出对应的mapper接口文件的类地址 , 如 : edu.henu.mapper.xxMapper

    • resultType : 对应的是返回值类型的类地址(自定义类型需要将类地址全部都写出来,如:edu.henu.pojo.xx) 一般集合元素返回值数据类型写的是泛型里规定的数据类型

      image-20250811211601526

    • parameterType:对应的是接口文件里面方法里写的形式参数的数据类型的类地址 (一般都是实体类的类型)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--映射文件-->
<mapper namespace="com.hualan.mapper.StudentMapper">
<!--    namespace:命名空间,值是接口文件的类路径,让xml文件与接口文件之间产生关联-->
<!--    接口中的方法必须在xml文件中有对应的SQL语句-->
<!--    返回值类型是自定义类对象的数据类型需要写类的类路径-->
<!--    增 insert--><insert id="addStudent" parameterType="Student">insert into student values( null, #{name}, #{age}, #{gender}, #{birthday})</insert><!--    删 delete--><delete id="deleteStudentById" parameterType="Integer">delete from student where id = #{id};</delete><!--    改 update--><update id="updateStudent" parameterType="Student"><!---->update student set name = #{name}, age = #{age}, gender = #{gender}, birthday = #{birthday} where id = #{id};</update><!--    查 select--><!--获取学生总数--><select id="getStudentCount" resultType="Integer">select count(*) from student;</select><select id="getInfoByName" parameterType="java.lang.String" resultType="Student">select * from student where name = #{name};</select><!--    java接收数据的时候用的是一个对象接收,所以用的是一个Student类型的数据,
返回值类型:resultType:写的是一个类路径(从公司域名开始写)--><!--获取所有的学生信息 当返回的是一个集合时,返回值类型resultType直接写泛型的数据类型即可--><select id="StudentList" resultType="Student">select * from student order by birthday desc;</select><!--    parameterType代表的是接受的参数类型--><!--根据id获取学生信息--><select id="getInfoById" resultType="Student" parameterType="Integer">
<!--  #{形参名字}是条件语句 预编译的模式-->select * from student where id = #{id};</select>----------------------------------模糊查询的方式------------------------------------------用concat()方式用多了
<!--    查询方式一: 用concat()函数拼接的方式进行模糊查询-->
<!--    <select id="getInfoByNameLike" parameterType="string" resultType="Student">select * from student where name like concat('%', #{name}, '%');</select>--><!--查询方式2: -->
<!--    <select id="getInfoByNameLike" parameterType="string" resultType="Student">select * from student where name like '%' #{name} '%';</select>--><!--查询方式3: 用的不多--><select id="getInfoByNameLike" parameterType="string" resultType="Student">select * from student where name like '%${name}%';</select></mapper>形式参数

resultType:是自动映射,可以将数据库表中的字段自动对应到java实体类属性对应的属性上

resultMap是手动映射,下面再写。

需要知道#{} 与 ${}的区别?

传参传进去的参数在SQL语句中可以用 #{参数名} 代表一个值,select * from student where id = 1等同于 select * from student where id=#{id},前提是id的传进去的参数

同理传进去的对象,可以用#{对象属性}代表一个值, 类似于 name=#{name} ,后面的#{name}是传入参数的对象属性

#{} 与 ${}的区别?1. #{}:预编译处理(参数绑定)
MyBatis 会将 #{} 替换为 SQL 中的 ? 占位符,然后通过 JDBC 的 PreparedStatement 进行预编译,再将参数值填充到占位符中。
示例:
SQL 映射中写 SELECT * FROM user WHERE id = #{id},实际执行时会变为:
SELECT * FROM user WHERE id = ?(预编译后,参数 id 的值通过 setInt() 等方法传入)。2. ${}:字符串拼接(直接替换)
MyBatis 会直接将 ${} 替换为参数的字符串值,相当于简单的字符串拼接,不会进行预编译处理。
示例:
SQL 映射中写 SELECT * FROM user WHERE psd = ${psd},若参数 psd 为 ' or 1 ',则实际执行的 SQL 是:
SELECT * FROM user WHERE psd = '' or 1 ''(参数值直接拼接到 SQL 中)。导致sql注入简单说:${参数} 会导致字符串拼接,存在sql注入的风险,可能会拼接sql语句#{参数} 预编译阶段,较为安全,防止sql注入,传递的是数值#{} 是 MyBatis 的预编译参数占位符,会转为 ? 并通过 JDBC PreparedStatement 安全传
参,能有效防止 SQL 注入,推荐用于传递字段值等。
${} 是 MyBatis 的字符串替换符,会直接将变量值拼接到 SQL 语句中,不进行预编译或转
义,存在 SQL 注入风险,一般只用于动态表名、列名等可信场景
  • 创建一个测试类
@SpringBootTest
public class TestCRUD {@Autowiredprivate StudentMapper studentMapper;//添加学生信息@Testpublic void testStudent(){//创建学生对象Student student = new Student();student.setName("张无忌");student.setGender("男");student.setAge(18);student.setBirthday(new Date());//添加学生信息int result = studentMapper.addStudent(student);System.out.println(result);}//删除学生信息@Testpublic void testDeleteStudent(){int result = studentMapper.deleteStudentById(1);System.out.println(result);}//修改学生信息@Testpublic void testUpdateStudent(){//修改学生信息需要先获取到要修改的学生对象,然后对这个对象的某些属性进行修改Student student = studentMapper.getInfoById(5);student.setName("朱重八");student.setAge(20);int result = studentMapper.updateStudent(student);System.out.println(student);System.out.println(result);}@Testpublic void testGetStudentByName(){List<Student> list = studentMapper.getInfoByName("张无忌");System.out.println(list);}@Testpublic void testShowStudent(){List<Student> students = studentMapper.StudentList();for (Student student : students) {System.out.println(student);}}//根据姓名模糊查询@Testpublic void selectLikeByName(){List<Student> students = studentMapper.getInfoByNameLike("张");for (Student student : students) {System.out.println(student);}}@Testpublic void testSelect(){//获取学生信息System.out.println(studentMapper.StudentList());//获取学生总数System.out.println(studentMapper.getStudentCount());//根据学生id获取学生信息System.out.println(studentMapper.getInfoById(1));}
}

2. Mapper接口多个参数的模糊查询

Mapper接口多个参数的查询方式我用了3种

  1. 通过传入一个对象,对对象属性进行模糊查询
  2. 传入一个Map集合,定义对应的字段进行查询
  3. 传入多个参数,与多个参数进行对比(多个参数需要用多个@Param("别名")来重命名参数)
  4. 通过传进去

1、通过传入一个对象的方式,解决多个条件查询问题

  • 实体类Teacher
@Data   //相当于getter/setter方法和hashCode()和equals()还有toString()方法
@NoArgsConstructor  //无参构造器
@AllArgsConstructor //有参构造器
public class Teacher {private Integer id;private String name;private Integer age;
}
  • 编写对应的Mapper接口文件
@Mapper
public interface TeacherMapper {//根据姓名模糊和年龄具体查询public abstract List<Teacher> getTeachersByNameAndAge(Teacher teacher);//根据姓名模糊和年龄范围查询public abstract List<Teacher> getTeachersByNameAndRangeAge(Map<String, Object> params);//注解的方式/*低版本的Mybatis不支持多参数直接使用别名,所以说需要使用@Param注解设置一个别名*/public abstract List<Teacher> getTeachersByNameAndRangeAge02(@Param("name") String name, @Param("minAge") Integer minAge,@Param("maxAge") Integer maxAge);
}
  • 编写对应的Mapper.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hualan.mapper.TeacherMapper">//通过传进来一个对象进行多参查询<select id="getTeachersByNameAndAge" parameterType="Teacher" resultType="teacher">select * from teacher where name like concat('%', #{name}, '%')and age = #{age};</select>//通过传进一个map集合进行多参查询<select id="getTeachersByNameAndRangeAge" resultType="teacher" parameterType="java.util.Map">select * from teacher where name like concat('%', #{name}, '%')and age between #{minAge} and #{maxAge}</select>//通过传进多个参数进行查询<select id="getTeachersByNameAndRangeAge02" resultType="teacher">select * from teacher where name like concat('%', #{name}, '%')and age between #{minAge} and #{maxAge}</select></mapper>
  • 编写测试类
@SpringBootTest
public class TestTeacher {@Autowiredprivate TeacherMapper teacherMapper;@Testpublic void testTeacher01() {Teacher teacher = new Teacher();teacher.setName("云");teacher.setAge(50);//获取到名字里带云的,并且年龄等于50岁。List<Teacher> teachers = teacherMapper.getTeachersByNameAndAge(teacher);for (Teacher teacher1 : teachers) {System.out.println(teacher1);}}
}

2、通过传进去一个map集合进行多参查询

  • 依旧使用Teacher实体类
  • 依旧使用上面的Mapper接口文件创建方法 getTeachersByNameAndRangeAge
  • 上面的Mapper.xml文件里面的,可以将map集合里面的key名直接用#{key名}包裹代表一个值可以映射到value,与数据库字段名进行对比
	//通过传进一个map集合进行多参查询<select id="getTeachersByNameAndRangeAge" resultType="teacher" parameterType="java.util.Map">select * from teacher where name like concat('%', #{name}, '%')and age between #{minAge} and #{maxAge}</select>
  • 编写测试类
    @Autowiredprivate TeacherMapper teacherMapper;//用Map集合传参@Testpublic void testTeacher02() {Map<String, Object> map = new HashMap<>();map.put("name", "云");map.put("minAge", 20);map.put("maxAge", 60);teacherMapper.getTeachersByNameAndRangeAge(map);}

3、通过写进去多个参数用@Param("别名") 给单个属性设置别名可以用写的别名在xml映射文件中使用

​ 注意:

1. 多个参数时可以使用@Param给形参一个别名,如果不给的话就是arg0,arg1....可读性不高;
2. 亦或者参数是一个集合泛型,也需要用@Param给集合设置一个别名。
  • 上面接口文件中第三个查询方法就是通过多个参数设置别名
    //注解的方式/*低版本的Mybatis不支持多参数直接使用别名,所以说需要使用@Param注解设置一个别名*/public abstract List<Teacher> getTeachersByNameAndRangeAge02(@Param("name") String name, @Param("minAge") Integer minAge,@Param("maxAge") Integer maxAge);
  • 映射文件里面的内容如下
	//通过传进多个参数进行查询<select id="getTeachersByNameAndRangeAge02" resultType="teacher">select * from teacher where name like concat('%', #{name}, '%')and age between #{minAge} and #{maxAge}</select>
  • 测试类测试内容
    @Testpublic void testTeacher03(){List<Teacher> teachers = teacherMapper.getTeachersByNameAndRangeAge02("云", 20, 60);System.out.println(teachers);}

3. 分页插件

  • 导入依赖包
<!--手动引入pagehelper的启动器-->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.1</version>
</dependenc
  • 在配置类中配置分页内容(用的是yaml文件,所以说里面很注重缩进的内容)
# pagehelper配置
pagehelper:
#开启合理化分页reasonable: true
  • 对上面写的Student实体类进行查询并且使用分页插件进行分页
@Authord
StudentMapper studentMapper;
@Test
public void fenye(){
// 1 设置分页信息PageHelper.startPage(2,2);
// 2 查询List<Student> students = studentMapper.selectAll();// 3 动态获取分页后相关的数据参数PageInfo<Student> pageInfo = new PageInfo<>(students);System.out.println(pageInfo.getTotal()); // 总条数System.out.println(pageInfo.getPageNum()); // 页码System.out.println(pageInfo.getPages()); // 总页数System.out.println(pageInfo.getPageSize()); // 每页展示条数System.out.println(pageInfo.getList()); // 数据集合
}

4. 动态SQL查询

主要是因为平时的条件查询就是通过将条件写死,不能修改直接进行查询,如果需要根据其他条件进行查询的时候需要再编写一条查询语句,所以说就需要动态sql查询

主要就是在xml映射文件里面进行修改,例如在进行修改的时候通过 xx如果条件判断为true的话,就会执行对应的sql语句

    <!--改--><update id="updateCertificate" parameterType="certificate">update tb_certificate<set><if test="certiName != null and certiName!=''">certi_name = #{certiName},</if><if test="image != null and image != ''">image = #{image},</if><if test="id != counselorId">counselor_id = #{counselorId}</if></set>where id = #{id}</update>

还有就是用xx这样的结构也可以进行动态sql查询

    <update id="updateCertificate" parameterType="certificate">select* from tb_certificate<where><if test="certiName != null and certiName!=''">certi_name = #{certiName} and</if><if test="image != null and image != ''">image = #{image} and</if><if test="id != counselorId">counselor_id = #{counselorId}</if></where></update>

如果只有一条sql条件满足的话标签可以将sqlwhere条件筛选中多余的and不识别。

image-20250814202747905

1. if条件判断语句,判断这段语句是否参与sql查询,只有满足条件才会被拼接到sql语句中
<select id="findUsers" resultType="User">SELECT * FROM user<where><if test="name != null">AND name = #{name}</if><if test="age != null">AND age = #{age}</if></where>
</select>
2. —— 多路选择(类似switch-case),我没用过,如果类似于switch-case那是不是就可以用if替代了哈哈哈
<select id="findActiveUser" resultType="User">
SELECT * FROM user
<where>
<choose>
<when test="status == 1">
AND active = 1
</when>
<when test="status == 0">
AND active = 0
</when>
<otherwise>
AND deleted = 0
</otherwise>
</choose>
</where>
</select>
3. 标签都可以消除拼接的sql语句中其他的类似于逗号and一类的关键字
4.循环语句,可以用于批量删除等操作,主要是对输入的集合参数进行循环遍历,一一拼接到sql语句中,写这个集合参数的时候需要用@Param(“”)设置别名
<select id="findByIds" resultType="User">SELECT * FROM userWHERE id IN<foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
</select>上面代码中foreach中各个属性代表的含义分别是collection="集合名",这里的集合名就是参数设置的别名,如果没有设置别名的话好像用arg0表示item="",这个item表示的是遍历到的集合元素的名字open="(",就是将 in()这个前面的半个括号补全close=")",就是将in()后面的半个括号补全separator=","意思是元素与元素之间的分隔符
最后都会参与sql语句拼接
5. 还有一个自定义裁剪字符串,我没用过
<trim prefix="WHERE" prefixOverrides="AND |OR "><if test="name != null">AND name = #{name}</if><if test="age != null">OR age = #{age}</if>
</trim>
6. sql片段,就是查询语句中因为用select * from....星符号对比将所有字段写出来会浪费性能,所以说为了避免多次重复写所有字段导致代码冗余度过高,用标签将会重复多次出现的代码都包括在一起,并设置一个 属性 id="", 根据这个属性对这个sql片段进行调用即可,用标签属性refid=""使用对应的sql片段
<!-- 定义一个sql,来定义其通用的查询的前半部分 -->
<sql id="sl">select id,name,sex,age from student
</sql><select id="selectByLikeName3" parameterType="java.lang.String"
resultType="student">
<include refid="sl"></include>
where name like '%${name}%'
</select>

七、表与表之间的关系

学习mysql时知道表与表之间的关系主要分为三种

  1. 一对一

    • 用association标签进行一对一实体类属性和数据库表字段之间的映射
  2. 一对多

    • 一对多主表对应的实体类扩展私有属性为从表对象对应的集合
    • 自定义一对多之间的映射
  3. 多对多(查询的时候需要中间表关联)

    • 看待单个对象时也是一对多的关系,在私有属性中添加从表对象对应的集合
    • 标签映射从表对应的属性

多对多映射中,对于一张表中的一个对象而言,另一张表跟它之间就是一对多的关系,返回的是一个集合

解决多表问题时通常建立在一下流程上(数据库中已经有对应的表)

1. 分析两张表之间的关系,确定主表,在navicat上先把sql语句写出来确定自己需要的表内容和字段,最后写的时候可以根据这个内容进行判断
2. 在主表的实体类私有属性上添加对应的从表的对象或者是对象对应的集合泛型
3. 编写Mapper接口文件
4. 编写Mapper.xml映射文件,在映射文件中用resultMap进行手动映射

注意:多表查询的时候先确定主表,分析出多张表之间的主表然后利用表与表之间的关系进行

在多表联查的关系中不能再用到 resultType进行自动映射 , 需要用到 resultMap进行手动映射,先拿一段代码把映射的规则说一下

  • 首先就是把结果的返回值resultType换成resultMap,再在外面通过双标签里面的自定义属性值id的值给到resultMap
  • 自定义的resultMap标签返回的值是mapper接口文件里面方法返回的返回值类型
  • 然后可以把要查的属性一一对应,主键用标签绑定,其他的属性用标签绑定,column对应的是数据库表中的字段名,property对应的是实体类的属性名。(如果数据库里面设置了别名,那就一定要用别名,防止字段不能映射到)
  • 如果是一对一的关系的话将从表对应的实体类在主表对应的实体类中创建出对应的对象的私有属性,然后在resultMap自定义映射中,用标签将另一个实体类中的字段与属性一一对应上(起别名用别名)
  • 在一对一映射中,association标签获取返回值类型用的是javaType,一对多中collection标签属性用的是ofType获取返回值类型

下面是自定义映射关系有一对一,一对多的关系中使用collection标签和association分别映射的例子,不用看sql语句,看映射关系就行

			# 对应第一点说的自定义id属性值    
<resultMap id="consultant_contant_level" type="consultantLevel"><id property="id" column="id"></id><result property="levelName" column="cl_name"></result><collection property="consultantList" ofType="consultant"><id property="id" column="id"></id><result property="name" column="name"></result><result property="image" column="image"></result><result property="age" column="age"></result><result property="levelId" column="level_id"></result><result property="intro" column="intro"></result><result property="isCertified" column="ct_ic"></result><result property="createdAt" column="created_at"></result><result property="updatedAt" column="updated_at"></result></collection></resultMap># 第一点说的resultMap标签里的自定义id值对应的就是这个resultMap属性对应的值<select id="getConsultLevel" resultMap="consultant_contant_level">select cl.*, ct.*, cl.level_name cl_name, ct.name, ct.image, ct.is_certified ct_ic from consultant_level clleft join consultant ct on ct.level_id=cl.id;</select>------------------------------------------------------------------------------------------------------<resultMap id="response_consult" type="consultService"><id property="id" column="id"/><result property="userId" column="user_id"/><result property="askContent" column="cs_ac"/><result property="consultantId" column="consultant_id"/><result property="status" column="status"/><result property="addTime" column="cs_at"/><result property="endTime" column="end_time"/><!--一对一--><association property="psyResponse" javaType="PsyResponse"><id property="id" column="id"/><result property="replyContent" column="pr_rc"/><result property="replyTime" column="pr_rt"/><result property="userId" column="user_id"/><result property="consultId" column="consult_id"/></association><association property="consultationRating" javaType="consultationRating"><id property="id" column="id"/><result property="userId" column="user_id"/><result property="consultId" column="consult_id"/><result property="startNum" column="start_num"/><result property="judgeContent" column="judge_content"/><result property="judgeTime" column="judge_time"/><result property="consultId" column="consult_id"/></association></resultMap><select id="getConsultServiceByUser" resultMap="response_consult">SELECT cs.*, cs.add_time cs_at, cs.ask_content cs_ac, pr.reply_content pr_rc, pr.reply_time pr_rt, cr.*from consult_service cs left join psy_response pr ON cs.id = pr.consult_id LEFT join consultation_rating cr on cs.id=cr.consult_idWHERE cs.user_id = 1 and cs.`status`= 1;</select>

在这种映射关系中可以只写出需要查询的字段属性他们的映射关系,其他不查询可以不映射。

注意:

1. 如果我用的是yaml文件进行配置的话,需要将properties配置文件里面的所有内容都删除,或者把properties文件删除,不然他的优先级高于yaml,会导致properties文件里面的内容先生效,等于说yaml文件配置不会生效;这也是我大意遇到的一个问题,发现映射文件找不到mapper,我以为yaml文件里面数据库连错了,发现还真是,结果我改回来之后还是不行,最后把所有接口文件写完,测试全部报错,最后误触了properties文件,发现里面的内容没有删除.........对自己好无语
2. 在多表联查中先将sql查询语句写出来,然后在编写接口文件中的方法和对应的mapper.xml文件中的方法,将映射关系一一对应出来,可以只展示部分只想展示的字段。

下载了mybatis-X之后可以直接生成对应的实体类,mapper接口文件,mapper.xml映射文件

image-20250815204405397

image-20250815204419350

只有第二张图的mapper文件需要改变路径;

八、springboot的基本使用

springboot框架主要就是简化spring框架的开发,等同于springMVC+Spring的效果,可以轻松写出来一个web接口(RequestMapping+方法),springboot内置了tomcat服务器,项目可以直接跑起来并通过http提供服务,不用额外部署

下面是我的理解:

在springboot项目跑起来之后会将项目部署到tomcat服务器,tomcat服务器主要就是负责监听客户端和服务端之间的数据请求和响应的过程,
前端请求时,tomcat会按照http协议解读请求内容,然后将内容交给后端服务器(就是springmvc)进行处理;
服务器会对前端的请求做出响应,这个时候,tomcat服务器会将相应的数据按照http协议发给前端。-- 下面的是我刚听到时的理解tomcat监听前端发送过来的数据,并按照http协议规定的形式解读,解读完毕之后,将数据交给springmvc框架,springmvc框架将数据交给controller控制器类,将数据交给方法处理,通过tomcat将数据按照http协议响应出去,将处理结果返回给前端用一个@Controller或@RestController来标记一个类是控制层的类。

Spring Boot 内嵌了 Tomcat 服务器,因此在启动时无需额外部署,应用可直接通过内置的 Tomcat 监听 HTTP 请求,快速提供 Web 服务。

1. HTTP协议

我的理解http协议就是浏览器和服务器之间数据交互的一种协议,所有的数据都需要按照这个规定传输。

  • HTTP(HyperText Transfer Protocol),即超文本传输协议。这个协议详细规定了浏览器和万 维网服务器之间互相通信的规则。
  • HTTP协议的作用:HTTP就是一个通信规则,通信规则规定了客户端发送给服务器的内容格式,也 规定了服务器发送给客户端的内容格式。
  • 客户端发送给服务器的格式叫“请求协议”【也称之为请求报文】;
  • 服务器发送给客户端的格式叫“响应协议”【也称之为响应报文】;
1.请求协议的主要结构:
  1. 请求行:包括请求方式,请求资源路径,http协议版本
  2. 请求头:都是以键值对的形式存在的,记住其中一个 User-Agent,它可以显示发送请求的设备型号,通过具体的参数对本次请求进行详细的说明;
  3. 请求体:包含了请求的内容(只有post请求方式的请求内容才放在请求体中)

image-20250817104357720

2. 请求方式:

image-20250817104430983

目前我初学者用得比较多的还是增删改查对应的四个请求方式:

讲解一下post和get两种请求方式有什么不同点:

  1. get请求主体在地址栏,post请求主体在请求体中
  2. post请求对比get请求方式更加安全
  3. 编码方式不同,get请求用的是地址栏编码,post用的是二进制编码,将参数转换成二进制进行传递
  4. 参数长度不一,get请求方式请求长度有限,但是post请求方式理论上是可以无限长的。
3. 响应数据的主要结构:
  1. 响应行:包含协议和状态码
  2. 响应头:
  3. 响应体:函数的返回参数

状态码如下:

image-20250817105049991

目前见过最常见的就是:

500:服务器出现错误,也可能是后端代码写错了
404:请求路径找不到
405:请求的方式与测试用的请求方式有误
400:前端请求内容错了
200:测试成功通过3xx:重定向(我的理解就是平时地址栏只搜一个baidu,他就会直接给你弄到www.baidu.com我认为这样可能就是重定向)

http协议中定义了浏览器发送请求的打包方式,加密方式,传输方式,传输信息,传输速度等等标准 URL(统一资源定位符)格式: http://ip:端口号/资源信息

  • 在浏览器中可以通过 :http://localhost:8080/接口路径发送请求,后端服务器会响应
  • https是http的升级,加入了更加复杂的加密方式。

这个是后端和前端交互的三层架构

主要就是controller控制层,service业务逻辑层,mapper数据访问层

  • controller控制层负责的是接收前端请求数据并且通过调用service层的方法响应前端数据,主要是负责与前端交互

  • service业务逻辑层主要负责代码的逻辑

  • mapper数据访问层主要是负责与数据库进行交互

image-20250817103614260

2. Controller控制层

​ 通过一个@RestController注解标识一个类是controller层(一个@Controller注解也可以但是不会把方法返回值作为响应主体返回出去),@RestController相当于是@ResponseBody注解和@Controller注解的合并,所以说@RestController注解的主要作用就是标识一个类是控制类,并且还可以将服务器响应数据作为响应主体返回给前端

​ 通常在controller层定义的方法和@RequestMapping被称为后端接口。

​ 在控制层还有一个日志输出较为常用的注解:@Slf4j 可以创建一个log对象,通过log.info("")代替sout的方式输出日志。

下面是ppt里一些对上面的注解的一些解释,上面是我的理解

@RestController1. Spring MVC 提供的注解,用于处理 HTTP 请求并返回数据,常用于前后端分离项目中为前端(如 
Vue/React/移动端)提供数据接口。
2. 用于构建RESTful API,自动将返回值序列化为JSON/XML并作为HTTP响应体返回。
3. 简化了RESTful服务开发,无需在每个方法上添加@ResponseBody。
单体项目:单体项目是将所有功能模块(包括前端、后端、数据库访问等)集成在一个统一的应用程序中开发的传统架构,适合小型项目,但扩展性和维护性较差。 
前后端分离项目:前后端分离项目是将前端界面与后端服务独立开发、部署和维护的现代架构,具有高灵活性、可扩展性和多端适配能力,是当前主流的开发模式。
@Controller 是 Spring MVC 中用于处理 HTTP 请求并返回视图(如 HTML/JSP/Thymeleaf 
页面)的注解,常用于单体项目中构建服务端渲染的传统 Web 应用。

Controller层代码如下:

@Slf4j
//这个注解可以直接使用日志对象输出日志,不用再创建对象了
@RestController
@RequestMapping("depts")
public class DeptController {//创建一个日志记录对象//private static Logger log = LoggerFactory.getLogger(DeptController.class);@Autowiredprivate DeptService deptService;@GetMappingpublic Result list(){log.info("查询全部部门数据");List<Dept> depts = deptService.selectDept();return Result.success(depts);}//删除@DeleteMapping("{id}")//@pathVariable注解可以将请求数据的参数弄到接口路径上public Result delete(@PathVariable Integer id){log.info("根据id删除部门信息"+id);int i = deptService.delete(id);return Result.success();}//新增部门@PostMapping//@RequestBody 可以将前端的json数据封装到对象中public Result add(@RequestBody Dept dept){//输出日志log.info("新增部门" + dept);deptService.add(dept);return Result.success();}//根据id查询@GetMapping("{id}")public Result getById(@PathVariable Integer id){Dept dept = deptService.selectDeptById(id);return Result.success(dept);}//更新数据@PutMappingpublic Result update(@RequestBody Dept dept){log.info("更新成功"+ dept);int i = deptService.update(dept);return Result.success();}
}
1. 控制层常用到的注解主要有:
  1. @Slf4j 主要是创建一个日志对象,可以代替sout输出日志。
  2. @RestController 主要作用是标识一个类是控制类,并且可以将函数返回内容作为响应主体返回给前端。
  3. @RequestMapping 主要作用是定义一个接口路径,前端可以通过这个路径地址发送请求,这个注解可以修饰类也可以修饰方法(修饰方法有可替代的代码)
  4. @RequestBody 主要作用是将前端请求的 Json数据封装到对象中,给 java服务器使用;
  5. @RequestParam 主要作用是识别前端请求的集合泛型,和mybatis中@Param识别多个参数用法一样,
    • value属性可以给参数设置别名(如果说前端请求参数名与后端方法参数名不一致,那么可以用这个注解给方法写一个别名)
    • required属性可以设置参数是否必须要传进来,true是必须,false是可以传空。
    • defaultValue属性可以给参数设置默认值
  6. @PathVariable 可以将请求路径变成动态可变的,路径用{参数}代表,通常用id表示。

上面有提到 Json数据,我的理解就是用 {} 封装的数据,Json字符串主要就是使内容变得井然有序有序,下面是一个Json格式的输出格式,都是键值对的格式,前端请求数据可以是Json格式,也可以是其他形式,所以说后端服务器接收到 Json数据的话就需要用@RequestBody注解将数据封装到对象当中,后端服务器返回出去的对象也是Json数据

{"code": 1,"msg": "success","data": {"id": 1,"username": "jinyong","password": "123456","name": "金庸","gender": 1,"image": "1.jpg","job": 4,"entrydate": "2000-01-01","deptId": 2,"createTime": "2025-08-17","updateTime": "2025-08-17"}
}
2. 工具类Result

主要是将要返回给前端的数据封装在Result对象里,将状态码code,信息msg,装有数据的Object变量data封装到Result对象里一起作为方法返回值返回给前端

下面是Result类

Result类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {private Integer code;//响应码,1 代表成功; 0 代表失败private String msg;  //响应信息 描述字符串private Object 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);}
}

controller层返回数据

    @PostMappingpublic Result save(@RequestBody Emp emp){log.info("插入成功" + emp);empService.save(emp);return Result.success();}
http://www.sczhlp.com/news/16046/

相关文章:

  • 【LLM1】大型语言模型的基本生成机制
  • 「CF2034F2」Khayyams Royal Decree (Hard Version)
  • ubuntu-禁用搜狗输入法快捷键 - fx
  • 如何个人电脑做网站网页设计用什么软件做
  • 做soho建立网站外贸推广公司
  • 移民网站建设谷歌搜索引擎大全
  • 2013影响网站百度搜索排名关键因素统计关键词排名的工具
  • 用什么软件搭建网站源码seo网站推广批发
  • 重庆做商城网站建设抖音关键词排名系统
  • 团队做网站分工seo引擎优化培训
  • 北京短视频制作公司郑州seo排名公司
  • 用几个域名做网站好软文代写
  • 自己怎样做海外网站上海抖音seo
  • wordpress 数据接口南京seo建站
  • 企业为什么需要网站汕头网络营销公司
  • Linux用QQ邮箱发送邮件
  • apk安装失败 Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Package Verification Result] 解决方法!
  • 8.18习题随记
  • 用html5做的音乐网站如何网上免费打广告
  • 企业名录搜索软件app深圳网站营销seo费用
  • dreamweaver网站模板网站内部seo优化包括
  • 企业网站变成app的方法郑州网站优化外包顾问
  • 读书网站怎么做百度销售岗位怎么样
  • php零基础做网站百度指数app下载
  • 网站切换语言怎么做竞价托管推广哪家好
  • 织梦如何做英文网站竞价托管公司排名
  • 网站需求方案百度官网首页入口
  • NOIP2025专题-搜索模拟(25直升搜索模拟)
  • 构建时序感知的智能RAG系统:让AI自动处理动态数据并实时更新知识库
  • b2c网站建设 广州百度收录的网站