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

JavaWeb学习

文章目录

    • 学习路线
    • Maven
      • Maven 坐标
      • 依赖管理
      • 生命周期
    • 1. Web入门
      • HTTP协议
      • Tomcat
    • 2. 请求响应
      • - 请求
      • 1. 简单参数
      • 2. 实体参数
      • 3. 数组集合参数
      • 4. 日期参数
      • 5.Json参数
      • 6.路径参数
      • - 响应
      • 响应数据
    • 3.分层解耦
      • 三层架构
      • 分层解耦
      • IOC & DI入门
      • IOC详解
      • DI详解
    • 4. MySQL
      • 数据库设计
      • 1. MySQL概述
      • 2. 数据库设计-DDL
      • 数据库操作
      • 1. 数据库操作-DML
      • 2. 数据库查询操作-DQL
      • 3. 多表设计
      • 4. 多表查询
      • 5. 事务
      • 数据库优化
      • 1. 索引
    • 5. Mybatis
      • 5.1 Mybatis入门
        • 1. 快速入门
        • 2. JDBC介绍
        • 3. 数据库连接池
        • 4. lombok
      • 5.2 Mybatis基础增删改查
        • 根据主键删除
        • 新增
        • 更新
        • 查询
        • 条件查询
      • 5.3 XML映射文件
      • 5.4 Mybatis动态SQL
        • if
        • foreach
        • sql&include
    • 6. 案例
      • 6.1 环境搭建
      • 6.2 员工管理
        • 分页查询
      • 6.3 文件上传
        • 本地存储
        • 云存储
      • 6.4 配置文件
        • 参数配置化
        • yml配置文件(推荐)
        • @ConfigurationProperties
    • 7. 登录校验
      • 7.1 登录标记
        • 会话技术
      • 7.2 统一拦截
        • 过滤器Filter
        • 拦截器Intercepter
      • 7.3 异常处理
        • 全局异常处理器
    • 8. 事务管理&AOP
      • 事务管理
        • Spring事务管理
        • 事务进阶
      • AOP基础
        • AOP概述
        • 实现
        • AOP核心概念
      • AOP进阶
        • 1.通知类型
        • 2.通知顺序
        • 3.切入点表达式
        • 4.连接点
    • 9. Springboot原理
      • 9.1 配置优先级
      • 9.2 Bean管理
        • 获取bean
        • bean作用域
        • 第三方bean
      • 9.3 SpringBoot原理
        • 起步依赖原理
        • 自动配置原理
        • Web后端开发-总结
    • 10. Maven高级
      • 10.1 分模块设计与开发
      • 10.2 继承与聚合
        • 继承
        • 聚合
      • 10.3 私服
        • 介绍
        • 资源上传与下载

Written with StackEdit中文版.

学习路线

html、css、js --> Ajax、Axios -->Vue、Element–>前端工程化,Vue脚手架
Maven–>Springboot基础(基于Springboot进行讲解Spring的IOC、DI等)–>Springboot SpringMVC基础–>MySQL(基于产品原型和需求分析,设计数据库表)–>JDBC Mabatis–>Web案例(基于Springboot整合SSM,根据页面原型、需求、接口文档编写接口)–>会话跟踪技术(Cookie、Session,令牌技术JWT)–>Filter Intercepter(令牌的统一拦截校验)–>ADP–>Springboot原理

Maven

jdk 11
构建和管理java项目的工具
项目对象模型POM

Maven 坐标

groupid:maven项目隶属组织名称(通常是域名反写)
artifactid
version

依赖管理

  • 依赖传递
    直接依赖-间接依赖
    A依赖B,B依赖C,那么A会依赖C
  • 排除依赖
    <exclusions><exclusion>
    
    主动断开依赖的资源,被排除的资源无需指定版本
  • 依赖范围
    依赖的jar包,默认情况下可以在任何地方使用,可以通过<scope>...<scope> 设置其作用范围
    • 主程序范围有效(main文件夹范围内)
    • 测试程序范围有效(test文件夹范围内)
    • 是否参与打包运行(package指令范围内)
      在这里插入图片描述

生命周期

maven的生命周期是为了对所有的maven项目构建过程进行抽象和统一
maven有三套独立的生命周期

  • clean:清理工作
  • default:核心工作,如:编译、测试、打包、安装、部署等
  • site:生成报告、发布站点等

在同一套生命周期中,阶段是有顺序的,后面的阶段依赖于前面的阶段。运行后面的阶段时,前面的阶段都会运行
在这里插入图片描述

在这里插入图片描述

1. Web入门

HTTP协议

超文本传输协议,规定了浏览器和服务器之间数据传输的规则

  • 请求协议
    请求行:请求方式、资源路径、协议
    请求头
    请求体:POST请求,存放请求参数

GET请求,请求参数在请求行中,没有请求体。GET请求大小有限制
POST请求,请求参数在请求体中,POST请求大小没有限制

在这里插入图片描述

  • 响应协议
    响应行 响应头 响应体
    响应行 200 404 500
    在这里插入图片描述

响应头
在这里插入图片描述

在这里插入图片描述

状态码大全 https://cloud.tencent.com/developer/section/1190137

  • 协议解析
    Tomcat web服务器对http协议进行封装

Tomcat

轻量级Web服务器,支持Servlet/JSP少量JavaEE规范。也被称为web容器、servlet容器

  • 起步依赖
    包含了对应业务开发所需要的常见依赖
  • 内嵌Tomcat服务器

2. 请求响应

前端发出的请求,都会先传给DispatcherServlet(前端控制器),DispatcherServlet再转给Controller程序。
TomCat会对前端的请求进行解析,并将解析后的所有信息封装到HttpServletRequest对象中。根据HttpServletResponse对象设置要响应的数据。

  • 请求(HttpServletRequest):获取请求数据
  • 响应(HttpServletResponse):设置相应数据
  • BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端
  • CS架构:Client/Server,客户端/服务器架构模式

- 请求

1. 简单参数

  • 原始方式
    在原始的web程序中,获取请求参数,需要通过HttpServletRequest对象手动获取
    繁琐、手动类型转换
  • Springboot方式
    简单参数:参数名与形参变量名相同,定义形参即可接收参数
    在接受过程中会自动进行类型转换
  • RequestParam注解
    • 如果方法形参名称与请求参数名称不匹配,可以使用@RequestParam完成映射
    • @RequestParam中的required属性默认为true,代表该请求参数必须传递。如果该参数是可选的,可以将required设置为false。
    public String simpleParam(@RequestParam(name = "name",required = false) String username, Integer age){  // 获取请求参数  System.out.println(username+":"+age);  return "OK";  
    }
    

2. 实体参数

  • 简单实体对象
    请求参数名与形参对象属性名相同,定义POJO接收即可
  • 复杂实体对象
    请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
    @RequestMapping("/complexPojo")  
    public String complexPojo(User user){  System.out.println(user);  return "OK";  
    }
    

3. 数组集合参数

  • 数组参数
    请求参数名与形参数组名称相同,且请求参数为多个,定义数组类型形参即可接收参数
    @RequestMapping("/arrayParam")  
    public String arrayParam(String[] hobby){  System.out.println(Arrays.toString(hobby));  return "OK";  
    }
    
  • 集合参数
    请求参数名与形参集合名称相同,且请求参数为多个,@RequestParam绑定参数关系
    默认封装到数组集合,如果要用list,就要加上注解
    @RequestMapping("/listParam")  
    public String listParam(@RequestParam List<String> hobby){  System.out.println(hobby);  return "OK";  
    }
    

4. 日期参数

  • 使用@DataTimeFormat注解完成日期参数格式转换,存到LocalDateTime对象中
    @RequestMapping("/dataParam")  
    public String dataParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime){  System.out.println(updateTime);  return "OK";  
    }
    

5.Json参数

  • JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数,需要使用@RequestBody标识
     @RequestMapping("/jsonParam")  
    public String jsonParam(@RequestBody User user){  System.out.println(user);  return "OK";  
    }
    

6.路径参数

  • 通过请求URL直接传递参数,使用{…}来标识该路径参数,需要使用@PathVariable获取路径参数
    @RequestMapping("/path/{id}")  
    public String pathParam(@PathVariable Integer id){  System.out.println(id);  return "OK";  
    }
    
    @RequestMapping("/path/{id}/{name}")  
    public String pathParam2(@PathVariable Integer id,@PathVariable String name){  System.out.println(id+":"+name);  return "OK";  
    }
    

- 响应

响应数据

  • @ResponseBody
    类型:方法注解、类注解
    位置:Controller方法上/类上
    作用:将方法返回值直接响应,如果返回值类型是 实体对象/集合,将会转换成JSON格式响应
    说明:@RestController=@Controller+@ResponseBody
  • 统一响应结果
    Result对象
    Result(code,msg,data)

3.分层解耦

三层架构

  • Controller:控制层,接受前端发送到请求,对请求进行处理,并响应数据
  • Service:业务逻辑层,处理具体的业务逻辑
  • Dao:数据访问层(Data Access Object)(持久层),负责数据访问操作,包括数据的增、删、改、查

分层解耦

    • 内聚:软件中各个功能模块内部的功能联系
    • 耦合:软件中各个层/模块之间的依赖、关联程度
    • 软件设计原则:高内聚低耦合
      在容器里放耦合代码,谁需要调用就来容器里面调用
  • 控制反转:Inversion of Control,IOC
    对象的创建控制权由程序自身转移到外部(容器)
  • 依赖注入:Dependency Injection,DI
    容器为应用程序提供运行时,所依赖的资源,称之为依赖注入
  • Bean对象:IOC容器内创建、管理的对象,称之为bean

IOC & DI入门

  • Service层及Dao层的实现类,交给IOC容器管理 添加@Component注解
    @Component 将当前类交给IOC容器管理,成为容器中的bean
  • 为Controller及Service注入运行时依赖的对象,添加@Autowired注解
    在这里插入图片描述

IOC详解

要把某个对象交给IOC容器管理,需要在对应类上加上如下注解之一:
@Component@Controller@Service@Repository
在这里插入图片描述

  • 声明bean的时候,可以通过value属性指定bean的名字,没有指定时默认类名是类名首字母小写
  • 声明控制器bean只能用@Controller
  • 组件扫描
  • Bean组件扫描
    • 声明bean的四大注解,需要被组件扫描注解@ComponentScan扫描
    • @ComponentScan注解虽然没有显示配置,但实际上已经包含在了启动类生命注解@SpringBootApplication中,默认扫描的范围是启动类所在包及其子包

DI详解

  • @Autowired注解,默认按照类型进行,如果存在多个相同类型的bean,就会报错
  • 解决方案
    • @Primary 想让哪个生效,就在哪个类前加该注解
    • @Qualifier 在@Autowired前添加@Qualifier(“类名首字母小写”)
    • @Resource 按照名称进行@Resource(name=“类名首字母小写”)
  • @Resource 与 @Autowired 区别
    • @Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
    • @Autowired 默认是按照类型注入,而@Resource默认按照名称注入

4. MySQL

  • DBMS 数据库管理系统

数据库设计

1. MySQL概述

  • 企业开发使用方式

    net start mysql80
    
    mysql -u用户名 -p密码 [-h数据库服务器IP地址 -P端口号]
    
  • 数据模型

    • 关系型数据库(RDBMS):建立在关系模型基础上,由多张相互连接的二维表组成的数据库
    • 创建数据库 create database db01;
      创建表结构
  • SQL简介

    分类用途
    DDL数据定义语言,操作表结构
    DML数据操作语言,增删改
    DQL数据查询语言
    DCL数据控制语言,创建用户、控制访问权限

2. 数据库设计-DDL

  • 数据库

    • 查询
      查询所有数据库:show databases;
      查询当前数据库:select database();
    • 使用 use 数据库名;
    • 创建 create database [if not exists] 数据库名;
    • 删除 drop database [if exists] 数据库名;
    • 上述语法中的database,也可以替换成schema
      []代表可写可不写
  • 数据类型
    数值类型、字符串类型、日期时间类型
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • DDL 表(创建、查询、修改、删除)

    • 创建
     create table 表名(字段1 字段类型 [约束] [comment 字段1注释],......字段n 字段类型 [约束] [comment 字段n注释],)[comment 表注释];
    

    约束是作用于表中字段上的规则,用于限制存储在表中的数据。保证数据库中数据的正确性、有效性和完整性
    在这里插入图片描述

    create table tb_user(  id int primary key comment 'ID 唯一标识',  username varchar(20) not null  unique comment '用户名',  name varchar(10) not null comment '姓名',  age int comment '年龄',  gender char(1) default '女' comment '性别'  
    )comment '用户表';
    
    • 查询
      查询当前数据库所有表 show tables;
      查询表结构 desc 表名;
      查询建表语句 show create table 表名;
    • 修改
      添加字段:alter table 表名 add 字段名 类型(长度) [comment 注释] [约束];
      修改字段类型 alter table 表名 modify 字段名 新数据类型(长度);
      修改字段名和字段类型 alter table 表名 change 旧字段名 类型(长度) [comment 注释] [约束];
      删除字段 alter table 表名 drop column 字段名;
      修改表名 rename table 表名 to 新表名;
    • 删除
      drop table [if exits] 表名;
      
  • datalog 图形化界面
    intelliJ IDEA 嵌入
    在这里插入图片描述

数据库操作

1. 数据库操作-DML

Data Munipulation Language

  • 添加数据(INSERT)
    指定字段添加数据:insert into 表名 (字段名1,字名2) values(值1,值2);
    全部字段添加数据:insert into 表名 values (值1,值2,….);
    批量添加数据(指定字段):insert into 表名(字段名1,字段名2) values (值1,值2),(值1,值2);
    批量添加数据(全部字段):insert into 表名 values(值1,值2,...),(值1,值2,...);
  • 修改数据(UPDATE)
    修改数据:update 表名 set 字段名1=值1,字段名2=值2,…[where 条件];
  • 删除数据(DELETE)
    delete form 表名 [where 条件];
    
    DELETE语句不能删除某一个字段的值(如果要操作,可以使用UPDATE,将该字段的值置为NULL

2. 数据库查询操作-DQL

关键字 SELECT
在这里插入图片描述

  • 基本查询

    • 查询多个字段:select 字段1,字段2,字段3 from 表名;
    • 查询所有字段(通配符):select * from 表名;
      *号尽量不使用
    • 设置别名:select 字段1 as 别名1,字段2 as 别名2 from 表名;
      as可省略
    • 去除重复记录:select distinct 字段列表 from 表名;
  • 条件查询

    select 字段列表 from 表名 where 条件列表;
    

    在这里插入图片描述

  • 聚合函数
    将一列数据作为一个整体,进行纵向计算
    不能对null值进行计算

    select 聚合函数(字段列表) from 表名;
    
    函数功能
    count统计数量
    max最大值
    min最小值
    sum求和
    avg平均值
    • count
      count()(推荐)、 count(常量)、 count(列名)
      COUNT(常量) 和 COUNT(
      )表示的是直接查询符合条件的数据库表的行数
  • 分组查询

    select 分组字段[聚合函数] from 表名 [where 条件] group by 分组字段名 [having 分组后过滤条件];
    
    /*先查询入职时间在'2015-01-01'(包含)以前的员工,并对结果根据职位分组,获取员工数量大于等于2的职位*/  
    select job,count(*) from tb_emp where entrydate<='2015-01-01' group by job having count(*)>=2;
    
    • where与having区别
      执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组之后对结果进行过滤。
      判断条件不同:where不能对聚合函数进行判断,而having可以。
    • 注意事项
      分组之后,查询的字段一般为聚合函数和分组字段,查询其他字段无任何意义
      执行顺序:where>聚合函数>having
  • 排序查询

    select 分组字段[聚合函数] from 表名 [where 条件] group by 分组字段名 order by 字段1 排序方式1,字段2 排序方式2 ...;
    
    • 排序方式:ASC:升序(默认值),DESC:降序
    • 如果是多字段排序,当第一个字段值相同时,才会根据第二个字段进行排序。
  • 分页查询

    select 字段列表 from 表名 limit 起始索引,查询记录数;
    
    • 起始索引从0开始,起始索引=(查询页码-1)*每页显示记录数。
    • 分页查询是数据库的方言,不同的数据库有不同的实现,MySOL中是LIMIT。
    • 如果查询的是第一页数据,起始索引可以省略,直接简写为limit 10。
    select if(gender=1,'女性员工','男性员工')性别,count(*) from tb_emp group by gender;
    

3. 多表设计

  • 一对多
    一对多关系实现:在数据库表中多的一方,添加字段,来关联一的一方的主键

  • 外键约束
    –创建表时指定

    create table 表名(字段名 数据类型...[constraint][外键名称]foreign key(外键字段名)references 主表(字段名)
    );
    
    --建完表后,添加外键
    alter table 表名 add constraint 外键名称 foreign key(外键字段名)references 主表(字段名)
    

    在这里插入图片描述

    • 缺点
      影响增、删、改的效率(需要检查外键关系)仅用于单节点数据库,不适用与分布式、集群场景。
      容易引发数据库的死锁问题,消耗性能。
  • 一对一

    • 案例:用户 与 身份证信息 的关系
    • 关系:一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他字段放在另一张表中,以提升操作效率
    • 实现:在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)
  • 多对多

    • 实现:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键

4. 多表查询

笛卡尔积
select * from tb_emp,tb_dept;
消除无效的笛卡尔积
select * from tb_emp,tb_dept where tb_emp.dept_id=tb_dept.id;
    1. 连接查询
    • 内连接:查询A、B交集数据
      隐式内连接:select字段列表 from 表1,表2where 条件...
      查询员工的姓名,及所属的部门名称
      select tb_emp.name,tb_dept.name from tb_emp,tb_dept where tb_emp.dept_id=tb_dept.id;
      起别名
      select e.name,d.name from tb_emp e,tb_dept d where e.dept_id=d.id;
      
      显式内连接:select字段列表 from 表1[inner]join 表2 on 连接条件...
      select tb_emp.name,tb_dept.name from tb_emp inner join tb_dept  on tb_emp.dept_id = tb_dept.id;
      
    • 外连接
      • 左外连接:以左表为基准,完全包括左表的数据和交集数据
        select 字段列表 from 表1 left [outer]join 表2 on 连接条件 …;
      • 右外连接:以右表为基准,完全包括右表的数据和交集数据
        select 字段列表 from 表1 right [outer]join 表2 on 连接条件...;
    1. 子查询
      介绍:SQL语句中嵌套select语句,称为嵌套查询,又称子查询。
      形式:select *from tl where column1=(select columnl from t2 ... );
      子查询外部的语句可以是insert/update/delete/select 的任何一个,最常见的是 select。
    • 标量子查询:子查询返回的结果为单个值
      常用操作符:= <> > >= < <=
      select * from tb_emp where dept_id = (select id from tb_dept where name='教研部') ;
    • 列子查询:子查询返回的结果为一列
      常用操作符:in、not in
      select * from tb_emp where dept_id in (select id from tb_dept where name = '教研部' or name='咨询部');
    • 行子查询:子查询返回的结果为一行
      常用操作符:= <> in not in
      select * from tb_emp where (entrydate,job) = (select entrydate,job from tb_emp where name='韦一笑');
    • 表子查询:子查询返回的结果为多行多列
      常见操作符:in
      select *,tb_dept.name from (select * from tb_emp where entrydate > '2006-01-01') e ,tb_dept where tb_dept.id = e.dept_id;

5. 事务

事务 是一组操作的集合,它是一个不可分割的工作单位。事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作 要么同时成功,要么同时失败

  • 事务控制
    • 开启事务:start transaction;/begin;
    • 提交事务:commit;
    • 回滚事务:rollback;
  • 四大特性(ACID)
    在这里插入图片描述

数据库优化

1. 索引

索引(index)是帮助数据库 高效获取数据 的 数据结构

  • 介绍

    • 优缺点
      优点:降低查询排序成本
      缺点:降低增删改效率
      在这里插入图片描述
  • 结构
    MySQL数据库支持的索引结构有很多,如:Hash索引、B+Tree索引、Ful-Text索引等。我们平常所说的索引,如果没有特别指明,都是指默认的 B+Tree 结构组织的索引。

  • B+Tree(多路平衡搜索树)
    每一个节点,可以存储多个key(有n个key,就有n个指针)
    所有的数据都存储在叶子节点,非叶子节点仅用于索引数据。
    叶子节点形成了一颗双向链表,便于数据的排序及区间范围查询。
    在这里插入图片描述

  • 语法

    • 创建索引:create [unique]index 索引名 on 表名(字段名,.);
    • 查看索引:show index from 表名;
    • 删除索引:drop index 索引名 on 表名;
    • 注意
      主键字段,在建表时,会自动创建主键索引。
      添加唯一约束时,数据库实际上会添加唯一索引。

5. Mybatis

5.1 Mybatis入门

1. 快速入门
  • 准备工作(创建springboot工程、数据库表user、实体类User)
    在这里插入图片描述

  • 引入Mybatis的相关依赖,配置Mybatis(数据库连接信息)

    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
    spring.datasource.username=root
    spring.datasource.password=1234
    
  • 编写SQL语句(注解/XML)
    定义持久层接口,加上Mapper注解定义接口

    @Mapper
    public interface UserMapper {@Select("select * from user")public List<User> list();
    }
    
2. JDBC介绍

JDBC:(Java DataBase Connectivity),就是使用Java语言操作关系型数据库的一套API。
各个数据库厂商去实现这套接口,提供数据库驱动jar包,
我们可以使用这套接口(JDBC)编,真正执行的代码是驱动jar包中的实现类

3. 数据库连接池

数据库连接池是个容器,负责分配、管理数据库连接(Connection)
它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
释放 空闲时间超过最大空闲时间 的连接,来避免因为没有释放连接而引起的数据库连接遗漏
在这里插入图片描述

在这里插入图片描述

<dependency>  <groupId>com.alibaba</groupId>  <artifactId>druid-spring-boot-3-starter</artifactId>  <version>1.2.21</version>  
</dependency>
4. lombok

在这里插入图片描述

5.2 Mybatis基础增删改查

根据主键删除
```
@Delete("delete from emp where id=#{id}")  //占位符
public void delete(Integer id);
```
  • 日志输出
    #指定mybatis输出日志的位置,输出控制台
    mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutmpl
    
  • 预编译SQL
    优势:性能更高、更安全(防止SQL注入)
    在这里插入图片描述

在这里插入图片描述

  • SQL注入
    SQL注入是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法
  • 参数占位符
    在这里插入图片描述
新增
// 新增员工  
@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +  "values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")  
public void insert(Emp emp);
  • 主键返回
@Options(useGeneratedKeys = true,keyProperty = "id")//获取返回属性,并将属性封装到id属性
更新
查询

在这里插入图片描述

实体类属性名 和 数据库表查询返回的字段名一致,mybatis会自动封装
如果实体类属性名 和 数据库表查询返回的字段名不一致,不能自动封装

  • 解决方案

    • 方案一:给字段起别名,让别名与实体类属性一致
    @Select("select id, username, password, name, gender, image, job, entrydate, " +  "dept_id deptId, create_time createTime, update_time updateTime from emp where id=#{id}")  
    public Emp getById(Integer id);  
    
    • 方案二:通过@Results,@Result注解手动映射封装
    @Results({  @Result(column = "dept_id",property = "deptId"),  @Result(column = "create_time",property = "createTime"),  @Result(column = "update_time",property = "updateTime"),  })  @Select("select * from emp where id=#{id}")  public Emp getById(Integer id);  
    
    • 方案三:开启mybatis驼峰命名自动映射开关 a_column------>aColumn,需要严格遵守命名规范
      application.properties中添加
    #开启驼峰命名  
    mybatis.configuration.map-underscore-to-camel-case=true
    
条件查询
// concat 字符串拼接函数  
@Select("select * from emp where name like concat('%',#{name},'%') and gender=#{gender} and entrydate between #{beginDate} and #{endDate} order by update_time desc")  
public List<Emp> list(String name, Short gender, LocalDate beginDate, LocalDate endDate);

5.3 XML映射文件

  • XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)
  • XML映射文件的namespace属性为Mapper接口全限定名一致。
  • XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。
    在这里插入图片描述
<?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.ljytest.mapper.EmpMapper">  <!--resultType:-->  <select id="list" resultType="com.ljytest.pojo.Emp">  select * from emp where name like concat('%',#{name},'%') and gender=#{gender} and entrydate between #{beginDate} and #{endDate} order by update_time desc  </select>  
</mapper>

使用Mybatis注解,主要完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句

5.4 Mybatis动态SQL

随着用户的输入或外部条件的变化而变化的SQL语句,我们称为动态SQL

if

用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL
<where>:where 元素只会在子元素有内容的情况下才插入where子句。而且会自动去除子句的开头的AND 或OR。
<set>:动态地在行首插入 SET关键字,并会删掉额外的逗号。(用在update语句中)

<!--动态更新员工信息-->  
<update id="update2">  update emp  <set>  <if test="username!=null"> username=#{username},</if>  <if test="name!=null">name=#{name},</if>  <if test="gender!=null">gender=#{gender},</if>  <if test="image!=null">image=#{image},</if>  <if test="job!=null">job=#{job},</if>  <if test="entrydate!=null">entrydate=#{entrydate},</if>  <if test="deptId!=null">dept_id=#{deptId},</if>  <if test="updateTime!=null">update_time=#{updateTime}</if>  </set>  where id = #{id}  
</update>  
<!--resultType:-->  
<select id="list" resultType="com.ljytest.pojo.Emp">  select *  from emp    <where>  <if test="name!=null">  name like concat('%', #{name}, '%')  </if>  <if test="gender!=null">  and gender = #{gender}  </if>  <if test="beginDate != null and endDate != null">  and entrydate between #{beginDate} and #{endDate}  </if>  </where>  order by update_time desc  
</select>
foreach
  • collection:遍历的集合
  • item:遍历出来的元素
  • separator:分隔符
  • open:遍历开始前拼接的SQL片段
  • close:遍历结束后拼接的SQL片段
<!--批量删除-->
<delete id="deleteByIds">  delete from emp where id in  <foreach collection="ids" item="id" separator="," open="(" close=")">  #{id}  </foreach>  
</delete>
sql&include

<sql>:定义可重用的SQL片段
<include>:通过属性refid,制定包含的sql片段

<sql id="commonSelect">  select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time  from emp
</sql>
<include refid="commonSelect"></include>

6. 案例

6.1 环境搭建

准备数据库表(dept、emp)
创建springboot工程,引入对应的起步依赖(web、mybatis、mysql驱动、lombok)配置文件application.properties中引入mybatis的配置信息,准备对应的实体类准备对应的Mapper、Service(接口、实现类)、Controller基础结构

  • 开发规范-Restful
    REST(REpresentational State Transfer),表述性状态转换,它是一种软件架构风格
    在这里插入图片描述

  • 开发规范-统一响应结果
    前后端交互统一响应结果 Result
    在这里插入图片描述

6.2 员工管理

分页查询
  • 注解
    @RequestParam(defaultValue="1") //设置请求参数默认值
    @Slf4j //定义日志记录对象
  • 分页插件PageHelper
    • 引入依赖
    <!--PageHelper分页插件-->  
    <dependency>  <groupId>com.github.pagehelper</groupId>  <artifactId>pagehelper-spring-boot-starter</artifactId>  <version>1.4.6</version>  
    </dependency>
    
    • 使用
      EmpServiceImpl
      public PageBean page(Integer page, Integer pageSize) {  // 1.设置分页参数  PageHelper.startPage(page,pageSize);  // 2.执行查询  List<Emp> empList = empMapper.list();  Page<Emp> empPage = (Page<Emp>) empList;  // 3.封装PageBean对象  PageBean pageBean = new PageBean(empPage.getTotal(),empPage.getResult());  return pageBean;  
      }
      
      EmpMapper
      @Select("select * from emp")  
      List<Emp> list();
      

6.3 文件上传

  • 服务端接收文件
    MultipartFile
本地存储

uuid 唯一标识

@PostMapping("/upload")  
public Result upload(String username, Integer age, MultipartFile image) throws IOException {  log.info(" 文件上传:{},{},{}",username,age,image);  // 获取原始文件名  String originalFilname = image.getOriginalFilename();  // 构造唯一文件名(不能重复)-uuid(通用唯一识别码)  int index = originalFilname.lastIndexOf(".");  String extname = originalFilname.substring(index);  String newFileName = UUID.randomUUID().toString() + extname;  log.info("新的文件名:{}",newFileName);  //将文件存储在服务器的磁盘目录下 image.transferTo(new File("F:\\LJY\\PostGraduate\\CodeLearing\\Java\\JavaWebTest\\images\\"+newFileName));  return Result.success();  
}
#配置单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB
#配置单个请求最大上传大小(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size=100MB

常用方法

String getOriginalFilename(); //获取原始文件名
void transferTo(File dest);//将接收的文件转存到磁盘文件中
long getsize(); //获取文件的大小,单位:字节
byte[] getBytes(); //获取文件内容的字节数组
Inputstream getinputstream();//获取收到的文件内容的输入流

无法直接访问、磁盘空间限制、磁盘损坏

云存储

https://oss.console.aliyun.com/bucket/oss-cn-beijing/ljy-web-framework01/object
阿里云对象存储OSS(Object Storage Service)
第三方服务-通用思路
在这里插入图片描述

Bucket:存储空间是用户用于存储对象(0bject,就是文件)的容器,所有的对象都必须隶属于某个存储空间,
SDK:Software Development Kit 的缩写,软件开发工具包,包括辅助软件开发的依赖(jar包)、代码示例等,都可以叫做SDK。

<!--阿里云OSS-->  
<dependency>  <groupId>com.aliyun.oss</groupId>  <artifactId>aliyun-sdk-oss</artifactId>  <version>3.15.1</version>  
</dependency>  <dependency>  <groupId>javax.xml.bind</groupId>  <artifactId>jaxb-api</artifactId>  <version>2.3.1</version>  
</dependency>  
<dependency>  <groupId>javax.activation</groupId>  <artifactId>activation</artifactId>  <version>1.1.1</version>  
</dependency>  
<!-- no more than 2.3.3-->  
<dependency>  <groupId>org.glassfish.jaxb</groupId>  <artifactId>jaxb-runtime</artifactId>  <version>2.3.3</version>  
</dependency>
@Component  
public class AliOSSUtils {  private String endpoint = "https://oss-cn-beijing.aliyuncs.com";  // 从环境变量中获取访问凭证  private String accessKeyId = "LTAI5tJd5jSaFs5rEaprVPfL";  private String accessKeySecret = "6Xm6GYkmopkwCkyvk22X6qzOwZWJrv";  // 填写Bucket名称  private String bucketName = "ljy-web-framework01";  /**  * 实现上传图片到OSS  */    public String upload(MultipartFile file) throws IOException {  // 获取上传的文件的输入流  InputStream inputStream = file.getInputStream();  // 避免文件覆盖  String originalFilename = file.getOriginalFilename();  String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));  //上传文件到 OSS        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);  ossClient.putObject(bucketName, fileName, inputStream);  //文件访问路径  String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;  // 关闭ossClient  ossClient.shutdown();  return url;// 把上传到oss的路径返回  }  }

6.4 配置文件

参数配置化

@Value 注解通常用于外部配置的属性注入,具体用法为: @Value("${配置文件中的key}")

  • application.properties
    #自定义的阿里云OSS配置信息  
    aliyun.oss.endpoint=https://oss-cn-beijing.aliyuncs.com  
    #从环境变量中获取访问凭证  
    aliyun.oss.accessKeyId=LTAI5tJd5jSaFs5rEaprVPfL  
    aliyun.oss.accessKeySecret=6Xm6GYkmopkwCkyvk22X6qzOwZWJrv  
    #填写Bucket名称  
    aliyun.oss.bucketName=ljy-web-framework01
    
  • AliOSSUtils
    @Value("${aliyun.oss.endpoint}")  
    private String endpoint;  
    // 从环境变量中获取访问凭证  
    @Value("${aliyun.oss.accessKeyId}")  
    private String accessKeyId;  
    @Value("${aliyun.oss.accessKeySecret}")  
    private String accessKeySecret;  // 填写Bucket名称  
    @Value("${aliyun.oss.bucketName}")  
    private String bucketName;
    
yml配置文件(推荐)

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

@ConfigurationProperties
  • 添加配置文件后,yml文件会有相对应的配置项的提示
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId>
    </dependency>
    
  • AliOSSProperties.java
    @Data  
    @Component  
    @ConfigurationProperties(prefix = "aliyun.oss")  
    public class AliOSSProperties {  private String endpoint;  // 从环境变量中获取访问凭证  private String accessKeyId;  private String accessKeySecret;  // 填写Bucket名称  private String bucketName;  
    }
    

7. 登录校验

7.1 登录标记

用户登录成功之后,每一次请求中,都可以获取到该标记——会话技术

会话技术
  • 会话:用户打开浏览器,访问web服务器资源,会话建立,知道有一方断开连接,会话结束。一次会话中可以包含多次请求和响应
    在这里插入图片描述

  • 会话跟踪:识别请求是否来自于同一个浏览器

  • 会话跟踪方案:

    • 客户端会话跟踪技术:Cookie
    • 服务端会话跟踪技术:Session
    • 令牌技术
  • 客户端会话跟踪技术:Cookie
    在这里插入图片描述

    跨域区分三个维度:协议、IP/域名、端口

    <dependency>  <groupId>javax.servlet</groupId>  <artifactId>servlet-api</artifactId>  <version>2.5</version>  
    </dependency>
    
    //设置Cookie
    @GetMapping("/c1")  
    public Result cookie1(HttpServletResponse response){  response.addCookie(new Cookie("login_username","itheima")); //设置Cookie/响应Cookie  return Result.success();  
    }  //获取Cookie  
    @GetMapping("/c2")  
    public Result cookie2(HttpServletRequest request){  Cookie[] cookies = request.getCookies();  for (Cookie cookie : cookies) {  if(cookie.getName().equals("login_username")){  System.out.println("login_username: "+cookie.getValue()); //输出name为login_username的cookie  }  }  return Result.success();  
    }
    
  • 服务端会话跟踪技术:Session
    在这里插入图片描述

    @GetMapping("/s1")  
    public Result session1(HttpSession session){  log.info("HttpSession-s1: {}", session.hashCode());  session.setAttribute("loginUser", "tom"); //往session中存储数据  return Result.success();  
    }  @GetMapping("/s2")  
    public Result session2(HttpServletRequest request){  HttpSession session = request.getSession();  log.info("HttpSession-s2: {}", session.hashCode());  Object loginUser = session.getAttribute("loginUser"); //从session中获取数据  log.info("loginUser: {}", loginUser);  return Result.success(loginUser);  
    }
    
  • 令牌技术
    在这里插入图片描述

JWT:JSON Web Token
①登录成功后,生成令牌
②后续每个请求,都要携带JWT令牌,系统在每次请求处理之前,先校验令牌,通过后,再处理
在这里插入图片描述

```
<dependency>  <groupId>io.jsonwebtoken</groupId>  <artifactId>jjwt</artifactId>  <version>0.9.1</version>  
</dependency>
```
```
/**  * 测试jwt令牌生成  */  
@Test  
public void testJwt(){  Map<String, Object> claims = new HashMap<>();  claims.put("id",1);  claims.put("name","tom");  String jwt = Jwts.builder()  .signWith(SignatureAlgorithm.HS256, "ljytest")//签名算法  .setClaims(claims)//设置自定义内容(载荷)  .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))//设置有效期为1h  .compact();  System.out.println(jwt);  
}  /**  * 解析令牌  */  
@Test  
public void testParseJwt(){  Claims claims = Jwts.parser()  .setSigningKey("ljytest")//指定签名令牌  .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTcyMTUzOTU0NH0.tjJtAFRl_-BQSM0a2siMpYwUjxjRsZCSOIwhKA-hzYk")//解析令牌  .getBody();  System.out.println(claims);  
}
```

7.2 统一拦截

过滤器Filter
  • 快速入门
    定义:实现Filter接口
    配置:@WebFilter(urlPatterns="/*")
    @ServletComponentScan
    在这里插入图片描述

  • 详解
    在这里插入图片描述

  • Filter拦截路径
    在这里插入图片描述

  • 过滤器链
    在这里插入图片描述

    在这里插入图片描述

    @Slf4j  
    @WebFilter(urlPatterns = "/*")  
    public class LoginCheckFilter implements Filter {  @Override  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {  HttpServletRequest req = (HttpServletRequest) servletRequest;  HttpServletResponse resp = (HttpServletResponse) servletResponse;  // 1.获取请求url  String url = req.getRequestURI().toString();  log.info("请求的url",url);  // 2.判断请求url中是否包含login,如果包含,说明是登录操作,放行  if(url.contains("login")){  log.info("登录操作,放行...");  filterChain.doFilter(servletRequest,servletResponse);  return;        }  // 3.获取请求头中的令牌(token)  String jwt = req.getHeader("token");  // 4.判断令牌是否存在,如果不存在,返回错误结果(未登录)  if(!StringUtils.hasLength(jwt)){  log.info("请求头token为空,返回未登录的信息");  Result error = Result.error("NOT_LOGIN");  // 手动转换 对象——json  ————————>阿里巴巴fastJson  String notLogin = JSON.toJSONString(error);  // 将字符串响应给浏览器  resp.getWriter().write(notLogin);  return;        }  // 5.解析token,如果解析失败,返回错误结果(未登录)  try {  JwtUtils.parseJWT(jwt);  }catch (Exception e){  e.printStackTrace();  log.info("解析令牌失败,返回未登录的信息");  Result error = Result.error("NOT_LOGIN");  // 手动转换 对象——json  ————————>阿里巴巴fastJson  String notLogin = JSON.toJSONString(error);  // 将字符串响应给浏览器  resp.getWriter().write(notLogin);  return;        }  // 6.放行  log.info("令牌合法,放行");  filterChain.doFilter(servletRequest,servletResponse);  }  
    }
    
拦截器Intercepter

在这里插入图片描述

  • 快速入门
  1. 定义拦截器,实现HandlerInterceptor接口,并重写所有方法(Ctrl+O)
  2. 注册拦截器
    在这里插入图片描述
  • 详解
    在这里插入图片描述

    在这里插入图片描述

  • 登录校验
    LoginCheckInterceptor

    @Slf4j  
    @Component  
    public class LoginCheckInterceptor implements HandlerInterceptor {  @Override//目标资源方法(即controller)运行前运行,返回true,放行;返回false,不放行  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  String jwt = request.getHeader("token");  if(!StringUtils.hasLength(jwt)){  log.info("请求头token为空,返回未登录的信息");  Result error = Result.error("NOT_LOGIN");  String notLogin = JSON.toJSONString(error);  response.getWriter().write(notLogin);  return false;        }  try {  JwtUtils.parseJWT(jwt);  }catch (Exception e){  log.info("jwt解析失败,返回未登录的信息");  Result error = Result.error("NOT_LOGIN");  String notLogin = JSON.toJSONString(error);  response.getWriter().write(notLogin);  return false;        }  log.info("令牌合法,放行");  return true;    }  @Override//目标资源方法运行后运行  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {  System.out.println("postHandle...");  }  @Override//视图渲染完毕后运行,最后运行  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {  System.out.println("afterCompletion...");  }  
    }
    

    WebConfig

    @Configuration //配置类  
    public class WebConfig implements WebMvcConfigurer {  @Autowired  private LoginCheckInterceptor loginCheckInterceptor;  @Override  public void addInterceptors(InterceptorRegistry registry) {  registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");  }  
    }
    

7.3 异常处理

全局异常处理器

@RestControllerAdvice
@ExceptionHandler

@RestControllerAdvice  
public class GlobalExceptionHandler {  @ExceptionHandler(Exception.class) //捕获所有的异常  public Result ex(Exception e){  e.printStackTrace();  return Result.error("对不起,操作失败,请联系管理员");  }  
}

8. 事务管理&AOP

事务管理

Spring事务管理

在这里插入图片描述

#开启事务管理日志  
logging:  level:  org.springframework.jdbc.support.jdbcTransactionManager: debug
事务进阶
  • rollbackFor
    默认情况下,只有出现 RuntimeException 才回滚异常。rollbackFor属性用于控制出现何种异常类型,回滚事务

    @Transactional(rollbackFor = Exception.class)//设置所有异常都会进行事务回滚
    
  • propagation
    事务传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制。
    在这里插入图片描述

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override  
    public void insert(DeptLog deptLog) {  deptLogMapper.insert(deptLog);  
    }
    

AOP基础

AOP概述

Aspect oriented ProaramnId(面向切面编程、面向方面编程),其实就是面向特定方法编程

实现

动态代理是面向切面编程最主流的实现。而SpringAOP是Spring框架的高级技术,旨在管理bean对象的过程中,主要通过底层的动态代理机制,对特定的方法进行编程。

  • 导入依赖:在pom.xml中导入AOP的依赖
    <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-aop</artifactId>  
    </dependency>
    
  • 编写AOP程序:针对于特定方法根据业务需要进行编程
    @Slf4j  
    @Component  
    @Aspect  
    public class TimeAspect {  @Around("execution(* com.ljytest.projectest.service.impl.*.*(..))") // 第一个*是方法的返回,第二个*是类名,第三个*是方法名  public Object recordTime(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {  // 记录开始时间  long begin = System.currentTimeMillis();  // 调用原始方法  Object result = proceedingJoinPoint.proceed();  // 记录结束时间,计算方法执行耗时  long end = System.currentTimeMillis();  log.info(proceedingJoinPoint.getSignature()+"方法执行耗时:{}ms",end-begin);  return result;  }  
    }
    
AOP核心概念

在这里插入图片描述

AOP进阶

1.通知类型

在这里插入图片描述

  • PointCut
    将公共的切点表达式抽取出来,需要用到时引用该切点表达式即可
    @Pointcut("execution(* com.ljytest.projectest.service.impl.DeptServiceImpl.*(..))")  
    private void pt(){}
    
    在这里插入图片描述
2.通知顺序

在这里插入图片描述

3.切入点表达式
  • execution(…):根据方法的签名来匹配,主要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配

    execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数) throws 异常?)
    
    • 其中带 ? 的表示可以省略的部分
      访问修饰符:可省略(比如: public、protected)
      包名.类名: 可省略
      throws 异常:可省略(注意是方法上声明抛出的异常,不是实际抛出的异常)
    • 使用通配符描述切入点
      在这里插入图片描述
  • @annotation(…):根据注解匹配
    com.ljytest.projectest.aop.MyLog

    @Retention(RetentionPolicy.RUNTIME) //指定什么时候生效  
    @Target(ElementType.METHOD)//作用在哪些地方  
    public @interface MyLog {  }
    

    DeptServiceImpl

    @MyLog //自定义注解  
    public List<Dept> findAll(){  return deptMapper.findAll();  
    }
    
    @Pointcut("@annotation(MyLog)")  
    private void pt1(){}  
    @Before("pt1()")  
    public void before1(){  log.info("before1..");  
    }
    
4.连接点

在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。

  • 对于 @Around 通知,获取连接点信息只能使用 ProceedingJoinPoint
  • 对于其他四种通知,获取连接点信息只能使用 JoinPoint ,它是 ProceedingJoinPoint 的父类型
    在这里插入图片描述

在这里插入图片描述

9. Springboot原理

9.1 配置优先级

  • application.properties>yml>yaml

  • SpringBoot 除了支持配置文件属性配置,还支持Java系统属性和命令行参数的方式进行属性配置
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

  • 优先级(从低到高)
    在这里插入图片描述

9.2 Bean管理

获取bean

默认情况下,Spring项目启动时,会把bean都创建好放在IOC容器中,如果想要主动获取这些bean,可以通过如下方式:

// 根据bean的名称获取  
DeptController bean1 = (DeptController) applicationContext.getBean("deptController");  
System.out.println(bean1);  
// 根据bean的类型获取  
DeptController bean2 = applicationContext.getBean(DeptController.class);  
System.out.println(bean2);  
// 根据bean的名称和类型获取  
DeptController bean3 = applicationContext.getBean("deptController", DeptController.class);  
System.out.println(bean3);

在这里插入图片描述

bean作用域

Spring支持五种作用域,后三种在web环境才生效:
在这里插入图片描述

@Scope("prototype")

在这里插入图片描述

第三方bean

如果要管理的bean对象来自于第三方(不是自定义的),是无法用 @Component 及衍生注解声明bean的,就需要用到 @Bean注解

@Configuration //配置类  
public class CommonConfig {  //声明第三方bean  @Bean //将当前方法的返回值对象交给IOC容器管理, 成为IOC容器bean  //通过@Bean注解的name/value属性指定bean名称, 如果未指定, 默认是方法名  public SAXReader reader(DeptService deptService){  System.out.println(deptService);  return new SAXReader();  }  
}

在这里插入图片描述

9.3 SpringBoot原理

起步依赖 自动配置

起步依赖原理

依赖传递

自动配置原理

SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作。

  • 第三方依赖自动配置
    在这里插入图片描述
    在这里插入图片描述

    ImportSelector接口类

    public class MyImportSelector implements ImportSelector {  public String[] selectImports(AnnotationMetadata importingClassMetadata) {  return new String[]{"com.example.HeaderConfig"};  }  
    }
    
  • 源码跟踪

    • @SpringBootApplication
      在这里插入图片描述

    • @Conditional
      在这里插入图片描述

  • 自定义starter
    在实际开发中,经常会定义一些公共组件,提供给各个项目团队使用。而在SpringBoot的项目中,一般会将这些公共组件封装为SpringBoot 的 starter

    • 规范
      SpringBoot官方:spring-boot-starter-XXX
      其他技术提供:XXX-spring-boot-starter
      在这里插入图片描述
      在这里插入图片描述
Web后端开发-总结

在这里插入图片描述

在这里插入图片描述

10. Maven高级

10.1 分模块设计与开发

将项目按照功能拆分成若干个子模块,方便项目的管理维护、扩展,也方便模块间的相互调用,资源共享
在这里插入图片描述

10.2 继承与聚合

继承

继承描述的是两个工程间的关系,与java中的继承相似,子工程可以继承父工程中的配置信息

<parent> … </parent>
  • 继承关系实现
    在这里插入图片描述
    在这里插入图片描述

projectest-parent

<parent>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-parent</artifactId>  <version>3.3.1</version>  <relativePath/> <!-- lookup parent from repository -->  
</parent><groupId>org.ljytest</groupId>  
<artifactId>projectest-parent</artifactId>  
<version>1.0-SNAPSHOT</version>  
<packaging>pom</packaging>

其他

<parent>  <groupId>org.ljytest</groupId>  <artifactId>projectest-parent</artifactId>  <version>1.0-SNAPSHOT</version>  <relativePath>../projectest-parent/pom.xml</relativePath>  
</parent>

在这里插入图片描述

  • 版本锁定
    在maven中,可以在父工程的pom文件中通过 <dependencyManagement> 来统一管理依赖版本。
    子工程需要引入依赖,无需指定 <version> 版本号,父工程统一管理。变更依赖版本,只需在父工程中统一变更。
  • 自定义属性/引用属性
    <properties>  <lombok.version>RELEASE</lombok.version>  <jjwt.version>0.9.1</jjwt.version>  
    </properties>
    
    <dependency>  <groupId>org.projectlombok</groupId>  <artifactId>lombok</artifactId>  <version>${lombok.version}</version>
    
聚合
  • 聚合:将多个模块组织成一个整体,同时进行项目的构建
  • 聚合工程:一个不具有业务功能的“空”工程(有且仅有一个pom文件)
  • 作用:快速构建项目(无需根据依赖关系手动构建,直接在聚合工程上构建即可)
  • maven中可以通过 <modules> 设置当前聚合工程所包含的子模块名称
    <!-- 聚合其他模块-->  
    <modules>  <module>../projectest-pojo</module>  <module>../projectest-utils</module>  <module>../projectest-web-management</module>  
    </modules>
    

在这里插入图片描述

10.3 私服

介绍

私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的中央仓库,用于解决团队内部的资源共享与资源同步问题。
依赖查找顺序:本地仓库–>私服–>中央仓库

资源上传与下载

在这里插入图片描述

  • 1.设置私服的访问用户名/密码(settings.xml中的servers中配置)
    <server>  <id>maven-releases</id>  <username>admin</username>  <password>admin</password>  
    </server>  
    <server>  <id>maven-snapshots</id>  <username>admin</username>  <password>admin</password>  
    </server>
    
  • 2.IDEA的maven工程的pom文件中配置上传(发布)地址
    <distributionManagement>  <repository>  <id>maven-releases</id>  <url>http://192.168.150.101:8081/repository/maven-releases/</url>  </repository>  <snapshotRepository>  <id>maven-snapshots</id>  <url>http://192.168.150.101:8081/repository/maven-snapshots/</url>  </snapshotRepository>  
    </distributionManagement>
    
  • 3.设置私服依赖下载的仓库组地址(settings.xml中的mirrors、profiles中配置)
    <mirror>  <id>maven-public</id>  <mirrorOf>*</mirrorOf>  <url>http://192.168.150.101:8081/repository/maven-public/</url>  
    </mirror>
    
    <profile>  <id>allow-snapshots</id>  <activation>  <activeByDefault>true</activeByDefault>  </activation>  <repositories>  <repository>  <id>maven-public</id>  <url>http://192.168.150.101:8081/repository/maven-public/</url>  <releases>  <enabled>true</enabled>  </releases>  <snapshots>  <enabled>true</enabled>  </snapshots>  </repository>  </repositories>  
    </profile>
    

mybatis-plus 瑞吉外卖 springCloud微服务技术栈 学成在线
在这里插入图片描述


http://www.mrgr.cn/news/30973.html

相关文章:

  • 开源模型应用落地-qwen模型小试-Qwen2.5-7B-Instruct-快速体验(十三)
  • 多模态文档理解:一文读懂mPLUG-DocOwl系列模型
  • 在基准测试和规划测试中选Flat还是Ramp-up?
  • 图像亮度均衡算法
  • 第二证券:“产业+科技” 中国并购重组市场持续升温
  • 非标工业模型评审不再难,3D一览通助力高效协同
  • 設置Android設備全局代理
  • Django SQL注入-漏洞分析
  • GitLab将会持续支持FluxCD
  • 准备招银社招记录
  • 【Elasticsearch系列十五】强大特性
  • 做完自动化测试,但别让不会汇报毁了你!
  • java--面向对象编程(中级部分)
  • Eclipse如何调整编辑器中的字体大小?
  • 让医院更智慧,让决策更容易
  • 代码随想录训练营第20天|235. 二叉搜索树的最近公共祖先、 701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点
  • 欧拉筛素数板子
  • 硬盘数据恢复必备:4 款强大硬盘数据恢复软件推荐!
  • [ComfyUI]Flux:更强融图!阿里最新重绘CN模型,生态加速器
  • OpenCV_图像像素读写操作