【SpringBoot】进阶之自定义starter(一起了解自定义starter的魅力)
🎉🎉欢迎来到我的CSDN主页!🎉🎉
🏅我是君易--鑨,一个在CSDN分享笔记的博主。📚📚
🌟推荐给大家我的博客专栏《SpringBoot开发》。🎯🎯
🎁如果感觉还不错的话请给我关注加三连吧!🎁🎁
?前言
? ? ? ? ?在上一期的博客分享中和老铁们学习了有关Freemarker的相关知识,以及在SpringBoot中集成Freemarker运用,并且列举项目案例进行演示使用,已达到一个学以致用的效果。今天给大家带来的是自定义Starter在SpringBoot中的运用。
一、自定义Starter简介?
1. 概述(基本概念)
?????????在Spring Boot中,Starter是一种特殊的依赖,它可以帮助开发人员快速引入和配置某个特定的功能模块。
????????Spring Boot的官方Starter并不一定包含所有开发人员所需的功能,这时候就需要自定义Starter来满足特定项目的需求。自定义Starter是一种自包含的、可重用的模块,它封装了一组特定功能的依赖和配置,并提供了简化配置的方式。通过自定义Starter,开发人员可以将一些常用的功能封装起来,使得在其他项目中引入这些功能变得更加简单和方便。
????????SpringBoot会自动通过classpath路径下的类发现需要的Bean,并注册进IOC容器。SpringBoot提供了针对日常企业应用研发各种场景的spring-boot-starter依赖模块。
?2. 为什么要使用它
????????使用自定义Starter的优势及好处有以下几点:(如下表格所示)
特点及优势 | 说明 |
模块化 | 自定义Starter可以将特定的功能模块化,使得开发人员可以更方便地管理和维护代码。 |
简化配置 | 通过自定义Starter,开发人员可以简化配置,减少重复的配置工作,提高开发效率。 |
提高代码重用性 | 自定义Starter可以封装一组特定功能的依赖和配置,使得在其他项目中引入这些功能变得更加简单和方便,从而提高代码重用性。 |
自定义功能 | 如果Spring Boot的官方Starter不能满足项目的需求,那么自定义Starter就可以发挥重要作用。开发人员可以根据项目需求自定义Starter,从而实现一些特定的功能。 |
? ? ? ? ?总之,在我们的日常开发工作中,经常会有一些独立于业务之外的配置模块,我们经常将其放到一个特定的包下,然后如果另一个工程需要复用这块功能的时候,需要将代码硬拷贝到另一个工程,重新集成一遍,麻烦至极。如果我们将这些可独立于业务代码之外的功能配置模块封装成一个个starter,复用的时候只需要将其在pom中引用依赖即可, SpringBoot为我们完成自动装配,简直不要太爽。
3. 应用场景
????????在我们的日常开发工作中,可能会需要开发一个通用模块,以供其它工程复用。SpringBoot就为我们提供这样的功能机制,我们可以把我们的通用模块封装成一个个starter,这样其它工程复用的时候只需要在pom中引用依赖即可,由SpringBoot为我们完成自动装配。
常见的应用场景:
1)通用模块-短信发送模块
2)基于AOP技术实现日志切面
3)分布式雪花ID,Long转String,解决精度问题
4)微服务项目的数据库连接池配置
5)微服务项目的每个模块都要访问redis数据库,每个模块都要配置redisTemplat
4. 自动加载核心注解说明
二、案例演示说明(模拟短信发送)
? ? ? ? 我们先重新创建一个SpringBoot项目用于编写模拟短信发送。只选择lombok依赖即可。创建好项目之后,右侧点击Maven选择,点击项目,点击第一个文件夹,会显示一个install选项,点击该选项则项目存放到本地的Maven项目中。
? ? ? ? 我们在本地的Maven仓库中可以查看到我们的下载的依赖。?路径时根据我们pom文件的版本来的。
?
1. 命名规范说明
? ? ? ? Starter项目和SpringBoot工程结构没有什么区别,一样必须引入依赖的依赖如下
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
? ? ? ? ?不引用改以来无法在其他项目中引用自定义依赖。
?说明:
spring-boot-configuration-processor
是一个注解处理器,用于处理 Spring Boot 配置类的注解,并生成配置属性的元数据。
?命名方式:
官方:
spring-boot-starter-{模块名}
自定义:
{模块名}-spring-boot-starter
?
2. 模拟短信发送
? ? ? ? 如果创建好SpringBoot项目发现没有resources文件夹以及yml文件需要我们手动的去创建添加。
? ? ? ? ?对yml文件进行对应编写
? ? ? ? ?创建一个SmsProperties.java文件对其进行编写
SmsProperties.java?
package com.yx.starter;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* com.yx.starter
*
* @author 君易--鑨
* @site www.yangxin.com
* @company 木易
* @create 2023/12/14
* 类似于短信发送的实体类
*/
@Data
@Component //定义组件给Spring管理
public class SmsProperties {
// 从yml文件中获取到对应的值
@Value("${sms.key}")
// 应用标识
String key;
@Value("${sms.secret}")
// 应用密钥
String secret;
}
? ? ? ? 在测试类中测试看看是否能够拿到yml文件中的值
测试类
运行结果如下
? ? ? ? ?我们到此这一步并没有实现模拟发送短信的请求,因此我们要编写一个Service类以及它的实现类。
ISmsService.java
package com.yx.starter.service;
public interface ISmsService {
/**
* 发送短信
*
* @param phone 要发送的手机号
* @param data 要发送的内容
*/
void send(String phone, String data);
}
SmsServiceImpl.java?
package com.yx.starter.service;
import com.yx.starter.SmsProperties;
import org.springframework.stereotype.Service;
public class SmsServiceImpl implements ISmsService {
private SmsProperties smsProperties; //null
public SmsServiceImpl(SmsProperties smsProperties) {
this.smsProperties=smsProperties;
}
@Override
public void send(String phone, String data) {
String key = smsProperties.getKey();
String secret = smsProperties.getSecret();
System.out.println("接入短信系统,Key=" + key + ",Secret=" + secret);
System.out.println("短信发送,phone=" + phone + "data=" + data);
}
}
? ? ? ? 然后在测试类通过实例化实现类调用方法实现模拟短信发送?
控制台输出的结果如下
? ? ? ? ?这里老铁们会有些疑惑,为什么没有使用@Service,因为我们要动态控制是否进行加载。通过yml文件中sms.enable的属性进行控制。所以我们要新建一个类来控制。
?SmsConfig.java
package com.yx.starter;
import com.yx.starter.service.ISmsService;
import com.yx.starter.service.SmsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* com.yx.starter
*
* @author 君易--鑨
* @site www.yangxin.com
* @company 木易
* @create 2023/12/14
* 配置类
* 动态控制是否使用短信发送
* 这个类要Spring加载
*/
@Configuration //表数配置类
public class SmsConfig {
// 控制Service是否加载到Spring中国
@Autowired
private SmsProperties smsProperties;
@Bean//会在spring运行时自动执行,返回值会被放到spring容器中
public ISmsService smsService(){
return new SmsServiceImpl(smsProperties);
}
}
? ? ? ? 测试类对其进行调整运行
? ? ? ? ?在之前编写SmsProperties使用了@Value不方便后续使用,该用@ConfigurationProperties在该类上适用
? ? ? ? 依次进行调试,控制台结果输出一样?
? ? ? ? ?我们可以将SmsProperties的@Component注释删除,在SmsConfig配置中使用@EnableConfigurationProperties指定指定的实体类。
调试结果一样
? ? ? ? ?接下来就是将它打包存放到本地的Maven仓库中,启动其他项目进行导入使用,在打包之前需要清空yml文件。
?导入短信依赖
? ? ? ? 导入了依赖之后我们在测试类中进行调试?,还要配置其yml文件
?
?????????配置完yml文件后,我们还需要编写短信发送的项目中的resources下新建META-INF文件夹,然后创建spring.factories文件; 在该文件中加入如下配置,该配置指定上步骤中定义的配置类为自动装配的配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.zking.scloudspringbootstarter.config.AutoConfig,\
com.zking.scloudspringbootstarter.config.WebLogAutoConfig
? ? ? ? 我们对其项目进行修改,没修改都需要重新打包?,下面是我的一些调整
? ? ? ? 调试结果如下?
三、实现基于AOP技术的日志切面功能
准备工作
? ? ? ? 重新创建一个项目,准备步骤与上面类似
?导入pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
? ? ? ? 一下是我的完整的pom依赖?
pom.xml?
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yx</groupId>
<artifactId>Aspect</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Aspect</name>
<description>Aspect</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.7.6</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.6</version>
</dependency>
<!-- 引用依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.yx.aspect.AspectApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
1.??创建切面配置类Properties
WebLogProperties.java
package com.yx.aspect;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "yx.weblog")
public class WebLogProperties {
private boolean enabled;
public WebLogProperties() {
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
2.?实现基于AOP技术的日志切面功能
WebLogAspect.java
package com.yx.aspect.config;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
@Aspect
@Component
@Slf4j
public class WebLogAspect {
@Pointcut("execution(* *..*Controller.*(..))")
public void webLog(){}
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
log.info("开始服务:{}", request.getRequestURL().toString());
log.info("客户端IP :{}" , request.getRemoteAddr());
log.info("参数值 :{}", Arrays.toString(joinPoint.getArgs()));
}
@AfterReturning(returning = "ret", pointcut = "webLog()")
public void doAfterReturning(Object ret) throws Throwable {
// 处理完请求,返回内容
log.info("返回值 : {}" , ret);
}
}
3.?创建自动配置类
WebLogConfig.java
package com.yx.aspect.config;
import com.yx.aspect.WebLogProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ConditionalOnProperty
* 配置属性a:
* 1:不配置a matchifmissing=false 不满足 matchifmissing=true 满足
* 2:配置a=false matchifmissing=false 不满足 matchifmissing=true 不满足
* 3:配置a=true matchifmissing=false 满足 matchifmissing=true 满足
*/
@Configuration
@EnableConfigurationProperties({WebLogProperties.class})
@ConditionalOnProperty(prefix = "yx.weblog",
value = "enabled",matchIfMissing = true)
public class WebLogConfig {
@Bean
@ConditionalOnMissingBean
public WebLogAspect webLogAspect(){
return new WebLogAspect();
}
}
4.?编写spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yx.aspect.config.WebLogAspect,\
com.yx.aspect.config.WebLogConfig
? ? ? ? 路径仅供参考,实际路径根据自身的项目路径为主?
5.?打包安装
6. 其他项目引用依赖
? ? ? ? 导入对应的pom依赖以及配置yml文件
? ? ? ? 博主的配置仅供参考,具体的配置信息根据自身的项目信息进行配置?
?7. 启动项目进行检验
? ? ? ? 启动项目并进行访问即可,然后在我们的IDEA控制台进行日志查看。
🎉🎉本期的博客分享到此结束🎉🎉
📚📚各位老铁慢慢消化📚📚
🎯🎯下期博客博主会带来新货🎯🎯
🎁三连加关注,阅读不迷路?!🎁
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!