Java SSM框架

Java SSM框架

宣胤

Spring

Spring Framework系统架构

Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基

image-20230606215746774
image-20230606215746774

Spring核心

代码书写现状:耦合性偏高
解决方案:使用对象时,在程序中不要注定使用new产生对象,转换为由外部提供对象

IoC(Inversion of Control)控制反转

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

Spring技术对IOC思想进行了实现:Spring提供了一个容器,称为IoC容器(系统架构中的Core Container),用来充当IoC思想的“外部”。
IoC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中被称为Bean

DI (Dependency Injection) 依赖注入

在容器中建立Bena与Bean之间的依赖关系的整个过程,称为依赖注入

目标:充分解耦

  1. 使用IoC容器管理bean (IoC)
  2. 在IoC容器内将有依赖关系的bean进行绑定 (DI)

最终效果:使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系

Bean实例化方式
  • 无参构造实例化bean
  • 静态工厂实例化bean
  • 实例工厂实例化bean
  • FactoryBean实例化bean
Bean的生命周期

生命周期:从创建到消亡的完整过程
Bean生命周期:bean从创建到销毁的整体过程(对象从创建到销毁)
Bean生命周期控制:在bean创建后到销毁前做一些事情

1、bean生命周期控制:

  • 配置

    init-method

    destory-method

  • 接口

    InitializingBean

    DisposableBean

2、关闭容器:

  • ConfigurableApplicationContext

    close()

    registerShutdownHook()

依赖注入

向一个类中传递数据的方式:

  • 普通方法(set方法)
  • 构造方法

创建Bean依赖的数据类型:

  • 引用类型
  • 简单类型(基本数据类型与String)

依赖注入方式:

  • setter注入

    简单类型

    引用类型

  • 构造器注入

    简单类型

    引用类型

依赖注入方式选择:

  1. 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
  2. 可选依赖使用setter注入进行,灵活性强
  3. Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
  4. 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
  5. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
  6. 自己开发的模块推荐使用setter注入

依赖自动装配:

​ IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配

自动装配方式:

  • 按类型(常用)
  • 按名称
  • 按构造方法
  • 不启用自动装配

依赖自动装配特征:

  • 自动装配用于引用类型依赖注入,不能对简单类型进行操作
  • 使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
  • 使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
  • 自动装配优先级低于setter注入与构造器注入,同时出现自动装配配置失效
容器

创建容器:

  • ClassPathXmlApplicationContext
  • FileSystemXmlApplicationContext

获取bean:

  • 获取之后强转
  • 获取时添加获取的类型参数
  • 按照类型获取

注解开发

注解开发定义bean
//加载配置类初始化容器
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class)

@Configuration注解用于设定当前类为配置类
@ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据请用数组格式

Spring提供@Componemt注解的三个衍生注解

  1. @Controller:用于表现层bean定义
  2. @Service:用于业务层bean定义
  3. @Repository:用于数据层bean定义

@Autowired注解用于自动装配类型
@Value注解用于设定简单类型的值
@PropertySource注解加载properties文件

AOP(Aspect Oriented Programming)面向切面编程

一种编程范式,指导开发者如何组织程序结构–(OOP(Object Oriented Programming)面向对象编程)

作用:在不惊动原始设计的基础上为其进行功能增强
Spring理念:无入侵式/无侵入式

核心概念
  • 连接点(JoinPoint):程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等
    在SpringAOP中,理解为方法的执行
  • 切入点(PointCut):要进行功能增强的方法
    切入点表达式:匹配连接点的式子
    在SpringAOP中,一个切入点表达式可以只描述一个具体方法,也可以匹配多个方法
    一个具体方法:com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法
    匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
  • 通知(Advice):在切入点处执行的操作,也就是共性功能
    在SpringAOP中,功能最终以方法的形式呈现
  • 通知类:定义通知的类
  • 切面(Aspect):描述通知与切入点的对应关系
工作流程
  1. Spring容器启动

  2. 读取所有切面配置中的切入点

  3. 初始化bean,判定bean对应的类中的方法是否匹配到任意切入点

    匹配失败,创建对象

    匹配成功,创建原始对象(目标对象)的代理对象

  4. 获取bean执行方法

    获取bean,调用方法并执行,完成操作

    获取的bean是代理对象时,根据代理对象的运行模式运行原始方法与增强的内容,完成操作

目标对象(Target):原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终工作的

代理(Proxy):目标对象无法直接完成的工作,需要对其进行功能回填,通过原始对象的代理对象实现

SpringAOP本质:代理模式

切入点表达式

切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数) 异常名)

Execution (public User com.itheima.service.UserService.findById(int))

  • 动作关键字:描述切入点的行为动作,例如execution表示执行到指定切入点
  • 可以使用通配符描述切入点,快速描述
通知获取数据
  • 获取切入点方法的参数

    JoinPoint:适用于前置、后置、返回后、抛出异常后通知

    ProceedJoinPoint:适用于环绕通知

  • 获取切入点方法返回值

    返回后通知

    环绕通知

  • 获取切入点方法运行异常信息

    抛出异常后通知

    环绕通知

Spring事务

事务简介

Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败

开启事务步骤:

  1. 在业务层接口上添加Spring事务管理
  2. 设置事务管理器
  3. 开启注解式事务驱动

注意事项:Spring注解式事务通常添加在业务层接口中而不会添加到业务层实现类中,降低耦合。注解式事务可以添加到业务方法上表示当前方法开启事务,也可以添加到接口上表示当前接口所有方法开启事务。

事务角色

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

事务属性

image-20230607225604276
image-20230607225604276

SpringMVC

SpringMVC简介

概述

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

SpringMVC是一种表现层框架技术,用于表现层功能开发

SpringMVC是一种基于Javahi实现MVC模型的轻量级WEB框架

优点

  • 使用简单,开发便捷
  • 灵活性强
入门案例

名称:@Controller
类型:类注解
位置:SpringMVC控制器类定义上方
作用:设定SpringMVC的核心控制器bean
范例:

@Controller
public class UserController{
}

名称:@ResponseBody
类型:方法注解
位置:SpringMVC控制器方法定义上方
作用:设置当前控制器方法响应内容为当前返回值,无需解析
范例:

@RequestMapping("/save")
@ResponseBody
public String save(){
    System.out.println("user save ...");
    return "{'info':'springmvc'}";
}
SpringMVC入门程序开发总结(1+N)

1次工作:

  • 创建工程,设置服务器,加载工程
  • 导入坐标
  • 创建Web容器启动类,加载SpringMVC配置,并设置SpringMVC请求拦截路径
  • SpringMVC核心配置类(设置配置类,扫描controller包,加载Controller控制器bean)

N次工作:

  • 定义处理请求的控制器类
  • 定义处理请求的控制器方法,并配置映射路径(@RequestMapping)与返回json数据(@ResponseBody)
入门案例工作流程分析

启动服务器初始化过程:

  1. 服务器启动,执行ServletContainerInitConfig类,初始化web容器

  2. 执行createServletApplicationContext方法,创建了WebApplicationContext对象

  3. 加载SpringMvcConfig

  4. 执行@ComponentScan加载对应的bean

  5. 加载UserController,每个@RequestMapping的名称对应一个具体的方法

  6. 执行getServletMapping方法,定义所有的请求都通过SpringMVC

    image-20230609230510011
    image-20230609230510011

单次请求过程:

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

Controller加载控制与业务bean加载控制:(加载属于自己的bean)

SpringMVC相关bean(表现层bean)

Spring控制的bean:

  • 业务bean(Service)
  • 功能bean(DataSource等)

SpringMVC相关bean加载控制:

  • SpringMVC加载的bean对应的包均在com.itheima.controller包内

Spring相关bean加载控制:

  • 方式一:Spring加载的bena设定扫描范围为com.itheima,排除掉controller包内的bean
  • 方式二:Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等
  • 方式三:不区分Spring和SpringMVC的环境,加载到同一个环境中

名称:@ComponentScan
类型:类注解
范例:

@Configuration
@ComponentScan(value = "com.itheima",
excludeFilters = @ComponentScan.Filter(
        type = FilterType.ANNOTATION,
        classes = Controller.class
    )
)
public class SpringConfig{
}

属性:

  • excludeFilters:排除扫描路径中加载的bean,需要指定类别(type)与具体项(classes)
  • includeFilters:加载指定的bean,需要指定类别(type)与具体项(classes)

请求与响应

请求映射路径

名称:@RequestMapping
类型:方法注解 类注解
位置:SpringMVC控制器方法定义上方
作用:设置当前控制器方法请求访问路径,如果设置在类上统一设置当前控制器方法请求访问路径前缀
范例:

@Controller
@RequestMapping("/user")
public class UserController{
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'module':'user save'}";
    }
}

属性:

  • value(默认):请求访问路径,或访问路径前缀
请求方式

Get请求

Post请求

SpringMVC中需要解决Post请求中文乱码问题

请求参数
普通参数

普通参数:请求参数名与形参变量名不同,使用@RequestParam绑定参数关系
(@RequestParam(“”name) Strign userName, int age)

image-20230610003158201
image-20230610003158201

POJO参数:请求参数名与形参对象属性名相同,定义POJO类型参即可接收参数
(User user)

image-20230610003227859
image-20230610003227859

嵌套POJO参数:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
(User user)

image-20230610002515153
image-20230610002515153

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

image-20230610002719066
image-20230610002719066

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

image-20230610002945086
image-20230610002945086

JSON数据参数
  1. 发送数据

    image-20230610003759113
    image-20230610003759113

  2. 开启自动转换json数据的支持(在SpringMvcConfig中)
    @EnableWebMvc

  3. 设置接收数据

    JSON数据参数:(@RequestBody List likes)–发送数据如上图

    POJO参数:json数据与形参对象属性名相同,定义POJO类型形参即可接收参数
    (@RequestBody User user)

    image-20230610004305035
    image-20230610004305035

    POJO集合参数:json数组数据与集合泛型 属性名形同,定义List类型形参即可接收参数
    (@RequestBody List list)

    image-20230610004751808
    image-20230610004751808

比较@RequestBody与@RequestParam

区别:

  • @RequestParam用于接收url地址传参,表单传参[application/x-www-form-urlencoded]
  • @RequestBody用于接收json数据[application/json]

应用:

  • 后期开发中,发送json格式数据为主,@RequestBody应用较广
  • 如果发送非json格式数据,选用@RequestParam接收请求参数
日期类型参数

名称:@DateTimeFormat
类型:类注解
位置:SpringMVC控制器方法形参前面
作用:设定日期时间型数据格式
范例:

@RequestMapping("/dataParam")
@ResponseBody
public String dataParam(@DateTimeFormat(pattern="yyyy-MM-dd") Date date){
    System.out.println("参数传递 date ==> "+date);
    return "{'module':'data param'}";
}

属性:pattern:日期时间格式字符串

日期类型参数:(Date date,
@DateTimeFormat(pattern=”yyyy-MM-dd”) Date date1,
@DateTimeFormat(pattern=”yyyy/MM/dd HH:mm:ss”) Date date2)

类型转换器

Converter接口

public interface Converter<S,T>&#123;
    @Nullable
    T convert(S var1);
&#125;
  • 请求参数年龄数据(String -> Integer)
  • 日期格式数据(String -> Date)

@EnableWebMvc功能之一:根据类型匹配对应的类型转换器

响应

响应页面

响应数据

  • 文本数据
  • json数据

名称:@ResponseBody
类型:方法注解
位置:SpringMVC控制器方法定义上方
作用:设置当前控制器返回值作为响应体
范例:

@RequestMapping("/save")
@ResponseBody
public String save()&#123;
    System.out.println("save ...");
    return "&#123;'info':'springmvc'&#125;";
&#125;

REST风格

REST简介

REST(Representational State Transfer),表现形式转换–访问网络资源的格式

传统风格资源描述形式:

REST风格描述形式:

优点:

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

按照REST风格访问资源时使用行为动作区分对资源进行了何种操作:

注意事项:上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范
描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、accounts …

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

RESTful入门案例

步骤:

  1. 设定http请求动作(动词)

    @RequestMapping(value="/users", method = RequestMethod.POST)
    
  2. 设定请求参数(路径变量)

    @RequestMapping(value="/users/&#123;id&#125;", method = RequestMethod.POST)
    @ResponseBody
    public String delete(@PathVariable Integer id)&#123;
        System.out.println("user delete ..." + id);
        return "&#123;'module':'user delet'&#125;";
    &#125;
    
REST快速开发

名称:@RestController
类型:类注解
位置:基于SpringMVC的RESTful开发控制器类定义上方
作用:设置当前控制器类为RESTful风格,等同于@Controller与@ResponseBody两个注解组合功能
范例:

@RestController
public class BookController&#123;
&#125;

名称:@GetMapping @PostMapping @PutMapping @DeleteMapping
类型:方法注解
位置:基于SpringMVC的RESTful开发控制器方法定义上方
作用:设置当前控制器方法请求访问路径与请求动作,每种对应一个请求动作,例如@GetMapping对应GET请求
范例:

@GetMapping("/&#123;id&#125;")
public String getById(@PathVariable Integer id)&#123;
    System.out.println("book getById ..." + id);
    return "&#123;'module':'book getById'&#125;";
&#125;
案例:基于RESTful页面数据交互

步骤:

  1. 制作SpringMVC控制器,并通过Postman测试

    @RestController
    @RequestMapping("/books")
    public class BookController&#123;
        @PostMapping
        public String save(@RequestBody Book book)&#123;
            System.out.println("book save ==> " + book);
            return "&#123;'module':'book save success'&#125;";
        &#125;
        
        @GetMapping
        public List<Book> getAll()&#123;
            System.out.println("book getAll is running ...");
            List<Book> bookList = new ArrayList<Book>();
            Book book1 = new Book();
            book1.setType("计算机");
            book1.setName("SpringMVC入门教程");
            book1.setDescription("小试牛刀");
            bookList.add(book1);
            //模拟数据...
            return bookList;
        &#125;
    &#125;
    
  2. 设置对静态资源放行

    @Configuration
    public class SpringMvcSupport extends WebMvcConfigurationSupport&#123;
        @Override
        protected void addResourceHandlers(ResourceHandlerRegistry registry)&#123;
            //当访问/pages/???时候,走/pages目录下的内容
            registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
        &#125;
    &#125;
    
  3. 前端页面通过异步提交访问后天控制器

    //添加
    saveBook()&#123;
        axios.post("/books",this.formData).then((res)=>&#123;&#125;);
    &#125;,	//this.formData表示要保存的数据
    
    //主页列表查询
    getAll()&#123;
        axios.get("/books").then((res)=>&#123;
            this.dataList = res.data;
        &#125;)
    &#125;	//res.data是返回的数据
    

SSM整合

SSM整合流程
image-20230613213934991
image-20230613213934991
Spring整合MyBatis
image-20230613225935865
image-20230613225935865

记得事务处理

Spring整合Spring MVC

image-20230613230331323
image-20230613230331323

image-20230613230355220
image-20230613230355220

image-20230613230410789
image-20230613230410789

表现层数据封装

概念:前端接收数据格式–封装特殊消息到message(msg)属性中

设置统一数据返回类

public class Result&#123;
    private Object data;
    private Integer code;
    private String msg;
&#125;

注意事项:Result类中的字段并不是固定的,可以根据需要自行增减。提供若干个构造方法,方便操作!

设置统一数据返回结果编码

public class Code&#123;
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    
    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
&#125;

注意事项:Code类的常量设计也不是固定的,可以根据需要自行增减

根据情况设定合理的Controller

image-20230613233629580
image-20230613233629580

异常处理器

程序开发过程中不可避免的会遇到异常现象
各个层级均出现异常,异常处理代码书写在哪一层–所有的异常均抛出到表现层进行处理
表现层处理异常,每个方法中单独书写,代码书写量巨大且意义不强,如何解决–AOP思想
Spring为了不让开发者去做AOP,创造了:异常处理器
异常处理器:集中、统一的处理项目中出现的异常

@RestControllerAdvice
public class ProjectExecptionAdvice&#123;
    @ExecptionHandler(Exception.class)
    public Result doExecption(Exception ex)&#123;
        return new Result(666,null);
    &#125;
&#125;
项目异常处理方案

项目异常分类:

  • 业务异常

    规范的用户行为产生的异常

    不规范的用户行为操作产生的异常

  • 系统异常

    项目运行过程中可预计且无法避免的异常

  • 其他异常

    编程人员未预期到的异常

项目异常处理方案:

  • 业务异常

    发送对应消息传递给用户,提醒规范操作

  • 系统异常

    发送固定消息传递给用户,安抚用户

    发送特定消息给运维人员,提醒维护

    记录日志

  • 其他异常

    发送固定消息传递给用户,安抚用户

    发送特定消息给开发人员,提醒维护(纳入预期范围内)

    记录日志

自定义项目系统级异常

public class SystemException extends RuntimeException&#123;
    private Integer code;

    public Integer getCode() &#123;
        return code;
    &#125;

    public void setCode(Integer code) &#123;
        this.code = code;
    &#125;

    public SystemException(Integer code, String message) &#123;
        super(message);
        this.code = code;
    &#125;

    public SystemException(Integer code, String message, Throwable cause) &#123;
        super(message, cause);
        this.code = code;
    &#125;
&#125;

自定义项目业务及异常

public class BusinessException extends RuntimeException&#123;
    private Integer code;

    public Integer getCode() &#123;
        return code;
    &#125;

    public void setCode(Integer code) &#123;
        this.code = code;
    &#125;

    public BusinessException(Integer code, String message) &#123;
        super(message);
        this.code = code;
    &#125;

    public BusinessException(Integer code, String message, Throwable cause) &#123;
        super(message, cause);
        this.code = code;
    &#125;
&#125;

自定义异常编码

设置触发自定义异常

@Service
public class BookServiceImpl implements BookService&#123;
    @Autowired
    private BookDao bookdao;
    public Book getById(Integer id)&#123;
        if(id < 0)&#123;
            throw new BusinessException(Code.PROJECT_BUSINESS_ERR,"请勿进行非法操作!");
        &#125;
        return bookdao.getById(id);
    &#125;
&#125;

拦截并处理异常

@RestControllerAdvice
public class ProjectExceptionAdvice &#123;
    //@ExceptionHandler用于设置当前处理器类对应的异常类型
    @ExceptionHandler(SystemException.class)
    public Result doSystemException(SystemException ex)&#123;
        //记录日志
        //发送消息给运维
        //发送邮件给开发人员,ex对象发送给开发人员
        return new Result(ex.getCode(),null,ex.getMessage());
    &#125;

    @ExceptionHandler(BusinessException.class)
    public Result doBusinessException(BusinessException ex)&#123;
        return new Result(ex.getCode(),null,ex.getMessage());
    &#125;
&#125;
案例:SSM整合标准开发

拦截器

拦截器概念

首先回顾一下web应用是如何工作的:

image-20230614235159362
image-20230614235159362

概念:拦截器是一种动态拦截方法调用的机制

作用:

  • 在指定的方法调用前后执行预先设定后的代码
  • 阻止原始方法的执行

拦截器与过滤器区别:

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

制作拦截器功能类:

声明拦截器的bean,并实现HandlerInterceptor接口(注意:扫描加载bean)

@Component
//定义拦截器类,实现HandlerInterceptor接口
//注意当前类必须受Spring容器控制
public class ProjectInterceptor implements HandlerInterceptor &#123;
    @Override
    //原始方法调用前执行的内容
    //返回值类型可以拦截控制的执行,true放行,false终止
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception &#123;
        String contentType = request.getHeader("Content-Type");
        HandlerMethod hm = (HandlerMethod)handler;
        System.out.println("preHandle..."+contentType);
        return true;
    &#125;

    @Override
    //原始方法调用后执行的内容
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception &#123;
        System.out.println("postHandle...");
    &#125;

    @Override
    //原始方法调用完成后执行的内容
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception &#123;
        System.out.println("afterCompletion...");
    &#125;
&#125;

preHandle()方法返回false的话,就不会执行处理器

配置拦截器的执行位置:

定义配置类,继承WebMvcConfigurationSupport,实现addInterceptor方法(注意:扫描加载配置)
添加拦截器并设定拦截的访问路径,路径可以通过可变参数设置多个

@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport &#123;
    @Autowired
    private ProjectInterceptor projectInterceptor;

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) &#123;
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
    &#125;

    @Override
    protected void addInterceptors(InterceptorRegistry registry) &#123;
        //配置拦截器
        registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
    &#125;
&#125;

也可以使用标准接口WebMvcConfigurer简化开发(注意:侵入式较强):

@Configuration
@ComponentScan(&#123;"com.itheima.controller"&#125;)
@EnableWebMvc
//实现WebMvcConfigurer接口可以简化开发,但具有一定的侵入性
public class SpringMvcConfig implements WebMvcConfigurer &#123;
    @Autowired
    private ProjectInterceptor projectInterceptor;
    @Autowired
    private ProjectInterceptor2 projectInterceptor2;

    @Override
    public void addInterceptors(InterceptorRegistry registry) &#123;
        //配置多拦截器
        registry.addInterceptor(projectInterceptor).addPathPatterns("/books","/books/*");
        registry.addInterceptor(projectInterceptor2).addPathPatterns("/books","/books/*");
    &#125;
&#125;
拦截器工作流程分析

image-20230615003003024
image-20230615003003024

拦截器参数

前置处理:

public boolean preHandle(HttpServletRequest request,
                        HttpServletResponse response,
                        Object handler) throws Exception&#123;
    System.out.println("preHandle...");
    return true;
&#125;

参数:

  • request:请求对象
  • response:响应对象
  • handler:被调用的处理器对象,本质上不是一个方法对象,对反射技术中的Method对象进行了再包装

返回值:返回值为false,被拦截的处理器将不执行

后置处理:

public void postHandle(HttpServletRequest request,
                        HttpServletResponse response,
                        Object handler,
                        ModelAndView modelAndView) throws Exception&#123;
    System.out.println("postHandle...");
&#125;

参数:modelAndView,如果处理器执行完成具有返回结果,可以读取到数据与页面信息,并进行调整

完成后处理:

public void afterCompletion(HttpServletRequest request,
                        HttpServletResponse response,
                        Object handler,
                        Exception ex) throws Exception&#123;
    System.out.println("afterCompletion...");
&#125;

参数:ex:如果处理器执行过程中出现异常现象,可以针对异常情况进行单独处理

拦截器链

配置代码见–入门案例:使用标准接口WebMvcConfigurer简化开发

多拦截器执行顺序:

image-20230615004840614
image-20230615004840614

SpringBoot

SpringBoot入门

SpringBoot概述

概述:SpringBoot提供了一种快速使用Spring的方式,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑业务之间进行思维的切换,全身心的投入到逻辑业务的代码编写中,从而大大提高了开发的效率,一定程度上缩短了项目周期。

Spring缺点:

  1. 配置繁琐
  2. 依赖繁琐

SpringBoot功能:

  1. 自动配置
  2. 起步依赖
  3. 辅助功能

SpringBoot并不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式

SpringBoot快速入门

需求:搭建SpringBoot,定义HelloController.hello()方法,返回“Hello SpringBoot!”

实现步骤:

  1. 创建Maven项目
  2. 导入SpringBoot起步依赖
  3. 定义Controller
  4. 编写引导类
  5. 启动测试

SpringBoot起步依赖原理分析

spring-boot-starter-parent

spring-boot-starter-web

SpringBoot配置

配置文件分类

SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用application.properties或者application.yml(yaml)进行配置:

properties:
server.port=8080

yml:
server:
port: 8080

优先级:application.properties > application.yml > application.yaml

获取数据

读取配置内容:

  1. @Value
  2. Enviroment
  3. @ConfigurationProperties
Profile

我们在开发SpringBoot应用时,通常同一套程序会被安装到不同环境,比如:开发、测试、生产等。其中数据库地址、服务器端口等等配置都不同,如果每次打包时,都要修改配置文件,那么非常麻烦。Profile功能就是来进行动态配置切换的。

Profile配置方式:

  • 多profile文件方式
  • yml多文档方式

Profile激活方式:

  • 配置文件

    image-20230616183724539
    image-20230616183724539
  • 虚拟机参数

    image-20230616184007279
    image-20230616184007279
  • 命令行参数

    java -jar xxx.jar –spring.profiles.active=pro

配置加载顺序

内部配置加载顺序:

SpringBoot程序启动时,会从以下位置加载配置文件:

  1. file:./confog/ :当前项目下的/config目录下
  2. file:./ :当前项目的根目录
  3. classpath:/config/:classpath的/config目录
  4. classpath:/ :classpath的根目录

加载顺序为上文的排列顺序,高优先级配置的属性会生效

外部配置加载顺序:

通过官网查看外部属性加载顺序:

SpringBoot整合其他框架

SpringBoot整合Junit

实现步骤:

  1. 创建SpringBoot工程

  2. 引入starter-test起步依赖

  3. 编写测试类

  4. 添加测试相关注解

    @RunWith(SpringRunner.class)

    @SpringBootTest(classes = 启动类.class)

  5. 编写测试方法

SpringBoot整合Redis

实现步骤:

  1. 创建SpringBoot工程
  2. 引入redis起步依赖
  3. 配置redis相关属性
  4. 注入RedisTemplate模板
  5. 编写测试方法,进行测试
SpringBoot整合MyBatis

实现步骤:

  1. 创建SpringBoot工程
  2. 引入MyBatis起步依赖,添加MySQL驱动
  3. 编写DataSource和MyBatis相关配置
  4. 定义表和实体类
  5. 编写dao和mapper文件/纯注解开发
  6. 测试

SpringBoot高级

SpringBoot自动配置

Condition

Codition是在Spring4.0增加的条件判断功能,通过这个功能可以实现选择性的创建Bean操作

思考:SpringBoot是如何知道要创建哪个Bean的?比如SpringBoot是如何知道要创建RedisTemplate的?

需求:在Spring的IOC容器中有一个User的Bean,现要求:

  1. 导入Jedis坐标后,加载该Bean,没导入,则不加载
  2. 将类的判断定义为动态的。判断哪个字节码文件存在可以动态指定

image-20230618004958445
image-20230618004958445

@Enable*注解

SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。而其底层原理是使用@Import注解导入一些配置类,实现Bean的动态加载

@Enable*底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。而@Import提供4种用法:

  1. 导入Bean
  2. 导入配置类
  3. 导入ImportSelector实现类,一般用于加载配置文件中的类
  4. 导入ImportBeanDefinitionRegistrar实现类
@EnableAutoConfiguration注解

@EnableAutoConfiguration注解内部使用@Import(AutoConfigurationImportSelector.class)来加载配置类

配置文件位置:META-INF/spring.factories,该配置文件种定义了大量的配置类,当SpringBoot应用启动时,会自动加载这些配置类,初始化Bean

并不是所有的Bean都会被初始化,在配置类中使用Condition来加载满足条件的Bean

自定义配置案例

需求:自定义redis-starter。要求当导入redis坐标时,SpringBoot自动创建Jedis的Bean

实现步骤:

  1. 创建redis-spring-boot-autoconfigure模块
  2. 创建redis-spring-boot-starter模块,依赖redis-spring-boot-autoconfigure的模块
  3. 在redis-spring-boot-autoconfigure模块中初始化Jedis的Bean。并定义META-INF/spring.factories文件
  4. 在测试模块中引入自定义的redis-starter依赖,测试获取Jedis的Bean,操作redis

SpringBoot监听机制

SpringBoot的监听机制,其实是对Java提供的事件监听机制的封装

Java中的事件监听机制定义了以下几个角色:

  1. 事件:Event,继承java.util.EventObject类的对象
  2. 事件源:Source,任意对象Object
  3. 监听器:Listener,实现java.util.EventListener接口的对象

SpringBoot在项目启动时,会对几个监听器进行回调,我们可以实现这些监听器接口,在项目启动时完成一些操作:

ApplicationContextInitializer、SpringApplicationRunListener、CommandLineRunner、ApplicationRunner

SpringBoot启动流程分析

SpringBoot监控

SpringBoot自带监控功能Actuator,可以帮助实现对程序内部运行情况监控,比如监控情况、Bean加载情况、配置属性、日志信息等

使用步骤:

  1. 导入依赖坐标:

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
  2. 访问–http://localhost:8080/actuator

图形化监控–Spring Boot Admin

Spring Boot Admin是一个开源社区项目,用于管理和监控SpringBoot应用程序
Spring Boot Admin有两个角色,客户端(Client)和服务端(Server)
应用程序作为Spring Boot Admin Client向Spring Boot Admin Server注册
Spring Boot Admin Server的UI界面将Spring Boot Admin Client的Actuator Endpoint的一些监控信息展示

使用步骤:

image-20230620234404139
image-20230620234404139
  • 标题: Java SSM框架
  • 作者: 宣胤
  • 创建于: 2023-06-06 21:51:38
  • 更新于: 2023-06-21 00:04:27
  • 链接: http://xuanyin02.github.io/2023/06069152.html
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
 评论
此页目录
Java SSM框架