SpringBoot学习

Spring全家桶

web:Spring Web MVC 、Spring MVC、Spring Web Flux
持久层:Spring DataSpring Data JPA、Spring Data RedisSpring Data MongoDB
安全校验:Spring Security
构建工程脚手架:Spring Boot
微服务:Spring Cloud

Spring以及Springboot是什么

Spring目的:为了简化开发,解决企业级开发的复杂性而创建;

Spring简化开发的关键策略:

基于POJO的轻量级和最小侵入性编程;
通过控制反转(IOC),依赖注入(DI)和面向接口来实现松耦合;
基于切面(AOP)和惯例进行声明式编程;
通过切面和模板(Template)减少样式代码;

注:
POJO = 普通Java对象(Plain Old Java Object

约定大于配置:

约定大于配置;
	“约定大于配置”(Convention Over Configuration,简称CoC)是软件工程领域的一种设计理念,尤其在现代Web框架中广泛采用,Spring Boot便是其中的典范。这一理念主张在设计框架或系统时,开发者应当遵循预设的约定,而无需进行大量显式的配置。这样做可以简化开发流程,减少配置错误,提高开发效率,让开发者能更快地专注于业务逻辑的实现。

“约定大于配置”在Spring Boot中的体现
自动配置:Spring Boot通过一系列的starter依赖和自动配置类,自动为项目添加常见的功能,如Web服务、数据库连接、安全控制等,而无需手动配置复杂的XML文件或繁琐的Java配置。例如,添加spring-boot-starter-web依赖后,Spring Boot会自动配置嵌入式Tomcat服务器、Spring MVC框架等。
默认启动类:Spring Boot应用程序通常有一个主类,标注@SpringBootApplication注解,这表明该类是应用程序的入口点。Spring Boot会扫描该类及其子包,自动发现和配置Bean。开发者不需要显式地指定每个组件的位置。
环境变量和配置文件:Spring Boot会自动读取application.properties或application.yml配置文件中的属性,以及环境变量,用于调整应用的行为,而不需要在代码中硬编码配置信息。
内置服务器:Spring Boot默认集成了TomcatJettyUndertow等内嵌服务器,开发者无需额外配置服务器即可运行应用。
日志管理:Spring Boot会自动配置日志系统,如Logback或log4j,开发者只需关注日志输出级别和格式,而不需要关心具体的日志框架配置。
健康检查和监控:Spring Boot Actuator模块提供了开箱即用的健康检查和应用监控功能,无需额外配置即可启用。
实际应用场景:
假设你正在构建一个新的Spring Boot项目,按照“约定大于配置”的原则,你只需要添加必要的starter依赖,比如spring-boot-starter-data-jpa和spring-boot-starter-web,并定义一些实体类和Repository接口。Spring Boot会自动配置JPA和Web环境,包括数据库连接、事务管理、RESTful API支持等,而无需编写复杂的配置代码。

总的来说,“约定大于配置”使得Spring Boot项目更加简洁、易维护,降低了学习和使用的门槛,让开发者能够快速上手,专注于业务逻辑的实现而非框架配置的细节。
自动装载;
 需要进一步修改的内容。。。。。TODO

SpringBoot的优点:

帮助所有Spring开发者快速入门
开箱即用,提供各种默认配置来简化项目配置
内嵌容器(tomact)简化web项目
没有冗余代码生成和XML配置的要求

Springboot项目创建

微服务:一种架构风格,将开发一个应用变成一系列小服务组合,可通过HTTP(RPC)方式互相通信。
单体应用架构:将一个应用的所有应用服务都封装在一个应用中,各个功能放在一个war包里。
微服务架构:将每个功能元素都独立出来,并将独立出来的功能元素动态组合,也就是对功能元素的复制,而不是整个应用的复制;

创建一个springboot项目
两种方式:Springboot官网版本 / IDEA自己创建(IDEA集成了这个网站);

Springboot官网创建

中文文档:https://springdoc.cn/spring-boot/
官网文档:https://spring.io/projects/spring-boot#learn
Springboot 最新版本是:3.2.2
当前创建页面只支持以下图展示内容:
在这里插入图片描述

IDEA创建现存版本

IDEA创建springboot项目
文件 – 新建 – 项目 – Spring Initializr
通过该方法java版本只有17和21 两种,经过验证:jdk1.8 与java17不匹配,可以和java21匹配;

项目注意事项

@SpringbootApplication
springboot中的启动类是application,其他的类都得在该启动类的同级目录下;
启动类application,程序的主入口,本身就是Spring的一个组件;
所有springboot的依赖都采用 spring-boot-starter 这个前缀;
项目打包:package

在这里插入图片描述

IDEA创建旧jdk版本项目

创建项目遇到的问题:
	java语言只有1721版本,jdk是1.8 如何解决?
解决:
	参考博客:https://zhuanlan.zhihu.com/p/668876308
	该博客的评论部分:把项目上面的start.spring.io 改成 start.aliyun.com即可

在新建项目的页面,修改链接;
在这里插入图片描述

application.properties配置修改

# web服务端口号修改
server.port = xxx
# banner修改
需要在线生成网站处理:
https://www.bootschool.net/ascii-art/search
在resource/banner.txt文件
将网站生成的图片放在该文件中。

在这里插入图片描述

自动配置原理分析

1 pom.xml

通过spring-boot-starter-parent →spring-boot-dependencies 该包管理的大量的jar包版本;

2 启动器

pom文件中的有大量的启动器(含有starter的包),也就是springboot的启动场景;
主程序
@SpringBootApplication 标注这个类是springboot应用;
SpringApplication.run方法 启动 springboot项目;

3 主程序

1. 主程序
@SpringBootApplication 标注这个类是springboot应用;
SpringApplication.run方法 启动 springboot项目;

2. 注解
@SpringBootConfigurationSpringboot的配置
	@Configuration Spring配置类
	@Component 说明是Spring的一个组件
@EnableAutoConfiguration 自动配置
	@AutoConfigurationPackage 自动配置的包
		@Import({Registrar.class}) 自动装配 包注册
	@Import({AutoConfigurationImportSelector.class})  自动配置导入选择
		List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
		// 获取所有的配置

结论:
springboot所有自动配置都是在启动的时候扫描并加载:spring.factories 
所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入了 对应的 start ,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功!

在这里插入图片描述

springboot项目启动

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

需要了解清楚,点击运行之后的所有内容如何运行启动的?


yml配置文件

springboot配置文件可以写的所有内容:
https://docs.spring.io/spring-boot/docs 官网地址没有找到
https://www.cnblogs.com/tangge/p/9609165.html 博客找到了

注意内容:

1 SpringBoot采用全局配置文件,名称是固定的;
	application.properties  key=value
	application.yml  key: value
2 yml比propreties存放对象更方便
	yml:
	student:
		name: dahua
		age: 3
	propreties:
	student.name = dahua
	student.age = 3
3 yml的行内写法
	student:{name,age}
4 yml存储数组(/列表)
	pets:
		- dog
		- cat
		- pig
	行内写法:
	pets:[dog,cat,pig]
5   对空格要求极为严格
	可以注入到项目的配置类
6 yml:可以直接给实体类赋值
	核实是@ConfigurationProperties
	@ConfigurationProperties作用:
	将配置文件中配置的每一个属性的值,映射到这个组件中;
	告诉springBoot将本类中的所有属性和配置文件中相关的配置进行绑定
	对应参数 prefix = “person” :将配置文件中的person下面的所有属性一一对应;
	只有这个组件是容器中的组件,才能使用容器提供的@Configurationproperties功能。
7 指定特殊的配置文件,xxx.properties 而不是默认配置文件application.properties
	@PropertySource(value = “classpath:xxx.properties”)
	类的具体属性前,@Value("${配置文件中所要设置的值}")	

多种配置文件

方式1:四个配置文件在相同路径下

配置文件所在路径:
	项目/src/main/resources/application-xxx.yml
配置文件有:
application.yml
application-dev.yml
application-prod.yml
application-test.yml
三种配置文件,以及一个总的配置文件;

application.yml文件内容:
spring:
  profiles:
    active: dev
可以正常启动application-dev.yml配置文件;

方式2:多个配置文件在不同的文件夹下

1. yml文件路径
整体路径为:resources/config/xxx/application.yml 以及 logback-spring.xml resources/config/mybatis-config.xml
其中xxx一般为:dev-本地开发;prod-线上环境;test-测试环境;

2. pom.xml配置
需要在配置文件中添加如下内容,才可以在idea右侧的界面中出现dev、prod、test的配置信息
<profiles>
        <profile>
            <id>dev</id>
            <properties>
                <profiles.active>dev</profiles.active>
            </properties>
        </profile>
        <profile>
            <id>test</id>
            <properties>
                <profiles.active>test</profiles.active>
            </properties>
        </profile>
        <profile>
            <id>prod</id>
            <properties>
                <profiles.active>prod</profiles.active>
            </properties>
            <!--默认情况-->
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
    </profiles>

3. 本地激活:
	使用哪个配置文件,通过maven选择;

4. 打包激活,需要在pom.xml进行配置
<!-- 构建配置 -->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources/config</directory>
                <excludes>
// exclude表示项目打包要排除的配置文件
                    <exclude>dev/*</exclude>
                    <exclude>prod/*</exclude>
                    <exclude>test/*</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources/config/${profiles.active}</directory>
            </resource>
        </resources>
        // 其中profiles.active参数是前文中提到的配置,通过maven选择进行打包;

Bean

AOP面向切面编程

概述

定义:
	AOP 面向切面编程,Aspect Oriented Programming。
	将复杂的需求分解为不同的切面,将散布在系统中的公共属性集中处理;
优点:
	降低模块之间的耦合度;
	更好的代码复用;
	....
特殊概念:
	切面 = 横切关注点,被模块化的抽象对象;
	通知 = 切面对象完成的工作;
	目标 = 被通知的对象
	代理 = 切面、通知、目标混合之后的对象
	连接点 = 通知要插入业务代码的具体位置
	切点 = AOP通过切点定位到连接点
实现方式:
	1 动态代理;
	2 基于Spring方式;
参考博客:https://blog.csdn.net/pedro7k/article/details/115415675

实现

动态代理

pom.xml引入项目依赖,spring-aop、spring-aspects;
创建接口interfacexx,定义方法;
创建实现该接口的类classxx,重写具体的方法(包含日志信息处理逻辑),存在较强的耦合性;
动态代理实现日志信息输出;
	涉及到内容:invocationHandler接口

动态代理核心代码:

public class invocationHandlerxxx implement invocationHandler{
// 实现InvocationHandler接口,创建动态代理对象的辅助类
	private Object object = null;
	// 接收委托都对象,使用静态代理对象的类;

	// bind对象 获取代理对象
	public Object bind(Object object){
		// 通过委托对象获取对应的代理类;
		this.object = object;
		//创建代理对象:所需参数:类加载器、委托对象的全部接口、当前的辅助类;
		// 返回内容是动态代理对象;
		return Proxy.newProxyInstance(object.getClass().getClassloader(),object.getClass().getInterfaces(),this);
	}
	@Overrid
	// 该方法写代理对象的功能,参数为代理对象、对应方法、方法参数;
	public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
		// 处理过程
		sout(method.getName()+"方法参数:"+Arrays.toString(args));
		// 调用方法本身的业务逻辑
		Object result = method.invoke(this.object,args);
		// 结果输出
		sout(method.getName()+"的结果是:"+result);
		return result;
	}
}

Spring实现AOP

添加依赖,spring-aop、spring-aspects、spring-context等,在pom.xml文件中;
定义接口interfacexxx,以及抽象方法;
定义实现类classxxx,已经普通方法;
创建切面类;

切面类:

@Slf4j
// 日志注解,使用logger对象
@Aspect
// 声明是一个切面类
@Component
// 把切面类交给IoC容器管理
public class LogsAspect {
        @Around("(execution(* com.unicom.xxx.xxx.xxx.xxx.*.*(..))))")
        // @Around 表示在方法的执行前后插入代码,即环绕通知;
        // execution 用于匹配方法的执行;
        // 表示在正则表达式匹配的所有方法 执行前后插入代码
        public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable {
        // 环绕通知方法的声明,ProceedingJoinPoint是Spring AOP中的一个连接点的接口,它允许你调用被通知的方法;
            try {
            	// 获取当前的业务跟踪信息
                ServiceTrace.BusinessTrace trace = ServiceTrace.BUSINESS_TRACE.get();
                ServiceId serviceId = null;
                if(trace == null || trace.getCover()){
                	// 获取当前执行的方法的签名 给service赋值
                    serviceId = ((MethodSignature) pjp.getSignature()).getMethod().getAnnotation(ServiceId.class);
                    //绑定 服务描述
                    if(ObjectUtils.isNotEmpty(serviceId)){
                        ServiceTrace.bind(null,serviceId.value().name());
                    }else{
                        ServiceTrace.bind();
                    }
                }else{
                    ServiceTrace.bind();
                }
                // 调用实际的方法执行,并获取返回结果。
                Object response = pjp.proceed();
                log.info(LogConstant.response_format, response);
                return response;
            } finally {
            	// 释放serviceTrace资源
                ServiceTrace.release();
            }
        }
}

// Pointcut定义切点,后续括号的参数是:匹配到所有方法的执行
@Pointcut("execution(* com.unicom.anon.sub.local.controller.*.*(..))")

// 用来声明一个后置返回通知;会在目标方法成功执行并返回结果之后执行;
// pointcut 指定通知应该应用的切点;
// returning 指定通知方法可以访问目标方法的返回值;result是目标方法返回值的别名;
@AfterReturning(pointcut = "controllerLayerPointcut()", returning = "result")
	// joinPoint 当前的连接点,被通知的方法
	// result 目标方法的返回值
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        // 获取方法名
        String methodName = joinPoint.getSignature().toShortString();
        // 记录日志
//        logger.info("Method [{}] returned with object: {}", methodName, GsonBuilderUtil.GSON_DEFAULT.toJson(result));
        AnonSubLog.log("Method [{}], returned with object: {}", methodName, GsonBuilderUtil.GSON_DEFAULT.toJson(result));
    }

实战

@Before不起作用

描述:
	给xxxAop配置了@Aspect@Order注解,但还是没有办法调用@Before修饰的方法;
分析:
	发现请求没有到达服务侧,采用的是post请求不行,但是get请求可以;
	

REST API

REST定义:
	REST = Representational State Transfer --》表述/具体的-状态-转移
	转移 = 前端与后端之间传递数据;
	状态 = 前后端传递的数据,例如删除某数据,传递的不是数据本身,而是想要修改的数据成某种状态;
	表述/具体的 = 修饰StateRESTful定义:
	xxx-ful 充满/富有xxx的;充满了“具体的状态转移”	的API;
	通过语义化的方式请求资源URL,并根据返回的语义来判断这次操作的返回类型和效果;
	
举例:前端到后端的整个过程;
前端HTML代码,通过渲染得到可视化页面,点击页面上的按钮-浏览器会发出HTTP请求,访问服务端的api接口(不是java中的接口);

案例:代码角度
创建控制类xxController,被@RequestMapping"api/xxx")
编写方法function1、function2.。。。
然后针对不同的方法采用不同的注解,@GetMapping表示获取 @PostMapping表示创建 @PUTMapping表示更新 @DelectMapping表示删除。

集成 web开发(业务核心)

静态资源导入

方式:
	通过resource/static文件夹 (现有项目就是该方式);
	通过http://localhost:8080/webjars/xxx/xxx/xxx.js 实现;
		其中webjars 等同于 /META-INF/resources/webjars/ 目录;
		pom中导入依赖实现,具体的依赖形式需要从https://www.webjars.org/ 网站查看;
	通过http://localhost:8080/xxx.js
		项目calsspath即项目/src/main/resources 其下面的目录  /resources/ /static/ /public/ 都可以放静态资源;
		各个目录的优先级:resources > static > public
	自定义静态资源目录,配置文件中写:spring.mvc.static-path-pattern=xxxx,其余配置文件都失效;
	
通过xxx查看可以有哪种方式导入静态资源:
	webMVCAutoConfiguration.java--webMvcAutoConfigurationAdaptor内部类--addResourceHandlers方法;

web首页如何定制

通过xxx查看可以有哪种方式导入静态资源:
	webMVCAutoConfiguration.java--welcomePageHandlerMapping内部类
	
放置路径:
	http://localhost:8080/webjars/xxx/xxx/xxx.js webjars =  文件路径/META-INF/resources/webjars/ 
	http://localhost:8080/xxx.js  文件路径 classpath: /resources/ /static/ /public/ 
	
classpath:/resources/template:
	在该目录下的静态页面,只能通过controller实现访问;
	但是需要加模板引擎,Thymeleaf等;
项目降springboot版本:
	修改pom文件中的parent/version。	

模板引擎

定义:
	如thymeleaf
	使用文档:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#using-thtext-and-externalizing-text
作用:
	核心是替换,将模板文件的标签字符替换成指定的业务数据,生成html文件;
跳转html页面:
	引入pom依赖 ==》通过maven官网下载:https://mvnrepository.com//resource/template/ 文件夹下添加 xxx.html
	在java路径下 写controller类,@RequestMapper("/xxx") 修饰某个方法,跳转xxx.html
	
html页面java代码中给定的值:
	java方法:
	@RequestMapper("/xxx")
	public String xxx(Model model){
		model.addAttribute("msg","cptbtptpbcptdtptp");
		return "xxx";
	}
	xxx.html:
	<div th:text="${msg}"></div>

注意:
	所有引入的包 都有xxxProperties类;

过滤器 Filter

概念:
	可以改变一个request 和 修改一个response;
	即客户端请求访问后端资源之前,可以拦截;服务器响应发送回客户端之前,可以拦截;

filter使用

整体过程:
🍇 过滤器定义

public class ExceptionFilter implements Filter {
// 含有三个方法:init、doFilter、destory
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void destroy() {}

// 核心方法
@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { }
    // 三个参数:请求-request,响应-response,过滤器链-chain
	// 实现链式调用;
	// 处理请求
	chain.doFilter(request,response);
	// 处理响应;
}

🍇 过滤器注册

有三种方式:
1. 利用WebFilter注解配置
在自定义filter类上添加注解 即
@WebFileter(filterName="xxx",urlPatterns={"xxx"}) // filterName 过滤器名字;urlPatterns需要拦截的访问路径
public class xxxFilter extends Filter{}
缺点:无法保证过滤器之间的执行顺序;
当前方式:是按照名字的字母表方式,执行过滤器;
还需要在启动类上 添加@ServletComponentScan注解;

2. FilterRegistrationBean方式
需要新定义一个类;
public class FilterRegistration{
	@Bean
	public FilterRegistrationBean filterRegistrationBean(){
		FilterRegistrationBean registration = new FilterRegistrationBean();
		registration.setFilter(new xxxFilter()); // 设置filter
		registration.setName("xxxFilter"); // 定义过滤器名称
		registration.addUrlPatterns("xxx"); // 设置拦截路径
		registration.setOrder(10); // 设置顺序
		return registration;
	}
}

3. 配置成Bean
将过滤器配置成Bean,注册到Spring容器中去;
@Component
@Order(xxx)  //可以设置过滤器的级别 
public class xxxFilter extends Filter{}
缺点:不能设置拦截规则,即拦截路径;(已知项目采用的方式)

过滤器链

定义:
	每个Filter程序都可以针对某一个URL进行拦截,如果多个Filter程序对同一个URL进行拦截,这些Filter就会组成一个Filter链,即过滤器链;
理解:
	假设访问服务器资源会经过两个过滤器,即filter1和filter2,首先filter1会对url进行处理,然后通过filter1的doFilter()方法将请求传递给filter2.
	其中filter1和filter2都会执行filterx.doFilter();方法
使用:
	xxxFilter对象中的doFilter方法,该方法参数包含ServletRequest request, ServletResponse response, FilterChain chain参数,其中使用chain.doFilter(request,response) 就是过滤器链。
执行流程:
	过滤器初始化,现一般采用@Component注解;
	请求到达过滤器链,每个过滤器在doFilter方法执行自己的逻辑,然后调用过滤器链上的下一个过滤器的doFilter方法;
	Servlet处理请求,处理请求,返回给过滤器链;
	响应经过过滤器链,按照与请求相反的顺序经过过滤器,执行自己的doFilter方法,然后调用下一个过滤器的doFilter方法;
	过滤器销毁,应用关闭或者卸载时,过滤器被销毁;

相关思考

多次处理问题

描述:
	同一个应用中使用过滤器filter,可能会存在单个请求被同一个过滤器多次处理的情况;
分析:
如何产生?
	重定向的情况:当一个请求被重定向时,浏览器会发送一个新的请求到指定位置;就算重定向前的请求经过了某个过滤器,重定向请求仍有可能再次经过某过滤器;
	转发:当Servlet容器内部对请求进行转发时,转发的目标资源可能还会再次经过相同的过滤器;
	循环引用:存在复杂逻辑的应用中,可能存在循环引用的情况,可能会在某种逻辑上导致请求会重新回到之前经过的过滤器。

解决方式:

// xFilter过滤器的doFilter方法
Object isProcessed = request.getAttribute("logfilter.processed");
// 给请求设置某个参数标识 请求经过x过滤器;
if (isProcessed != null && (boolean) isProcessed) {
    // 已经经过LogFilter的处理。
    chain.doFilter(request, response);
    return;
}
request.setAttribute("logfilter.processed", true);

拦截器 Interceptor

集成 数据库 Druid

分布式开发:Dubbo(RPC) + zookeeper

swagger:接口文档

任务调度

SpringSecurit:Shiro

本质上是:拦截器与过滤器就可以实现安全功能;

Linux项目部署

具体内容

RowMapper接口

定义:
	是Spring框架提供的将数据库查询封装的接口
	用来把数据库中的列字段和java bean中属性对应上;
	即可以将数据中的每一行数据封装成用户定义的类;
作用:
	原生JDBC,从数据库查询出来的记录全都被保存在ResultSet结果集中,需要将结果集中的数据一条条地获取并设置到具体的实体类上,这时就需要RowMapper来处理;

BaseMapper接口

概念:
	是Mybatis-plus中的,利用的Mybatis接口编程的实现机制,其默认提供了一系列的增删改查的基础方法,并且开发人员对于这些基础操作不需要写SQL进行处理操作。
作用:
	用于操作数据库;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值