SpringBoot 手写 Starter
spring-boot-starter 模块
1.介绍
SpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰。SpringBoot会自动通过classpath路径下的类发现需要的Bean,并注册进IOC容器。SpringBoot提供了针对日常企业应用研发各种场景的spring-boot-starter依赖模块。所有这些依赖模块都遵循着约定成俗的默认配置,并允许我们调整这些配置,即遵循“约定大于配置”的理念。
优点
一般认为,SpringBoot 微框架从两个主要层面影响 Spring 社区的开发者们:
-
基于 Spring 框架的“约定优先于配置(COC)”理念以及最佳实践之路。
-
提供了针对日常企业应用研发各种场景的 spring-boot-starter 自动配置依赖模块,如此多“开箱即用”的依赖模块,使得开发各种场景的 Spring 应用更加快速和高效。
SpringBoot 提供的这些“开箱即用”的依赖模块都约定以 spring-boot-starter- 作为命名的前缀,并且皆位于 org.springframework.boot 包或者命名空间下(虽然 SpringBoot 的官方参考文档中提到不建议大家使用 spring-boot-starter- 来命名自己写的类似的自动配置依赖模块,但实际上,配合不同的 groupId,这不应该是什么问题)。
2.starter自定义
springboot 官方建议springboot官方推出的starter 以spring-boot-starter-xxx的格式来命名,第三方开发者自定义的starter则以xxxx-spring-boot-starter的规则来命名,事实上,很多开发者在自定义starter的时候往往会忽略这个东西。
自定义一个分页:pagex-spring-boot-starter
开发步骤:
2.1新建工程


2.2父pom文件
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.11.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><packaging>pom</packaging><groupId>cn.jyx</groupId><artifactId>win-root</artifactId><version>1.0-SNAPSHOT</version><properties><java.version>8</java.version></properties><modules><module>win-model</module><module>win-core</module><module>pagex-spring-boot-starter</module><module>logtimex-spring-boot-starter</module></modules><dependencyManagement><dependencies><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.6</version></dependency></dependencies></dependencyManagement>
</project>
2.3model 模块
pom
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>cn.jyx</groupId><artifactId>win-root</artifactId><version>1.0-SNAPSHOT</version><relativePath>../pom.xml</relativePath></parent><artifactId>win-model</artifactId><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><executions><execution><id>attach-sources</id><phase>package</phase><goals><goal>jar</goal></goals></execution></executions></plugin></plugins></build>
</project>
响应返回对象
package cn.win.model;import lombok.Data;@Data
public class ResponseDTO {private int code;private String msg;private Object data;public static ResponseDTO success(Object data){ResponseDTO responseDTO = new ResponseDTO();responseDTO.setCode(0);responseDTO.setData(data);return responseDTO;}public static ResponseDTO error(int code,String msg){ResponseDTO responseDTO = new ResponseDTO();responseDTO.setCode(code);responseDTO.setMsg(msg);return responseDTO;}
}
2.4core模块
pom
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>cn.jyx</groupId><artifactId>win-root</artifactId><version>1.0-SNAPSHOT</version><relativePath>../pom.xml</relativePath></parent><artifactId>win-core</artifactId><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><executions><execution><id>attach-sources</id><phase>package</phase><goals><goal>jar</goal></goals></execution></executions></plugin></plugins></build></project>
声明调用注解
package cn.win.core.annotations;import java.lang.annotation.*;@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PageX {
}
package cn.win.core.exceptioin;public class BizException extends RuntimeException {private int code;private String msg;public int getCode() {return code;}public BizException(int code, String msg) {super();this.code = code;this.msg = msg;}public void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}
}
pagex-spring-boot-starter 模块
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>cn.jyx</groupId><artifactId>win-root</artifactId><version>1.0-SNAPSHOT</version><relativePath>../pom.xml</relativePath></parent><artifactId>pagex-spring-boot-starter</artifactId><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>cn.jyx</groupId><artifactId>win-core</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope></dependency><dependency><groupId>cn.jyx</groupId><artifactId>win-model</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><executions><execution><id>attach-sources</id><phase>package</phase><goals><goal>jar</goal></goals></execution></executions></plugin></plugins></build></project>
全局响应处理类 advice
用于处理Spring MVC框架中的异常和响应体的转换
package cn.win.logtimex.advice;import cn.hutool.json.JSONUtil;
import cn.win.core.exceptioin.BizException;
import cn.win.model.ResponseDTO;
import com.github.pagehelper.Page;import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;import java.util.HashMap;@RestControllerAdvice
public class MyResponseAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter methodParameter, Class aClass) {return true;}@ExceptionHandler(Exception.class)public Object exceptionHandler(Exception ex){ex.printStackTrace();if(ex instanceof BizException){BizException bizException= (BizException) ex;return ResponseDTO.error(bizException.getCode(),bizException.getMsg());}return ResponseDTO.error(500, ex.getMessage());}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {if (body instanceof ResponseDTO){return body;}ResponseDTO dto = ResponseDTO.success(body);if(body instanceof Page){Page page = (Page) body;long total = page.getTotal();HashMap<String,Object> map = new HashMap<>();map.put("total",total);map.put("items",body);dto = ResponseDTO.success(map);}if(aClass == StringHttpMessageConverter.class){return JSONUtil.toJsonStr(dto);}return dto;}
}
AOP
package cn.win.logtimex.aop;import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageHelper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;@Component
@Aspect
public class PagexAop {//切点表达式,表示该切面将应用于所有被PageX注解标记的方法。@Pointcut("@annotation(cn.win.core.annotations.PageX)")public void point(){}@Around("point()")public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("执行方法之前");RequestAttributes requestAttributes= RequestContextHolder.getRequestAttributes();HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();String pageNum = request.getParameter("pageNum");String pageSize = request.getParameter("pageSize");if (ObjectUtil.isNotEmpty(pageNum)&&ObjectUtil.isNotEmpty(pageSize)){PageHelper.startPage(Integer.parseInt(pageNum),Integer.parseInt(pageSize));}Object result = pjp.proceed(); // 调用目标方法System.out.println("执行方法之后");return result;}
}
创建自动配置类AuthorityAutoConfigruation
package cn.win.logtimex.autoconfiguration;import cn.win.logtimex.advice.MyResponseAdvice;
import cn.win.logtimex.aop.PagexAop;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;@Configuration
@Import( {PagexAop.class, MyResponseAdvice.class})
// cn.smart.pagex.enbale = xxx
@ConditionalOnProperty(prefix = "cn.win.pagex", value = "enable",havingValue="true",matchIfMissing=true)
public class PageXAutoConfiguration { // 领头羊
}
配置类
package cn.win.logtimex.properties;import lombok.Data;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;@Data
@ConfigurationProperties(prefix = "cn.win.pagex")
@EnableAutoConfiguration
public class PageXProperties {private boolean enable=true;
}
配置自动配置
在resourecs文件目录下创建META-INF,并创建我们自己的spring.factories,并把我们的 MemberStaterAutoConfiguration 添加进去
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\cn.win.logtimex.autoconfiguration.PageXAutoConfiguration
相关文章:
SpringBoot 手写 Starter
spring-boot-starter 模块 1.介绍 SpringBoot中的starter是一种非常重要的机制,能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配…...
C++ 学习笔记(Structured bindings)
C 学习笔记(Structured bindings) 这个特性是 C17 引入的,个人认为主要是解决如何让函数返回多个值的问题。在这之前,我们一般用 std::pair 或者 std::tuple 来返回多个值。比如下面的例子: std::tuple<int, int …...
K8S常用kubectl命令汇总(持续更新中)
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
加密和签名的区别及应用场景
原文网址:加密和签名的区别及应用场景_IT利刃出鞘的博客-CSDN博客 简介 本文介绍加密和签名的区别及应用场景。 RSA是一种非对称加密算法, 可生成一对密钥(私钥和公钥)。(RSA可以同时支持加密和签名)。 …...
双非二本找实习前的准备day3
学习目标: 每天2-3到简单sql(刷完即止),每天复习代码随想录上的题目3道算法(时间充足可以继续),背诵的八股的问题也在这里记录了 今日碎碎念: 1)偶尔还是贪玩游戏&…...
又挖到宝了!国人团队研发的AI视频工具PixVerse,这么好用居然还完全免费!(强烈推荐)
昨天发了一款国产免费的 AI 绘画工具 Dreamina 的介绍: 居然才发现!字节跳动旗下国产AI绘画工具Dreamina,这么好用居然还免费!(强烈推荐) 发现大家对国产 AI 工具还挺感兴趣的。今天继续帮大家挖国产的 A…...
勒索病毒普通用户防范建议
勒索病毒普通用户防范建议 定期备份存储在计算机上的数据,这样勒索软件感染不会永远破坏您的个人数据。 最好创建两个备份副本:一个存储在云中(记住使用一个自动备份文件的服务),另一个物理存储(便携式硬…...
Zabbix“专家坐诊”第231期问答
问题一 Q:用docker-compose部署zabbix,部署完后如果要修改zabbix的配置应该要改docker-compose文件里的环境变量吧?改了环境变量之后只能重建容器才能生效吗?能不能在不影响已经配好的那些监控项的情况下让新的环境变量生效&#…...
【.NET Core】深入理解IO - FileSteam流
【.NET Core】深入理解IO - FileSteam流 文章目录 【.NET Core】深入理解IO - FileSteam流一、IO流概述二、文件流FileStream2.1 FileStream概述2.2 FileStream检测流位置更改2.3 FileStream构造函数2.4 FileStream常用属性2.5 FileStream.Read方法2.6 FileStream.Write方法2.7…...
CentOS7 Mysql 忘记密码或临时密码进不去时怎么跳过密码进去然后再更改密码
CentOS7 Mysql 忘记密码或临时密码进不去时怎么跳过密码进去然后再更改密码 1、进文件 vi /etc/my.cnf2、加skip-grant-tables设置跳过密码 在[mysqld]下面加 skip-grant-tables3、mysql -u root -p直接回车无密码进去mysql mysql -u root -p3、先更新,不执行这…...
深度学习 精选笔记(8)梯度消失和梯度爆炸
学习参考: 动手学深度学习2.0Deep-Learning-with-TensorFlow-bookpytorchlightning ①如有冒犯、请联系侵删。 ②已写完的笔记文章会不定时一直修订修改(删、改、增),以达到集多方教程的精华于一文的目的。 ③非常推荐上面(学习参考&#x…...
linux操作docker
docker地址 官方地址 centos7安装docker 卸载旧版本docker sudo //在前面表示以管理员权限操作yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine安装docker //安装所需资…...
k8s Pod 进阶(资源限制,健康检查探针详解,启动退出,pod生命周期,)
目录 资源限制 查看资源控制字段 Pod 资源限制方式 Pod 和容器中定义资源请求和限制的具体字段 CPU资源单位 内存资源单位 示例 健康检查(探针) 探针的三种规则 存活探针(Liveness Probe) 就绪探针(Readines…...
SpringBoot整合ActiveMQ步骤
SpringBoot整合ActiveMQ主要涉及以下几个步骤: 添加依赖:在SpringBoot项目的pom.xml文件中添加ActiveMQ的依赖。 <dependency><groupId>org.apache.activemq</groupId><artifactId>activemq-spring</artifactId><ver…...
MySQL的单表和多表查询
我们在前面曾构建过三个用于实验的表格,下面将基于这三个表进行实践。 # 建立一个用于实验的三个表格 mysql> create table emp (-> empno varchar(10),-> ename varchar(50),-> job varchar(50),-> mgr int,-> hiredate timestamp,-&…...
攻防世界例题wp
1.看到_wakeup()函数第一反应要么触发,要么绕过在这里绕过 2.构造payload实例化一个对象后反序列化 3构造脚本如下: 4.因为它是一个绕过的方法所以我们要使用绕过的方法。 5.继续构造payload将上图的1换成2进行绕过 最终的payload为 O:4:"xctf…...
仿牛客网项目---显示评论和添加评论功能的实现
这篇文章,我来介绍一下我的项目中的另外一个功能:显示评论和添加评论。 其实这两个功能都不怎么重要,我感觉最重要的应该是用户注册登录功能,这个也了解一下,知道这么一回事儿就好。 首先设计DAO层。 Mapper public …...
idea集成git详解教程(实用篇)
0.Git常用命令 Git常用命令-CSDN博客 1.下载git Git - Downloads 一路傻瓜式安装即可(NEXT) 2.软件测试 在Windows桌面空白处,点击鼠标右键,弹出右键菜单 Git软件安装后,会在右键菜单中增加两个菜单 Git GUI He…...
搭建LNMP环境并配置个人博客系统
LNMP是Linux(操作系统)、Nginx(Web服务器)、MySQL(数据库)和PHP(脚本解释器)的组合,常用于部署高性能的动态网站,如WordPress等博客平台 一、安装Linux操作系…...
为什么网络安全缺口这么大,还是这么缺网络安全工程师?
为啥网安领域缺口多达300多万人,但网安工程师(白帽黑客)却很少,难道又是砖家在忽悠人??? 主要原因为这三点: 首先是学校的原因,很多学校网络安全课程用的还都是十年前的老教材&…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...
