Ⅰ Spring

  • 核心

    image-20230914211135926

一 Ioc

1.1 概念

  • IOC(Inversion Of Control)控制反转

  • 使用对象的时候,由主动new产生对象转为外部提供对象,此过程的对象创建控制权由程序转移到外部,这个思想称为控制反转

  • Spring提供了一个容器,称为Ioc容器,用来充当Ioc思想中的“外部”
  • 被创建或者管理的对象在Ioc容器中统一称为Bean
  • DI(Dependecy Injection)依赖注入:在容器中建立Bean与Bean之间的依赖关系的整个过程称为依赖注入
  • 目标:充分解耦
  • 最终效果:使用对象的时候不仅可以直接从Ioc容器中获取,并且获取到的Bean已经绑定了所有的依赖关系

1.2 IOC demo

  • maven中导入spring坐标 spring-context
  • 在xml文件中配置bean
    • <bean id = "bookDao123" class="com.itheima.dao.impl.BookDaoImpl"/>
      • id为给bean起的名字
      • class属性表示给bean定义类型(是实现类而不是接口)
  • 获取IoC容器
    • ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
      • applicationContext. xml是上一步的配置文件
  • 获取bean
    • BookDao bookDao = (BookDao) ctx.getBean("bookDao123");

1.3 DI demo

  • 分析

    • 基于IoC管理bean
    • Service中使用new的形式创建Dao对象不再保留(为了解耦)
    • Service中需要的Dao对象如何进入到Service中(提供方法)
    • Service和Dao之间的关系如何描述(by配置文件)
  • 删除上一个demo中new的方式创建对象

  • 在xml中配置Service和Dao的关系

    • ```xml

      <!-- 配置Service和Dao的关系 -->
      <property name="bookDao" ref="bookDao123"/>
      

      </bean>

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56

      - property表示配置当前的bean属性

      - name表示配置哪一个具体的属性(就是BookServiceImpl这个类的属性值的名称,里面 `private BookDao123 bookDao ` )

      - ref表示参照哪一个bean

      ### 1.4 Bean

      #### 1.4.1 bean配置

      - 默认单例模式
      - `<bean id = "bookDao123" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype"/>`
      - scope默认为singleton(单例)
      - 为什么?高效
      - 适合交给容器管理的bean
      - 表现层、业务层、数据层、工具对象
      - 不适合的
      - 封装实体的域对象
      - 多命名方式

      #### 1.4.2 bean实例化

      - 方式一:本质上是对象,使用**无参构造**方法创建,故需要提供无参构造方法

      - **如何看报错**:从下往上看,第一行是连着下面的所有提示

      - 方式二:使用静态工厂初始化对象(使用较少,以前用的多)

      - `<bean id = "orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>`
      - `OrderDaoFactory`类是工厂类,里面提供了一个静态方法`getOrderDao()`new了一个对象

      - 方式三:使用实例工厂初始化对象(了解)

      - `<bean id = "userFactory" class="com.itheima.factory.UserDaoFactory"/>`
      - `<bean id = "userDao" factory-method="getUserDao" factory-bean="userFactory">`
      - 第一行先创建了工厂的实例对象
      - 第二行使用`userFactory`工厂对象的`getUserDao`方法创建了对象
      - 实际上userFactory没什么意义(只是创建了调用了他的创建对象的方法)

      - 方法四:改良方法三(框架们用的很多)

      - 创建一个工厂bean引入接口FactoryBean

      ```java
      public class UserDaoFactoryBean implements FactoryBean<UserDao>{
      public UserDao getObject() throws Exception {
      return new UserDaoImpl();
      }
      public Class<?> getObjectType(){
      return UserDao.class;
      }
      public boolean isSingleton(){
      return false;//false表示非单例,true表示单例,通常都是单例的
      }
      }
    • 配置bean

      <bean id = "userDao" class="com.itheima.factory.UserDaoFactoryBean">

1.4.3 bean的生命周期

  • 配置bean的初始化、销毁时候的方法

    • ```xml
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44

      - 其中`initm`和`destroym`为类中定义的方法
      - 改进,实现类继承`initializingBean`和`DisposableBean`两个接口,然后实现`afterPropertiesSet`和`destroy`方法,配置文件中就不要init-method和destroy-method了

      - 生命周期

      - 初始化容器
      - 创建对象(分配内存)
      - 执行构造方法
      - 执行属性注入(set操作)
      - **执行bean初始化方法**
      - 使用bean
      - 关闭/销毁容器(手工关闭/注册关闭钩子)
      - **执行bean的销毁方法**

      ### 1.5 DI

      #### 1.5.1 简介

      - 向一个类中传递数据的方式:普通方法(set)和构造方法
      - 注入数据种类:引用类型和简单类型
      - DI方式(四种)
      - setter注入:简单类型/引用类型
      - 构造器注入:简单类型/引用类型

      #### 1.5.2 setter注入引用类型

      ![image-20230914224440089](https://myl-mdimg.oss-cn-beijing.aliyuncs.com/TyporaImg/SSM.assets/image-20230914224440089.png)

      - 如果有多个属性就写多行`<property>`标签

      #### 1.5.3 setter注入简单类型

      - 在对象中定义简单类型(int、String等)并生成set方法
      - 在配置文件中同样是`<property>`标签,只不过ref变为 `value=""`

      #### 1.5.4 构造器注入

      - 配置文件中

      ```xml
      <bean id = "bookService" class="com.itheima.dao.impl.bookServiceImpl">
      <constructor-arg name="bookDao" ref="bookDao123">
      </bean>
  • name中的名字是构造方法中形参的名字(会导致耦合度较高的问题

    • 解决方案:用type来代替name,但是会导致多个同类型的参数无法分配的问题;用index代替name,也有一点问题
  • ref 是配置文件中bean的id
  • 如果是简单类型则ref变为value

1.5.5 怎么选

  • 强制依赖使用构造器注入,使用setter注入有概率不进行注入导致null对象出现
  • 可选依赖使用setter注入
  • Spring倡导使用构造器,第三方框架内部多数采用构造器注入
  • 自己开发的模块推荐setter注入

1.5.6 自动装配

  • IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean的过程称为自动装配
  • 方式:按类型(常用)、按名称、按构造方法
    • 用于引用类型的依赖注入
1
<bean id = "bookDao123" class="com.itheima.dao.impl.BookDaoImpl" autowire="byType"/>
  • 注意:上述方法需要先在类中设置set方法
  • byType改为byName就是按名称
    • 按名称必须保障容器中具有指定名称的bean,因变量与配置耦合,不推荐使用
  • 自动装配优先级低于setter注入与构造器注入,同时出现的时候自动装配配置失效

1.5.7 集合注入

  • list、set、map、properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<bean id = "bookDao123" class="com.itheima.dao.impl.BookDaoImpl">
<property name="myList">
<list>
<value>100</value>
<value>200</value>
<ref bean = "..."/>
</list>
</property>

<property name="mySet">
<set>
<value>man</value>
<value>yi</value>
</set>
</property>

<property name="myMap">
<map>
<entry key="country" value="china"/>
<entry key="city" value="changsha"/>
</map>
</property>

<property name="myProperty">
<props>
<props key="country">china</props>
<props key="city">changsha</props>
</props>
</property>
</bean>

1.6 加载properties文件

  • xml文件头开命名空间(灰色的三行,直接copy然后beans换为context)

    image-20230915105033303

  • 使用context空间加载properties文件

image-20230915105158137

  • 使用properties的数据(通过${}引用外部properties中的值)

image-20230915105233506

  • 注意
    • 加载多个properties 在第二步的时候location后面加逗号连接,也可以写为*.properties或者 classpath:*.properties(推荐使用第二种)
      • 最佳为classpath*:*.properties区别是这个还可以加载导入的jar包里面的properties

1.7 容器总结

  • 加载容器

    • 类路径加载(常用)

      1
      Applicationcontext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    • 文件系统加载

      1
      Applicationcontext ctx = new FileSystemXmlApplicationContext("绝对路径")
  • 获取bean,三种方式

    1
    2
    3
    BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    BookDao bookDao = ctx.getBean("bookDao", BookDao.class);
    BookDao bookDao = ctx.getBean(BookDao.class);
  • Beanfactory是IoC容器的顶层接口,初始化的时候加载的bean延迟加载

  • Applicationcontext接口是Spring的核心接口,初始化的时候bean立即加载

    • ClassPathXmlApplicationContextFileSystemXmlApplicationContext是其常用的初始化类
  • bean相关的标签

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <bean
    id = "" bean的id
    name = "" bean的别名
    class = "" bean的类型静态工厂类FactoryBean类
    scope = "" 控制bean实例数量
    init-method = "" 生命周期初始化方法
    destroy-method = "" 生命周期销毁方法
    autowoire = "" 自动装配类型
    factory-method = "" bean工厂方法应用于静态工厂或实例工厂
    factory-bean = "" 实例工厂bean
    lazy-init = "" 控制bean延迟加载
    />

1.8 注解开发

1.8.1 注解开发定义bean

  • 使用@component定义Bean
1
2
3
4
@component("bookDao")//指定了bean的名称为bookDao
public class BookDapImpl implements BooDao {

}
  • 核心配置文件中通过组件扫描加载bean
1
<context:component-scan base-package="com.itheima">
  • Spring提供了三个衍生注解
    • @Service@Repository@Controller
    • 分别表示业务层、数据层、表现层(为了方便阅读,功能都是一样的)

1.8.2 纯注解开发定义bean

  • Spring3.0新功能

  • 使用配置类代替配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    @Configuration
    @ComponentScan("com.itheima")
    //或者
    @ComponentScan({"com.itheima.service", "com.itheima.dao"})
    //因为有些bean可能不能加载
    public class SpringConfig{

    }
    • @Configuration :表示该类为配置类
    • @ComponentScan:表示需要扫描的路径
  • 加载使用

    1
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class)

1.8.3 bean管理

  • 单例与否
    • 在类上添加注解 @Scope("singleton")
  • 初始化方法:`PostConstruct
  • 销毁前方法:@reDestroy

1.8.4 依赖注入—自动装配

  • 属性前加注解 @Autowired

    • 使用的是反射注入,所以不用set方法

    • 如果是简单类型就用 @Value("值")

    • 如果简单类型引用的是配置文件的值

      • ```java
        @Configuration
        @ComponentScan(“com.itheima”)
        @PropertySource({“jdbc.properties”, “user.properties”})// 配置文件清单 不能用*.properties
        public class SpringConfig {

        }

        //类的定义
        @Repository(“bookDao”)
        public class BookDaoIml implements BookDao {

        @Value("${name}")//引入配置文件中的属性值
        private String name;
        

        }

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40

        #### 1.8.5 第三方bean管理

        - 第三方bean管理

        - ```java
        @Configuration
        @Import({JdbcConfig.class, ...})//3 导入配置类
        public class SpringConfig {

        }


        // 0 新建一个配置类(也可以写在主配置类SpringConfig中,但是bean多了不好管理)
        public class JdbcConfig {

        @Value("driver")// 4 引入外部配置文件中的简单类型数据
        private String driver;
        @Value("url")
        private String url;
        @Value("userName")
        private String userName;
        @Value("password")
        private String password;

        // 1 定义一个方法获得要管理的对象
        // 2 添加@Bean表示当前方法的返回值是一个bean
        @Bean
        public DataSource dataSource(BookDao bookdao){

        System.out.println(bookdao.name);// 5 引用类型数据的自动装配

        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
        }
        }
  • 第三方bean依赖注入(上段代码第4、5点)

1.9 注解总结

image-20230916143320550

二 框架整合

2.1 Spring整合MyBatis

  • (项目Spring_MyBatis)

2.1.1 MyBatis核心步骤

image-20230916144055956

  • 主要就是SqlSessionFactory对象

2.1.2 整合步骤

  • 新建一个MybatisConfig类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class MybatisConfig {
    //定义bean,SqlSessionFactoryBean,用于产生SqlSessionFactory对象
    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
    SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
    ssfb.setTypeAliasesPackage("com.itheima.domain");//设置类型别名的包
    ssfb.setDataSource(dataSource); // 设置数据库
    return ssfb;
    }
    //定义bean,返回MapperScannerConfigurer对象
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
    MapperScannerConfigurer msc = new MapperScannerConfigurer();
    msc.setBasePackage("com.itheima.dao"); // 设置扫描的包
    return msc;
    }
    }

2.2 Spring整合JUnit

  • 在Maven配置文件中导入JUnit坐标
  • 基本固定三步如下

  • ```java
    @RunWith(SpringJUnit4ClassRunner.class)//1 指定类运行器
    @ContextConfiguration(classes = SpringConfig.class)//2 指定Spring配置类
    public class AccountServiceTest {

    @AutoWired//3 自动装配bean
    private AccountService accountService;
    
    @Test
    public void testFindById(){
         System.out.println(accountService.findById(1));   
    }
    

    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51

    ## 三 AOP

    ### 3.1 概念

    - AOP(Aspect Oriented Programming):面向切面编程,一种编程范式,指导开发者如何组织程序结构
    - 作用:在不惊动原始设计的基础上为其进行功能增强
    - Spring理念:无入侵式编程

    ### 3.2 AOP概念

    - 连接点(JoinPoint):程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等
    - 在Spring AOP中,理解为方法的执行
    - 切入点(Pointcut):匹配连接点的式子
    - 在Spring AOP中,一个切入点可以只描述一个具体的方法,也可以匹配多个方法
    - 一个具体方法:com.itheima.dao包下单BookDao接口中的无形参无返回值的save方法
    - 匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口方法,所有带有一个参数的方法
    - 通知(Adcive):在切入点处执行的操作,也就是共性功能
    - 在Spring AOP中功能最终以方法的形式呈现
    - 通知类:定义通知的类
    - 切面(Aspect):描述通知于切入点的对应关系

    ### 3.3 AOP demo

    - 开发模式:XML或者注解

    - 思路分析

    - 1 导入坐标

    - aspectjweaver
    - spring-context

    - 2 制作连接点方法(原始操作,Dao接口与实现类)

    - 3 制作共性功能(通知类与通知)

    - 创建一个新的类

    - ```java
    @Component //Spring会扫描它当作一个bean
    @Aspect //告诉Spring这是一个AOP
    public class MyAdvice {
    @Pointcur("execution(void com.itheima.dao.BookDao.update())")// 4 切入点定义
    private void pt(){}

    @Before("pt()")// 5 绑定切入点与通知的关系
    public void method(){
    //方法体
    }
    }
    • 在Spring配置类中添加注解 @EnableAspectJAutoProxy

    • ```java
      @Configuration
      @ComponentScan(“com.itheima”)
      @EnableAspectJAutoProxy
      public class SpringConfig {
      }

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74

      - 4 定义切入点

      - 5 绑定切入点与通知关系

      - 结果:运行 `com.itheima.dao.BookDao.update()`的方法的时候在执行完update的内容前会额外执行MyAdvice中的`method()`的内容

      ### 3.4 AOP工作流程

      - Spring容器启动
      - 读取所有切面配置中的切入点
      - 初始化bean,判定bean对应的类中的方法是否匹配到任意切入点
      - 匹配失败,创建对象
      - 匹配成功,创建原始对象(目标对象)的代理对象
      - 获取bean执行方法
      - 获取bean,调用方法并执行,完成操作
      - 获取的bean是代理对象的时候,根据代理对象的运行模式运行原始方法与增强的内容,完成操作
      - **AOP本质:代理模式**

      ### 3.5 AOP切入点表达式

      - 切入点:要进行增强的方法

      - 切入点表达式:要进行增强的方法的描述方式

      - 切入点表达式标准格式:

      - `动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数) 异常名)`
      - `execution(void com.itheima.dao.BookDao.update())`
      - 动作关键字:描述切入点的行为动作,如execution表示执行到指定切入点
      - 访问修饰符:public,private等,可以省略
      - 异常名:方法中定义抛出的指定异常,可以省略

      - 可以使用通配符描述切入点,快速描述

      - `*`:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀匹配符

      - `execution(public * com.itheima.*.UserService.find*(*))`:

      匹配 com.itheima下的任意包的UserService类或接口中所有find开头的带一个参数的方法

      - `..`:多个连续的任意符号,可以独立出现,常用于简化包名与参数的书写

      - `execution(public User com..UserService.findById(..))`:

      匹配com包下任意包中的UserService类或接口中所有名称为findById的方法

      - `+`:专用于匹配子类类型

      - 规范

      ![image-20230917231842486](https://myl-mdimg.oss-cn-beijing.aliyuncs.com/TyporaImg/SSM.assets/image-20230917231842486.png)

      ### 3.6 AOP通知类型

      - AOP通知类型:前置通知、后置通知、环绕通知(重点)、返回后通知、抛出异常后通知

      - 前置通知:`@Before()`

      - 后置通知:`@After()`

      - 环绕通知:`@Aroud()`(功能最强大)

      - ```java
      @Aroud("pt()")
      public Object aroud(ProccdingJoinPoint pjp){
      //前置操作

      Object ret = pjp.proceed();

      //后置操作

      return ret;//这里的ret是原始方法的返回值,如果原始方法是void就不需要return
      }
    • 返回后通知:@AfterReturning()

    • 抛出异常后通知:@AfterThrowing()

3.7 案例:测试业务曾接口万次执行效率

  • 需求:任意业务层接口执行均可显示其执行效率(执行时长)
  • 分析:
    • 业务功能:分别获取前后执行的系统时间后取差值
    • 通知类型选择环绕通知

3.8 AOP通知获取数据

  • 获取切入点方法的参数
    • JoinPoint:适用于前置、后置、返回后、抛出异常后通知
    • ProccdingJoinPoint:适用于环绕通知
  • 获取切入点方法返回值
    • 返回后通知
    • 环绕通知
  • 获取切入点方法运行异常信息
    • 环绕通知
    • 抛出异常后通知
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Component   
@Aspect
public class MyAdvice {
@Pointcur("execution(* com.itheima.dao.BookDao.findName(..))")
private void pt(){}

@Before("pt()")// 获取切入点方法的参数,同时@After、@Aroud也可以用
public void method(JoinPoint jp) {
Object[] args = jp.getArgs();
System.out.println(Arrays.toString(args);//会打印切入点方法的输入参数

args[0] = 666;//在这里可以修改传入参数的值,保证程序的正确运行
}
//ProccdingJoinPoint是继承自JoinPoint,所以也可以获取输入参数


@AfterReturning("pt()")
public void afterReturning(Object ret){
System.out.println(Arrays.toString(ret);//获取切入点方法返回值
}

}

3.9 AOP总结

  • 是一种编程范式。为了在不惊动原始设计的方法上对功能进行增强
  • 核心概念
    • 代理:SpringAOP核心本质是代理模式
    • 连接点:SpringAOP中,理解为任意方法的执行
    • 切入点:匹配连接点的式子,也是具有共性功能的方法描述
    • 通知:若干个方法的共性功能,在切入点处执行,最终体现为一个方法
    • 切面:描述通知与切入点的对应关系
    • 目标对象:被代理的原始对象成为目标对象

四 事务

4.1 Spring事务简介

  • 事务作用:在数据层保障一系列的数据库操作同成功同失败
  • Spring事务的作用:在数据层或者业务层保障一系列的数据库操作同成功同失败
1
2
3
4
public interface PlatformTransactionManager{
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}

4.2 银行转账

  • 需求:A账户减钱,B账户加钱

  • 分析

    • 数据层提供基础操作,指定账户减钱(outMoney),指定账户加钱(inMoney)
    • 业务层提供转账操作(transfer),调用加钱与加钱操作
    • 提供两个账户和操作金额执行转账操作
    • 基于Spring整合MaBatis环境搭建上述操作
  • 步骤

    • 设置事务管理器(是jdbc的)

      • ```java
        @Bean
        public PlatformTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager()
           transactionManager.setDataSource(dataSource);
        return transactionManager
        
        }
        1
        2
        3
        4
        5
        6
        7

        - 在transfer方法上添加注解 `@Transactional`开启事务(在接口中加比较规范)

        - 在Spring配置文件中添加注解,开启事务驱动

        - ```
        @EnableTransactionManagement

4.3 Spring事务

  • 事务角色

    • 事务管理员:发起事务方,在Spring中通常指开启事务的方法
    • 事务协调员:加入事务方,在Spring中通常指数据层方法,也可以是业务层方法
  • 相关配置:在注解上开启

    • image-20230919203352637

    • eg:

      1
      @Transactional(readOnly="true", timeout=-1, rollBackFor{IOException.class})
  • 事务传播行为

    image-20230919204618495

Ⅱ SpringMVC

一简介

1.1 概述

  • SpringMVC技术与Servlet技术功能等同,均属于web层开发技术

  • SpringMVC是一种基于Java实现的MVC模型单独轻量级Web框架(表现层)

    image-20230919210256287

  • 是做表现层的,之前的Servlet技术也是表现层的技术,但是SpringMVC更简洁

1.2 demo

  • 导入坐标

    • spring-webmvc
  • 创建SpringMVC控制器类(等同于Servlet功能)

    1
    2
    3
    4
    5
    6
    7
    8
    @Controller
    public class UserControlller {
    @RequestMapping("/save")//访问路径
    @ResponseBody//返回内容作为响应内容
    public String save(){

    }
    }
  • 初始化SpringMVC环境(同Spring环境)设定SpringMVC加载对应的bean

    1
    2
    3
    4
    5
    @Configuration
    @ComponentScan("com.itheima.controller")
    public class SpringConfig{

    }
  • 初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求

    image-20230919213334716

  • 总结:

    • 一次性工作
      • 创建工程,设置服务器,加载工程
      • 导入坐标
      • 创建web容器启动类,加载SpringMVC配置,并设置SpringMVC请求拦截路径
      • SpringMVC核心配置类(设置配置类,扫描controller包,加载Controller包控制器bean)
    • 多次工作
      • 定义处理请求的控制器类
      • 定义处理请求的控制器方法,并配置映射路径(@RequestMapping)与返回的json数据@ResponseBody

1.3 demo工作流程分析

  • 启动服务器初始化过程

    • 服务器启动,执行ServletContainerInitConfig类,初始化web容器
    • 执行createServletApplicationContext方法,创建WebApplicationContext对象
    • 加载SpringMvcConfig
    • 执行@ComponentScan加载bean
    • 加载UserController,每个@ResponseBody名称对应一个具体的方法
    • 执行getServletMappings方法,定义所有请求都通过SpringMVC

    image-20230919215722107

  • 单次请求的过程

    • 发送请求localhost/save
    • web容器发现所有请求都经过SpringMVC,将请求交给SpringMVC处理
    • 解析请求路径/save
    • 由/save匹配执行对应的方法save()
    • 执行save()
    • 检测到有@ResponseBody直接将save方法的返回值作为响应体返回给请求方

1.4 bean的加载控制

  • 加载Spring控制的bean的时候,排除SpringMVC的bean
    • 方式一:Spring加载的bean设定范围为精确范围(常用)
    • 方式二:排除controller包(Spring boot有用)
    • 不区分两者,加载到同一容器

1.5 PostMan简介

  • 是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件
  • 作用:用于进行接口测试
  • 使用:
    • 注册登录
    • 创建工作空间
    • 发起请求测试结果

二 请求与响应

2.1 请求映射路径

  • 团队多人开发的时候,每个人设置不同的请求路径,冲突问题如何解决

    • 规范命名

    • 定义两层@RequestMapping

      • 第一层在类上@RequestMapping
      • 第二层在方法上@RequestMapping

      image-20230919223005854

2.2 请求参数

2.2.1 请求方式

  • Get请求

    • localhost:8080/commonparam?name=zhangsan&age=15

    • ```java
      @RequestMapping(“/commonparam”)
      @ResponseBody
      public String method(String name, int age){

      //方法体
      

      }

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13

      - Post请求

      #### 2.2.2 参数种类

      - 普通参数:url地址传参,如果请求参数与形参不一致,形参前加注解

      ```java
      @RequestMapping("/commonparam")
      @ResponseBody
      public String method(@RequestParam("username") String name, int age){
      //方法体
      }
  • POJO参数:请求参数名与形参对象属性名相同,定义POJO类型形参即可接收参数

    1
    2
    3
    4
    5
    @RequestMapping("/pojoParam")
    @ResponseBody
    public String method(User user){
    //方法体
    }
  • 嵌套POJO参数:POJO对象中包含POJO对象,则请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数

  • 数组参数:请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型形参即可接收参数

  • 集合保存普通参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系

    1
    2
    3
    4
    5
    @RequestMapping("/listParam")
    @ResponseBody
    public String listParam(@RequestParam List<String> likes){
    //方法体
    }

2.2.3 请求参数传递json数据

  • 步骤

    • maven导入坐标

    • 在postman中定义发送json请求

      image-20230920225550371

    • Spring配置类上面添加注解@EnableWebMvc开启json转换为对象的功能

    • 在形参前面加入注解 @RequestBody

      1
      2
      3
      4
      5
      @RequestMapping("/listParamForJson")
      @ResponseBody
      public String listParam(@RequestBody List<String> likes){
      //方法体
      }
  • 关键是@RequestBody注解

image-20230920230201329

2.2.4 日期类数据

  • @DateTimeFormat(pattern="yyyy-MM-dd")

  • @DateTimeFormat(pattern="yyyy/MM/dd HH:MM:ss") 可以自定义格式,根据请求参数的格式来设置

  • 也有一个默认的格式

    1
    2
    3
    4
    5
    @RequestMapping("/dataParam")
    @ResponseBody
    public String dataParam(@DateTimeFormat(pattern="yyyy-MM-dd") Date date){
    //方法体
    }

2.3 响应json数据

2.3.1 响应页面

1
2
3
4
@RequestMapping("/toJumpPage")
public String toJumpPage(){
return "page.jsp"
}

2.3.2 响应数据

  • 文本数据

    1
    2
    3
    4
    5
    @RequestMapping("/toText")
    @ResponseBody
    public String toText(){
    return "response text"
    }
  • json数据

    • POJO对象

      1
      2
      3
      4
      5
      6
      @RequestMapping("/toJsonPOJO")
      @ResponseBody
      public User toJsonPOJO(){
      User user = new User();
      return user;
      }

      返回对象会自动转为json数据

    • POJO集合:返回对象改为返回集合即可

  • 关键是 @ResponseBody注解,可以将返回值自动转为json数据进行响应

三 REST风格

3.1 简介

  • REST(Representational State Transfer),表现形式状态转换

    • 传统风格
      • http://localhost/user/getById?id=1
      • http://localhost/user/saveUser
    • REST风格
      • http://localhost/user/1
      • http://localhost/user
  • 优点:

    • 隐藏资源访问行为,无法通过地址得知对资源是何种操作
    • 书写简化
  • 风格

    image-20230920232530706

  • 路径+请求方式 ==> 一个资源的访问行为

  • 根据REST风格对资源进行访问称为RESTful

3.2 RESTful demo

1
2
3
4
5
6
7
8
9
10
11
@RequestMapping(value = "/users",method = RequestMethod.POST)// 指定post方式的请求
@ResponseBody
public String save(){
return "user save";
}

@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)// 可以动态传入参数
@ResponseBody
public String delete(@PathVariable Integer id){
return "user delete";
}

按照REST风格修改相关的请求方法

image-20230920233357258

  • 快速版, 简化注解

    image-20230920233657696

3.3 restful 案例

rest_case项目

四 SSM整合

4.1 整合Spring、MyBatis、SpringMVC

  • com.itheima.config目录下的配置类
  • pom.xml导入坐标

4.2 功能模块开发

  • com.itheima.domain下定义Book类
  • com.itheima.dao下定义bookDao
  • com.itheima.service.impl下定义方法接口并与相应实现类
  • com.itheima.controller下定义BookController实现控制层逻辑

4.3 接口测试

  • 在test中创建相应的类与方法进行测试 业务层

4.4. 表现层与前端的接口

  • 前端接收数据格式——创建结果模型类,封装数据到data属性中

    image-20230924210602994

    但是无法确定某一个data是对应者什么操作

  • 前端接收数据格式——封装操作到code属性中

    image-20230924210725312

    但是对于查询来说不知道查询是否成功

  • 前端接收数据格式——封装特殊消息到message(msg)属性中

    image-20230924210959571

  • 设置统一数据返回结果类(Controller层)

    1
    2
    3
    4
    5
    6
    public class Result {
    private Object data;
    private Integer code;
    private String msg
    }
    //注意:result类中的字段不是固定的,可以根据需求删减

    Controller中的方法的返回值设置为Result

4.5 异常处理

  • 种类

    • 框架内部异常
    • 数据层抛出异常:因外部服务器故障
    • 业务层抛出异常:业务逻辑错误
    • 表现层抛出异常:收集数据,校验数据等
    • 工具类抛出异常
  • 一般写在表现层处理,其他层就往上抛(数据层->业务层->表现层),分类处理+AOP思想

  • 异常处理器:集中统一的处理项目中的异常()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package com.itheima.controller;

    @RestControllerAdvice
    public class ProjectExceptionAdvice {

    @ExceptionHandler(Exception.class)
    public Result doException(Exception e) {
    //自定义异常处理逻辑
    System.out.println(e);

    return new Result(666, null);//返回错误提示结果给前端
    }

    }
  • 项目异常处理方案

五 拦截器

5.1 概念

  • 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行

    image-20230925201425828

  • 作用

    • 在指定的方法调用前后执行预先设定的代码
    • 阻止原始方法的执行
  • 与过滤器的区别

    • 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
    • 拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对SpringMVC的访问进行增强

5.2 案例

  • com.itheima.controller.interceptor包下创建ProjectInterceptor类继承接口HandlerInterceptor并重写方法(3个)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @ConComponent // 让spring能够扫描到
    public class ProjectInterceptor implements HandlerInterceptor{
    //preHandle postHandle afterComleption三种方法
    public boolean preHandle(...) throws Exception {
    System.out.println("preHandle...");
    return true;//如果返回false执行完preHandle就不会执行另外两个了
    }

    public void postHandle(...) throws Exception {
    System.out.println("postHandle...");
    }

    public void afterCompletion(...) throws Exception {
    System.out.println("afterCompletion...");
    }
    }
  • 定义配置类,继承WenMvcConfigurationSupport,实现addInterceptor方法,并添加拦截器访问路径

    image-20230925204158055

  • 也可以直接在SpringMvcConfig配置类中继承WebMvcConfigurer并重新addInterceptors方法(但是侵入式较强

    image-20230925204709765

  • 拦截器执行流程

    image-20230925205017238

5.3 拦截器参数

  • 前置处理preHandle
    • HttpServletRequest request:请求对象
    • HttpServletResponse response:响应对象
    • Object handler:被调用的处理器对象,本质上是一个方法对象,对反射技术中的Method对象进行了再包装
    • 返回值
      • 为false,被拦截的处理器将不再执行
  • 后置处理postHandle
    • 多了一个ModelAndView modelAndView
  • 完成后处理afterCompletion
    • 相对于preHandle多了一个Exception ex

5.4 拦截器工作流程分析

  • 当配置多个拦截器的时候,形成拦截器链

  • 拦截器的运行顺序参照拦截器添加顺序

  • 当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行

    image-20230925210234869

Ⅲ Maven

一 分模块开发

  • 创建不同模块,dao,domain,等都可以拆开
  • 通过maven指令安装模块到本地仓库(install)
  • 团队内部开发需要发布模块功能到团队内部可共享的仓库中(私服)

二 依赖管理

  • 传递性:直接依赖与间接依赖
  • 依赖传递冲突问题

    • 路径优先:当依赖中出现相同的资源时,层级越深,优先级越低
    • 声明优先:当资源中相同层级被依赖时,配置顺序靠前的覆盖配置顺序靠后
    • 特殊优先:当同级配置了相同资源的不同版本,后配置的覆盖先配置的
  • 可选依赖:对外隐藏依赖

    • 在pom中的dependency标签中添加optional标签,true表示隐藏依赖(别人不知道依赖了这个)
  • 排除依赖:主动断开依赖

    • exclusion

三 继承与聚合

3.1 聚合

  • 聚合:将多个模块组织成一个整体,同时进行项目构建的过程成为聚合
  • 聚合工程:通常是一个不具有业务功能的空工程(有且仅有一个pom文件)
  • 作用:使用聚合工程可以将多个工程编组,通过对聚合工程进行构建,实现对所包含的模块进行同步构建
    • 当工程中某个模块发生更新的时候,必须保障工程中与已更新的模块同步更新,此时使用聚合工程可以批量解决
  • 聚合工程的构建
    • 打包类型设置为pom
    • image-20230925220646122
    • 不用管模块的顺序,实际的时候会根据它们之间的相互关系自动设置构建顺序

3.2 继承

  • 继承:两个工程之间的关系,子工程可以继承父工程中的配置信息,常见于依赖关系的继承
  • 作用
    • 简化配置
    • 减少依赖冲突
  • 继承的定义
    • image-20230925221127695

四 属性

  • 在pom中定义属性

    1
    2
    3
    <properties>
    <spring.version>5.2.10.RELEASE</spring.version>
    </properties>
  • 然后在坐标中的version标签中的版本改为 ${spring.version},这样就不用一个一个更新版本了

  • 配置文件加载属性

    image-20230925222549294

    • 然后就可以使用${...}来读取resources下的.propertise文件了
  • 版本管理

    • 工程版本
      • SHAPSHOT(快照版本)
        • 项目开发过程中临时输出的版本,成为快照版本
        • 快照版本会随着开发的进展不断更新
      • RELEASE(发布版本)
        • 项目开发进入到里程碑后,向团队外部发布较为稳定的版本

五 多环境配置与应用

  • maven提供配置多种环境的设定,帮助开发者使用过程中快速切换环境

  • pom文件中

    image-20230926201922374

  • 也可以执行 maven install -P env_test 就不用设置 activation 标签了

    • mvn 指令 -P 环境定义id
  • 跳过测试
    • 应用场景
      • 功能更新中并且没有开发完毕
      • 快速打包等
    • mvn 指令 -D skipTest
    • 或者配置插件,在pom中定义
    • image-20230926203036479

六 私服

6.1 概念

  • 是一台独立的服务器,用于解决团队内部的资源共享与资源同步问题

  • Nexus

    • 一款maven私服产品
    • https://help.sonatype.com/repomanager3/download
  • 分类

    image-20230926204827260

6.2 本地资源访问私服配置

  • 上传与下载的过程

    image-20230926205251592

  • 配置修改

    • maven的setting文件中修改

Ⅳ SpringBoot

一 demo

1.1 原始SpringMVC开发

  • 配置依赖

    image-20230926210332728

  • web配置

    image-20230926210401675

  • SpringMvc配置

    image-20230926210432864

  • 至少一个controller类

    image-20230926210504763

1.2 SpringBoot Demo

  • 05_springboot_demo

    image-20230926214037232

  • 只定义了一个类

  • 对比原始

    image-20230926214406563

  • 注意:基于idea开发springboot程序需要联网

    • 也可以在springboot官网创建,然后下载zip

二 SpringBoot概述

  • 设计目的是为了简化Spring应用的初始搭建以及开发过程

  • springboot项目快速启动

    • 项目打jar包(boot程序一般打jar包)

    • 执行启动命令 java -jar springboot.jar

      image-20230926221042145

  • springboot程序优点

    • 自动配置
    • 起步依赖(简化依赖配置)
    • 辅助功能(内置服务器…)
  • 起步依赖

    • starter

      • springboot中常见项目名称,定义了当前项目使用的所有项目坐标,以达到减少依赖配置的目的
    • parent

      • 所有springboot项目要继承的项目,定义了若干个坐标版本号(依赖管理,而非依赖),以达到减少依赖冲突的问题
  • 辅助功能

  • 排除tomcat服务器,使用jetty服务器

    • image-20230926222457600

三 配置文件

  • 修改服务器端口

    • 默认是8080

    • 方式一:resources目录下的 application.properties文件中 server.port=80

    • 方式二:resources目录下创建 application.yml(主要用这种)

      • ```yml
        server:
        port: 80

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43

        - 注意数据前需要加空格

        - 方式三:resources目录下创建`application.yaml`

        - 同上

        - 三种冲突的话,优先级:`.properties` > `.yml` > `.yaml`

        - yaml

        - YAML:(YAML Ain't Markup Language),一种数据序列化格式

        - 优点

        - 易阅读、易与脚本语言交互、与数据为核心,重数据轻格式

        - YAML文件扩展名

        - .yml
        - .yaml

        - 语法

        - 大小写敏感
        - 属性层级关系使用多行描述,每行结尾使用冒号结束
        - 使用缩进表示层级关系,同层级左侧对其,只允许使用空格(不允许tab)
        - **属性值前面添加空格**
        - #表示注释

        - 数据读取

        - 方式一:`@Value(${一级属性名.二级属性名...})`

        ![image-20230927210417992](https://myl-mdimg.oss-cn-beijing.aliyuncs.com/TyporaImg/SSM.assets/image-20230927210417992.png)

        - 方式二:`@AutoWired`一次性全部装配所有的属性

        ```java
        @AutoWired
        private Environment enviroment;

        enviroment.getProperty("lesson");//返回SpringBoot
      • 方式三:(常用)

        1
        2
        3
        4
        5
        6
        7
        8
        9
        @Component
        @ConfigurationProperties(prefix = "enterprise")
        public class Enterprise {
        private String name;
        private Integer age;
        private String tel;
        private String[] subject;
        //会自动读取enterprise中的四个数据
        }
  • 多环境开发配置

    image-20230927211807762

  • 多环境启动命令格式

    • 带参数启动SpringBoot

      • java -jar springboot.jar --spring.profiles.active=test

      • java -jar springboot.jar --server.port=88

      • java -jar springboot.jar --server.port=88 --spring.profiles.active=test

  • 配置文件分类

四 SpringBoot整合JUnit

  • spring整合JUnit

    • 设置运行器 -> 加载环境 -> 注入测试对象 -> 测试功能

      image-20230927213922940

  • SpringBoot

    • 定义好所需要测试的类

    • ```java
      @SpringBootTest
      class ApplicationTests {

      @Autowired
      private BookService bookService;
      
      @Test
      public void saveTest() {
          bookService.save();
      }
      

      }

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73

      ![image-20230927220625953](https://myl-mdimg.oss-cn-beijing.aliyuncs.com/TyporaImg/SSM.assets/image-20230927220625953.png)

      ## 五 SpringBoot整合SSM

      - 整合Spring和SpringMVC均不需要,只需整合MyBatis


      ### 5.1 Spring整合MyBatis

      - SpringConfig
      - 导入JdbcConfig
      - 导入MyBatisConfig
      - JDBCConfig
      - 定义数据源(加载properties)
      - MyBatisConfig
      - 定义`SqlSessionFactoryBean`
      - 定义映射配置

      ### 5.2 SpringBoot整合MyBatis

      - 创建模块

      - yml中设置数据源

      ![image-20230927224136784](https://myl-mdimg.oss-cn-beijing.aliyuncs.com/TyporaImg/SSM.assets/image-20230927224136784.png)

      - 定义数据层接口与映射配置

      ![image-20230927224213163](https://myl-mdimg.oss-cn-beijing.aliyuncs.com/TyporaImg/SSM.assets/image-20230927224213163.png)

      - 测试类中注入dao接口,测试功能

      ![image-20230927224238830](https://myl-mdimg.oss-cn-beijing.aliyuncs.com/TyporaImg/SSM.assets/image-20230927224238830.png)

      # Ⅴ MyBatis Plus
      ## 一 简介

      - 简称MP,是基于Mybatis框架基础上开发的增强型工具,旨在简化开发、提高效率

      ### 1.1 SpringBoot整合Mybatis过程

      - 创建SpringBoot工程

      - 勾选配置使用的技术

      - 设置dataSource相关属性(JDBC参数)

      ![image-20231016210817888](.(https://myl-mdimg.oss-cn-beijing.aliyuncs.com/TyporaImg/SSM.assets/image-20231016210817888.png)

      - 定义数据层接口映射配置

      ![image-20231016210853914](.(https://myl-mdimg.oss-cn-beijing.aliyuncs.com/TyporaImg/SSM.assets/image-20231016210853914.png)

      ### 1.2 SpringBoot整合Mybatis plus过程

      - 创建SpringBoot工程

      - 勾选配置使用的技术 (仅保留JDBC)

      - 手动添加起步依赖

      ![image-20231016212322111](.(https://myl-mdimg.oss-cn-beijing.aliyuncs.com/TyporaImg/SSM.assets/image-20231016212322111.png)

      - 设置Jdbc参数(application.yml),制作实体类与表结构

      - 与之不同的是定义数据层接口的时候继承BaseMapper

      ```java
      @Mapper
      public interface UserDao extends BaseMapper<User> {

      }

    不再需要写@Select

  • 测试

    image-20231016212043874

二 标准数据层开发

  • image-20231016212940985

  • lombok

    • 一个java类库,提供了一堆注解,简化POJO实体类开发

    image-20231016213905086

    • 常用注解:@Data
      • 为当前实体类在编译期设置对应的get/set方法,无参/全参构造方法,toString方法,hashCode方法,equals方法等
  • 分页功能

    • IPage类

    • ```java
      IPage page = new Page(1,2)//当前页码:1,每页2条
      userDao.selectPage(page, null);

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
        ![image-20231016214532717](.(https://myl-mdimg.oss-cn-beijing.aliyuncs.com/TyporaImg/SSM.assets/image-20231016214532717.png)

      - 需要额外定义一个拦截器Bean

      ```java
      @Configuration
      public class MpConfig {
      @Bean
      pubic MybatisPlusInterceptor mpInterceptor(){
      //定义Mp拦截器
      MybatisPlusInterceptor mpi = new MybatisPlusInterceptor();
      //添加具体的拦截器
      mpi.addInterInterceptor(new PaginationInnerInterceptor());
      return mpi
      }
      }

三 DQL控制

3.1 条件查询方式

  • MybatisPlus将复杂的SQL查询条件进行了封装,使用编程的形式完成条件的组合查询

  • 方式一:QueryWrapper

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @SpringBootTest
    class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll(){
    QueryWrapper qw = new QueryWrapper();
    qw.lt("age",30);
    qw.gt("age", 10);//大于10小于30
    List<User> userList = userDao.selectList(qw);
    System.out.println(userList);
    }
    }
  • 方式二:QueryWrapper的基础上使用lambda

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @SpringBootTest
    class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll(){
    QueryWrapper<User> qw = new QueryWrapper<User>();
    qw.lambda().lt(User::getAge, 10);//添加条件
    List<User> userList = userDao.selectList(qw);
    System.out.println(userList);
    }
    }
  • 方式三LambdaQueryWrapper

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @SpringBootTest
    class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll(){
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
    lqw.lt(User::getAge, 10);
    List<User> userList = userDao.selectList(lqw);
    System.out.println(userList);
    }
    }
  • null值处理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @SpringBootTest
    class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll(){
    //模拟页面传递过来的查询数据
    UserQuery uq = new UserQuery();
    uq.setAge(10);
    uq.setAge2(30);
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
    lqw.lt(null!=uq.getAge2(),User::getAge, uq.getAge2());
    lqw.gt(null!=uq.getAge(),User::getAge, uq.getAge());
    List<User> userList = userDao.selectList(lqw);
    System.out.println(userList);
    }
    }

3.2 查询投影

  • 使用lambda

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @SpringBootTest
    class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll(){
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
    lqw.select(User::getId,User::getName,User::getAge);
    List<User> userList = userDao.selectList(lqw);
    System.out.println(userList);
    }
    }
  • 手动指定查询字段

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @SpringBootTest
    class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll(){
    QueryWrapper<User> lqw = new QueryWrapper<User>();
    lqw.select("id","name","age","tel");
    List<User> userList = userDao.selectList(lqw);
    System.out.println(userList);
    }
    }

3.3 字段映射与表名映射

  • 问题一:表字段与编码属性设计不同步

    image-20231016224202175

  • 问题二:编码中添加了数据库中未定义的属性

    image-20231016224312282

  • 问题三:采用了默认查询开放了更多的字段查看权限(比如密码)

    image-20231016224445721

  • 问题四:表名与编码开发设计不同步

    image-20231016224619205

四 DML控制

4.1 增

  • id生成策略控制
    • @TableId
    • image-20231016225723236
    • image-20231016225841407
    • 雪花算法生成id
      • image-20231016225947967

4.2 删

  • 多条删除

    image-20231016230155184

    • 多条查询:selectBatchIds(list)
  • 逻辑删除

4.3 改

  • 乐观锁

    • 原理:表字段中添加一个version,在set的时候对version进行判断,与此同时version+1以防止并发错误
  • 实现:

    • 表中添加version字段

    • 实体类中添加属性,加@version注解

    • 在拦截器定义的bean中添加乐观锁拦截器

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      @Configuration
      public class MpConfig {
      @Bean
      pubic MybatisPlusInterceptor mpInterceptor(){
      //定义Mp拦截器
      MybatisPlusInterceptor mpi = new MybatisPlusInterceptor();
      //添加具体的拦截器
      mpi.addInterInterceptor(new PaginationInnerInterceptor());
      //添加乐观锁拦截器
      mpi.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
      return mpi;
      }
      }

五 快速开发

  • 代码生成器

  • AutoGenerator

  • psvm(){
        AutoGenerator autoGenerator = new AutoGenerator();    
    
        //需要先定义DataSource对象
        autoGenerator.setDataSource(dataSource);
    
        //需先定义全局配置对象
        autoGenerator.setGlobalConfig(globalConfig);
    }