JavaWeb

JavaWeb最新

HTML和CSS

介绍

  • HTML(HyperText Markup Language):超文本标记语言

    • 超文本:超越了文本的限制,比普通文本更强大。除了文字信息,还可以定义图片、音频、视频等内容。
    • 标记语言:由标签构成的语言
      • HTML标签都是预定义好的。例如:使用<a>展示超链接,使用<img>展示图片,<video>展示视频。
      • HTML代码直接在浏览器中运行,HTML标签由浏览器解析
  • CSS(Cascading Style Sheet):层叠样式表,用于控制页面的样式(表现)。

  • 颜色表示形式

表示方式 表示含义 取值
关键字 预定义的颜色名 red、green、blue…
rgb表示法 红绿蓝三原色,每项取值范围:0-255 rbg(0,0,0)、rbg(255,255,255)、rbg(255,0,0)
十六进制表示法 #开头,将数字转换成十六进制表示 #000000、#ff0000、#cccccc,简写:#000、#ccc

排版一

  1. 标题标签
  • 标签:<h1>…</h1>
  • 注意:HTML标签都是预定义好的,不能自己随意定义
  1. 水平线标签 <hr>
  2. 图片标签 <img src=“…” width=“…” height=“…”>
  • 绝对路径:绝对磁盘路径
  • 相对路径:从当前文件开始查找

样式一

  1. CSS引入方式
  • 行内样式:<h1 style=“…”>
  • 内嵌样式:<style>…</style>
  • 外联样式:xxx.css <link href=“…”>
  1. 颜色表示
  • 关键字:red、green…
  • rgb表示法:rbg(255,0,0)、rbg(134,100,89)
  • 十六进制:#ff0000、#cccccc、#ccc
  1. 颜色属性
  • color:设置文本内容的颜色

样式二

  1. <span>标签
  • <span>是一个在开发网页时大量会用到的没有语义的布局标签
  • 特点:一行可以显示多个(组合行内元素),宽度和高度默认由内容展开
  1. CSS选择器
  • 元素选择器:标签名 {…}
  • id选择器:#id属性值 {…}
  • 类选择器:.class属性值 {…}
  • 优先级:id选择器 > 类选择器 > 元素选择器
  1. CSS属性
  • color:设置文本的颜色
  • font-size:字体大小(注意:记得加px)

超链接

  1. 超链接
1
2
3
4
5
6
标签: <a>
属性:
href: 指定资源访问的url
target: 指定在何处打开资源链接
_self: 默认值,在当前页面打开
_blank: 在空白页面打开
  1. CSS属性
1
2
text-decoration: 规定添加到文本的修饰,none表示定义标准的文本
color: 定义文本的颜色

排版二

  1. 音频、视频标签
1
<audio> <video>
  1. 换行、段落标签
1
换行: <br> ; 段落: <p>
  1. 文本加粗标签
1
<b> <strong>
  1. CSS样式
1
2
3
ling-height: 设置行高
text-indent:定义第一个行内容的缩进
text-align: 规定元素中的文本的水平对齐方式
  1. 注意
1
在HTML中无论输入多少个空格,只会显示一个。可以使用空格占位符: &nbsp;

页面布局

  • 盒子:页面中所有的元素(标签),都可以看作是一个盒子,由盒子将页面中的元素包含在一个矩形区域内,通过盒子的视角更方便的进行页面布局
  • 盒子模型组成:内容区域(content)内边距区域(padding)边框区域(border)外边距区域(margin)
  1. CSS盒子模型
1
组成: 内容(content)、内边距(padding)、边框(border)、外边框(margin)
  1. CSS属性
1
2
3
4
5
6
7
width: 设置宽度
height: 设置高度
border: 设置边框的属性,如:1px solid #000;
padding: 内边距
margin: 外边距

如果只需要设置某一个方位的边框、内边距、外边距,可以在属性名后加上 -位置,如:padding-top、padding-left、padding-right...

表格标签

  • 场景:在网页中以表格(行、列)形式整齐展示数据,如:班级表
  • 标签:
标签 描述 属性/备注
<table> 定义表格整体,可以包裹多个 <tr> border:规定表格边框的宽度 width:规定表格的宽度 cellspacing:规定单元之间的空间
<tr> 表格的行,可以包裹多个 <td>
<td> 表格单元格(普通),可以包裹内容 如果是表头单元格,可以替换为 <th>

表单标签

  • 场景:在网页中主要负责数据采集功能,如:注册、登录的表单。

  • 标签: <form>

  • 表单项标签: 不同类型的input元素、下拉列表、文本域等。

    • <input>: 定义表单项,通过type属性控制输入形式
    • <select>: 定义下拉列表
    • <textarea>: 定义文本域
  • 属性:

    • action: 规定表单提交时,向何处发送表单数据,表单提交的URL。
    • method: 规定用于发送表单数据的方式,常见为: GET、POST。
      • GET:表单数据是拼接在url后面的,?username=java,url中能携带的表单数据大小是有限制的。
      • POST: 表单数据是在请求体(消息体)中携带的,大小没有限制。

表单项

  • <input>:表单项,通过type属性控制输入形式
type取值 描述
text 默认值,定义单行的输入字段
password 定义密码字段
radio 定义单选按钮
checkbox 定义复选框
file 定义文件上传按钮
date/time/datetime-local 定义日期/时间/日期时间
number 定义数字输入框
email 定义邮件输入框
hidden 定义隐藏域
submit / reset / button 定义提交按钮 / 重置按钮 / 可点击按钮
  • <select>:定义下拉列表,<option>:定义列表项
  • <textarea>:文本域
HTML-表单项标签
姓名:

密码:

性别:

爱好:

图像:

生日:

时间:

日期时间:

邮箱:

年龄:

学历:

描述:

1
2
3
4
5
6
7
8
9
10
 <!-- 表单常见按钮 -->
<input type="button" value="按钮">
<input type="reset" value="重置">
<input type="submit" value="提交">
<br>

</form>

</body>
</html>

JavaScript

介绍

  • JavaScript是一门跨平台、面向对象的脚本语言。是用来控制网页行为的,它能使网页可交互

引入方式

  • 内部脚本:将JS代码定义在HTML页面中
    • JavaScript代码必须位于<script></script>标签之间
    • 在HTML文档中,可以在任何地方,放置任意数量的<script>
    • 一般会把脚本置于<body>元素的底部,可改善显示速度
1
2
3
<script>
alert("Hello JavaScript")
</script>
  • 外部脚本:将JS代码定义在外部JS文件中,然后引入到HTML页面中

    • 外部JS文件,只包含JS代码,不包含<script>标签
    • <script>标签不能自闭合

语法

输出语句

  • 使用**window.alert()**写入警告框
  • 使用**document.write()**写入HTML输出
  • 使用**console.log()**写入浏览器控制台
1
2
3
4
5
6
7
<script>
window.alert(""); //浏览器弹出警告框

document.write(""); //写入HTML,在浏览器展示

console.log(""); //写入浏览器控制台
</script>

变量

关键字 解释
var 早期ECMAScript5中用于变量声明的关键字
let ECMAScript6中新增的用于变量声明的关键字,相比较var,let只在代码块内生效
const 声明常量的,常量一旦声明,不能修改
  • JavaScript 是一门弱类型语言,变量可以存放不同类型的值
  • 变量名需要遵循如下规则:
    • 组成字符可以是任何字母、数字、下划线(_)或美元符号($)
    • 数字不能开头
    • 建议使用驼峰命名

数据类型

数据类型 描述
number 数字(整数、小数、NaN(Not a Number))
string 字符串,单双引皆可
boolean 布尔。true,false
null 对象为空
undefined 当声明的变量未初始化时,该变量的默认值是 undefined

运算符

运算规则 运算符
算术运算符 + , - , * , / , % , ++ , –
赋值运算符 = , += , -= , *= , /= , %=
比较运算符 > , < , >= , <= , != , == , === 注意 == 会进行类型转换,=== 不会进行类型转换
逻辑运算符 && , || , !
三元运算符 条件表达式 ? true_value: false_value

函数

1
2
3
function 函数名(参数1,参数2..){
//要执行的代码
}
  • 形式参数不需要声明类型,并且JavaScript中不管什么类型都是let或者var去声明,加上也没有意义。
  • 返回值也不需要声明类型,直接return即可

对象

Array数组

  • 定义
1
var 变量名 = new Array(元素列表);
1
var 变量名 = [元素列表] ;
  • 访问
1
arr[索引] = 值;
  • 属性
属性 描述
length 设置或返回数组中元素的数量。
  • 方法
方法方法 描述
forEach() 遍历数组中的每个有值得元素,并调用一次传入的函数
push() 将新元素添加到数组的末尾,并返回新的长度
splice() 从数组中删除元素

String字符串

  • String对象的创建方式有2种
1
var 变量名 = new String("…") ; //方式一
1
var 变量名 = "…" ; //方式二
  • 属性
属性 描述
length 字符串的长度
  • 方法
方法 描述
charAt() 返回在指定位置的字符
indexOf() 检索字符串
trim() 去除字符串两边的空格
substring() 提取字符串中两个指定的索引号之间的字符

JSON

  • 定义格式
1
2
3
4
5
6
var 对象名 = {
属性名1: 属性值1,
属性名2: 属性值2,
属性名3: 属性值3,
函数名称: function(形参列表){}
};
  • 调用格式
1
2
对象名.属性名();
对象名.函数名();
  • JSON对象:JavaScript Object Notation,JavaScript对象标记法。是通过JavaScript标记法书写的文本
1
2
3
4
5
{
"key":value,
"key":value,
"key":value
};

BOM

  • Browser Object Model 浏览器对象模型,允许JavaScript与浏览器对话,JavaScript将浏览器的各个组成部分封装为对象
对象名称 描述
Window 浏览器窗口对象
Navigator 浏览器对象
Screen 屏幕对象
History 历史记录对象
Location d地址栏对象
Windows对象
  • 属性
属性 描述
history 用于获取history对象
location 用于获取location对象
Navigator 用于获取Navigator对象
Screen 用于获取Screen对象
  • 方法
函数 描述
alert() 显示带有一段消息和一个确认按钮的警告框
comfirm() 显示带有一段消息以及确认按钮和取消按钮的对话框
setInterval() 按照指定的周期(以毫秒计)来调用函数或计算表达式
setTimeout() 在指定的毫秒数后调用函数或计算表达式
Location对象
1
2
3
4
//获取浏览器地址栏信息
alert(location.href);
//设置浏览器地址栏信息
location.href = "https://www.itcast.cn";

DOM

  • Document Object Model 文档对象模型

  • 将标记语言的各个组成部分封装为对应的对象

    • Document:整个文档对象
    • Element:元素对象
    • Attribute:属性对象
    • Text:文本对象
    • Comment:注释对象
  • JavaScript通过DOM,能对HTML进行操作

    • 改变 HTML 元素的内容
    • 改变 HTML 元素的样式(CSS)
    • 对 HTML DOM 事件作出反应
    • 添加和删除 HTML 元素
获取DOM对象
函数 描述
document.getElementById() 根据id属性值获取,返回单个Element对象
document.getElementsByTagName() 根据标签名称获取,返回Element对象数组
document.getElementsByName() 根据name属性值获取,返回Element对象数组
document.getElementsByClassName() 根据class属性值获取,返回Element对象数组

事件

  • 事件:HTML事件是发生在HTML元素上的“事情”
    • 按钮被点击
    • 鼠标移动到元素上
    • 按下键盘按键
  • 事件监听:JavaScript可以在事件被侦测到时执行代码
事件绑定
  • 通过HTML标签中的事件属性进行绑定
1
2
3
4
5
6
7
<input type="button" onclick="on()" value="按钮1" >

<script>
function on(){
alert('我被点击了!');
}
</script>
  • 通过DOM元素属性绑定
1
2
3
4
5
6
7
<input type="button" id="btn" value="按钮2" >

<script>
document.getElementBuId('btn').onclick=function(){
alert('我被点击了!');
}
</script>
常见事件
事件属性名 说明
onclick 鼠标单击事件
onblur 元素失去焦点
onfocus 元素获得焦点
onload 某个页面或图像被完成加载
onsubmit 当表单提交时触发该事件
onmouseover 鼠标被移到某元素之上
onmouseout 鼠标从某元素移开

Vue

概述

  • Vue是一套前端框架,免除原生JavaScript中的DOM操作,简化书写

  • 基于MVVM(Model View ViewModel)思想,实现数据的双向绑定

  • 官网

常用指令

  • **指令:**HTML 标签上带有 v- 前缀的特殊属性,不同指令具有不同含义。例如:v-if,v-for…
指令 作用
v-bind 为HTML标签绑定属性值,如设置 href , css样式等
v-model 在表单元素上创建双向数据绑定
v-on 为HTML标签绑定事件
v-if 条件性的渲染某元素,判定为true时渲染,否则不渲染
v-else 同上
v-else-if 同上
v-show 根据条件展示某元素,区别在于切换的是display属性的值
v-for 列表渲染,遍历容器的元素或者对象的属性

生命周期

  • vue的生命周期:指的是vue对象从创建到销毁的过程
  • vue的生命周期包含8个阶段:每触发一个生命周期事件,会自动执行一个生命周期方法
状态 阶段周期
beforeCreate 创建前
created 创建后
beforeMount 挂载前
mounted 挂载完成
beforeUpdate 更新前
updated 更新后
beforeDestroy 销毁前
destroyed 销毁后
  • mounted:挂在完成,Vue初始化成功,HTML页面渲染成功。(发送请求到服务端,加载数据)

Ajax

介绍

  • Asynchronous JavaScript And XML,异步的JavaScript和XML
  • 作用
    • 数据交换:通过Ajax可以给服务器发送请求,并获取服务器响应的数据
    • 异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如搜索联想、用户名是否可用的校验等

Axios

  • Axios对原生的Ajax进行了封装,简化书写,快速开发
  • 官网

前后端分离

YApi

  • YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。

  • 官网

YApi主要提供了2个功能:

  • API接口管理:根据需求撰写接口,包括接口的地址,参数,响应等等信息
  • Mock服务:模拟真实接口,生成接口的模拟测试数据,用于前端的测试

前端工程化

前端工程化方式的开发,主要包括如下4个特点

  • 模块化:将js和css等,做成一个个可复用模块
  • 组件化:我们将UI组件,css样式,js行为封装成一个个的组件,便于管理
  • 规范化:我们提供一套标准的规范的目录接口和编码规范,所有开发人员遵循这套规范
  • 自动化:项目的构建,测试,部署全部都是自动完成

Element

  • 组件:组成网页的部件,例如超链接、按钮、图片、表格、表单等

  • 官网

  • 安装ElementUI组件库

1
npm install element-ui@2.15.3 
  • 引入ElementUI组件库
1
2
3
4
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI);
  • 访问官网,复制组件代码

Vue路由

  • Vue Router是Vue的官方路由
  • 组成:
    • VueRouter:路由器类,根据路由请求在路由视图中动态渲染选中的组件
    • <router-link>:请求链接组件,浏览器会解析成<a>
    • <router-view>:动态视图组件,渲染展示与路由路径对应的组件

打包部署

Nginx

  • Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少,并发能力强,在各大型互联网公司都有非常广泛的使用

  • 官网

  • 部署:将打包好的dist目录下的文件,复制到nginx安装目录的html目录下

  • 注意:如果80端口被占用,需要通过conf/nginx.conf配置文件来修改端口号

Maven

介绍

  • Maven是Apache旗下的一个开源项目,是一款用于管理和构建java项目的工具
  • 官网

依赖传递

  • 排除依赖:主动断开依赖的资源,被排除的资源无需指定版本

依赖范围

  • 可以通过<scope>标签设置其作用范围

  • 作用范围:

  1. 主程序范围有效(main文件夹范围内)

  2. 测试程序范围有效(test文件夹范围内)

  3. 是否参与打包运行(package指令范围内)

scope 主程序 测试程序 打包(运行) 范例
compile(默认) Y Y Y log4j
test - Y - junit
provided Y Y - servlet-api
runtime - Y Y jdbc驱动

生命周期

  • Maven的生命周期就是为了对所有的构建过程进行抽象和统一
  • Maven中有3套相互独立的生命周期
    • clean:清理工作

    • default:核心工作。如:编译、测试、打包、安装、部署等

    • site:生成报告、发布站点等

Web

Spring

  • Spring发展到今天已经形成了一种开发生态圈,Spring提供了若干个子项目,每个项目用于完成特定的功能
  • 官网

HTTP

  • 概念:Hyper Text Transfer Protocol(超文本传输协议),规定了浏览器与服务器之间数据传输的规则
  • 特点:
  1. **基于TCP协议: ** 面向连接,安全

    TCP是一种面向连接的(建立连接之前是需要经过三次握手)、可靠的、基于字节流的传输层通信协议,在数据传输方面更安全

  2. 基于请求-响应模型: 一次请求对应一次响应(先请求后响应)

    请求和响应是一一对应关系,没有请求,就没有响应

  3. HTTP协议是无状态协议: 对于数据没有记忆能力。每次请求-响应都是独立的

    无状态指的是客户端发送HTTP请求给服务端之后,服务端根据请求响应数据,响应完后,不会记录任何信息。

    • 缺点: 多次请求间不能共享数据
    • 优点: 速度快

HTTP协议

HTTP协议又分为:请求协议和响应协议

  • 请求协议:浏览器将数据以请求格式发送到服务器
    • 包括:请求行请求头请求体
  • 响应协议:服务器将数据以响应格式返回给浏览器
    • 包括:响应行响应头响应体
请求方式 请求说明
GET 获取资源。向特定的资源发出请求
POST 传输实体主体。向指定资源提交数据进行处理请求(例:上传文件),数据被包含在请求体中。
OPTIONS 返回服务器针对特定资源所支持的HTTP请求方式。因为并不是所有的服务器都支持规定的方法,为了安全有些服务器可能会禁止掉一些方法,例如:DELETE、PUT等。那么OPTIONS就是用来询问服务器支持的方法。
HEAD 获得报文首部。HEAD方法类似GET方法,但是不同的是HEAD方法不要求返回数据。通常用于确认URI的有效性及资源更新时间等。
PUT 传输文件。PUT方法用来传输文件。类似FTP协议,文件内容包含在请求报文的实体中,然后请求保存到URL指定的服务器位置。
DELETE 删除文件。请求服务器删除Request-URI所标识的资源
TRACE 追踪路径。回显服务器收到的请求,主要用于测试或诊断
CONNECT 要求用隧道协议连接代理。HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
区别方式 GET请求 POST请求
请求参数 请求参数在请求行中 请求参数在请求体中
请求参数长度 请求参数长度有限制(浏览器不同限制也不同) 请求参数长度没有限制
安全性 安全性低。原因:请求参数暴露在浏览器地址栏中 安全性相对高

响应状态码

状态码分类 说明
1xx 响应中 — 临时状态码。表示请求已经接受,告诉客户端应该继续请求或者如果已经完成则忽略
2xx 成功 — 表示请求已经被成功接收,处理已完成
3xx 重定向 — 重定向到其它地方,让客户端再发起一个请求以完成整个处理
4xx 客户端错误 — 处理发生错误,责任在客户端,如:客户端的请求一个不存在的资源,客户端未被授权,禁止访问等
5xx 服务器端错误 — 处理发生错误,责任在服务端,如:服务端抛出异常,路由出错,HTTP版本不支持等
  • 200 ok 客户端请求成功
  • 404 Not Found 请求资源不存在
  • 500 Internal Server Error 服务端发生不可预期的错误

Tomcat

  • Tomcat服务器软件是一个免费的开源的web应用服务器。支持Servlet/JSP少量JavaEE规范
  • 官网

请求响应

  1. 原始方式获取请求参数
  • Controller方法形参中声明HttpServletRequest对象
  • 调用对象的getParameter(参数名)
  1. SpringBoot中接收简单参数
  • 请求参数名与方法形参变量名相同
  • 自动进行类型转换
  1. @RequestParam注解
  • 方法形参名称与请求参数名称不匹配,通过该注解完成映射
  • 该注解的required属性默认是true,代表请求参数必须传递

请求

  1. 简单参数
  • 定义方法形参,请求参数名与形参变量名一致
  • 如果不一致,通过@RequestParam手动映射
  1. 实体参数
  • 请求参数名,与实体对象的属性名一致,会自动接收封装
  1. 数组集合参数
  • 数组:请求参数名与数组名一致,直接封装
  • 集合:请求参数名与集合名一致,@RequestParam绑定关系
  1. 日期参数
  • @DataTimeFormat
  1. JSON参数
  • @RequestBody
  1. 路径参数
  • @PathVariable

响应

  1. @ResponseBody
1
2
位置:Controller类上/方法上
作用:将方法返回值直接响应,若返回值类型是实体对象/集合,转JSON格式响应
  1. 统一响应结果
1
Result(codemsgdata)

分层解耦

三层架构

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

IOC-DL

  • 控制反转:Inversion Of Control,简称IOC。对象的创建控制权有程序自身转移到外部(容器),这种思想称为控制反转
  • 依赖注入:Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入
  • Bean对象:IOC容器中创建、管理的对象,称之为bean

Bean的声明

  • 要把某个对象交给IOC容器管理,需要在对应的类上加上如下注解之一
注解 说明 位置
@Controller @Component的衍生注解 标注在控制器类上
@Service @Component的衍生注解 标注在业务类上
@Repository @Component的衍生注解 标注在数据访问类上(由于与mybatis整合,用的少)
@Component 声明bean的基础注解 不属于以上三类时,用此注解

注意事项:

  • 声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为类名首字母小写
  • 使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能用@Controller

依赖注入的注解

  • @Autowired:默认按照类型自动装配
  • 如果同类型的bean存在多个
    • @Primary
    • @Autowired + @Qualifier(“bean的名称”)
    • @Resource(name = “bean的名称”)

@Resouce与@Autowired区别

  • @Autowired是spring框架提供的注解,而@Resource是JDK提供的注解
  • @Autowired默认按照类型注入,而@Resource默认按照名称注入

MySQL

概述

  • 数据库:DataBase(DB),是存储和管理数据的仓库
  • 数据库管理系统:DataBase Management System(DBMS),操纵和管理数据库的大型软件
  • SQL:Structured Query Lanaguage,操作关系型数据库的编程语言,定义了一套操作关系型数据库统一标准
1
mysql -u用户名 -p密码 [-h数据库服务器的IP地址 -P端口号]

分类

  • SQL语句通常被分为四大类
分类 全称 说明
DDL Data Definition Language 数据定义语言,用来定义数据库对象(数据库,表,字段)
DML Data Manipulation Language 数据操作语言,用来对数据库表中的数据进行增删改
DQL Data Query Language 数据查询语言,用来查询数据库中表的记录
DCL Data Control Language 数据控制语言,用来创建数据库用户、控制数据库的访问权限

DDL

数据库操作

  1. 查询
  • 查询所有数据库:show databases;
  • 查询当前数据库:select databases;
  1. 使用
  • 使用数据库:use 数据库名;
  1. 创建
  • 创建数据库:create database[if not exists] 数据库名;
  1. 删除
  • 删除数据库:drop database[if exists] 数据库名;

表操作

  • 表结构
1
2
3
4
5
6
create table  表名(
字段1 字段1类型 [约束] [comment 字段1注释 ],
字段2 字段2类型 [约束] [comment 字段2注释 ],
......
字段n 字段n类型 [约束] [comment 字段n注释 ]
) [ comment 表注释 ] ;
约束 描述 关键字
非空约束 限制该字段值不能为null not null
唯一约束 保证字段的所有数据都是唯一、不重复的 unique
主键约束 主键是一行数据的唯一标识,要求非空且唯一 primary key
默认约束 保存数据时,如果未指定该字段值,则采用默认值 default
外键约束 让两张表的数据建立连接,保证数据的一致性和完整性 foreign key
数据类型
类型 大小 有符号(SIGNED)范围 无符号(UNSIGNED)范围 描述
TINYINT 1byte (-128,127) (0,255) 小整数值
SMALLINT 2bytes (-32768,32767) (0,65535) 大整数值
MEDIUMINT 3bytes (-8388608,8388607) (0,16777215) 大整数值
INT/INTEGER 4bytes (-2147483648,2147483647) (0,4294967295) 大整数值
BIGINT 8bytes (-2^63,2^63-1) (0,2^64-1) 极大整数值
FLOAT 4bytes (-3.402823466 E+38,3.402823466351 E+38) 0 和 (1.175494351 E-38,3.402823466 E+38) 单精度浮点数值
DOUBLE 8bytes (-1.7976931348623157 E+308,1.7976931348623157 E+308) 0 和 (2.2250738585072014 E-308,1.7976931348623157 E+308) 双精度浮点数值
DECIMAL 依赖于M(精度)和D(标度)的值 依赖于M(精度)和D(标度)的值
字符串类型
类型 大小 描述
CHAR 0-255 bytes 定长字符串(需要指定长度)
VARCHAR 0-65535 bytes 变长字符串(需要指定长度)
TINYBLOB 0-255 bytes 不超过255个字符的二进制数据
TINYTEXT 0-255 bytes 短文本字符串
BLOB 0-65 535 bytes 二进制形式的长文本数据
TEXT 0-65 535 bytes 长文本数据
MEDIUMBLOB 0-16 777 215 bytes 二进制形式的中等长度文本数据
MEDIUMTEXT 0-16 777 215 bytes 中等长度文本数据
LONGBLOB 0-4 294 967 295 bytes 二进制形式的极大文本数据
LONGTEXT 0-4 294 967 295 bytes 极大文本数据
日期时间类型
类型 大小 范围 格式 描述
DATE 3 1000-01-01 至 9999-12-31 YYYY-MM-DD 日期值
TIME 3 -838:59:59 至 838:59:59 HH:MM:SS 时间值或持续时间
YEAR 1 1901 至 2155 YYYY 年份值
DATETIME 8 1000-01-01 00:00:00 至 9999-12-31 23:59:59 YYYY-MM-DD HH:MM:SS 混合日期和时间值
TIMESTAMP 4 1970-01-01 00:00:01 至 2038-01-19 03:14:07 YYYY-MM-DD HH:MM:SS 混合日期和时间值,时间戳

DML

添加

  • 向指定字段添加数据

    1
    insert into 表名 (字段名1, 字段名2) values (值1, 值2);
  • 全部字段添加数据

    1
    insert into 表名 values (值1, 值2, ...);
  • 批量添加数据(指定字段)

    1
    insert into 表名 (字段名1, 字段名2) values (值1, 值2), (值1, 值2);
  • 批量添加数据(全部字段)

    1
    insert into 表名 values (值1, 值2, ...), (值1, 值2, ...);
  • Insert操作的注意事项:

  1. 插入数据时,指定的字段顺序需要与值的顺序是一一对应的

  2. 字符串和日期型数据应该包含在引号中

  3. 插入的数据大小,应该在字段的规定范围内

修改

1
update 表名 set 字段名1 =1 , 字段名2 =2 , .... [where 条件] ;

删除

1
delete from 表名  [where  条件] ;
  • 注意事项:
  1. DELETE 语句的条件可以有,也可以没有,如果没有条件,则会删除整张表的所有数据
  2. DELETE 语句不能删除某一个字段的值(可以使用UPDATE,将该字段值置为NULL即可
  3. 当进行删除全部数据操作时,会提示询问是否确认删除所有数据,直接点击Execute即可

DQL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT
字段列表
FROM
表名列表
WHERE
条件列表
GROUP BY
分组字段列表
HAVING
分组后条件列表
ORDER BY
排序字段列表
LIMIT
分页参数

基本查询

  • 查询多个字段

    1
    select 字段1, 字段2, 字段3 from  表名;
  • 查询所有字段(通配符)

    1
    select *  from  表名;
  • 设置别名

    1
    select 字段1 [ as 别名1 ] , 字段2 [ as 别名2 ]  from  表名;
  • 去除重复记录

    1
    select distinct 字段列表 from  表名;

条件查询

1
select 字段列表 from 表名 where 条件列表 ; -- 条件列表:意味着可以有多个条件
比较运算符 功能
> 大于
>= 大于等于
< 小于
<= 小于等于
= 等于
<> 或 != 不等于
between … and … 在某个范围之内(含最小、最大值)
in(…) 在in之后的列表中的值,多选一
like 占位符 模糊匹配(_匹配单个字符, %匹配任意个字符)
is null 是null
逻辑运算符 功能
and 或 && 并且 (多个条件同时成立)
or 或 || 或者 (多个条件任意一个成立)
not 或 ! 非 , 不是

聚合函数

1
select  聚合函数(字段列表)  from  表名 ;
函数 功能
count 统计数量
max 最大值
min 最小值
avg 平均值
sum 求和
  • 注意
  1. null值不参与所有聚合函数运算

  2. 统计数量可以使用:count(),count(字段),count(常量),推荐使用count(*)

分组查询

1
select  字段列表  from  表名  [where 条件]  group by 分组字段名  [having 分组后过滤条件];
  • where与having区别
  1. 执行时机不同:where是分组之前进行过滤,不满足where条件,不参与分组;而having是分组之后对结果进行过滤
  2. 判断条件不同:where不能对聚合函数进行判断,而having可以
  • 注意
  1. 分组之后,查询的字段一般为聚合函数和分组字段,查询其他字段无任何意义

  2. 执行顺序:where > 聚合函数 > having

排序查询

  • 排序方式:
    • ASC :升序(默认值)
    • DESC:降序
1
2
3
4
5
select  字段列表  
from 表名
[where 条件列表]
[group by 分组字段 ]
order by 字段1 排序方式1 , 字段2 排序方式2 … ;

分页查询

1
select 字段列表 from 表名 limit 起始索引, 查询记录数 ;
  • 注意
  1. 起始索引从0开始,起始索引 = (查询页码 - 1)* 每页显示记录数

  2. 分页查询是数据库的方言,不同的数据库有不同的实现,MySQL中是LIMIT

  3. 如果查询的是第一页数据,起始索引可以省略,直接简写为 limit 条数

多表设计

在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种:

  • 一对多(多对一)

  • 多对多

  • 一对一

外键约束

  • 物理外键和逻辑外键
    • 物理外键

      • 概念:使用foreign key定义外键关联另外一张表
      • 缺点:
        • 影响增、删、改的效率(需要检查外键关系)
        • 仅用于单节点数据库,不适用与分布式、集群场景
        • 容易引发数据库的死锁问题,消耗性能
    • 逻辑外键

      • 概念:在业务层逻辑中,解决外键关联
      • 通过逻辑外键,就可以很方便的解决上述问题

多表查询

概述

  • 指从多张表中查询数据
  • 笛卡尔乘积是指在数学中,两个集合(A集合和B集合)的所有组合情况。在多表查询时,需要消除无效的笛卡尔积

内连接

  • 隐式内连接
1
select 字段列表 from 表1, 表2 where 条件 ... ;
  • 显示内连接
1
select 字段列表 from 表1 [ inner ] join 表2 on 连接条件 ... ;

外连接

  • 左外连接
1
select 字段列表 from 表1 left [ outer ] join 表2 on 连接条件 ... ;
  • 右外连接
1
select 字段列表 from 表1 right [ outer ] join 表2 on 连接条件 ... ;

子查询

概述
  • SQL语句中嵌套select语句,称为嵌套查询,又称子查询
  • 形式
1
select * from t1 where column1 = (select column1 from t2 ...);
  • 子查询外部的语句可以是insert / update / delete / select的任何一个,最常见的是select
标量子查询
  • 子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式
  • 常见的操作符:= <> > >= < <=
列子查询
  • 子查询返回的结果是一列(可以是多行)
  • 常见的操作符:in、not in等
行子查询
  • 子查询返回的结果是一行(可以是多列)
  • 常见的操作符:= <> > >= < <=
表子查询
  • 子查询返回的结果是多行多列,常作为临时表
  • 常用的操作符:in

事务

概念

  • 事务是一组操作的集合,它是一个不可分割的工作单位。事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,要么同时成功,要么同时失败
  • 注意:默认MySQL的事务是自动提交的,当执行一条DML语句,MySQL会立即隐式的提交事务

操作

  • 开启事务:start transaction; /begin;
  • 提交事务:commit;
  • 回滚事务:rollback;

四大特性

  • 原子性:事务时不可分割的最小单元,要么全部成功,要么全部失败
  • 一致性:事务完成时,必须使所有的数据都保持一致状态
  • 隔离性:数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行
  • 持久性:事务一旦提交或回滚,对数据库中的数据的改变就是永久的

索引

概念

  • 帮助数据库高效获取数据数据结构

  • 优缺点

    • 优点
      • 提高数据查询到效率,降低数据库的IO成本
      • 通过索引列对数据进行排序,降低数据排序的成本,降低CPU消耗
    • 缺点
      • 索引会占用存储空间
      • 索引大大提高了查询效率,同时却也降低的insert、update、delete的效率

结构

  • B+ Tree(多路平衡搜索树)

语法

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

Mybatis

简介

  • MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。
  • 官网

入门

  • 创建SpringBoot工程、数据库表、实体类User
  • 引入Mybatis相关依赖,配置Mybatis(数据库连接信息)
  • 编写SQL语句(注解/XML)

数据库连接池

  • 是个容器,负责分配、管理数据库连接(Connection)

  • 允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个

  • 释放空闲时间超过最大空闲时间的连接,避免因为没有释放连接而引起的数据库连接遗漏

  • 标准接口:DataSource

    • 获取连接
    1
    Connection getConnection() throws SQLException;

lombok

  • Lombok是一个实用的Java类库,能通过注解的形式自动生成构造器,并可以自动化生成日志变量,简化java开发,提高效率
注解 作用
@Getter/@Setter 为所有的属性提供get/set方法
@ToString 会给类自动生成易阅读的 toString 方法
@EqualsAndHashCode 根据类所拥有的非静态字段自动重写 equals 方法和 hashCode 方法
@Data 提供了更综合的生成代码功能(@Getter + @Setter + @ToString + @EqualsAndHashCode)
@NoArgsConstructor 为实体类生成无参的构造器方法
@AllArgsConstructor 为实体类生成除了static修饰的字段之外带有各参数的构造器方法
1
2
3
4
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

操作

删除
  • SQL语句
1
delete from emp where id = 17;
  • 接口方法
1
2
@Delete("delete from emp where id = #{id}")
public void delete(Integer id);
  • 注意:如果mapper接口方法形参只有一个普通类型的参数,#{…}里面的属性名可以随便写,如:#{id}、#{value}

  • 预编译SQL

性能更高

更安全(防止SQL注入)

SQL注入是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法

新增
  • SQL语句
1
insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) values('Tom','汤姆',1,'1.jpg',2,'2012-12-31',2,'2022-12-31 10:00:00','2022-12-31 10:00:00')
  • 接口方法
1
2
@Insert("insert int 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);
  • 主键返回
1
@Options(keyProperty = "id", useGeneratedKeys = true)
更新
  • SQL语句
1
update emp set username = 'xiaoming', name = '小明', gender = 1, image = '1.jpg', job = 2, entrydate = '2012-01-01', dept_id = 2, update_time = '2022-10-01 12:12:12' where id = 17;
  • 接口方法
1
2
@Update("update emp set username=#{username}, name=#{name}, gender=#{gender}, image=#{image}, job=#{job}, entrydate=#{entrydate}, dept_id=#{deptId}, update_time=#{updateTime} where id=#{id}")
public void update(Emp emp);
查询
根据ID查询
  • SQL语句
1
select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp;
  • 接口方法
1
2
@Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp where id=#{id}")
public Emp getById(Integer id);
  • 数据封装(开启驼峰命名)
1
2
# 在application.properties中添加:
mybatis.configuration.map-underscore-to-camel-case=true
条件查询
  • SQL语句
1
select * from emp where name like '%张%' and gender = 1 and entrydate between '2010-01-01' and '2020-01-01' order by update_time desc;
  • 接口方法
1
2
@Select("select * from emp where name like '%${name}%' and gender = #{gender} and entrydate between #{begin} and #{end} order by update_time desc")
public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
  • 解决SQL注入问题
1
2
@Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and entrydate between #{begin} and #{end} order by update_time desc")
public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
XML映射文件
  • XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)

  • XML映射文件的namespace属性为Mapper接口全限定名一致

  • XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致

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

动态SQL

<if>:用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL

<where>只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或OR

<set>:动态的在SQL语句中插入set关键字,并会删掉额外的逗号。(用于update语句中

<foreach>
  • SQL语句:
1
delete from emp where id in (1,2,3);
  • Mapper接口
1
2
3
4
5
@Mapper
public interface EmpMapper {
//批量删除
public void deleteByIds(List<Integer> ids);
}
  • XML映射文件
1
2
3
<foreach collection="集合名称" item="集合遍历出来的元素/项" separator="每一次遍历使用的分隔符" 
open="遍历开始前拼接的片段" close="遍历结束后拼接的片段">
</foreach>
sql片段
  • <sql>:定义可重用的SQL片段

  • <include>:通过属性refid,指定包含的SQL片段

文件上传

  1. 前端页面三要素
  • 表单项 type = “type”
  • 表单提交方式 post
  • 表单的enctype属性 multipart/form-data
  1. 服务端接收文件
  • MutipartFile

本地存储

  • 在服务器本地磁盘上创建images目录,用来存储上传的文件(例:E盘创建images目录)
  • 使用MultipartFile类提供的API方法,把临时文件转存到本地磁盘目录下

MultipartFile 常见方法:

方法 注释
String getOriginalFilename(); 获取原始文件名
void transferTo(File dest); 将接收的文件转存到磁盘文件中
long getSize(); 获取文件的大小,单位:字节
byte[] getBytes(); 获取文件内容的字节数组
InputStream getInputStream(); 获取接收到的文件内容的输入流
1
2
3
4
5
#配置单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB

#配置单个请求最大上传大小(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size=100MB

阿里云OSS

  • Bucket:存储空间是用户用于存储对象(Object,文件)的容器,索引的对象都必须隶属于某个存储空间
  • SDK:Software Development Kit的缩写,软件开发工具包,包括辅助软件开发的依赖(jar包)、代码示例等,都可以叫做SDK
内容 说明
accessKeyId 阿里云账号AccessKey
accessKeySecret 阿里云账号AccessKey对应的秘钥
bucketName Bucket名称
objectName 对象名称,在Bucket中存储的对象的名称
filePath 文件路径

配置文件

格式

  • XML(臃肿)
1
2
3
4
<server>
<port>8080</port>
<address>127.0.0.1</address>
</server>
  • properties(层级结构不清晰)
1
2
server.port=8080
server.address=127.0.0.1
  • yml/yaml(简洁,推荐)
1
2
3
server:
port: 8080
address: 127.0.0.1

@Value:只能一个一个的进行外部属性的注入@configurationProperties:可以批量的将外部的属性配置注入到bean对象的属性中

登录校验

登录标记

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

统一拦截

  • 过滤器Filter
  • 拦截器Interceptor

会话技术

  • 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到一方断开连接,会话结束。一次会话中可以包含多次请求和响应

  • 会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次绘画的多次请求间共享数据

  • 会话跟踪方案:

    • 客户端会话跟踪技术:Cookie
    • 服务端会话跟踪技术:Session
    • 令牌技术
会话跟踪技术
  • Cookie

    • 优点:
      • HTTP协议中支持的技术
    • 缺点:
      • 移动端APP无法使用Cookie
      • 不安全,用户可以自己禁用Cookie
      • Cookie不能跨域
  • Session

    • 优点:
      • 存储在服务器,安全
    • 缺点:
      • 服务器集群环境下无法直接使用Session
      • Cookie的缺点
  • 令牌技术

    • 优点:
      • 支持PC端、移动端
      • 解决集群环境下的认证问题
      • 减轻服务器端存储压力
    • 缺点:
      • 需要自己实现

JWT令牌

简介
  • 全称:Json Web Token 官网

  • 定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在这些信息是可靠的

  • 组成:

    • 第一部分:Header(头), 记录令牌类型、签名算法等。 例如:{“alg”:“HS256”,“type”:“JWT”}

    • 第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。 例如:{“id”:“1”,“username”:“Tom”}

    • 第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload,并加入指定秘钥,通过指定签名算法计算而来

  • 场景:登录认证

    • 登录成功后,生成令牌
    • 后续每个请求,携带JWT令牌,系统在每次请求处理之前,先校验令牌,通过后,再处理
生成和校验
1
2
3
4
5
6
<!-- JWT依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
  • 生成令牌
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void genJwt(){
Map<String,Object> claims = new HashMap<>();
claims.put("id",1);
claims.put("username","Tom");

String jwt = Jwts.builder()
.setClaims(claims) //自定义内容(载荷)
.signWith(SignatureAlgorithm.HS256, "itheima") //签名算法
.setExpiration(new Date(System.currentTimeMillis() + 24*3600*1000)) //有效期
.compact();

System.out.println(jwt);
}
  • 解析令牌
1
2
3
4
5
6
7
8
@Test
public void parseJwt(){
Claims claims = Jwts.parser()
.setSigningKey("itheima")//指定签名密钥(必须保证和生成令牌时使用相同的签名密钥)
.parseClaimsJws("")
.getBody();
System.out.println(claims);
}

Filter

  • Filter表示过滤器,是 JavaWeb三大组件(Servlet、Filter、Listener)之一
  • 过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能
  • 过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等
入门
  • 定义:实现Filter接口

  • 配置:@WebFilter(urlPatterns=“/”)

    ​ @ServletComponentScan

拦截路径
  • Filter可以根据需求,配置不同的拦截资源路径
拦截路径 urlPattern值 含义
拦截具体路径 /login 只有访问/login路径时,才会被拦截
目录拦截 /emps/* 访问/emps下的所有资源,都会被拦截
拦截所有 /* 访问所有资源,都会被拦截
过滤器链
  • 介绍:一个web应用中,可以配置多个过滤器,形成一个过滤器链

  • 顺序:注解配置的Filter,优先级时按照过滤器类名(字符串)的自然排序

Interceptor

  • 概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架提供,用来动态拦截控制器方法的执行
  • 作用:拦截请求,在指定方法调用后,根据业务需要执行预先设定的代码
拦截路径
  • interceptor可以根据需求,配置不同的拦截资源路径
拦截路径 含义 举例
/* 一级路径 能匹配/depts,/emps,/login,不能匹配 /depts/1
/** 任意级路径 能匹配/depts,/depts/1,/depts/1/2
/depts/* /depts下的一级路径 能匹配/depts/1,不能匹配/depts/1/2,/depts

Filter与Interceptor区别

  • 接口范围不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerInterceptor接口
  • 拦截范围不同:过滤器Filter会拦截所有的资源,而Interceptor只会拦截Spring环境中的资源

异常处理

  • 全局异常处理器
1
2
3
4
5
6
7
8
9
@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(Exception.class)
public Result ex(Exception ex){
ex.printStackTrace();
return Result.error("操作失败");
}
}

事务管理

Spring事务管理

  • 注解:@Transactional
  • 位置:业务(service)层的方法、类、接口上
  • 作用:将当前方法交给spring进行事务管理,方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务
rollbackFor属性
  • 默认情况下,只有出现RuntimeException才回滚异常
propagation属性
  • 事务传播行为:指当一个事务被另一个事务方法调用时,这个事务方法应该如何进行事务控制
属性值 含义
REQUIRED 【默认值】需要事务,有则加入,无则创建新事务
REQUIRES_NEW 需要新事务,无论有无,总是创建新事务
SUPPORTS 支持事务,有则加入,无则在无事务状态中运行
NOT_SUPPORTED 不支持事务,在无事务状态下运行,如果当前存在已有事务,则挂起当前事务
MANDATORY 必须有事务,否则抛异常
NEVER 必须没事务,否则抛异常
  • REQUIRED:大部分情况下用该传播行为即可
  • REQUIRES_NEW:不希望事务之间相互影响,可以使用该传播行为。比如:下单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功

AOP

入门

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

AOP程序:TimeAspect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Component
@Aspect //当前类为切面类
@Slf4j
public class TimeAspect {

@Around("execution(* com.itheima.service.*.*(..))")
public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {
//记录方法执行开始时间
long begin = System.currentTimeMillis();

//执行原始方法
Object result = pjp.proceed();

//记录方法执行结束时间
long end = System.currentTimeMillis();

//计算方法执行耗时
log.info(pjp.getSignature()+"执行耗时: {}毫秒",end-begin);

return result;
}
}

核心概念

  • 连接点:Joinpoint,可以被AOP控制的方法(暗含方法执行时的相关信息)
  • 通知:Advice,指哪些重复的逻辑,就是共性功能(最终体现为一个方法)
  • 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用
  • 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
  • 目标对象:Target,通知所应用的对象

通知类型

  • @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行

  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行

  • @After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行

  • @AfterReturning : 返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行

  • @AfterThrowing : 异常后通知,此注解标注的通知方法发生异常后执行

  • 注意

    • @Around环绕通知需要自己调用 ProceedingJoinPoint.proceed() 来让原始方法执行,其他通知不需要考虑目标方法执行
    • @Around环绕通知方法的返回值,必须指定为Object,来接收原始方法的返回值

通知顺序

  • 当有多个切面的切入点都匹配到了目标方法,目标方法运行时,多个通知方法都会被执行
  • 不同切面类中,默认按照切面类的类名字母排序
    • 目标方法前的通知方法:字母排名靠前的先执行
    • 目标方法后的通知方法:字母排名靠前的后执行
  • 用**@Order(数字)加在切面类上来控制顺序**
    • 目标方法前的通知方法:数字小的先执行
    • 目标方法后的通知方法:数字小的后执行

切入点表达式

execution
  • execution主要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配,语法为:
1
execution(访问修饰符?  返回值  包名.类名.?方法名(方法参数) throws 异常?)
  • 其中带?的表示可以省略的部分

    • 访问修饰符:可省略(比如: public、protected)
    • 包名.类名: 可省略
    • throws 异常:可省略(注意是方法上声明抛出的异常,不是实际抛出的异常)
  • 可以使用通配符描述切入点

    • * :单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分
    1
    execution(* com.*.service.*.update*(*))
    • .. :多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数
    1
    execution(* com.itheima..DeptService.*(..))
  • 根据业务需要,可以使用且(&&)、或(||)、非(!)来组合比较复杂的切入点表达式

  • 切入点表达式的书写建议:

    • 所有业务方法名命名时尽量规范,方便切入点表达式快速匹配。如:查询类方法都是 find 开头,更新类方法都是update开头
    • 描述切入点方法通常基于接口描述,而不是直接描述实现类,增强拓展性
    • 在满足业务需要的前提下,尽量缩小切入点的匹配范围。如:包名匹配尽量不使用 …,使用 * 匹配单个包
@annotation
  • 切入点表达式,用于匹配标识有特定注解的方法

  • @annotation(注解全类名)

连接点

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

    • 对于@Around通知,获取连接点信息只能使用ProceedingJoinPoint类型

    • 对于其他四种通知,获取连接点信息只能使用JoinPoint,它是ProceedingJoinPoint的父类型

SpringBoot

优先级

  • 虽然SpringBoot支持多种格式配置文件,但是在项目开发时,推荐统一使用一种格式的配置**(yml是主流)**

  • SpringBoot除了支持配置文件属性配置,还支持Java系统属性命令行参数的方式进行属性配置

    • Java系统属性(格式: -Dkey=value)
    1
    -Dserver.port=9000
    • 命令行参数(格式:–key=value)
    1
    --server.port=10010
  • 执行Java指令,运行jar包

    1
    java -Dserver.port=9000 -jar XXXXX.jar --server.port=10010
  • 注意:

    • SpringBoot项目在进行打包时,需要引入插件spring-boot-maven-plugin
优先级(从低到高)
application.yaml(忽略)
application.yml
application.properties
java系统属性(-Dxxx=xxx)
命令行参数(–xxx=xxx)

Bean管理

获取bean
  • 默认情况下,Spring项目启动时,会把bean都创建好放在IOC容器中

    • 根据name获取bean

      1
      Object getBean(String name)
    • 根据类型获取bean

      1
      <T> T getBean(Class<T> requiredType)
    • 根据name获取bean(带类型转换)

      1
      <T> T getBean(String name, Class<T> requiredType)
  • 注意

    • 【Spring项目启动时,会把bean都创建好】还会受到作用域及延迟初始化影响,主要针对于默认的单例,非延迟加载的bean而言
  • 代码

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

    @Autowired
    private ApplicationContext applicationContext; //IOC容器对象

    //获取bean对象
    @Test
    public void testGetBean(){
    //根据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环境才生效:

    作用域 说明
    singleton 容器内同名称的bean只有一个实例(单例)(默认)
    prototype 每次使用该bean时会创建新的实例(非单例)
    request 每个请求范围内会创建新的实例(web环境中,了解)
    session 每个会话范围内会创建新的实例(web环境中,了解)
    application 每个应用范围内会创建新的实例(web环境中,了解)
  • 可以通过@Scope注解来配置作用域

  • 注意:

    • 默认singleton的bean,在容器启动时被创建,可以使用@Lazy注解来延迟初始化(延迟到第一次使用)
    • prototype的bean,每一次使用该bean的时候都会创建一个新的实例
    • 实际开发中,绝大部分的bean是单例的,大部分bean不需要配置scope属性
第三方bean
  • 如果要管理的bean对象来自于第三方(不是自己定义的),无法使用@Component及衍生注解声明bean的,需要用到@Bean注解

  • 若要管理第三方bean对象,建议对这些bean集中分类配置,可以通过@Configuration注解声明一个配置类

  • 代码

1
2
3
4
5
6
7
8
9
10
11
@Configuration //配置类  (在配置类当中对第三方bean进行集中的配置管理)
public class CommonConfig {

//声明第三方bean
@Bean //将当前方法的返回值对象交给IOC容器管理, 成为IOC容器bean
//通过@Bean注解的name/value属性指定bean名称, 如果未指定, 默认是方法名
public SAXReader reader(DeptService deptService){
System.out.println(deptService);
return new SAXReader();
}
}
  • 注意:
    • 通过@Bean注解的name或value属性可以声明bean的名称,如果不指定,默认bean的名称就是方法名
    • 如果第三方bean需要依赖其他bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配

自动配置

  • SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到IOC容器中,不需要手动声明,从而简化开发,省去繁琐的配置操作
方案
  • 方案一:@ComponentScan组件扫描(使用繁琐,性能低)
1
2
3
@ComponentScan({"com.example","com.itheima"})
@SpringBootApplication
public class ...{}
  • 方案二:@Import导入。使用@Import导入的类会被Spring加载到IOC容器中,导入形式主要有以下几种:
    • 导入 普通类
    • 导入 配置类
    • 导入 ImportSelector接口实现类
    • @EnableXxxx注解,封装@Import注解(方便)
源码跟踪

@SpringBootApplication

  • 该注解标识在SpringBoot工程引导类上,是SpringBoot中最重要的注解。该注解由三个部分组成
    • @SpringBootConfiguration:该注解与@Configuration注解作用相同,用来声明当前也是一个配置类
    • @ComponentScan:组件扫描,默认扫描当前引导类所在包及其子包
    • @EnableAutoConfiguration:SpringBoot实现自动化配置的核心注解

@Condition

  • 作用:按照一定的条件进行判断,在满足给定条件后才会注册对应的bean对象到Spring IOC容器中
  • 位置:方法、类
  • @Condition本身是一个父注解
    • @ConditionOnClass:判断环境中是否有对应字节码文件,才注册bean到IOC容器
    • @ConditionOnMissingBean:判断环境中没有对应的bean(类型或名称),才注册bean到IOC容器
    • @ConditionOnProperty:判断配置文件中有对应属性和值,才注册bean到IOC容器
自定义starter
  • 实际开发中,经常会定义一些公共组件,提供给各个项目团队使用。而在SpringBoot的项目中,一般会将这些公共组件封装为SpringBoot的starter

  • 步骤

    • 第1步:创建自定义starter模块(进行依赖管理)
      • 把阿里云OSS所有的依赖统一管理起来
    • 第2步:创建autoconfigure模块
      • 在starter中引入autoconfigure (我们使用时只需要引入starter起步依赖即可)
    • 第3步:在autoconfigure中完成自动配置
      1. 定义一个自动配置类,在自动配置类中将所要配置的bean都提前配置好
      2. 定义配置文件,把自动配置类的全类名定义在配置文件中

总结

Maven

分模块设计

  • 将项目按照功能拆分成若干个子模块,方便项目的管理维护、扩展,也方便模块间的相互调用、资源共享
  • 注意:
    • 分模块设计需要先针对模块功能进行设计,再进行编码。不会将工程开发完毕,然后进行拆分

继承

  • 概念:继承描述的是两个工程间的关系,与java中的继承相似,子工程可以继承父工程中的配置信息,常见于依赖关系的继承

  • 作用:简化依赖配置、统一管理依赖

  • 实现:

    1
    2
    3
    4
    5
    6
    <parent>
    <groupId>...</groupId>
    <artifactId>...</artifactId>
    <version>...</version>
    <relativePath>....</relativePath>
    </parent>
继承关系实现
  • 创建maven模块tlias-parent,该工程为父工程,设置打包方式pom(默认jar)
1
2
3
4
5
6
7
8
9
10
11
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.itheima</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
  • 子工程的pom.xml文件中,配置继承关系
1
2
3
4
5
6
7
8
9
<parent>
<groupId>com.itheima</groupId>
<artifactId>tlias-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../tlias-parent/pom.xml</relativePath>
</parent>

<artifactId>tlias-utils</artifactId>
<version>1.0-SNAPSHOT</version>
  • 父工程中配置各个工程共有的依赖(子工程会自动继承父工程的依赖)
1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
</dependencies>
版本锁定
  • 在maven中,可以在父工程的pom文件中通过<dependencyManagement> 来统一管理依赖版本

    • 父工程:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!--统一管理依赖版本-->
    <dependencyManagement>
    <dependencies>
    <!--JWT令牌-->
    <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
    </dependency>
    </dependencies>
    </dependencyManagement>
    • 子工程:
    1
    2
    3
    4
    5
    6
    7
    <dependencies>
    <!--JWT令牌-->
    <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    </dependency>
    </dependencies>
  • 注意:

    • 子工程引入依赖时,无需指定<version>版本号,父工程统一管理。变更依赖版本,只需在父工程中统一变更
  • 也可以通过自定义属性及属性引用的形式,在父工程中将依赖的版本号进行集中管理维护

    • 自定义属性
    1
    2
    3
    <properties>
    <lombok.version>1.18.24</lombok.version>
    </properties>
    • 引用属性
    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>${lombok.version}</version>
    </dependency>
  • 面试题:<dependencyManagement><dependencies> 的区别是什么?

<dependencies> 是直接依赖,在父工程配置了依赖,子工程会直接继承下来

<dependencyManagement> 是统一管理依赖版本,不会直接依赖,还需要在子工程中引入所需依赖(无需指定版本)

聚合

  • 聚合:将多个模块组织成一个整体,同时进行项目的构建。

  • 聚合工程:一个不具有业务功能的“空”工程(有且仅有一个pom文件)

  • 作用:快速构建项目(无需根据依赖关系手动构建,直接在聚合工程上构建即可)

  • maven中可以通过<modules>设置当前聚合工程所包含的子模块名称

继承与聚合

  • 作用
    • 聚合用于快速构建项目
    • 继承用于简化依赖配置、统一管理依赖
  • 相同点
    • 聚合与继承的pom.xml文件打包方式均为pom,可以将两种关系制作到同一个pom文件中
    • 聚合与继承均属于设计型模块,并无实际的模块内容
  • 不同点
    • 聚合是在聚合工程中配置关系,聚合可以感知到参与聚合的模块有哪些
    • 继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己

私服

介绍
  • 私服是一种特殊的远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的中央仓库,用于解决团队内部的资源共享与资源同步问题
  • 依赖查找顺序:
    • 本地仓库
    • 私服
    • 中央仓库
  • 注意:
    • 私服在企业项目开发在,一个项目/公司,只需要一台(无需自己搭建)
上传和下载

私服配置

使用私服,需要在maven的settings.xml配置文件中,做如下配置:

  1. 需要在 servers 标签中,配置访问私服的个人凭证(访问的用户名和密码)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <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. mirrors 中只配置我们自己私服的连接地址(如果之前配置过阿里云,需要直接替换掉)

    1
    2
    3
    4
    5
    <mirror>
    <id>maven-public</id>
    <mirrorOf>*</mirrorOf>
    <url>http://192.168.150.101:8081/repository/maven-public/</url>
    </mirror>
  3. 需要在 profiles 中,增加如下配置,来指定snapshot快照版本的依赖,依然允许使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <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>
  4. 如果需要上传自己的项目到私服上,需要在项目的pom.xml文件中,增加如下配置,来配置项目发布的地址(也就是私服的地址)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <distributionManagement>
    <!-- release版本的发布地址 -->
    <repository>
    <id>maven-releases</id>
    <url>http://192.168.150.101:8081/repository/maven-releases/</url>
    </repository>

    <!-- snapshot版本的发布地址 -->
    <snapshotRepository>
    <id>maven-snapshots</id>
    <url>http://192.168.150.101:8081/repository/maven-snapshots/</url>
    </snapshotRepository>
    </distributionManagement>
  5. 发布项目,直接运行 deploy 生命周期即可 (发布时,建议跳过单元测试)

启动本地私服
  1. 解压: apache-maven-nexus.zip

  2. 进入目录: apache-maven-nexus\nexus-3.39.0-01\bin

  3. 启动服务:双击 start.bat

  4. 访问服务:localhost:8081

  5. 私服配置说明:将上述配置私服信息的 192.168.150.101 改为 localhost


JavaWeb
https://www.renkelin.vip/2023/04/29/JavaWeb/
Author
Kolin
Posted on
April 29, 2023
Licensed under