JAVA-Web开发学习记录
Maven
Maven是Apache下的一个开源项目,是一款用于管理和构建java项目的工具
作用:
- 依赖管理:方便快捷的管理项目依赖的资源(jar包),避免版本冲突问题
- 统一项目结构:提供标准的、统一的项目结构
- src:
- main:实际项目资源
- java:java源代码目录
- resources:配置文件目录
- test:
- java:java源代码目录
- resources:配置文件目录
- pom.xml:项目配置文件,project Object model
- main:实际项目资源
- src:
- 项目构建:标准跨平台(Linux、windows、macOS)的自动化项目构建方式
- 清理->编译->测试->打包->发布
介绍
- 项目对象模型POM
- 依赖管理模型dependency
- 构建生命周期/阶段(Build lifecycle&phases),通过插件来实现功能,并生成对应模块产物
maven仓库:本地仓库、中央仓库、远程仓库(私服)
安装与配置
- 下载maven
- 配置本地仓库:修改conf/settings.xml的<localRepository>为一个指定目录
- 换源(配置私服)
- 配置环境变量
Maven坐标配置(资源唯一标识),需要通过坐标来定义项目或引入项目中所需要的依赖
- GroupId:组织名,如com.yd0ng
- ArtifactId:模块名
- Version:版本号
依赖管理
- 依赖配置
- 依赖:当前项目运行所需要的jar包,一个项目中可以引入多个依赖
- 配置:
- 在pom.xml中编写<dependencies>标签
- 在<dependencies>标签中使用<dependency>引入坐标
- 定义坐标的groupId、artifactId、version
- 点击刷新按钮,引入最新加入的坐标
- 依赖传递
- 传递具有依赖性
- 直接依赖:在当前项目中通过依赖配置建立的依赖关系
- 间接依赖:被依赖的资源如果依赖其他资源,当前项目间接依赖其他资源
- 排除依赖:主动断开依赖的资源,被排除的资源无需指定版本
- 在pom.xml的<dependency>标签中加入<exclusions>标签
- 在<exclusions>中使用<exclusion>
- 在<exclusion>中引入坐标(不需要指定版本)
- 传递具有依赖性
- 依赖范围
- 依赖的jar包,默认情况下可以在任何地方使用。可以通过<scope>设置其使用范围
- 作用范围:
- 主程序范围有效(main文件夹范围内)
- 测试程序范围有效(test文件夹范围内)
- 是否参与打包运行(package指令范围内)

- 依赖配置
生命周期
- Maven的生命周期是为了对所有的Maven构建过程进行抽象和统一
- 三套独立的声明周期
- clean:清理工作。
- Default:核心工作,如:编译、测试、打包、安装、部署等。
- site:生产报告、发布站点等。
- 核心阶段(在同一套生命周期中,运行后面的阶段时,前面的阶段都会运行)
- clean:移除上一次构建生成的文件
- Compile:编译项目源代码
- Test:使用合适的单元测试框架运行测试
- package:将编译后的文件打包,如jar、war等
- Install:安装项目到本地仓库
模块拆分:将大型项目根据场景分为不同的maven模块
Maven的打包方式
- Jar:普通模块打包,SpringBoot项目基本都是jar包(内嵌Tomcat运行)
- war:普通web程序打包,需要部署在外部的tomcat服务器中运行
- pom:父工程或聚合工程,该模块不写代码,仅进行依赖管理
继承:
- 解决多模块依赖重复的问题,创建父工程来加载共同依赖,子工程直接引入父工程即可
- 通过<parent>xxx</parent>来实现maven的继承
- 实现:
- 创建父功能,设置打包方式为pom(默认为jar)
- 在子工程的pom.xml中配置继续关系,配置<parent>xxx</parent>和<relativePath>path</relativePath>
- 注意:父工程和子工程都配置了同一个依赖的不同版本,以子工程的为准。
- 版本锁定:在maven中,可以在父工程中通过<dependencyManagement>来统一管理依赖版本。此时子工程引入依赖时,无需指定<version>版本号
- Maven自定义属性
- 父工程:
- <properties><xxx.version>x.x.x</xxx.version></properties>
- <version>${xxx.version}></version>
- 父工程:
聚合
- 分模块后打包需要依次手动打包,聚合就是用来解决此问题,将多个模块组织成一个整体,同时进行项目的构建。
- 聚合工程:
- 一个不具有业务功能的空工程(有且仅有一个pom文件)
- 通过<modules><module>项目路径</module></modules>
私服
Sonatype Nexus Repository Manager(开源的maven私服)搭建
私服仓库类型
- central仓库: 从中央仓库拉取的依赖
- Release仓库:发行版本仓库,存储功能趋于稳定、当前更新停止,可以用于发行的版本。
- Snapshot仓库:发行版本仓库,存储功能不稳定、尚处于开发中的版本。
Maven中的settings.xml配置私服地址,私服用户名及密码
私服配置:
1
2
3
4
5
6
7
8
9
10
11
12<servers>
<server>
<id>x</id>
<username>x</username>
<password>x</password>
</server>
<server>
<id>x</id>
<username>x</username>
<password>x</password>
</server>
<servers>项目pom配置(用于上传):
1
2
3
4
5
6
7
8
9
10<distributionManagement>
<repository>
<id>x</id>
<url>x</url>
</repository>
<snapshotRepository>
<id>x</id>
<url>x</url>
</snapshotRepository>
</distributionManagement>项目pom配置(用于下载):
1
2
3
4
5<mirror>
<id>xxx</id>
<mirrorOf>xxx</mirrorOf>
<url>xxx</url>
</mirror>私服配置(用于上传):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<profile>
<id>xxx</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<profile>
<repositories>
<repository>
<id>x</id>
<url>x</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
通过maven的deploy来上传制品与下载
Tomcat
介绍
- Tomcat是一个免费的轻量级Web服务器,支持Servlet/JSP少量JavaEE规范。
- JavaEE技术规范(13项):JDBC、JNDI、EJB、RMI、JSP、Servlet、XML、JMS、Java IDL、JTS、JTA、JavaMail、JAF。
- Tomcat也被称为Web容器或者Servlet容器,Servlet程序需要依赖于Tomcat才能运行
- 项目结构
- 下载安装此处不再赘述
- 修改端口:conf/server.xml中
- 项目部署:将项目放置在webapps目录下,即部署完成
SpringBoot
- Springboot项目的创建及快速上手(略,到时候新开blog记录)
- 起步依赖:
- spring-boot-starter-web:包含了web应用开发所需要的常见依赖。
- spring-boot-starter-test:包含了单元测试所需要的常见依赖。
- 官方提供的starter: https://docs.spring.io/spring-boot/docs/2.7.4/reference/htmlsingle/#using.build-systems.starters
- 请求响应解析
- Springboot中的DispatcherServlet实现了Servlet接口,所有请求由Servlet转给controller处理,处理完成后再由Servlet返回给用户,DispatcherServlet在此起前端控制器效果
- 获取请求数据:Tomcat将解析的http请求信息封装为HttpServletRequest对象
- 设置响应数据:Java代码可以创建HttpServletResponse对象,并实现响应效果
请求与响应
- POSTMAN的基本使用:https://www.postman.com/
- 创建Controller文件
- controller文件夹下创建NameController.java,类名上绑定@RestController注解
- 在NameController.java内定义成员方法,方法名上绑定@RequestMapping注解,并定义路径
- 简单参数获取
- 原始方式(繁琐,了解即可):request.getParameter(“name”):
- Springboot方式:
- controller方法中的参数名设置为与形参变量名相同,定义形参即可接受参数。
- 如果方法形参名称与请求参数名称不匹配,可以使用@RequestParam完成映射
- 如@RequestParam(name=“name) String username)
- RequestParam中有默认属性required,代表参数必选
- 获取请求
- 实体参数获取
- 简单实体对象:请求参数名与形参对象属性名相同,定义POJO接收即可
- 复杂实体对象:请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
- 数组集合参数
- 数组参数:请求参数名与数组名称相同且请求参数为多个,定义数组类型即可接收参数
- 集合参数:请求参数名与数组名称相同且请求参数为多个,@RequestParam绑定参数关系
- 日期参数:使用@DateTimeFormat注解完成日期参数格式转换,参数不可传空
- @DateTimeFormat(pattern = “yyyy-MM-dd HH:mm:ss”) LocalDateTime localDateTime
- Json参数:
- JSON数据键名与形参对象属性名相同,定义形参接收参数,@RequestBody绑定参数关系
- 路径参数:
- 通过请求URL直接传递参数,使用{…}来标识该路径参数,@PathVariable绑定参数关系
- 支持多个路径参数同时使用
- 实体参数获取
- 设置响应
- ResponseBody
- 使用类型:方法注解或类注解,用于Controller方法上或类
- 作用:将方法返回值直接响应,如果返回值类型是实体对象/集合,将会转换为Json格式响应
- 说明:@RestController = @Controller+@ResponseBody
- 统一响应结果,设置public class Result,成员变量有code、msg、data三部分
- ResponseBody
分层解耦
- 三层结构
- Controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据
- Service:业务逻辑层,处理具体的业务逻辑
- Dao:数据访问层(Data Access Object),也叫持久层,负责数据库访问操作,包括数据的增、删、改、查
- 分层解耦
- 内聚:软件中各个功能模块内部的功能联系。
- 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
- 软件设计原则:高内聚低耦合。
- 控制反转(IOC,inversion of Control):对象的创建控制权由程序自身转移到外部(容器)
- 依赖注入(DI,dependency Injection):容器为应用程序提供运行时所依赖的资源
- Bean对象:IOC容中创建、管理的对象,称之为bean
- IOC & DI入门
- Service层和Dao层的实现类,增加@Component注解,交给IOC容器管理
- 为Controller及Service注入运行时依赖的对象,在成员方法上增加@Autowired注解,不再通过new来创建对象,此处的成员变量类型需要用接口类型来定义。
- IOC详情
- 要把某个对象交给IOC容器管理,需要在类上加如下注解:
- @Component,不属于以下三类时候,用此注解,可以通过value赋值
- @Controller,是Component的衍生注解,标注在控制器上,可以通过value赋值
- @Service,是Component的衍生注解,标注在业务类上,可以通过value赋值
- @Repository,是Component的衍生注解,标注在数据访问类上,(与Mybatis整合,用的比较少),可以通过value赋值
- Bean组件扫描
- 声明bean的四大注解,要想生效,还需要被组件扫描注解@ComponentScan扫描
- @ComponentScan注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解@SpringBootApplication中,默认扫描的范围是启动类所在包及其子包
- 如果手动指定@ComponentScan,需要value赋值数组形式来指定所有的包
- 要把某个对象交给IOC容器管理,需要在类上加如下注解:
- DI详解
- @Autowired注解,默认按照类型注入,如果存在多个相同类型的bean,将会报错
- 解决方案:
- @Primary:想让哪个bean生效就加这个注解
- @Qualifier:在成员变量声明处加这个注解指定value为想依赖注入的bean名称,value格式为类名但是首字母不大写
- @Resource:默认按照bean名注入,在成员变量声明处加这个注解指定name为想依赖注入的bean对象,value格式为类名但是首字母不大写
- @Resource与@AutoWired区别
- @AutoWired是Spring框架提供的注解,@Resource是JDK提供的注解
- @AutoWired按照类型注入,@Resource按照名称注入
配置文件
- applications.properties + @value(“${key}”)
- applications.yml
- 注意事项
- 大小写敏感
- 数值前有空格作为分隔符
- 使用锁紧表示层级关系,缩进时不允许使用Tab,只能用空格
- 锁进的空格数组不重要,只要相同层级的元素左侧对齐即可
- #表示注释,从这个字符一直到行尾都会被忽略
- 注意事项
配置优先级
配置
- 文件属性配置:application.properties>application.yml(主流)>application.yaml
- java系统属性配置:-Dserver.port=9000
- 命令行参数配置:–server.port=10010
优先级:命令行参数>java系统属性配置>文件属性配置
@ConfigurationProperties
- pom引入spring-boot-configuration-processor依赖
- 配置文件中key的名字和实体类成员变量需要和文件一致
- 实体类实现get和set方法,加@DATA
- 实体类交给IOC管理,加@Component
- 实体类需要绑定前缀,加@ConfigurationProperties(“prefix”)
- 实现类需要依赖注入, 加@AutoWired
登录认证
- cookie机制:
- 优点:http协议自带支持,无需前端手动添加cookie
- 缺点:
- 移动端APP无法使用Cookie
- 不安全,用户可以自己禁用Cookie
- Cookie不能跨域(同源:协议、IP/域名、端口)
- Session机制(基于Cookie实现):
- 优点:存储在服务端、安全
- 缺点:
- 服务器集群环境下无法直接使用Session
- 移动端APP无法使用Session
- 不安全,用户可以自己禁用
- 不能跨域(同源:协议、IP/域名、端口)
- 令牌技术
- 优点:
- 支持PC端、移动端
- 解决集群环境下的认证问题
- 减轻服务器端存储压力
- 缺点:需要自己实现
- 优点:
- JWT
- 简介
- Json Web Token:https://jwt.io
- 特点:简单、自包含
- 三大组成(各部分均base64):
- Header :记录令牌类型。
- Payload:携带一些自定义信息、默认信息等。
- Signature:防止Token被篡改、确保安全性。(Header.Payload,secret)
- 将Header、Payload,并加入指定秘钥,通过指定签名算法计算而来。
- 使用:
- 引入依赖
- 生成Token
- 生成JWT并设置签名算法及秘钥
- 设置Payload并存储Map类型Payload
- 设置Token有效期
- 生成令牌
- 解析Token
- 设置秘钥
- 解密内容
- 前后端交互
- 后端
- 生成Token,并在response中返回
- 在每次登录请求中,校验令牌信息
- 前端:存储Token,并在后续访问中携带令牌
- 后端
- 简介
Filter过滤器
- 概述
- FIlter过滤器,是javaweb三大组件(Servlet、Filter、Listener)之一。
- 可以把对资源的请求拦截下来,从而实现对应的功能。
- 一般用于完成通用校验,比如登录验证、编码处理、敏感字符处理等。
- 入门
- 定义Filter:
- 定义一个类,实现WebMvcConfigurer接口,并重写其所有方法(init、doFilter、destroy)。
- doFilter中放行请求filterChain.doFilter(servletRequest,servletResponse);
- 定义Filter:
- 配置Filter:
- Filter实现类上加上@WebFilter注解,配置拦截资源的路径,如@WebFilter(“/*”)。
- Springboot启动类上加@ServletComponentScan开启Servlet组件支持。
- 配置Filter:
- 细节:
- 执行流程
- 执行放行前过滤逻辑(filterChain.doFilter之前)
- 放行操作(filterChain.doFilter)
- 放行后逻辑(filterChain.doFilter之后)
- 拦截路径
- Filter可以根据需求,配置不同的拦截资源路径@WebFilter(urlPatterns=”/*”)
- 拦截路径
- 拦截具体路径:/login
- 目录拦截:/admin/*
- 拦截所有:/*
- 过滤器链
- 一个web应用中,可以配置多个过滤器链,这多个过滤器就形成了一个过滤器链
- 多过滤器执行顺序:Filter1放行前逻辑->Filter1放行->Filter2放行前逻辑->Filter2放行->访问API资源->Filter2放行后逻辑->Filter1放行后逻辑
- 注解配置的FIlter,优先级按照过滤器类名(字符串)的自然顺序排序
- 执行流程
Interceptor拦截器
- 概述
- 概念:是一种动态拦截方法调用的机制,类似于过滤器,Spring框架中提供的,用来动态拦截控制器方法的执行。
- 作用:拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码。
- 快速入门
- 定义拦截器:
- 定义类实现HandlerInterceptor接口,并重写其所有方法,增加@Component
- preHandle:controller目标资源执行前执行,return ture放行/ return false不放行
- postHandle:目标资源方法执行后执行,controller执行后放行
- afterCompletion):视图渲染完毕后执行,最后执行
- 定义类实现HandlerInterceptor接口,并重写其所有方法,增加@Component
- 注册拦截器
- public class WebConfig implements WebMvcConfigurer{},增加@Configuration
- 创建拦截器类的成员变量,并增加@AutoWired
- 重写addInterceptors(InterceptorRegistry registry)方法,并在其中写明拦截策略,如registry.addInterceptor(实现类).addPathPatterns(“/**”);
- 拦截路径
- 方法:
- addPathPatterns:拦截哪些路径
- excludePathPatterns:不需要拦截哪些路径
- 路径:
- /*:一级路径
- /**:任意级路径
- 方法:
- 执行流程
- request->filter->DispatcherServlet(request)->Interceptor->controller->Interceptor(放行)->DispatcherServlet(response)->filter(放行)->response
- FIlter与Interceptor区别
- 接口规范不同:Filter需要实现Filter接口,而拦截器实现HandlerInterceptor接口
- 拦截范围不同:过滤器Filter拦截所有资源,而Interceptor只会拦截Spring环境资源的
- 定义拦截器:
全局异常处理
- 在Controller的所有方法中进行try、catch处理(臃肿)-不推荐
- 全局异常处理器(简单、优雅)-推荐
- 定义异常处理类,增加@RestControllerAdvice注解
- 重写ex(Exception ex){return Result.error(“error info”)}
- ex方法上增加注解@ExceptionHandler(Exception.class)
事务管理
- Spring事务管理
- @Transactional
- 位置:业务层的方法上、类上、接口上,常用与存在多次数据写操作的某个方法。
- 将当前方法交给Spring进行事务管理。
- 方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务
- 事务管理日志:logging.level.org.springframework.jdbc.support.JdbcTransactionManager:debug
- 事务进阶
- rollbackFor
- 默认情况下,只有出现RuntimeException及其子类才回滚异常。
- 如果开启全部异常均回滚需要如下配置:@Transactional(rollbackFor=Exception.class)
- propagation:配置事务的传播行为
- 事务传播行为:当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制
- @Transactional(propagation=propagation.Type),Type类型如下:
- REQUIRED:(默认值)需要事务,有则加入,无则新建
- REQUIRES_NEW:无论有无事务均需要新建
- SUPPORTS:支持事务,有则加入,无则在无事务状态中运行
- NOT_SUPPORTS:不支持事务,在无事务状态中运行,如果有事务则挂起事务
- MANDATORY:必须有事务,否则抛异常
- NEVER::必须没事务,否则抛异常
- rollbackFor
AOP
- 概述
- Aspect Oriented Programming(面向切面编程),其实就是面向方法编程
- 动态代理是实现AOP的最主流实现方式,SpringAOP是 Spring框架的高级技术,旨在管理bean对象的过程中,通过底层动态代理机制,对特定的方法进行编程。
- 快速入门
- 引入Spring AOP依赖:spring-boot-starter-aop
- 编写AOP类,增加@Component和@Aspect注解
- 传参ProceedingJoinPoint proceedingJoinPoint
1
2object obj = proceedingJoinPoint.proceed()方法时继续执行
proceedingJoinPoint.getSignature():返回方法签名 - 方法前标记生效范围,如
1
@Around("execution(* com.yd0ng.service.*.*(..))")
- 实现注入前代码、object obj = proceedingJoinPoint.proceed()、实现注入后代码
- 使用场景
- 记录操作日志
- 权限控制
- 事务管理
- 优势:
- 代码无侵入
- 减少重复代码
- 提高开发效率
- 维护方便
- AOP核心概念
- 连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)
- 通知:Advice,指哪些重复的逻辑,也就是共性方法(最终体现为一个方法)
- 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用
- 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
- 目标对象:Target,通知所应用的对象
- AOP执行流程:AOP运行的不再是原始对象,而是动态代理对象。
- 先执行共性逻辑前部分代码,然后执行原始对象代码,最后执行后半部分代码
- 通知类型
- @Around:环绕通知,此注解标注的通知方法在目标方法前后都执行,后部分有异常不执行
- 需要自己调用 proceedingJoinPoint.proceed()继续执行原始代码
- 方法返回值比如为Object,来接收原始方法的返回值。
- @Before:前置通知,此注解标注的通知方法在目标方法前被执行
- @After:后置通知,此注解标注的通知方法在目标方法节后被执行,无论是否有异常
- @AfterReturning:返回后通知,此注解标注的通知方法在目标方法被执行后执行,有异常不会执行
- @AfterThrowing:异常后通知,此注解标注的通知方法发生异常后执行
- @Around:环绕通知,此注解标注的通知方法在目标方法前后都执行,后部分有异常不执行
- 通知顺序
- 切面内:@Around(前)>@Before>@AfterReturning/@AfterThrowing>@After>@Around(后,无异常)
- 多个切面时
- 默认切面执行顺序和类名自然排序有关
- Before:1>2>3>4>5
- After:5>4>3>2>1
- 可以增加@order(num)来指定各切面执行顺序
- 默认切面执行顺序和类名自然排序有关
- 切入点表达式
- 描述切入点方法的一种表达式
- 作用:主要用来决定项目中的哪些方法需要加入通知
- 常见形式:
- execution:根据方法的签名来匹配
- execution(访问修饰符 返回值 包名.类名.?方法名(方法参数) throws 异常?)
- 带?的表示可省略的部分
- 访问修复符:可省略,比如public、protected
- 包名.类名:可省略但是不建议省略,否则匹配不够精准
- throws:可省略(注意是方法上声明抛出的异常,不是实际抛出的异常)
- 通配符
- 单个*表示匹配任意返回值、包名、类名、方法名、任意类型的一个参数
- ..两个连续的.可以通配任意层级的包,或任意类型、任意个数的类型
- 带?的表示可省略的部分
- 单execution中可以用逻辑运算符来匹配多个切入点表达式
- 书写建议:
- 业务方法命名规范:查询类为findXXX,更新类为updateXXX
- 描述切入点方法通常基于接口描述,增强拓展性
- 尽量缩小切入点的范围
- execution(访问修饰符 返回值 包名.类名.?方法名(方法参数) throws 异常?)
- @annotation():根据注解匹配
- annotation(FullClassName)
- 自定义注解:
- 新建Annotation类型的class文件
- 类名加上元注解
- @Retention(RetentionPolicy.RUNTIME):运行时生效
- @Target(ElementType.METHOD):方法生效
- execution:根据方法的签名来匹配
- 简化
- 定义private/public成员方法pt,如private void pt(){}
- 为pt增加注解@Pointcut,其为切入表达式注解,用于抽取公共切入表达式
- @Pointcut的value为表达式值,如execution(* com.yd0ng.service..(..))
- @Around(“pt()”)
- 连接点
- Spring中用JoinPoint抽象了连接点,用它可以获得方法的相关信息,如目标类名、方法名、方法参数等
- 对于@Around通知,只能使用ProceedingJoinPoint;对于其他通知,只能使用JoinPoint(ProceedingJoinPoint的父类)
- ProceedingJoinPoint常用方法
- String xxx = joinPoint.getTarget().getClass().getName():获取目标类名
- String xxx = joinPoint.getSignature():获取目标方法签名
- String xxx = joinPoint.getSignature.getName():获取目标方法名
- Object[] args = joinPoint.getArgs():获取目标方法运行参数
- Object res = joinPoint.proceed():执行原始方法,获取返回值(仅环绕通知)
Bean管理
- 获取bean
- 默认情况下,Spring项目启动时,会把bean都创建好放在IOC容器中,如果想要主动获取核心bean,使用如下方法
- IOC容器对象注入: private ApplicationContext applicationContext;,加@AutoWired
- 根据name获取bean:Object Bean(String name)
- 根据类型获取bean:
T getBean(Class requiredType) - 根据name获取bean(带类型转换):
T getBean(String name, Class requiredType)
- IOC容器对象注入: private ApplicationContext applicationContext;,加@AutoWired
- 默认情况下,Spring项目启动时,会把bean都创建好放在IOC容器中,如果想要主动获取核心bean,使用如下方法
- Bean作用域:Spring支持五种作用域,后三种在web环境才生效:
- 类型
- singleton:容器内同名称的bean只有一个实例(单例),此为默认配置
- prototype:每次使用该bean时创建新的实例(非单例)
- request:每个请求范围内会创建新的实例(Web环境中,了解)
- session:每个会话范围内会创建新的实例(Web环境中,了解)
- application:每个应用范围内会创建新的实例(Web环境中,了解)
- 设置作用域:@Scope(“作用域类型”)
- 延迟初始化:@Lazy,第一次使用时才会初始化bean,项目启动时不初始化bean
- 类型
- 第三方bean
- 如果要管理的bean对象来自第三方(不是自定义的),是无法用@Component及衍生注解声明bean的,这时候需要用到注解@Bean,@Bean注解的value/name属性可以给三方Bean指定名称(不指定名称的话默认是方法名)。
- 使用方法
- 方法1:在SpringBoot的启动类当中,定义一个方法,方法名随意,给方法加上@Bean注解,该方法的返回对象是要管理的bean对象,如public SAXReader saxReader(){ return new SAXReader();}
- 方法2:新建配置类,类增加@Configuation,类中定义一个方法,方法名随意,给方法加上@Bean注解,该方法的返回对象是要管理的bean对象,如public SAXReader saxReader(){ return new SAXReader();}
- 如果三方bean需要依赖其他bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装载。
起步依赖与自动配置
起步依赖
- SpringBoot的起步依赖本质上就是maven的依赖传递
- 概述:SpringBoot的自动配置就是当SpringBoot容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要手动声明,从而简化了开发,省去了繁琐的配置操作。
- 三方bean引入
- @Component组件扫描:三方bean引入后不会直接生效,需要在启动类增加注解@ComponentScan开启三方Bean扫描
- @Import导入:在启动类增加注解@Import,使用@Import导入的类会被Spring记载到IOC容器中,导入形式有以下几种:
- 导入普通类
- 导入配置类
- 导入ImportSelector接口实现类
- 三方类EnableXxxx注解
- 源码跟踪
- 从@SpringBootApplication入手
- @SpringBootConfiguration:与Configuration作用相同,声明当前是一个配置类
- @ComponentScan:组件扫描,默认扫描当前引导类所在包及其子包
- #EnableAutoConfiguration:SpringBoot自动化配置核心注解
- 底层是Import(AutoConfigurationImportSelector.class),实现了selectImports接口
- 实际是加载了spring.factories(2.7.0之前)和AutoConfiguration.imports
- Conditional注解:按照一定的条件进行判断,满足条件后才进行依赖注入
- ConditionalOnClass(name):判断环境中是否有name对应字节码文件,才注册bean到IOC容器
- ConditionalOnMissingBean(name/type):判断环境中没有对应的bean(类型或名称),才注册bean到IOC容器
- ConditionalOnProperty(name,havingValue):判断配置文件中有对应属性和值,才注册bean到IOC容器
- 从@SpringBootApplication入手
- 自定义starter
- 起步依赖:functionName-spring-boot-starter
- 自动配置:functionName-spring-boot-autoconfigure
- 在其中定义自动配置文件META-INF/spring/xxxx.imports
MYSQL
- SQL分类:DDL、DML、DQL、DCL
- DDL:数据定义语言,用来定义数据库对象(数据库、表、字段)
- show、use、create、drop、desc
- DML:数据操作语言,用来对数据库表中的数据进行增删改
- insert、delete、update
- DQL:数据查询语言,用来查询数据库中表的记录
- select
- DCL:数据控制语言,用来创建数据库用户、控制数据库的访问权限
- DDL:数据定义语言,用来定义数据库对象(数据库、表、字段)
- create table相关的约束
- not null
- unique
- primary key(auto_increment自增)
- default
- foreign key
- select
- group by having
- 多表设计
- 一对多
- 物理外键:foreign key(外键字段名) references 主表(字段名)
- 逻辑外键:在业务层逻辑中,解决外键关联,不再依靠数据库层面物理外键
- 一对一
- 拆分高频读取信息和低频读取信息到两个表,在任意一方加入外键,关联另一方的主键,并设置外键为唯一的unique
- 多对多
- 建立第三张中间表,中间表至少包含两个外键,分别关联另外两个表的主键
- 一对多
- 多表查询
- 连接查询
- 内连接:查询A、B交集部分数据(不包含null)
- 隐式内连接:from tb1,tb2 where tb1.field = tb2.field
- 显式内连接:from tb1 inner join tb2 on tb1.field = tb2.field
- 外连接:
- 左外连接:查询左表所有数据(完全包含左表,包含null)
- from tb1 left outer join tb2 on tb1.field = tb2.field
- 右外连接:查询右表所有数据(完全包含右表,包含null)
- from tb1 right outer join tb2 on tb1.field = tb2.field
- 左外连接:查询左表所有数据(完全包含左表,包含null)
- 内连接:查询A、B交集部分数据(不包含null)
- 子查询
- select * from t1 where column1 = (select column1 from t2 where xxx)
- 分类
- 标量子查询:
- 子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式
- 常用操作符:=、<>、>、>=、<、<=
- 列子查询:
- 子查询返回的结果是一列(可以是多行)
- 常用操作符:in、not in
- 行子查询:
- 子查询返回的结果是一行(可以是多列)
- 常用操作符:=、<>、in、not in
- 表子查询:
- 子查询返回的结果是多行多列,常作为临时表
- 常用的操作符:in
- 标量子查询:
- 连接查询
- 事务
- 定义
- 是一组操作的集合,是一个不可分割的工作单位。
- 事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功、要么同时失败。
- 默认Mysql的事务是自动提交的,可以手动开启事务:
- 开启事务:start transaction;/begin;
- 然后执行对应的批量操作,如delete xxx; delete xxx;
- 提交事务:commit;
- 回滚事务:rollback;
- 开启事务:start transaction;/begin;
- 四大特性
- 原子性:事务是不可分割的最小单元,要么全部成功、要么全部失败。
- 一致性:事务完成时,必须使所有的数据都保持一致状态。
- 隔离性:数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境中运行。
- 持久性:事务一旦提交或回滚,它对数据库中的改变就是永久的
- 定义
- 索引
- 索引是帮助数据库高效获取数据的数据结构。
- 无索引情况下,全表扫描
- 有索引情况下,使用特定的数据结构优化数据,如二叉搜索树
- 语法:
- 创建索引:create (unique) index index_name on table_name(column_name,…);
- 查看索引:show index from table_name;
- 删除索引:drop index index_name on table_name;
- 其他
- 主键字段,在建表时,会自动创建主键索引。
- 添加唯一约束unique时,数据库实际上会添加唯一索引。
- 优缺点:
- 优点:提升查询和排序效率
- 缺点:占用存储空间、降低增删改的效率
- 结构
- Mysql支持的索引结构比较多,如Hash索引、B+Tree索引、Full-Text索引等,默认使用B+Tree作为索引。
- B+Tree(多路平衡搜索树)
- 索引是帮助数据库高效获取数据的数据结构。
Mybatis
- mybatis是一款优秀的持久层框架,用于简化JDBC的开发
简单入门
- 准备工作:Springboot工程、数据库表user、实体类User
- 创建项目时引入Mybatis相关依赖(Mybatis Framework、MySQL Driver)
- 配置Mybatis(application.properties)
- 编写SQL语句(注解/XML)
- 新建接口名为ClassNameMapper,接口上增加@Mapper注解
- 新建方法名为MethodName,方法上增加@Select等注解,设置value为对应SQL语句即可。
- jdbc连接使用
- 数据库连接池
- lombok
- lombok能通过注解的形式自动生成构造器、setter/getter、equals、hashcode、toString等方法,并可以自动化生成日志变量,简化java开发,提高效率。
- 常用注解
- @Getter/@Setter:为所有的属性提供get/set方法
- @ToString:会给类自动生成易阅读的toString方法
- @EqualsAndHashCode:重写equals和hashCode
- @Data:生成setter、getter、toString、equals和hashCode
- @NoArgsConstructor:生成无参构造方法
- @AllArgsConstructor:生成全参构造方法(除外static字段)
- 原理:在编译时根据注解自动生成对应方法
- 预编译#{}的好处
- 性能更高:一次sql编译,后续sql直接执行
- 更安全:防止sql注入
- XML映射文件
- xml映射文件的名称需要与Mapper接口保持一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)
- XML映射文件的namespace属性为Mapper接口全限定名一致
- XML映射文件中sql的id与Mapper接口中的方法名保持一致,并保持返回类型一致
- Mybatis的动态sql
1
2
3
4
5
6
7
8
9
10
11
12
13<where>condition</where>
<if test="name!=null">name=#{name}</if>
<set>condition</set>
<foreach collection="names" item="name" separator="," open="(" close=")">
#{name}
</foreach>
<sql id="sql_name">sql_query_statement</sql>
<include refid="sql_name" /> - 其他:
- 简单sql用注解、复杂sql用xml
- 拿主键,@Option(keyProperty=”key”,useGeneratedKeys=true)
- 数据库字段名与model成员变量名映射不一致
- 起别名:select xxx as xxx
- 手动结果映射@Results({@Result(column=””,property=””)})
- 开启驼峰命名开关,camel=true(推荐),命名格式需要规范
- XML中string!=null and string!=’’
本文作者:
yd0ng
本文链接: https://blog.yd0ng.top/2025/04/29/JAVA-Web%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!
本文链接: https://blog.yd0ng.top/2025/04/29/JAVA-Web%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!