【SpringBoot自定义启动器实现过程】

一、创建SpringBoot模块工程


前言

通过maven创建SpringBoot项目,创建模块工程,实现简单模块开发。

实现手写验证码启动器,并在其他模块调用。


提示:以下是本篇文章正文内容,下面案例可供参考

一、创建SpringBoot模块工程

1. 创建父工程

1)创建新项目NewProject选择Maven,选择使用jdk版本,勾选,选择maven-quickstart,next

2)选择存储路径

3)选择maven仓库

2. 创建子工程 back

1)在父工程上,右键,new,moudle

2)重复创建父工程的过程

3)选择存储位置(重点是选择正确的父工程)

4)maven仓库和父工程一样

5)项目结构

3. 创建子工程 common

1)重复创建子工程的过程

4. 当前工程结构如下

5. 修改工程结构

1)修改父工程

 删掉父工程的src

按图修改父工程的pom.xml文件:

在pom.xml中添加内容

最终 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <artifactId>spring-boot-starter-parent</artifactId>
    <groupId>org.springframework.boot</groupId>
    <version>2.6.13</version>
  </parent>

  <groupId>com.cykj</groupId>
  <artifactId>moudle-code-start</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>back</module>
    <module>common</module>
  </modules>

  <name>moudle-code-start</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>

  </dependencies>

</project>

3)修改子工程

删掉两个子工程下的test

如图修改两个子工程的pom.xml

二、编写启动器

1. 选择common模块编写启动器

2. 修改pom.xml文件

修改common模块的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 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <!--默认的父-->
<!--    <parent>-->
<!--        <artifactId>moudle-code-start</artifactId>-->
<!--        <groupId>com.cykj</groupId>-->
<!--        <version>1.0-SNAPSHOT</version>-->
<!--    </parent>-->

    <!--springboot启动器-->
    <!--启动器要与其他的模块分开,单独存在,所以用springboot的父 而不是默认的-->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.6.13</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

    <artifactId>common</artifactId>

    <name>common</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <!--启动器的三个依赖 必须的-->
    <dependencies>
        <!--springboot 启动器 web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.6.13</version>
        </dependency>
        <!--springboot 自动装配-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.6.13</version>
        </dependency>
        <!--springboot 配置处理器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <version>2.6.13</version>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

3. 创建默认配置文件

在main下创建resources,在resources下创建META-INF,在META-INF下创建默认配置文件

additional-spring-configuration-metadata.json

配置文件的内容如下:

{
  "properties": [
    {
      "name": "cykj.code.code-count",
      "description": "验证码个数",
      "defaultValue": "6"
    },
    {
      "name": "cykj.code.width",
      "description": "验证码宽度",
      "defaultValue": "120"
    },
    {
      "name": "cykj.code.height",
      "description": "验证码高度",
      "defaultValue": "30"
    },
    {
      "name": "cykj.code.line-count",
      "description": "干扰线的个数",
      "defaultValue": "20"
    }
  ]
}

4. 创建实体类,承接配置类 

代码如下:

package com.cykj.config;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @author HuaYu
 * @date 2024/5/28 8:13
 * 说明:实体类 ,承接配置文件中解析出来的关于验证码的相关信息
 */
/*下面这个注解没有注册会报红,需要去配置类中开启注册*/
@ConfigurationProperties(prefix = "cykj.code")
public class CodePropertiesEntity {
    private int width=160;
    private int height=40;
    private int codeCount=6;
    private int lineCount=20;

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getCodeCount() {
        return codeCount;
    }

    public void setCodeCount(int codeCount) {
        this.codeCount = codeCount;
    }

    public int getLineCount() {
        return lineCount;
    }

    public void setLineCount(int lineCount) {
        this.lineCount = lineCount;
    }
}

5. 创建配置类

开启配置类属性读取,开启后实体类的注解就不会报红了

 

package com.cykj.config;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author HuaYu
 * @date 2024/5/28 8:16
 * 说明:配置类
 */
/*表明当前类是配置类的注解*/
@Configuration
/*表示开启配置类属性读取操作*/
@EnableConfigurationProperties(CodePropertiesEntity.class)
public class CodeConfig {

}

6. 创建验证码工具类 

代码如下:

package com.cykj.util;

import com.cykj.config.CodePropertiesEntity;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

/**
 * @author HuaYu
 * @date 2024/5/28 8:13
 * 说明:验证码工具类
 */
public class ImageCodeUtils {

    /**
     * 图片的宽度
     */
    private int width = 160;
    /**
     * 图片的高度
     */
    private int height = 40;
    /**
     * 验证码字符个数
     */
    private int codeCount = 4;
    /**
     * 验证码干扰线数
     */
    private int lineCount = 20;
    /**
     * 验证码
     */
    private String code = null;

    private BufferedImage buffImg = null;
    Random random = new Random();

    public ImageCodeUtils() {
        createImage();
    }

    public ImageCodeUtils(CodePropertiesEntity codeProp) {
        this.width = codeProp.getWidth();
        this.height = codeProp.getHeight();
        this.codeCount = codeProp.getCodeCount();
        this.lineCount = codeProp.getLineCount();
        createImage();
    }

    public ImageCodeUtils(int width, int height) {
        this.width = width;
        this.height = height;
        createImage();
    }

    public ImageCodeUtils(int width, int height, int codeCount) {
        this.width = width;
        this.height = height;
        this.codeCount = codeCount;
        createImage();
    }

    public ImageCodeUtils(int width, int height, int codeCount, int lineCount) {
        this.width = width;
        this.height = height;
        this.codeCount = codeCount;
        this.lineCount = lineCount;
        createImage();
    }


    /**
     * 生成图片
     */
    private void createImage() {
        // 字体的宽度
        int fontWidth = width / codeCount;
        // 字体的高度
        int fontHeight = height - 5;
        int codeY = height - 8;

        // 图像buffer
        buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = buffImg.getGraphics();

        // 设置背景色
        g.setColor(getRandColor(200, 250));
        g.fillRect(0, 0, width, height);



        // 设置字体
        //Font font1 = getFont(fontHeight);
        Font font = new Font("Fixedsys", Font.BOLD, fontHeight);
        g.setFont(font);

        // 设置干扰线
        for (int i = 0; i < lineCount; i++) {
            int xs = random.nextInt(width);
            int ys = random.nextInt(height);
            int xe = xs + random.nextInt(width);
            int ye = ys + random.nextInt(height);
            g.setColor(getRandColor(1, 255));
            g.drawLine(xs, ys, xe, ye);
        }

        // 添加噪点
        float yawpRate = 0.01f;
        int area = (int) (yawpRate * width * height);
        for (int i = 0; i < area; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);

            buffImg.setRGB(x, y, random.nextInt(255));
        }

        // 得到随机字符
        String str1 = randomStr(codeCount);
        this.code = str1;
        for (int i = 0; i < codeCount; i++) {
            String strRand = str1.substring(i, i + 1);
            g.setColor(getRandColor(1, 255));

            // a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处
            g.drawString(strRand, i*fontWidth+3, codeY);
        }
    }

    /**
     * 得到随机字符串
     * @param n
     * @return
     */
    private String randomStr(int n) {
        String str1 = "ABCDEFGHJKMNOPQRSTUVWXYZabcdefghjkmnopqrstuvwxyz1234567890";
        String str2 = "";
        int len = str1.length() - 1;
        double r;
        for (int i = 0; i < n; i++) {
            r = (Math.random()) * len;
            str2 = str2 + str1.charAt((int) r);
        }
        return str2;
    }

    /**
     * 得到随机颜色
     * @param fc
     * @param bc
     * @return
     */
    private Color getRandColor(int fc, int bc) {
        if (fc > 255){
            fc = 255;
        }
        if (bc > 255){
            bc = 255;
        }
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    /**
     * 产生随机字体
     */
    private Font getFont(int size) {
        Random random = new Random();
        Font[] font = new Font[5];
        font[0] = new Font("Ravie", Font.PLAIN, size);
        font[1] = new Font("Antique Olive Compact", Font.PLAIN, size);
        font[2] = new Font("Fixedsys", Font.PLAIN, size);
        font[3] = new Font("Wide Latin", Font.PLAIN, size);
        font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size);
        return font[random.nextInt(5)];
    }

    /**
     * 扭曲方法
     * @param g
     * @param w1
     * @param h1
     * @param color
     */
    private void shear(Graphics g, int w1, int h1, Color color) {
        shearX(g, w1, h1, color);
        shearY(g, w1, h1, color);
    }

    private void shearX(Graphics g, int w1, int h1, Color color) {

        int period = random.nextInt(2);

        boolean borderGap = true;
        int frames = 1;
        int phase = random.nextInt(2);

        for (int i = 0; i < h1; i++) {
            double d = (double) (period >> 1)
                    * Math.sin((double) i / (double) period
                    + (6.2831853071795862D * (double) phase)
                    / (double) frames);
            g.copyArea(0, i, w1, 1, (int) d, 0);
            if (borderGap) {
                g.setColor(color);
                g.drawLine((int) d, i, 0, i);
                g.drawLine((int) d + w1, i, w1, i);
            }
        }

    }

    private void shearY(Graphics g, int w1, int h1, Color color) {

        int period = random.nextInt(40) + 10;

        boolean borderGap = true;
        int frames = 20;
        int phase = 7;
        for (int i = 0; i < w1; i++) {
            double d = (double) (period >> 1)
                    * Math.sin((double) i / (double) period
                    + (6.2831853071795862D * (double) phase)
                    / (double) frames);
            g.copyArea(i, 0, 1, h1, 0, (int) d);
            if (borderGap) {
                g.setColor(color);
                g.drawLine(i, (int) d, i, 0);
                g.drawLine(i, (int) d + h1, i, h1);
            }

        }

    }

    public void write(OutputStream sos) throws IOException {
        ImageIO.write(buffImg, "png", sos);
        sos.close();
    }

    public BufferedImage getBuffImg() {
        return buffImg;
    }

    public String getCode() {
        return code.toLowerCase();
    }
}

7. 编写配置类 

添加内容

配置类代码如下:

import com.cykj.util.ImageCodeUtils;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 王显辉
 * @date 2024/5/28 8:16
 * 说明:
 */
@Configuration
/*表示开启配置类属性读取操作*/
@EnableConfigurationProperties(CodePropertiesEntity.class)
public class CodeConfig {

    private CodePropertiesEntity prop;

    /*构造方法赋值*/
    public CodeConfig(CodePropertiesEntity prop){
        this.prop=prop;
    }

    /*自动获取bean的时候 自动赋值,注入到IOC容器*/
    @Bean
    public ImageCodeUtils getImageCodeUtils( ){
        return new ImageCodeUtils(prop);
    }
}

8. 新建文件 spring.factories

存储配置类的信息

org.springframework.boot.autoconfigure.EnableAutoConfiguration = \
com.cykj.config.CodeConfig

 9. 打包到本地

依次点击

install之后根据路径去本地仓库查看

三、子工程调用启动器

1. 添加依赖

添加两个依赖,其中一个是上面写的启动器。

代码如下:

<?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">
    <parent>
        <artifactId>moudle-code-start</artifactId>
        <groupId>com.cykj</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>back</artifactId>

    <name>back</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.6.13</version>
        </dependency>

        <!--写的启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>common</artifactId>
            <version>2.6.13</version>
        </dependency>

    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

2. 修改启动类

package com.cykj;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Hello world!
 *
 */
@SpringBootApplication
public class App 
{
    public static void main( String[] args )
    {
        SpringApplication.run(App.class,args);
    }
}

3. 编写测试类

 代码如下:

package com.cykj.Controller;

import com.cykj.util.ImageCodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author HuaYu
 * @date 2024/5/28 8:47
 * 说明:测试类,测试启动类
 */
@RestController
public class TestController {

    @Autowired
    private ImageCodeUtils imageCodeUtils;

    @RequestMapping("/code")
    public void capture(HttpServletResponse response){
        try {
            imageCodeUtils.write(response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

4. 启动程序

启动成功 访问地址,显示验证码。

http://127.0.0.1:8080/code

 


总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值