Java Web 学习总结(新编)
前端
学习网站 w3school
MVVM
MVVM(Model-View-ViewModel):
Model: 数据模型,前端请求从后台获取的数据 —> Ajax
View: 视图,html+css无数据处理 —> Element UI
ViewModel: 将数据用JS的DOM技术展示到视图上 —> Vue
DOM
DOM技术(文档对象模型)接口,动态访问和更新网页。
核心是将HTML或XML文档视为一个树形结构。
通过DOM,可用JS等来操作节点,从而实现对页面内容的修改、添加或删除等功能。
- 节点(Node): 基本单位,元素、属性、文本。
- 元素(Element): 节点的一种,比如
<div>,<p>等。 - 属性(Attribute): 如id, class等。
常用DOM操作
- 获取元素:
○ document.getElementById() 通过ID获取单个元素
○ document.getElementsByTagName() 通过标签名获取一组元素
○ document.querySelector() 和 document.querySelectorAll() 使用CSS选择器来获取单个或多个元素 - 修改元素内容:
○ element.innerHTML 修改元素内部的HTML代码
○ element.textContent 只修改元素内的文本内容 - 修改元素属性:
○ element.setAttribute(name, value) 设置属性值
○ element.getAttribute(name) 获取属性值
○ element.removeAttribute(name) 删除属性 - 添加/移除元素:
○ parentElement.appendChild(newChild) 向父元素添加子元素
○ parentElement.removeChild(oldChild) 从父元素中移除子元素 - 事件监听:
○ element.addEventListener(event, function, useCapture) 为元素添加事件处理器
○ element.removeEventListener(event, function, useCapture) 移除事件处理器
Vue:提高开发的效率
1 | <!DOCTYPE html> |
el: 用来指定哪儿些标签受 Vue 管理。该属性取值#app中的app需要是受管理的标签的id属性值
data: 用来定义数据模型
methods: 用来定义函数{{}}插值表达式:用来将vue对象中定义的model展示到页面上
| 指令 | 作用 |
|---|---|
| v-bind | 为HTML标签绑定属性值,如设置 href , css样式等,当vue对象中的数据模型发 、生变化时,标签的属性值会随之发生变化 |
| v-model | 在表单元素上创建双向数据绑定,一定使用在表单项标签上 |
| v-on 简写@ |
为HTML标签绑定事件,给标签的事件绑定的函数必须是vue对象种声明的函数,绑定事件时,事件名相比较js中的事件名,没有on |
| v-if | v-else v-else-if |
| v-show | 根据条件展示某元素,区别在于切换的是display属性的值,和v-if的作用效果是一样的,只是原理不一样 |
| v-for | 列表渲染,遍历容器的元素或者对象的属性 <标签v-for=”变量名/(变量名,索引变量) in 集合模型数据”> 标签> |
Ajax(异步的JS和XML)
客户端的Ajax请求代码如下有如下4步:
- 首先创建AJAX的文件夹,并且创建html文件,按钮绑定单击事件希望点击按钮发送ajax请求
- 创建Request对象,连接服务器
- 调用对象的open()方法设置请求的参数信息(请求地址,请求方式),然后调用 send()方法向服务器发送请求
- 通过绑定事件的方式,来获取服务器响应的数据,通过浏览器f12抓包,点击网络中的XHR请求抓包到我们发送的Ajax请求
XHR代表的就是异步请求
Axios
Axios是对原生的Ajax进行封装,简化书写。
Axios官网
使用
引入Axios文件
使用Axios发送请求,并获取响应结果,官方提供的api很多,此处给出2种,如下
- 发送 get 请求
axios({ method:"get", url:"http://localhost:8080/ajax-demo1/aJAXDemo1? username=zhangsan" }).then(function (resp){ alert(resp.data); }) - 发送 post 请求
axios({ method:"post", url:"http://localhost:8080/ajax-demo1/aJAXDemo1", data:"username=zhangsan" }).then(function (resp){ alert(resp.data); });
axios()是用来发送异步请求的,小括号中使用 js的JSON对象传递请求相关的参数:
method属性:用来设置请求方式的,取值为 get 或 post
url属性:用来书写请求的资源路径
如果是 get 请求,需要将请求参数拼接到路径的后面,格式为:url?参数名=参数值&参数名2=参数值2。
data属性:作为请求体被发送的数据。也就是说如果是 post 请求的话,数据需要作为 data 属性的值。
then() 需要传递一个匿名函数(回调函数)意思是该匿名函数在发送请求时不会被调用,而是在成功响应后调用的函数。
而该回调函数中的 resp 参数是对响应的数据进行封装的对象,通过 resp.data 可以获取到响应的数据。
Axios还针对不同的请求,提供了别名方式的api,具体如下:
| 方法 | 描述 |
|---|---|
| axios.get(url [, config]) | 发送get请求 |
| axios.delete(url [, config]) | 发送delete请求 |
| axios.post(url [, data[, config]]) | 发送post请求 |
| axios.put(url [, data[, config]]) | 发送put请求 |
axios.get("http://yapi.smartxwork.cn/mock/169327/emp/list").then(result => { console.log(result.data); })
axios.post("http://yapi.smartxwork.cn/mock/169327/emp/deleteById","id=1").then(result => { console.log(result.data); })
前端工程化
前端工程化通过脚手架Vue-cli完成,快速的生成一个Vue的项目模板。
需要先安装 NodeJS,然后才能安装Vue-cli
Vue-cli主要提供了如下功能:
- 统一的目录结构
- 本地调试
- 热部署
- 单元测试
- 集成打包上线
npm create vue@latest
main.js
1 | import Vue from 'vue' |
Element
饿了么公司前端开发团队提供的一套基于 Vue 的网站组件库,用于快速构建网页
vue路由
vue官方提供了路由插件Vue Router,其主要组成如下:
VueRouter:路由器类,根据路由请求在路由视图中动态渲染选中的组件
安装插件 npm install vue-router@3.5.1
在src/router/index.js文件中定义路由表,根据其提供的模板代码进行修改
修改页面按钮为router-link,App.vue中定义route-view,作为组件的切换
前端工程打包
NPM脚本中提供的build按钮
通过nginx服务器发布前端工程
轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器
直接将资源放入到html目录中
dist目录下得内容拷贝到nginx的html目录下
双击nginx.exe文件启动nginx
nginx服务器的端口号是80直接访问 http://localhost:80 即可,其中80端口可省略
Nginx默认占用80端口号,如果80端口号被占用,可以在nginx.conf中修改端口号。(netstat –ano | findStr 80)
接口文档
当前最为主流的开发模式:前后端分离
页面原型+需求
- 基本信息
- 请求参数
- 响应数据
后端
Maven
- 依赖管理
- 统一项目结构
- 项目构建


仓库:用于存储资源,管理各种jar包
- 本地仓库:自己计算机上的一个目录(用来存储jar包)
- 中央仓库:由Maven团队维护的全球唯一的。仓库地址:<https://repo1.maven.org/maven 2/>
- 远程仓库(私服):一般由公司团队搭建的私有仓库
使用方法一
下载地址:https://maven.apache.org/download.cgi
bin目录:存放的是可执行命令。(mvn 命令重点关注)
conf目录:存放Maven的配置文件。(settings.xml配置文件后期需要修改)
lib目录:存放Maven依赖的jar包。
本地仓库
新建一个目录
conf下修改settings.xml
定位到53行,复制标签,粘贴到注释的外面(55行)
复制之前新建的用来存储jar包的路径,替换掉标签体内容
配置阿里云私服
conf下修改settings.xml
定位到160行左右,在标签下为其添加子标签
1 | <mirror> |
配置环境变量
新建一个变量MAVEN_HOME,环境变量的值,设置为maven的解压安装目录
PATH环境变量的值,设置为:%MAVEN_HOME%\bin
检查安装 mvn -v
使用方法二
选择 IDEA中 File => Settings => Build,Execution,Deployment => Build Tools => Maven
选择 IDEA中 File => close project
POM (Project Object Model)
指的是项目对象模型,用来描述当前的maven项目
groupId:定义当前Maven项目隶属组织名称
artifactId:定义当前Maven项目名称
常用命令
1 | # 清理项目 |
Spring
依赖注入(DI)、事务管理、web开发支持、数据访问、消息服务等等
勾选web开发相关依赖
创建一个子包controller,包下新建一个类:HelloController
1 | package com.itheima.controller; |
WEB服务器-Tomcat
免费的开源的web应用服务器,Web容器、Servlet容器
Tomcat的官网: https://tomcat.apache.org/
使用步骤
- 准备静态资源
- 下载安装Web服务器软件
- 将静态资源部署到Web服务器上
- 启动Web服务器使用浏览器访问对应的资源

bin:目录下有两类文件,一种是以 .bat 结尾的,是Windows系统的可执行文件,一种是以 .sh 结尾 的,是Linux系统的可执行文件。
webapps:就是以后项目部署的目录

Tomcat的默认端口为8080,所以在浏览器的地址栏输入http://127.0.0.1:8080即可访问tomcat服务器
正常关闭:bin\shutdown.bat或者Ctrl+C
问题1:Tomcat启动时,窗口一闪而过(检查JAVA_HOME环境变量是否正确配置)
问题2:端口号冲突
spring-boot-starter-web和spring-boot-starter-test,在SpringBoot中又称为:起步依赖
而在SpringBoot的项目中,有很多的起步依赖,共同的特征:就是以 spring-boot-starter- 作开头
spring-boot-starter-web:包含了web应用开发所需要的常见依赖(集成了内置的Tomcat服务器)
spring-boot-starter-test:包含了单元测试所需要的常见依赖
举例:当我们开发中需要使用redis数据库时,只需要在SpringBoot项目中,引入:springboot-starter-redis ,即可导入redis开发所需要的依赖。
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。
Postman
作用:进行接口测试
简单参数:在向服务器发起请求时,向服务器传递的是一些普通的请求数据
后端接收传递过来的普通参数数据
- 原始方式
通过Servlet中提供的API:HttpServletRequest(请求对象),获取请求的相关信息
在Controller中,我们要想获取Request对象,可以直接在方法的形参中声明 HttpServletRequest 对象 - SpringBoot方式
Springboot的环境中,对原始的API进行了封装,接收参数的形式更加简单
如果是简单参数,参数名与形参变量名相同,定义同名的形参即可接收参数
使用Spring提供的@RequestParam注解完成映射,方法形参前面加上 @RequestParam 然后通过value属性执行请求参数名,从而完成映射
实体参数:将请求参数封装到一个实体类对象中(请求参数名与实体类的属性名相同)
数组集合参数:
数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数
前端请求时,有两种传递形式
方式一: xxxxxxxxxx?hobby=game&hobby=java
方式二:xxxxxxxxxxxxx?hobby=game,java
集合参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam 绑定参数关系
前端请求时,有两种传递形式
方式一: xxxxxxxxxx?hobby=game&hobby=java
方式二:xxxxxxxxxxxxx?hobby=game,java
日期参数:
日期类型的参数在进行封装时,需要通过@DateTimeFormat注解以及其pattern属性来设置日期的格式
@DateTimeFormat注解的pattern属性中指定了哪种日期格式,前端的日期参数就必须按照指定的格式传递。 后端controller方法中,需要使用Date类型或LocalDateTime类型,来封装传递的参数。
JSON参数:
- Postman在发送请求时,如何传递json格式的请求参数

- 在服务端的controller方法中,如何接收json格式的请求参数
(1. 传递json格式的参数,在Controller中会使用实体类进行封装
(2. 封装规则:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数。需要使用 @RequestBody标识。
(3. @RequestBody注解:将JSON数据映射到形参的实体类对象中(JSON中的key和实体类中的属性 名保持一致)
路径参数:
直接在请求的URL中传递参数,掌握在后端的controller方法中,如何接收路径参数
前端:通过请求URL直接传递参数
后端:使用{…}来标识该路径参数,需要使用@PathVariable获取路径参数
响应
Controller程序,除了接收请求外,还可以进行响应
@ResponseBody
类型:方法注解、类注解
位置:Controller方法上或类上
作用:将方法返回值(controller方法中的return的结果)直接响应给浏览器
如果返回值类型是实体对象/集合,将会转换为JSON格式后在响应给浏览器
@RestController = @Controller + @ResponseBody(组合注解)
统一响应结果
统一的返回结果使用类来描述,在这个结果中包含:
- 响应状态码:当前请求是成功,还是失败
- 状态码信息:给页面的提示信息
- 返回的数据:给前端响应的数据(字符串、对象、集合)
当我们要修改操作数据部分的代码,需要改动Controller
当我们要完善逻辑处理部分的代码,需要改动Controller
当我们需要修改数据响应的代码,还是需要改动Controller
会造成整个工程代码的复用性比较差,而且代码难以维护。
有非常成熟的解决思路,分层开发
分层解耦

- Controller:控制层。接收前端发送的请求,请求处理,响应数据
- Service:业务逻辑层。处理具体业务逻辑
- Dao:数据访问层,也称为持久层。数据访问操作,增、删、改、查
高内聚低耦合
控制反转: Inversion Of Control,简称IOC
对象的创建控制权由程序自身转移到外部 (容器)
对象的创建权由程序员主动创建转移到容器(由容器创建、管理对象)。这个容器称为:IOC 容器 或 Spring 容器
Spring 提供两种类型的IoC容器:
- BeanFactory:最简单的容器,提供基本的Dl支持。
- ApplicationContext:扩展了BeanFactory,.增加了更多企业级功能,如事件发布、国际化支持、资源加载
等。在大多数场景下,我们使用ApplicationContext,因为它提供了更丰富的功能。
依赖注入: Dependency Injection,简称DI
容器为应用程序提供运行时,所依赖的资源
程序运行时需要某个资源,此时容器就为其提供这个资源。
例:EmpController程序运行时需要EmpService对象,Spring容器就为其提供并注入 EmpService对象
IOC容器中创建、管理的对象,称之为:bean对象
依赖注入有三种注入方式:
- 构造器注入
- 字段注入(使用注解)
- setter方法注入
注意
注意:虽然字段注入使用起来最为简便,但Spring团队推荐使用构造函数注入,因为它可以:
·确保依赖不可变
·确保必要的依赖在对象创建时就已存在
·便于单元测试
完成Controller层、Service层、Dao层的代码解耦
思路:
- 删除Controller层、Service层中new对象的代码
- Service层及Dao层的实现类,交给IOC容器管理
Spring提供的注解:@Component ,就可以实现类交给IOC容器管理 - 为Controller及Service注入运行时依赖的对象
Controller程序中注入依赖的Service层对象
Service程序中注入依赖的Dao层对象
Spring提供的注解:@Autowired ,就可以实现程序运行时IOC容器自动注入需要的依赖对象
@Component的衍生注解:
@Controller (标注在控制层类上)
@Service (标注在业务层类上)
@Repository (标注在数据访问层类上)dao
在IOC容器中,每一个Bean都有一个属于自己的名字,可以通过注解的value属性指定bean的名字。如果没有指定,默认为类名首字母小写。
在springboot集成web开发中,声明控制器bean 只能用@Controller
使用四大注解声明的bean,要想生效,还需要被组件扫描注解@ComponentScan扫描
@SpringBootApplication 中, 默认扫描的范围是SpringBoot启动类所在包及其子包
在IOC容器中,存在多个相同类型的bean对象,程序运行会报错
使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现
使用@Qualifier注解:指定当前要注入的bean对象。在@Qualifier的value属性中,指定注入的 bean的名称。
使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称
@Autowird 与 @Resource的区别
@Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
@Autowired 默认是按照类型注入,而@Resource是按照名称注入
Bean的生命周期
在Spring容器中,Bean有一个明确的生命周期:
- 实例化:创建Bean的实例
- 填充属性:设置Bean的属性值和依赖关系
- 初始化前:调用 BeanPostProcessor 的
postProcessBeforelnitialization方法 - 初始化:调用Bean的初始化方法(@PostConstruct注解的方法或实现Initializing Bean接口的afterPropertiesSet方法)
- 初始化后:调用BeanPostProcessor的postProcessAfterlnitialization方法
- 使用:Bean可以被应用程序使用
- 销毁:当容器关闭时,调用Bean的销毁方法(@PreDestroy注解的方法或实现DisposableBean接口的destroy方法)
Mybatis
Java操作数据库,现在主流的方式是:Mybatis
MyBatis是一款优秀的持久层框架,用于简化JDBC的开发
官网:https://mybatis.org/mybatis-3/zh/index.html
持久层:dao,操作数据库
创建用户表user,并创建对应的实体类User
1 | -- 用户表 |
1 | public class User { |
在springboot项目中编写application.properties文件,配置数据库连接信息。
连接数据库,就需要配置数据库连接的基本信息,包括:driver-class-name、url 、username, password
1 | #驱动类名称 |
在创建出来的springboot工程中,在引导类所在包下,在创建一个包 mapper。
在mapper包下创建 一个接口 UserMapper ,这是一个持久层接口(Mybatis的持久层接口规范一般都叫 XxxMapper)
1 | //表示是mybatis中的Mapper接口 |
在SpringBoot工程中,在src下的test目录下,已经自动帮我们创建好了测试类,并且在测试类上已经添加了注解 @SpringBootTest,代表该测试类已经与SpringBoot整合。
该测试类在运行时,会自动通过引导类加载Spring的环境(IOC容器)。
我们要测试那个bean对象,就可以直接通过@Autowired注解直接将其注入进行,然后就可以测试了。
JDBC
Java语言操作关系型数据库的一套API
- 注册驱动
- 获取连接对象
- 执行SQL语句,返回执行结果
- 处理执行结果
- 释放资源

数据库连接池是个容器,负责分配、管理数据库连接(Connection)
程序启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用) 释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏 客户端获取到Connection对象了,但是Connection对象并没有去访问数据库(处于空闲),数据 库连接池发现Connection对象的空闲时间 > 连接池中预设的最大空闲时间,此时数据库连接池就会自动释放掉这个连接对象
数据库连接池的好处:
- 资源重用
- 提升系统响应速度
- 避免数据库连接遗漏
实现数据库连接池
官方(sun)提供了数据库连接池标准(javax.sql.DataSource接口)
功能:获取连接public ConnectiongetConnection() throws SQLException;
第三方组织必须按照DataSource接口实现
常见的数据库连接池:C3P0 DBCP Druid Hikari(springboot默认)
现在使用更多的是:Hikari、Druid (性能更优越)
Hikari(追光者) [默认的连接池]
Druid(德鲁伊) 阿里巴巴开源的数据库连接池项目,Java语言最好的数据库连接池之一
默认的数据库连接池切换为Druid数据库连接池
参考官方地址:<https://github.com/alibaba/druid/tree/master/druid-spring-b oot-starter>
在pom.xml文件中引入依赖
在application.properties中引入数据库连接配置
MybatisX是一款基于IDEA的快速开发Mybatis的插件,为效率而生
Mybatis的开发有两种方式:
- 注解
- XML
使用Mybatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建 议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。
在Mybatis中使用XML映射文件方式开发,需要符合一定的规范: - XML映射文件的名称与Mapper接口名称一致,并且放置在相同包下(同包同名)
- XML映射文件的namespace属性为Mapper接口全限定名一致
- XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。
标签:就是用于编写select查询语句的。resultType属性,指的是查询返回的单条记录所封装的类型。
编写XML映射文件
xml映射文件中的dtd约束,直接从mybatis官网复制即可
1 | <?xml version="1.0" encoding="UTF-8" ?> |
动态SQL
SQL语句会随着用户的输入或外部条件的变化而变化
只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或 OR
动态的在SQL语句中插入set关键字,并会删掉额外的逗号(用于update语句中)
事务管理
事务是一组操作的集合,它是一个不可分割的工作单位。
事务会把所有的操作作为一个整体,一起向数据库提交或者是撤销操作请求。所以这组操作要么同时成功,要么同时失败。
事务的操作主要有三步:
- 开启事务(一组操作开始前,开启事务):start transaction / begin ;
- 提交事务(这组操作全部成功后,提交事务):commit ;
- 回滚事务(中间任何一个操作出现异常,回滚事务):rollback ;
在spring框架当中就已经把事务控制的代码都已经封装好了,并不需要我们手动实现。只需要@Transactional就搞定了
@Transactional作用:就是在当前这个方法执行开始之前来开启事务,方法执行完毕之后提交 事务。如果在这个方法执行的过程当中出现了异常,就会进行事务的回滚操作。
@Transactional注解:我们一般会在业务层当中来控制事务,因为在业务层当中,一个业务功 能可能会包含多个数据访问的操作。在业务层来控制事务,我们就可以将多个数据访问操作控制在 一个事务范围内。
@Transactional注解书写位置:
方法 当前方法交给spring进行事务管理
类 当前类中所有的方法都交由spring进行事务管理
接口 接口下所有的实现类当中所有的方法都交给spring 进行事务管理
@Transactional注解当中的两个常见的属性:
异常回滚的属性:rollbackFor
默认情况下,只有出现RuntimeException(运行时异常)才会回滚事务。
让所有的异常都回滚,需要来配置@Transactional注解当中的rollbackFor属性,通过rollbackFor这个属性可以指定出现何种异常类型回滚事务。事务传播行为:propagation
我们要想控制事务的传播行为,在@Transactional注解的后面指定一个属性propagation,通过 propagation 属性来指定传播行为。
接下来我们就来介绍一下常见的事务传播行为:
- REQUIRED 【默认值】需要事务,有则加入,无则创建新事务
- REQUIRES_NEW 需要新事务,无论有无,总是创建新事务
- SUPPORTS 支持事务,有则加入,无则在无事务状态中运行
- NOT_SUPPORTED 不支持事务,在无事务状态下运行,如果当前存在已有事务,则挂起当前事务
- MANDATORY 必须有事务,否则抛异常
- NEVER 必须没事务,否则抛异常
场景
lREQUIRED :大部分情况下都是用该传播行为即可。
lREQUIRES_NEW :当我们不希望事务之间相互影响时,可以使用该传播行为。
比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功。
AOP
1 | <dependency> |
- 连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)例如:部分业务方法都是可以被aop控制的方法
- 通知:Advice,指哪些重复的逻辑,也就是共性功能(最终体现为一个方法) 在AOP面向切面编程当中,只需要将这部分重复代码逻辑抽取出来单独定义。
- 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用在通知当中,定义的共性功能到底要应用在哪些方法上?此时就涉及到了切入点。切入点指的是匹配连接点的条件。通知仅会在切入点方法运行时才会被应用。 在aop的开发当中,我们通常会通过一个切入点表达式来描述切入点
- 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)当通知和切入点结合在一起,就形成了一个切面。通过切面就能够描述当前aop程序需要针对于哪个原始方法,在什么时候执行什么样的操作
- 目标对象:Target,通知所应用的对象
通知类型
@Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行
@Before:前置通知,此注解标注的通知方法在目标方法前被执行
@After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行
@AfterReturning :返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
@AfterThrowing :异常后通知,此注解标注的通知方法发生异常后执行程序没有发生异常的情况下,@AfterThrowing标识的通知方法不会执行。
程序发生异常的情况下: @AfterReturning标识的通知方法不会执行,@AfterThrowing标识的通知方法执行了 @Around环绕通知中原始方法调用时有异常,通知中的环绕后的代码逻辑也不会在执行了(因为原始方法调用已经出异常了)
@Around环绕通知需要自己调用 ProceedingJoinPoint.proceed() 来让原始方法执行,其他通知不需要考虑目标方法执行 @Around环绕通知方法的返回值,必须指定为Object,来接收原始方法的返回值,否则原始方法 执行完毕,是获取不到返回值的。
切入点表达式重复的问题?答案就是:抽取
Spring提供了@PointCut注解,该注解的作用是将公共的切入点表达式抽取出来,需要用到时引用该切入点表达式即可。
需要注意的是:当切入点方法使用private修饰时,仅能在当前切面类中引用该表达式,当外部其他切面类中也要引用当前类中的切入点表达式,就需要把private改为public,而在引用的时候,具体的语法为: 全类名.方法名()通知顺序
通过以上程序运行可以看出在不同切面类中,默认按照切面类的类名字母排序:
目标方法前的通知方法:字母排名靠前的先执行
目标方法后的通知方法:字母排名靠前的后执行
如果我们想控制通知的执行顺序有两种方式:修改切面类的类名(这种方式非常繁琐、而且不便管理)
使用Spring提供的@Order注解
- 不同的切面类当中,默认情况下通知的执行顺序是与切面类的类名字母排序是有关系的
- 可以在切面类上面加上@Order注解,来控制不同的切面类通知的执行顺序
切入点表达式
描述切入点方法的一种表达式(2种)
作用:主要用来决定项目中的哪些方法需要加入通知
常见形式:
execution(……):根据方法的签名来匹配
//带 ? 的表示可以省略的部分
execution(访问修饰符? 返回值包名.类名.?方法名(方法参数) throws异常?)
*:单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数, 也可以通配包、类、方法名的一部分
..:多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数
切入点表达式的语法规则:方法的访问修饰符可以省略
返回值可以使用 * 号代替(任意返回值类型)
包名可以使用 * 号代替,代表任意包(一层包使用一个 * )
使用 .. 配置包名,标识此包以及此包下的所有子包
类名可以使用 * 号代替,标识任意类
方法名可以使用 * 号代替,表示任意方法
可以使用 * 配置参数,一个任意类型的参数
可以使用 .. 配置参数,任意个任意类型的参数
根据业务需要,可以使用且(&&)、或(||)、非(!)来组合比较复杂的切入点表达式
查询类方法都是 find 开 头,更新类方法都是update开头
@annotation(……) :根据注解匹配
编写自定义注解
在业务类要做为连接点的方法上添加自定义注解
execution切入点表达式:
根据我们所指定的方法的描述信息来匹配切入点方法,这种方式也是最为常用的一种方式
如果我们要匹配的切入点方法的方法名不规则,或者有一些比较特殊的需求,通过execution切入点表达式描述比较繁琐
annotation 切入点表达式:
基于注解的方式来匹配切入点方法。这种方式虽然多一步操作,我们需要自定义一个注解,但是相对来比较灵活。我们需要匹配哪个方法,就在方法上加上对应的注解就可以了连接点
我们目标对象当中所有的方法是不是都是可以被AOP控制的方法。
而在SpringAOP当中,连接点又特指方法的执行。 }
//后置通知
@After(“@annotation(com.itheima.anno.MyLog)”) publicvoidafter(){ log.info(“MyAspect6 -> after …”); } }
在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。
对于@Around通知,获取连接点信息只能使用ProceedingJoinPoint类型对于其他四种通知,获取连接点信息只能使用JoinPoint,它是ProceedingJoinPoint的父类型
SpingBoot原理
配置优先级:Springboot项目当中属性配置的常见方式以及配置的优先级
properties、yaml、yml三种配置文件,优先级最高的是properties,最低是yaml
还支持另外两种常见的配置方式:
- Java系统属性配置(格式: -Dkey=value)
- 命令行参数(格式:–key=value)
优先级:命令行参数 > 系统属性参数 > properties参数 > yml参数 > yaml参数
Bean的管理
- 如何从IOC容器中手动的获取到bean对象
- bean的作用域配置
- 管理第三方的bean对象
标准项目结构:
my-spring-app/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── myapp/
│ │ │ ├── MySpringAppApplication.java # 主应用类
│ │ │ ├── config/ # 配置类
│ │ │ ├── controller/ # 控制器
│ │ │ ├── model/ # 实体类
│ │ │ ├── repository/ # 数据访问层
│ │ │ ├── service/ # 业务逻辑层
│ │ │ └── util/ # 工具类
│ │ └── resources/
│ │ ├── application.yml # 应用配置
│ │ ├── static/ # 静态资源
│ │ └── templates/ # 模板文件
│ └── test/ # 测试代码
├── pom.xml # Maven 配置
└── README.md # 项目文档
- Application类:通常使用
@SpringBootApplication注解。 - controller(控制器):处理HTTP请求,通常使用
@Controller、@RestContro1ler注解。 - Service(服务):包含业务逻辑,通常使用
@Service注解。 - Repository(仓库):负责数据访问,通常使用
@Repository注解。 - Model(模型):表示领域对象,通常是实体类。
- Configuration(配置):提供Bean定义和应用配置,使用
@Configuration注解。
剖析Springboot的底层原理

SpringBoot框架之所以使用起来更简单更快捷,是因为SpringBoot框架底层提供了两个非常重要的功能:
- 自动配置
1 | // 添加依赖后,数据源会被自动配置 |
- 起步依赖
1 | <!-- 示例:Spring Boot Web 起步依赖 --> |
起步依赖的原理就是Maven的依赖传递









