SpringBoot 手写 Starter

发布于:2024-03-01 ⋅ 阅读:(36) ⋅ 点赞:(0)

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 {

    @Override
    public 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());
    }
    @Override
    public 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

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到